CDO/NCO - Replicate dataset over a dimension - netcdf

I have several variables defined as follows:
dimensions:
t = UNLIMITED ; // (1 currently)
y = 3963 ;
x = 5762 ;
myz = 1 ;
z = 98 ;
variables:
float e1u(t, y, x, myz) ;
float e1v(t, y, x, myz) ;
float e2v(t, y, x, myz) ;
float e2u(t, y, x, myz) ;
float nav_lev(z) ;
I'd like to define the e1u variable over the z dimension, by replicating the (x,y) grid for all the 98 levels. Is there a cdo/nco command to accomplish that?
Thanks!

ncap2 -s 'e1uz[t,y,x,myz,z]=e1u' in.nc out.nc # This replicates over z
ncks -O -x -v e1u out.nc out.nc # Delete original e1u variable
ncrename -v e1uz,e1u out.nc # Rename to original name

Related

NetCDF re-ordering dimension

I have 1 netCDF file with a variable ppt and three dimension ppt(time,lat,lon). See below:
dimensions:
time = UNLIMITED ; // (756 currently)
lon = 55 ;
lat = 60 ;
variables:
double time(time) ;
time:standard_name = "time" ;
time:long_name = "time" ;
time:units = "days since 1900-01-01 00:00:00" ;
time:calendar = "gregorian" ;
time:axis = "T" ;
double lon(lon) ;
lon:standard_name = "longitude" ;
lon:long_name = "longitude" ;
lon:units = "degrees_east" ;
lon:axis = "X" ;
double lat(lat) ;
lat:standard_name = "latitude" ;
lat:long_name = "latitude" ;
lat:units = "degrees_north" ;
lat:axis = "Y" ;
int ppt(time, lat, lon) ;
ppt:standard_name = "precipitation_amount" ;
ppt:long_name = "precipitation_amount" ;
ppt:units = "mm" ;
ppt:add_offset = 0. ;
ppt:scale_factor = 0.1 ;
ppt:_FillValue = -2147483648 ;
ppt:missing_value = -2147483648 ;
ppt:description = "Accumulated Precipitation" ;
ppt:dimensions = "lon lat time" ;
ppt:coordinate_system = "WGS84,EPSG:4326" ;
I would like re-order the dimension from time,lat,lon to lat,lon,time.
I use command: ncpdq -a lat,lon,time in.nc out.nc
After re-ordering the variables, the lat dimension becomes UNLIMITED which is wrong. The time dimension should be the UNLIMITED dimension.
dimensions:
time = 756 ;
lon = 55 ;
lat = UNLIMITED ; // (60 currently)
...
...
int ppt(lat, lon, time) ;
Then I tried to fix the lat dimension who becomes UNLIMITED using ncks command below:
ncks --fix_rec_dmn lat out.nc out1.nc
It's worked, see below:
dimensions:
lat = 60 ;
lon = 55 ;
time = 756 ;
Now I would like to make UNLIMITED the time dimension again using ncks command below:
ncks --fix_rec_dmn time out1.nc out2.nc
Unfortunately nothing happen, the result remain same. See below:
dimensions:
lat = 60 ;
lon = 55 ;
time = 756 ;
My question, how to make UNLIMITED the time dimension again?
I found similar problem and answer from https://stackoverflow.com/a/55883675/10874805
My mistake, to make UNLIMITED the time dimension, I must use --mk_rec_dmn instead of --fix_rec_dmn
So the code should be: ncks --mk_rec_dmn time out1.nc out2.nc
In netCDF3 files, variables can only have the unlimited dimension, if any, as their first dimension. netCDF4 relaxes this restriction, so if you want the record dimension in a position other than the most rapidly varying dimension, you must ensure the output is a netCDF4 file.

renaming dimension in netcdf file

