barakuda_orca.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. import sys
  2. import numpy as nmp
  3. def get_basin_info( cf_bm ):
  4. from netCDF4 import Dataset
  5. l_b_names = [] ; l_b_lgnms = []
  6. l_b_names.append(u'GLO') ; l_b_lgnms.append(u'Global Ocean')
  7. id_bm = Dataset(cf_bm)
  8. list_var = id_bm.variables.keys()
  9. for cv in list_var:
  10. if cv[:5] == 'tmask':
  11. l_b_names.append(cv[5:])
  12. l_b_lgnms.append(id_bm.variables[cv].long_name)
  13. id_bm.close()
  14. return l_b_names, l_b_lgnms
  15. def lon_reorg_orca(ZZ, Xlong, ilon_ext=0, v_jx_jump_p=170., v_jx_jump_m=-170.):
  16. #
  17. #
  18. # IN:
  19. # ===
  20. # ZZ : 1D, 2D, or 3D array to treat
  21. # Xlong : 1D or 2D array containing the longitude, must be consistent with the shape of ZZ !
  22. # ilon_ext : longitude extention of the map you want (in degrees)
  23. #
  24. # OUT:
  25. # ====
  26. # ZZx : re-organized array, mind the possibility of modified x dimension !
  27. #
  28. import barakuda_tool as bt
  29. #
  30. idim_lon = len(nmp.shape(Xlong))
  31. if idim_lon not in [ 1 , 2 ]:
  32. print 'util_orca.lon_reorg_orca: ERROR => longitude array "Xlong" must be 1D or 2D !'; sys.exit(0)
  33. #
  34. if idim_lon == 2: (nj,ni) = nmp.shape(Xlong)
  35. if idim_lon == 1: ni = len(Xlong)
  36. #
  37. vlon = nmp.zeros(ni)
  38. #
  39. if idim_lon == 2: vlon[:] = Xlong[nj/3,:]
  40. if idim_lon == 1: vlon[:] = Xlong[:]
  41. #
  42. lfound_jx_jump = False
  43. ji=0
  44. while ( not lfound_jx_jump and ji < ni-1):
  45. if vlon[ji] > v_jx_jump_p and vlon[ji+1] < v_jx_jump_m:
  46. jx_jump = ji + 1
  47. lfound_jx_jump = True
  48. ji = ji + 1
  49. print " *** barakuda_orca.lon_reorg_orca >> Longitude jump at ji = ", jx_jump
  50. #
  51. lfound_jx_zero = False
  52. ji=0
  53. while ( not lfound_jx_zero and ji < ni-1):
  54. if vlon[ji] < 0. and vlon[ji+1] > 0.:
  55. jx_zero = ji + 1
  56. lfound_jx_zero = True
  57. ji = ji + 1
  58. print " *** barakuda_orca.lon_reorg_orca >> Longitude zero at ji = ", jx_zero
  59. #
  60. del vlon
  61. jx_oo = 2 # orca longitude overlap...
  62. vdim = ZZ.shape
  63. ndim = len(vdim)
  64. if ndim < 1 or ndim > 4:
  65. print 'util_orca.lon_reorg_orca: ERROR we only treat 1D, 2D, 3D or 4D arrays...'
  66. if ndim == 4:
  67. #
  68. [ nr, nz , ny , nx ] = vdim ; nx0 = nx - jx_oo
  69. ZZx = nmp.zeros((nr, nz, ny, nx0))
  70. ZZx_ext = nmp.zeros((nr, nz, ny, (nx0+ilon_ext)))
  71. #
  72. for jx in range(jx_zero,nx):
  73. ZZx[:,:,:,jx-jx_zero] = ZZ[:,:,:,jx]
  74. for jx in range(jx_oo,jx_zero):
  75. ZZx[:,:,:,jx+(nx-jx_zero)-jx_oo] = ZZ[:,:,:,jx]
  76. #
  77. if ilon_ext == 0: ZZx_ext[:,:,:,:] = ZZx[:,:,:,:]
  78. #
  79. #
  80. if ndim == 3:
  81. #
  82. [ nz , ny , nx ] = vdim ; nx0 = nx - jx_oo
  83. #print 'nx, ny, nz = ', nx, ny, nz
  84. #
  85. ZZx = nmp.zeros(nx0*ny*nz) ; ZZx.shape = [nz, ny, nx0]
  86. ZZx_ext = nmp.zeros((nx0+ilon_ext)*ny*nz) ; ZZx_ext.shape = [nz, ny, (nx0+ilon_ext)]
  87. #
  88. for jx in range(jx_zero,nx):
  89. ZZx[:,:,jx-jx_zero] = ZZ[:,:,jx]
  90. for jx in range(jx_oo,jx_zero):
  91. ZZx[:,:,jx+(nx-jx_zero)-jx_oo] = ZZ[:,:,jx]
  92. #
  93. if ilon_ext == 0: ZZx_ext[:,:,:] = ZZx[:,:,:]
  94. #
  95. #
  96. if ndim == 2:
  97. #
  98. [ ny , nx ] = vdim ; nx0 = nx - jx_oo
  99. #print 'nx, ny = ', nx, ny
  100. #
  101. ZZx = nmp.zeros(nx0*ny) ; ZZx.shape = [ny, nx0]
  102. ZZx_ext = nmp.zeros((nx0+ilon_ext)*ny) ; ZZx_ext.shape = [ny, (nx0+ilon_ext)]
  103. #
  104. for jx in range(jx_zero,nx):
  105. ZZx[:,jx-jx_zero] = ZZ[:,jx]
  106. for jx in range(jx_oo,jx_zero):
  107. ZZx[:,jx+(nx-jx_zero)-jx_oo] = ZZ[:,jx]
  108. #
  109. if ilon_ext == 0: ZZx_ext[:,:] = ZZx[:,:]
  110. #
  111. #
  112. if ndim == 1:
  113. #
  114. [ nx ] = vdim ; nx0 = nx - jx_oo
  115. #print 'nx = ', nx
  116. #
  117. ZZx = nmp.zeros(nx0) ; ZZx.shape = [nx0]
  118. ZZx_ext = nmp.zeros(nx0+ilon_ext) ; ZZx_ext.shape = [nx0+ilon_ext]
  119. #
  120. for jx in range(jx_zero,nx):
  121. ZZx[jx-jx_zero] = ZZ[jx]
  122. #print jx-jx_zero, 'prend', jx, ' ', vlon[jx]
  123. #
  124. #print ''
  125. for jx in range(jx_oo,jx_zero):
  126. ZZx[jx+(nx-jx_zero)-jx_oo] = ZZ[jx]
  127. #print jx+(nx-jx_zero)-jx_oo, 'prend', jx, ' ', vlon[jx]
  128. #
  129. if ilon_ext == 0: ZZx_ext[:] = ZZx[:]
  130. #iwa = nmp.where(vlon0 < 0.) ; vlon0[iwa] = vlon0[iwa] + 360.
  131. #
  132. #
  133. #
  134. # Now longitude extenstion:
  135. if ilon_ext > 0: ZZx_ext = bt.extend_domain(ZZx, ilon_ext)
  136. del ZZx
  137. return ZZx_ext
  138. def conf_exp(ccexp):
  139. #
  140. # Find the CONF from CONF-EXP and exit if CONF does not exist!
  141. #
  142. i = 0 ; conf = ''
  143. while i < len(ccexp) and ccexp[i] != '-' : conf = conf+ccexp[i]; i=i+1
  144. #print 'conf =', conf, '\n'
  145. return conf
  146. def mean_3d(XD, LSM, XVOL):
  147. #
  148. # XD : 3D+T array containing data
  149. # LSM : 3D land sea mask
  150. # XVOL : 3D E1T*E2T*E3T : 3D mesh volume
  151. #
  152. # RETURN vmean: vector containing 3d-averaged values at each time record
  153. ( lt, lz, ly, lx ) = nmp.shape(XD)
  154. if nmp.shape(LSM) != ( lz, ly, lx ):
  155. print 'ERROR: mean_3d.barakuda_orca.py => XD and LSM do not agree in shape!'
  156. sys.exit(0)
  157. if nmp.shape(XVOL) != ( lz, ly, lx ):
  158. print 'ERROR: mean_3d.barakuda_orca.py => XD and XVOL do not agree in shape!'
  159. sys.exit(0)
  160. vmean = nmp.zeros(lt)
  161. XX = LSM[:,:,:]*XVOL[:,:,:]
  162. rd = nmp.sum( XX )
  163. XX = XX/rd
  164. if rd > 0.:
  165. for jt in range(lt):
  166. vmean[jt] = nmp.sum( XD[jt,:,:,:]*XX )
  167. else:
  168. vmean[:] = nmp.nan
  169. return vmean
  170. def mean_2d(XD, LSM, XAREA):
  171. #
  172. # XD : 2D+T array containing data
  173. # LSM : 2D land sea mask
  174. # XAREA : 2D E1T*E2T : mesh area
  175. #
  176. # RETURN vmean: vector containing 2d-averaged values at each time record
  177. ( lt, ly, lx ) = nmp.shape(XD)
  178. if nmp.shape(LSM) != ( ly, lx ):
  179. print 'ERROR: mean_2d.barakuda_orca.py => XD and LSM do not agree in shape!'
  180. sys.exit(0)
  181. if nmp.shape(XAREA) != ( ly, lx ):
  182. print 'ERROR: mean_2d.barakuda_orca.py => XD and XAREA do not agree in shape!'
  183. sys.exit(0)
  184. vmean = nmp.zeros(lt)
  185. XX = LSM[:,:]*XAREA[:,:]
  186. rd = nmp.sum( XX )
  187. # Sometimes LSM can be 0 everywhere! => rd == 0. !
  188. if rd > 0.:
  189. XX = XX/rd
  190. for jt in range(lt):
  191. vmean[jt] = nmp.sum( XD[jt,:,:]*XX )
  192. else:
  193. vmean[:] = nmp.nan
  194. return vmean
  195. def ij_from_xy(xx, yy, xlon, xlat):
  196. #
  197. #=============================================================
  198. # Input:
  199. # xx : longitude of searched point (float)
  200. # yy : latitude of searched point (float)
  201. # xlon : 2D array of longitudes of the ORCA grid
  202. # xlat : 2D array of latitudes of the ORCA grid
  203. # Output:
  204. # ( ji, jj ) : coresponding i and j indices on the ORCA grid
  205. #=============================================================
  206. #
  207. ji=0 ; jj=0
  208. #
  209. if xx < 0.: xx = xx + 360.
  210. #
  211. (nj , ni) = xlon.shape
  212. iwa = nmp.where(xlon < 0.) ; xlon[iwa] = xlon[iwa] + 360. # Want only positive values in longitude:
  213. #
  214. # Southernmost latitude of the ORCA domain:
  215. ji0 = nmp.argmin(xlat[0,:])
  216. lat_min = xlat[0,ji0]
  217. ji = ji0
  218. yy = max( yy, lat_min )
  219. #
  220. # Northernmost latitude of the ORCA domain:
  221. ji0 = nmp.argmax(xlat[nj-1,:])
  222. lat_max = xlat[nj-1,ji0]
  223. yy = min( yy, lat_max )
  224. #
  225. A = nmp.abs( xlat[:-2,:-2]-yy ) + nmp.abs( xlon[:-2,:-2]-xx )
  226. (jj,ji) = nmp.unravel_index(A.argmin(), A.shape)
  227. #
  228. return ( ji, jj )
  229. def transect_zon_or_med(x1, x2, y1, y2, xlon, xlat): #, rmin, rmax, dc):
  230. #
  231. #=============================================================
  232. # Input:
  233. # x1,x2 : longitudes of point P1 and P2 defining the section (zonal OR meridional)
  234. # y1,y2 : latitudes of point P1 and P2 defining the section (zonal OR meridional)
  235. # => so yes! either x1==x2 or y1==y2 !
  236. # xlon : 2D array of longitudes of the ORCA grid
  237. # xlat : 2D array of latitudes of the ORCA grid
  238. # Output:
  239. # ( ji1, ji2, jj1, jj2 ) : coresponding i and j indices on the ORCA grid
  240. #=============================================================
  241. #
  242. ji1=0 ; ji2=0 ; jj1=0 ; jj2=0
  243. lhori = False ; lvert = False
  244. #
  245. if y1 == y2: lhori = True
  246. if x1 == x2: lvert = True
  247. #
  248. if not (lhori or lvert) :
  249. print 'transect_zon_or_med only supports horizontal or vertical sections!'
  250. sys.exit(0)
  251. #
  252. (ji1,jj1) = ij_from_xy(x1, y1, xlon, xlat)
  253. (ji2,jj2) = ij_from_xy(x2, y2, xlon, xlat)
  254. #
  255. if lhori and (jj1 != jj2): jj2=jj1
  256. if lvert and (ji1 != ji2): ji2=ji1
  257. #
  258. return ( ji1, ji2, jj1, jj2 )
  259. def shrink_domain(LSM):
  260. # Decrasing the domain size to only retain the (rectangular region) with
  261. # ocean points (LSM == 1)
  262. #
  263. # Input:
  264. # LSM : 2D land sea mask array
  265. # Output:
  266. # (i1,j1,i2,j2): coordinates of the 2 points defining the rectangular region
  267. #
  268. ( ly, lx ) = nmp.shape(LSM)
  269. #
  270. #if nmp.shape(LSM) != ( lz, ly, lx ):
  271. # print 'ERROR: shrink_domain.barakuda_orca.py => XD and LSM do not agree in shape!'
  272. # sys.exit(0)
  273. (vjj , vji) = nmp.where(LSM[:,:]>0.5)
  274. j1 = max( nmp.min(vjj)-2 , 0 )
  275. i1 = max( nmp.min(vji)-2 , 0 )
  276. j2 = min( nmp.max(vjj)+2 , ly-1 ) + 1
  277. i2 = min( nmp.max(vji)+2 , lx-1 ) + 1
  278. #
  279. if (i1,j1,i2,j2) != (0,0,lx,ly):
  280. print ' ===> zooming on i1,j1 -> i2,j2:', i1,j1,'->',i2,j2
  281. if (i1,i2) == (0,lx): i2 = i2-2 ; # Mind east-west periodicity overlap of 2 points...
  282. #
  283. return (i1,j1,i2,j2)