NetCDF metadata extraction#
Enumerate and normalize all metadata from NetCDF files using GDAL's Multidimensional (MDim) API.
Overview:
- Open NetCDF files as MDArray-backed datasets
- Traverse groups, arrays, dimensions, and attributes
- Produce a JSON-serializable metadata object
- Keep compatibility with the existing dimension parser exposed via
NetCDF.meta_data
Pipeline#
get_metadata drives a MetadataBuilder, which hands a GroupTraverser the root group and walks it
breadth-first, emitting one info record per group / array / dimension into the aggregate
NetCDFMetadata. The result serializes to JSON, a plain dict, or a flat search index — and round-trips
back from JSON:
flowchart LR
S[("GDAL MDIM dataset<br/>GetRootGroup()")] --> B["MetadataBuilder.build()"]
B --> T["GroupTraverser.walk(root)<br/>breadth-first"]
T --> VI["VariableInfo"]
T --> DI["DimensionInfo"]
T --> GI["GroupInfo"]
VI --> M["NetCDFMetadata"]
DI --> M
GI --> M
M -->|to_json| J[("JSON string")]
M -->|to_dict| D[("dict")]
M -->|flatten_for_index| FI[("flat index")]
J -->|from_json| M
to_json, to_dict, from_json, and flatten_for_index (the edge labels above) are module-level
functions in pyramids.netcdf.metadata that take a NetCDFMetadata argument — not methods on the
class. NetCDFMetadata's only public method is get_dimension.
See the data models for the structure of each info record.
Usage#
Read all metadata from a file:
from pyramids.netcdf.netcdf import NetCDF
from pyramids.netcdf.metadata import to_json
# Open the file in MDIM mode
nc = NetCDF.read_file("tests/data/netcdf/cf__4v__1d3-3d1__proj__y-desc.nc", open_as_multi_dimensional=True)
# Read everything (groups, arrays, dimensions, attributes)
md = nc.get_all_metadata()
# Convert to JSON
print(to_json(md))
You can also pass open options (persisted into the result for provenance):
Dimension overview#
For convenience and backward compatibility, the returned metadata includes a dimension_overview
section summarizing parsed dimensions using the existing dimensions.MetaData logic.
Shape:
names:list[str]sizes:dict[str, int]attrs:dict[str, dict[str, str]]values:dict[str, list[int | float | str]] | None
This mirrors nc.meta_data and provides a compact CF-friendly view.
Notes#
- The feature uses GDAL's MDim API starting at
dataset.GetRootGroup(). - Attributes are normalized to JSON-friendly scalars or vectors; bytes are decoded as UTF-8.
- Convenience fields on arrays include: unit, nodata (
_FillValue/missing_valueprecedence), scale/offset, CRS (WKT/PROJJSON), structural info, block size, and coordinate variables. - No array data values are read; only metadata.
- The module provides helpers to serialize to/from JSON and to a plain dict.
References#
API#
Functions for extracting, serializing, and deserializing NetCDF metadata using GDAL's Multidimensional API.
pyramids.netcdf.metadata.get_metadata(source, open_options=None, start_group=None)
#
Read and normalize all NetCDF MDIM metadata.
Accepts several source types and delegates to
MetadataBuilder to produce a NetCDFMetadata instance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Dataset | str | object
|
The data source.
Accepts a GDAL dataset directly, a file path (opened
internally with |
required |
open_options
|
dict[str, Any] | None
|
Optional dictionary of GDAL open-options. Stored in the resulting metadata for provenance but not used to open the file. |
None
|
start_group
|
Group | None
|
Optional GDAL group to traverse from instead
of the dataset's root group. A |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
NetCDFMetadata |
NetCDFMetadata
|
Fully populated metadata dataclass. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If source is a string path that cannot be opened as a multidimensional raster. |
Examples:
Open from a file path:
>>> from osgeo import gdal
>>> import pyramids.netcdf.metadata as meta
>>> md = meta.get_metadata(
... "precip.nc"
... )
>>> md.driver
'netCDF'
See Also
MetadataBuilder: The builder class used internally.
Source code in src/pyramids/netcdf/metadata.py
pyramids.netcdf.metadata.to_json(metadata)
#
Serialize NetCDFMetadata to a compact JSON string.
Converts the dataclass tree to plain dicts via to_dict
and then encodes to JSON with no extra whitespace.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata
|
NetCDFMetadata
|
A |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
JSON-encoded string with no ASCII escaping and
compact separators (no spaces after |
Examples:
Round-trip a minimal metadata object:
>>> import json
>>> from pyramids.netcdf.metadata import to_json
>>> from pyramids.netcdf.models import (
... NetCDFMetadata, StructuralInfo,
... )
>>> md = NetCDFMetadata(
... driver="netCDF",
... root_group="/",
... groups={},
... variables={},
... dimensions={},
... global_attributes={},
... structural=StructuralInfo(
... driver_name="netCDF"
... ),
... created_with={"library": "GDAL"},
... )
>>> s = to_json(md)
>>> json.loads(s)["driver"]
'netCDF'
See Also
to_dict: Converts to plain dicts without JSON encoding.
from_json: Deserializes the string back to
NetCDFMetadata.
Source code in src/pyramids/netcdf/metadata.py
pyramids.netcdf.metadata.from_json(s)
#
Deserialize NetCDFMetadata from a JSON string.
Parses the JSON produced by to_json and manually
reconstructs the dataclass hierarchy (GroupInfo,
VariableInfo, DimensionInfo, StructuralInfo, and the
CF cross-reference block CFInfo when present).
Only the schema produced by to_dict / to_json is
supported; arbitrary JSON will likely raise KeyError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s
|
str
|
A JSON string previously produced by |
required |
Returns:
| Name | Type | Description |
|---|---|---|
NetCDFMetadata |
NetCDFMetadata
|
Reconstructed metadata instance. |
Raises:
| Type | Description |
|---|---|
JSONDecodeError
|
If s is not valid JSON. |
KeyError
|
If required fields are missing from the JSON payload. |
Examples:
Round-trip through JSON:
>>> from pyramids.netcdf.metadata import (
... to_json, from_json,
... )
>>> from pyramids.netcdf.models import (
... NetCDFMetadata, StructuralInfo,
... )
>>> md = NetCDFMetadata(
... driver="netCDF",
... root_group="/",
... groups={},
... variables={},
... dimensions={},
... global_attributes={"history": "created"},
... structural=StructuralInfo(
... driver_name="netCDF"
... ),
... created_with={"library": "GDAL"},
... )
>>> s = to_json(md)
>>> restored = from_json(s)
>>> restored.driver
'netCDF'
>>> restored.global_attributes["history"]
'created'
See Also
to_json: The serialization counterpart.
Source code in src/pyramids/netcdf/metadata.py
832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 | |
pyramids.netcdf.metadata.to_dict(metadata)
#
Convert NetCDFMetadata to plain dicts suitable for JSON.
Recursively walks all dataclass fields and converts them to
plain dict / list / scalar types so the result can be
passed directly to json.dumps.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
metadata
|
NetCDFMetadata
|
A |
required |
Returns:
| Name | Type | Description |
|---|---|---|
dict |
dict[str, Any]
|
Nested dictionary with all dataclass fields converted to plain dicts. |
Examples:
Convert a minimal metadata object:
>>> from pyramids.netcdf.metadata import to_dict
>>> from pyramids.netcdf.models import (
... NetCDFMetadata, StructuralInfo,
... )
>>> md = NetCDFMetadata(
... driver="netCDF",
... root_group="/",
... groups={},
... variables={},
... dimensions={},
... global_attributes={"title": "test"},
... structural=StructuralInfo(
... driver_name="netCDF"
... ),
... created_with={"library": "GDAL"},
... )
>>> d = to_dict(md)
>>> d["driver"]
'netCDF'
>>> d["global_attributes"]["title"]
'test'
>>> d["structural"]["driver_name"]
'netCDF'
See Also
to_json: Serializes directly to a JSON string.
from_json: Deserializes a JSON string back to
NetCDFMetadata.