bashnetcdfncocdo-climate

how to find the time/date of the first positive entry in a netcdf file using nco or cdo?


I have a timeseries of values and I want to find the time or date of the first timestep when the data series becomes positive. I know I can read it into a python, R or Fortran script to do it, but I was wondering if I can do it from the command line in BASH perhaps using nco or cdo?

I thought to use

cdo gec,0.0 in.nc out.nc

to make a mask but that doesn't help me much. I need somehow to split the file according to the sign of the data, and then I could simply pick up the date using

cdo showdate 

piped into awk.

There is a link to a small example file here:

http://clima-dods.ictp.it/Users/tompkins/se/trmm_per10_pc0_year2000_nc2.nc

Any tips?


Solution

  • EDITED ANSWER:

    With the new timcumsum function that has been added to CDO v1.8.0 onwards (https://code.zmaw.de/projects/cdo/embedded/index.html#x1-3300002.8.1) this task can now be accomplished for a gridded field:

    cdo gec,0 precip.nc mask.nc      # positive entries are 1, negative are zero
    cdo timcumsum mask.nc maskcum.nc # sum the mask in the time direction
    
    # invert the mask so that you have 1 at start, but then zero from 1st +ve val
    cdo lec,0.5 maskcum.nc maskinv.nc   
    
    # sum this new mask, and add 1, result is timestep when first positive value occurs:
    cdo addc,1  -timcumsum maskinc.nc stepfirstpos.nc 
    

    I think this function does it all on one line

    cdo addc,1 -timcumsum -lec,0.5 -timcumsum -gec,0 precip.nc stepfirstpos.nc
    

    ORIGINAL ANSWER:

    It took me a year but I worked out a way to do this with a combination of NCO and CDO for a single point file but not a gridded field:

    #!/bin/bash
    # code to find date of first positive file entry
    file=trmm_per10_pc0_year2000_nc2.nc
    # set negative values to missing
    cdo -s setrtomiss,-1.e36,0.0 $file set.nc
    ntime=`cdo -s ntime set.nc`  # number of steps in file
    # loop over steps to find first positive value
    for i in `seq 1 ${ntime}` ; do
      # nco counts from step 0, cdo from 1 
      ncoi=`expr $i - 1` 
      # print out the value in step i
      op=`ncks -d time,$ncoi -s "%16.10f\n" -H -C -v precip set.nc`
      if [[ $op != "_" ]] ; then  # not missing
        # print the date of timestep i
        cdo -s showdate -seltimestep,$i set.nc
        rm -f set.nc 
        exit
      fi
    done
    # no positive value found
    rm -f set.nc
    echo "All values in $file are negative"