1

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?

ClimateUnboxed
  • 7,106
  • 3
  • 41
  • 86

2 Answers2

2

Ive racked my brain and can think of no silver bullet witn NCO. I've come up with the following snippet for ncap2. ( loops are unoptimized in ncap2 ) to run the snippet use the command

ncap2 -v -O -S sign.nco  trmm_per10_pc0_year2000_nc2.nc foo.nc out.nc

/****************** sign.nco***********************************/
lon_sz=$lon.size;
lat_sz=$lat.size;
time_sz=$time.size;
*precip_prev=precip(0,0,0);
*precip_cur=2.0;
for(*idx=0;idx<time_sz;idx++)
{
   for(*jdx=0;jdx<lat_sz;jdx++)
   {

     for(*kdx=0;kdx<lon_sz;kdx++)
     {
      precip_cur= precip(idx,jdx,kdx);
      if( precip_cur > 0.0 && precip_prev<0.0)
         print(time(idx));

         precip_prev=precip_cur;

    }
  }
}
/***************************************************************/
  • Thanks for this, but it doesn't seem to work on bash on my MAC, I get this as the output: "time, size = 1 NC_DOUBLE, value = 29769" - I'm not sure I understand the code snippet. – ClimateUnboxed May 05 '17 at 16:24
0

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"
ClimateUnboxed
  • 7,106
  • 3
  • 41
  • 86