I am a beginner with nco and I would appreciate some advice on my workflow and some help with a problem I an struggling with.
I have these data which contain 3D salinity values at two different time steps:
dimensions:
t = 780 ;
z = 54 ;
y = 450 ;
x = 3600 ;
variables:
double time(t) ;
time:units = "days since 1-1-1 00:00:0.0" ;
float level(z) ;
level:units = "[m]" ;
float lat(y) ;
float lon(x) ;
float salt(x, y, z) ;
salt:units = "psu * 1000 + 35" ;
salt:missingvalue = "-1.0E34" ;
salt:longname = "salinity" ;
I want to concatenate the two netcdf files.
To do so I first use ncecat *.nc -O merged.nc:
dimensions:
record = UNLIMITED ; // (2 currently)
t = 780 ;
z = 54 ;
y = 450 ;
x = 3600 ;
variables:
double time(record, t) ;
time:units = "days since 1-1-1 00:00:0.0" ;
float level(record, z) ;
level:units = "[m]" ;
float lat(record, y) ;
float lon(record, x) ;
float salt(record, x, y, z) ;
salt:units = "psu * 1000 + 35" ;
salt:missingvalue = "-1.0E34" ;
salt:longname = "salinity" ;
where now the variable time and dimension t are spurious. So, I delete them with ncks -O -x -v time merged.nc merged.nc:
record = UNLIMITED ; // (2 currently)
y = 450 ;
z = 54 ;
x = 3600 ;
variables:
float lat(record, y) ;
float level(record, z) ;
level:units = "[m]" ;
float lon(record, x) ;
float salt(record, x, y, z) ;
salt:units = "psu * 1000 + 35" ;
salt:missingvalue = "-1.0E34" ;
salt:longname = "salinity" ;
Now, I want to rename the dimension record with: ncrename -d record,time merged.nc. The command runs with no errors or warnings. But when I do ncdump -h merged.nc I get this error:
ncdump: merged.nc: NetCDF: HDF error
What does this mean? Where do I do wrong?
EDIT
Following the answer posted by Charlie Zender
ncecat -O -u time *.nc merged.nc
ncks -O -x -v time merged.nc merged.nc
result in:
dimensions:
time = UNLIMITED ; // (2 currently)
y = 450 ;
z = 54 ;
x = 3600 ;
t = 780 ;
variables:
float lat(time, y) ;
float level(time, z) ;
level:units = "[m]" ;
float lon(time, x) ;
float salt(time, x, y, z) ;
salt:units = "psu * 1000 + 35" ;
salt:missingvalue = "-1.0E34" ;
salt:longname = "salinity" ;
double time(time, t) ;
time:units = "days since 1-1-1 00:00:0.0" ;
// global attributes:
:history = "Tue Jun 5 09:08:25 2018: ncks -O -x -v time merged.nc merged.nc\nTue Jun 5 09:08:19 2018: ncecat -O -u time OFES_salt_mmean_607.nc OFES_salt_mmean_608.nc merged.nc" ;
:NCO = "netCDF Operators version 4.7.4 (http://nco.sf.net)" ;
:nco_openmp_thread_number = 1 ;
Firstly, the command I recommend is
ncecat -O -u time *.nc merged.nc
That prevents the need to rename record to time. Then
ncks -O -x -v time merged.nc merged.nc
Does that work?
Answer to EDITed question:
Regarding the error received with ncrename, you may have encountered a netCDF4 library bug described here. The recommended solution is to convert to netCDF3, rename, then convert back to netCDF4 if desired:
ncks -3 in.nc out.nc
ncrename -d record,time out.nc
ncks -4 out.nc out.nc

Plotting a chain of spheres with gnuplot

From a function in C++ I get in a file the coordinates of the centers of a chain of spheres (of constant radius r). I would like to plot this chain with gnuplot. How can I represent the spheres with the true radius? This solution actually does not work, since the unit of pointsize is not the same as that of the axis (and is also changing with the axis limits).
This a slightly dirty solution which uses parametric (and some commands from Unix). For each line of the following data, we will plot a sphere with radius r, and centered at (x,y,z):
# points.dat :
# x y z radius
0 0 0 0.5
1 2 2 1.0
3 4 5 0.7
2 5 7 1.0
1 3 4 0.75
2 0 1 1.5
In other words, we will run commands with the form:
splot x1+r1*cos(v)*cos(u), y1+r1*cos(v)*sin(u), z1+r1*sin(v) title "line 1",\
x2+r2*cos(v)*cos(u), y2+r2*cos(v)*sin(u), z2+r2*sin(v) title "line 2", ...
The following code will do the trick (comments through the script):
set view equal xyz # to scale the axes of the plot
set hidden3d front # draw opaque spheres
set parametric # enable parametric mode with angles (u,v)
set urange [0:2*pi]
set vrange [-pi/2.0:pi/2.0]
filename = 'spheres.dat'
# get number of data-lines in filename
nlines = system(sprintf('grep -v ^# %s | wc -l', filename))
# this will save the plot commands
commands = 'splot '
do for [i=1:nlines] {
# get the i-th line
line = system( sprintf('grep -v ^# %s | awk "NR == %i {print; exit}" ', filename, i) )
# extract the data
x = word(line,1)
y = word(line,2)
z = word(line,3)
r = word(line,4)
# and save the instructions to plot the corresponding sphere
commands = commands . sprintf('%s + %s*cos(v)*cos(u), %s + %s*cos(v)*sin(u), %s + %s*sin(v) t "line %i"', x, r, y, r, z, r, i)
# if not EOF, add a comma to commands
if(i<nlines) { commands = commands . ', ' }
}
# commands is a string. We can run it into the command line through macros
set macros
#commands
This is the output I obtain:

