简体   繁体   English

无法读取NetCDF结构变量数组子范围

[英]Unable to read NetCDF structure variable array subrange

I have an NCDF structure being retrieved from an HDF5 file, and I'm trying to read a subrange of an array variable using the Java NetCDF 4.3.16 library. 我有一个从HDF5文件中检索到的NCDF结构,我正在尝试使用Java NetCDF 4.3.16库读取数组变量的子范围。 I find the variable like this: 我发现这样的变量:

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

At this point I can read the entire variable if I want: 此时,如果需要,我可以读取整个变量:

netCDFArray = netCDFVariable.read();

But let's say that the variable is an integer array of length 10, and I want to read just the subrange of indexes 3, 4, 5, 6, and 7: 但让我们说该变量是一个长度为10的整数数组,我只想读取索引3、4、5、6和7的子范围:

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

But here Variable.read(Section) throws an InvalidRangeException . 但是这里Variable.read(Section)抛出InvalidRangeException Tracing through the code, the variable checks its own internal shape variable, which happens to be [] and finds that to be invalid. 跟踪代码,该变量检查其自己的内部shape变量,该变量恰好是[]并发现该变量无效。

So why doesn't the variable have an appropriate shape ? 那么,为什么变量没有合适的shape呢? Do I have to read the variable first to get its correct shape? 我必须先读取变量以获取正确的形状吗? (That would of course defeat the purpose of trying to read a subrange in the first place.) (这当然会挫败尝试首先读取子范围的目的。)

As of NetCDF 4.3.17 the implementations of Variable.read() and Variable.read(Section) differ considerably when reading a member of an array of structures, neither adhering to the API documentation. 从NetCDF 4.3.17开始,在读取结构数组的成员时, Variable.read()Variable.read(Section)有很大不同,但都没有遵守API文档。 Below I present a workaround. 下面,我提出一种解决方法。

For illustration, let's say I have the following: 为了举例说明,假设我有以下内容:

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

This is a 24-element array named example of structures, each structure containing two members, foo and bar . 这是一个24元素的数组,命名为structure的example ,每个结构包含两个成员foobar Let us assume I get a reference to the foo member like so: 让我们假设我像这样获得对foo成员的引用:

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

If I call fooVariable.read() , the API documentation says that I will get back the first value, because foo is part of a structure that is an element in an array. 如果我调用fooVariable.read() ,API文档会说我将取回第一个值,因为foo是结构的一部分,该结构是数组中的元素。 This is not what happens; 这不会发生; instead, the library actually does some clever reading and returns the foo member from all the structures as a single array of foo values. 相反,该库实际上进行了一些巧妙的读取,并将所有结构中的foo成员作为foo值的单个数组返回。 This is the behavior I desire. 这是我想要的行为。

Unfortunately the fooVariable.read(Section) implementation does not have the same bit of clever code as does fooVariable.read() , and instead is written to throw an UnsupportedOperationException . 不幸的是, fooVariable.read(Section)实施不具有巧妙的代码相同的位一样fooVariable.read()而是被写入抛出一个UnsupportedOperationException (Through the lack of an added check the code doesn't even get that far, throwing an InvalidRangeException because it thinks the given Section is invalid. This is a pity, because (once a check is added to avoid an InvalidRangeException ) the clever code from the Variable.read() implementation would work equally well for Variable.read(Section) with the insertion of only a single method argument on a single line! (通过缺少添加的检查,代码甚至还没有InvalidRangeException那么远,抛出InvalidRangeException因为它认为给定的Section无效。这很遗憾,因为(一旦添加了检查以避免InvalidRangeException ),那么聪明的代码从Variable.read()实现中获得的结果对于Variable.read(Section)同样适用,只需在一行上插入单个方法参数即可!

Using the clever code from Variable.read() I have created a method that works around this problem, allowing a caller to ask for a section of an array with any variable. 使用Variable.read()的巧妙代码,我创建了一个解决此问题的方法,允许调用者请求包含任何变量的数组部分。 If the variable is a member of a structure in an array, the subrange of just that member will be read, effectively creating another version of the fooVariable.read(Section) method that has the same behavior as fooVariable.read() for structure members: 如果变量是数组中结构的成员,则将读取该成员的子范围,从而有效地创建另一个版本的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
    }
  }

I reported this problem (now identified as NRW-974703) with Unidata NetCDF Support . 我通过Unidata NetCDF支持报告了此问题(现在标识为NRW-974703)。 At first I was told that these methods didn't apply to HDF5 and only apply to Unidata's own NetCDF file format. 最初,我被告知这些方法不适用于HDF5,而仅适用于Unidata自己的NetCDF文件格式。 (This is completely incorrect.) Then I was told that I didn't understand the Java NetCDF API (although from the previous answer I question who exactly lacks understanding of the Unidata library). (这是完全不正确的。)然后,我被告知我不理解Java NetCDF API(尽管从前面的回答中,我质疑谁完全不了解Unidata库)。 I have not yet received a response from Unidata after tracing down the specific problem code and providing the above workaround. 跟踪特定的问题代码并提供上述解决方法后,我尚未收到Unidata的答复。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM