├── docs ├── .nojekyll ├── _static │ ├── custom.css │ ├── file.png │ ├── minus.png │ ├── plus.png │ ├── graphviz.css │ ├── check-solid.svg │ ├── documentation_options.js │ ├── copy-button.svg │ ├── copybutton.css │ └── customise-alabaster.css ├── objects.inv ├── _templates │ ├── logo_EC.png │ ├── logo_ERC.png │ ├── logo_NCAS.png │ ├── logo_NERC.png │ ├── base.rst │ ├── autosummary │ │ ├── base.rst │ │ └── class.rst │ ├── function.rst │ ├── attribute.rst │ ├── method.rst │ ├── layout.html │ ├── globaltoc.html │ ├── page.html │ ├── sponsors.html │ └── about.html ├── source │ ├── _themes │ │ └── homepage │ │ │ └── theme.conf │ ├── sample_files │ │ ├── file.nc │ │ ├── parent.nc │ │ ├── external.nc │ │ ├── gathered.nc │ │ ├── geometry.nc │ │ ├── contiguous.nc │ │ └── subsampled.nc │ ├── Changelog.rst │ ├── reset_test_tutorial │ ├── constant.rst │ ├── index.rst │ ├── support.rst │ ├── class │ │ ├── cfdm.core.DocstringRewriteMeta.rst │ │ ├── cfdm.Constant.rst │ │ ├── cfdm.Configuration.rst │ │ ├── cfdm.core.NumpyArray.rst │ │ ├── cfdm.core.Array.rst │ │ ├── cfdm.core.Datum.rst │ │ ├── cfdm.core.Container.rst │ │ ├── cfdm.core.DomainAxis.rst │ │ ├── cfdm.core.Parameters.rst │ │ ├── cfdm.core.Properties.rst │ │ ├── cfdm.core.CellMethod.rst │ │ ├── cfdm.core.Bounds.rst │ │ ├── cfdm.core.InteriorRing.rst │ │ ├── cfdm.Array.rst │ │ ├── cfdm.core.CoordinateConversion.rst │ │ ├── cfdm.CellMethod.rst │ │ ├── cfdm.Datum.rst │ │ └── cfdm.core.Data.rst │ ├── update_sample_file_Conventions │ ├── api_reference.rst │ ├── sample_datasets.rst │ ├── functions.rst │ ├── extract_tutorial_code.py │ ├── class.rst │ ├── class_core.rst │ └── _static │ │ ├── copybutton.js │ │ └── customise-alabaster.css └── _downloads │ └── cfdm_tutorial_files.zip ├── cfdm ├── test │ ├── __init__.py │ ├── example_field_0.zarr2 │ │ ├── time │ │ │ ├── 0 │ │ │ ├── .zattrs │ │ │ └── .zarray │ │ ├── .zgroup │ │ ├── .zattrs │ │ ├── lat │ │ │ ├── 0 │ │ │ ├── .zattrs │ │ │ └── .zarray │ │ ├── lon │ │ │ ├── 0 │ │ │ ├── .zattrs │ │ │ └── .zarray │ │ ├── q │ │ │ ├── 0.0 │ │ │ ├── 0.1 │ │ │ ├── 1.0 │ │ │ ├── 1.1 │ │ │ ├── .zattrs │ │ │ └── .zarray │ │ ├── lat_bnds │ │ │ ├── .zattrs │ │ │ ├── 0.0 │ │ │ ├── 1.0 │ │ │ └── .zarray │ │ └── lon_bnds │ │ │ ├── .zattrs │ │ │ ├── 0.0 │ │ │ ├── 1.0 │ │ │ └── .zarray │ ├── example_field_0.nc │ ├── create_test_files.npz │ ├── example_field_0.zarr3 │ │ ├── lat │ │ │ ├── c │ │ │ │ └── 0 │ │ │ └── zarr.json │ │ ├── lon │ │ │ ├── c │ │ │ │ └── 0 │ │ │ └── zarr.json │ │ ├── q │ │ │ ├── c │ │ │ │ └── 0 │ │ │ │ │ └── 0 │ │ │ └── zarr.json │ │ ├── time │ │ │ ├── c │ │ │ └── zarr.json │ │ ├── lat_bnds │ │ │ ├── c │ │ │ │ └── 0 │ │ │ │ │ └── 0 │ │ │ └── zarr.json │ │ └── lon_bnds │ │ │ ├── c │ │ │ └── 0 │ │ │ │ └── 0 │ │ │ └── zarr.json │ ├── test_List.py │ ├── test_Index.py │ ├── test_Count.py │ ├── test_Quantization.py │ ├── test_core_2.py │ ├── test_Bounds.py │ ├── test_LinearSubarray.py │ ├── test_RaggedIndexedArray.py │ ├── test_RaggedContiguousArray.py │ ├── test_InteriorRing.py │ ├── test_NodeCountProperties.py │ ├── test_CFDMImplementation.py │ ├── test_PartNodeCountProperties.py │ ├── test_SparseArray.py │ ├── run_tests_and_coverage │ ├── test_CellMeasure.py │ └── test_RaggedIndexedContiguousArray.py ├── core │ ├── data │ │ ├── abstract │ │ │ └── __init__.py │ │ └── __init__.py │ ├── mixin │ │ └── __init__.py │ ├── meta │ │ └── __init__.py │ ├── docstring │ │ └── __init__.py │ ├── utils.py │ ├── abstract │ │ ├── __init__.py │ │ └── topology.py │ ├── datum.py │ ├── coordinateconversion.py │ ├── interiorring.py │ ├── domainancillary.py │ ├── bounds.py │ ├── fieldancillary.py │ ├── __init__.py │ └── auxiliarycoordinate.py ├── data │ ├── locks.py │ ├── fragment │ │ ├── mixin │ │ │ └── __init__.py │ │ ├── __init__.py │ │ ├── fragmentnetcdf4array.py │ │ ├── fragmenth5netcdfarray.py │ │ └── fragmentuniquevaluearray.py │ ├── mixin │ │ └── __init__.py │ ├── subarray │ │ ├── abstract │ │ │ └── __init__.py │ │ ├── mixin │ │ │ ├── __init__.py │ │ │ ├── linearinterpolation.py │ │ │ ├── bilinearinterpolation.py │ │ │ └── pointtopology.py │ │ ├── __init__.py │ │ ├── linearsubarray.py │ │ ├── bilinearsubarray.py │ │ ├── interpolationsubarray.py │ │ ├── pointtopologyfromedgessubarray.py │ │ ├── raggedsubarray.py │ │ ├── cellconnectivitysubarray.py │ │ ├── quadraticlatitudelongitudesubarray.py │ │ ├── pointtopologyfromfacessubarray.py │ │ └── biquadraticlatitudelongitudesubarray.py │ ├── abstract │ │ ├── __init__.py │ │ └── array.py │ ├── numpyarray.py │ ├── __init__.py │ └── sparsearray.py ├── docstring │ └── __init__.py ├── abstract │ ├── __init__.py │ └── container.py ├── read_write │ ├── netcdf │ │ ├── __init__.py │ │ ├── flatten │ │ │ └── __init__.py │ │ └── zarr.py │ ├── abstract │ │ ├── __init__.py │ │ ├── abstractio.py │ │ └── readwrite.py │ ├── __init__.py │ └── exceptions.py ├── units.py ├── constants.py ├── datum.py ├── mixin │ ├── __init__.py │ └── boundsmixin.py ├── coordinateconversion.py ├── nodecountproperties.py ├── partnodecountproperties.py ├── list.py ├── interpolationparameter.py ├── count.py └── domainancillary.py ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ ├── question.md │ └── bug_report.md └── workflows │ └── linting.yml ├── requirements.txt ├── MANIFEST.in ├── .pydocstyle.ini ├── create_documentation.md ├── check_docs_api_coverage ├── .gitignore ├── test_release ├── upload_to_pypi ├── test_tutorial_code ├── pyproject.toml ├── codemeta.json ├── codecov.yml ├── .flake8 ├── LICENSE ├── CONTRIBUTING.md └── tag /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cfdm/test/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/time/0: -------------------------------------------------------------------------------- 1 | ?@ -------------------------------------------------------------------------------- /cfdm/core/data/abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from .array import Array 2 | -------------------------------------------------------------------------------- /cfdm/core/mixin/__init__.py: -------------------------------------------------------------------------------- 1 | from .fielddomain import FieldDomain 2 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/.zgroup: -------------------------------------------------------------------------------- 1 | { 2 | "zarr_format": 2 3 | } -------------------------------------------------------------------------------- /docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | /* This file intentionally left blank. */ 2 | -------------------------------------------------------------------------------- /cfdm/core/meta/__init__.py: -------------------------------------------------------------------------------- 1 | from .docstringrewrite import DocstringRewriteMeta 2 | -------------------------------------------------------------------------------- /cfdm/data/locks.py: -------------------------------------------------------------------------------- 1 | from threading import Lock 2 | 3 | netcdf_lock = Lock() 4 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "Conventions": "CF-1.12" 3 | } -------------------------------------------------------------------------------- /docs/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/objects.inv -------------------------------------------------------------------------------- /cfdm/docstring/__init__.py: -------------------------------------------------------------------------------- 1 | from .docstring import _docstring_substitution_definitions 2 | -------------------------------------------------------------------------------- /docs/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_static/plus.png -------------------------------------------------------------------------------- /cfdm/core/docstring/__init__.py: -------------------------------------------------------------------------------- 1 | from .docstring import _docstring_substitution_definitions 2 | -------------------------------------------------------------------------------- /docs/_templates/logo_EC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_templates/logo_EC.png -------------------------------------------------------------------------------- /cfdm/test/example_field_0.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.nc -------------------------------------------------------------------------------- /docs/_templates/logo_ERC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_templates/logo_ERC.png -------------------------------------------------------------------------------- /docs/_templates/logo_NCAS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_templates/logo_NCAS.png -------------------------------------------------------------------------------- /docs/_templates/logo_NERC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_templates/logo_NERC.png -------------------------------------------------------------------------------- /docs/source/_themes/homepage/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | 4 | [options] 5 | homepage = None -------------------------------------------------------------------------------- /cfdm/abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from .container import Container 2 | from .implementation import Implementation 3 | -------------------------------------------------------------------------------- /cfdm/test/create_test_files.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/create_test_files.npz -------------------------------------------------------------------------------- /docs/_templates/base.rst: -------------------------------------------------------------------------------- 1 | {{ fullname }} 2 | {{ underline }} 3 | 4 | .. auto{{ objtype }}:: {{ fullname }} 5 | -------------------------------------------------------------------------------- /docs/source/sample_files/file.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/file.nc -------------------------------------------------------------------------------- /cfdm/read_write/netcdf/__init__.py: -------------------------------------------------------------------------------- 1 | from .netcdfread import NetCDFRead 2 | from .netcdfwrite import NetCDFWrite 3 | -------------------------------------------------------------------------------- /docs/source/sample_files/parent.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/parent.nc -------------------------------------------------------------------------------- /cfdm/read_write/abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from .abstractio import IO, IORead, IOWrite 2 | from .readwrite import ReadWrite 3 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lat/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/lat/0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lon/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/lon/0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/q/0.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/q/0.0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/q/0.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/q/0.1 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/q/1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/q/1.0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/q/1.1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/q/1.1 -------------------------------------------------------------------------------- /docs/source/sample_files/external.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/external.nc -------------------------------------------------------------------------------- /docs/source/sample_files/gathered.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/gathered.nc -------------------------------------------------------------------------------- /docs/source/sample_files/geometry.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/geometry.nc -------------------------------------------------------------------------------- /cfdm/core/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .abstract import Array 2 | from .numpyarray import NumpyArray 3 | from .data import Data 4 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lat/c/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr3/lat/c/0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lon/c/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr3/lon/c/0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/q/c/0/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr3/q/c/0/0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/time/c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr3/time/c -------------------------------------------------------------------------------- /docs/_downloads/cfdm_tutorial_files.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/_downloads/cfdm_tutorial_files.zip -------------------------------------------------------------------------------- /docs/source/sample_files/contiguous.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/contiguous.nc -------------------------------------------------------------------------------- /docs/source/sample_files/subsampled.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/docs/source/sample_files/subsampled.nc -------------------------------------------------------------------------------- /cfdm/read_write/__init__.py: -------------------------------------------------------------------------------- 1 | from .abstract import IO, IORead, IOWrite 2 | from .read import read 3 | from .write import write 4 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lat_bnds/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "_ARRAY_DIMENSIONS": [ 3 | "lat", 4 | "bounds2" 5 | ] 6 | } -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lat_bnds/0.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/lat_bnds/0.0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lat_bnds/1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/lat_bnds/1.0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lon_bnds/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "_ARRAY_DIMENSIONS": [ 3 | "lon", 4 | "bounds2" 5 | ] 6 | } -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lon_bnds/0.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/lon_bnds/0.0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lon_bnds/1.0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr2/lon_bnds/1.0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lat_bnds/c/0/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr3/lat_bnds/c/0/0 -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lon_bnds/c/0/0: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NCAS-CMS/cfdm/HEAD/cfdm/test/example_field_0.zarr3/lon_bnds/c/0/0 -------------------------------------------------------------------------------- /cfdm/data/fragment/mixin/__init__.py: -------------------------------------------------------------------------------- 1 | from .fragmentarraymixin import FragmentArrayMixin 2 | from .fragmentfilearraymixin import FragmentFileArrayMixin 3 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/time/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "_ARRAY_DIMENSIONS": [], 3 | "standard_name": "time", 4 | "units": "days since 2018-12-01" 5 | } -------------------------------------------------------------------------------- /cfdm/data/mixin/__init__.py: -------------------------------------------------------------------------------- 1 | from .arraymixin import ArrayMixin 2 | from .compressedarraymixin import CompressedArrayMixin 3 | from .indexmixin import IndexMixin 4 | -------------------------------------------------------------------------------- /docs/_templates/autosummary/base.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. currentmodule:: {{ module }} 4 | 5 | .. auto{{ objtype }}:: {{ objname }} 6 | 7 | -------------------------------------------------------------------------------- /docs/_templates/function.rst: -------------------------------------------------------------------------------- 1 | {{ fullname }} 2 | {{ underline }} 3 | 4 | .. currentmodule:: cfdm 5 | .. default-role:: obj 6 | 7 | .. autofunction:: {{ objname }} 8 | -------------------------------------------------------------------------------- /cfdm/data/subarray/abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from .meshsubarray import MeshSubarray 2 | from .subarray import Subarray 3 | from .subsampledsubarray import SubsampledSubarray 4 | -------------------------------------------------------------------------------- /docs/_templates/attribute.rst: -------------------------------------------------------------------------------- 1 | {{ fullname }} 2 | {{ underline }} 3 | 4 | .. currentmodule:: cfdm 5 | .. default-role:: obj 6 | 7 | .. autoattribute:: {{ fullname }} 8 | -------------------------------------------------------------------------------- /docs/_templates/method.rst: -------------------------------------------------------------------------------- 1 | :orphan: 2 | 3 | {{ fullname }} 4 | {{ underline }} 5 | 6 | .. currentmodule:: cfdm 7 | .. default-role:: obj 8 | 9 | .. automethod:: {{ fullname }} 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an enhancement 4 | title: 'Request: ' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lat/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "_ARRAY_DIMENSIONS": [ 3 | "lat" 4 | ], 5 | "bounds": "lat_bnds", 6 | "standard_name": "latitude", 7 | "units": "degrees_north" 8 | } -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lon/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "_ARRAY_DIMENSIONS": [ 3 | "lon" 4 | ], 5 | "bounds": "lon_bnds", 6 | "standard_name": "longitude", 7 | "units": "degrees_east" 8 | } -------------------------------------------------------------------------------- /cfdm/data/abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from .array import Array 2 | from .compressedarray import CompressedArray 3 | from .filearray import FileArray 4 | from .mesharray import MeshArray 5 | from .raggedarray import RaggedArray 6 | -------------------------------------------------------------------------------- /docs/_static/graphviz.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Sphinx stylesheet -- graphviz extension. 3 | */ 4 | 5 | img.graphviz { 6 | border: 0; 7 | max-width: 100%; 8 | } 9 | 10 | object.graphviz { 11 | max-width: 100%; 12 | } 13 | -------------------------------------------------------------------------------- /docs/source/Changelog.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | **Change log** 5 | ============== 6 | 7 | .. contents:: 8 | :local: 9 | :backlinks: entry 10 | 11 | .. include:: ../../Changelog.rst 12 | -------------------------------------------------------------------------------- /cfdm/abstract/container.py: -------------------------------------------------------------------------------- 1 | from .. import core, mixin 2 | 3 | 4 | class Container(mixin.Container, core.abstract.Container): 5 | """Abstract base class for storing components. 6 | 7 | .. versionadded:: (cfdm) 1.8.7.0 8 | 9 | """ 10 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/time/.zarray: -------------------------------------------------------------------------------- 1 | { 2 | "chunks": [], 3 | "compressor": null, 4 | "dtype": "=1.7.2 2 | cftime>=1.6.4 3 | numpy>=2.0.0 4 | packaging>=20.0 5 | scipy>=1.10.0 6 | h5netcdf>=1.3.0 7 | h5py>=3.12.0 8 | s3fs>=2024.6.0 9 | dask>=2025.5.1 10 | distributed>=2025.5.1 11 | uritools>=4.0.3 12 | cfunits>=3.3.7 13 | zarr>=3.0.8 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: 'Ask a question, such as "how can I do this?", "why does it behave like that?", 4 | "how can I make it faster?", etc. ' 5 | title: 'Question: ' 6 | labels: question 7 | assignees: '' 8 | 9 | --- 10 | 11 | 12 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include Changelog.rst 2 | include README.md 3 | include requirements.txt 4 | include LICENSE 5 | include CONTRIBUTING.md 6 | include CODE_OF_CONDUCT.md 7 | include cfdm/test/create_test_files.npz 8 | include cfdm/test/example_field_0.nc 9 | recursive-include cfdm/test/example_field_0.zarr[23] * -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/q/.zattrs: -------------------------------------------------------------------------------- 1 | { 2 | "_ARRAY_DIMENSIONS": [ 3 | "lat", 4 | "lon" 5 | ], 6 | "cell_methods": "area: mean", 7 | "coordinates": "time", 8 | "project": "research", 9 | "standard_name": "specific_humidity", 10 | "units": "1" 11 | } -------------------------------------------------------------------------------- /docs/_templates/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "!layout.html" %} 2 | {% block rootrellink %} 3 |
  • Archive «
  • 4 |
  • cf-python {{ release }} »
  • 5 | {{ super() }} 6 | {% endblock %} 7 | -------------------------------------------------------------------------------- /docs/source/reset_test_tutorial: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -x 4 | mkdir -p test_tutorial 5 | 6 | sample_files=sample_files 7 | test_tutorial=test_tutorial 8 | 9 | rm $test_tutorial/* 10 | 11 | cp $sample_files/* $test_tutorial 12 | 13 | cd $test_tutorial 14 | 15 | zip cfdm_tutorial_files.zip *.nc 16 | set +x 17 | -------------------------------------------------------------------------------- /.pydocstyle.ini: -------------------------------------------------------------------------------- 1 | [pydocstyle] 2 | inherit = false 3 | match = .*\.py 4 | convention = google 5 | 6 | # Don't require a docstring for every module and package (i.e. in any __init__) 7 | # 8 | # Ignore D415: First line should end with a period, question mark, or 9 | # exclamation point 10 | add-ignore=D100,D104,D415 11 | -------------------------------------------------------------------------------- /cfdm/core/utils.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | 4 | class cached_property(functools.cached_property): 5 | """Read only version of functools.cached_property.""" 6 | 7 | def __set__(self, instance, val): 8 | """Raise an error when attempting to set a cached property.""" 9 | raise AttributeError("Can't set attribute") 10 | -------------------------------------------------------------------------------- /docs/_static/check-solid.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/_templates/globaltoc.html: -------------------------------------------------------------------------------- 1 | {# 2 | basic/globaltoc.html 3 | ~~~~~~~~~~~~~~~~~~~~ 4 | 5 | Sphinx sidebar template: global table of contents. 6 | 7 | :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. 8 | :license: BSD, see LICENSE for details. 9 | 10 | Updated by DCH. 11 | #} 12 | {{ toctree() }} 13 | -------------------------------------------------------------------------------- /cfdm/data/fragment/fragmentnetcdf4array.py: -------------------------------------------------------------------------------- 1 | from ..netcdf4array import NetCDF4Array 2 | from .mixin import FragmentFileArrayMixin 3 | 4 | 5 | class FragmentNetCDF4Array(FragmentFileArrayMixin, NetCDF4Array): 6 | """A fragment of aggregated data in a file accessed with `netCDF4`. 7 | 8 | .. versionadded:: (cfdm) 1.12.0.0 9 | 10 | """ 11 | -------------------------------------------------------------------------------- /cfdm/data/fragment/fragmenth5netcdfarray.py: -------------------------------------------------------------------------------- 1 | from ..h5netcdfarray import H5netcdfArray 2 | from .mixin import FragmentFileArrayMixin 3 | 4 | 5 | class FragmentH5netcdfArray(FragmentFileArrayMixin, H5netcdfArray): 6 | """A fragment of aggregated data in a file accessed with `h5netcdf`. 7 | 8 | .. versionadded:: (cfdm) 1.12.0.0 9 | 10 | """ 11 | -------------------------------------------------------------------------------- /cfdm/read_write/exceptions.py: -------------------------------------------------------------------------------- 1 | """Custom exceptions for read/write errors.""" 2 | 3 | 4 | class DatasetTypeError(Exception): 5 | """Raised when an input dataset is of an unknown type.""" 6 | 7 | 8 | class ReadError(Exception): 9 | """A general dataset read error.""" 10 | 11 | 12 | class WriteTypeError(Exception): 13 | """A general dataset write error.""" 14 | -------------------------------------------------------------------------------- /cfdm/core/abstract/__init__.py: -------------------------------------------------------------------------------- 1 | from .container import Container 2 | 3 | from .properties import Properties 4 | from .propertiesdata import PropertiesData 5 | from .propertiesdatabounds import PropertiesDataBounds 6 | from .coordinate import Coordinate 7 | from .topology import Topology 8 | 9 | from .parameters import Parameters 10 | from .parametersdomainancillaries import ParametersDomainAncillaries 11 | -------------------------------------------------------------------------------- /docs/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | const DOCUMENTATION_OPTIONS = { 2 | VERSION: '1.12.3.1', 3 | LANGUAGE: 'en', 4 | COLLAPSE_INDEX: false, 5 | BUILDER: 'html', 6 | FILE_SUFFIX: '.html', 7 | LINK_SUFFIX: '.html', 8 | HAS_SOURCE: true, 9 | SOURCELINK_SUFFIX: '.txt', 10 | NAVIGATION_WITH_KEYS: false, 11 | SHOW_SEARCH_SUMMARY: true, 12 | ENABLE_SEARCH_SHORTCUTS: true, 13 | }; -------------------------------------------------------------------------------- /cfdm/data/abstract/array.py: -------------------------------------------------------------------------------- 1 | from cfdm import core 2 | from cfdm.mixin import Container 3 | 4 | from .. import mixin 5 | 6 | 7 | class Array(mixin.ArrayMixin, Container, core.Array): 8 | """Abstract base class for a container of an underlying array. 9 | 10 | The form of the array is defined by the initialisation parameters 11 | of a subclass. 12 | 13 | .. versionadded:: (cfdm) 1.7.0 14 | 15 | """ 16 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/lat/.zarray: -------------------------------------------------------------------------------- 1 | { 2 | "chunks": [ 3 | 5 4 | ], 5 | "compressor": { 6 | "blocksize": 0, 7 | "clevel": 5, 8 | "cname": "lz4", 9 | "id": "blosc", 10 | "shuffle": 1 11 | }, 12 | "dtype": " 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr2/q/.zarray: -------------------------------------------------------------------------------- 1 | { 2 | "chunks": [ 3 | 3, 4 | 4 5 | ], 6 | "compressor": { 7 | "blocksize": 0, 8 | "clevel": 5, 9 | "cname": "lz4", 10 | "id": "blosc", 11 | "shuffle": 1 12 | }, 13 | "dtype": "`. 16 | 17 | **Examples:** 18 | 19 | Masking every element of a field construct's data could be done as 20 | follows: 21 | 22 | >>> f[...] = cfdm.masked 23 | 24 | -------------------------------------------------------------------------------- /check_docs_api_coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------- 4 | # Check the documentation method-coverage of all classes listed in 5 | # docs/source/class.rst 6 | # 7 | # If being used on the cfdm library, the classes listed in 8 | # docs/source/class_core.rst are also checked. 9 | # 10 | # Call as: 11 | # 12 | # $ ./check_docs_api_coverage 13 | # 14 | # Returns non-zero return code if any methods were not documented 15 | # -------------------------------------------------------------------- 16 | 17 | python docs/source/check_docs_api_coverage.py docs/source 18 | rc=$? 19 | exit $? 20 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | ################ 5 | **cfdm package** 6 | ################ 7 | 8 | ---- 9 | 10 | .. include:: introduction.rst 11 | 12 | **Contents** 13 | ============ 14 | 15 | ---- 16 | 17 | .. toctree:: 18 | :maxdepth: 1 19 | 20 | introduction 21 | cf_data_model 22 | installation 23 | contributing 24 | tutorial 25 | api_reference 26 | philosophy 27 | performance 28 | extensions 29 | releases 30 | Changelog 31 | 32 | **Index and search** 33 | ==================== 34 | 35 | ---- 36 | 37 | * :ref:`genindex` 38 | * :ref:`Search ` 39 | -------------------------------------------------------------------------------- /cfdm/read_write/netcdf/flatten/__init__.py: -------------------------------------------------------------------------------- 1 | """Flatten NetCDF groups. 2 | 3 | Portions of this package were adapted from the `netcdf_flattener` 4 | library, which carries the following Apache 2.0 License: 5 | 6 | Copyright (c) 2020 EUMETSAT 7 | 8 | Licensed to the Apache Software Foundation (ASF) under one or more 9 | contributor license agreements. The ASF licenses this file to you 10 | under the Apache License, Version 2.0 (the "License"); you may not use 11 | this file except in compliance with the License. You may obtain a copy 12 | of the License at http://www.apache.org/licenses/LICENSE-2.0. 13 | 14 | """ 15 | 16 | from .flatten import netcdf_flatten 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude from git version control staging for commits... 2 | # (unless a listed file, e.g. `gitignored-filename`, is forcibly staged, via: 3 | # $ git add --force -- gitignored-filename 4 | # ) 5 | 6 | 7 | # ... any '__pycache__' directory anywhere under the root directory: 8 | **/__pycache__/ 9 | 10 | # all Python compiled bytecode files: 11 | *.py[cdo] 12 | 13 | # test files that change if & when the test suite (or a subset of it) is run: 14 | cfdm/test/*.nc 15 | cfdm/test/*.nca 16 | 17 | # packaging-related files changing with environment adjustments: 18 | *.egg-info/ 19 | 20 | # docs: backup files, doctrees and buildinfo generated by changes and builds: 21 | docs/source/*.rst.bak 22 | docs/.* 23 | -------------------------------------------------------------------------------- /test_release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------- 4 | # Install and run tests in ~/tmp 5 | # 6 | # Usage: 7 | # 8 | # $ ./test_release 1.9.0.1 9 | # -------------------------------------------------------------------- 10 | 11 | set -x 12 | 13 | if [[ ! $1 ]] ; then 14 | echo "Must set version as \$1 (e.g. 1.9.0.1)" 15 | exit 1 16 | fi 17 | 18 | vn=$1 19 | 20 | dir=~/tmp/test_cfdm 21 | rm -fr $dir 22 | 23 | pip install dist/cfdm-$vn.tar.gz -t $dir --no-deps 24 | 25 | export PYTHONPATH=$dir:$PYTHONPATH 26 | export PATH=$dir/bin:$PATH 27 | 28 | cd $dir/cfdm/test 29 | 30 | python run_tests.py 31 | test_result_status=$? 32 | 33 | set -x 34 | 35 | exit $test_result_status 36 | -------------------------------------------------------------------------------- /docs/_templates/page.html: -------------------------------------------------------------------------------- 1 | {% extends "!page.html" %} 2 | {% block body %} 3 | {% if current_version and latest_version and current_version != latest_version %} 4 |

    5 | 6 | {% if current_version.is_released %} 7 | You're reading an old version of this documentation. 8 | If you want up-to-date information, please have a look at {{latest_version.name}}. 9 | {% else %} 10 | You're reading the documentation for a development version. 11 | For the latest released version, please have a look at {{latest_version.name}}. 12 | {% endif %} 13 | 14 |

    15 | {% endif %} 16 | {{ super() }} 17 | {% endblock %}% 18 | -------------------------------------------------------------------------------- /upload_to_pypi: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------- 4 | # Run this within a local respository directory to upload the latest 5 | # release to PyPi 6 | # 7 | # It is presumed that `python setup.py sdist` has already been run. 8 | # 9 | #>> ./upload_to_pypi 1.7 10 | # -------------------------------------------------------------------- 11 | 12 | set -x 13 | 14 | if [[ ! $1 ]] ; then 15 | echo "No version \$1 (e.g. 2.0.1)" 16 | exit 1 17 | fi 18 | 19 | version=$1 20 | 21 | tarball=dist/cfdm-${version}.tar.gz 22 | 23 | if [[ ! -f $tarball ]] ; then 24 | echo "Tar ball for cfdm version $version does not exist: $tarball" 25 | exit 2 26 | fi 27 | 28 | twine upload $tarball --verbose 29 | 30 | set +x 31 | -------------------------------------------------------------------------------- /docs/source/support.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | .. _Support: 5 | 6 | **Support** 7 | =========== 8 | 9 | ---- 10 | 11 | Version |release| for version |version| of the CF conventions. 12 | 13 | General questions, suggestions for enhancements, and reports of bugs 14 | may be reported in the GitHub issue tracker: 15 | https://github.com/NCAS-CMS/cfdm/issues 16 | 17 | ---- 18 | 19 | .. _Contributing: 20 | 21 | **Contributing** 22 | ---------------- 23 | 24 | Contributions to cfdm are welcome and should be raised as issues in 25 | the GitHub issue tracker: https://github.com/NCAS-CMS/cfdm/issues, 26 | prior to submitting a pull request containing the new code made from a 27 | fork of the cfdm GitHub code repository: 28 | https://github.com/NCAS-CMS/cfdm. 29 | -------------------------------------------------------------------------------- /cfdm/units.py: -------------------------------------------------------------------------------- 1 | from cfunits import Units as cfUnits 2 | 3 | from .core.meta import DocstringRewriteMeta 4 | 5 | 6 | class Units(metaclass=DocstringRewriteMeta): 7 | """Store, combine, compare, and convert physical units. 8 | 9 | This is a convenience class that creates a `cfunits.Units` 10 | instance. 11 | 12 | The full documentation is available via a `{{package}}.Units` 13 | instance, e.g. ``help({{package}}.Units())``. 14 | 15 | """ 16 | 17 | def __new__(cls, *args, **kwargs): 18 | """Return a new Units instance.""" 19 | return cfUnits(*args, **kwargs) 20 | 21 | @staticmethod 22 | def conform(*args, **kwargs): 23 | """Conform values to equivalent values in a compatible unit.""" 24 | return cfUnits.conform(*args, **kwargs) 25 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.DocstringRewriteMeta.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.DocstringRewriteMeta 5 | ============================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.DocstringRewriteMeta 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.DocstringRewriteMeta.mro 24 | ~cfdm.core.DocstringRewriteMeta._docstring_special_substitutions 25 | ~cfdm.core.DocstringRewriteMeta._docstring_substitutions 26 | ~cfdm.core.DocstringRewriteMeta._docstring_package_depth 27 | ~cfdm.core.DocstringRewriteMeta._docstring_method_exclusions 28 | 29 | -------------------------------------------------------------------------------- /test_tutorial_code: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------- 4 | # Test the code examples found in tutorial.rst 5 | # 6 | # Call as: 7 | # 8 | # $ ./test_tutorial_code 9 | # 10 | # Returns non-zero return code if any tutorial code did not work 11 | # -------------------------------------------------------------------- 12 | 13 | set -x 14 | echo PYTHONPATH=$PYTHONPATH 15 | 16 | d=$PWD 17 | cd docs/source 18 | 19 | python extract_tutorial_code.py tutorial.rst 20 | 21 | ls -l tutorial.py 22 | 23 | ./reset_test_tutorial 24 | cd test_tutorial 25 | 26 | python ../tutorial.py 27 | rc=$? 28 | if [[ $rc != 0 ]]; then 29 | echo "Runtime failure in tutorial.py" 30 | exit $rc 31 | fi 32 | 33 | cd $d 34 | echo "tutorial code ran successfully" 35 | set +x 36 | -------------------------------------------------------------------------------- /cfdm/data/subarray/__init__.py: -------------------------------------------------------------------------------- 1 | from .bilinearsubarray import BiLinearSubarray 2 | from .boundsfromnodessubarray import BoundsFromNodesSubarray 3 | from .cellconnectivitysubarray import CellConnectivitySubarray 4 | from .gatheredsubarray import GatheredSubarray 5 | from .biquadraticlatitudelongitudesubarray import ( 6 | BiQuadraticLatitudeLongitudeSubarray, 7 | ) 8 | from .interpolationsubarray import InterpolationSubarray 9 | from .linearsubarray import LinearSubarray 10 | from .pointtopologyfromedgessubarray import PointTopologyFromEdgesSubarray 11 | from .pointtopologyfromfacessubarray import PointTopologyFromFacesSubarray 12 | from .quadraticlatitudelongitudesubarray import ( 13 | QuadraticLatitudeLongitudeSubarray, 14 | ) 15 | from .quadraticsubarray import QuadraticSubarray 16 | from .raggedsubarray import RaggedSubarray 17 | -------------------------------------------------------------------------------- /docs/source/update_sample_file_Conventions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------- 4 | # Update the Conventions attribute of the tutorial sample files, e.g. 5 | # 6 | # $ update_sample_file_Conventions CF-1.10 7 | # 8 | # Uses `ncatted` to make the changes 9 | # -------------------------------------------------------------------- 10 | set -x 11 | 12 | VN=$1 13 | 14 | if [[ -z $VN ]] ; then 15 | echo "You must set the new CF conventions version as \$1 (e.g. CF-1.10)" 16 | exit 1 17 | fi 18 | 19 | for filename in sample_files/*.nc 20 | do 21 | echo "File: $filename" 22 | ncatted -h -a Conventions,global,o,c,"$VN" $filename 23 | echo "Check: `ncdump -h $filename | grep Conventions`" 24 | done 25 | 26 | git commit -m "Updated Conventions to $VN" sample_files/*.nc 27 | 28 | set +x 29 | -------------------------------------------------------------------------------- /docs/source/api_reference.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | 5 | **API reference** 6 | ================= 7 | 8 | ---- 9 | 10 | Version |release| for version |version| of the CF conventions. 11 | 12 | * **Construct classes** 13 | 14 | * :py:class:`cfdm.Field` 15 | * :py:class:`cfdm.Domain` 16 | * :py:class:`cfdm.AuxiliaryCoordinate` 17 | * :py:class:`cfdm.CellConnectivity` 18 | * :py:class:`cfdm.CellMeasure` 19 | * :py:class:`cfdm.CellMethod` 20 | * :py:class:`cfdm.CoordinateReference` 21 | * :py:class:`cfdm.DimensionCoordinate` 22 | * :py:class:`cfdm.DomainAncillary` 23 | * :py:class:`cfdm.DomainAxis` 24 | * :py:class:`cfdm.DomainTopology` 25 | * :py:class:`cfdm.FieldAncillary` 26 | 27 | .. toctree:: 28 | :maxdepth: 2 29 | 30 | functions 31 | class 32 | constant 33 | class_core 34 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/time/zarr.json: -------------------------------------------------------------------------------- 1 | { 2 | "shape": [], 3 | "data_type": "float64", 4 | "chunk_grid": { 5 | "name": "regular", 6 | "configuration": { 7 | "chunk_shape": [] 8 | } 9 | }, 10 | "chunk_key_encoding": { 11 | "name": "default", 12 | "configuration": { 13 | "separator": "/" 14 | } 15 | }, 16 | "fill_value": 0.0, 17 | "codecs": [ 18 | { 19 | "name": "bytes", 20 | "configuration": { 21 | "endian": "little" 22 | } 23 | }, 24 | { 25 | "name": "zstd", 26 | "configuration": { 27 | "level": 0, 28 | "checksum": false 29 | } 30 | } 31 | ], 32 | "attributes": { 33 | "standard_name": "time", 34 | "units": "days since 2018-12-01" 35 | }, 36 | "zarr_format": 3, 37 | "node_type": "array", 38 | "storage_transformers": [] 39 | } 40 | -------------------------------------------------------------------------------- /cfdm/core/datum.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class Datum(abstract.Parameters): 5 | """A datum component of a coordinate reference of the CF data model. 6 | 7 | A datum is a complete or partial definition of the zeroes of the 8 | dimension and auxiliary coordinate constructs which define a 9 | coordinate system. 10 | 11 | The datum may contain the definition of a geophysical surface 12 | which corresponds to the zero of a vertical coordinate construct, 13 | and this may be required for both horizontal and vertical 14 | coordinate systems. 15 | 16 | Elements of the datum not specified may be implied by the 17 | properties of the dimension and auxiliary coordinate constructs 18 | referenced by the `CoordinateReference` instance that contains the 19 | datum. 20 | 21 | .. versionadded:: (cfdm) 1.7.0 22 | 23 | """ 24 | -------------------------------------------------------------------------------- /docs/source/sample_datasets.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | .. _Sample-datasets: 5 | 6 | **Sample datasets** 7 | ------------------- 8 | 9 | This tutorial uses a number of small sample datasets, all of which can 10 | be found in the zip file ``cfdm_tutorial_files.zip`` 11 | (:download:`download <../source/sample_files/cfdm_tutorial_files.zip>`, 12 | 8kB): 13 | 14 | .. code-block:: console 15 | :caption: *Unpack the sample datasets.* 16 | 17 | $ unzip -q cfdm_tutorial_files.zip 18 | $ ls -1 19 | cfdm_tutorial_files.zip 20 | contiguous.nc 21 | external.nc 22 | file.nc 23 | gathered.nc 24 | geometry.nc 25 | parent.nc 26 | 27 | The tutorial examples assume that the Python session is being run from 28 | the directory that contains the zip file and its unpacked contents, 29 | and no other files. 30 | 31 | ---- 32 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lat_bnds/zarr.json: -------------------------------------------------------------------------------- 1 | { 2 | "shape": [ 3 | 5, 4 | 2 5 | ], 6 | "data_type": "float64", 7 | "chunk_grid": { 8 | "name": "regular", 9 | "configuration": { 10 | "chunk_shape": [ 11 | 5, 12 | 2 13 | ] 14 | } 15 | }, 16 | "chunk_key_encoding": { 17 | "name": "default", 18 | "configuration": { 19 | "separator": "/" 20 | } 21 | }, 22 | "fill_value": 0.0, 23 | "codecs": [ 24 | { 25 | "name": "bytes", 26 | "configuration": { 27 | "endian": "little" 28 | } 29 | }, 30 | { 31 | "name": "zstd", 32 | "configuration": { 33 | "level": 0, 34 | "checksum": false 35 | } 36 | } 37 | ], 38 | "attributes": { 39 | }, 40 | "dimension_names": [ 41 | "lat", 42 | "bounds2" 43 | ], 44 | "zarr_format": 3, 45 | "node_type": "array", 46 | "storage_transformers": [] 47 | } 48 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lon_bnds/zarr.json: -------------------------------------------------------------------------------- 1 | { 2 | "shape": [ 3 | 8, 4 | 2 5 | ], 6 | "data_type": "float64", 7 | "chunk_grid": { 8 | "name": "regular", 9 | "configuration": { 10 | "chunk_shape": [ 11 | 8, 12 | 2 13 | ] 14 | } 15 | }, 16 | "chunk_key_encoding": { 17 | "name": "default", 18 | "configuration": { 19 | "separator": "/" 20 | } 21 | }, 22 | "fill_value": 0.0, 23 | "codecs": [ 24 | { 25 | "name": "bytes", 26 | "configuration": { 27 | "endian": "little" 28 | } 29 | }, 30 | { 31 | "name": "zstd", 32 | "configuration": { 33 | "level": 0, 34 | "checksum": false 35 | } 36 | } 37 | ], 38 | "attributes": { 39 | }, 40 | "dimension_names": [ 41 | "lon", 42 | "bounds2" 43 | ], 44 | "zarr_format": 3, 45 | "node_type": "array", 46 | "storage_transformers": [] 47 | } 48 | -------------------------------------------------------------------------------- /cfdm/constants.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | import numpy as np 4 | 5 | 6 | # -------------------------------------------------------------------- 7 | # logging 8 | # -------------------------------------------------------------------- 9 | class ValidLogLevels(Enum): 10 | """Enumerates all valid log levels for the logging in cfdm.""" 11 | 12 | DISABLE = 0 13 | WARNING = 1 14 | INFO = 2 15 | DETAIL = 3 16 | DEBUG = -1 17 | 18 | 19 | # -------------------------------------------------------------------- 20 | # masked 21 | # -------------------------------------------------------------------- 22 | """A constant that allows data values to be masked by direct 23 | assignment. This is consistent with the behaviour of numpy masked 24 | arrays. 25 | 26 | For example, masking every element of a field constructs data array 27 | could be done as follows: 28 | 29 | >>> f[...] = cfdm.masked 30 | 31 | """ 32 | masked = np.ma.masked 33 | -------------------------------------------------------------------------------- /docs/_templates/sponsors.html: -------------------------------------------------------------------------------- 1 | {# 2 | Acknowledge sponsors in sidebar. 3 | #} 4 | 5 |
    6 | cfdm development has been supported by 7 | the ERC 8 | through Couplet; 9 | by the EC 10 | Horizon 2020 programme through 11 | IS-ENES3; 12 | by NERC through 13 | UKFAFMIP; 14 | and by NCAS. 15 |
    16 |
    17 | 18 | 19 | 20 |
    21 | 22 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | # This file is currently used only to configure the black Python code 2 | # formatter, rather than provide project metadata (see 3 | # https://www.python.org/dev/peps/pep-0621/) which can be found instead 4 | # in the setup.py file. 5 | 6 | # To run the black checker with this configuration, execute 'black .' in the 7 | # root of this repository. See https://black.readthedocs.io/en/stable/ for 8 | # the 'black' documentation. 9 | [tool.black] 10 | line-length = 79 11 | 12 | # Set for compatibility of 'black' and 'isort' auto-formatting tools 13 | [tool.isort] 14 | profile = "black" 15 | # ... and since we set this against the black default line length: 16 | line_length=79 17 | # Prevent isort from auto-formatting '__init__.py' file imports because 18 | # they require a specific non-aphabetical (etc.) ordering else they will 19 | # cause errors due to bad or circular importing across the modules. 20 | extend_skip_glob = [ 21 | "**/__init__.py", 22 | ] 23 | -------------------------------------------------------------------------------- /cfdm/datum.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class Datum(mixin.Parameters, mixin.NetCDFVariable, mixin.Files, core.Datum): 5 | """A datum component of a CF data model coordinate reference. 6 | 7 | A datum is a complete or partial definition of the zeroes of the 8 | dimension and auxiliary coordinate constructs which define a 9 | coordinate system. 10 | 11 | The datum may contain the definition of a geophysical surface 12 | which corresponds to the zero of a vertical coordinate construct, 13 | and this may be required for both horizontal and vertical 14 | coordinate systems. 15 | 16 | Elements of the datum not specified may be implied by the 17 | properties of the dimension and auxiliary coordinate constructs 18 | referenced by the `CoordinateReference` instance that contains the 19 | datum. 20 | 21 | **NetCDF interface** 22 | 23 | {{netCDF variable}} 24 | 25 | .. versionadded:: (cfdm) 1.7.0 26 | 27 | """ 28 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lat/zarr.json: -------------------------------------------------------------------------------- 1 | { 2 | "shape": [ 3 | 5 4 | ], 5 | "data_type": "float64", 6 | "chunk_grid": { 7 | "name": "regular", 8 | "configuration": { 9 | "chunk_shape": [ 10 | 5 11 | ] 12 | } 13 | }, 14 | "chunk_key_encoding": { 15 | "name": "default", 16 | "configuration": { 17 | "separator": "/" 18 | } 19 | }, 20 | "fill_value": 0.0, 21 | "codecs": [ 22 | { 23 | "name": "bytes", 24 | "configuration": { 25 | "endian": "little" 26 | } 27 | }, 28 | { 29 | "name": "zstd", 30 | "configuration": { 31 | "level": 0, 32 | "checksum": false 33 | } 34 | } 35 | ], 36 | "attributes": { 37 | "units": "degrees_north", 38 | "standard_name": "latitude", 39 | "bounds": "lat_bnds", 40 | }, 41 | "dimension_names": [ 42 | "lat" 43 | ], 44 | "zarr_format": 3, 45 | "node_type": "array", 46 | "storage_transformers": [] 47 | } 48 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/lon/zarr.json: -------------------------------------------------------------------------------- 1 | { 2 | "shape": [ 3 | 8 4 | ], 5 | "data_type": "float64", 6 | "chunk_grid": { 7 | "name": "regular", 8 | "configuration": { 9 | "chunk_shape": [ 10 | 8 11 | ] 12 | } 13 | }, 14 | "chunk_key_encoding": { 15 | "name": "default", 16 | "configuration": { 17 | "separator": "/" 18 | } 19 | }, 20 | "fill_value": 0.0, 21 | "codecs": [ 22 | { 23 | "name": "bytes", 24 | "configuration": { 25 | "endian": "little" 26 | } 27 | }, 28 | { 29 | "name": "zstd", 30 | "configuration": { 31 | "level": 0, 32 | "checksum": false 33 | } 34 | } 35 | ], 36 | "attributes": { 37 | "units": "degrees_east", 38 | "standard_name": "longitude", 39 | "bounds": "lon_bnds", 40 | }, 41 | "dimension_names": [ 42 | "lon" 43 | ], 44 | "zarr_format": 3, 45 | "node_type": "array", 46 | "storage_transformers": [] 47 | } 48 | -------------------------------------------------------------------------------- /codemeta.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": "https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld", 3 | "@type": "Code", 4 | "author": [ 5 | { 6 | "@id": "https://orcid.org/0000-0001-5106-7502", 7 | "@type": "Person", 8 | "email": "david.hassell@ncas.ac.uk", 9 | "name": "David Hassell", 10 | "affiliation": "NCAS" 11 | }, 12 | { 13 | "@id": "https://orcid.org/0000-0002-6180-3603", 14 | "@type": "Person", 15 | "email": "sadie.bartholomew@ncas.ac.uk", 16 | "name": "Sadie L. Bartholomew", 17 | "affiliation": "NCAS" 18 | } 19 | ], 20 | "identifier": "", 21 | "codeRepository": "https://github.com/NCAS-CMS/cfdm", 22 | "datePublished": "2025-10-15", 23 | "dateModified": "2025-10-15", 24 | "dateCreated": "2025-10-15", 25 | "description": "A Python reference implementation of the CF data model.", 26 | "keywords": "cf, metadata, netcdf, python", 27 | "license": "MIT", 28 | "title": "cfdm", 29 | "version": "1.12.3.1" 30 | } 31 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | # This config overrides the default Codecov config, as outlined at: 2 | # https://docs.codecov.io/docs/codecov-yaml 3 | 4 | coverage: 5 | round: up 6 | range: "70...100" 7 | precision: 2 8 | 9 | status: 10 | project: 11 | default: 12 | target: auto 13 | threshold: "0%" 14 | base: auto 15 | branches: 16 | - main 17 | if_no_uploads: success 18 | if_not_found: success 19 | if_ci_failed: error 20 | only_pulls: true 21 | patch: 22 | default: 23 | target: "90%" 24 | threshold: "10%" 25 | base: auto 26 | branches: 27 | - main 28 | if_no_uploads: success 29 | if_not_found: success 30 | if_ci_failed: error 31 | only_pulls: false 32 | 33 | # Note: there is a Codecov 'ignore' key to ignore certain paths, but this is 34 | # not needed (I think) since we ignore the test directory path etc. in 35 | # generating our coverage XML, so it should already not be processed. 36 | -------------------------------------------------------------------------------- /cfdm/core/coordinateconversion.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class CoordinateConversion(abstract.ParametersDomainAncillaries): 5 | """A coordinate conversion for a coordinate reference. 6 | 7 | That is, a coordinate conversion component of a coordinate 8 | reference construct of the CF data model. 9 | 10 | A coordinate conversion formula converting coordinate values taken 11 | from the dimension or auxiliary coordinate constructs to a 12 | different coordinate system. A term of the conversion formula can 13 | be a scalar or vector parameter which does not depend on any 14 | domain axis constructs, may have units, or may be a descriptive 15 | string (such as the projection name "mercator"), or it can be a 16 | reference to a domain ancillary construct (such as one containing 17 | spatially varying orography data). A coordinate reference 18 | construct relates the coordinate values of the field to locations 19 | in a planetary reference frame. 20 | 21 | .. versionadded:: (cfdm) 1.7.0 22 | 23 | """ 24 | -------------------------------------------------------------------------------- /cfdm/mixin/__init__.py: -------------------------------------------------------------------------------- 1 | from .boundsmixin import BoundsMixin 2 | from .container import Container 3 | from .files import Files 4 | from .quantizationmixin import QuantizationMixin 5 | from .properties import Properties 6 | from .propertiesdata import PropertiesData 7 | from .propertiesdatabounds import PropertiesDataBounds 8 | from .coordinate import Coordinate 9 | from .topology import Topology 10 | 11 | from .parameters import Parameters 12 | from .parametersdomainancillaries import ParametersDomainAncillaries 13 | 14 | from .netcdf import ( 15 | NetCDFComponents, 16 | NetCDFGlobalAttributes, 17 | NetCDFGroupAttributes, 18 | NetCDFUnlimitedDimension, 19 | NetCDFDimension, 20 | NetCDFExternal, 21 | NetCDFGeometry, 22 | NetCDFGroupsMixin, 23 | NetCDFChunks, 24 | NetCDFInterpolationSubareaDimension, 25 | NetCDFMixin, 26 | NetCDFNodeCoordinateVariable, 27 | NetCDFSampleDimension, 28 | NetCDFSubsampledDimension, 29 | NetCDFUnreferenced, 30 | NetCDFVariable, 31 | ) 32 | 33 | from .fielddomain import FieldDomain 34 | -------------------------------------------------------------------------------- /cfdm/coordinateconversion.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class CoordinateConversion( 5 | mixin.ParametersDomainAncillaries, core.CoordinateConversion 6 | ): 7 | """A coordinate conversion component. 8 | 9 | Specifically, a coordinate conversion component of a coordinate 10 | reference construct of the CF data model. 11 | 12 | A coordinate conversion formula converting coordinate values taken 13 | from the dimension or auxiliary coordinate constructs to a 14 | different coordinate system. A term of the conversion formula can 15 | be a scalar or vector parameter which does not depend on any 16 | domain axis constructs, may have units, or may be a descriptive 17 | string (such as the projection name "mercator"), or it can be a 18 | reference to a domain ancillary construct (such as one containing 19 | spatially varying orography data). A coordinate reference 20 | construct relates the coordinate values of the field to locations 21 | in a planetary reference frame. 22 | 23 | .. versionadded:: (cfdm) 1.7.0 24 | 25 | """ 26 | -------------------------------------------------------------------------------- /cfdm/test/example_field_0.zarr3/q/zarr.json: -------------------------------------------------------------------------------- 1 | { 2 | "shape": [ 3 | 5, 4 | 8 5 | ], 6 | "data_type": "float64", 7 | "chunk_grid": { 8 | "name": "regular", 9 | "configuration": { 10 | "chunk_shape": [ 11 | 5, 12 | 8 13 | ] 14 | } 15 | }, 16 | "chunk_key_encoding": { 17 | "name": "default", 18 | "configuration": { 19 | "separator": "/" 20 | } 21 | }, 22 | "fill_value": 0.0, 23 | "codecs": [ 24 | { 25 | "name": "bytes", 26 | "configuration": { 27 | "endian": "little" 28 | } 29 | }, 30 | { 31 | "name": "zstd", 32 | "configuration": { 33 | "level": 0, 34 | "checksum": false 35 | } 36 | } 37 | ], 38 | "attributes": { 39 | "project": "research", 40 | "standard_name": "specific_humidity", 41 | "units": "1", 42 | "cell_methods": "area: mean", 43 | "coordinates": "time", 44 | }, 45 | "dimension_names": [ 46 | "lat", 47 | "lon" 48 | ], 49 | "zarr_format": 3, 50 | "node_type": "array", 51 | "storage_transformers": [] 52 | } 53 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | name: Linting 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | # default (from docs) is just on [opened, synchronize, reopened] 9 | types: [opened, reopened, ready_for_review, edited] 10 | branches: 11 | - main 12 | 13 | # Note: only running this on Ubuntu (latest) and Python 3.8 as representative, 14 | # since the linting output should be machine dependent and not vary much if 15 | # at all by Python minor version. 16 | 17 | jobs: 18 | # Lint against selected pre-commit hooks (see https://pre-commit.com 19 | # and https://github.com/pre-commit/action). 20 | # *The config. applied here is from our .pre-commit-config.yaml* 21 | # 22 | # Note the pre-commit linting includes all of the other linters configured 23 | # to run as pre-commit hooks, namely black, flake8 and docformatter etc., 24 | # so there is no need to set these up individually! 25 | pre-commit: 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v2 29 | - uses: actions/setup-python@v2 30 | - uses: pre-commit/action@v2.0.0 31 | -------------------------------------------------------------------------------- /cfdm/core/interiorring.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class InteriorRing(abstract.PropertiesData): 5 | """An interior ring array with properties. 6 | 7 | If a cell is composed of multiple polygon parts, an individual 8 | polygon may define an "interior ring", i.e. a region that is to be 9 | omitted from, as opposed to included in, the cell extent. In this 10 | case an interior ring array is required that records whether each 11 | polygon is to be included or excluded from the cell, and is 12 | supplied by an interior ring variable in CF-netCDF. The interior 13 | ring array spans the same domain axis constructs as its coordinate 14 | array, with the addition of an extra dimension that indexes the 15 | parts for each cell. For example, a cell describing the land area 16 | surrounding a lake would require two polygon parts: one defines 17 | the outer boundary of the land area; the other, recorded as an 18 | interior ring, is the lake boundary, defining the inner boundary 19 | of the land area. 20 | 21 | .. versionadded:: (cfdm) 1.8.0 22 | 23 | """ 24 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | # Configure the flake8 code style checker. Note this must be in INI style 2 | # (see https://flake8.pycqa.org/en/latest/). To run the flake8 checker with 3 | # this configuration, simply execute 'flake8' under the root of the repo. 4 | 5 | [flake8] 6 | # Ignores should include listing of pycodestyle ignores as in test_style.py. 7 | # Note W503 is incompatible with PEP8 which we want to abide by 8 | ignore = 9 | W605, 10 | E272, 11 | E402, 12 | E501, 13 | E203, 14 | W503 15 | # Exclude these directories/files, otherwise check all *.py files 16 | exclude = 17 | .git, 18 | __pycache__, 19 | cfdm.egg-info, 20 | docs/build/ 21 | 22 | # Ignore certain rules for some files (can't do this via comments in the files) 23 | per-file-ignores = 24 | # Ignore unused imports in __init__ modules, as they are there to provide 25 | # the project namespace (decide not to use __all__ to contain these, as 26 | # suggested in some flake8 discussions e.g. by the core maintainer at 27 | # https://stackoverflow.com/questions/59167405/) 28 | __init__.py: F401 29 | */__init__.py: F401 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 NCAS CMS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.Constant.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.Constant 5 | ============= 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.Constant 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../attribute/ 21 | :template: attribute.rst 22 | 23 | ~cfdm.Constant.value 24 | 25 | Copying 26 | ------- 27 | 28 | .. rubric:: Methods 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.Constant.copy 36 | 37 | .. rubric:: Attributes 38 | 39 | .. autosummary:: 40 | :nosignatures: 41 | :toctree: ../attribute/ 42 | :template: attribute.rst 43 | 44 | ~cfdm.Constant._func 45 | 46 | Special 47 | ------- 48 | 49 | .. rubric:: Methods 50 | 51 | .. autosummary:: 52 | :nosignatures: 53 | :toctree: ../method/ 54 | :template: method.rst 55 | 56 | ~cfdm.Constant.__deepcopy__ 57 | ~cfdm.Constant.__enter__ 58 | ~cfdm.Constant.__exit__ 59 | ~cfdm.Constant.__repr__ 60 | ~cfdm.Constant.__str__ 61 | 62 | -------------------------------------------------------------------------------- /cfdm/data/subarray/mixin/linearinterpolation.py: -------------------------------------------------------------------------------- 1 | class LinearInterpolation: 2 | """Mixin class for linear interpolation. 3 | 4 | See CF appendix J "Coordinate Interpolation Methods". 5 | 6 | .. versionadded:: (cfdm) 1.10.0.0 7 | 8 | """ 9 | 10 | def _linear_interpolation(self, ua, ub, d1, s=None): 11 | """Interpolate linearly between two points. 12 | 13 | u = fl(ua, ub, s) = ua + s*(ub-ua) 14 | = ua*(1-s) + ub*s 15 | 16 | See CF appendix J "Coordinate Interpolation Methods". 17 | 18 | .. versionadded:: (cfdm) 1.10.0.0 19 | 20 | .. seealso:: `_s` 21 | 22 | :Parameters: 23 | 24 | ua, ub: `numpy.ndarray` 25 | The tie points at locations A and B, in the sense of 26 | CF appendix J Figure J.1. 27 | 28 | {{d1: `int`}} 29 | 30 | {{s: array_like, optional}} 31 | 32 | :Returns: 33 | 34 | `numpy.ndarray` 35 | The result of interpolating the tie points to interior 36 | locations implied by *s*. 37 | 38 | """ 39 | s = self._s(d1, s=s) 40 | u = ua + s * (ub - ua) 41 | return u 42 | -------------------------------------------------------------------------------- /cfdm/mixin/boundsmixin.py: -------------------------------------------------------------------------------- 1 | class BoundsMixin: 2 | """Mixin class for a bounds variable. 3 | 4 | .. versionadded:: (cfdm) 1.12.2.0 5 | 6 | """ 7 | 8 | def __initialise_from_source(self, source, copy=True): 9 | """Initialise inherited properties from a source. 10 | 11 | This method is called by 12 | `_Container__parent_initialise_from_source`, which in turn is 13 | called by `cfdm.core.Container.__init__`. 14 | 15 | .. versionadded:: (cfdm) 1.12.2.0 16 | 17 | :Parameters: 18 | 19 | source: 20 | The object from which to extract the initialisation 21 | information. Typically, but not necessarily, a 22 | `{{class}}` object. 23 | 24 | copy: `bool`, optional 25 | If True (the default) then deep copy the 26 | initialisation information. 27 | 28 | :Returns: 29 | 30 | `None` 31 | 32 | """ 33 | try: 34 | inherited_properties = source.inherited_properties() 35 | except AttributeError: 36 | inherited_properties = {} 37 | 38 | self._set_component( 39 | "inherited_properties", inherited_properties, copy=False 40 | ) 41 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Thank you for taking the time to consider making a contribution to the 2 | cfdm package. 3 | 4 | Please consult the 5 | [dedicated guidance page](https://ncas-cms.github.io/cfdm/contributing.html) 6 | in the documentation for detailed guidance on contributing to cfdm. 7 | 8 | Overall, general questions, suggestions for enhancements, and reports 9 | of bugs are appreciated and should be reported via the 10 | [GitHub issue tracker](https://github.com/NCAS-CMS/cfdm/issues). 11 | 12 | Code-change contributions to cfdm are also very welcome, though to 13 | ensure the work is in line with plans for development of the library, please 14 | always discuss any intended changes with the core development team in the 15 | first instance. The standard way to do so is also through the 16 | issue tracker: 17 | 18 | * if there is an existing issue in the tracker than you would like 19 | to address, comment on that issue to indicate you would like to work on 20 | it; 21 | * conversely, if there is not an issue corresponding to your ideas for 22 | contribution, please raise a new issue outlining the idea. 23 | 24 | If you are not sure about any aspect related to contributing after 25 | reading the guidance page, do not hesitate to get in touch by posting 26 | a question in an issue. 27 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.Configuration.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.Configuration 5 | ================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.Configuration 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Copying 14 | ------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.Configuration.copy 24 | 25 | Dictionary functionality 26 | ------------------------ 27 | 28 | .. rubric:: Methods 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.Configuration.clear 36 | ~cfdm.Configuration.fromkeys 37 | ~cfdm.Configuration.get 38 | ~cfdm.Configuration.items 39 | ~cfdm.Configuration.keys 40 | ~cfdm.Configuration.pop 41 | ~cfdm.Configuration.popitem 42 | ~cfdm.Configuration.setdefault 43 | ~cfdm.Configuration.update 44 | ~cfdm.Configuration.values 45 | 46 | Special 47 | ------- 48 | 49 | .. rubric:: Methods 50 | 51 | .. autosummary:: 52 | :nosignatures: 53 | :toctree: ../method/ 54 | :template: method.rst 55 | 56 | ~cfdm.Configuration.__enter__ 57 | ~cfdm.Configuration.__exit__ 58 | ~cfdm.Configuration.__repr__ 59 | 60 | -------------------------------------------------------------------------------- /cfdm/data/subarray/linearsubarray.py: -------------------------------------------------------------------------------- 1 | from .abstract import SubsampledSubarray 2 | from .mixin import LinearInterpolation 3 | 4 | 5 | class LinearSubarray(LinearInterpolation, SubsampledSubarray): 6 | """A subarray of an array compressed by subsamplng. 7 | 8 | A subarray describes a unique part of the uncompressed array. 9 | 10 | The compressed data is reconstituted by linear interpolation. 11 | 12 | See CF appendix J "Coordinate Interpolation Methods". 13 | 14 | .. versionadded:: (cfdm) 1.10.0.0 15 | 16 | """ 17 | 18 | def __getitem__(self, indices): 19 | """Return a subspace of the uncompressed data. 20 | 21 | x.__getitem__(indices) <==> x[indices] 22 | 23 | Returns a subspace of the uncompressed data as an independent 24 | numpy array. 25 | 26 | .. versionadded:: (cfdm) 1.10.0.0 27 | 28 | """ 29 | (d1,) = tuple(self.compressed_dimensions()) 30 | 31 | u_ab = self._select_data() 32 | 33 | u = self._linear_interpolation( 34 | ua=self._select_location(u_ab, {d1: 0}), 35 | ub=self._select_location(u_ab, {d1: 1}), 36 | d1=d1, 37 | ) 38 | u = self._post_process(u) 39 | 40 | if indices is Ellipsis: 41 | return u 42 | 43 | return u[indices] 44 | -------------------------------------------------------------------------------- /docs/source/functions.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | .. _function: 5 | 6 | **cfdm functions** 7 | ================== 8 | 9 | ---- 10 | 11 | Version |release| for version |version| of the CF conventions. 12 | 13 | Reading and writing 14 | ------------------- 15 | 16 | .. autosummary:: 17 | :nosignatures: 18 | :toctree: function/ 19 | :template: function.rst 20 | 21 | cfdm.read 22 | cfdm.write 23 | cfdm.netcdf_flatten 24 | cfdm.netcdf_index 25 | 26 | Mathematical operations 27 | ----------------------- 28 | 29 | .. autosummary:: 30 | :nosignatures: 31 | :toctree: function/ 32 | :template: function.rst 33 | 34 | cfdm.atol 35 | cfdm.rtol 36 | 37 | Resource management 38 | ------------------- 39 | 40 | .. autosummary:: 41 | :nosignatures: 42 | :toctree: function/ 43 | :template: function.rst 44 | 45 | cfdm.configuration 46 | cfdm.chunksize 47 | 48 | Miscellaneous 49 | ------------- 50 | 51 | .. autosummary:: 52 | :nosignatures: 53 | :toctree: function/ 54 | :template: function.rst 55 | 56 | cfdm.CF 57 | cfdm.abspath 58 | cfdm.dirname 59 | cfdm.environment 60 | cfdm.example_field 61 | cfdm.example_fields 62 | cfdm.example_domain 63 | cfdm.implementation 64 | cfdm.integer_dtype 65 | cfdm.log_level 66 | cfdm.unique_constructs 67 | -------------------------------------------------------------------------------- /cfdm/test/test_List.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class ListTest(unittest.TestCase): 11 | """Unit test for the List class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or 18 | # calls (those without a 'verbose' option to do the same) 19 | # e.g. to debug them, wrap them (for methods, start-to-end 20 | # internally) as follows: 21 | # 22 | # cfdm.LOG_LEVEL('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | self.gathered = "gathered.nc" 27 | 28 | def test_List__repr__str__dump(self): 29 | """Test all means of List inspection.""" 30 | f = cfdm.read(self.gathered)[0] 31 | 32 | list_ = f.data.get_list() 33 | 34 | _ = repr(list_) 35 | _ = str(list_) 36 | self.assertIsInstance(list_.dump(display=False), str) 37 | 38 | 39 | if __name__ == "__main__": 40 | print("Run date:", datetime.datetime.now()) 41 | cfdm.environment() 42 | print() 43 | unittest.main(verbosity=2) 44 | -------------------------------------------------------------------------------- /cfdm/test/test_Index.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class IndexTest(unittest.TestCase): 11 | """Unit test for the Index class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or 18 | # calls (those without a 'verbose' option to do the same) 19 | # e.g. to debug them, wrap them (for methods, start-to-end 20 | # internally) as follows: 21 | # 22 | # cfdm.LOG_LEVEL('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | self.indexed = "DSG_timeSeries_indexed.nc" 27 | 28 | def test_Index__repr__str__dump(self): 29 | """Test all means of Index inspection.""" 30 | f = cfdm.read(self.indexed)[0] 31 | 32 | index = f.data.get_index() 33 | 34 | _ = repr(index) 35 | _ = str(index) 36 | self.assertIsInstance(index.dump(display=False), str) 37 | 38 | 39 | if __name__ == "__main__": 40 | print("Run date:", datetime.datetime.now()) 41 | cfdm.environment() 42 | print() 43 | unittest.main(verbosity=2) 44 | -------------------------------------------------------------------------------- /cfdm/test/test_Count.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class CountTest(unittest.TestCase): 11 | """Unit test for the Count class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or 18 | # calls (those without a 'verbose' option to do the same) 19 | # e.g. to debug them, wrap them (for methods, start-to-end 20 | # internally) as follows: 21 | # 22 | # cfdm.LOG_LEVEL('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | self.contiguous = "DSG_timeSeries_contiguous.nc" 27 | 28 | def test_Count__repr__str__dump(self): 29 | """Test all means of Count inspection.""" 30 | f = cfdm.read(self.contiguous)[0] 31 | 32 | count = f.data.get_count() 33 | 34 | _ = repr(count) 35 | _ = str(count) 36 | self.assertIsInstance(count.dump(display=False), str) 37 | 38 | 39 | if __name__ == "__main__": 40 | print("Run date:", datetime.datetime.now()) 41 | cfdm.environment() 42 | print() 43 | unittest.main(verbosity=2) 44 | -------------------------------------------------------------------------------- /cfdm/test/test_Quantization.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import unittest 3 | 4 | import cfdm 5 | 6 | 7 | class QuantizationTest(unittest.TestCase): 8 | """Unit test for the Quantization class.""" 9 | 10 | q = cfdm.Quantization({"quantization_nsd": 4, "algorithm": "bitgroom"}) 11 | 12 | def test_Quantization_algorithm_parameters(self): 13 | """Test Quantization.algorithm_parameters.""" 14 | self.assertEqual( 15 | cfdm.Quantization().algorithm_parameters(), 16 | { 17 | "bitgroom": "quantization_nsd", 18 | "bitround": "quantization_nsb", 19 | "digitround": "quantization_nsd", 20 | "granular_bitround": "quantization_nsd", 21 | }, 22 | ) 23 | 24 | def test_Quantization__str__(self): 25 | """Test Quantization.__str__.""" 26 | self.assertEqual(str(self.q), "algorithm=bitgroom, quantization_nsd=4") 27 | 28 | def test_Quantization_dump(self): 29 | """Test Quantization.dump.""" 30 | self.assertEqual( 31 | self.q.dump(display=False), 32 | "Quantization: \n" 33 | " algorithm = 'bitgroom'\n" 34 | " quantization_nsd = 4", 35 | ) 36 | 37 | 38 | if __name__ == "__main__": 39 | print("Run date:", datetime.datetime.now()) 40 | cfdm.environment() 41 | print("") 42 | unittest.main(verbosity=2) 43 | -------------------------------------------------------------------------------- /cfdm/test/test_core_2.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import datetime 3 | import unittest 4 | 5 | import numpy as np 6 | 7 | import cfdm 8 | 9 | 10 | class Core2Test(unittest.TestCase): 11 | """Unit test for the `cfdm.core` package.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or 18 | # calls (those without a 'verbose' option to do the same) 19 | # e.g. to debug them, wrap them (for methods, start-to-end 20 | # internally) as follows: 21 | # 22 | # cfdm.log_level('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | def test_core_NumpyArray(self): 27 | """Test cfdm.core.NumpyArray class.""" 28 | a = cfdm.core.NumpyArray(np.array([1, 2, 3])) 29 | 30 | # __deepcopy__ 31 | copy.deepcopy(a) 32 | 33 | # __array__ 34 | np.array(a) 35 | np.array(a, dtype="float") 36 | 37 | def test_core_Container(self): 38 | """Test cfdm.core.Container class.""" 39 | cfdm.core.Container(source="qwerty") 40 | 41 | 42 | if __name__ == "__main__": 43 | print("Run date:", datetime.datetime.now()) 44 | cfdm.environment() 45 | print("") 46 | unittest.main(verbosity=2) 47 | -------------------------------------------------------------------------------- /cfdm/read_write/abstract/abstractio.py: -------------------------------------------------------------------------------- 1 | import abc 2 | 3 | 4 | class IO(metaclass=abc.ABCMeta): 5 | """Abstract base class for reading and writing Fields.""" 6 | 7 | def __init__(self, implementation): 8 | """**Initialisation** 9 | 10 | :Parameters: 11 | 12 | implementation: `Implementation' 13 | The objects required to represent a Field. 14 | 15 | """ 16 | self.implementation = implementation 17 | 18 | @abc.abstractmethod 19 | def file_close(self, *args, **kwargs): 20 | """Close the dataset file.""" 21 | raise NotImplementedError() # pragma: no cover 22 | 23 | @abc.abstractmethod 24 | def file_open(self, *args, **kwargs): 25 | """Open the dataset file.""" 26 | raise NotImplementedError() # pragma: no cover 27 | 28 | 29 | class IORead(IO, metaclass=abc.ABCMeta): 30 | """Abstract base class for instantiating Fields from a dataset.""" 31 | 32 | @abc.abstractmethod 33 | def read(self, *args, **kwargs): 34 | """Read fields from a netCDF file.""" 35 | raise NotImplementedError() # pragma: no cover 36 | 37 | 38 | class IOWrite(IO, metaclass=abc.ABCMeta): 39 | """Abstract base class for writing Fields to a dataset.""" 40 | 41 | @abc.abstractmethod 42 | def write(self, *args, **kwargs): 43 | """Write fields to a netCDF file.""" 44 | raise NotImplementedError() # pragma: no cover 45 | -------------------------------------------------------------------------------- /cfdm/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .abstract import Array 2 | from .abstract import CompressedArray 3 | from .abstract import MeshArray 4 | from .abstract import RaggedArray 5 | 6 | from .subarray import ( 7 | BiLinearSubarray, 8 | BiQuadraticLatitudeLongitudeSubarray, 9 | BoundsFromNodesSubarray, 10 | CellConnectivitySubarray, 11 | GatheredSubarray, 12 | InterpolationSubarray, 13 | LinearSubarray, 14 | QuadraticLatitudeLongitudeSubarray, 15 | QuadraticSubarray, 16 | RaggedSubarray, 17 | ) 18 | 19 | 20 | from .subarray.abstract import MeshSubarray, Subarray, SubsampledSubarray 21 | 22 | from .aggregatedarray import AggregatedArray 23 | from .boundsfromnodesarray import BoundsFromNodesArray 24 | from .cellconnectivityarray import CellConnectivityArray 25 | from .gatheredarray import GatheredArray 26 | from .fullarray import FullArray 27 | from .h5netcdfarray import H5netcdfArray 28 | from .netcdfarray import NetCDFArray 29 | from .netcdf4array import NetCDF4Array 30 | from .netcdfindexer import netcdf_indexer 31 | from .numpyarray import NumpyArray 32 | from .pointtopologyarray import PointTopologyArray 33 | from .raggedcontiguousarray import RaggedContiguousArray 34 | from .raggedindexedarray import RaggedIndexedArray 35 | from .raggedindexedcontiguousarray import RaggedIndexedContiguousArray 36 | from .sparsearray import SparseArray 37 | from .subsampledarray import SubsampledArray 38 | from .zarrarray import ZarrArray 39 | 40 | from .data import Data 41 | -------------------------------------------------------------------------------- /cfdm/test/test_Bounds.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class DimensionCoordinateTest(unittest.TestCase): 11 | """Unit test for the DimensionCoordinate class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or 18 | # calls (those without a 'verbose' option to do the same) 19 | # e.g. to debug them, wrap them (for methods, start-to-end 20 | # internally) as follows: 21 | # 22 | # cfdm.LOG_LEVEL('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | def test_Bounds_inherited_properties(self): 27 | """Test cfdm.Bounds.inherited_properties.""" 28 | b = cfdm.Bounds() 29 | 30 | properties = {"standard_name": "latitude"} 31 | b._set_component("inherited_properties", properties, copy=False) 32 | self.assertEqual(b.inherited_properties(), properties) 33 | 34 | c = b.copy() 35 | self.assertEqual(c.inherited_properties(), properties) 36 | 37 | 38 | if __name__ == "__main__": 39 | print("Run date:", datetime.datetime.now()) 40 | cfdm.environment() 41 | print() 42 | unittest.main(verbosity=2) 43 | -------------------------------------------------------------------------------- /cfdm/core/domainancillary.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class DomainAncillary(abstract.PropertiesDataBounds): 5 | """A domain ancillary construct of the CF data model. 6 | 7 | A domain ancillary construct provides information which is needed 8 | for computing the location of cells in an alternative coordinate 9 | system. It is referenced by a term of a coordinate conversion 10 | formula of a coordinate reference construct. It contains a data 11 | array which depends on zero or more of the domain axes. 12 | 13 | It also contains an optional array of cell bounds, stored in a 14 | `Bounds` object, recording the extents of each cell (only 15 | applicable if the array contains coordinate data), and properties 16 | to describe the data. 17 | 18 | An array of cell bounds spans the same domain axes as the data 19 | array, with the addition of an extra dimension whose size is that 20 | of the number of vertices of each cell. 21 | 22 | .. versionadded:: (cfdm) 1.7.0 23 | 24 | """ 25 | 26 | @property 27 | def construct_type(self): 28 | """Return a description of the construct type. 29 | 30 | .. versionadded:: (cfdm) 1.7.0 31 | 32 | :Returns: 33 | 34 | `str` 35 | The construct type. 36 | 37 | **Examples** 38 | 39 | >>> d = {{package}}.{{class}}() 40 | >>> d.construct_type 41 | 'domain_ancillary' 42 | 43 | """ 44 | return "domain_ancillary" 45 | -------------------------------------------------------------------------------- /cfdm/data/subarray/bilinearsubarray.py: -------------------------------------------------------------------------------- 1 | from .abstract import SubsampledSubarray 2 | from .mixin import BiLinearInterpolation 3 | 4 | 5 | class BiLinearSubarray(BiLinearInterpolation, SubsampledSubarray): 6 | """A subarray of an array compressed by subsamplng. 7 | 8 | A subarray describes a unique part of the uncompressed array. 9 | 10 | The compressed data is reconstituted by bi-linear interpolation. 11 | 12 | See CF appendix J "Coordinate Interpolation Methods". 13 | 14 | .. versionadded:: (cfdm) 1.10.0.0 15 | 16 | """ 17 | 18 | def __getitem__(self, indices): 19 | """Return a subspace of the uncompressed data. 20 | 21 | x.__getitem__(indices) <==> x[indices] 22 | 23 | Returns a subspace of the uncompressed data as an independent 24 | numpy array. 25 | 26 | .. versionadded:: (cfdm) 1.10.0.0 27 | 28 | """ 29 | (d2, d1) = sorted(self.compressed_dimensions()) 30 | 31 | u_abcd = self._select_data() 32 | 33 | u = self._bilinear_interpolation( 34 | ua=self._select_location(u_abcd, {d2: 0, d1: 0}), 35 | ub=self._select_location(u_abcd, {d2: 0, d1: 1}), 36 | uc=self._select_location(u_abcd, {d2: 1, d1: 0}), 37 | ud=self._select_location(u_abcd, {d2: 1, d1: 1}), 38 | d2=d2, 39 | d1=d1, 40 | ) 41 | u = self._post_process(u) 42 | 43 | if indices is Ellipsis: 44 | return u 45 | 46 | return u[indices] 47 | -------------------------------------------------------------------------------- /cfdm/nodecountproperties.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class NodeCountProperties( 5 | mixin.NetCDFVariable, 6 | mixin.Properties, 7 | mixin.Files, 8 | core.abstract.Properties, 9 | ): 10 | """Properties for a netCDF node count variable. 11 | 12 | **NetCDF interface** 13 | 14 | {{netCDF variable}} 15 | 16 | .. versionadded:: (cfdm) 1.8.0 17 | 18 | """ 19 | 20 | def dump( 21 | self, 22 | display=True, 23 | _key=None, 24 | _title=None, 25 | _create_title=True, 26 | _prefix="", 27 | _level=0, 28 | _omit_properties=None, 29 | ): 30 | """A full description of the node count variable. 31 | 32 | Returns a description of all properties. 33 | 34 | .. versionadded:: (cfdm) 1.8.0 35 | 36 | :Parameters: 37 | 38 | display: `bool`, optional 39 | If False then return the description as a string. By 40 | default the description is printed. 41 | 42 | :Returns: 43 | 44 | {{returns dump}} 45 | 46 | """ 47 | if _create_title and _title is None: 48 | _title = "Node Count: " + self.identity(default="") 49 | 50 | return super().dump( 51 | display=display, 52 | _key=_key, 53 | _omit_properties=_omit_properties, 54 | _prefix=_prefix, 55 | _level=_level, 56 | _title=_title, 57 | _create_title=_create_title, 58 | ) 59 | -------------------------------------------------------------------------------- /cfdm/data/subarray/interpolationsubarray.py: -------------------------------------------------------------------------------- 1 | from .abstract import SubsampledSubarray 2 | 3 | 4 | class InterpolationSubarray(SubsampledSubarray): 5 | """A subarray of an array compressed by subsamplng. 6 | 7 | A subarray describes a unique part of the uncompressed array. 8 | 9 | The subarray has no standardised interpolation algorithm. An 10 | interpolation algorithm may have been provided via the 11 | *interpolation_description* parameter, but that algorithm can not 12 | be interpreted by the {{class}} object. Nonetheless, the subarray 13 | is still representable in its uncompressed form (e.g. its shape is 14 | known), even though the uncompressed data values can not be 15 | calculated. 16 | 17 | See CF section 8.3.3 "Interpolation Variable". 18 | 19 | .. versionadded:: (cfdm) 1.10.0.2 20 | 21 | """ 22 | 23 | def __getitem__(self, indices): 24 | """Return a subspace of the uncompressed data. 25 | 26 | x.__getitem__(indices) <==> x[indices] 27 | 28 | Always raises a `ValueError`, rather than returning a subspace 29 | of the uncompressed data as an independent numpy array, since 30 | the non-standardised interpolation algorithm can't be 31 | interpreted. 32 | 33 | .. versionadded:: (cfdm) 1.10.0.2 34 | 35 | """ 36 | raise ValueError( 37 | "Can't uncompress subsampled data using a non-standardised " 38 | "interpolation algorithm:\n\n" 39 | f"{self.get_interpolation_description('')}" 40 | ) 41 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.NumpyArray.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.NumpyArray 5 | ==================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.NumpyArray 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../attribute/ 21 | :template: attribute.rst 22 | 23 | ~cfdm.core.NumpyArray.array 24 | ~cfdm.core.NumpyArray.dtype 25 | ~cfdm.core.NumpyArray.ndim 26 | ~cfdm.core.NumpyArray.shape 27 | ~cfdm.core.NumpyArray.size 28 | 29 | Miscellaneous 30 | ------------- 31 | 32 | .. autosummary:: 33 | :nosignatures: 34 | :toctree: ../method/ 35 | :template: method.rst 36 | 37 | ~cfdm.core.NumpyArray.copy 38 | 39 | Docstring substitutions 40 | ----------------------- 41 | 42 | .. rubric:: Methods 43 | 44 | .. autosummary:: 45 | :nosignatures: 46 | :toctree: ../method/ 47 | :template: method.rst 48 | 49 | ~cfdm.core.NumpyArray._docstring_special_substitutions 50 | ~cfdm.core.NumpyArray._docstring_substitutions 51 | ~cfdm.core.NumpyArray._docstring_package_depth 52 | ~cfdm.core.NumpyArray._docstring_method_exclusions 53 | -------------------------------------------------------------------------------- /cfdm/core/bounds.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class Bounds(abstract.PropertiesData): 5 | """A cell bounds component. 6 | 7 | That is, a cell bounds component of a coordinate or domain 8 | ancillary construct of the CF data model. 9 | 10 | An array of cell bounds spans the same domain axes as its 11 | coordinate array, with the addition of an extra dimension whose 12 | size is that of the number of vertices of each cell. This extra 13 | dimension does not correspond to a domain axis construct since it 14 | does not relate to an independent axis of the domain. Note that, 15 | for climatological time axes, the bounds are interpreted in a 16 | special way indicated by the cell method constructs. 17 | 18 | .. versionadded:: (cfdm) 1.7.0 19 | 20 | """ 21 | 22 | def __init__( 23 | self, 24 | properties=None, 25 | data=None, 26 | source=None, 27 | copy=True, 28 | _use_data=True, 29 | ): 30 | """**Initialisation** 31 | 32 | :Parameters: 33 | 34 | {{init properties: `dict`, optional}} 35 | 36 | *Parameter example:* 37 | ``properties={'standard_name': 'longitude'}`` 38 | 39 | {{init data: data_like, optional}} 40 | 41 | {{init source: optional}} 42 | 43 | {{init copy: `bool`, optional}} 44 | 45 | """ 46 | super().__init__( 47 | properties=properties, 48 | data=data, 49 | source=source, 50 | copy=copy, 51 | _use_data=_use_data, 52 | ) 53 | -------------------------------------------------------------------------------- /cfdm/data/subarray/mixin/bilinearinterpolation.py: -------------------------------------------------------------------------------- 1 | from .linearinterpolation import LinearInterpolation 2 | 3 | 4 | class BiLinearInterpolation(LinearInterpolation): 5 | """Mixin class for bi-linear interpolation. 6 | 7 | See CF appendix J "Coordinate Interpolation Methods". 8 | 9 | .. versionadded:: (cfdm) 1.10.0.0 10 | 11 | """ 12 | 13 | def _bilinear_interpolation(self, ua, ub, uc, ud, d2, d1): 14 | """Interpolate bi-linearly between four points. 15 | 16 | uac = fl(ua, uc, s(ia2, ic2, i2)) 17 | ubd = fl(ub, ud, s(ia2, ic2, i2)) 18 | u(i2, i1) = fl(uac, ubd, s(ia1, ib1, i1)) 19 | 20 | See CF appendix J "Coordinate Interpolation Methods". 21 | 22 | .. versionadded:: (cfdm) 1.10.0.0 23 | 24 | .. seealso:: `_linear_interpolation`, `_s` 25 | 26 | :Parameters: 27 | 28 | ua, ub: `numpy.ndarray` 29 | The tie points at locations A and B, in the sense of 30 | CF appendix J Figure J.2. 31 | 32 | uc, ud: `numpy.ndarray` 33 | The tie points at locations C and D, in the sense of 34 | CF appendix J Figure J.2. 35 | 36 | {{d2: `int`}} 37 | 38 | {{d1: `int`}} 39 | 40 | :Returns: 41 | 42 | `numpy.ndarray` 43 | The result of interpolating the tie points to interior 44 | locations implied by *s*. 45 | 46 | """ 47 | uac = self._linear_interpolation(ua, uc, d2) 48 | ubd = self._linear_interpolation(ub, ud, d2) 49 | 50 | u = self._linear_interpolation(uac, ubd, d1) 51 | 52 | return u 53 | -------------------------------------------------------------------------------- /cfdm/data/subarray/pointtopologyfromedgessubarray.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from .abstract import MeshSubarray 4 | from .mixin import PointTopology 5 | 6 | 7 | class PointTopologyFromEdgesSubarray(PointTopology, MeshSubarray): 8 | """A subarray of a point topology array compressed by UGRID edges. 9 | 10 | A subarray describes a unique part of the uncompressed array. 11 | 12 | .. versionadded:: (cfdm) 1.11.0.0 13 | 14 | """ 15 | 16 | def _connected_nodes(self, node, node_connectivity, masked): 17 | """Return the nodes that are joined to *node* by edges. 18 | 19 | The input *node* is included at the start of the returned 20 | list. 21 | 22 | .. versionadded:: (cfdm) 1.11.0.0 23 | 24 | :Parameters: 25 | 26 | node: `int` 27 | A node identifier. 28 | 29 | node_connectivity: `numpy.ndarray` 30 | A UGRID "edge_node_connectivity" array. 31 | 32 | masked: `bool`, optional 33 | Whether or not *node_connectivity* has masked 34 | elements. 35 | 36 | :Returns: 37 | 38 | `list` 39 | All nodes that are joined to *node*, including *node* 40 | itself at the start. 41 | 42 | """ 43 | nodes = sorted( 44 | set( 45 | node_connectivity[np.where(node_connectivity == node)[0]] 46 | .flatten() 47 | .tolist() 48 | ) 49 | ) 50 | 51 | # Move 'node' to the front of the list 52 | nodes.remove(node) 53 | nodes.insert(0, node) 54 | 55 | return nodes 56 | -------------------------------------------------------------------------------- /cfdm/read_write/netcdf/zarr.py: -------------------------------------------------------------------------------- 1 | class ZarrDimension: 2 | """A named Zarr dimension. 3 | 4 | This class defines a Zarr dimension with the same API as 5 | `netCDF4.Dimension`. 6 | 7 | .. versionadded:: (cfdm) 1.12.2.0 8 | 9 | """ 10 | 11 | def __init__(self, name, size, group): 12 | """**Initialisation** 13 | 14 | :Parameters: 15 | 16 | name: `str` 17 | The dimension name. 18 | 19 | size: `int` 20 | The dimension size. 21 | 22 | group: `zarr.Group` 23 | The group that the dimension is a member of. 24 | 25 | """ 26 | self.name = name 27 | self.size = size 28 | self.group = group 29 | 30 | def __len__(self): 31 | """The size of the dimension. 32 | 33 | x.__len__() <==> len(x) 34 | 35 | .. versionadded:: (cfdm) 1.12.2.0 36 | 37 | """ 38 | return self.size 39 | 40 | def group(self): 41 | """Return the group that the dimension is a member of. 42 | 43 | .. versionadded:: (cfdm) 1.12.2.0 44 | 45 | :Returns: 46 | 47 | `zarr.Group` 48 | The group containing the dimension. 49 | 50 | """ 51 | return self.group 52 | 53 | def isunlimited(self): 54 | """Whether or not the dimension is unlimited. 55 | 56 | In Zarr v2 and v3, dimensions can not be unlimited. 57 | 58 | .. versionadded:: (cfdm) 1.12.2.0 59 | 60 | :Returns: 61 | 62 | `bool` 63 | `True` if and only if the dimension is unlimited. 64 | 65 | """ 66 | return False 67 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Array.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Array 5 | =============== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.Array 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../attribute/ 21 | :template: attribute.rst 22 | 23 | ~cfdm.core.Array.dtype 24 | ~cfdm.core.Array.ndim 25 | ~cfdm.core.Array.shape 26 | ~cfdm.core.Array.size 27 | ~cfdm.core.Array.array 28 | 29 | Miscellaneous 30 | ------------- 31 | 32 | .. rubric:: Methods 33 | 34 | .. autosummary:: 35 | :nosignatures: 36 | :toctree: ../method/ 37 | :template: method.rst 38 | 39 | ~cfdm.core.Array.copy 40 | 41 | Special 42 | ------- 43 | 44 | .. rubric:: Methods 45 | 46 | .. autosummary:: 47 | :nosignatures: 48 | :toctree: ../method/ 49 | :template: method.rst 50 | 51 | ~cfdm.core.Array.__deepcopy__ 52 | 53 | Docstring substitutions 54 | ----------------------- 55 | 56 | .. rubric:: Methods 57 | 58 | .. autosummary:: 59 | :nosignatures: 60 | :toctree: ../method/ 61 | :template: method.rst 62 | 63 | ~cfdm.core.Array._docstring_special_substitutions 64 | ~cfdm.core.Array._docstring_substitutions 65 | ~cfdm.core.Array._docstring_package_depth 66 | ~cfdm.core.Array._docstring_method_exclusions 67 | -------------------------------------------------------------------------------- /tag: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------- 4 | # Run this within a local respository directory to tag the latest 5 | # commit, both locally and in the remote repository. 6 | # 7 | # For example: 8 | # 9 | #>> ./tag 1.7.2 10 | # ++ git log --pretty=format:%H -n 1 11 | # + latest_checksum=2cfa6a85c6d3bcfde3863f3e7417d0099782e198 12 | # + git tag -a v1.7.2 -m 'version 1.7.2' 2cfa6a85c6d3bcfde3863f3e7417d0099782e198 13 | # + git tag 14 | # v1.7.0 15 | # v1.7.1 16 | # + git push origin v1.7.2 17 | # Password for 'https://cfpython@bitbucket.org': 18 | # Counting objects: 1, done. 19 | # Writing objects: 100% (1/1), 164 bytes | 0 bytes/s, done. 20 | # Total 1 (delta 0), reused 0 (delta 0) 21 | # To https://cfpython@bitbucket.org/cfpython/cf-python.git 22 | # * [new tag] v1.7.2 -> v1.7.2 23 | # + set +x 24 | # -------------------------------------------------------------------- 25 | 26 | if [[ ! $1 ]] ; then 27 | echo "No version \$1 (e.g. 1.7.0)" 28 | exit 1 29 | fi 30 | 31 | version=$1 32 | major_version=$(echo $version | cut -c 1) 33 | 34 | current_branch=`git rev-parse --abbrev-ref HEAD` 35 | 36 | echo "New tag: v$version" 37 | echo 38 | 39 | echo "Existing Tags:" 40 | git tag 41 | echo 42 | 43 | x=`git tag | grep "^v$version$"` 44 | if [[ $? -eq 0 ]] ; then 45 | echo "ERROR: Tag v$version already exists" 46 | exit 1 47 | fi 48 | 49 | set -x 50 | 51 | # Find checksum of latest commit 52 | latest_checksum=`git log --pretty=format:'%H' -n 1` 53 | 54 | # Create tag in local repository 55 | git tag -a v$version -m "version $version" $latest_checksum 56 | 57 | # Look at at all my tags 58 | git tag 59 | 60 | # Push tag to remote repository 61 | git push origin v$version 62 | 63 | set +x 64 | -------------------------------------------------------------------------------- /cfdm/test/test_LinearSubarray.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class LinearSubarrayTest(unittest.TestCase): 11 | """Unit test for the LinearSubarrayArray class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or 18 | # calls (those without a 'verbose' option to do the same) 19 | # e.g. to debug them, wrap them (for methods, start-to-end 20 | # internally) as follows: 21 | # cfdm.log_level('DEBUG') 22 | # < ... test code ... > 23 | # cfdm.log_level('DISABLE') 24 | 25 | def test_LinearSubarray_compressed_dimensions(self): 26 | """Test `LinearSubarray.compressed_dimensions`.""" 27 | cd = {1: (1,)} 28 | x = cfdm.LinearSubarray(compressed_dimensions=cd) 29 | self.assertEqual(x.compressed_dimensions(), cd) 30 | 31 | x = cfdm.LinearSubarray() 32 | with self.assertRaises(ValueError): 33 | x.compressed_dimensions() 34 | 35 | def test_LinearSubarray_get_filename(self): 36 | """Test LinearSubarray.get_filename.""" 37 | x = cfdm.LinearSubarray( 38 | data=123, parameters={}, dependent_tie_points={} 39 | ) 40 | with self.assertRaises(AttributeError): 41 | x.get_filename() 42 | 43 | 44 | if __name__ == "__main__": 45 | print("Run date:", datetime.datetime.now()) 46 | cfdm.environment() 47 | print("") 48 | unittest.main(verbosity=2) 49 | -------------------------------------------------------------------------------- /cfdm/test/test_RaggedIndexedArray.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class RaggedIndexedArrayTest(unittest.TestCase): 11 | """Unit test for the RaggedIndexedArray class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or calls (those 18 | # without a 'verbose' option to do the same) e.g. to debug them, wrap 19 | # them (for methods, start-to-end internally) as follows: 20 | # cfdm.log_level('DEBUG') 21 | # < ... test code ... > 22 | # cfdm.log_level('DISABLE') 23 | 24 | compressed_data = cfdm.Data([280.0, 281.0, 279.0, 278.0, 279.5]) 25 | index = cfdm.Index(data=[0, 1, 1, 1]) 26 | self.r = cfdm.RaggedIndexedArray( 27 | compressed_data, shape=(2, 3), size=6, ndim=2, index_variable=index 28 | ) 29 | 30 | def test_RaggedIndexedArray_to_memory(self): 31 | """Test `RaggedIndexedArray.to_memory`""" 32 | self.assertIsInstance(self.r.to_memory(), cfdm.RaggedIndexedArray) 33 | 34 | def test_RaggedIndexedArray_get_index(self): 35 | """Test `RaggedIndexedArray.get_index`""" 36 | r = self.r.copy() 37 | self.assertIsInstance(r.get_index(), cfdm.Index) 38 | r._del_component("index_variable") 39 | self.assertIsNone(r.get_index(None)) 40 | 41 | 42 | if __name__ == "__main__": 43 | print("Run date:", datetime.datetime.now()) 44 | cfdm.environment() 45 | print("") 46 | unittest.main(verbosity=2) 47 | -------------------------------------------------------------------------------- /cfdm/test/test_RaggedContiguousArray.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class RaggedContiguousArrayTest(unittest.TestCase): 11 | """Unit test for the RaggedContiguousArray class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or calls (those 18 | # without a 'verbose' option to do the same) e.g. to debug them, wrap 19 | # them (for methods, start-to-end internally) as follows: 20 | # cfdm.log_level('DEBUG') 21 | # < ... test code ... > 22 | # cfdm.log_level('DISABLE') 23 | 24 | compressed_data = cfdm.Data([280.0, 281.0, 279.0, 278.0, 279.5]) 25 | count = cfdm.Count(data=[1, 3]) 26 | self.r = cfdm.RaggedContiguousArray( 27 | compressed_data, shape=(2, 3), size=6, ndim=2, count_variable=count 28 | ) 29 | 30 | def test_RaggedContiguousArray_to_memory(self): 31 | """Test `RaggedContiguousArray.to_memory`""" 32 | self.assertIsInstance(self.r.to_memory(), cfdm.RaggedContiguousArray) 33 | 34 | def test_RaggedContiguousArray_get_count(self): 35 | """Test `RaggedContiguousArray.get_count`""" 36 | r = self.r.copy() 37 | self.assertIsInstance(r.get_count(), cfdm.Count) 38 | r._del_component("count_variable") 39 | self.assertIsNone(r.get_count(None)) 40 | 41 | 42 | if __name__ == "__main__": 43 | print("Run date:", datetime.datetime.now()) 44 | cfdm.environment() 45 | print("") 46 | unittest.main(verbosity=2) 47 | -------------------------------------------------------------------------------- /cfdm/partnodecountproperties.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class PartNodeCountProperties( 5 | mixin.NetCDFVariable, 6 | mixin.NetCDFDimension, 7 | mixin.Properties, 8 | mixin.Files, 9 | core.abstract.Properties, 10 | ): 11 | """Properties for a netCDF part node count variable. 12 | 13 | **NetCDF interface** 14 | 15 | {{netCDF variable}} 16 | 17 | The name of the netCDF dimension spanned by the netCDF part node 18 | count variable's data may be accessed with the `nc_set_dimension`, 19 | `nc_get_dimension`, `nc_del_dimension` and `nc_has_dimension` 20 | methods. 21 | 22 | .. versionadded:: (cfdm) 1.8.0 23 | 24 | """ 25 | 26 | def dump( 27 | self, 28 | display=True, 29 | _key=None, 30 | _title=None, 31 | _create_title=True, 32 | _prefix="", 33 | _level=0, 34 | _omit_properties=None, 35 | ): 36 | """A full description of the part node count variable. 37 | 38 | Returns a description of all properties. 39 | 40 | .. versionadded:: (cfdm) 1.8.0 41 | 42 | :Parameters: 43 | 44 | display: `bool`, optional 45 | If False then return the description as a string. By 46 | default the description is printed. 47 | 48 | :Returns: 49 | 50 | {{returns dump}} 51 | 52 | """ 53 | if _create_title and _title is None: 54 | _title = "Part Node Count: " + self.identity(default="") 55 | 56 | return super().dump( 57 | display=display, 58 | _key=_key, 59 | _omit_properties=_omit_properties, 60 | _prefix=_prefix, 61 | _level=_level, 62 | _title=_title, 63 | _create_title=_create_title, 64 | ) 65 | -------------------------------------------------------------------------------- /cfdm/data/subarray/raggedsubarray.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from .abstract import Subarray 4 | 5 | 6 | class RaggedSubarray(Subarray): 7 | """A subarray of a compressed ragged array. 8 | 9 | A subarray describes a unique part of the uncompressed array. 10 | 11 | See CF section 9 "Discrete Sampling Geometries". 12 | 13 | .. versionadded:: (cfdm) 1.10.0.0 14 | 15 | """ 16 | 17 | def __getitem__(self, indices): 18 | """Return a subspace of the uncompressed subarray. 19 | 20 | x.__getitem__(indices) <==> x[indices] 21 | 22 | Returns a subspace of the uncompressed subarray as an 23 | independent numpy array. 24 | 25 | .. versionadded:: (cfdm) 1.10.0.0 26 | 27 | """ 28 | d1, u_dims = self.compressed_dimensions().popitem() 29 | uncompressed_shape = self.shape 30 | 31 | data = self._select_data(check_mask=False) 32 | 33 | if data.size: 34 | shape = list(data.shape) 35 | u_indices0 = [slice(None)] * data.ndim 36 | 37 | u_indices0[d1] = slice(0, shape[d1]) 38 | shape[d1] = uncompressed_shape[u_dims[-1]] 39 | 40 | u = np.ma.masked_all(shape, dtype=self.dtype) 41 | 42 | u[tuple(u_indices0)] = data 43 | 44 | u = u.reshape(uncompressed_shape) 45 | else: 46 | # This subarray contains no elements of the compressed 47 | # data 48 | u = np.ma.masked_all(uncompressed_shape, dtype=self.dtype) 49 | 50 | if indices is Ellipsis: 51 | return u 52 | 53 | return u[indices] 54 | 55 | @property 56 | def dtype(self): 57 | """The data-type of the uncompressed data. 58 | 59 | .. versionadded:: (cfdm) 1.10.0.0 60 | 61 | """ 62 | return self.data.dtype 63 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Datum.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Datum 5 | =============== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.Datum 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Parameters 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.Datum.del_parameter 24 | ~cfdm.core.Datum.get_parameter 25 | ~cfdm.core.Datum.has_parameter 26 | ~cfdm.core.Datum.set_parameter 27 | ~cfdm.core.Datum.parameters 28 | ~cfdm.core.Datum.clear_parameters 29 | ~cfdm.core.Datum.set_parameters 30 | 31 | Miscellaneous 32 | ------------- 33 | 34 | .. rubric:: Methods 35 | 36 | .. autosummary:: 37 | :nosignatures: 38 | :toctree: ../method/ 39 | :template: method.rst 40 | 41 | ~cfdm.core.Datum.copy 42 | 43 | Special 44 | ------- 45 | 46 | .. rubric:: Methods 47 | 48 | .. autosummary:: 49 | :nosignatures: 50 | :toctree: ../method/ 51 | :template: method.rst 52 | 53 | ~cfdm.core.Datum.__deepcopy__ 54 | 55 | Docstring substitutions 56 | ----------------------- 57 | 58 | .. rubric:: Methods 59 | 60 | .. autosummary:: 61 | :nosignatures: 62 | :toctree: ../method/ 63 | :template: method.rst 64 | 65 | ~cfdm.core.Datum._docstring_special_substitutions 66 | ~cfdm.core.Datum._docstring_substitutions 67 | ~cfdm.core.Datum._docstring_package_depth 68 | ~cfdm.core.Datum._docstring_method_exclusions 69 | -------------------------------------------------------------------------------- /cfdm/core/fieldancillary.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class FieldAncillary(abstract.PropertiesData): 5 | """A field ancillary construct of the CF data model. 6 | 7 | The field ancillary construct provides metadata which are 8 | distributed over the same sampling domain as the field itself. For 9 | example, if a data variable holds a variable retrieved from a 10 | satellite instrument, a related ancillary data variable might 11 | provide the uncertainty estimates for those retrievals (varying 12 | over the same spatiotemporal domain). 13 | 14 | The field ancillary construct consists of an array of the 15 | ancillary data, which is zero-dimensional or which depends on one 16 | or more of the domain axes, and properties to describe the 17 | data. It is assumed that the data do not depend on axes of the 18 | domain which are not spanned by the array, along which the values 19 | are implicitly propagated. CF-netCDF ancillary data variables 20 | correspond to field ancillary constructs. Note that a field 21 | ancillary construct is constrained by the domain definition of the 22 | parent field construct but does not contribute to the domain's 23 | definition, unlike, for instance, an auxiliary coordinate 24 | construct or domain ancillary construct. 25 | 26 | .. versionadded:: (cfdm) 1.7.0 27 | 28 | """ 29 | 30 | @property 31 | def construct_type(self): 32 | """Return a description of the construct type. 33 | 34 | .. versionadded:: (cfdm) 1.7.0 35 | 36 | :Returns: 37 | 38 | `str` 39 | The construct type. 40 | 41 | **Examples** 42 | 43 | >>> f = {{package}}.{{class}}() 44 | >>> f.construct_type 45 | 'field_ancillary' 46 | 47 | """ 48 | return "field_ancillary" 49 | -------------------------------------------------------------------------------- /cfdm/test/test_InteriorRing.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import os 4 | import unittest 5 | 6 | faulthandler.enable() # to debug seg faults and timeouts 7 | 8 | import cfdm 9 | 10 | 11 | class InteriorRingTest(unittest.TestCase): 12 | """Unit test for the InteriorRing class.""" 13 | 14 | def setUp(self): 15 | """Preparations called immediately before each test method.""" 16 | # Disable log messages to silence expected warnings 17 | cfdm.LOG_LEVEL("DISABLE") 18 | # Note: to enable all messages for given methods, lines or 19 | # calls (those without a 'verbose' option to do the same) 20 | # e.g. to debug them, wrap them (for methods, start-to-end 21 | # internally) as follows: 22 | # cfdm.LOG_LEVEL('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.LOG_LEVEL('DISABLE') 25 | 26 | self.geometry_interior_ring_file = os.path.join( 27 | os.path.dirname(os.path.abspath(__file__)), 28 | "geometry_interior_ring.nc", 29 | ) 30 | self.geometry_interior_ring_file_2 = os.path.join( 31 | os.path.dirname(os.path.abspath(__file__)), 32 | "geometry_interior_ring_2.nc", 33 | ) 34 | 35 | def test_InteriorRing__repr__str__dump(self): 36 | """Test all means of InteriorRing inspection.""" 37 | f = cfdm.read(self.geometry_interior_ring_file)[0] 38 | 39 | coord = f.construct("axis=X") 40 | self.assertTrue(coord.has_interior_ring()) 41 | 42 | i = coord.get_interior_ring() 43 | 44 | _ = repr(i) 45 | _ = str(i) 46 | self.assertIsInstance(i.dump(display=False), str) 47 | 48 | 49 | if __name__ == "__main__": 50 | print("Run date:", datetime.datetime.now()) 51 | cfdm.environment() 52 | print() 53 | unittest.main(verbosity=2) 54 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Container.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Container 5 | =================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.Container 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Miscellaneous 14 | ------------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.Container.copy 24 | 25 | Private 26 | ------- 27 | 28 | .. rubric:: Methods 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.core.Container._del_component 36 | ~cfdm.core.Container._get_component 37 | ~cfdm.core.Container._has_component 38 | ~cfdm.core.Container._set_component 39 | 40 | Special 41 | ------- 42 | 43 | .. rubric:: Methods 44 | 45 | .. autosummary:: 46 | :nosignatures: 47 | :toctree: ../method/ 48 | :template: method.rst 49 | 50 | ~cfdm.core.Container.__deepcopy__ 51 | 52 | Docstring substitutions 53 | ----------------------- 54 | 55 | .. rubric:: Methods 56 | 57 | .. autosummary:: 58 | :nosignatures: 59 | :toctree: ../method/ 60 | :template: method.rst 61 | 62 | ~cfdm.core.Container._docstring_special_substitutions 63 | ~cfdm.core.Container._docstring_substitutions 64 | ~cfdm.core.Container._docstring_package_depth 65 | ~cfdm.core.Container._docstring_method_exclusions 66 | -------------------------------------------------------------------------------- /cfdm/test/test_NodeCountProperties.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import os 4 | import unittest 5 | 6 | faulthandler.enable() # to debug seg faults and timeouts 7 | 8 | import cfdm 9 | 10 | 11 | class NodeCountPropertiesTest(unittest.TestCase): 12 | """Unit test for the NodeCountProperties class.""" 13 | 14 | def setUp(self): 15 | """Preparations called immediately before each test method.""" 16 | # Disable log messages to silence expected warnings 17 | cfdm.log_level("DISABLE") 18 | # Note: to enable all messages for given methods, lines or 19 | # calls (those without a 'verbose' option to do the same) 20 | # e.g. to debug them, wrap them (for methods, start-to-end 21 | # internally) as follows: 22 | # cfdm.log_level('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | self.geometry_interior_ring_file = os.path.join( 27 | os.path.dirname(os.path.abspath(__file__)), 28 | "geometry_interior_ring.nc", 29 | ) 30 | self.geometry_interior_ring_file_2 = os.path.join( 31 | os.path.dirname(os.path.abspath(__file__)), 32 | "geometry_interior_ring_2.nc", 33 | ) 34 | 35 | def test_NodeCountProperties__repr__str__dump(self): 36 | """Test all means of NodeCountProperties inspection.""" 37 | f = cfdm.read(self.geometry_interior_ring_file)[0] 38 | 39 | coord = f.construct("axis=X") 40 | self.assertTrue(coord.has_node_count()) 41 | 42 | n = coord.get_node_count() 43 | 44 | _ = repr(n) 45 | _ = str(n) 46 | self.assertIsInstance(n.dump(display=False), str) 47 | 48 | 49 | if __name__ == "__main__": 50 | print("Run date:", datetime.datetime.now()) 51 | cfdm.environment() 52 | print() 53 | unittest.main(verbosity=2) 54 | -------------------------------------------------------------------------------- /cfdm/test/test_CFDMImplementation.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class CFDMImplementationTest(unittest.TestCase): 11 | """Unit test for the CFDMImplementation class.""" 12 | 13 | def setUp(self): 14 | """Preparations called immediately before each test method.""" 15 | # Disable log messages to silence expected warnings 16 | cfdm.log_level("DISABLE") 17 | # Note: to enable all messages for given methods, lines or calls (those 18 | # without a 'verbose' option to do the same) e.g. to debug them, wrap 19 | # them (for methods, start-to-end internally) as follows: 20 | # cfdm.log_level('DEBUG') 21 | # < ... test code ... > 22 | # cfdm.log_level('DISABLE') 23 | self.i = cfdm.implementation() 24 | 25 | def test_CFDMImplementation__init__(self): 26 | """Test the constructor of CFDMImplementation.""" 27 | cfdm.CFDMImplementation({"NewClass1": "qwerty", "NewClass2": None}) 28 | 29 | def test_CFDMImplementation_classes(self): 30 | """Test the classes method of CFDMImplementation.""" 31 | self.assertIsInstance(self.i.classes(), dict) 32 | 33 | def test_CFDMImplementation_set_class(self): 34 | """Test the `set_class` method of CFDMImplementation.""" 35 | self.i.set_class("NewClass", "qwerty") 36 | 37 | def test_CFDMImplementation_get_class(self): 38 | """Test the `get_class` method of CFDMImplementation.""" 39 | self.assertIs(self.i.get_class("Field"), cfdm.Field) 40 | 41 | with self.assertRaises(ValueError): 42 | self.i.get_class("qwerty") 43 | 44 | 45 | if __name__ == "__main__": 46 | print("Run date:", datetime.datetime.now()) 47 | cfdm.environment() 48 | print("") 49 | unittest.main(verbosity=2) 50 | -------------------------------------------------------------------------------- /cfdm/test/test_PartNodeCountProperties.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import os 4 | import unittest 5 | 6 | faulthandler.enable() # to debug seg faults and timeouts 7 | 8 | import cfdm 9 | 10 | 11 | class PartNodeCountPropertiesTest(unittest.TestCase): 12 | """Unit test for the PartNodeCountProperties class.""" 13 | 14 | def setUp(self): 15 | """Preparations called immediately before each test method.""" 16 | # Disable log messages to silence expected warnings 17 | cfdm.log_level("DISABLE") 18 | # Note: to enable all messages for given methods, lines or 19 | # calls (those without a 'verbose' option to do the same) 20 | # e.g. to debug them, wrap them (for methods, start-to-end 21 | # internally) as follows: 22 | # cfdm.log_level('DEBUG') 23 | # < ... test code ... > 24 | # cfdm.log_level('DISABLE') 25 | 26 | self.geometry_interior_ring_file = os.path.join( 27 | os.path.dirname(os.path.abspath(__file__)), 28 | "geometry_interior_ring.nc", 29 | ) 30 | self.geometry_interior_ring_file_2 = os.path.join( 31 | os.path.dirname(os.path.abspath(__file__)), 32 | "geometry_interior_ring_2.nc", 33 | ) 34 | 35 | def test_PartNodeCountProperties__repr__str__dump(self): 36 | """Test all means of PartNodeCountProperties inspection.""" 37 | f = cfdm.read(self.geometry_interior_ring_file)[0] 38 | 39 | coord = f.construct("axis=X") 40 | self.assertTrue(coord.has_part_node_count()) 41 | 42 | p = coord.get_part_node_count() 43 | 44 | _ = repr(p) 45 | _ = str(p) 46 | self.assertIsInstance(p.dump(display=False), str) 47 | 48 | 49 | if __name__ == "__main__": 50 | print("Run date:", datetime.datetime.now()) 51 | cfdm.environment() 52 | print() 53 | unittest.main(verbosity=2) 54 | -------------------------------------------------------------------------------- /cfdm/data/subarray/cellconnectivitysubarray.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from .abstract import MeshSubarray 4 | 5 | 6 | class CellConnectivitySubarray(MeshSubarray): 7 | """A cell connectivity subarray defined by UGRID connectivity. 8 | 9 | A subarray describes a unique part of the uncompressed array. 10 | 11 | A UGRID connectivity variable contains indices which map each cell 12 | to its neighbours, as found in a UGRID "face_face_connectivity" 13 | variable. 14 | 15 | .. versionadded:: (cfdm) 1.11.0.0 16 | 17 | .. seealso:: `CellConnectivityArray` 18 | 19 | """ 20 | 21 | def __getitem__(self, indices): 22 | """Return a subspace of the uncompressed data. 23 | 24 | x.__getitem__(indices) <==> x[indices] 25 | 26 | Returns a subspace of the uncompressed data as an independent 27 | numpy array. 28 | 29 | .. versionadded:: (cfdm) 1.11.0.0 30 | 31 | """ 32 | from cfdm.functions import integer_dtype 33 | 34 | start_index = self.start_index 35 | shape = self.shape 36 | start = 0 37 | stop = shape[0] 38 | if start_index: 39 | start += 1 40 | stop += 1 41 | 42 | data = self._select_data(check_mask=True) 43 | if np.ma.isMA(data): 44 | empty = np.ma.empty 45 | else: 46 | empty = np.empty 47 | 48 | dtype = integer_dtype(stop - 1) 49 | u = empty(shape, dtype=dtype) 50 | 51 | # Store the cell identifiers in the first column 52 | u[:, 0] = np.arange(start, stop, dtype=dtype) 53 | # Store the identifiers of the connected cells in the other 54 | # columns 55 | u[:, 1:] = data 56 | 57 | if indices is not Ellipsis: 58 | u = u[indices] 59 | 60 | # Make sure that the values are zero-based 61 | if start_index: 62 | u -= 1 63 | 64 | return u 65 | -------------------------------------------------------------------------------- /cfdm/data/subarray/quadraticlatitudelongitudesubarray.py: -------------------------------------------------------------------------------- 1 | from .abstract import SubsampledSubarray 2 | from .mixin import QuadraticLatitudeLongitudeInterpolation 3 | 4 | 5 | class QuadraticLatitudeLongitudeSubarray( 6 | QuadraticLatitudeLongitudeInterpolation, SubsampledSubarray 7 | ): 8 | """A subarray of an array compressed by subsamplng. 9 | 10 | A subarray describes a unique part of the uncompressed array. 11 | 12 | The compressed data is reconstituted by quadratic latitude 13 | longitude interpolation. 14 | 15 | See CF appendix J "Coordinate Interpolation Methods". 16 | 17 | .. versionadded:: (cfdm) 1.10.0.0 18 | 19 | """ 20 | 21 | def __getitem__(self, indices): 22 | """Return a subspace of the uncompressed data. 23 | 24 | x.__getitem__(indices) <==> x[indices] 25 | 26 | Returns a subspace of the uncompressed data as an independent 27 | numpy array. 28 | 29 | .. versionadded:: (cfdm) 1.10.0.0 30 | 31 | """ 32 | (d1,) = tuple(self.compressed_dimensions()) 33 | 34 | lat, lon = self._codependent_tie_points("latitude", "longitude") 35 | 36 | lat = self._select_data(lat) 37 | lon = self._select_data(lon) 38 | 39 | u = self._quadratic_latitude_longitude_interpolation( 40 | lat_a=self._select_location(lat, {d1: 0}), 41 | lon_a=self._select_location(lon, {d1: 0}), 42 | lat_b=self._select_location(lat, {d1: 1}), 43 | lon_b=self._select_location(lon, {d1: 1}), 44 | ce=self._select_parameter("ce"), 45 | ca=self._select_parameter("ca"), 46 | location_use_3d_cartesian=self._select_parameter( 47 | "location_use_3d_cartesian" 48 | ), 49 | d1=d1, 50 | ) 51 | u = self._post_process(u) 52 | 53 | if indices is Ellipsis: 54 | return u 55 | 56 | return u[indices] 57 | -------------------------------------------------------------------------------- /cfdm/core/__init__.py: -------------------------------------------------------------------------------- 1 | """`cfdm.core`, the core reference implementation of the CF data model. 2 | 3 | It is a stand-alone core implementation that includes no functionality 4 | beyond that mandated by the CF data model (and therefore excludes any 5 | information about the netCDF encoding of constructs). 6 | 7 | The core implementation provides the basis (via inheritance) for the 8 | `cfdm` package that provides further practical functionality in 9 | addition, for example enabling the reading and writing of netCDF 10 | datasets and the inspection of CF data model constructs. 11 | 12 | """ 13 | 14 | __date__ = "2025-10-15" 15 | __cf_version__ = "1.12" 16 | __version__ = "1.12.3.1" 17 | 18 | # Count the number of docstrings (first element), and the number which 19 | # have docstring substitutions applied to them (second element). 20 | _docstring_substitutions = [0, 0] 21 | 22 | from .constructs import Constructs 23 | from .functions import CF, environment 24 | from .data import Data, Array, NumpyArray 25 | 26 | from .bounds import Bounds 27 | from .coordinateconversion import CoordinateConversion 28 | from .datum import Datum 29 | from .domain import Domain 30 | from .interiorring import InteriorRing 31 | 32 | from .auxiliarycoordinate import AuxiliaryCoordinate 33 | from .cellconnectivity import CellConnectivity 34 | from .cellmeasure import CellMeasure 35 | from .cellmethod import CellMethod 36 | from .coordinatereference import CoordinateReference 37 | from .dimensioncoordinate import DimensionCoordinate 38 | from .domainancillary import DomainAncillary 39 | from .domainaxis import DomainAxis 40 | from .domaintopology import DomainTopology 41 | from .field import Field 42 | from .fieldancillary import FieldAncillary 43 | 44 | from .abstract import ( 45 | Container, 46 | Properties, 47 | PropertiesData, 48 | PropertiesDataBounds, 49 | Coordinate, 50 | Parameters, 51 | ParametersDomainAncillaries, 52 | Topology, 53 | ) 54 | 55 | from .meta import DocstringRewriteMeta 56 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.DomainAxis.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.DomainAxis 5 | ==================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.DomainAxis 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../attribute/ 21 | :template: attribute.rst 22 | 23 | ~cfdm.core.DomainAxis.construct_type 24 | 25 | Size 26 | ---- 27 | 28 | .. rubric:: Methods 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.core.DomainAxis.del_size 36 | ~cfdm.core.DomainAxis.get_size 37 | ~cfdm.core.DomainAxis.has_size 38 | ~cfdm.core.DomainAxis.set_size 39 | 40 | Miscellaneous 41 | ------------- 42 | 43 | .. rubric:: Methods 44 | 45 | .. autosummary:: 46 | :nosignatures: 47 | :toctree: ../method/ 48 | :template: method.rst 49 | 50 | ~cfdm.core.DomainAxis.copy 51 | 52 | Special 53 | ------- 54 | 55 | .. rubric:: Methods 56 | 57 | .. autosummary:: 58 | :nosignatures: 59 | :toctree: ../method/ 60 | :template: method.rst 61 | 62 | ~cfdm.core.DomainAxis.__deepcopy__ 63 | 64 | Docstring substitutions 65 | ----------------------- 66 | 67 | .. rubric:: Methods 68 | 69 | .. autosummary:: 70 | :nosignatures: 71 | :toctree: ../method/ 72 | :template: method.rst 73 | 74 | ~cfdm.core.DomainAxis._docstring_special_substitutions 75 | ~cfdm.core.DomainAxis._docstring_substitutions 76 | ~cfdm.core.DomainAxis._docstring_package_depth 77 | ~cfdm.core.DomainAxis._docstring_method_exclusions 78 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Parameters.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Parameters 5 | ==================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.Parameters 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Parameter terms 14 | --------------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.Parameters.del_parameter 24 | ~cfdm.core.Parameters.get_parameter 25 | ~cfdm.core.Parameters.has_parameter 26 | ~cfdm.core.Parameters.set_parameter 27 | ~cfdm.core.Parameters.parameters 28 | ~cfdm.core.Parameters.clear_parameters 29 | ~cfdm.core.Parameters.set_parameters 30 | 31 | Miscellaneous 32 | ------------- 33 | 34 | .. rubric:: Methods 35 | 36 | .. autosummary:: 37 | :nosignatures: 38 | :toctree: ../method/ 39 | :template: method.rst 40 | 41 | ~cfdm.core.Parameters.copy 42 | 43 | Special 44 | ------- 45 | 46 | .. rubric:: Methods 47 | 48 | .. autosummary:: 49 | :nosignatures: 50 | :toctree: ../method/ 51 | :template: method.rst 52 | 53 | ~cfdm.core.Parameters.__deepcopy__ 54 | 55 | Docstring substitutions 56 | ----------------------- 57 | 58 | .. rubric:: Methods 59 | 60 | .. autosummary:: 61 | :nosignatures: 62 | :toctree: ../method/ 63 | :template: method.rst 64 | 65 | ~cfdm.core.Parameters._docstring_special_substitutions 66 | ~cfdm.core.Parameters._docstring_substitutions 67 | ~cfdm.core.Parameters._docstring_package_depth 68 | ~cfdm.core.Parameters._docstring_method_exclusions 69 | -------------------------------------------------------------------------------- /cfdm/list.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class List( 5 | mixin.NetCDFVariable, 6 | mixin.PropertiesData, 7 | mixin.Files, 8 | core.abstract.PropertiesData, 9 | ): 10 | """A list variable required to uncompress a gathered array. 11 | 12 | Compression by gathering combines axes of a multidimensional array 13 | into a new, discrete axis whilst omitting the missing values and 14 | thus reducing the number of values that need to be stored. 15 | 16 | The information needed to uncompress the data is stored in a list 17 | variable that gives the indices of the required points. 18 | 19 | **NetCDF interface** 20 | 21 | {{netCDF variable}} 22 | 23 | {{netCDF dataset chunks}} 24 | 25 | .. versionadded:: (cfdm) 1.7.0 26 | 27 | """ 28 | 29 | def dump( 30 | self, 31 | display=True, 32 | _key=None, 33 | _title=None, 34 | _create_title=True, 35 | _prefix="", 36 | _level=0, 37 | _omit_properties=None, 38 | _axes=None, 39 | _axis_names=None, 40 | ): 41 | """A full description of the list variable. 42 | 43 | Returns a description of all properties, including those of 44 | components, and provides selected values of all data arrays. 45 | 46 | .. versionadded:: (cfdm) 1.7.0 47 | 48 | :Parameters: 49 | 50 | display: `bool`, optional 51 | If False then return the description as a string. By 52 | default the description is printed. 53 | 54 | :Returns: 55 | 56 | {{returns dump}} 57 | 58 | """ 59 | if _create_title and _title is None: 60 | _title = "List: " + self.identity(default="") 61 | 62 | return super().dump( 63 | display=display, 64 | _key=_key, 65 | _omit_properties=_omit_properties, 66 | _prefix=_prefix, 67 | _level=_level, 68 | _title=_title, 69 | _create_title=_create_title, 70 | _axes=_axes, 71 | _axis_names=_axis_names, 72 | ) 73 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Properties.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Properties 5 | ==================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.Properties 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Properties 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.Properties.del_property 24 | ~cfdm.core.Properties.get_property 25 | ~cfdm.core.Properties.has_property 26 | ~cfdm.core.Properties.set_property 27 | ~cfdm.core.Properties.properties 28 | ~cfdm.core.Properties.clear_properties 29 | ~cfdm.core.Properties.del_properties 30 | ~cfdm.core.Properties.set_properties 31 | 32 | Miscellaneous 33 | ------------- 34 | 35 | .. rubric:: Methods 36 | 37 | .. autosummary:: 38 | :nosignatures: 39 | :toctree: ../method/ 40 | :template: method.rst 41 | 42 | ~cfdm.core.Properties.copy 43 | ~cfdm.core.Properties.has_bounds 44 | ~cfdm.core.Properties.has_data 45 | 46 | Special 47 | ------- 48 | 49 | .. rubric:: Methods 50 | 51 | .. autosummary:: 52 | :nosignatures: 53 | :toctree: ../method/ 54 | :template: method.rst 55 | 56 | ~cfdm.core.Properties.__deepcopy__ 57 | 58 | Docstring substitutions 59 | ----------------------- 60 | 61 | .. rubric:: Methods 62 | 63 | .. autosummary:: 64 | :nosignatures: 65 | :toctree: ../method/ 66 | :template: method.rst 67 | 68 | ~cfdm.core.Properties._docstring_special_substitutions 69 | ~cfdm.core.Properties._docstring_substitutions 70 | ~cfdm.core.Properties._docstring_package_depth 71 | ~cfdm.core.Properties._docstring_method_exclusions 72 | -------------------------------------------------------------------------------- /cfdm/test/test_SparseArray.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | import numpy as np 6 | from scipy.sparse import coo_array 7 | 8 | faulthandler.enable() # to debug seg faults and timeouts 9 | 10 | import cfdm 11 | 12 | row = np.array([0, 3, 1, 0]) 13 | col = np.array([0, 3, 1, 2]) 14 | data = np.array([4, 5, 7, 9]) 15 | s = coo_array((data, (row, col)), shape=(4, 4)) 16 | 17 | 18 | class SparseArrayTest(unittest.TestCase): 19 | """Unit test for the SparseArray class.""" 20 | 21 | def setUp(self): 22 | """Preparations called immediately before each test method.""" 23 | # Disable log messages to silence expected warnings 24 | cfdm.LOG_LEVEL("DISABLE") 25 | # Note: to enable all messages for given methods, lines or 26 | # calls (those without a 'verbose' option to do the same) 27 | # e.g. to debug them, wrap them (for methods, start-to-end 28 | # internally) as follows: cfdm.LOG_LEVEL('DEBUG') 29 | # 30 | # < ... test code ... > 31 | # cfdm.log_level('DISABLE') 32 | 33 | def test_SparseArray_copy(self): 34 | """Test the copy module copying behaviour of SparseArray.""" 35 | x = cfdm.SparseArray(s) 36 | self.assertTrue((s.toarray() == x.array).all()) 37 | 38 | def test_SparseArray__array__(self): 39 | """Test the numpy array conversion of SparseArray.""" 40 | x = cfdm.SparseArray(s) 41 | self.assertTrue((np.array(x) == x.array).all()) 42 | 43 | def test_SparseArray_get_filename(self): 44 | """Test SparseArray.get_filename.""" 45 | x = cfdm.SparseArray() 46 | with self.assertRaises(AttributeError): 47 | x.get_filename() 48 | 49 | def test_SparseArray_get_filenames(self): 50 | """Test SparseArray.get_filenames.""" 51 | x = cfdm.SparseArray() 52 | with self.assertRaises(AttributeError): 53 | x.get_filenames() 54 | 55 | 56 | if __name__ == "__main__": 57 | print("Run date:", datetime.datetime.now()) 58 | cfdm.environment() 59 | print("") 60 | unittest.main(verbosity=2) 61 | -------------------------------------------------------------------------------- /docs/source/extract_tutorial_code.py: -------------------------------------------------------------------------------- 1 | """Extract tutorial Python code into an executable Python script.""" 2 | 3 | import re 4 | import sys 5 | 6 | if len(sys.argv) >= 2: 7 | tutorials_rst = sys.argv[1:] 8 | else: 9 | raise ValueError( 10 | "Must provide at least one .rst file contaiing code examples" 11 | ) 12 | 13 | for tutorial_rst in tutorials_rst: 14 | tutorial = [] 15 | code_block = False 16 | caption = False 17 | 18 | with open(tutorial_rst, mode="r") as f: 19 | for line in f.readlines(): 20 | line = line.strip() 21 | 22 | code = re.split("^\s*>>>\s", line) 23 | 24 | if len(code) == 2: 25 | if re.findall("# Raises Exception\s*$", line): 26 | code[1] = "try:\n " + code[1] + "\nexcept:\n pass" 27 | else: 28 | code = re.split("^\s*\.\.\.\s", line) 29 | 30 | if len(code) == 2: 31 | tutorial.append(code[1]) 32 | continue 33 | 34 | if re.match("\s*\.\. Code Block Start", line): 35 | code_block = True 36 | tutorial.append("# Start of code block") 37 | continue 38 | 39 | if code_block: 40 | if re.match("\s*\.\. code-block::", line): 41 | continue 42 | 43 | if not caption and re.match("\s*:caption:", line): 44 | caption = True 45 | continue 46 | 47 | if caption: 48 | # Blank line marks end of caption 49 | if re.match("\s*$", line): 50 | caption = False 51 | 52 | continue 53 | 54 | if re.match("\.\. Code Block End", line): 55 | code_block = False 56 | tutorial.append("# End of code block") 57 | continue 58 | 59 | tutorial.append(line.replace(" ", "", 1)) 60 | 61 | tutorial.append("") 62 | 63 | tutorial_py = tutorial_rst.replace(".rst", ".py") 64 | 65 | with open(tutorial_py, "w") as f: 66 | f.write("\n".join(tutorial)) 67 | -------------------------------------------------------------------------------- /cfdm/test/run_tests_and_coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # -------------------------------------------------------------------------- 4 | # Run the full test suite and produce a coverage report: 5 | # 6 | # $ run_test_and_coverage 7 | # 8 | # Or to omit the generation of an html report: 9 | # 10 | # $ run_test_and_coverage --nohtml 11 | # 12 | # An XML report is required by Codecov (a code coverage service providing 13 | # detailed reports with visualisations in-browser) so is created unless set: 14 | # 15 | # $ run_test_and_coverage --noxml 16 | # 17 | # where running with both the --nohtml and --noxml arguments will omit both 18 | # reports, just printing a concise result table to STDOUT. 19 | # -------------------------------------------------------------------------- 20 | 21 | #set -x 22 | 23 | 24 | library=cfdm 25 | 26 | # Parse arguments. Note that XML output is required for codecov: 27 | generate_xml="true" 28 | generate_html="true" 29 | for arg in "$@" 30 | do 31 | if [[ $arg == "--noxml" ]] 32 | then 33 | generate_xml="false" 34 | fi 35 | if [[ $arg == "--nohtml" ]] 36 | then 37 | generate_html="false" 38 | fi 39 | done 40 | 41 | if ! command -v coverage &> /dev/null 42 | then 43 | echo \ 44 | "Requires the coverage module: install it e.g. via \ 45 | 'pip install coverage'" 46 | exit 3 47 | fi 48 | 49 | coverage erase 50 | coverage run --source=.. --omit="*/test/*" run_tests.py 51 | # Capture exit status from unit tests 52 | rc=$? 53 | 54 | coverage report 55 | 56 | cov_dir=${library}_coverage_reports 57 | mkdir -p $cov_dir 58 | echo "coverage docs: https://coverage.readthedocs.io" 59 | if [[ $generate_html == "true" ]] ; then 60 | html_dir=$cov_dir/html 61 | mkdir -p $html_dir 62 | coverage html --title "$library test suite coverage report" -d $html_dir 63 | 64 | echo "coverage HTML report URL: file://$PWD/$html_dir/index.html" 65 | fi 66 | if [[ $generate_xml == "true" ]] ; then 67 | coverage xml 68 | mv "coverage.xml" $cov_dir/"coverage.xml" 69 | 70 | echo "coverage XML report URL: file://$PWD/$cov_dir/coverage.xml" 71 | fi 72 | 73 | # Return exit status from unit tests 74 | exit $rc 75 | 76 | #set +x 77 | -------------------------------------------------------------------------------- /cfdm/core/auxiliarycoordinate.py: -------------------------------------------------------------------------------- 1 | from . import abstract 2 | 3 | 4 | class AuxiliaryCoordinate(abstract.Coordinate): 5 | """An auxiliary coordinate construct of the CF data model. 6 | 7 | An auxiliary coordinate construct provides information which 8 | locate the cells of the domain and which depend on a subset of the 9 | domain axis constructs. Auxiliary coordinate constructs have to be 10 | used, instead of dimension coordinate constructs, when a single 11 | domain axis requires more then one set of coordinate values, when 12 | coordinate values are not numeric, strictly monotonic, or contain 13 | missing values, or when they vary along more than one domain axis 14 | construct simultaneously. CF-netCDF auxiliary coordinate variables 15 | and non-numeric scalar coordinate variables correspond to 16 | auxiliary coordinate constructs. 17 | 18 | The auxiliary coordinate construct consists of a data array of the 19 | coordinate values which spans a subset of the domain axis 20 | constructs, an optional array of cell bounds recording the extents 21 | of each cell (stored in a `Bounds` object), and properties to 22 | describe the coordinates. An array of cell bounds spans the same 23 | domain axes as its coordinate array, with the addition of an extra 24 | dimension whose size is that of the number of vertices of each 25 | cell. This extra dimension does not correspond to a domain axis 26 | construct since it does not relate to an independent axis of the 27 | domain. Note that, for climatological time axes, the bounds are 28 | interpreted in a special way indicated by the cell method 29 | constructs. 30 | 31 | .. versionadded:: (cfdm) 1.7.0 32 | 33 | """ 34 | 35 | @property 36 | def construct_type(self): 37 | """Return a description of the construct type. 38 | 39 | .. versionadded:: (cfdm) 1.7.0 40 | 41 | :Returns: 42 | 43 | `str` 44 | The construct type. 45 | 46 | **Examples** 47 | 48 | >>> c = {{package}}.{{class}}() 49 | >>> c.construct_type 50 | 'auxiliary_coordinate' 51 | 52 | """ 53 | return "auxiliary_coordinate" 54 | -------------------------------------------------------------------------------- /cfdm/data/subarray/pointtopologyfromfacessubarray.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from .abstract import MeshSubarray 4 | from .mixin import PointTopology 5 | 6 | 7 | class PointTopologyFromFacesSubarray(PointTopology, MeshSubarray): 8 | """A subarray of a point topology array compressed by UGRID faces. 9 | 10 | A subarray describes a unique part of the uncompressed array. 11 | 12 | .. versionadded:: (cfdm) 1.11.0.0 13 | 14 | """ 15 | 16 | def _connected_nodes(self, node, node_connectivity, masked): 17 | """Return nodes that are joined to *node* by face edges. 18 | 19 | The input *node* is included at the start of the returned 20 | list. 21 | 22 | .. versionadded:: (cfdm) 1.11.0.0 23 | 24 | :Parameters: 25 | 26 | node: `int` 27 | A node identifier. 28 | 29 | node_connectivity: `numpy.ndarray` 30 | A UGRID "face_node_connectivity" array. 31 | 32 | masked: `bool` 33 | Whether or not *node_connectivity* has masked 34 | elements. 35 | 36 | :Returns: 37 | 38 | `list` 39 | All nodes that are joined to *node*, including *node* 40 | itself at the start. 41 | 42 | """ 43 | if masked: 44 | where = np.ma.where 45 | else: 46 | where = np.where 47 | 48 | # Find the faces that contain this node: 49 | faces = where(node_connectivity == node)[0] 50 | 51 | nodes = [] 52 | nodes_extend = nodes.extend 53 | 54 | # For each face, find which two of its nodes are neighbours to 55 | # 'node'. 56 | for face_nodes in node_connectivity[faces]: 57 | if masked: 58 | face_nodes = face_nodes.compressed() 59 | 60 | face_nodes = face_nodes.tolist() 61 | face_nodes.append(face_nodes[0]) 62 | nodes_extend( 63 | [ 64 | m 65 | for m, n in zip(face_nodes[:-1], face_nodes[1:]) 66 | if n == node 67 | ] 68 | ) 69 | 70 | nodes = list(set(nodes)) 71 | 72 | # Insert 'node' at the front of the list 73 | nodes.insert(0, node) 74 | 75 | return nodes 76 | -------------------------------------------------------------------------------- /docs/source/class.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | .. _class_extended: 5 | 6 | **cfdm classes** 7 | ================ 8 | 9 | ---- 10 | 11 | Version |release| for version |version| of the CF conventions. 12 | 13 | 14 | Field construct class 15 | --------------------- 16 | 17 | .. autosummary:: 18 | :nosignatures: 19 | :toctree: class/ 20 | 21 | cfdm.Field 22 | 23 | Domain construct class 24 | ---------------------- 25 | 26 | .. autosummary:: 27 | :nosignatures: 28 | :toctree: class/ 29 | 30 | cfdm.Domain 31 | 32 | Metadata construct classes 33 | -------------------------- 34 | 35 | .. autosummary:: 36 | :nosignatures: 37 | :toctree: class/ 38 | 39 | cfdm.AuxiliaryCoordinate 40 | cfdm.CellConnectivity 41 | cfdm.CellMeasure 42 | cfdm.CellMethod 43 | cfdm.CoordinateReference 44 | cfdm.DimensionCoordinate 45 | cfdm.DomainAncillary 46 | cfdm.DomainAxis 47 | cfdm.DomainTopology 48 | cfdm.FieldAncillary 49 | 50 | Constructs class 51 | ---------------- 52 | 53 | .. autosummary:: 54 | :nosignatures: 55 | :toctree: class/ 56 | 57 | cfdm.Constructs 58 | 59 | Coordinate component classes 60 | ---------------------------- 61 | 62 | .. autosummary:: 63 | :nosignatures: 64 | :toctree: class/ 65 | 66 | cfdm.Bounds 67 | cfdm.CoordinateConversion 68 | cfdm.Datum 69 | cfdm.InteriorRing 70 | 71 | Data classes 72 | ------------ 73 | 74 | .. autosummary:: 75 | :nosignatures: 76 | :toctree: class/ 77 | 78 | cfdm.Data 79 | cfdm.NetCDF4Array 80 | cfdm.H5netcdfArray 81 | cfdm.ZarrArray 82 | cfdm.Array 83 | 84 | Data compression classes 85 | ------------------------ 86 | 87 | Classes that support the creation and storage of compressed arrays. 88 | 89 | .. autosummary:: 90 | :nosignatures: 91 | :toctree: class/ 92 | 93 | cfdm.Count 94 | cfdm.Index 95 | cfdm.List 96 | cfdm.GatheredArray 97 | cfdm.RaggedContiguousArray 98 | cfdm.RaggedIndexedArray 99 | cfdm.RaggedIndexedContiguousArray 100 | cfdm.CompressedArray 101 | cfdm.Quantization 102 | 103 | Miscellaneous classes 104 | --------------------- 105 | 106 | .. autosummary:: 107 | :nosignatures: 108 | :toctree: class/ 109 | 110 | cfdm.Constant 111 | cfdm.Configuration 112 | 113 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.CellMethod.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.CellMethod 5 | ==================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.CellMethod 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../attribute/ 21 | :template: attribute.rst 22 | 23 | ~cfdm.core.CellMethod.construct_type 24 | 25 | Properties 26 | ---------- 27 | 28 | .. rubric:: Methods 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.core.CellMethod.del_axes 36 | ~cfdm.core.CellMethod.get_axes 37 | ~cfdm.core.CellMethod.has_axes 38 | ~cfdm.core.CellMethod.set_axes 39 | ~cfdm.core.CellMethod.del_method 40 | ~cfdm.core.CellMethod.get_method 41 | ~cfdm.core.CellMethod.has_method 42 | ~cfdm.core.CellMethod.set_method 43 | ~cfdm.core.CellMethod.del_qualifier 44 | ~cfdm.core.CellMethod.get_qualifier 45 | ~cfdm.core.CellMethod.has_qualifier 46 | ~cfdm.core.CellMethod.set_qualifier 47 | ~cfdm.core.CellMethod.qualifiers 48 | 49 | Miscellaneous 50 | ------------- 51 | 52 | .. rubric:: Methods 53 | 54 | .. autosummary:: 55 | :nosignatures: 56 | :toctree: ../method/ 57 | :template: method.rst 58 | 59 | ~cfdm.core.CellMethod.copy 60 | 61 | Special 62 | ------- 63 | 64 | .. rubric:: Methods 65 | 66 | .. autosummary:: 67 | :nosignatures: 68 | :toctree: ../method/ 69 | :template: method.rst 70 | 71 | ~cfdm.core.CellMethod.__deepcopy__ 72 | 73 | Docstring substitutions 74 | ----------------------- 75 | 76 | .. rubric:: Methods 77 | 78 | .. autosummary:: 79 | :nosignatures: 80 | :toctree: ../method/ 81 | :template: method.rst 82 | 83 | ~cfdm.core.CellMethod._docstring_special_substitutions 84 | ~cfdm.core.CellMethod._docstring_substitutions 85 | ~cfdm.core.CellMethod._docstring_package_depth 86 | ~cfdm.core.CellMethod._docstring_method_exclusions 87 | -------------------------------------------------------------------------------- /docs/source/class_core.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | .. _class_core: 5 | 6 | **cfdm.core classes** 7 | ===================== 8 | 9 | ---- 10 | 11 | Version |release| for version |version| of the CF conventions. 12 | 13 | 14 | Field construct class 15 | --------------------- 16 | 17 | .. autosummary:: 18 | :nosignatures: 19 | :toctree: class/ 20 | 21 | cfdm.core.Field 22 | 23 | Domain construct class 24 | ---------------------- 25 | 26 | .. autosummary:: 27 | :nosignatures: 28 | :toctree: class/ 29 | 30 | cfdm.core.Domain 31 | 32 | Metadata construct classes 33 | -------------------------- 34 | 35 | .. autosummary:: 36 | :nosignatures: 37 | :toctree: class/ 38 | 39 | cfdm.core.AuxiliaryCoordinate 40 | cfdm.core.CellConnectivity 41 | cfdm.core.CellMeasure 42 | cfdm.core.CellMethod 43 | cfdm.core.CoordinateReference 44 | cfdm.core.DimensionCoordinate 45 | cfdm.core.DomainAncillary 46 | cfdm.core.DomainAxis 47 | cfdm.core.DomainTopology 48 | cfdm.core.FieldAncillary 49 | 50 | Constructs class 51 | ---------------- 52 | 53 | .. autosummary:: 54 | :nosignatures: 55 | :toctree: class/ 56 | 57 | cfdm.core.Constructs 58 | 59 | Coordinate component classes 60 | ---------------------------- 61 | 62 | .. autosummary:: 63 | :nosignatures: 64 | :toctree: class/ 65 | 66 | cfdm.core.Bounds 67 | cfdm.core.CoordinateConversion 68 | cfdm.core.Datum 69 | cfdm.core.InteriorRing 70 | 71 | Data classes 72 | ------------ 73 | 74 | .. autosummary:: 75 | :nosignatures: 76 | :toctree: class/ 77 | 78 | cfdm.core.Data 79 | cfdm.core.NumpyArray 80 | cfdm.core.Array 81 | 82 | Abstract base classes 83 | --------------------- 84 | 85 | Abstract base classes that provide the basis for constructs and 86 | construct components. 87 | 88 | .. autosummary:: 89 | :nosignatures: 90 | :toctree: class/ 91 | 92 | cfdm.core.Container 93 | cfdm.core.Properties 94 | cfdm.core.PropertiesData 95 | cfdm.core.PropertiesDataBounds 96 | cfdm.core.Coordinate 97 | cfdm.core.Parameters 98 | cfdm.core.ParametersDomainAncillaries 99 | 100 | Miscellaneous 101 | ------------- 102 | 103 | .. autosummary:: 104 | :nosignatures: 105 | :toctree: class/ 106 | 107 | cfdm.core.DocstringRewriteMeta 108 | 109 | -------------------------------------------------------------------------------- /docs/_templates/about.html: -------------------------------------------------------------------------------- 1 | {# 2 | 'about.html' sidebar template element, as included from the 'Alabaster' 3 | official theme (see 'alabaster/alabaster/about.html' file in the 4 | 'bitprophet/alabaster' repo) but with h1 title changed to be the package 5 | name and release, e.g. 'cfdm 1.8.0', rather than the conf.py 'project' key. 6 | #} 7 | 8 | 9 | {% if theme_logo %} 10 |

    cfdm {{ release }}

    15 | {% endif %} 16 | 17 |

    18 | {% else %} 19 |

    cfdm {{ release }}

    20 | {% endif %} 21 | 22 | {% if theme_description %} 23 |

    {{ theme_description }}

    24 | {% endif %} 25 | 26 | {% if theme_github_user and theme_github_repo %} 27 | {% if theme_github_button|lower == 'true' %} 28 |

    29 | 31 |

    32 | {% endif %} 33 | {% endif %} 34 | 35 | {% if theme_travis_button|lower != 'false' %} 36 | {% if theme_travis_button|lower == 'true' %} 37 | {% set path = theme_github_user + '/' + theme_github_repo %} 38 | {% else %} 39 | {% set path = theme_travis_button %} 40 | {% endif %} 41 |

    42 | 43 | https://secure.travis-ci.org/{{ path }}.svg?branch={{ theme_badge_branch }} 47 | 48 |

    49 | {% endif %} 50 | 51 | {% if theme_codecov_button|lower != 'false' %} 52 | {% if theme_codecov_button|lower == 'true' %} 53 | {% set path = theme_github_user + '/' + theme_github_repo %} 54 | {% else %} 55 | {% set path = theme_codecov_button %} 56 | {% endif %} 57 |

    58 | 59 | https://codecov.io/github/{{ path }}/coverage.svg?branch={{ theme_badge_branch }} 63 | 64 |

    65 | {% endif %} 66 | -------------------------------------------------------------------------------- /cfdm/data/subarray/biquadraticlatitudelongitudesubarray.py: -------------------------------------------------------------------------------- 1 | from .abstract import SubsampledSubarray 2 | from .mixin import BiQuadraticLatitudeLongitudeInterpolation 3 | 4 | 5 | class BiQuadraticLatitudeLongitudeSubarray( 6 | BiQuadraticLatitudeLongitudeInterpolation, SubsampledSubarray 7 | ): 8 | """A subarray of an array compressed by subsamplng. 9 | 10 | A subarray describes a unique part of the uncompressed array. 11 | 12 | The compressed data is reconstituted by bi-quadratic latitude 13 | longitude interpolation. 14 | 15 | See CF appendix J "Coordinate Interpolation Methods". 16 | 17 | .. versionadded:: (cfdm) 1.10.0.0 18 | 19 | """ 20 | 21 | def __getitem__(self, indices): 22 | """Return a subspace of the uncompressed data. 23 | 24 | x.__getitem__(indices) <==> x[indices] 25 | 26 | Returns a subspace of the uncompressed subarray as an 27 | independent numpy array. 28 | 29 | .. versionadded:: (cfdm) 1.10.0.0 30 | 31 | """ 32 | (d2, d1) = sorted(self.compressed_dimensions()) 33 | 34 | lat, lon = self._codependent_tie_points("latitude", "longitude") 35 | 36 | lat = self._select_data(lat) 37 | lon = self._select_data(lon) 38 | 39 | u = self._bi_quadratic_latitude_longitude_interpolation( 40 | lat_a=self._select_location(lat, {d2: 0, d1: 0}), 41 | lon_a=self._select_location(lon, {d2: 0, d1: 0}), 42 | lat_b=self._select_location(lat, {d2: 0, d1: 1}), 43 | lon_b=self._select_location(lon, {d2: 0, d1: 1}), 44 | lat_c=self._select_location(lat, {d2: 1, d1: 0}), 45 | lon_c=self._select_location(lon, {d2: 1, d1: 0}), 46 | lat_d=self._select_location(lat, {d2: 1, d1: 1}), 47 | lon_d=self._select_location(lon, {d2: 1, d1: 1}), 48 | ce1=self._select_parameter("ce1"), 49 | ca1=self._select_parameter("ca1"), 50 | ce2=self._select_parameter("ce2"), 51 | ca2=self._select_parameter("ca2"), 52 | ce3=self._select_parameter("ce3"), 53 | ca3=self._select_parameter("ca3"), 54 | location_use_3d_cartesian=self._select_parameter( 55 | "location_use_3d_cartesian" 56 | ), 57 | d2=d2, 58 | d1=d1, 59 | ) 60 | u = self._post_process(u) 61 | 62 | if indices is Ellipsis: 63 | return u 64 | 65 | return u[indices] 66 | -------------------------------------------------------------------------------- /docs/_static/copybutton.css: -------------------------------------------------------------------------------- 1 | /* Copy buttons */ 2 | button.copybtn { 3 | position: absolute; 4 | display: flex; 5 | top: .3em; 6 | right: .3em; 7 | width: 1.7em; 8 | height: 1.7em; 9 | opacity: 0; 10 | transition: opacity 0.3s, border .3s, background-color .3s; 11 | user-select: none; 12 | padding: 0; 13 | border: none; 14 | outline: none; 15 | border-radius: 0.4em; 16 | /* The colors that GitHub uses */ 17 | border: #1b1f2426 1px solid; 18 | background-color: #f6f8fa; 19 | color: #57606a; 20 | } 21 | 22 | button.copybtn.success { 23 | border-color: #22863a; 24 | color: #22863a; 25 | } 26 | 27 | button.copybtn svg { 28 | stroke: currentColor; 29 | width: 1.5em; 30 | height: 1.5em; 31 | padding: 0.1em; 32 | } 33 | 34 | div.highlight { 35 | position: relative; 36 | } 37 | 38 | /* Show the copybutton */ 39 | .highlight:hover button.copybtn, button.copybtn.success { 40 | opacity: 1; 41 | } 42 | 43 | .highlight button.copybtn:hover { 44 | background-color: rgb(235, 235, 235); 45 | } 46 | 47 | .highlight button.copybtn:active { 48 | background-color: rgb(187, 187, 187); 49 | } 50 | 51 | /** 52 | * A minimal CSS-only tooltip copied from: 53 | * https://codepen.io/mildrenben/pen/rVBrpK 54 | * 55 | * To use, write HTML like the following: 56 | * 57 | *

    Short

    58 | */ 59 | .o-tooltip--left { 60 | position: relative; 61 | } 62 | 63 | .o-tooltip--left:after { 64 | opacity: 0; 65 | visibility: hidden; 66 | position: absolute; 67 | content: attr(data-tooltip); 68 | padding: .2em; 69 | font-size: .8em; 70 | left: -.2em; 71 | background: grey; 72 | color: white; 73 | white-space: nowrap; 74 | z-index: 2; 75 | border-radius: 2px; 76 | transform: translateX(-102%) translateY(0); 77 | transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); 78 | } 79 | 80 | .o-tooltip--left:hover:after { 81 | display: block; 82 | opacity: 1; 83 | visibility: visible; 84 | transform: translateX(-100%) translateY(0); 85 | transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); 86 | transition-delay: .5s; 87 | } 88 | 89 | /* By default the copy button shouldn't show up when printing a page */ 90 | @media print { 91 | button.copybtn { 92 | display: none; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /cfdm/test/test_CellMeasure.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import os 4 | import unittest 5 | 6 | faulthandler.enable() # to debug seg faults and timeouts 7 | 8 | import cfdm 9 | 10 | 11 | class CellMeasureTest(unittest.TestCase): 12 | """Unit test for the CellMeasure class.""" 13 | 14 | def setUp(self): 15 | """Preparations called immediately before each test method.""" 16 | # Disable log messages to silence expected warnings 17 | cfdm.LOG_LEVEL("DISABLE") 18 | # Note: to enable all messages for given methods, lines or 19 | # calls (those without a 'verbose' option to do the same) 20 | # e.g. to debug them, wrap them (for methods, start-to-end 21 | # internally) as follows: 22 | # 23 | # cfdm.LOG_LEVEL('DEBUG') 24 | # < ... test code ... > 25 | # cfdm.log_level('DISABLE') 26 | 27 | self.filename = os.path.join( 28 | os.path.dirname(os.path.abspath(__file__)), "test_file.nc" 29 | ) 30 | f = cfdm.read(self.filename) 31 | self.assertEqual(len(f), 1) 32 | self.f = f[0] 33 | 34 | def test_CellMeasure__init__(self): 35 | """Test the CellMeasure constructor and source keyword.""" 36 | cfdm.CellMeasure(source="qwerty") 37 | 38 | def test_CellMeasure__repr__str__dump_construct_type(self): 39 | """Test all means of CellMeasure inspection.""" 40 | f = self.f 41 | 42 | for cm in f.cell_measures().values(): 43 | _ = repr(cm) 44 | _ = str(cm) 45 | self.assertIsInstance(cm.dump(display=False), str) 46 | self.assertEqual(cm.construct_type, "cell_measure") 47 | 48 | def test_CellMeasure(self): 49 | """Test measure access and (un)setting CellMeasure methods.""" 50 | f = self.f.copy() 51 | 52 | cm = f.construct("measure:area") 53 | 54 | self.assertTrue(cm.has_measure()) 55 | self.assertTrue(cm.get_measure(), "area") 56 | 57 | measure = cm.del_measure() 58 | self.assertFalse(cm.has_measure()) 59 | self.assertIsNone(cm.get_measure(None)) 60 | self.assertIsNone(cm.del_measure(None)) 61 | 62 | cm.set_measure(measure) 63 | self.assertTrue(cm.has_measure()) 64 | self.assertEqual(cm.get_measure(), "area") 65 | 66 | 67 | if __name__ == "__main__": 68 | print("Run date:", datetime.datetime.now()) 69 | cfdm.environment() 70 | print("") 71 | unittest.main(verbosity=2) 72 | -------------------------------------------------------------------------------- /cfdm/data/sparsearray.py: -------------------------------------------------------------------------------- 1 | from .abstract import Array 2 | 3 | 4 | class SparseArray(Array): 5 | """An underlying sparse array. 6 | 7 | The sparse array is assumed to have the same API as `scipy` sparse 8 | arrays. 9 | 10 | .. versionadded:: (cfdm) 1.11.0.0 11 | 12 | """ 13 | 14 | def __init__(self, array=None, source=None, copy=True): 15 | """**Initialisation** 16 | 17 | :Parameters: 18 | 19 | array: `numpy.ndarray` 20 | The numpy array. 21 | 22 | {{init source: optional}} 23 | 24 | {{init copy: `bool`, optional}} 25 | 26 | """ 27 | super().__init__(source=source, copy=copy) 28 | 29 | if source is not None: 30 | try: 31 | array = source._get_component("array", None) 32 | except AttributeError: 33 | array = None 34 | 35 | self._set_component("array", array, copy=False) 36 | if array is not None: 37 | self._set_component("dtype", array.dtype, copy=False) 38 | self._set_component("shape", array.shape, copy=False) 39 | 40 | @property 41 | def array(self): 42 | """Return an independent numpy array containing the data. 43 | 44 | .. versionadded:: (cfdm) 1.11.0.0 45 | 46 | .. seealso:: `sparse_array` 47 | 48 | :Returns: 49 | 50 | `numpy.ndarray` 51 | An independent numpy array of the data. 52 | 53 | **Examples** 54 | 55 | >>> isinstance(a.array, numpy.ndarray) 56 | True 57 | 58 | """ 59 | return self._get_component("array").toarray() 60 | 61 | @property 62 | def sparse_array(self): 63 | """Return an independent `scipy` sparse array of the data. 64 | 65 | .. versionadded:: (cfdm) 1.11.0.0 66 | 67 | .. seealso:: `array` 68 | 69 | :Returns: 70 | 71 | An independent `scipy` sparse array of the data. 72 | 73 | **Examples** 74 | 75 | >>> from scipy.sparse import issparse 76 | >>> issparse(a.sparse_array) 77 | True 78 | 79 | """ 80 | return self._get_component("array").copy() 81 | 82 | def to_memory(self): 83 | """Bring data on disk into memory. 84 | 85 | .. versionadded:: (cfdm) 1.11.0.0 86 | 87 | :Returns: 88 | 89 | Returns the contained sparse array, which is already 90 | in memory. 91 | 92 | """ 93 | return self 94 | -------------------------------------------------------------------------------- /cfdm/interpolationparameter.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class InterpolationParameter( 5 | mixin.NetCDFVariable, 6 | mixin.PropertiesData, 7 | mixin.Files, 8 | core.abstract.PropertiesData, 9 | ): 10 | """An interpolation parameter variable. 11 | 12 | Space may be saved by storing a subsample of the coordinates. The 13 | uncompressed coordinates can be reconstituted by interpolation 14 | from the subsampled coordinate values, also called either "tie 15 | points" or "bounds tie points". 16 | 17 | An interpolation parameter variable provides values for 18 | coefficient terms in the interpolation equation, or for any other 19 | terms that configure the interpolation process. 20 | 21 | **NetCDF interface** 22 | 23 | {{netCDF variable}} 24 | 25 | {{netCDF HDF5 chunks}} 26 | 27 | The netCDF subsampled dimension name and the netCDF interpolation 28 | subarea dimension name, if required, are set on the on the 29 | corresponding tie point index variable. 30 | 31 | .. versionadded:: (cfdm) 1.10.0.0 32 | 33 | .. seealso:: `TiePointIndex` 34 | 35 | """ 36 | 37 | def dump( 38 | self, 39 | display=True, 40 | _key=None, 41 | _title=None, 42 | _create_title=True, 43 | _prefix="", 44 | _level=0, 45 | _omit_properties=None, 46 | _axes=None, 47 | _axis_names=None, 48 | ): 49 | """A full description of the interpolation parameter variable. 50 | 51 | Returns a description of all properties, including those of 52 | components, and provides selected values of all data arrays. 53 | 54 | .. versionadded:: (cfdm) 1.10.0.0 55 | 56 | :Parameters: 57 | 58 | display: `bool`, optional 59 | If False then return the description as a string. By 60 | default the description is printed. 61 | 62 | :Returns: 63 | 64 | {{returns dump}} 65 | 66 | """ 67 | if _create_title and _title is None: 68 | _title = "Interpolation parameter: " + self.identity(default="") 69 | 70 | return super().dump( 71 | display=display, 72 | _key=_key, 73 | _omit_properties=_omit_properties, 74 | _prefix=_prefix, 75 | _level=_level, 76 | _title=_title, 77 | _create_title=_create_title, 78 | _axes=_axes, 79 | _axis_names=_axis_names, 80 | ) 81 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Bounds.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Bounds 5 | ================ 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.Bounds 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Properties 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.Bounds.del_property 24 | ~cfdm.core.Bounds.get_property 25 | ~cfdm.core.Bounds.has_property 26 | ~cfdm.core.Bounds.set_property 27 | ~cfdm.core.Bounds.properties 28 | ~cfdm.core.Bounds.clear_properties 29 | ~cfdm.core.Bounds.del_properties 30 | ~cfdm.core.Bounds.set_properties 31 | 32 | Data 33 | ---- 34 | 35 | .. rubric:: Methods 36 | 37 | .. autosummary:: 38 | :nosignatures: 39 | :toctree: ../method/ 40 | :template: method.rst 41 | 42 | ~cfdm.core.Bounds.del_data 43 | ~cfdm.core.Bounds.get_data 44 | ~cfdm.core.Bounds.has_data 45 | ~cfdm.core.Bounds.set_data 46 | 47 | .. rubric:: Attributes 48 | 49 | .. autosummary:: 50 | :nosignatures: 51 | :toctree: ../attribute/ 52 | :template: attribute.rst 53 | 54 | ~cfdm.core.Bounds.data 55 | ~cfdm.core.Bounds.dtype 56 | ~cfdm.core.Bounds.ndim 57 | ~cfdm.core.Bounds.shape 58 | ~cfdm.core.Bounds.size 59 | 60 | Miscellaneous 61 | ------------- 62 | 63 | .. rubric:: Methods 64 | 65 | .. autosummary:: 66 | :nosignatures: 67 | :toctree: ../method/ 68 | :template: method.rst 69 | 70 | ~cfdm.core.Bounds.copy 71 | ~cfdm.core.Bounds.has_bounds 72 | 73 | Special 74 | ------- 75 | 76 | .. rubric:: Methods 77 | 78 | .. autosummary:: 79 | :nosignatures: 80 | :toctree: ../method/ 81 | :template: method.rst 82 | 83 | ~cfdm.core.Bounds.__deepcopy__ 84 | 85 | Docstring substitutions 86 | ----------------------- 87 | 88 | .. rubric:: Methods 89 | 90 | .. autosummary:: 91 | :nosignatures: 92 | :toctree: ../method/ 93 | :template: method.rst 94 | 95 | ~cfdm.core.Bounds._special_substitutions 96 | ~cfdm.core.Bounds._substitutions 97 | ~cfdm.core.Bounds._package_depth 98 | ~cfdm.core.Bounds._method_exclusions 99 | -------------------------------------------------------------------------------- /cfdm/test/test_RaggedIndexedContiguousArray.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import faulthandler 3 | import unittest 4 | 5 | faulthandler.enable() # to debug seg faults and timeouts 6 | 7 | import cfdm 8 | 9 | 10 | class RaggedIndexedContiguousArrayTest(unittest.TestCase): 11 | """Unit test for the RaggedIndexedContiguousArray class.""" 12 | 13 | r = cfdm.RaggedIndexedContiguousArray( 14 | compressed_array=cfdm.Data( 15 | [ 16 | 280.0, 17 | 281.0, 18 | 279.0, 19 | 278.0, 20 | 279.5, 21 | 281.0, 22 | 282.0, 23 | 278.0, 24 | 279.0, 25 | 277.5, 26 | ] 27 | ), 28 | shape=(2, 2, 3), 29 | index_variable=cfdm.Index(data=[0, 0, 0, 0, 1, 1, 1, 1]), 30 | count_variable=cfdm.Count(data=[1, 3, 2, 2]), 31 | ) 32 | 33 | def setUp(self): 34 | """Preparations called immediately before each test method.""" 35 | # Disable log messages to silence expected warnings 36 | cfdm.log_level("DISABLE") 37 | # Note: to enable all messages for given methods, lines or calls (those 38 | # without a 'verbose' option to do the same) e.g. to debug them, wrap 39 | # them (for methods, start-to-end internally) as follows: 40 | # cfdm.log_level('DEBUG') 41 | # < ... test code ... > 42 | # cfdm.log_level('DISABLE') 43 | 44 | def test_RaggedIndexedContiguousArray_to_memory(self): 45 | """Test `RaggedIndexedContiguousArray.to_memory`""" 46 | self.assertIsInstance( 47 | self.r.to_memory(), cfdm.RaggedIndexedContiguousArray 48 | ) 49 | 50 | def test_RaggedIndexedContiguousArray_get_count(self): 51 | """Test `RaggedIndexedContiguousArray.get_count`""" 52 | r = self.r.copy() 53 | self.assertIsInstance(r.get_count(), cfdm.Count) 54 | r._del_component("count_variable") 55 | self.assertIsNone(r.get_count(None)) 56 | 57 | def test_RaggedIndexedContiguousArray_get_index(self): 58 | """Test `RaggedIndexedContiguousArray.get_index`""" 59 | r = self.r.copy() 60 | self.assertIsInstance(r.get_index(), cfdm.Index) 61 | r._del_component("index_variable") 62 | self.assertIsNone(r.get_index(None)) 63 | 64 | 65 | if __name__ == "__main__": 66 | print("Run date:", datetime.datetime.now()) 67 | cfdm.environment() 68 | print("") 69 | unittest.main(verbosity=2) 70 | -------------------------------------------------------------------------------- /cfdm/core/abstract/topology.py: -------------------------------------------------------------------------------- 1 | from .propertiesdata import PropertiesData 2 | 3 | 4 | class Topology(PropertiesData): 5 | """Abstract base class for topology-related constructs. 6 | 7 | .. versionadded:: (cfdm) 1.11.0.0 8 | 9 | """ 10 | 11 | @property 12 | def ndim(self): 13 | """The number of data dimensions. 14 | 15 | Only the data dimensions that correspond to a domain axis 16 | construct are included. 17 | 18 | .. versionadded:: (cfdm) 1.11.0.0 19 | 20 | .. seealso:: `data`, `has_data`, `shape`, `size` 21 | 22 | **Examples** 23 | 24 | >>> d.shape 25 | (1324,) 26 | >>> d.ndim 27 | 1 28 | >>> f.size 29 | 1324 30 | 31 | """ 32 | try: 33 | return len(self.shape) 34 | except AttributeError: 35 | raise AttributeError( 36 | f"{self.__class__.__name__} object has no attribute 'ndim'" 37 | ) 38 | 39 | @property 40 | def shape(self): 41 | """A tuple of the data array's dimension sizes. 42 | 43 | Only the data dimension that corresponds to a domain axis 44 | construct is included. 45 | 46 | .. versionadded:: (cfdm) 1.11.0.0 47 | 48 | .. seealso:: `data`, `has_data`, `ndim`, `size` 49 | 50 | **Examples** 51 | 52 | >>> d.shape 53 | (1324,) 54 | >>> d.ndim 55 | 1 56 | >>> d.size 57 | 1324 58 | 59 | """ 60 | data = self.get_data(None, _units=False, _fill_value=False) 61 | if data is not None: 62 | return data.shape[:1] 63 | 64 | raise AttributeError( 65 | f"{self.__class__.__name__} object has no attribute 'shape'" 66 | ) 67 | 68 | @property 69 | def size(self): 70 | """The number elements in the data. 71 | 72 | `size` is equal to the product of `shape`, that only includes 73 | the data dimension corresponding to a domain axis construct. 74 | 75 | .. versionadded:: (cfdm) 1.11.0.0 76 | 77 | .. seealso:: `data`, `has_data`, `ndim`, `shape` 78 | 79 | **Examples** 80 | 81 | >>> d.shape 82 | (1324,) 83 | >>> d.ndim 84 | 1 85 | >>> d.size 86 | 1324 87 | 88 | """ 89 | try: 90 | return self.shape[0] 91 | except AttributeError: 92 | raise AttributeError( 93 | f"{self.__class__.__name__} object has no attribute 'size'" 94 | ) 95 | -------------------------------------------------------------------------------- /cfdm/read_write/abstract/readwrite.py: -------------------------------------------------------------------------------- 1 | from collections.abc import Iterable 2 | 3 | from cfdm.cfdmimplementation import implementation 4 | from cfdm.core import DocstringRewriteMeta 5 | from cfdm.docstring import _docstring_substitution_definitions 6 | 7 | 8 | class ReadWrite(metaclass=DocstringRewriteMeta): 9 | """TODOCFA.""" 10 | 11 | implementation = implementation() 12 | 13 | def __docstring_substitutions__(self): 14 | """Defines applicable docstring substitutions. 15 | 16 | Substitutons are considered applicable if they apply to this 17 | class as well as all of its subclasses. 18 | 19 | These are in addtion to, and take precendence over, docstring 20 | substitutions defined by the base classes of this class. 21 | 22 | See `_docstring_substitutions` for details. 23 | 24 | .. versionaddedd:: (cfdm) 1.12.0.0 25 | 26 | :Returns: 27 | 28 | `dict` 29 | The docstring substitutions that have been applied. 30 | 31 | """ 32 | return _docstring_substitution_definitions 33 | 34 | def __docstring_package_depth__(self): 35 | """Returns the package depth for {{package}} substitutions. 36 | 37 | See `_docstring_package_depth` for details. 38 | 39 | .. versionaddedd:: (cfdm) 1.12.0.0 40 | 41 | """ 42 | return 0 43 | 44 | @classmethod 45 | def _flat(cls, x): 46 | """Return an iterator over an arbitrarily nested sequence. 47 | 48 | .. versionadded:: (cfdm) 1.12.0.0 49 | 50 | :Parameters: 51 | 52 | x: scalar or arbitrarily nested sequence 53 | The arbitrarily nested sequence to be flattened. Note 54 | that if *x* is a string or a scalar then this is 55 | equivalent to passing a single element sequence 56 | containing *x*. 57 | 58 | :Returns: 59 | 60 | generator 61 | An iterator over the flattened sequence. 62 | 63 | **Examples** 64 | 65 | >>> list({{package}}.write._flat([1, (2, [3, 4])])) 66 | [1, 2, 3, 4] 67 | 68 | >>> list({{package}}.write._flat(['a', ['bc', ['def', 'ghij']]])) 69 | ['a', 'bc', 'def', 'ghij'] 70 | 71 | >>> list({{package}}.write._flat(2004)) 72 | [2004] 73 | 74 | """ 75 | if not isinstance(x, Iterable) or isinstance(x, str): 76 | x = (x,) 77 | 78 | for a in x: 79 | if not isinstance(a, str) and isinstance(a, Iterable): 80 | for sub in cls._flat(a): 81 | yield sub 82 | else: 83 | yield a 84 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.InteriorRing.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.InteriorRing 5 | ====================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.InteriorRing 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Properties 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.InteriorRing.del_property 24 | ~cfdm.core.InteriorRing.get_property 25 | ~cfdm.core.InteriorRing.has_property 26 | ~cfdm.core.InteriorRing.set_property 27 | ~cfdm.core.InteriorRing.properties 28 | ~cfdm.core.InteriorRing.clear_properties 29 | ~cfdm.core.InteriorRing.del_properties 30 | ~cfdm.core.InteriorRing.set_properties 31 | 32 | Data 33 | ---- 34 | 35 | .. rubric:: Methods 36 | 37 | .. autosummary:: 38 | :nosignatures: 39 | :toctree: ../method/ 40 | :template: method.rst 41 | 42 | ~cfdm.core.InteriorRing.del_data 43 | ~cfdm.core.InteriorRing.get_data 44 | ~cfdm.core.InteriorRing.has_data 45 | ~cfdm.core.InteriorRing.set_data 46 | 47 | .. rubric:: Attributes 48 | 49 | .. autosummary:: 50 | :nosignatures: 51 | :toctree: ../attribute/ 52 | :template: attribute.rst 53 | 54 | ~cfdm.core.InteriorRing.data 55 | ~cfdm.core.InteriorRing.dtype 56 | ~cfdm.core.InteriorRing.ndim 57 | ~cfdm.core.InteriorRing.shape 58 | ~cfdm.core.InteriorRing.size 59 | 60 | Miscellaneous 61 | ------------- 62 | 63 | .. rubric:: Methods 64 | 65 | .. autosummary:: 66 | :nosignatures: 67 | :toctree: ../method/ 68 | :template: method.rst 69 | 70 | ~cfdm.core.InteriorRing.copy 71 | ~cfdm.core.InteriorRing.has_bounds 72 | 73 | Special 74 | ------- 75 | 76 | .. rubric:: Methods 77 | 78 | .. autosummary:: 79 | :nosignatures: 80 | :toctree: ../method/ 81 | :template: method.rst 82 | 83 | ~cfdm.core.InteriorRing.__deepcopy__ 84 | 85 | Docstring substitutions 86 | ----------------------- 87 | 88 | .. rubric:: Methods 89 | 90 | .. autosummary:: 91 | :nosignatures: 92 | :toctree: ../method/ 93 | :template: method.rst 94 | 95 | ~cfdm.core.InteriorRing._docstring_special_substitutions 96 | ~cfdm.core.InteriorRing._docstring_substitutions 97 | ~cfdm.core.InteriorRing._docstring_package_depth 98 | ~cfdm.core.InteriorRing._docstring_method_exclusions 99 | -------------------------------------------------------------------------------- /docs/source/_static/copybutton.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | /* Add a [>>>] button on the top-right corner of code samples to hide 3 | * the >>> and ... prompts and the output and thus make the code 4 | * copyable. */ 5 | var div = $('.highlight-python .highlight,' + 6 | '.highlight-python3 .highlight') 7 | var pre = div.find('pre'); 8 | 9 | // get the styles from the current theme 10 | pre.parent().parent().css('position', 'relative'); 11 | var hide_text = 'Hide the prompts and output'; 12 | var show_text = 'Show the prompts and output'; 13 | var border_width = pre.css('border-top-width'); 14 | var border_style = pre.css('border-top-style'); 15 | var border_color = pre.css('border-top-color'); 16 | var button_styles = { 17 | 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0', 18 | 'border-color': border_color, 'border-style': border_style, 19 | 'border-width': border_width, 'color': border_color, 'text-size': '75%', 20 | 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em' 21 | } 22 | 23 | // create and add the button to all the code blocks that contain >>> 24 | div.each(function(index) { 25 | var jthis = $(this); 26 | if (jthis.find('.gp').length > 0) { 27 | var button = $('>>>'); 28 | button.css(button_styles) 29 | button.attr('title', hide_text); 30 | jthis.prepend(button); 31 | } 32 | // tracebacks (.gt) contain bare text elements that need to be 33 | // wrapped in a span to work with .nextUntil() (see later) 34 | jthis.find('pre:has(.gt)').contents().filter(function() { 35 | return ((this.nodeType == 3) && (this.data.trim().length > 0)); 36 | }).wrap(''); 37 | }); 38 | 39 | // define the behavior of the button when it's clicked 40 | $('.copybutton').toggle( 41 | function() { 42 | var button = $(this); 43 | button.parent().find('.go, .gp, .gt').hide(); 44 | button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden'); 45 | button.css('text-decoration', 'line-through'); 46 | button.attr('title', show_text); 47 | }, 48 | function() { 49 | var button = $(this); 50 | button.parent().find('.go, .gp, .gt').show(); 51 | button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible'); 52 | button.css('text-decoration', 'none'); 53 | button.attr('title', hide_text); 54 | }); 55 | }); 56 | 57 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.Array.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.Array 5 | ========== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.Array 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.Array.get_attributes 24 | 25 | .. rubric:: Attributes 26 | 27 | .. autosummary:: 28 | :nosignatures: 29 | :toctree: ../attribute/ 30 | :template: attribute.rst 31 | 32 | ~cfdm.Array.array 33 | ~cfdm.Array.dtype 34 | ~cfdm.Array.ndim 35 | ~cfdm.Array.shape 36 | ~cfdm.Array.size 37 | 38 | Units 39 | ----- 40 | 41 | .. rubric:: Methods 42 | 43 | .. autosummary:: 44 | :nosignatures: 45 | :toctree: ../method/ 46 | :template: method.rst 47 | 48 | ~cfdm.Array.get_calendar 49 | ~cfdm.Array.get_units 50 | 51 | .. rubric:: Attributes 52 | 53 | .. autosummary:: 54 | :nosignatures: 55 | :toctree: ../attribute/ 56 | :template: attribute.rst 57 | 58 | ~cfdm.Array.Units 59 | 60 | Compression 61 | ----------- 62 | 63 | .. rubric:: Methods 64 | 65 | .. autosummary:: 66 | :nosignatures: 67 | :toctree: ../method/ 68 | :template: method.rst 69 | 70 | ~cfdm.Array.get_compression_type 71 | 72 | Miscellaneous 73 | ------------- 74 | 75 | .. rubric:: Methods 76 | 77 | .. autosummary:: 78 | :nosignatures: 79 | :toctree: ../method/ 80 | :template: method.rst 81 | 82 | ~cfdm.Array.copy 83 | ~cfdm.Array.get_subspace 84 | ~cfdm.Array.astype 85 | 86 | Special 87 | ------- 88 | 89 | .. rubric:: Methods 90 | 91 | .. autosummary:: 92 | :nosignatures: 93 | :toctree: ../method/ 94 | :template: method.rst 95 | 96 | ~cfdm.Array.__array__ 97 | ~cfdm.Array.__deepcopy__ 98 | ~cfdm.Array.__getitem__ 99 | ~cfdm.Array.__repr__ 100 | ~cfdm.Array.__str__ 101 | 102 | Docstring substitutions 103 | ----------------------- 104 | 105 | .. rubric:: Methods 106 | 107 | .. autosummary:: 108 | :nosignatures: 109 | :toctree: ../method/ 110 | :template: method.rst 111 | 112 | ~cfdm.Array._docstring_special_substitutions 113 | ~cfdm.Array._docstring_substitutions 114 | ~cfdm.Array._docstring_package_depth 115 | ~cfdm.Array._docstring_method_exclusions 116 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.CoordinateConversion.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.CoordinateConversion 5 | ============================== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.core.CoordinateConversion 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Parameter terms 14 | --------------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.core.CoordinateConversion.del_parameter 24 | ~cfdm.core.CoordinateConversion.get_parameter 25 | ~cfdm.core.CoordinateConversion.has_parameter 26 | ~cfdm.core.CoordinateConversion.set_parameter 27 | ~cfdm.core.CoordinateConversion.parameters 28 | ~cfdm.core.CoordinateConversion.clear_parameters 29 | ~cfdm.core.CoordinateConversion.set_parameters 30 | 31 | Domain ancillary terms 32 | ---------------------- 33 | 34 | .. rubric:: Methods 35 | 36 | .. autosummary:: 37 | :nosignatures: 38 | :toctree: ../method/ 39 | :template: method.rst 40 | 41 | ~cfdm.core.CoordinateConversion.del_domain_ancillary 42 | ~cfdm.core.CoordinateConversion.get_domain_ancillary 43 | ~cfdm.core.CoordinateConversion.has_domain_ancillary 44 | ~cfdm.core.CoordinateConversion.set_domain_ancillary 45 | ~cfdm.core.CoordinateConversion.domain_ancillaries 46 | ~cfdm.core.CoordinateConversion.clear_domain_ancillaries 47 | ~cfdm.core.CoordinateConversion.set_domain_ancillaries 48 | 49 | Miscellaneous 50 | ------------- 51 | 52 | .. rubric:: Methods 53 | 54 | .. autosummary:: 55 | :nosignatures: 56 | :toctree: ../method/ 57 | :template: method.rst 58 | 59 | ~cfdm.core.CoordinateConversion.copy 60 | 61 | Special 62 | ------- 63 | 64 | .. rubric:: Methods 65 | 66 | .. autosummary:: 67 | :nosignatures: 68 | :toctree: ../method/ 69 | :template: method.rst 70 | 71 | ~cfdm.core.CoordinateConversion.__deepcopy__ 72 | 73 | Docstring substitutions 74 | ----------------------- 75 | 76 | .. rubric:: Methods 77 | 78 | .. autosummary:: 79 | :nosignatures: 80 | :toctree: ../method/ 81 | :template: method.rst 82 | 83 | ~cfdm.core.CoordinateConversion._docstring_special_substitutions 84 | ~cfdm.core.CoordinateConversion._docstring_substitutions 85 | ~cfdm.core.CoordinateConversion._docstring_package_depth 86 | ~cfdm.core.CoordinateConversion._docstring_method_exclusions 87 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.CellMethod.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | .. _cfdm-CellMethod: 5 | 6 | cfdm.CellMethod 7 | =============== 8 | 9 | ---- 10 | 11 | .. autoclass:: cfdm.CellMethod 12 | :no-members: 13 | :no-inherited-members: 14 | 15 | Inspection 16 | ---------- 17 | 18 | .. rubric:: Methods 19 | 20 | .. autosummary:: 21 | :nosignatures: 22 | :toctree: ../method/ 23 | :template: method.rst 24 | 25 | ~cfdm.CellMethod.dump 26 | ~cfdm.CellMethod.identity 27 | ~cfdm.CellMethod.identities 28 | 29 | .. rubric:: Attributes 30 | 31 | .. autosummary:: 32 | :nosignatures: 33 | :toctree: ../attribute/ 34 | :template: attribute.rst 35 | 36 | ~cfdm.CellMethod.construct_type 37 | 38 | Properties 39 | ---------- 40 | 41 | .. rubric:: Methods 42 | 43 | .. autosummary:: 44 | :nosignatures: 45 | :toctree: ../method/ 46 | :template: method.rst 47 | 48 | ~cfdm.CellMethod.del_axes 49 | ~cfdm.CellMethod.get_axes 50 | ~cfdm.CellMethod.has_axes 51 | ~cfdm.CellMethod.set_axes 52 | ~cfdm.CellMethod.del_method 53 | ~cfdm.CellMethod.get_method 54 | ~cfdm.CellMethod.has_method 55 | ~cfdm.CellMethod.set_method 56 | ~cfdm.CellMethod.del_qualifier 57 | ~cfdm.CellMethod.get_qualifier 58 | ~cfdm.CellMethod.has_qualifier 59 | ~cfdm.CellMethod.set_qualifier 60 | ~cfdm.CellMethod.qualifiers 61 | 62 | Miscellaneous 63 | ------------- 64 | 65 | .. rubric:: Methods 66 | 67 | .. autosummary:: 68 | :nosignatures: 69 | :toctree: ../method/ 70 | :template: method.rst 71 | 72 | ~cfdm.CellMethod.copy 73 | ~cfdm.CellMethod.creation_commands 74 | ~cfdm.CellMethod.equals 75 | ~cfdm.CellMethod.sorted 76 | 77 | Special 78 | ------- 79 | 80 | .. rubric:: Methods 81 | 82 | .. autosummary:: 83 | :nosignatures: 84 | :toctree: ../method/ 85 | :template: method.rst 86 | 87 | ~cfdm.CellMethod.__deepcopy__ 88 | ~cfdm.CellMethod.__repr__ 89 | ~cfdm.CellMethod.__str__ 90 | 91 | Docstring substitutions 92 | ----------------------- 93 | 94 | .. rubric:: Methods 95 | 96 | .. autosummary:: 97 | :nosignatures: 98 | :toctree: ../method/ 99 | :template: method.rst 100 | 101 | ~cfdm.CellMethod._docstring_special_substitutions 102 | ~cfdm.CellMethod._docstring_substitutions 103 | ~cfdm.CellMethod._docstring_package_depth 104 | ~cfdm.CellMethod._docstring_method_exclusions 105 | -------------------------------------------------------------------------------- /cfdm/count.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class Count( 5 | mixin.NetCDFVariable, 6 | mixin.NetCDFDimension, 7 | mixin.NetCDFSampleDimension, 8 | mixin.PropertiesData, 9 | mixin.Files, 10 | core.abstract.PropertiesData, 11 | ): 12 | """A count variable required to uncompress a ragged array. 13 | 14 | A collection of features stored using a contiguous ragged array 15 | combines all features along a single dimension (the sample 16 | dimension) such that each feature in the collection occupies a 17 | contiguous block. 18 | 19 | The information needed to uncompress the data is stored in a count 20 | variable that gives the size of each block. 21 | 22 | **NetCDF interface** 23 | 24 | {{netCDF variable}} 25 | 26 | The name of the netCDF dimension spanned by the count variable's 27 | data may be accessed with the `nc_set_dimension`, 28 | `nc_get_dimension`, `nc_del_dimension` and `nc_has_dimension` 29 | methods. 30 | 31 | The name of the netCDF sample dimension spanned by the compressed 32 | data (that is stored in the "sample_dimension" netCDF attribute 33 | and which does not correspond to a domain axis construct) may be 34 | accessed with the `nc_set_sample_dimension`, 35 | `nc_get_sample_dimension`, `nc_del_sample_dimension` and 36 | `nc_has_sample_dimension` methods. 37 | 38 | {{netCDF dataset chunks}} 39 | 40 | .. versionadded:: (cfdm) 1.7.0 41 | 42 | """ 43 | 44 | def dump( 45 | self, 46 | display=True, 47 | _key=None, 48 | _title=None, 49 | _create_title=True, 50 | _prefix="", 51 | _level=0, 52 | _omit_properties=None, 53 | _axes=None, 54 | _axis_names=None, 55 | ): 56 | """A full description of the count variable. 57 | 58 | Returns a description of all properties, including those of 59 | components, and provides selected values of all data arrays. 60 | 61 | .. versionadded:: (cfdm) 1.7.0 62 | 63 | :Parameters: 64 | 65 | display: `bool`, optional 66 | If False then return the description as a string. By 67 | default the description is printed. 68 | 69 | :Returns: 70 | 71 | {{returns dump}} 72 | 73 | """ 74 | if _create_title and _title is None: 75 | _title = "Count: " + self.identity(default="") 76 | 77 | return super().dump( 78 | display=display, 79 | _key=_key, 80 | _omit_properties=_omit_properties, 81 | _prefix=_prefix, 82 | _level=_level, 83 | _title=_title, 84 | _create_title=_create_title, 85 | _axes=_axes, 86 | _axis_names=_axis_names, 87 | ) 88 | -------------------------------------------------------------------------------- /cfdm/domainancillary.py: -------------------------------------------------------------------------------- 1 | from . import core, mixin 2 | 3 | 4 | class DomainAncillary( 5 | mixin.NetCDFVariable, 6 | mixin.PropertiesDataBounds, 7 | mixin.Files, 8 | core.DomainAncillary, 9 | ): 10 | """A domain ancillary construct of the CF data model. 11 | 12 | A domain ancillary construct provides information which is needed 13 | for computing the location of cells in an alternative coordinate 14 | system. It is referenced by a term of a coordinate conversion 15 | formula of a coordinate reference construct. It contains a data 16 | array which depends on zero or more of the domain axes. 17 | 18 | It also contains an optional array of cell bounds, stored in a 19 | `Bounds` object, recording the extents of each cell (only 20 | applicable if the array contains coordinate data), and properties 21 | to describe the data. 22 | 23 | An array of cell bounds spans the same domain axes as the data 24 | array, with the addition of an extra dimension whose size is that 25 | of the number of vertices of each cell. 26 | 27 | **NetCDF interface** 28 | 29 | {{netCDF variable}} 30 | 31 | {{netCDF dataset chunks}} 32 | 33 | .. versionadded:: (cfdm) 1.7.0 34 | 35 | """ 36 | 37 | def dump( 38 | self, 39 | display=True, 40 | _omit_properties=None, 41 | _key=None, 42 | _level=0, 43 | _title=None, 44 | _axes=None, 45 | _axis_names=None, 46 | ): 47 | """A full description of the domain ancillary construct. 48 | 49 | Returns a description of all properties, including those of 50 | components, and provides selected values of all data arrays. 51 | 52 | .. versionadded:: (cfdm) 1.7.0 53 | 54 | :Parameters: 55 | 56 | display: `bool`, optional 57 | If False then return the description as a string. By 58 | default the description is printed. 59 | 60 | :Returns: 61 | 62 | {{returns dump}} 63 | 64 | """ 65 | if _title is None: 66 | ncvar = self.nc_get_variable(None) 67 | if ncvar is not None: 68 | ncvar = f" (ncvar%{ncvar})" 69 | else: 70 | ncvar = "" 71 | 72 | if _key is None: 73 | default = "" 74 | else: 75 | default = _key 76 | 77 | _title = ( 78 | f"Domain Ancillary: {self.identity(default=default)}{ncvar}" 79 | ) 80 | 81 | return super().dump( 82 | display=display, 83 | _omit_properties=_omit_properties, 84 | _key=_key, 85 | _level=_level, 86 | _title=_title, 87 | _axes=_axes, 88 | _axis_names=_axis_names, 89 | ) 90 | -------------------------------------------------------------------------------- /docs/_static/customise-alabaster.css: -------------------------------------------------------------------------------- 1 | /* 2 | * overrides for alabaster 3 | * 4 | */ 5 | 6 | div.sphinxsidebar { 7 | width: {{ theme_sidebar_width }}; 8 | font-size: '13pt'; 9 | line-height: 1.5; 10 | max-height: 100%; 11 | overflow-y: auto; 12 | } 13 | 14 | /* -- body styles ----------------------------------------------------------- */ 15 | 16 | code.xref { 17 | color: #5682ad; 18 | text-decoration: none; 19 | } 20 | 21 | 22 | div.admonition p.admonition-title { 23 | font-size: 13pt; 24 | font-weight: bold; 25 | } 26 | 27 | /* -- tables ---------------------------------------------------------------- */ 28 | 29 | table.docutils { 30 | border: 0; 31 | border-collapse: collapse; 32 | } 33 | 34 | table.docutils td, table.docutils th { 35 | padding: 1px 8px 1px 5px; 36 | border-top: 0; 37 | border-left: 0; 38 | border-right: 0; 39 | border-bottom: 1px solid #aaa; 40 | } 41 | 42 | table.field-list td, table.field-list th { 43 | border: 0 !important; 44 | } 45 | 46 | table.footnote td, table.footnote th { 47 | border: 0 !important; 48 | } 49 | 50 | th { 51 | text-align: left; 52 | vertical-align: top; 53 | padding-right: 5px; 54 | background-color: #5682ad; 55 | color: white; 56 | } 57 | 58 | /* 59 | * Force top alignment for table items so left reference item can align with 60 | * the start of text to describe it in column to right, for better ease of 61 | * comprehension in detailed rows where description text spans many lines. 62 | */ 63 | td { 64 | vertical-align: top; 65 | } 66 | 67 | /* Some tables are otherwise not left-aligned so force them to be. */ 68 | table.align-default { 69 | margin-left: 0; 70 | } 71 | 72 | table.citation { 73 | border-left: solid 1px gray; 74 | margin-left: 1px; 75 | } 76 | 77 | table.citation td { 78 | border-bottom: none; 79 | } 80 | 81 | /* -- Sphinx 2.3.1 build tweaks (hopefully needed only temporarily) --------- */ 82 | 83 | /* Force one-line spacing between docstring paragraphs (missing for v 2.3.1) */ 84 | .field-list p { 85 | margin-bottom: 1.0em; 86 | } 87 | 88 | /* 89 | * Alabaster theme is responsive and when screen width becomes small enough 90 | * (e.g. with tablets/mobiles) it sets this to 0, making the bullet points sit 91 | * outside of their boxes. Prevent that by overriding for all widths. 92 | */ 93 | ul { 94 | margin-left: 30px; 95 | } 96 | 97 | /* Recolour ugly beige for API function/class/constant element signatures */ 98 | dt[id] { 99 | background-color: #ffed9f; 100 | } 101 | 102 | /* Subtle colours for parameters and returns info for API reference items */ 103 | dl.field-list > dt { 104 | background-color: #edf7e2; 105 | word-break: keep-all; 106 | } 107 | -------------------------------------------------------------------------------- /docs/source/_static/customise-alabaster.css: -------------------------------------------------------------------------------- 1 | /* 2 | * overrides for alabaster 3 | * 4 | */ 5 | 6 | div.sphinxsidebar { 7 | width: {{ theme_sidebar_width }}; 8 | font-size: '13pt'; 9 | line-height: 1.5; 10 | max-height: 100%; 11 | overflow-y: auto; 12 | } 13 | 14 | /* -- body styles ----------------------------------------------------------- */ 15 | 16 | code.xref { 17 | color: #5682ad; 18 | text-decoration: none; 19 | } 20 | 21 | 22 | div.admonition p.admonition-title { 23 | font-size: 13pt; 24 | font-weight: bold; 25 | } 26 | 27 | /* -- tables ---------------------------------------------------------------- */ 28 | 29 | table.docutils { 30 | border: 0; 31 | border-collapse: collapse; 32 | } 33 | 34 | table.docutils td, table.docutils th { 35 | padding: 1px 8px 1px 5px; 36 | border-top: 0; 37 | border-left: 0; 38 | border-right: 0; 39 | border-bottom: 1px solid #aaa; 40 | } 41 | 42 | table.field-list td, table.field-list th { 43 | border: 0 !important; 44 | } 45 | 46 | table.footnote td, table.footnote th { 47 | border: 0 !important; 48 | } 49 | 50 | th { 51 | text-align: left; 52 | vertical-align: top; 53 | padding-right: 5px; 54 | background-color: #5682ad; 55 | color: white; 56 | } 57 | 58 | /* 59 | * Force top alignment for table items so left reference item can align with 60 | * the start of text to describe it in column to right, for better ease of 61 | * comprehension in detailed rows where description text spans many lines. 62 | */ 63 | td { 64 | vertical-align: top; 65 | } 66 | 67 | /* Some tables are otherwise not left-aligned so force them to be. */ 68 | table.align-default { 69 | margin-left: 0; 70 | } 71 | 72 | table.citation { 73 | border-left: solid 1px gray; 74 | margin-left: 1px; 75 | } 76 | 77 | table.citation td { 78 | border-bottom: none; 79 | } 80 | 81 | /* -- Sphinx 2.3.1 build tweaks (hopefully needed only temporarily) --------- */ 82 | 83 | /* Force one-line spacing between docstring paragraphs (missing for v 2.3.1) */ 84 | .field-list p { 85 | margin-bottom: 1.0em; 86 | } 87 | 88 | /* 89 | * Alabaster theme is responsive and when screen width becomes small enough 90 | * (e.g. with tablets/mobiles) it sets this to 0, making the bullet points sit 91 | * outside of their boxes. Prevent that by overriding for all widths. 92 | */ 93 | ul { 94 | margin-left: 30px; 95 | } 96 | 97 | /* Recolour ugly beige for API function/class/constant element signatures */ 98 | dt[id] { 99 | background-color: #ffed9f; 100 | } 101 | 102 | /* Subtle colours for parameters and returns info for API reference items */ 103 | dl.field-list > dt { 104 | background-color: #edf7e2; 105 | word-break: keep-all; 106 | } 107 | -------------------------------------------------------------------------------- /cfdm/data/subarray/mixin/pointtopology.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class PointTopology: 5 | """Mixin class for point topology array compressed by UGRID. 6 | 7 | Subclasses must also inherit from `MeshSubarray`. 8 | 9 | .. versionadded:: (cfdm) 1.11.0.0 10 | 11 | """ 12 | 13 | def __getitem__(self, indices): 14 | """Return a subspace of the uncompressed data. 15 | 16 | x.__getitem__(indices) <==> x[indices] 17 | 18 | .. versionadded:: (cfdm) 1.11.0.0 19 | 20 | """ 21 | from math import isnan 22 | 23 | from scipy.sparse import csr_array 24 | 25 | from cfdm.functions import integer_dtype 26 | 27 | start_index = self.start_index 28 | node_connectivity = self._select_data(check_mask=False) 29 | 30 | masked = np.ma.isMA(node_connectivity) 31 | 32 | largest_node_id = node_connectivity.max() 33 | if not start_index: 34 | # Add 1 to remove all zeros (0 is the fill value in the 35 | # sparse array), first making sure that the datatpe can 36 | # handle it. 37 | if largest_node_id == np.iinfo(node_connectivity.dtype).max: 38 | node_connectivity = node_connectivity.astype(int, copy=False) 39 | 40 | node_connectivity = node_connectivity + 1 41 | largest_node_id = largest_node_id + 1 42 | 43 | p = 0 44 | pointers = [0] 45 | cols = [] 46 | u = [] 47 | 48 | pointers_append = pointers.append 49 | cols_extend = cols.extend 50 | u_extend = u.extend 51 | 52 | # WARNING (TODO): This loop is a potential performance bottleneck. 53 | for node in np.unique(node_connectivity).tolist(): 54 | # Find the collection of all nodes that are joined to this 55 | # node via links in the mesh, including this node itself 56 | # (which will be at the start of the list). 57 | nodes = self._connected_nodes(node, node_connectivity, masked) 58 | 59 | n_nodes = len(nodes) 60 | p += n_nodes 61 | pointers_append(p) 62 | cols_extend(range(n_nodes)) 63 | u_extend(nodes) 64 | 65 | u = np.array(u, dtype=integer_dtype(largest_node_id)) 66 | u = csr_array((u, cols, pointers)) 67 | u = u.toarray() 68 | 69 | if any(map(isnan, self.shape)): 70 | # Store the shape, now that is it known. 71 | self._set_component("shape", u.shape, copy=False) 72 | 73 | if indices is not Ellipsis: 74 | u = u[indices] 75 | 76 | # Mask all zeros 77 | u = np.ma.where(u == 0, np.ma.masked, u) 78 | 79 | if not start_index: 80 | # Subtract 1 to get back to zero-based node identities 81 | u -= 1 82 | 83 | return u 84 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.Datum.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.Datum 5 | ========== 6 | 7 | ---- 8 | 9 | .. autoclass:: cfdm.Datum 10 | :no-members: 11 | :no-inherited-members: 12 | 13 | Inspection 14 | ---------- 15 | 16 | .. rubric:: Methods 17 | 18 | .. autosummary:: 19 | :nosignatures: 20 | :toctree: ../method/ 21 | :template: method.rst 22 | 23 | ~cfdm.Datum.dump 24 | 25 | Parameter terms 26 | --------------- 27 | 28 | .. rubric:: Methods 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.Datum.del_parameter 36 | ~cfdm.Datum.get_parameter 37 | ~cfdm.Datum.has_parameter 38 | ~cfdm.Datum.set_parameter 39 | ~cfdm.Datum.parameters 40 | ~cfdm.Datum.set_parameters 41 | ~cfdm.Datum.clear_parameters 42 | 43 | Miscellaneous 44 | ------------- 45 | 46 | .. rubric:: Methods 47 | 48 | .. autosummary:: 49 | :nosignatures: 50 | :toctree: ../method/ 51 | :template: method.rst 52 | 53 | ~cfdm.Datum.copy 54 | ~cfdm.Datum.equals 55 | ~cfdm.Datum.get_original_filenames 56 | ~cfdm.Datum.creation_commands 57 | 58 | NetCDF 59 | ------ 60 | 61 | .. rubric:: Methods 62 | 63 | .. autosummary:: 64 | :nosignatures: 65 | :toctree: ../method/ 66 | :template: method.rst 67 | 68 | ~cfdm.Datum.nc_del_variable 69 | ~cfdm.Datum.nc_get_variable 70 | ~cfdm.Datum.nc_has_variable 71 | ~cfdm.Datum.nc_set_variable 72 | 73 | Groups 74 | ^^^^^^ 75 | 76 | .. rubric:: Methods 77 | 78 | .. autosummary:: 79 | :nosignatures: 80 | :toctree: ../method/ 81 | :template: method.rst 82 | 83 | ~cfdm.Datum.nc_variable_groups 84 | ~cfdm.Datum.nc_set_variable_groups 85 | ~cfdm.Datum.nc_clear_variable_groups 86 | 87 | Special 88 | ------- 89 | 90 | .. rubric:: Methods 91 | 92 | .. autosummary:: 93 | :nosignatures: 94 | :toctree: ../method/ 95 | :template: method.rst 96 | 97 | ~cfdm.Datum.__bool__ 98 | ~cfdm.Datum.__deepcopy__ 99 | ~cfdm.Datum.__repr__ 100 | ~cfdm.Datum.__str__ 101 | 102 | Docstring substitutions 103 | ----------------------- 104 | 105 | .. rubric:: Methods 106 | 107 | .. autosummary:: 108 | :nosignatures: 109 | :toctree: ../method/ 110 | :template: method.rst 111 | 112 | ~cfdm.Datum._docstring_special_substitutions 113 | ~cfdm.Datum._docstring_substitutions 114 | ~cfdm.Datum._docstring_package_depth 115 | ~cfdm.Datum._docstring_method_exclusions 116 | -------------------------------------------------------------------------------- /cfdm/data/fragment/fragmentuniquevaluearray.py: -------------------------------------------------------------------------------- 1 | from ..fullarray import FullArray 2 | from .mixin import FragmentArrayMixin 3 | 4 | 5 | class FragmentUniqueValueArray(FragmentArrayMixin, FullArray): 6 | """A fragment of aggregated data that has a single unique value. 7 | 8 | .. versionadded:: (cfdm) 1.12.0.0 9 | 10 | """ 11 | 12 | def __init__( 13 | self, 14 | unique_value=None, 15 | dtype=None, 16 | shape=None, 17 | unpack_aggregated_data=True, 18 | aggregated_attributes=None, 19 | attributes=None, 20 | source=None, 21 | copy=True, 22 | ): 23 | """**Initialisation** 24 | 25 | :Parameters: 26 | 27 | unique_value: scalar 28 | The unique value for the fragment. 29 | 30 | dtype: `numpy.dtype` 31 | The data type of the aggregated array. May be `None` 32 | if the numpy data-type is not known (which can be the 33 | case for netCDF string types, for example). This may 34 | differ from the data type of the netCDF fragment 35 | variable. 36 | 37 | shape: `tuple` 38 | The shape of the fragment within the aggregated 39 | array. This may differ from the shape of the netCDF 40 | fragment variable in that the latter may have fewer 41 | size 1 dimensions. 42 | 43 | {{init attributes: `dict` or `None`, optional}} 44 | 45 | {{aggregated_units: `str` or `None`, optional}} 46 | 47 | {{aggregated_calendar: `str` or `None`, optional}} 48 | 49 | {{init source: optional}} 50 | 51 | {{init copy: `bool`, optional}} 52 | 53 | """ 54 | super().__init__( 55 | fill_value=unique_value, 56 | dtype=dtype, 57 | shape=shape, 58 | attributes=None, 59 | source=source, 60 | copy=False, 61 | ) 62 | 63 | if source is not None: 64 | 65 | try: 66 | aggregated_attributes = source._get_component( 67 | "aggregated_attributes", None 68 | ) 69 | except AttributeError: 70 | aggregated_attributes = None 71 | 72 | try: 73 | unpack_aggregated_data = source._get_component( 74 | "unpack_aggregated_data", True 75 | ) 76 | except AttributeError: 77 | unpack_aggregated_data = True 78 | 79 | self._set_component( 80 | "unpack_aggregated_data", 81 | unpack_aggregated_data, 82 | copy=False, 83 | ) 84 | if aggregated_attributes is not None: 85 | self._set_component( 86 | "aggregated_attributes", aggregated_attributes, copy=copy 87 | ) 88 | -------------------------------------------------------------------------------- /docs/source/class/cfdm.core.Data.rst: -------------------------------------------------------------------------------- 1 | .. currentmodule:: cfdm 2 | .. default-role:: obj 3 | 4 | cfdm.core.Data 5 | ============== 6 | 7 | .. autoclass:: cfdm.core.Data 8 | :no-members: 9 | :no-inherited-members: 10 | 11 | Inspection 12 | ---------- 13 | 14 | .. rubric:: Attributes 15 | 16 | .. autosummary:: 17 | :nosignatures: 18 | :toctree: ../attribute/ 19 | :template: attribute.rst 20 | 21 | ~cfdm.core.Data.array 22 | ~cfdm.core.Data.dtype 23 | ~cfdm.core.Data.ndim 24 | ~cfdm.core.Data.shape 25 | ~cfdm.core.Data.size 26 | 27 | Units 28 | ----- 29 | 30 | .. autosummary:: 31 | :nosignatures: 32 | :toctree: ../method/ 33 | :template: method.rst 34 | 35 | ~cfdm.core.Data.del_units 36 | ~cfdm.core.Data.get_units 37 | ~cfdm.core.Data.has_units 38 | ~cfdm.core.Data.set_units 39 | 40 | Date-time support 41 | ----------------- 42 | 43 | .. autosummary:: 44 | :nosignatures: 45 | :toctree: ../method/ 46 | :template: method.rst 47 | 48 | ~cfdm.core.Data.del_calendar 49 | ~cfdm.core.Data.get_calendar 50 | ~cfdm.core.Data.has_calendar 51 | ~cfdm.core.Data.set_calendar 52 | 53 | Data creation routines 54 | ---------------------- 55 | 56 | From existing data 57 | ^^^^^^^^^^^^^^^^^^ 58 | 59 | .. autosummary:: 60 | :nosignatures: 61 | :toctree: ../method/ 62 | :template: method.rst 63 | 64 | ~cfdm.core.Data.copy 65 | 66 | Mask support 67 | ------------ 68 | 69 | .. autosummary:: 70 | :nosignatures: 71 | :toctree: ../method/ 72 | :template: method.rst 73 | 74 | ~cfdm.core.Data.del_fill_value 75 | ~cfdm.core.Data.get_fill_value 76 | ~cfdm.core.Data.has_fill_value 77 | ~cfdm.core.Data.set_fill_value 78 | 79 | Miscellaneous 80 | ------------- 81 | 82 | .. autosummary:: 83 | :nosignatures: 84 | :toctree: ../method/ 85 | :template: method.rst 86 | 87 | ~cfdm.core.Data.source 88 | 89 | Special 90 | ------- 91 | 92 | .. autosummary:: 93 | :nosignatures: 94 | :toctree: ../method/ 95 | :template: method.rst 96 | 97 | ~cfdm.core.Data.__deepcopy__ 98 | ~cfdm.core.Data.__repr__ 99 | ~cfdm.core.Data.__str__ 100 | 101 | Docstring substitutions 102 | ----------------------- 103 | 104 | .. rubric:: Methods 105 | 106 | .. autosummary:: 107 | :nosignatures: 108 | :toctree: ../method/ 109 | :template: method.rst 110 | 111 | ~cfdm.core.Data._docstring_special_substitutions 112 | ~cfdm.core.Data._docstring_substitutions 113 | ~cfdm.core.Data._docstring_package_depth 114 | ~cfdm.core.Data._docstring_method_exclusions 115 | --------------------------------------------------------------------------------