How to store vertices positions of a hexgrid in a 2D Array?

Im facing this issue. I want to create an hexgrid and be able to create in this fashion:
//grid extents
int numCols,numRows;
for (int i=0; i<numCols; ++i){
for (int j=0; j<numRows; ++j){
//x and y coordinates of my hexagon's vertices
float xpos,ypos;
//2D array storing verteces of my hextopology
vertices[i][j] = new VertexClass(xpos, ypos);
// statements to change xpos/ypos and create hex
}
}
All methods I found to make hexgrid, first create an hex object and then replicate it over a grid thus creating duplicate verteces position ad joining edges. I want to avoid duplicating verteces position. How can I declare statements to make such a grid?
Thanks
Let L be length of hexagon side, and let index vertices in column i and row `j in this way:
i 0 0 1 1 2 2 3...
j \ / \ /
0 . A---o . . o---o
/ \ / \
/ \ /
/ \ /
1 -o . . o---o .
\ / \
\ / \
\ / \ /
2 . o---o . . o---o
/ \ / \
and let (x,y) be coordinate of vertex A (top-left).
Than y coordinate of each row is moved for L*sqrt(3)/2. X coordinate is quite easy to calculate if we look points in hexagon on distance L/4 in x direction from vertices. These points (marked with dots) make lattice with distance L*3/2 in X direction.
Than:
vertices[i][j] = Vertex( x - L/4 + i*L*3/2 + L/4*(-1)^(i+j), y - j*L*sqrt(3)/2 )
The indices of the vertices in one hexagon are of type: (i,j), (i+1,j), (i+1,j+1), (i+1,j+2), (i,j+2), (i,j+1).

Assembly 8x8 four quadrant multiply algorithm

In the book "Musical Applications of Microprocessors," the author gives the following algorithm to do a 4 quadrant multiplication of two 8 bit signed integers with a 16 bit signed result:
Do an unsigned multiply on the raw operands. Then to correct the result, if the multiplicand sign is negative, unsigned single precision subtract the multiplier from the top 8 bits of the raw 16 bit result. If the multiplier sign is also negative, unsigned single precision subtract the multiplicand from the top 8 bits of the raw 16 bit result.
I tried implementing this in assembler and can't seem to get it to work. For example, if I unsigned multiply -2 times -2 the raw result in binary is B11111100.00000100. When I subtract B1111110 twice from the top 8 bits according to the algorithm, I get B11111110.00000100, not B00000000.00000100 as one would want. Thanks for any insight into where I might be going wrong!
Edit - code:
#define smultfix(a,b) \
({ \
int16_t sproduct; \
int8_t smultiplier = a, smultiplicand = b; \
uint16_t uproduct = umultfix(smultiplier,smultiplicand);\
asm volatile ( \
"add %2, r1 \n\t" \
"brpl smult_"QUOTE(__LINE__)"\n\t" \
"sec \n\t" \
"sbc %B3, %1 \n\t" \
"smult_"QUOTE(__LINE__)": add %1, r1 \n\t" \
"brpl send_"QUOTE(__LINE__)" \n\t" \
"sec \n\t" \
"sbc %B3, %2 \n\t" \
"send_"QUOTE(__LINE__)": movw %A0,%A3 \n\t" \
:"=&r" (sproduct):"a" (smultiplier), "a" (smultiplicand), "a" (uproduct)\
); \
sproduct; \
})
Edit:
You got the subtraction wrong.
1111'1110b * 1111'1110b == 1111'1100'0000'0100b
-1111'1110'0000'0000b
-1111'1110'0000'0000b
---------------------
100b
Otherwise your algorithm is correct: In the fourth quadrant, you need to subtract 100h multiplied with the sum (a+b). Writing the two-complement bytes as (100h-x) I get:
(100h-a)(100h-b) = 10000h - 100h*(a+b) + ab = 100h*(100h-a) + 100h*(100h-b) + ab mod 10000h
(100h-a)(100h-b) - 100h*(100h-a) - 100*(100h-b) = ab mod 10000h
When I subtract B1111110 twice from
the top 8 bits according to the
algorithm, I get B11111110.00000100,
not B00000000.00000100 as one would
want.
If I subtract B11111110 twice from B11111100, I get B00000000, as required:
B11111100 - B11111110 = B11111110
B11111110 - B11111110 = B00000000
Seems simple enough.

Resources