0

我有一个从 HDF5 文件中检索的 NCDF 结构,我正在尝试使用 Java NetCDF 4.3.16 库读取数组变量的子范围。我发现这样的变量:

Variable netCDFVariable = netCDFFile.findVariable("/group/struct.var");

此时,如果需要,我可以读取整个变量:

netCDFArray = netCDFVariable.read();

但是假设变量是一个长度为 10 的整数数组,我只想读取索引 3、4、5、6 和 7 的子范围:

Section section=new Section(new int[]{3}, new int[]{5});
netCDFArray = netCDFVariable.read(section);

但这里Variable.read(Section)抛出一个InvalidRangeException. 跟踪代码,变量检查它自己的内部shape变量,它恰好是[]并发现它是无效的。

那么为什么变量没有适当的shape? 我是否必须先读取变量才能获得正确的形状?(这当然会破坏首先尝试读取子范围的目的。)

4

1 回答 1

0

从 NetCDF 4.3.17 开始,在读取结构数组的成员时,实现Variable.read()和差异很大,既不遵守 API 文档。Variable.read(Section)下面我介绍一个解决方法。

为了说明,假设我有以下内容:

Structure {
  int foo;
    :_Unsigned = "true";
  int bar;
    :_Unsigned = "true";
} example(24);

这是一个以结构命名的 24 元素数组example,每个结构包含两个成员,foo并且bar. 让我们假设我得到了对foo成员的引用,如下所示:

final Variable fooVariable = netcdfFile.findVariable("/blah/example.foo");

如果我调用fooVariable.read(),API 文档说我将取回第一个值,因为foo它是数组中元素的结构的一部分。这不是发生的事情;相反,该库实际上做了一些巧妙的读取,并将foo所有结构中的成员作为单个foo值数组返回。这是我想要的行为。

不幸的是,该fooVariable.read(Section)实现没有像那样聪明的代码fooVariable.read(),而是编写为抛出一个UnsupportedOperationException. (由于没有添加检查,代码甚至没有走那么远,抛出 anInvalidRangeException因为它认为给定Section的无效。这很遗憾,因为(一旦添加检查以避免)来自实现InvalidRangeException的聪明代码在一行中仅插入一个方法参数Variable.read()同样适用!Variable.read(Section)

使用Variable.read()我的巧妙代码创建了一个解决此问题的方法,允许调用者请求包含任何变量的数组的一部分。如果变量是数组中结构的成员,则仅读取该成员的子范围,从而有效地创建具有与结构成员fooVariable.read(Section)相同行为的方法的另一个版本:fooVariable.read()

  /**
   * Reads an array of data from the provided NetCDF variable. If the variable is a member of a structure, that member is read
   * from all the structures in the array and returned as a single array containing that member from each structure.
   * @param variable The NetCDF variable to read.
   * @param section The section indicating the element of the array to read
   * @param indexEnd The ending source index, exclusive, or -1 if all available values should be read.
   * @return An array representing the requested range of values read for the given variable.
   * @throws IOException if there is an error reading the data.
   */
  public static Array readArray(final Variable variable, final Section section) throws IOException, InvalidRangeException {
    if (variable.isMemberOfStructure()) { //if the variable is member of a structure
      final Structure parentStructure = variable.getParentStructure().select(variable.getShortName()); //select just the member variable
      final ArrayStructure arrayStructure = (ArrayStructure) parentStructure.read(section); //read the array of structures
      return arrayStructure.extractMemberArray(arrayStructure.findMember(variable.getShortName())); //extract just the member into an array
    } else { //if the variable is not a member of a structure
      return variable.read(section); //just read the section directly from the variable
    }
  }

我通过Unidata NetCDF Support报告了这个问题(现在标识为 NRW-974703)。起初我被告知这些方法不适用于 HDF5,仅适用于 Unidata 自己的 NetCDF 文件格式。(这是完全不正确的。)然后我被告知我不了解 Java NetCDF API(尽管从上一个答案中我质疑谁完全缺乏对 Unidata 库的了解)。在追踪到具体问题代码并提供上述解决方法后,我尚未收到 Unidata 的回复。

于 2013-07-30T20:19:21.117 回答