*************************************************************************************** * $Id: monmask.gs,v 1.32 2019/02/27 21:44:04 bguan Exp $ * * Copyright (c) 2013-2017, Bin Guan * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this * list of conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. *************************************************************************************** function monmask(arg) * * Create mask for specified calendar months. * rc=gsfallow('on') * Define system temporary directory. tmpdir='/tmp' * Get username and create user-specific temporary directory. '!echo $USER > .bGASL.txt' rc=read('.bGASL.txt') while(sublin(rc,1)) '!echo $USER > .bGASL.txt' rc=read('.bGASL.txt') endwhile user=sublin(rc,2) '!rm .bGASL.txt' mytmpdir=tmpdir'/bGASL-'user '!mkdir -p 'mytmpdir * Get process ID. pidlock=mytmpdir'/pid.lock' pidfile=mytmpdir'/pid.txt' '!while true; do if mkdir 'pidlock'; then break; else echo System busy. Please wait...; sleep 1; fi; done 2> /dev/null' '!echo $PPID > 'pidfile rc=read(pidfile) randnum=sublin(rc,2) '!rm -r 'pidlock mon_s=subwrd(arg,1) mon_e=subwrd(arg,2) mask=subwrd(arg,3) month=subwrd(arg,4) if(mask='') usage() return endif if(!valnum(mon_s)) say '[monmask ERROR] must be numeric.' return endif if(!valnum(mon_e)) say '[monmask ERROR] must be numeric.' return endif mon.JAN=1 mon.FEB=2 mon.MAR=3 mon.APR=4 mon.MAY=5 mon.JUN=6 mon.JUL=7 mon.AUG=8 mon.SEP=9 mon.OCT=10 mon.NOV=11 mon.DEC=12 qdims(1,'mydim') * * Write .dat file. * 'set x '_.mydim.xs 'set y '_.mydim.ys 'set z '_.mydim.zs 'set gxout fwrite' 'set fwrite 'mytmpdir'/monmask.dat.'randnum cnt=_.mydim.ts while(cnt<=_.mydim.te) 'set t 'cnt 'query dims' line5=sublin(result,5) time_str=subwrd(line5,6) len=strlen(time_str) MMM=substr(time_str,len-6,3) DD=substr(time_str,len-8,2) if(valnum(mon_s)=1 & valnum(mon_e)=1) 'display 'mon.MMM else 'display 'mon.MMM+DD/100 endif cnt=cnt+1 endwhile 'disable fwrite' 'set gxout contour' 'set t '_.mydim.ts' '_.mydim.te writectl(mytmpdir'/monmask.ctl.'randnum,'^monmask.dat.'randnum,'mon') * * Output to variable(s). Done before resetting x/y/z to save memory. * 'open 'mytmpdir'/monmask.ctl.'randnum file_num=file_number() if(mon_e>=mon_s) 'monmasktmp1=maskout(1,mon.'file_num'-('mon_s'-0.005))' 'monmasktmp2=maskout(1,('mon_e'+0.005)-mon.'file_num')' mask'=monmasktmp1*monmasktmp2' 'undefine monmasktmp1' 'undefine monmasktmp2' else 'monmasktmp1=maskout(1,mon.'file_num'-('mon_s'-0.005))' 'monmasktmp1=const(monmasktmp1,0,-u)' 'monmasktmp2=maskout(1,('mon_e'+0.005)-mon.'file_num')' 'monmasktmp2=const(monmasktmp2,0,-u)' 'monmasktmp3=monmasktmp1+monmasktmp2-0.5' mask'=maskout(1,monmasktmp3)' 'undefine monmasktmp1' 'undefine monmasktmp2' 'undefine monmasktmp3' endif if(month!='') 'define 'month'=mon.'file_num'*'mask endif 'close 'file_num '!rm 'mytmpdir'/monmask.dat.'randnum * * Restore original dimension environment. * _.mydim.resetx _.mydim.resety _.mydim.resetz _.mydim.resett return *************************************************************************************** function writectl(ctlfile,datfile,var) * * Write .ctl file. * lines=11 line.1='dset 'datfile line.2='undef -9.99e8' if(_.mydim.cal='') line.3='*options' else line.3='options '_.mydim.cal endif line.4='title intentionally left blank.' line.5='xdef 1 levels '_.mydim.lons line.6='ydef 1 levels '_.mydim.lats line.7='zdef 1 levels '_.mydim.levs line.8=_.mydim.tdef line.9='vars 1' line.10=var' 0 99 numbers between 1 and 12 corresponding to calendar month of each time step.' line.11='endvars' cnt=1 while(cnt<=lines) status=write(ctlfile,line.cnt) cnt=cnt+1 endwhile status=close(ctlfile) return *************************************************************************************** function file_number() * * Get the number of files opened. * 'query files' line1=sublin(result,1) if(line1='No files open') return 0 endif lines=1 while(sublin(result,lines+1)!='') lines=lines+1 endwhile return lines/3 *************************************************************************************** function usage() * * Print usage information. * say ' Create mask for specified calendar months.' say '' say ' USAGE: monmask []' say ' : range of calendar month(s) NOT to mask out. Decimals can be used for partial month (see EXAMPLE 4).' say ' : mask. Ones over to inclusive, missing values elsewhere.' say ' : calendar month where = 1, missing value elsewhere. Will be decimal if or is decimal.' say '' say ' NOTE: any time grid or calendar is supported.' say '' say ' EXAMPLE 1: define a variable "winmask" with ones over December, January, and February, and missing values over other months.' say ' monmask 12 2 winmask' say '' say ' EXAMPLE 2: define a variable "summask" with ones over June, July, and August, and missing values over other months.' say ' monmask 6 8 summask' say '' say ' EXAMPLE 3: define a variable "julmask" with ones over July and missing values over other months.' say ' monmask 7 7 julmask' say '' say ' EXAMPLE 4: define a variable "daymask" with ones over July 1-15 and missing values over other days.' say ' monmask 7.01 7.15 daymask' say '' say ' DEPENDENCIES: qdims.gsf' say '' say ' Copyright (c) 2013-2017, Bin Guan.' return