Up|<<Prev|Next>>


3.2 データアクセス

NetCDFデータにアクセスする(読み込む・書き込む)場合には ,オープンされたNetCDFファイル、NetCDF変数、及び変数の要素を特定する情報(例:番号)を指定します。アクセス機能の名前は内部データ型の名前に対応します。内部データ型と外部変数型の表現が異なる場合にはデータが読み書きされる際に内部型と外部型との間の変換が行われます。

データへは direct(直接)アクセスします。これによって大きなファイルから小さな部分集合を効率的にアクセスすることができます。その部分集合の前にあるデータを先にアクセスしないからです。 データを、ファイル中の位置ではなく、変数を指定することによって読み書きすることは 、データアクセスをそのファイルの中に他に幾つ変数が存在するかとは無関係になります。これによってデータに新たな変数が加わるデータフォーマットの変更に対してプログラムの書き換えは不必要になります。

CとFORTRANインターフェースでは、データアクセスをする度にファイルを名前で特定せずに、ファイルが初めて作成・オープンされた時に割り当てられるファイルIDと呼ばれる小さな整数によって識別されます。

同様に、 任意の変数はデータアクセスの度に名前で識別されません。その代わり、変数IDと呼ばれる、NetCDF中の各変数を識別するのに使用される小さな整数 によって識別されます。

3.2.1 データアクセスの形式

NetCDFインターフェースにはオープンなNetCDFファイル中のデータ値に直接アクセスする方法が幾つか用意されています。これらのアクセス形式を汎用性の小さいほうら順に説明します:

4種類のベクトル ( index vector count vector stride vector index mapping vector )は変数の各次元に対応する要素を一つずつ持っています。ですから、n次元の 変数(rank = n)についてはn個のベクトルが必要となります。変数がスカラー量(無次元)の場合には、 これらのベクトルは無視されます。

Array section (配列断面)とは2つのベクトルによって指定される連続的な直方体、もしくは「板切れ」のようなものです。 Index vectorが原点に最も近い角の要素の座標を表します。 Count vector は各変数の次元に沿った板切れの縁の長さを順番に表します。アクセスされた値の個数はこれらの縁の長さの積です。

Subsampled array section (部分サンプルされた配列断面)は array section に似ていますが、さらにに stride vector というベクトルを使用してサンプリングを識別するために使用されます。このベクトルは各次元ごとに要素があり、その次元に沿って取るべきストライドの長さを表しています。例えば、ストライドが4であるなら、その次元に沿って4つ置きの値をとるという意味になります。この場合にも、アクセスされた値の総数は count vector(カウントベクトル)の各要素の積になります。 .

Mapped array section (マップドアレイセクション)は subsampled array section に似ていますが、さらに index mapping vector (インデックスマッピング)が加わり、NetCDF変数に関連するデータのメモリー中の配置を指定することができます。 各値の参照値からのオフセットは 各インデックスと対応する index mapping vectorの要素を掛け合わせたものの和になります。(マッピングがされていない場合には仮想的な内部配列のインデックスが使用されます。)アクセスされた値の個数は subsampled array section の場合と同じになります。

マップされた配列断面の応用については後により詳細に述べます。その前に、より一般的な配列断面へのアクセスの例を見ましょう。

3.2.2 配列断面のアクセス例

先に扱ったNetCDFファイルの例(Network Common Data Form Language (CDL))において、あるレベル(例えば2段目)の temp 変数の全データの断面を読み取りたいとし、そしてそのNetCDFファイルには記録が3つ ( time 値)あるとます。次元は

  lat = 5, lon = 10, level = 4, time = unlimited;

と定義されます。そして、変数 temp はCDL表記においては

  float   temp(time, level, lat, lon);

と宣言されます。

対応するC変数で、ある一つのレベルのみのデータを保持しているものは、データを1次元配列に留めておくために、

#define LATS  5
#define LONS 10
#define LEVELS 1
#define TIMES 3                 /* 現在 */
    ... 
float   temp[TIMES*LEVELS*LATS*LONS];

と宣言されるかもしれません。又は、多次元配列を使って

    ... 
float   temp[TIMES][LEVELS][LATS][LONS];

と宣言されます。

