NetCDF re-ordering dimension - netcdf

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.

Related

Merge two ASCII DEC values together and convert to int

i have two DEC variables and i would like to merge them like this:
unsigned int first_dig = 57; // Number 9
unsigned int second_dig = 52; // Number 4
unsigned int all_dig = 0;
Now i want to save them in all_dig. I already tried to shift bytes but it ends up in a Mess
all_dig = ((first_dig<<8)|second_dig); // prints 14644
I want all_dig to contain 94. Is there a simpler way? I would like to use the same concept for three digits too.
Thanks already for the help
For two digits, d_1, d_0:
res = (d_1 - '0') * 10 + (d_0 - '0')
For three digits, d_2, d_1, d_0:
res = (d_2 - '0') * 100 + (d_1 - '0') * 10 + (d_0 - '0')
Notice that the expression is only valid if
'0' <= d_i <= '9' for each d_i
If that were not the case, the result wouldn't be correct.

CDO/NCO - Replicate dataset over a dimension

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

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

How do I make a three-dimensional plot correctly in Scilab?

I am trying to make a plot of three column vectors right now in order to make a three dimensional surface plot, but the output is just a discontinuous line. Any help is appreciated, code is below. Apologies in advance for the confusing variable names.
co = 29;
BF = .0446;
WPW = 50;
E = [0:0.01:2]; //sets up a column vector
p = [];
WBR =[];
w = [];
t = 8.64E13;
delta = [0:0.5:100];
R =[];
DeltaMu = [];
Total = [];
//begin program iteration through k; change "k" value in for loop to change
//the number of iterations the program runs over, and thus the amount
//of degrees of freedom
k = 200;
for i = 1:k,
I = 12.5 + 0.167*i;
mu = I/co;
sigma = .11*mu;
cdf = cdfnor("PQ", E, mu*ones(E), sigma*ones(E));
n = 201; // variable over which the loop is iterated
pdf = zeros(201,1); // sets up an appendable matrix of all zeros
temp = 0; //initiates a temporary integer variable
while n > 1,
temp = cdf(n) - cdf(n-1); //assigns a value to the temp variable every pass
pdf(n) = temp; //assigns the temp value to the nth slot in the
//column vector, works through the matrix backwards
n = n-1; //iterates the while loop on n
end //breaks from while loop after n hits 1
temp = cdf(n);
pdf(n) = temp;
n = 201;
while n > 1,
a = exp(-WPW*exp(-delta(n)*(1-E)));
n = n-1;
end
n = 201; // variable over which the loop is iterated
prob = zeros(201,1); // sets up an appendable matrix of all zeros
temp = 0; //initiates a temporary integer variable
while n > 1,
temp = a(n)*pdf(n); //assigns a value to the temp variable every pass
prob(n) = temp; //assigns the temp value to the nth slot in the
//column vector, works through the matrix backwards
n = n-1; //iterates the while loop on n
end //breaks from while loop after n hits 1
WBR(i) = sum(prob)*BF
w(i) = mu
end
//begin program iteration through k; change "k" value in for loop to change
//the number of iterations the program runs over, and thus the amount
//of degrees of freedom
k = 200;
for i = 1:k,
mu = .5*i;
sigma = .1*mu;
cdf = cdfnor("PQ", delta, mu*ones(delta), sigma*ones(delta));
n = 201; // variable over which the loop is iterated
pdf = zeros(201,1); // sets up an appendable matrix of all zeros
temp = 0; //initiates a temporary integer variable
while n > 1,
temp = cdf(n) - cdf(n-1); //assigns a value to the temp variable every pass
pdf(n) = temp; //assigns the temp value to the nth slot in the
//column vector, works through the matrix backwards
n = n-1; //iterates the while loop on n
end //breaks from while loop after n hits 1
temp = cdf(n);
p = 1-(exp(-t*exp(-delta)));
n = 201; // variable over which the loop is iterated
Psw = zeros(201,1); // sets up an appendable matrix of all zeros
temp = 0; //initiates a temporary integer variable
while n > 1,
temp = p(n)*pdf(n); //assigns a value to the temp variable every pass
Psw(n) = temp; //assigns the temp value to the nth slot in the
//column vector, works through the matrix backwards
n = n-1; //iterates the while loop on n
end //breaks from while loop after n hits 1
R(i) = sum(Psw)
DeltaMu(i) = mu
end
n = 200;
while n > 1,
Total(n) = WBR(n) + R(n);
n = n-1;
end
xdel(winsid()); //close any open graphs
plot3d(WBR, R, Total)
To plot a surface with plot3d, you need:
a vector of x-values
a vector of y-values
a matrix of z-values, where the (i,j) entry will determine the height over the point (x(i),y(j))
Toy example:
plot3d([1 2 3], [2 3 4], [0 1 2; 2 3 2; 0 2 1])
There is no mathematically reasonable to make a surface plot from three column vectors. What you could do with them is draw a parametric curve, which uses three vectors for x,y,z coordinates:
param3d(WBR, R, Total)
With your data, the result is still unspectacular because of the high dynamic range with the arrays. Consider plotting on the logarithmic scale.

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