barakuda_tool.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
  1. import sys
  2. import os
  3. import numpy as nmp
  4. # #Lfinite = nmp.isfinite(XF)
  5. # #Lshit = nmp.logical_not(Lfinite)
  6. # #idx_bad = nmp.where(Lshit)
  7. ris2 = 1./nmp.sqrt(2.)
  8. def chck4f(cf, script_name=''):
  9. cmesg = 'ERROR: File '+cf+' does not exist !!!'
  10. if script_name != '': cmesg = 'ERROR in script '+script_name+': File '+cf+' does not exist !!!'
  11. if not os.path.exists(cf):
  12. print cmesg ; sys.exit(0)
  13. else:
  14. print ' *** will open file '+cf
  15. def check_env_var(cnm, list):
  16. # * cnm : string for the name of the script calling this function
  17. # * list : a list of string supposed to be environement variables
  18. #
  19. # Returns a dictionary containing the variable names and their respective content
  20. print "\n In "+cnm+" :"
  21. env_var_dic = {} ; # empty dictionary
  22. for cv in list:
  23. cenv = os.getenv(cv)
  24. if cenv is None:
  25. print " ERROR in "+cnm+":"
  26. print(" => the {} environement is not set".format(cv))
  27. sys.exit(0)
  28. env_var_dic[cv] = cenv
  29. print " *** "+cv+" => "+cenv
  30. print ""
  31. return env_var_dic
  32. def round_to_multiple_of(x, prec=2, base=0.5):
  33. ## Round to non-integer values, such as 0.5 !
  34. return round(base * round(float(x)/base),prec)
  35. def int_as_multiple_of(x, base=5):
  36. # Closest integer multiple of base:
  37. return int(base * round(float(x)/base))
  38. def lon_180_180(x):
  39. rsign = 1.
  40. if 180.-x < 0.: rsign=-1.
  41. return rsign*min(x,abs(x-360.))
  42. def get_sections_from_file(cfile):
  43. list_sections = []
  44. f = open(cfile, 'r') ; cread_lines = f.readlines() ; f.close()
  45. jl=0 ; l_stop=False
  46. while not l_stop:
  47. ll = cread_lines[jl]
  48. ls = ll.split()
  49. cc = ls[0]
  50. if cc == 'EOF':
  51. l_stop=True
  52. elif cc[0] != '#':
  53. if cc != 'EOF' and cc[0:13] != 'ref_temp_sali':
  54. print ls
  55. list_sections.append(cc)
  56. jl=jl+1 ; # to skip coordinates line
  57. else:
  58. print ' .... '
  59. jl=jl+1
  60. return list_sections
  61. def iaxe_tick(ny):
  62. # I want 20 ticks on the absciss axe and multiple of 5
  63. itick = int( max( 1 , min(ny/20 , max(ny/20,5)/5*5) ) )
  64. if itick == 4 or itick == 3: itick = 5
  65. if ny >= 16 and itick == 1: itick = 2
  66. if ny >= 45 and ny < 100: itick = 5
  67. if ny >= 100 and ny < 250: itick = 10
  68. if ny >= 250 and ny < 750: itick = 25
  69. if ny >= 750 and ny <2000: itick = 50
  70. if ny >= 2000: itick = 100
  71. return itick
  72. def monthly_2_annual(vtm, XDm):
  73. # Transform a montly time series into an annual time series
  74. nbm = len(vtm)
  75. if len(nmp.shape(XDm)) == 1:
  76. # XDm is a vector
  77. nbcol = 1
  78. nt = len(XDm)
  79. else:
  80. # XDm is an array
  81. [ nbcol, nt ] = nmp.shape(XDm)
  82. #print nt
  83. if nt < nbm:
  84. print 'ERROR: vmonthly_2_vannual.barakuda_tool.py => vt and data disagree in size!'
  85. print ' => size vt = '+str(nbm)+' / size data = '+str(nt)
  86. sys.exit(0)
  87. if nt > nbm:
  88. print 'WARNING: vmonthly_2_vannual.barakuda_tool.py => vt and data disagree in size!'
  89. print ' => size vt = '+str(nbm)+' / size data = '+str(nt)
  90. print ' => deleting the last '+str(nt-nbm)+' of data array data...'
  91. #if nbcol == 1:
  92. XDm = nmp.delete(XDm, nmp.arange(nbm,nt))
  93. print ' => new shape of data =', nmp.shape(XDm),'\n'
  94. if nbm%12 != 0: print 'ERROR: vmonthly_2_vannual.barakuda_tool.py => not a multiple of 12!'; sys.exit(0)
  95. nby = nbm/12
  96. vty = nmp.zeros(nby)
  97. XDy = nmp.zeros((nbcol,nby))
  98. #print 'DEBUG: monthly_2_annual.barakuda_tool.py => nbm, nby, nbcol:', nbm, nby, nbcol
  99. for jy in range(nby):
  100. jt_jan = jy*12
  101. vty[jy] = nmp.trunc(vtm[jt_jan]) + 0.5 ; # 1992.5, not 1992
  102. if nbcol == 1:
  103. XDy[0,jy] = nmp.mean(XDm[jt_jan:jt_jan+12])
  104. else:
  105. XDy[:,jy] = nmp.mean(XDm[:,jt_jan:jt_jan+12], axis=1)
  106. if nbcol == 1:
  107. return vty, XDy[0,:]
  108. else:
  109. #print 'DEBUG: monthly_2_annual.barakuda_tool.py => shape(vty):', nmp.shape(vty)
  110. return vty, XDy
  111. def find_ij_region_box(vbox4, VX, VY):
  112. [x_min, y_min, x_max, y_max ] = vbox4
  113. print ''
  114. print 'barakuda_tool.find_ij_region_box : x_min, y_min, x_max, y_max => ', x_min, y_min, x_max, y_max
  115. # fixing longitude:
  116. # ~~~~~~~~~~~~~~~~~
  117. if x_min < 0. : x_min = x_min + 360.
  118. if x_max < 0. : x_max = x_max + 360.
  119. VXtmp = nmp.zeros(len(VX)) ; VXtmp[:] = VX[:]
  120. idx = nmp.where(VX[:] < 0.0) ; VXtmp[idx] = VX[idx] + 360.
  121. # fixing latitude:
  122. # ~~~~~~~~~~~~~~~~~
  123. # Is latitude increasing with j ?
  124. jy_inc = 1
  125. if VY[1] < VY[0]: jy_inc = -1
  126. #print jy_inc
  127. #VYtmp = nmp.zeros(len(VY)) ; VYtmp[:] = VY[:]
  128. j_y_min = find_index_from_value( y_min, VY )
  129. j_y_max = find_index_from_value( y_max, VY )
  130. i_x_min = find_index_from_value( x_min, VXtmp )
  131. i_x_max = find_index_from_value( x_max, VXtmp )
  132. if i_x_min == -1 or i_x_max == -1 or j_y_min == -1 or j_y_max == -1:
  133. print 'ERROR: barakuda_tool.find_ij_region_box, indiex not found'
  134. sys.exit(0)
  135. if jy_inc == -1: jdum = j_y_min; j_y_min = j_y_max; j_y_max = jdum
  136. #print ' * i_x_min = ', i_x_min, ' => ', VX[i_x_min]
  137. #print ' * j_y_min = ', j_y_min, ' => ', VY[j_y_min]
  138. #print ' * i_x_max = ', i_x_max, ' => ', VX[i_x_max]
  139. #print ' * j_y_max = ', j_y_max, ' => ', VY[j_y_max]
  140. #print '\n'
  141. return [ i_x_min, j_y_min, i_x_max, j_y_max ]
  142. #-----------------------------------
  143. def read_ascii_column(cfile, ivcol2read):
  144. #
  145. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  146. # INPUT
  147. # cfile : ASCII file
  148. # ivcol2read : vector containing indices of colum to be read (ex: [0, 1, 4])
  149. #
  150. # OUTPUT
  151. # Xout : array containg the extracted data
  152. #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  153. #
  154. chck4f(cfile)
  155. f = open(cfile, 'r')
  156. cread_lines = f.readlines()
  157. f.close()
  158. #
  159. nbcol = len(ivcol2read) ; #print "nbcol = ", nbcol
  160. #
  161. # Need to know how many "non-comment" lines:
  162. jl = 0
  163. for ll in cread_lines:
  164. ls = ll.split()
  165. if ls[0] != '#': jl = jl + 1
  166. nbl = jl
  167. #print 'number of lines = ', nbl ; sys.exit
  168. #
  169. Xout = nmp.zeros((nbcol,nbl))
  170. #
  171. jl = -1
  172. for ll in cread_lines:
  173. ls = ll.split()
  174. if ls[0] != '#':
  175. jl = jl+1
  176. jc = -1
  177. for icol in ivcol2read:
  178. jc = jc+1
  179. Xout[jc,jl] = float(ls[icol])
  180. #
  181. return Xout
  182. def get_min_max_df(ZZ, ndf):
  183. import math
  184. # RETURNS rounded Min and Max of array ZZ as well as the contour interval for "ndf" contours...
  185. # Testing where the array has finite values (non nan, non infinite)
  186. Lfinite = nmp.isfinite(ZZ)
  187. idx_good = nmp.where(Lfinite)
  188. zmin = nmp.amin(ZZ[idx_good]) ; zmax = nmp.amax(ZZ[idx_good])
  189. if abs(zmin) >= abs(zmax):
  190. zmax = -zmin
  191. else:
  192. zmin = -zmax
  193. zmin0 = zmin ; zmax0 = zmax
  194. #print ' Before in barakuda_tool.get_min_max_df: zmin, zmax =', zmin, zmax
  195. rmagn = 10.**(int(math.log10(zmax)))
  196. zmin = round(zmin/rmagn - 0.5)
  197. zmax = round(zmax/rmagn + 0.5)
  198. zdf0 = (zmax - zmin)/ndf
  199. zdf = 0.0 ; idec = 0
  200. while zdf == 0.0:
  201. idec = idec + 1
  202. zdf = round(zdf0,idec)
  203. if idec >= 1: zmin = round(zmin,idec-1) ; zmax = round(zmax,idec-1)
  204. zmin = zmin*rmagn
  205. zmax = zmax*rmagn
  206. zdf = (zmax - zmin)/ndf
  207. while zmax - zdf >= zmax0 and zmin + zdf <= zmin0:
  208. zmax = zmax - zdf
  209. zmin = zmin + zdf
  210. if abs(zmin) < zmax: zmax = abs(zmin)
  211. if abs(zmin) > zmax: zmin = -zmax
  212. # Might divide zdf by 2 of zmax and zmin really decreased...
  213. rn1 = (zmax-zmin)/zdf
  214. nn = int(round(float(ndf)/rn1,0))
  215. zdf = zdf/nn
  216. fact = 10**(-(int(math.log10(zdf))-1))
  217. zdf = round(zdf*fact,0)
  218. zdf = zdf/fact
  219. # we want zmax and rmin to be mutilples of zdf :
  220. zmax = zdf*int(round(zmax/zdf))
  221. zmin = zdf*int(round(zmin/zdf))
  222. return [ zmin, zmax, zdf ]
  223. def find_index_from_value( val, VX ):
  224. if val > nmp.max(VX) or val < nmp.min(VX):
  225. print 'ERROR: find_index_from_value.barakuda_tool => value "'+str(val)+'"outside range of Vector!'
  226. print VX[:] ; print ' => value =', val
  227. sys.exit(0)
  228. jval = -1; jj = 0 ; lfound = False
  229. while not lfound:
  230. if VX[jj] <= val and VX[jj + 1] > val:
  231. jval = jj+1; lfound = True
  232. jj = jj+1
  233. return jval
  234. def drown(X, mask, k_ew=-1, nb_max_inc=5, nb_smooth=5):
  235. '''
  236. PURPOSE : fills continental areas of field X (defined by mask==0)
  237. ------- using nearest surrounding sea points (defined by mask==1)
  238. field X is absoluletly unchanged where mask==1
  239. Input/Output :
  240. --------------
  241. * X : treated array (float) / modified! [2D array]
  242. * mask : land-sea mask (integer) / unchanged [2D array]
  243. Optional :
  244. ----------
  245. * k_ew : east-west periodicity on the input file/grid
  246. k_ew = -1 --> no periodicity
  247. k_ew >= 0 --> periodicity with overlap of k_ew points
  248. * nb_max_inc : distance (in grid points) of incursion into the continents for the drowning...
  249. * nb_smooth : number of times the smoother is applied on masked region (mask=0)
  250. => default: nb_smooth = 50
  251. Author : Laurent BRODEAU, 2007, as part of SOSIE
  252. ported to python November 2013
  253. '''
  254. cmesg = 'ERROR, barakuda_tool.py => drown :'
  255. nbdim = len(nmp.shape(X))
  256. if nbdim > 3 or nbdim <2:
  257. print cmesg+' size of data array is wrong!!!'; sys.exit(0)
  258. nt = 1
  259. l_record = False
  260. if nbdim == 3: l_record = True
  261. if l_record:
  262. if nmp.shape(X[0,:,:]) != nmp.shape(mask):
  263. print cmesg+' size of data and mask do not match!!!'; sys.exit(0)
  264. (nt,nj,ni) = nmp.shape(X)
  265. else:
  266. if nmp.shape(X) != nmp.shape(mask):
  267. print cmesg+' size of data and mask do not match!!!'; sys.exit(0)
  268. (nj,ni) = nmp.shape(X)
  269. if nmp.sum(mask) == 0 :
  270. print 'The mask does not have sea points! Skipping drown!'
  271. return
  272. Xtemp = nmp.zeros((nj,ni))
  273. for jt in range(nt):
  274. if l_record:
  275. Xtemp[:,:] = X[jt,:,:]
  276. else:
  277. Xtemp[:,:] = X[:,:]
  278. maskv = nmp.zeros((nj,ni), dtype=nmp.int)
  279. dold = nmp.zeros((nj,ni))
  280. xtmp = nmp.zeros((nj,ni))
  281. mask_coast = nmp.zeros((nj,ni))
  282. jinc = 0
  283. maskv[:,:] = mask[:,:]
  284. for jinc in range(1,nb_max_inc+1):
  285. dold[:,:] = Xtemp[:,:]
  286. # Building mask of the coast-line (belonging to land points)
  287. mask_coast[:,:] = 0
  288. 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))
  289. if k_ew >= 0:
  290. # Left LBC:
  291. 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))
  292. # Right LBC:
  293. 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))
  294. idx_coast = nmp.where(mask_coast[:,:] > 0)
  295. #mask_coast[:,:] = 0
  296. #mask_coast[idx_coast] = 1
  297. # Extrapolating sea values on that coast line:
  298. (idx_j_land,idx_i_land) = idx_coast
  299. ic = 0
  300. for jj in idx_j_land:
  301. ji = idx_i_land[ic]
  302. if ji == 0 and k_ew >= 0:
  303. Xtemp[jj,0] = 1./(maskv[jj,1]+maskv[jj+1,0]+maskv[jj,ni-1-k_ew]+maskv[jj-1,0]+
  304. 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])*(
  305. maskv[jj,1]*dold[jj,1] + maskv[jj+1,0]*dold[jj+1,0] +
  306. maskv[jj,ni-1-k_ew]*dold[jj,ni-1-k_ew] + maskv[jj-1,0]*dold[jj-1,0] +
  307. ris2*maskv[jj+1,1]*dold[jj+1,1] + ris2*maskv[jj+1,ni-1-k_ew]*dold[jj+1,ni-1-k_ew] +
  308. ris2*maskv[jj-1,ni-1-k_ew]*dold[jj-1,ni-1-k_ew] + ris2*maskv[jj-1,1]*dold[jj-1,1] )
  309. elif ji == ni-1 and k_ew >= 0:
  310. Xtemp[jj,ni-1] = 1./(maskv[jj,k_ew]+maskv[jj+1,ni-1]+maskv[jj,ni-2]+maskv[jj-1,ni-1]+
  311. ris2*maskv[jj+1,k_ew]+ris2*maskv[jj+1,ni-2]+ris2*maskv[jj-1,ni-2]+ris2*maskv[jj-1,k_ew])*(
  312. maskv[jj,k_ew]*dold[jj,k_ew] + maskv[jj+1,ni-1]*dold[jj+1,ni-1] +
  313. maskv[jj,ni-2]*dold[jj,ni-2] + maskv[jj-1,ni-1]*dold[jj-1,ni-1] +
  314. ris2*maskv[jj+1,k_ew]*dold[jj+1,k_ew] + ris2*maskv[jj+1,ni-2]*dold[jj+1,ni-2] +
  315. ris2*maskv[jj-1,ni-2]*dold[jj-1,ni-2] + ris2*maskv[jj-1,k_ew]*dold[jj-1,k_ew] )
  316. else:
  317. Xtemp[jj,ji] = 1./(maskv[jj,ji+1]+maskv[jj+1,ji]+maskv[jj,ji-1]+maskv[jj-1,ji]+
  318. ris2*maskv[jj+1,ji+1]+ris2*maskv[jj+1,ji-1]+ris2*maskv[jj-1,ji-1]+ris2*maskv[jj-1,ji+1])*(
  319. maskv[jj,ji+1]*dold[jj,ji+1] + maskv[jj+1,ji]*dold[jj+1,ji] +
  320. maskv[jj,ji-1]*dold[jj,ji-1] + maskv[jj-1,ji]*dold[jj-1,ji] +
  321. ris2*maskv[jj+1,ji+1]*dold[jj+1,ji+1] + ris2*maskv[jj+1,ji-1]*dold[jj+1,ji-1] +
  322. ris2*maskv[jj-1,ji-1]*dold[jj-1,ji-1] + ris2*maskv[jj-1,ji+1]*dold[jj-1,ji+1] )
  323. ic = ic+1
  324. # Loosing land for next iteration:
  325. maskv[idx_coast] = 1
  326. # Smoothing the what's been done on land:
  327. if nb_smooth >= 1:
  328. dold[:,:] = Xtemp[:,:]
  329. for kk in range(nb_smooth):
  330. xtmp[:,:] = Xtemp[:,:]
  331. 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] )
  332. if k_ew != -1: # we can use east-west periodicity
  333. 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] )
  334. 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] )
  335. Xtemp[1:-1,:] = mask[1:-1,:]*dold[1:-1,:] - (mask[1:-1,:]-1)*Xtemp[1:-1,:]
  336. del maskv, dold, mask_coast, xtmp
  337. if l_record:
  338. X[jt,:,:] = Xtemp[:,:]
  339. else:
  340. X[:,:] = Xtemp[:,:]
  341. Xtemp[:,:] = 0.
  342. # loop on nt over
  343. del Xtemp
  344. return
  345. def extend_domain(ZZ, ext_east_deg, skp_west_deg=0):
  346. #
  347. # IN:
  348. # ===
  349. # ZZ : array to extend in longitude, 2D field or 1D longitude vector
  350. # ext_east_deg : eastward extension in degrees...
  351. # skp_west_deg : what to skip at the west in degrees...
  352. #
  353. # OUT:
  354. # ====
  355. # ZZx : zonally-extended array
  356. #
  357. #
  358. #
  359. vdim = ZZ.shape
  360. ndim = len(vdim)
  361. if ndim < 1 or ndim > 3: print 'extend_conf.py: ERROR we only treat 1D or 2D arrays...'; sys.exit(0)
  362. if ndim == 3: [ nz , ny , nx ] = vdim
  363. if ndim == 2: [ ny , nx ] = vdim
  364. if ndim == 1: [ nx ] = vdim
  365. nb_skp = int(nx/360.*skp_west_deg)
  366. nb_ext = int(nx/360.*ext_east_deg) - nb_skp
  367. nx_ext = nx + nb_ext
  368. if ndim == 3:
  369. ZZx = nmp.zeros((nz, ny, nx_ext))
  370. for jx in range(nx-skp_west_deg): ZZx[:,:,jx] = ZZ[:,:,jx+skp_west_deg]
  371. for jx in range(nx-skp_west_deg, nx_ext): ZZx[:,:,jx] = ZZ[:,:,jx-nx+skp_west_deg]
  372. if ndim == 2:
  373. ZZx = nmp.zeros((ny, nx_ext))
  374. for jx in range(nx-skp_west_deg): ZZx[:,jx] = ZZ[:,jx+skp_west_deg]
  375. for jx in range(nx-skp_west_deg, nx_ext): ZZx[:,jx] = ZZ[:,jx-nx+skp_west_deg]
  376. if ndim == 1:
  377. ZZx = nmp.zeros(nx_ext)
  378. for jx in range(nx-skp_west_deg): ZZx[jx] = ZZ[jx+skp_west_deg]
  379. for jx in range(nx-skp_west_deg,nx_ext): ZZx[jx] = ZZ[jx-nx+skp_west_deg] + 360.
  380. return ZZx
  381. def mk_zonal(XF, XMSK=[0.], r_mask_from_val=-9999.):
  382. #**************************************************************************************
  383. # Computes the zonal average of field XF, ignoring points where XMSK==0.
  384. #
  385. # INPUT:
  386. # * XF: 2D [ny,nx] or 2D+time [ny,nx,Nt] array of input field
  387. # " opt:
  388. # * XMSK: 2D [ny,nx] array, 1 on points to consider, 0 on points to exclude
  389. # * r_mask_from_val: instead of providing the 2D mask provide the flag value
  390. # where mask should be 0
  391. # RETURNS:
  392. # * VZ: 1D [ny] array of zonally-averaged XF
  393. #**************************************************************************************
  394. #
  395. vshp = nmp.shape(XF)
  396. ndim = len(vshp)
  397. if ndim == 3:
  398. ( Nt, ny, nx ) = vshp
  399. elif ndim == 2:
  400. ( ny, nx ) = vshp
  401. Nt = 1
  402. else:
  403. print ' ERROR (mk_zonal of barakuda_tool.py): dimension of your field is weird!'
  404. sys.exit(0)
  405. #
  406. if len(nmp.shape(XMSK)) == 2:
  407. (n2,n1) = XMSK.shape
  408. if n2 != ny or n1 != nx:
  409. print 'ERROR: mk_zonal.barakuda_tool.py => XF and XMSK do not agree in size!'
  410. sys.exit(0)
  411. else:
  412. # Need to build the mask
  413. xtmp = nmp.zeros((ny,nx))
  414. if ndim == 3: xtmp = XF[0,:,:]
  415. if ndim == 2: xtmp = XF[ :,:]
  416. XMSK = nmp.zeros((ny,nx))
  417. idx1 = nmp.where(xtmp > r_mask_from_val + 1.E-6)
  418. XMSK[idx1] = 1.
  419. idx1 = nmp.where(xtmp < r_mask_from_val - 1.E-6)
  420. XMSK[idx1] = 1.
  421. del xtmp
  422. #
  423. VZ = nmp.zeros((Nt,ny))
  424. #
  425. vweights = nmp.zeros(ny)
  426. for jy in range(ny): vweights[jy] = nmp.sum(XMSK[jy,:])
  427. idx0 = nmp.where(vweights == 0.)
  428. vweights[idx0] = 1.E12
  429. #
  430. for jt in range(Nt):
  431. for jy in range(ny):
  432. if ndim == 3: rmean = nmp.sum(XF[jt,jy,:]*XMSK[jy,:])/vweights[jy]
  433. if ndim == 2: rmean = nmp.sum(XF[ jy,:]*XMSK[jy,:])/vweights[jy]
  434. VZ[jt,jy] = rmean
  435. VZ[jt,idx0] = nmp.nan
  436. if ndim == 3: return VZ
  437. if ndim == 2: return VZ[0,:]
  438. def read_coor(cf, ctype='int', lTS_bounds=False):
  439. # cf : file containing sections or coordinates (name lon1 lat1 lon2 lat2)
  440. # ctype: 'int' or 'float'
  441. # lTS_bounds: read and return the bounds (min and max) for T and S !
  442. chck4f(cf)
  443. f = open(cf, 'r')
  444. cread_lines = f.readlines()
  445. f.close()
  446. vboxes = [] ; vi1 = [] ; vj1 = [] ; vi2 = [] ; vj2 = []
  447. vTs = [] ; vTl = [] ; vSs = [] ; vSl = [] ;
  448. leof = False
  449. jl = -1
  450. while not leof:
  451. jl = jl + 1
  452. ll = cread_lines[jl]
  453. ls = ll.split()
  454. #
  455. c1 = ls[0] ; c1 = c1[0]
  456. #
  457. if c1 != '#' and ls[0] != 'EOF':
  458. vboxes.append(ls[0])
  459. if ctype == 'int':
  460. vi1.append(int(ls[1]))
  461. vj1.append(int(ls[2]))
  462. vi2.append(int(ls[3]))
  463. vj2.append(int(ls[4]))
  464. elif ctype == 'float':
  465. vi1.append(float(ls[1]))
  466. vj1.append(float(ls[2]))
  467. vi2.append(float(ls[3]))
  468. vj2.append(float(ls[4]))
  469. else:
  470. print 'ERROR: read_coor => ctype must be "int" or "float"'
  471. sys.exit(0)
  472. #
  473. if lTS_bounds:
  474. # Min and max values for temperature and salinity
  475. if len(ls) == 9:
  476. vTs.append(float(ls[5]))
  477. vTl.append(float(ls[6]))
  478. vSs.append(float(ls[7]))
  479. vSl.append(float(ls[8]))
  480. elif len(ls) == 5:
  481. # no temp. sal. bounds given, chosing some defaults for you...
  482. vTs.append(float(-2.)) ; # deg.C
  483. vTl.append(float(30.)) ; # deg.C
  484. vSs.append(float(33.)) ; # PSU
  485. vSl.append(float(37.)) ; # PSU
  486. else:
  487. print 'ERROR: read_coor => something wrong in line "'+ls[0]+'" !'
  488. sys.exit(0)
  489. #
  490. if ls[0] == 'EOF': leof = True
  491. if lTS_bounds:
  492. return vboxes, vi1, vj1, vi2, vj2, vTs, vTl, vSs, vSl
  493. else:
  494. return vboxes, vi1, vj1, vi2, vj2
  495. def test_nb_years(vt, cd):
  496. nb_rec = len(vt)
  497. # Monthly or Annual time-series?
  498. idt = int( vt[1] - vt[0] )
  499. if (idt == 0) and (nb_rec%12 == 0):
  500. # Montly time-series
  501. nb_m = nb_rec
  502. nb_y = nb_rec/12
  503. elif idt == 1:
  504. # Annual time-series
  505. nb_m = -1
  506. nb_y = nb_rec
  507. else:
  508. print 'ERROR: '+csn+' for diag='+cd
  509. print ' => the time vector seems to be neither monthly nor annual!'
  510. print ' => Nb. rec. = '+str(nb_rec)
  511. sys.exit(0)
  512. ttick = iaxe_tick(nb_y)
  513. return (nb_y, nb_m, nb_rec, ttick)
  514. def var_and_signs( csin ):
  515. # Ex: if csin = 'Qsol+Qr-Qlat-Qsens' (or '+Qsol+Qr-Qlat-Qsens')
  516. # this function will return:
  517. # ['Qsol', 'Qr', 'Qlat', 'Qsens'] , [1.0, 1.0, -1.0, -1.0]
  518. from re import split as splt
  519. #
  520. sgn1 = '+'
  521. cvar = splt('\-|\+',csin)
  522. if cvar[0] == '':
  523. if csin[0] == '-': sgn1 = '-'
  524. cvar = cvar[1:]
  525. ccum = ''
  526. for cc in cvar: ccum=ccum+'|'+cc
  527. ccum = ccum+'|'
  528. ctt=splt("'"+ccum+"'",csin)
  529. csgn = ctt[:-1]
  530. isgn = []
  531. for cs in csgn: isgn.append(float(cs+'1'))
  532. return cvar, isgn
  533. def smoother(X, msk, nb_smooth=5):
  534. ### Do boundaries!!!
  535. cmesg = 'ERROR, barakuda_tool.py => smoother :'
  536. nbdim = len(nmp.shape(X))
  537. if nbdim != 2:
  538. print cmesg+' size of data array is wrong!!!'; sys.exit(0)
  539. (nj,ni) = nmp.shape(X)
  540. xtmp = nmp.zeros((nj,ni))
  541. for ii in range(nb_smooth):
  542. xtmp[:,:] = X[:,:]*msk[:,:]
  543. 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] \
  544. + ris2*( xtmp[2:,2:] + xtmp[:-2,2:] + xtmp[:-2,:-2] + xtmp[2:,:-2] ) ) ) \
  545. / nmp.maximum( msk[1:-1,2:] + msk[2:,1:-1] + msk[1:-1,:-2] + msk[:-2,1:-1] \
  546. + ris2*( msk[2:,2:] + msk[:-2,2:] + msk[:-2,:-2] + msk[2:,:-2] ) \
  547. , 1.E-6 )
  548. X[:,:] = X[:,:]*msk[:,:]
  549. del xtmp
  550. return