import sys import os import numpy as nmp # #Lfinite = nmp.isfinite(XF) # #Lshit = nmp.logical_not(Lfinite) # #idx_bad = nmp.where(Lshit) ris2 = 1./nmp.sqrt(2.) def chck4f(cf, script_name=''): cmesg = 'ERROR: File '+cf+' does not exist !!!' if script_name != '': cmesg = 'ERROR in script '+script_name+': File '+cf+' does not exist !!!' if not os.path.exists(cf): print cmesg ; sys.exit(0) else: print ' *** will open file '+cf def check_env_var(cnm, list): # * cnm : string for the name of the script calling this function # * list : a list of string supposed to be environement variables # # Returns a dictionary containing the variable names and their respective content print "\n In "+cnm+" :" env_var_dic = {} ; # empty dictionary for cv in list: cenv = os.getenv(cv) if cenv is None: print " ERROR in "+cnm+":" print(" => the {} environement is not set".format(cv)) sys.exit(0) env_var_dic[cv] = cenv print " *** "+cv+" => "+cenv print "" return env_var_dic def round_to_multiple_of(x, prec=2, base=0.5): ## Round to non-integer values, such as 0.5 ! return round(base * round(float(x)/base),prec) def int_as_multiple_of(x, base=5): # Closest integer multiple of base: return int(base * round(float(x)/base)) def lon_180_180(x): rsign = 1. if 180.-x < 0.: rsign=-1. return rsign*min(x,abs(x-360.)) def get_sections_from_file(cfile): list_sections = [] f = open(cfile, 'r') ; cread_lines = f.readlines() ; f.close() jl=0 ; l_stop=False while not l_stop: ll = cread_lines[jl] ls = ll.split() cc = ls[0] if cc == 'EOF': l_stop=True elif cc[0] != '#': if cc != 'EOF' and cc[0:13] != 'ref_temp_sali': print ls list_sections.append(cc) jl=jl+1 ; # to skip coordinates line else: print ' .... ' jl=jl+1 return list_sections def iaxe_tick(ny): # I want 20 ticks on the absciss axe and multiple of 5 itick = int( max( 1 , min(ny/20 , max(ny/20,5)/5*5) ) ) if itick == 4 or itick == 3: itick = 5 if ny >= 16 and itick == 1: itick = 2 if ny >= 45 and ny < 100: itick = 5 if ny >= 100 and ny < 250: itick = 10 if ny >= 250 and ny < 750: itick = 25 if ny >= 750 and ny <2000: itick = 50 if ny >= 2000: itick = 100 return itick def monthly_2_annual(vtm, XDm): # Transform a montly time series into an annual time series nbm = len(vtm) if len(nmp.shape(XDm)) == 1: # XDm is a vector nbcol = 1 nt = len(XDm) else: # XDm is an array [ nbcol, nt ] = nmp.shape(XDm) #print nt if nt < nbm: print 'ERROR: vmonthly_2_vannual.barakuda_tool.py => vt and data disagree in size!' print ' => size vt = '+str(nbm)+' / size data = '+str(nt) sys.exit(0) if nt > nbm: print 'WARNING: vmonthly_2_vannual.barakuda_tool.py => vt and data disagree in size!' print ' => size vt = '+str(nbm)+' / size data = '+str(nt) print ' => deleting the last '+str(nt-nbm)+' of data array data...' #if nbcol == 1: XDm = nmp.delete(XDm, nmp.arange(nbm,nt)) print ' => new shape of data =', nmp.shape(XDm),'\n' if nbm%12 != 0: print 'ERROR: vmonthly_2_vannual.barakuda_tool.py => not a multiple of 12!'; sys.exit(0) nby = nbm/12 vty = nmp.zeros(nby) XDy = nmp.zeros((nbcol,nby)) #print 'DEBUG: monthly_2_annual.barakuda_tool.py => nbm, nby, nbcol:', nbm, nby, nbcol for jy in range(nby): jt_jan = jy*12 vty[jy] = nmp.trunc(vtm[jt_jan]) + 0.5 ; # 1992.5, not 1992 if nbcol == 1: XDy[0,jy] = nmp.mean(XDm[jt_jan:jt_jan+12]) else: XDy[:,jy] = nmp.mean(XDm[:,jt_jan:jt_jan+12], axis=1) if nbcol == 1: return vty, XDy[0,:] else: #print 'DEBUG: monthly_2_annual.barakuda_tool.py => shape(vty):', nmp.shape(vty) return vty, XDy def find_ij_region_box(vbox4, VX, VY): [x_min, y_min, x_max, y_max ] = vbox4 print '' print 'barakuda_tool.find_ij_region_box : x_min, y_min, x_max, y_max => ', x_min, y_min, x_max, y_max # fixing longitude: # ~~~~~~~~~~~~~~~~~ if x_min < 0. : x_min = x_min + 360. if x_max < 0. : x_max = x_max + 360. VXtmp = nmp.zeros(len(VX)) ; VXtmp[:] = VX[:] idx = nmp.where(VX[:] < 0.0) ; VXtmp[idx] = VX[idx] + 360. # fixing latitude: # ~~~~~~~~~~~~~~~~~ # Is latitude increasing with j ? jy_inc = 1 if VY[1] < VY[0]: jy_inc = -1 #print jy_inc #VYtmp = nmp.zeros(len(VY)) ; VYtmp[:] = VY[:] j_y_min = find_index_from_value( y_min, VY ) j_y_max = find_index_from_value( y_max, VY ) i_x_min = find_index_from_value( x_min, VXtmp ) i_x_max = find_index_from_value( x_max, VXtmp ) if i_x_min == -1 or i_x_max == -1 or j_y_min == -1 or j_y_max == -1: print 'ERROR: barakuda_tool.find_ij_region_box, indiex not found' sys.exit(0) if jy_inc == -1: jdum = j_y_min; j_y_min = j_y_max; j_y_max = jdum #print ' * i_x_min = ', i_x_min, ' => ', VX[i_x_min] #print ' * j_y_min = ', j_y_min, ' => ', VY[j_y_min] #print ' * i_x_max = ', i_x_max, ' => ', VX[i_x_max] #print ' * j_y_max = ', j_y_max, ' => ', VY[j_y_max] #print '\n' return [ i_x_min, j_y_min, i_x_max, j_y_max ] #----------------------------------- def read_ascii_column(cfile, ivcol2read): # #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # INPUT # cfile : ASCII file # ivcol2read : vector containing indices of colum to be read (ex: [0, 1, 4]) # # OUTPUT # Xout : array containg the extracted data #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # chck4f(cfile) f = open(cfile, 'r') cread_lines = f.readlines() f.close() # nbcol = len(ivcol2read) ; #print "nbcol = ", nbcol # # Need to know how many "non-comment" lines: jl = 0 for ll in cread_lines: ls = ll.split() if ls[0] != '#': jl = jl + 1 nbl = jl #print 'number of lines = ', nbl ; sys.exit # Xout = nmp.zeros((nbcol,nbl)) # jl = -1 for ll in cread_lines: ls = ll.split() if ls[0] != '#': jl = jl+1 jc = -1 for icol in ivcol2read: jc = jc+1 Xout[jc,jl] = float(ls[icol]) # return Xout def get_min_max_df(ZZ, ndf): import math # RETURNS rounded Min and Max of array ZZ as well as the contour interval for "ndf" contours... # Testing where the array has finite values (non nan, non infinite) Lfinite = nmp.isfinite(ZZ) idx_good = nmp.where(Lfinite) zmin = nmp.amin(ZZ[idx_good]) ; zmax = nmp.amax(ZZ[idx_good]) if abs(zmin) >= abs(zmax): zmax = -zmin else: zmin = -zmax zmin0 = zmin ; zmax0 = zmax #print ' Before in barakuda_tool.get_min_max_df: zmin, zmax =', zmin, zmax rmagn = 10.**(int(math.log10(zmax))) zmin = round(zmin/rmagn - 0.5) zmax = round(zmax/rmagn + 0.5) zdf0 = (zmax - zmin)/ndf zdf = 0.0 ; idec = 0 while zdf == 0.0: idec = idec + 1 zdf = round(zdf0,idec) if idec >= 1: zmin = round(zmin,idec-1) ; zmax = round(zmax,idec-1) zmin = zmin*rmagn zmax = zmax*rmagn zdf = (zmax - zmin)/ndf while zmax - zdf >= zmax0 and zmin + zdf <= zmin0: zmax = zmax - zdf zmin = zmin + zdf if abs(zmin) < zmax: zmax = abs(zmin) if abs(zmin) > zmax: zmin = -zmax # Might divide zdf by 2 of zmax and zmin really decreased... rn1 = (zmax-zmin)/zdf nn = int(round(float(ndf)/rn1,0)) zdf = zdf/nn fact = 10**(-(int(math.log10(zdf))-1)) zdf = round(zdf*fact,0) zdf = zdf/fact # we want zmax and rmin to be mutilples of zdf : zmax = zdf*int(round(zmax/zdf)) zmin = zdf*int(round(zmin/zdf)) return [ zmin, zmax, zdf ] def find_index_from_value( val, VX ): if val > nmp.max(VX) or val < nmp.min(VX): print 'ERROR: find_index_from_value.barakuda_tool => value "'+str(val)+'"outside range of Vector!' print VX[:] ; print ' => value =', val sys.exit(0) jval = -1; jj = 0 ; lfound = False while not lfound: if VX[jj] <= val and VX[jj + 1] > val: jval = jj+1; lfound = True jj = jj+1 return jval def drown(X, mask, k_ew=-1, nb_max_inc=5, nb_smooth=5): ''' PURPOSE : fills continental areas of field X (defined by mask==0) ------- using nearest surrounding sea points (defined by mask==1) field X is absoluletly unchanged where mask==1 Input/Output : -------------- * X : treated array (float) / modified! [2D array] * mask : land-sea mask (integer) / unchanged [2D array] Optional : ---------- * k_ew : east-west periodicity on the input file/grid k_ew = -1 --> no periodicity k_ew >= 0 --> periodicity with overlap of k_ew points * nb_max_inc : distance (in grid points) of incursion into the continents for the drowning... * nb_smooth : number of times the smoother is applied on masked region (mask=0) => default: nb_smooth = 50 Author : Laurent BRODEAU, 2007, as part of SOSIE ported to python November 2013 ''' cmesg = 'ERROR, barakuda_tool.py => drown :' nbdim = len(nmp.shape(X)) if nbdim > 3 or nbdim <2: print cmesg+' size of data array is wrong!!!'; sys.exit(0) nt = 1 l_record = False if nbdim == 3: l_record = True if l_record: if nmp.shape(X[0,:,:]) != nmp.shape(mask): print cmesg+' size of data and mask do not match!!!'; sys.exit(0) (nt,nj,ni) = nmp.shape(X) else: if nmp.shape(X) != nmp.shape(mask): print cmesg+' size of data and mask do not match!!!'; sys.exit(0) (nj,ni) = nmp.shape(X) if nmp.sum(mask) == 0 : print 'The mask does not have sea points! Skipping drown!' return Xtemp = nmp.zeros((nj,ni)) for jt in range(nt): if l_record: Xtemp[:,:] = X[jt,:,:] else: Xtemp[:,:] = X[:,:] maskv = nmp.zeros((nj,ni), dtype=nmp.int) dold = nmp.zeros((nj,ni)) xtmp = nmp.zeros((nj,ni)) mask_coast = nmp.zeros((nj,ni)) jinc = 0 maskv[:,:] = mask[:,:] for jinc in range(1,nb_max_inc+1): dold[:,:] = Xtemp[:,:] # Building mask of the coast-line (belonging to land points) mask_coast[:,:] = 0 mask_coast[1:-1,1:-1] = (maskv[1:-1,2:] + maskv[2:,1:-1] + maskv[1:-1,:-2] + maskv[:-2,1:-1])*(-(maskv[1:-1,1:-1]-1)) if k_ew >= 0: # Left LBC: mask_coast[1:-1,0] = (maskv[1:-1,1] + maskv[2:,0] + maskv[1:-1,ni-1-k_ew] + maskv[:-2,0] )*(-(maskv[1:-1,0] -1)) # Right LBC: mask_coast[1:-1,ni-1] = (maskv[1:-1,k_ew] + maskv[2:,ni-1] + maskv[1:-1,ni-2] + maskv[:-2,ni-1])*(-(maskv[1:-1,ni-1]-1)) idx_coast = nmp.where(mask_coast[:,:] > 0) #mask_coast[:,:] = 0 #mask_coast[idx_coast] = 1 # Extrapolating sea values on that coast line: (idx_j_land,idx_i_land) = idx_coast ic = 0 for jj in idx_j_land: ji = idx_i_land[ic] if ji == 0 and k_ew >= 0: Xtemp[jj,0] = 1./(maskv[jj,1]+maskv[jj+1,0]+maskv[jj,ni-1-k_ew]+maskv[jj-1,0]+ ris2*maskv[jj+1,1]+ris2*maskv[jj+1,ni-1-k_ew]+ris2*maskv[jj-1,ni-1-k_ew]+ris2*maskv[jj-1,1])*( maskv[jj,1]*dold[jj,1] + maskv[jj+1,0]*dold[jj+1,0] + maskv[jj,ni-1-k_ew]*dold[jj,ni-1-k_ew] + maskv[jj-1,0]*dold[jj-1,0] + ris2*maskv[jj+1,1]*dold[jj+1,1] + ris2*maskv[jj+1,ni-1-k_ew]*dold[jj+1,ni-1-k_ew] + ris2*maskv[jj-1,ni-1-k_ew]*dold[jj-1,ni-1-k_ew] + ris2*maskv[jj-1,1]*dold[jj-1,1] ) elif ji == ni-1 and k_ew >= 0: Xtemp[jj,ni-1] = 1./(maskv[jj,k_ew]+maskv[jj+1,ni-1]+maskv[jj,ni-2]+maskv[jj-1,ni-1]+ ris2*maskv[jj+1,k_ew]+ris2*maskv[jj+1,ni-2]+ris2*maskv[jj-1,ni-2]+ris2*maskv[jj-1,k_ew])*( maskv[jj,k_ew]*dold[jj,k_ew] + maskv[jj+1,ni-1]*dold[jj+1,ni-1] + maskv[jj,ni-2]*dold[jj,ni-2] + maskv[jj-1,ni-1]*dold[jj-1,ni-1] + ris2*maskv[jj+1,k_ew]*dold[jj+1,k_ew] + ris2*maskv[jj+1,ni-2]*dold[jj+1,ni-2] + ris2*maskv[jj-1,ni-2]*dold[jj-1,ni-2] + ris2*maskv[jj-1,k_ew]*dold[jj-1,k_ew] ) else: Xtemp[jj,ji] = 1./(maskv[jj,ji+1]+maskv[jj+1,ji]+maskv[jj,ji-1]+maskv[jj-1,ji]+ ris2*maskv[jj+1,ji+1]+ris2*maskv[jj+1,ji-1]+ris2*maskv[jj-1,ji-1]+ris2*maskv[jj-1,ji+1])*( maskv[jj,ji+1]*dold[jj,ji+1] + maskv[jj+1,ji]*dold[jj+1,ji] + maskv[jj,ji-1]*dold[jj,ji-1] + maskv[jj-1,ji]*dold[jj-1,ji] + ris2*maskv[jj+1,ji+1]*dold[jj+1,ji+1] + ris2*maskv[jj+1,ji-1]*dold[jj+1,ji-1] + ris2*maskv[jj-1,ji-1]*dold[jj-1,ji-1] + ris2*maskv[jj-1,ji+1]*dold[jj-1,ji+1] ) ic = ic+1 # Loosing land for next iteration: maskv[idx_coast] = 1 # Smoothing the what's been done on land: if nb_smooth >= 1: dold[:,:] = Xtemp[:,:] for kk in range(nb_smooth): xtmp[:,:] = Xtemp[:,:] Xtemp[1:-1,1:-1] = 0.35*xtmp[1:-1,1:-1] + 0.65*0.25*( xtmp[1:-1,2:] + xtmp[2:,1:-1] + xtmp[1:-1,:-2] + xtmp[:-2,1:-1] ) if k_ew != -1: # we can use east-west periodicity Xtemp[1:-1,0] = 0.35*xtmp[1:-1,0] + 0.65*0.25*( xtmp[1:-1,1] + xtmp[2:,1] + xtmp[1:-1,ni-1-k_ew] + xtmp[:-2,1] ) Xtemp[1:-1,ni-1] = 0.35*xtmp[1:-1,ni-1] + 0.65*0.25*( xtmp[1:-1,k_ew] + xtmp[2:,ni-1] + xtmp[1:-1,ni-2] + xtmp[:-2,ni-1] ) Xtemp[1:-1,:] = mask[1:-1,:]*dold[1:-1,:] - (mask[1:-1,:]-1)*Xtemp[1:-1,:] del maskv, dold, mask_coast, xtmp if l_record: X[jt,:,:] = Xtemp[:,:] else: X[:,:] = Xtemp[:,:] Xtemp[:,:] = 0. # loop on nt over del Xtemp return def extend_domain(ZZ, ext_east_deg, skp_west_deg=0): # # IN: # === # ZZ : array to extend in longitude, 2D field or 1D longitude vector # ext_east_deg : eastward extension in degrees... # skp_west_deg : what to skip at the west in degrees... # # OUT: # ==== # ZZx : zonally-extended array # # # vdim = ZZ.shape ndim = len(vdim) if ndim < 1 or ndim > 3: print 'extend_conf.py: ERROR we only treat 1D or 2D arrays...'; sys.exit(0) if ndim == 3: [ nz , ny , nx ] = vdim if ndim == 2: [ ny , nx ] = vdim if ndim == 1: [ nx ] = vdim nb_skp = int(nx/360.*skp_west_deg) nb_ext = int(nx/360.*ext_east_deg) - nb_skp nx_ext = nx + nb_ext if ndim == 3: ZZx = nmp.zeros((nz, ny, nx_ext)) for jx in range(nx-skp_west_deg): ZZx[:,:,jx] = ZZ[:,:,jx+skp_west_deg] for jx in range(nx-skp_west_deg, nx_ext): ZZx[:,:,jx] = ZZ[:,:,jx-nx+skp_west_deg] if ndim == 2: ZZx = nmp.zeros((ny, nx_ext)) for jx in range(nx-skp_west_deg): ZZx[:,jx] = ZZ[:,jx+skp_west_deg] for jx in range(nx-skp_west_deg, nx_ext): ZZx[:,jx] = ZZ[:,jx-nx+skp_west_deg] if ndim == 1: ZZx = nmp.zeros(nx_ext) for jx in range(nx-skp_west_deg): ZZx[jx] = ZZ[jx+skp_west_deg] for jx in range(nx-skp_west_deg,nx_ext): ZZx[jx] = ZZ[jx-nx+skp_west_deg] + 360. return ZZx def mk_zonal(XF, XMSK=[0.], r_mask_from_val=-9999.): #************************************************************************************** # Computes the zonal average of field XF, ignoring points where XMSK==0. # # INPUT: # * XF: 2D [ny,nx] or 2D+time [ny,nx,Nt] array of input field # " opt: # * XMSK: 2D [ny,nx] array, 1 on points to consider, 0 on points to exclude # * r_mask_from_val: instead of providing the 2D mask provide the flag value # where mask should be 0 # RETURNS: # * VZ: 1D [ny] array of zonally-averaged XF #************************************************************************************** # vshp = nmp.shape(XF) ndim = len(vshp) if ndim == 3: ( Nt, ny, nx ) = vshp elif ndim == 2: ( ny, nx ) = vshp Nt = 1 else: print ' ERROR (mk_zonal of barakuda_tool.py): dimension of your field is weird!' sys.exit(0) # if len(nmp.shape(XMSK)) == 2: (n2,n1) = XMSK.shape if n2 != ny or n1 != nx: print 'ERROR: mk_zonal.barakuda_tool.py => XF and XMSK do not agree in size!' sys.exit(0) else: # Need to build the mask xtmp = nmp.zeros((ny,nx)) if ndim == 3: xtmp = XF[0,:,:] if ndim == 2: xtmp = XF[ :,:] XMSK = nmp.zeros((ny,nx)) idx1 = nmp.where(xtmp > r_mask_from_val + 1.E-6) XMSK[idx1] = 1. idx1 = nmp.where(xtmp < r_mask_from_val - 1.E-6) XMSK[idx1] = 1. del xtmp # VZ = nmp.zeros((Nt,ny)) # vweights = nmp.zeros(ny) for jy in range(ny): vweights[jy] = nmp.sum(XMSK[jy,:]) idx0 = nmp.where(vweights == 0.) vweights[idx0] = 1.E12 # for jt in range(Nt): for jy in range(ny): if ndim == 3: rmean = nmp.sum(XF[jt,jy,:]*XMSK[jy,:])/vweights[jy] if ndim == 2: rmean = nmp.sum(XF[ jy,:]*XMSK[jy,:])/vweights[jy] VZ[jt,jy] = rmean VZ[jt,idx0] = nmp.nan if ndim == 3: return VZ if ndim == 2: return VZ[0,:] def read_coor(cf, ctype='int', lTS_bounds=False): # cf : file containing sections or coordinates (name lon1 lat1 lon2 lat2) # ctype: 'int' or 'float' # lTS_bounds: read and return the bounds (min and max) for T and S ! chck4f(cf) f = open(cf, 'r') cread_lines = f.readlines() f.close() vboxes = [] ; vi1 = [] ; vj1 = [] ; vi2 = [] ; vj2 = [] vTs = [] ; vTl = [] ; vSs = [] ; vSl = [] ; leof = False jl = -1 while not leof: jl = jl + 1 ll = cread_lines[jl] ls = ll.split() # c1 = ls[0] ; c1 = c1[0] # if c1 != '#' and ls[0] != 'EOF': vboxes.append(ls[0]) if ctype == 'int': vi1.append(int(ls[1])) vj1.append(int(ls[2])) vi2.append(int(ls[3])) vj2.append(int(ls[4])) elif ctype == 'float': vi1.append(float(ls[1])) vj1.append(float(ls[2])) vi2.append(float(ls[3])) vj2.append(float(ls[4])) else: print 'ERROR: read_coor => ctype must be "int" or "float"' sys.exit(0) # if lTS_bounds: # Min and max values for temperature and salinity if len(ls) == 9: vTs.append(float(ls[5])) vTl.append(float(ls[6])) vSs.append(float(ls[7])) vSl.append(float(ls[8])) elif len(ls) == 5: # no temp. sal. bounds given, chosing some defaults for you... vTs.append(float(-2.)) ; # deg.C vTl.append(float(30.)) ; # deg.C vSs.append(float(33.)) ; # PSU vSl.append(float(37.)) ; # PSU else: print 'ERROR: read_coor => something wrong in line "'+ls[0]+'" !' sys.exit(0) # if ls[0] == 'EOF': leof = True if lTS_bounds: return vboxes, vi1, vj1, vi2, vj2, vTs, vTl, vSs, vSl else: return vboxes, vi1, vj1, vi2, vj2 def test_nb_years(vt, cd): nb_rec = len(vt) # Monthly or Annual time-series? idt = int( vt[1] - vt[0] ) if (idt == 0) and (nb_rec%12 == 0): # Montly time-series nb_m = nb_rec nb_y = nb_rec/12 elif idt == 1: # Annual time-series nb_m = -1 nb_y = nb_rec else: print 'ERROR: '+csn+' for diag='+cd print ' => the time vector seems to be neither monthly nor annual!' print ' => Nb. rec. = '+str(nb_rec) sys.exit(0) ttick = iaxe_tick(nb_y) return (nb_y, nb_m, nb_rec, ttick) def var_and_signs( csin ): # Ex: if csin = 'Qsol+Qr-Qlat-Qsens' (or '+Qsol+Qr-Qlat-Qsens') # this function will return: # ['Qsol', 'Qr', 'Qlat', 'Qsens'] , [1.0, 1.0, -1.0, -1.0] from re import split as splt # sgn1 = '+' cvar = splt('\-|\+',csin) if cvar[0] == '': if csin[0] == '-': sgn1 = '-' cvar = cvar[1:] ccum = '' for cc in cvar: ccum=ccum+'|'+cc ccum = ccum+'|' ctt=splt("'"+ccum+"'",csin) csgn = ctt[:-1] isgn = [] for cs in csgn: isgn.append(float(cs+'1')) return cvar, isgn def smoother(X, msk, nb_smooth=5): ### Do boundaries!!! cmesg = 'ERROR, barakuda_tool.py => smoother :' nbdim = len(nmp.shape(X)) if nbdim != 2: print cmesg+' size of data array is wrong!!!'; sys.exit(0) (nj,ni) = nmp.shape(X) xtmp = nmp.zeros((nj,ni)) for ii in range(nb_smooth): xtmp[:,:] = X[:,:]*msk[:,:] X[1:-1,1:-1] = 0.35*xtmp[1:-1,1:-1] + ( 0.65*( xtmp[1:-1,2:] + xtmp[2:,1:-1] + xtmp[1:-1,:-2] + xtmp[:-2,1:-1] \ + ris2*( xtmp[2:,2:] + xtmp[:-2,2:] + xtmp[:-2,:-2] + xtmp[2:,:-2] ) ) ) \ / nmp.maximum( msk[1:-1,2:] + msk[2:,1:-1] + msk[1:-1,:-2] + msk[:-2,1:-1] \ + ris2*( msk[2:,2:] + msk[:-2,2:] + msk[:-2,:-2] + msk[2:,:-2] ) \ , 1.E-6 ) X[:,:] = X[:,:]*msk[:,:] del xtmp return