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()Variable.read(Section)構造体の配列のメンバーを読み取るときにかなり異なり、どちらも API ドキュメントに準拠していません。以下に回避策を示します。

説明のために、次のものがあるとしましょう。

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

これは、構造体の名前が付けられた 24 要素の配列exampleであり、各構造体には 2 つのメンバーfooとが含まれbarます。foo次のようにメンバーへの参照を取得するとします。

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

を呼び出すと、配列内の要素である構造体の一部であるfooVariable.read()ため、最初の値が返されると API ドキュメントに記載されています。fooこれは起こることではありません。代わりに、ライブラリは実際に巧妙な読み取りを行いfoo、すべての構造体から値の単一の配列としてメンバーを返しfooます。これは私が望む動作です。

残念ながら、このfooVariable.read(Section)実装には と同じように巧妙なコードがfooVariable.read()なく、代わりに をスローするように記述されていUnsupportedOperationExceptionます。(チェックが追加されていないため、コードはそれほど遠くまで到達せずInvalidRangeException、指定されたものが無効であると見なされるため、 をスローしSectionます。これは残念です。(チェックを追加して を回避すると)実装InvalidRangeExceptionからの巧妙なコード1 行に 1 つのメソッド引数のみを挿入して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
    }
  }

この問題 (現在は NRW-974703 として識別されています) をUnidata NetCDF Supportで報告しました。最初に、これらの方法は HDF5 には適用されず、Unidata 独自の NetCDF ファイル形式にのみ適用されると言われました。(これは完全に間違っています。) その後、私は Java NetCDF API を理解していないと言われました (ただし、前の回答から、Unidata ライブラリを正確に理解していない人は誰なのか疑問に思います)。特定の問題コードを追跡し、上記の回避策を提供した後、Unidata からまだ応答を受け取っていません。

于 2013-07-30T20:19:21.117 に答える