Next: , Previous: Left hand casting, Up: ncap2 netCDF Arithmetic Processor


4.1.5 Arrays and hyperslabs

Generating a regularly spaced one-dimensional array with ncap2 is simple with the array() function. The syntax is

     output=array(val_srt,val_ncr,$dmn_nm); // One-dimensional output
     output=array(val_srt,val_ncr,var_tpl);  // Multi-dimensional output
     h

where the arguments are the starting value val_srt, incremental value val_ncr, and, for one-dimensional output, the single dimension $dmn_nm, or, for multi-dimensional output, a template variable var_tpl, i.e., a variable with the same shape as the desired output.

Once the associated dimensions have been defined, the start and increment arguments may be supplied as values, mathmatical expressions, or variables:

     var_out=array(1,1,$time); // 1,2,3,4,5,6,7,8,9,10
     var_out=array(1+2-2,one,$time); // 1,2,3,4,5,6,7,8,9,10
     var_out=array(1,2,three_dmn_rec_var); // 1,3,5,...155,157,159

Hyperslabs in ncap2 are more limited than hyperslabs with the other NCO operators. ncap2 does not understand the shell command-line syntax used to specify multi-slabs, wrapped co-ordinates, negative stride or coordinate value limits. However with a bit of syntactic magic they are all are possible. ncap2 accepts (in fact, it requires) N-hyperslab arguments for a variable of rank N:

     var1(arg1,arg2 ... argN);

where each hyperslab argument is of the form

     start:end:stride

and the arguments for different dimensions are separated by commas. If "start" is omitted, it defaults to 0. If "end" is omitted, it defaults to dimension size minus one. If "stride" is omitted, it defaults to 1.


If a single value is present then it is assumed that that dimension collapses to a single value (i.e., a cross-section). The number of hyperslab arguments MUST equal the variable's rank.

Hyperslabs on the Right Hand Side of an assign

A simple 1D example:

     ($time.size=10)
     od[$time]={20,22,24,26,28,30,32,34,36,38};
     
     od(7);     // 34
     od(7:);    // 34,36,38
     od(:7);    // 20,22,24,26,28,30,32,34
     od(::4);   // 20,28,36
     od(1:6:2)  // 22,26,30
     od(:)      // 20,22,24,26,28,30,32,34,36,38

A more complex three dimensional example:

     ($lat.size=2,$lon.size=4)
     th[$time,$lat,$lon]=
                               {1, 2, 3, 4, 5, 6, 7, 8,
                               9,10,11,12,13,14,15,16,
                               17,18,19,20,21,22,23,24,
                               -99,-99,-99,-99,-99,-99,-99,-99,
                               33,34,35,36,37,38,39,40,
                               41,42,43,44,45,46,47,48,
                               49,50,51,52,53,54,55,56,
                               -99,58,59,60,61,62,63,64,
                               65,66,67,68,69,70,71,72,
                               -99,74,75,76,77,78,79,-99 };
     
     th(1,1,3);        // 16
     th(2,0,:);        // 17, 18, 19, 20
     th(:,1,3);        // 8, 16, 24, -99, 40, 48, 56, 64, 72, -99
     th(::5 ,:,0:3:2); // 1, 3, 5, 7, 41, 43, 45, 47

If hyperslab arguments collapse to a single value (a cross-section has been specified), then that dimension is removed from the returned variable. If all the values collapse then a scalar variable is returned. So, for example, the following is valid:

     th_nw=th(0,:,:)+th(9,:,:);
     // th_nw has dimensions $lon,$lat
     // NB: the time dimension has become degenerate

The following is invalid:

     th_nw=th(0,:,0:1)+th(9,:,0:1);

because the $lon dimension now only has two elements. The above can be calculated by using a LHS cast with $lon_nw as replacement dim for $lon:

     defdim("lon_nw",2);
     th_nw[$lat,$lon_nw]=th(0,:,0:1) +th(9,:,0:1);

Hyperslabs on the Left Hand Side of an assign
When hyperslabing on the LHS, the expression on the RHS must evaluate to a scalar or a variable/attribute with the same number of elements as the LHS hyperslab. Set all elements of the last record to zero:

     th(9,:,:)=0.0;

Set first element of each lon element to 1.0:

     th(:,:,0)=1.0;

One may hyperslab on both sides of an assign. For example, this sets the last record to the first record:

     th(9,:,:)=th(0,:,:);

Say th0 represents pressure at height=0 and th1 represents pressure at height=1. Then it is possible to insert these hyperslabs into the records

     prs[$time,$height,$lat,$lon]=0.0;
     prs(:,0,:,:)=th0;
     prs(:,1,:,:)=th1

Reverse method
Use the reverse() method to reverse a dimension's elements in a variable with at least one dimension. This is equivalent to a negative stride, e.g.,

     th_rv=th(1 ,:,:).reverse($lon); // {12,11,10,9 }, {16,15,14,13}
     od_rv=od.reverse($time);        // {38,36,34,32,30,28,26,24,22,20}

Permute method
Use the permute() method to swap the dimensions of a variable. The number and names of dimension arguments must match the dimensions in the variable. If the first dimension in the variable is of record type then this must remain the first dimension. If you want to change the record dimension then consider using ncpdq.

Consider the variable:

     float three_dmn_var(lat,lev,lon);
     three_dmn_var_prm=three_dmn_var.permute($lon,$lat,$lev);
     // The permuted values are
     three_dmn_var_prm=
       0,4,8,
       12,16,20,
       1,5,9,
       13,17,21,
       2,6,10,
       14,18,22,
       3,7,11,
       15,19,23;