clawhdf5-netcdf4: variables' dimensions come from the file
Variables got the first unused dimension of equal size, so a variable on an unlimited dimension with fewer records got an anonymous dim_<n>, and dimensions of one size could be swapped. Resolve them as netCDF-C does (libhdf5/hdf5open.c): _Netcdf4Coordinates ids, else the scales DIMENSION_LIST references (the last one attached to an axis), searched in the variable's group and its parents; a coordinate variable is on its own scale. Size matching remains only for axes the file names nothing for. variables()/variable_names() leave out dimension scales that are only dimensions, and _nc4_non_coord_<name> is the variable <name>. Variable::shape is the netCDF shape (an unlimited dimension's length) and the reads pad unwritten records with the fill value (_FillValue, else NC_FILL_*; NaN from read_f64); Variable::stored_shape is the HDF5 extent. New NetCDF4File::variable_names. Tests compare with netCDF4-python variable by variable: the known-issues reproducer, equal sizes, (p, p), scalars, inherited dimensions, unwritten records, h5py dimension scales, h5netcdf and xarray files. CI installs h5netcdf. known-issues entry moved to Fixed (history); stale open-table row for the unlimited-size fix removed. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -27,6 +27,7 @@ pub mod cf;
|
||||
pub mod dimension;
|
||||
pub mod error;
|
||||
pub mod group;
|
||||
mod scope;
|
||||
pub mod types;
|
||||
pub mod variable;
|
||||
|
||||
@@ -75,25 +76,25 @@ impl NetCDF4File {
|
||||
|
||||
/// List dimensions defined in the root group.
|
||||
pub fn dimensions(&self) -> Result<Vec<Dimension>, Error> {
|
||||
dimension::extract_dimensions_from_datasets(&self.hdf5.root(), &self.hdf5)
|
||||
Ok(dimension::group_dims(&self.hdf5, &self.hdf5.root())?.dims)
|
||||
}
|
||||
|
||||
/// List all variables in the root group.
|
||||
/// List all variables in the root group: its datasets, except the
|
||||
/// dimension scales that are only dimensions (netCDF-C does not list
|
||||
/// them either).
|
||||
pub fn variables(&self) -> Result<Vec<Variable<'_>>, Error> {
|
||||
let dims = self.dimensions()?;
|
||||
variable::build_variables(&self.hdf5.root(), &dims)
|
||||
scope::Scope::new(&self.hdf5, "/")?.variables()
|
||||
}
|
||||
|
||||
/// The names of the root group's variables (see
|
||||
/// [`variables`](Self::variables)).
|
||||
pub fn variable_names(&self) -> Result<Vec<String>, Error> {
|
||||
scope::Scope::new(&self.hdf5, "/")?.variable_names()
|
||||
}
|
||||
|
||||
/// Get a specific variable by name from the root group.
|
||||
pub fn variable(&self, name: &str) -> Result<Variable<'_>, Error> {
|
||||
let dims = self.dimensions()?;
|
||||
let ds = self
|
||||
.hdf5
|
||||
.dataset(name)
|
||||
.map_err(|_| Error::VariableNotFound(name.to_string()))?;
|
||||
let shape = ds.shape()?;
|
||||
let var_dims = variable::match_dimensions_to_variable(&shape, &dims);
|
||||
Ok(Variable::new(name.to_string(), ds, var_dims))
|
||||
scope::variable_at(&self.hdf5, "", name)
|
||||
}
|
||||
|
||||
/// Read all global (root group) attributes.
|
||||
@@ -112,7 +113,12 @@ impl NetCDF4File {
|
||||
.hdf5
|
||||
.group(name)
|
||||
.map_err(|_| Error::GroupNotFound(name.to_string()))?;
|
||||
Ok(NetCDF4Group::new(name.to_string(), &self.hdf5, hdf5_group))
|
||||
Ok(NetCDF4Group::new(
|
||||
name.to_string(),
|
||||
name.to_string(),
|
||||
&self.hdf5,
|
||||
hdf5_group,
|
||||
))
|
||||
}
|
||||
|
||||
/// Access the underlying HDF5 file for advanced operations.
|
||||
|
||||
Reference in New Issue
Block a user