5

I want to set all values below a constant c to c itself in a netcdf file: file.nc

A solution using climate data operators (CDO) would be

cdo mul -gec,$c file.nc file.nc t1.nc
cdo add -mulc,$c -ltc,$c file.nc t1.nc output.nc
rm -f t1.nc

But is there a neater/shorter way to do this?

ClimateUnboxed
  • 7,106
  • 3
  • 41
  • 86

5 Answers5

6

You can use NCO's ncap2 to do this easily.

For example, set all values of x below 100 to 100 in file.nc and output in file2.nc:

>>> ncap2 -s 'where(x<100.) x=100;' file.nc -O file2.nc 
N1B4
  • 3,377
  • 1
  • 21
  • 24
6

ncap2's clipping operator is most concise:

ncap2 -s 'x=x>>100' in.nc out.nc
Charlie Zender
  • 5,929
  • 14
  • 19
  • this command works but silently transforms the data from e.g. float to double (ncap2 version 4.3.7) – Chris Mar 25 '20 at 18:03
  • That's a pretty old version. Works fine (float stays as float) with current version. Just tried it. – Charlie Zender Mar 26 '20 at 19:51
  • @CharlieZender consider that I have a large NETCDF with many timesteps. The above will result in memory issues. How can one apply the above line of code to 1 timestep at a time without reading the whole data file to perform the above operation? – code123 Aug 12 '20 at 17:05
  • You could try clipping N slices at a time using ncap2's array syntax which is described in the manual. If that does not work then you can split the file with ncks, clip with ncap2, and reassemble with ncrcat. – Charlie Zender Aug 13 '20 at 19:36
2

To set all values below $c to $c, you could use the setrtoc command of Climate Data Operators (cdo).

cdo setrtoc,-inf,$c,$c infile.nc outfile.nc

The command will set all values in the range between -inf (minus infinity) and $c to $c. Additional information on the setrtoc operator can be found in the CDO manual in Section 2.15.7.

ClimateUnboxed
  • 7,106
  • 3
  • 41
  • 86
Andreas
  • 21
  • 1
1

Using Python with NumPy and netCDF4 you could do the following:

import numpy as np
from netCDF4 import Dataset

dataset = Dataset('/path/to/dataset','r+')

data = dataset.variables['data_variable_name'][:]

threshold = 100 # or whatever your constant c is

# np.where(condition, value if true, value if false)
new_data = np.where(data < threshold, threshold, data)

# Write your new data back to the NetCDF file
dataset.variables['data_variable_name'][:] = new_data[:]

dataset.close()

Good luck!

AvlWx
  • 291
  • 3
  • 9
1

There is also a more efficient way to do this with the Climate Data Operator (CDO) using the expr. Adapting the example from this post to the specific example from this question, assuming that the name of the variable is x and the constant is c, then the command would be something like this:

cdo -expr,'x = ((x > c)) ? x : c' infile.nc outfile.nc

Where ? and : are ternary conditional operators, and x ? y : z, means y if x not equal 0, else z. Additional information related to operators and expressions are available on the CDO Manual, section 2.7.1.

ClimateUnboxed
  • 7,106
  • 3
  • 41
  • 86
Nemesi
  • 781
  • 3
  • 13
  • 29