第2レベルにのみある全時刻・全緯度・全経度のデータブロックを識別するためには、始点インデックスと縁の長さを与えなければなりません。始点インデックスは Cでは(0, 1, 0, 0) であるので、 time lon lat 次元については最初から開始したいのですが、 level 次元については2番目の値から開始したいわけです。 Time 値については3個全て、 level 値については1個のみ、 lat 値については5個全て、そして lon v値については10個全てを取得しいので、縁の長さは Cでは(3, 1, 5, 10) (になります。この操作によって合計150個(3*1*5*1)の不動小数点数が返されるので、これだけの数を収容するのに十分な配列スペースを 確保しなければなりません。このデータが返される順番は最も早く変化する 最後の次元 lon , になります:

     temp[0][1][0][0]
     temp[0][1][0][1]
     temp[0][1][0][2]
     temp[0][1][0][3]
 
           ...
 
     temp[2][1][4][7]
     temp[2][1][4][8]
     temp[2][1][4][9]
 

Cや FORTRANなどの異なる言語インターフェースにおける 次元の順番が異なるのはディスク上で保存されている順番が異なるからではなく、単に各言語に対する手続きインターフェースのによってサポートされいる順番が異なっているからです。 一般的に、NetCDFファイルが Cや FORTRAN、又は他の言語インターフェースで作成されていても何も変わりません。NetCDFをサポートする言語で作成されたNetCDFファイルは他の言語で書かれたプログラムを使って読み取ることができます。

3.2.3 一般的な部分アクスセスに関する追記

Mapped array sections を使用することによって変数要素のディスクアドレスとメモリ上で格納されているアドレスの間に自明ではない関係を確立することができます。 例えば、メモリ上のマトリクスはディスク上のマトリクスを移項したもので、要素が全く異なる順番で格納されるかもしれません。通常の array sectionにおいてはディスク上とメモリアドレス の関係は自明です:メモリ内値の構造(次元サイズと順番)は array sectionのものと一致しています。しかしながら、mapped array sectionにおいてはNetCDFの変数要素の指数とそれらのメモリ上のアドレスとのマッピングを定義するのに index mapping vector が使用されます。

マップ アレイアクセスによって,メモリに常駐する配列の原点とある任意の点間とのオフセット量(配列の要素の数)は index mapping vectorとその点の coordinate offset vector inner product 1 (内積)で表される。 ある任意の 点の coordinate offset vector は各次元の内包される配列の原点からその点までのオフセット量を与えます。C言語ではある点の coordinate offset vector は元のcoordinate vectorと同一です。

通常の配列部分の index mapping vector はム最も早く変化する次元から最も遅く変化する次元の順番にム常に定数1を持つはずです。なぜならば、その値と最も早く変化する次元の一辺の長さの積を取り、その値と次に早く変化する次元の一辺の長さとの積を取る、という操作を繰る返すからです。 しかし、mapped arrayにおいては, NetCDF変数のディスク上での位置とメモリ上での位置との相関は異なることもあります。

下記の C言語での定義の場合を例に取りましょう。
struct vel {
    int flags;
    float u;
    float v;
} vel[NX][NY];
ptrdiff_t imap[2] = {
    sizeof(struct vel),
    sizeof(struct vel)*NY
};

ここで、 imapは index mapping vectorであり、 メモリ上に常駐しているNetCDF変数 vel(NY,NX) にアクセスするのに使用できます。例え次元が移項されていて、データが2次元の不動小数点数ではなく2次元の配列構造を取っていても大丈夫です。

マップドアレイアクセスに関する詳しい例はマップドアレイアクセスに関するインターフェースの説明文にあります。 7.9 - マップされた配列の値を書き込む: nc_put_varm_ type.

NetCDF抽象化によって部分サンプルされた配列断面やマップドアレイセクションによるアクセスを可能ですが、 これらを使用する必要はありません。 これらのより汎用的なアクセス法が不必要な場合には、これらの機能を無視して単一値によるアクセスや通常の配列断面アクセス方法を使用してください。


1.  ベクトル [x0, x1, ..., xn] と [y0, y1, ..., yn] の内積は単にx0*y0 + x1*y1 + ... + xn*ynとなります。


Up|<<Prev|Next>>