lasprs 0.14.3

Library for Acoustic Signal Processing (Rust edition, with optional Python bindings via pyo3)
Documentation
//! Common helper functions for working with HDF5 files.
use crate::measurement::*;
use snafu::prelude::*;
use std::{path::PathBuf, str::FromStr};

use hdf5_metno::{Error, File, H5Type, Location, types::VarLenUnicode};
type Result<T> = std::result::Result<T, MeasurementError>;

/// Read a scalar attribute from an HDF5 file.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
///
/// # Returns
///
/// A `Result` containing the value of the attribute or an error.
pub fn read_h5_attr_scalar<T>(loc: &hdf5_metno::Location, attr_name: &str) -> Result<T>
where
    T: H5Type,
{
    let attr = loc.attr(attr_name).and_then(|attr| attr.read_scalar::<T>());
    let attr = attr.map_err(H5Error::from);
    attr.context(ReadingAttributeFailedSnafu { attr_name })
}
/// Write a scalar attribute to an HDF5 file.
///
/// # Arguments
///
/// * `file` - A reference to the HDF5 file.
/// * `name` - The name of the attribute.
/// * `val` - The value of the attribute.
///
/// # Returns
///
/// A `Result` indicating success or failure.
pub fn write_h5_attr_scalar<T>(loc: &hdf5_metno::Location, attr_name: &str, val: T) -> Result<()>
where
    T: H5Type,
{
    // Returns a FileProblem, if error
    let attr = loc
        .new_attr::<T>()
        .create(attr_name)
        .map_err(H5Error::from)
        .context(H5FileProblemSnafu {
            operation: format!("Creating scalar attribute for: {}", attr_name),
        })?;

    attr.write_scalar(&val)
        .map_err(H5Error::from)
        .with_context(|_| WritingAttributeFailedSnafu {
            attr_name: attr_name.to_string(),
        })?;
    Ok(())
}

/// Write a scalar attribute to an HDF5 file, overwriting any existing attribute
/// with the same name.
///
/// # Arguments
///
/// * `file` - A reference to the HDF5 file.
/// * `name` - The name of the attribute.
/// * `val` - The value of the attribute.
///
/// # Returns
///
/// A `Result` indicating success or failure.
pub fn write_h5_attr_scalar_overwrite<T>(
    loc: &hdf5_metno::Location,
    attr_name: &str,
    val: T,
) -> Result<()>
where
    T: H5Type,
{
    if let Err(e) = loc.delete_attr(attr_name) {
        eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
    }
    write_h5_attr_scalar(loc, attr_name, val)
}

/// Read a list of values from an HDF5 attribute.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
///
/// # Returns
///
/// A `Result` containing the list of values or an error.
pub fn read_h5_attr_list<T>(loc: &Location, attr_name: &str) -> Result<Vec<T>>
where
    T: H5Type + Clone,
{
    let attr = loc
        .attr(attr_name)
        .and_then(|attr| attr.read_1d::<T>())
        .map(|arr| arr.to_vec());
    attr.map_err(H5Error::from)
        .with_context(|_| ReadingAttributeFailedSnafu {
            attr_name: attr_name.to_string(),
        })
}

/// Write an attribute slice to an HDF5 file.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
/// * `val` - The values of the attribute.
///
/// # Returns
///
/// A `Result` indicating success or failure. Possible errors are due to an
/// existing attribute with the same name.
pub fn write_h5_attr_list<T>(loc: &Location, attr_name: &str, val: &[T]) -> Result<()>
where
    T: H5Type,
{
    let attr = loc
        .new_attr::<T>()
        .shape([val.len()])
        .create(attr_name)
        .map_err(H5Error::from)
        .context(WritingAttributeFailedSnafu { attr_name })?;
    attr.write(val)
        .map_err(H5Error::from)
        .context(WritingAttributeFailedSnafu { attr_name })?;
    Ok(())
}

/// Write a string attribute to an HDF5 file, overwriting any existing attribute with the same name.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
/// * `val` - The value of the attribute.
///
/// # Returns
///
/// A `Result` indicating success or failure.
pub fn write_h5_attr_list_overwrite<T>(loc: &Location, attr_name: &str, val: &[T]) -> Result<()>
where
    T: H5Type,
{
    if let Err(e) = loc.delete_attr(attr_name) {
        eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
    }
    write_h5_attr_list(loc, attr_name, val)
}

/// Read a string attribute from an HDF5 file.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
///
/// # Returns
///
/// A `Result` containing the string or an error.
pub fn read_h5_attr_string(loc: &Location, attr_name: &str) -> Result<String> {
    let attr = loc
        .attr(attr_name)
        .and_then(|attr| attr.read_scalar::<VarLenUnicode>())
        .map(|s| s.to_string())
        .map_err(H5Error::from);
    attr.with_context(|_| ReadingAttributeFailedSnafu {
        attr_name: attr_name.to_string(),
    })
}

/// Write a string attribute to an HDF5 file.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
/// * `val` - The string value to write.
///
/// # Returns
///
/// A `Result` indicating success or an error.
pub fn write_h5_attr_string(loc: &Location, attr_name: &str, val: &str) -> Result<()> {
    let h5string: VarLenUnicode =
        VarLenUnicode::from_str(val).expect("Failed to convert string to VarLenUnicode");
    write_h5_attr_scalar(loc, attr_name, h5string)
}

/// Write a string attribute to an HDF5 file, overwriting any existing attribute
/// with the same name.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
/// * `val` - The string value to write.
///
/// # Returns
///
/// A `Result` indicating success or an error.
pub fn write_h5_attr_string_overwrite(loc: &Location, attr_name: &str, val: &str) -> Result<()> {
    if let Err(e) = loc.delete_attr(attr_name) {
        eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
    }
    write_h5_attr_string(loc, attr_name, val)
}

/// Read a list of strings from an HDF5 attribute.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
///
/// # Returns
///
/// A `Result` containing the list of strings or an error.
pub fn read_h5_attr_stringlist(loc: &Location, attr_name: &str) -> Result<Vec<String>> {
    let attr = loc
        .attr(attr_name)
        .and_then(|attr| attr.read_1d::<VarLenUnicode>())
        .map(|arr| arr.into_iter().map(|s| s.to_string()).collect())
        .map_err(H5Error::from);
    attr.context(ReadingAttributeFailedSnafu { attr_name })
}

/// Write a list of strings to an HDF5 attribute.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
/// * `val` - The list of strings to write.
///
/// # Returns
///
/// A `Result` indicating success or an error.
pub fn write_h5_attr_stringlist(loc: &Location, attr_name: &str, val: &[String]) -> Result<()> {
    let attr_h5 = val
        .iter()
        .map(|v| VarLenUnicode::from_str(v).expect("Error converting string to hdf5 VarLenUnicode"))
        .collect::<Vec<_>>();
    write_h5_attr_list(loc, attr_name, &attr_h5)
}

/// Write a list of strings to an HDF5 attribute, overwriting any existing
/// attribute with the same name.
///
/// # Arguments
///
/// * `loc` - A reference to a location in the HDF5 file.
/// * `attr_name` - The name of the attribute.
/// * `val` - The list of strings to write.
///
/// # Returns
///
/// A `Result` indicating success or an error.
pub fn write_h5_attr_stringlist_overwrite(
    loc: &Location,
    attr_name: &str,
    val: &[String],
) -> Result<()> {
    if let Err(e) = loc.delete_attr(attr_name) {
        eprintln!("Failed to delete attribute when updating attribute {attr_name}: {e}")
    }
    write_h5_attr_stringlist(loc, attr_name, val)
}