Thanks to the suggestion from Jmb about using ndarray::ArrayView2
, I was able to get create the attribute with the desired DATASPACE
definition:
use anyhow::{Ok, Result};
use hdf5::types::FixedAscii;
use hdf5::{Dataspace, File};
use std::path::PathBuf;
use std::str::Bytes;
use ndarray::ArrayView2;
fn main() -> Result<()> {
let hdf5_path = PathBuf::from(
"SVM15_npp_d20181005_t2022358_e2024003_b35959_c20181008035331889474_cspp_bck.h5",
);
let file = File::open_rw(hdf5_path)?;
let gmtco_name =
"GMTCO_npp_d20181005_t2022358_e2024003_b35959_c20181008035331889474_cspp_bck.h5";
let attr_name = "FixedAscii_2D_array";
let ascii_array: hdf5::types::FixedAscii<79> =
hdf5::types::FixedAscii::from_ascii(&gmtco_name)?;
let ascii_array = [ascii_array];
let data = ArrayView2::from_shape((1, 1), &ascii_array)?;
file.new_attr::<hdf5::types::FixedAscii<79>>()
.shape([1, 1])
.create(attr_name)?
.write(&data)?;
Ok(())
}
which results in the attribute (as shown via h5dump
):
$> h5dump -a FixedAscii_2D_array SVM15_npp_d20181005_t2022358_e2024003_b35959_c20181008035331889474_cspp_bck.h5
HDF5 "SVM15_npp_d20181005_t2022358_e2024003_b35959_c20181008035331889474_cspp_bck.h5" {
ATTRIBUTE "FixedAscii_2D_array" {
DATATYPE H5T_STRING {
STRSIZE 79;
STRPAD H5T_STR_NULLPAD;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SIMPLE { ( 1, 1 ) / ( 1, 1 ) }
DATA {
(0,0): "GMTCO_npp_d20181005_t2022358_e2024003_b35959_c20181008035331889474_cspp_bck.h5\000"
}
}
}
As far as I can tell, there is as yet no high-level interface to set STRPAD
to H5T_STR_NULLTERM
rather than H5T_STR_NULLPAD
, however I believe this can be done using the hdf5-sys
crate in an unsafe block.
I have created a git repo containing many examples of reading and writing HDF5 (and NetCDF4) attributes and datasets (including several variants of the above solution) at https://codeberg.org/gpcureton/hdf5_netcdf_test.rs , in the hope that it may be useful for people trying to use the Rust interface to HDF5 and NetCDF4.