如何在HDF5文件中筛选特定对象

1 投票
1 回答
782 浏览
提问于 2025-04-18 03:57

我正在学习ILNumerics HDF5 API。我很喜欢用C#对象初始化器一次性设置复杂的HDF5文件的这个选项。我创建了以下文件:

using (var f = new H5File("myFile.h5")) {

    f.Add(new H5Group("myTopNode") {
        new H5Dataset("dsNo1", ILMath.vec<float>(1,200)),  // no attributes 
        new H5Group("myGroup") {
            new H5Dataset("dsYes", ILMath.rand(100,200)) { // matching dataset
                Attributes = { 
                    { "att1", 1 },
                    { "att2", 2 } 
                }
            }, 
            new H5Dataset("dsNo2") {  // attributes but wrong name
                Attributes = { 
                    { "wrong1", -100 },
                    { "wrong2", -200 } 
                }
            }
        }
    });
}

现在我在寻找一个聪明的方法来遍历这个文件,并筛选出具有特定属性的数据集。我想找到所有至少有一个属性名中包含“att”的数据集,并收集并返回它们的内容。这是我到目前为止做的:

IList<ILArray<double>> list = new List<ILArray<double>>();
using (var f = new H5File("myFile.h5")) {
    var groups = f.Groups;
    foreach (var g in groups) {
        foreach (var obj in g) {
            if (obj.H5Type == H5ObjectTypes.Dataset && obj.Name.Contains("ds")) {
                var ds = obj as H5Dataset;
                // look for attributes 
                foreach (var att in ds.Attributes) {
                    //ds.Attributes["att"].
                    if (att.Name.Contains("att")) {
                        list.Add(ds.Get<double>());
                    }
                }
            }
        }
    }
}
return list; 

但是它并没有递归地工作。我可以调整一下,但ILNumerics声称它很方便,所以一定有更好的方法?有没有类似于Python中h5py的东西?

1 个回答

1

H5Group 提供了一个叫 Find<T> 的方法,正好能满足你的需求。这个方法会遍历整个子树,并考虑到各种条件:

var matches = f.Find<H5Dataset>(
                 predicate: ds => ds.Attributes.Any(a => a.Name.Contains("att")));

为什么不让你的函数返回 'ILCell' 而不是 'List' 呢?这样做可以更好地融入 ILNumerics 的内存管理(这样就不会有多余的存储空间在那儿等着垃圾回收器来处理):

using (var f = new H5File("myFile.h5")) {
    // create container for the dataset contents
    ILCell c = cell(size(1, 1)); // one element init

    // retrieve datasets filtered
    var matches = f.Find<H5Dataset>(predicate: ds => {
        if (ds.Attributes.Any(a => a.Name.Contains("att"))) {
            c[end + 1] = ds.Get<double>();
            return true; 
        }
        return false; 
    });
    return c; 
}

一些链接:

http://ilnumerics.net/hdf5-interface.html

http://ilnumerics.net/Cells.html

http://ilnumerics.net/GeneralRules.html

撰写回答