1 | function parse_dir { |
---|
2 | # Syntax: export variables from directory $1 with structure var1/var2/.../varN ($2) |
---|
3 | # Each variable ${vari} is exported. |
---|
4 | local d=$1 s=$2 |
---|
5 | while :; do |
---|
6 | export ${s%%/*}=${d%%/*} |
---|
7 | s=${s#*/}; d=${d#*/} |
---|
8 | if [ "$s" = "${s#*/}" ]; then break; fi |
---|
9 | done |
---|
10 | } |
---|
11 | #================================================================================== |
---|
12 | function addc { |
---|
13 | local s |
---|
14 | s="$1"; while [ ${#s} -lt $2 ]; do s="_$s"; done ; echo "$s"; unset s |
---|
15 | } |
---|
16 | #================================================================================== |
---|
17 | function progress_bar { |
---|
18 | # $1: iteration $2: iterations number $3: length of the bar |
---|
19 | local n bar |
---|
20 | bar=`echo "scale=1 ; (100*$1)/$2" | bc` |
---|
21 | bar="`addc "$bar" 5`% [" |
---|
22 | n=`echo "scale=0 ; ($3*$1)/$2" | bc` |
---|
23 | if [ $n -ne 0 ]; then bar="$bar"`eval "printf '='%.0s {1..$n}"`; fi |
---|
24 | n=$(($3-$n)) |
---|
25 | if [ $n -ne 0 ]; then bar="$bar"`eval "printf '.'%.0s {1..$n}"`']\r'; fi |
---|
26 | echo -ne $bar; if [ $2 -eq $1 ]; then echo; fi |
---|
27 | unset n bar |
---|
28 | } |
---|
29 | #================================================================================== |
---|
30 | function extract { |
---|
31 | # Input arguments: |
---|
32 | # $1: v_in,v_ou (input/output variable names) |
---|
33 | # $2: f_in,f_ou (input/output files names) |
---|
34 | # $3: Ymin,Ymax,dY (min/max available years, years/file number) |
---|
35 | # $4: nmrg (number of additional months before and after) |
---|
36 | # |
---|
37 | # Purpose: |
---|
38 | # * Extract year $Y for variable $v_in from files $f_in containing data from |
---|
39 | # $Ymin to $Ymax, where each input file contains $dY years |
---|
40 | # * Outputs are stored in file $f_ou, and variable renamed $v_ou. |
---|
41 | # * Optionally, add before/after the 12 months the $nmrg previous/next months. |
---|
42 | # - Y=Ymin (missing Ymin-1) => $nmrg last months of year $Y used instead. |
---|
43 | # - Y=Ymax (missing Ymax+1) => $nmrg first months of year $Y used instead. |
---|
44 | # |
---|
45 | # Remark: First record of first file has to be january $Ymin. |
---|
46 | # |
---|
47 | local v_in v_ou d_in f_ou Ymin Ymax Yb Ye Y dY nbm nmrg it fin fou fm ff fp ib ie |
---|
48 | v_in="${1%%,*}"; v_ou="${1#*,}"; shift |
---|
49 | f_in="${1%%,*}"; f_ou="${1#*,}"; shift |
---|
50 | Ymin="${1%%,*}"; Ymax="${1#*,}"; dY="${Ymax#*,}"; Ymax="${Ymax%%,*}"; shift |
---|
51 | Y=$1; shift; if [ $# -eq 1 ]; then nmrg=$1; else nmrg=0; fi |
---|
52 | if [ $dY -eq $((Ymax-Ymin+1)) ]; then dY=0; fi #--- SINGLE FILE |
---|
53 | ff=actu_${v_in}_${Y}.nc; fm=""; fp="" |
---|
54 | #--- INITIAL AND FINAL YEAR OF FILE CONTAINING CURRENT YEAR |
---|
55 | if [ $dY -eq 0 ]; then |
---|
56 | Yb=$Ymin; Ye=$Ymax |
---|
57 | else |
---|
58 | Yb=$((dY*(Y/dY))); Ye=$((Yb+dY-1)); Ye=$(($Ye>$Ymax?$Ymax:$Ye)) |
---|
59 | fi |
---|
60 | nbm=$((12*(Ye-Yb+1)-1)) #--- MONTHS NUMBER OF CURRENT FILE |
---|
61 | it=$((12*(Y-Yb))) #--- JANUARY INDEX IN CURRENT FILE |
---|
62 | fin=`var=$v_in; Yb=$Yb; Ye=$Ye; eval echo $f_in` #--- CURRENT FILE NAME |
---|
63 | fou=`var=$v_ou; Y=$Y; eval echo $f_ou` #--- OUTPUT FILE NAME |
---|
64 | ib=$(($it<=nmrg?0:$((it-nmrg)))) #--- INDEX OF FIRST USED MONTH |
---|
65 | ie=$(($((it+11+mrg))>=$nbm?$nbm:$((it+11+nmrg)))) #--- INDEX OF LAST USED MONTHF |
---|
66 | rm -f $ff ; rm -f $ff ; ncks -d time,$ib,$ie $fin $ff |
---|
67 | #--- MISSING PREVIOUS YEAR LAST MONTHS => CURRENT YEAR INSTEAD |
---|
68 | if [ $it -lt $nmrg ]; then fm="prev_${v_in}_${Y}.nc"; rm -f $fm |
---|
69 | if [[ $Y -eq $Ymin || $dY -eq 0 ]]; then ncks -d time,$((it-nmrg+12)),11 $fin $fm |
---|
70 | else Yb=$((dY*((Y-1)/dY))); Ye=$((Yb+dY-1)); Ye=$(($Ye>$Ymax?$Ymax:$Ye)) |
---|
71 | ncks -d time,$((12*(Ye-Yb+1)-nmrg+it)),$((12*(Ye-Yb+1)-1)) `var=$v_in; Yb=$Yb; Ye=$Ye; eval echo $f_in` $fm |
---|
72 | fi |
---|
73 | fi |
---|
74 | #--- MISSING FOLLOWING YEAR FIRST MONTHS => CURRENT YEAR INSTEAD |
---|
75 | if [ $((it+nmrg+11)) -gt $nbm ]; then fp="next_${v_in}_${Y}.nc"; rm -f $fp |
---|
76 | if [[ $Y -eq $Ymax || $dY -eq 0 ]]; then ncks -d time,$((nbm-11)),$((it+nmrg-1)) $fin $fp |
---|
77 | else Yb=$((dY*((Y+1)/dY))); Ye=$((Yb+dY-1)); Ye=$(($Ye>$Ymax?$Ymax:$Ye)) |
---|
78 | ncks -d time,0,$((nmrg-1)) `var=$v_in; Yb=$Yb; Ye=$Ye; eval echo $f_in` $fp |
---|
79 | fi |
---|
80 | fi |
---|
81 | if [ ! -d ${fou%/*} ]; then mkdir -p ${fou%/*}; fi |
---|
82 | if [[ "$fm" != "" || "$fp" != "" ]]; then |
---|
83 | rm -f $fou ; ncrcat $fm $ff $fp $fou ; rm -f $fm $ff $fp |
---|
84 | else |
---|
85 | mv $ff $fou |
---|
86 | fi |
---|
87 | if [ "$v_in" != "$v_ou" ]; then |
---|
88 | ncrename -v $v_in,$v_ou $fou > /dev/null 2>&1 |
---|
89 | fi |
---|
90 | } |
---|
91 | #================================================================================== |
---|
92 | function make_clim { |
---|
93 | # Input arguments: |
---|
94 | # $1: variable name $2: input files name |
---|
95 | # $3: beg-end years $4: index for january (optional, starting from 0) |
---|
96 | # |
---|
97 | # Purpose: |
---|
98 | # Create a 12 months climatology for a variable using 1-year monthly files. |
---|
99 | # |
---|
100 | # Remark: |
---|
101 | # Files with additional months are usable if the index for january is given (default: 0) |
---|
102 | # |
---|
103 | local f_ou f0 Yb Ye ib ie M MM |
---|
104 | Yb="${3%%-*}"; Ye="${3#*-}" |
---|
105 | if [ $# -eq 4 ]; then ib=$4; else ib=0; fi; ie=$((ib+11)) #=== INDEX $ib FOR JANUARY |
---|
106 | for M in $(eval echo {$ib..$ie}); do |
---|
107 | MM=$((M+1-ib)); if [ $MM -le 9 ]; then MM=0$MM; fi |
---|
108 | for Y in `eval echo {${Yb}..${Ye}}`; do |
---|
109 | f_ou=$(var=$1; Y=$Y; eval echo $2) |
---|
110 | rm -f ${1}_$Y$MM.nc ; ncks -d time,$M $(var=$1; Y=$Y; eval echo $f_ou) ${1}_$Y$MM.nc |
---|
111 | done |
---|
112 | rm -f ${1}_$MM.nc ; ncra ${1}_????$MM.nc ${1}_$MM.nc ; rm -f ${1}_????$MM.nc |
---|
113 | progress_bar $((M+1-ib)) $((ie-ib+1)) 50 |
---|
114 | done |
---|
115 | f_ou=$(var=$1; Y=${Yb}_${Ye}_clim; eval echo $2) |
---|
116 | rm -f $f_ou ; ncrcat ${1}_??.nc $f_ou ; rm -f ${1}_??.nc |
---|
117 | f0=`var=$1; Y='YYYY'; eval echo $2`; f0=$(var=$1; Y='YYYY'; eval echo $f0); f0=${f0##*/} |
---|
118 | ncatted -a comment,global,a,c,"\nClimatology from $Yb to $Ye using file(s) $f0" $f_ou |
---|
119 | echo ">> Done for variable $1." |
---|
120 | } |
---|
121 | #================================================================================== |
---|
122 | function str2ascii() { |
---|
123 | LC_CTYPE=C printf '%d' "'$1" |
---|
124 | } |
---|
125 | |
---|
126 | #================================================================================== |
---|
127 | function deblank { |
---|
128 | #--- REMOVE UNEXPECTED CHARACTERS (IN PARTICULAR THOSE WEIRD ASCII(0) CHARS) |
---|
129 | local a |
---|
130 | a=$1; while [ `str2ascii ${a:0:1}` -lt 32 ]; do a=${a:1:${#a}}; done; echo $a |
---|
131 | } |
---|
132 | |
---|
133 | #================================================================================== |
---|
134 | function dim_nam { |
---|
135 | #--- GET DIMENSION $2 (X/Y/Z/T) NAME FOR FILE $1 |
---|
136 | #--- SPECIAL CASE: RETURN 'Seasons' IF "$2" = "S". |
---|
137 | local a v Units |
---|
138 | case $2 in |
---|
139 | X) Units='degrees_east degree_east degree_e degrees_e "degrees east" "degree east" degreee degreese' ;; |
---|
140 | Y) Units='degrees_north degree_north degree_n degrees_n "degrees north" "degree north" degreen degreesn' ;; |
---|
141 | Z) Units='pa pascal pascals hpa millibar millibars mbar mbars mb bar bars atm atms atmosphere atmospheres' ;; |
---|
142 | T) Units=' since' ;; |
---|
143 | S) echo Seasons; return 0 ;; |
---|
144 | *) echo "error in dim_nam: unrecognized axis $2"; return 1 ;; |
---|
145 | esac |
---|
146 | for u in $Units; do |
---|
147 | case $2 in |
---|
148 | X|Y|Z) a=`ncdump -h $1 | grep -i ':units = "'"$u"'"'` ;; |
---|
149 | T) a=`ncdump -h $1 | grep -i $u | grep ':units = "'` ;; |
---|
150 | esac |
---|
151 | if [ "$a" != "" ]; then |
---|
152 | if [ "$2" = "Z" ]; then v=${a%%:*}; v=`deblank $v` |
---|
153 | if [ "`ncdump -h $1 | grep -i "$v($v)"`" != "" ]; then break; fi |
---|
154 | else break |
---|
155 | fi |
---|
156 | fi |
---|
157 | done |
---|
158 | if [[ "$a" = "" && "$2" = "Z" ]]; then a=`ncdump -h $1 | grep -i ':positive = "'`; fi |
---|
159 | if [ "$a" = "" ]; then echo "error in dim_nam: unable to recognize axis $2"; return 1; fi |
---|
160 | echo ${a%%:*}; return 0 |
---|
161 | } |
---|
162 | |
---|
163 | #================================================================================== |
---|
164 | function test_var { |
---|
165 | # Input arguments: |
---|
166 | # $1: file name $2: variable name |
---|
167 | ncdump -h $1 | grep "double $2" > /dev/null; if [ $? -eq 0 ]; then return 0; fi |
---|
168 | ncdump -h $1 | grep "float $2" > /dev/null; return $? |
---|
169 | } |
---|
170 | #================================================================================== |
---|
171 | function get_boundsvar { |
---|
172 | # Input arguments: |
---|
173 | # $1: file name $2: variable name |
---|
174 | local a=$(ncdump -h $1 | grep -P "\t$2:bounds") |
---|
175 | if [ "$a" != "${a#*\"}" ]; then a=${a#*\"}; echo ${a%\"*}; else echo ""; fi |
---|
176 | } |
---|
177 | #================================================================================== |
---|
178 | function rename_bounds { |
---|
179 | # Input arguments: |
---|
180 | # $1: file name $2: variable name $3: new variable name |
---|
181 | # returns: $old_var,$old_boundvar,$new_boundvar |
---|
182 | local vin=$(get_boundsvar $1 $2) beg end vou |
---|
183 | if [ "$vin" = "" ]; then return 1; fi |
---|
184 | beg=${vin##*$2}; if [ "$beg" = "$vin" ]; then beg=$vin; fi |
---|
185 | beg=${vin%%$2*}; if [ "$end" = "$vin" ]; then end=$vin; fi |
---|
186 | if [[ "$beg" = "" && "$end" = "" ]]; then return 1; fi |
---|
187 | vou=$beg$3$end |
---|
188 | echo "$2,$vin,$vou" |
---|
189 | } |
---|
190 | #================================================================================== |
---|
191 | function rename_dims { |
---|
192 | # Input arguments: |
---|
193 | # $1: file name $2...: <axis>:<target_name> (axis=X,Y,Z or T) |
---|
194 | # |
---|
195 | # Purpose: |
---|
196 | # Rename dimensions, dimensional variables. |
---|
197 | # In case of boundary grid variables with bounds_<variable> names are available, |
---|
198 | # they are renamed together with the corresponding "bounds" attributes. |
---|
199 | local vio f=$1 att="" ren="" nam_in nam_ou |
---|
200 | shift |
---|
201 | while [ $# -ge 1 ]; do |
---|
202 | nam_ou=${1##*:}; nam_in=$(dim_nam $f ${1%:*}); shift |
---|
203 | if [ "$nam_in" != "$nam_ou" ]; then |
---|
204 | ren="$ren -d $nam_in,$nam_ou -v $nam_in,$nam_ou" |
---|
205 | #--- CHECK WETHER "bounds" ATTRIBUTE IS THERE |
---|
206 | vio="$(rename_bounds $f $nam_in $nam_ou)" |
---|
207 | if [ "$vio" != "" ]; then |
---|
208 | att="$att -a bounds,$nam_ou,m,c,${vio##*,}"; ren="$ren -v ${vio#*,}" |
---|
209 | fi |
---|
210 | fi |
---|
211 | done |
---|
212 | if [ "$ren" != "" ]; then ncrename $ren $f 2>&1 > /dev/null ; fi |
---|
213 | if [ "$att" != "" ]; then ncatted $att $f 2>&1 > /dev/null ; fi |
---|
214 | } |
---|
215 | #================================================================================== |
---|
216 | function zonal_mean { |
---|
217 | # Input arguments: |
---|
218 | # $1: input file $2: output file |
---|
219 | local tmp=tmp.$$.nc |
---|
220 | ncwa -a longitude $1 $tmp ; mv $tmp $2 #--- Zonal mean |
---|
221 | ncks -O -x -v longitude $2 $tmp ; mv $tmp $2 #--- Remove longitude |
---|
222 | v="bounds_longitude"; test_var $2 $v #--- Remove bounds vars |
---|
223 | if [ $? -eq 0 ]; then ncks -O -x -v $v $2 $tmp ; mv $tmp $2; fi |
---|
224 | } |
---|
225 | #================================================================================== |
---|
226 | function get_date { |
---|
227 | # $1: varname $2: datatype $3: dirin $4:...: files_in |
---|
228 | # Assumes the following filename structure: *_${Yb}*-${Ye}*.* (Yb/e: 4 digits) |
---|
229 | local v_in dtyp d_in f_in ixf Yb Ye St a f first dates |
---|
230 | v_in=$1; shift; dtyp=$1; shift; d_in=$1; shift |
---|
231 | for f_in in $@; do parse_dir ${f_in} $DIRSTRUCT; Yb=1000000; Ye=0; first='t' |
---|
232 | #=== /!\ ERROR IN THE STORAGE TREE ON CICLAD FOR PCMDI-AMIP-1-1-0 |
---|
233 | if [ $dataset = "PCMDI-AMIP-1-1-0" ]; then grid='gs1x1'; fi |
---|
234 | for f in $(var=$v_in; Yb=????; Ye=????; datatype=$dtyp; eval echo $d_in/$f_in); do |
---|
235 | a=${f##*_}; if [ ${a::4} -le $Yb ]; then Yb=${a::4}; fi |
---|
236 | a=${a##*-}; if [ ${a::4} -ge $Ye ]; then Ye=${a::4}; fi |
---|
237 | if [ $first = 't' ]; then St=$((Ye-Yb+1)); first='f'; fi |
---|
238 | done |
---|
239 | if [ $f_in = $1 ]; then dates="$Yb-$Ye-$St"; else dates="$dates $Yb-$Ye-$St"; fi |
---|
240 | done |
---|
241 | echo $dates |
---|
242 | } |
---|
243 | #================================================================================== |
---|
244 | function dim_len { |
---|
245 | local n |
---|
246 | if [ "$2" = "T" ]; then |
---|
247 | n=$(ncdump -h $1 | grep 'UNLIMITED'); n=${n#*// (}; echo ${n% currently*} |
---|
248 | else |
---|
249 | n=$(ncdump -h $1 | grep $2' = '); n=${n#* = }; echo ${n% ;*} |
---|
250 | fi |
---|
251 | } |
---|
252 | #================================================================================== |
---|
253 | function get_grid { |
---|
254 | # $1: filename $2: varname |
---|
255 | X=$(dim_nam $1 X); if [ $? -ne 0 ]; then X=""; else lX=$(dim_len $1 $X); fi |
---|
256 | Y=$(dim_nam $1 Y); if [ $? -ne 0 ]; then Y=""; else lY=$(dim_len $1 $Y); fi |
---|
257 | Z=$(dim_nam $1 Z); if [ $? -ne 0 ]; then Z=""; else lZ=$(dim_len $1 $Z); fi |
---|
258 | T=$(dim_nam $1 T); if [ $? -ne 0 ]; then T=""; else lT=$(dim_len $1 T); fi |
---|
259 | t=$(ncdump -h $1 | grep "double $2") |
---|
260 | if [ $? -ne 0 ]; then t=$(ncdump -h $1 | grep "float $2"); fi |
---|
261 | t=${t##*$2(}; t=${t%)*}; g=""; r="" |
---|
262 | while :; do s=${t##*, }; t=${t%,*} |
---|
263 | case $s in |
---|
264 | $X) g=${g}X; r=${r}x$lX ;; |
---|
265 | $Y) g=${g}Y; r=${r}x$lY ;; |
---|
266 | $Z) g=${g}Z; r=${r}x$lZ ;; |
---|
267 | $T) g=${g}T; r=${r}x$lT ;; |
---|
268 | esac |
---|
269 | if [ "$s" = "$t" ]; then break; fi |
---|
270 | done |
---|
271 | echo $g=${r:1:${#r}} |
---|
272 | } |
---|
273 | #================================================================================== |
---|
274 | |
---|