# Pthon script to comput diagnostics # L. Fita, LMD. CNR, UPMC-Jussieu, Paris, France # File diagnostics.inf provides the combination of variables to get the desired diagnostic # To be used with module_ForDiagnostics.F90, module_ForDiagnosticsVars.F90, module_generic.F90 # foudre: f2py -m module_ForDiagnostics --f90exec=/usr/bin/gfortran-4.7 -c module_generic.F90 module_ForDiagnosticsVars.F90 module_ForDiagnostics.F90 >& run_f2py.log # ciclad: f2py --f90flags="-fPIC" --f90exec=/usr/bin/gfortran -L/opt/canopy-1.3.0/Canopy_64bit/System/lib/ -L/usr/lib64/ -L/opt/canopy-1.3.0/Canopy_64bit/System/lib/ -m module_ForDiagnostics -c module_generic.F90 module_ForDiagnosticsVars.F90 module_ForDiagnostics.F90 >& run_f2py.log ## e.g. # diagnostics.py -d 'Time@time,bottom_top@ZNU,south_north@XLAT,west_east@XLONG' -v 'clt|CLDFRA,cllmh|CLDFRA@WRFp,RAINTOT|RAINC@RAINNC@XTIME' -f WRF_LMDZ/NPv31/wrfout_d01_1980-03-01_00:00:00 ## e.g. # diagnostics.py -f /home/lluis/PY/diagnostics.inf -d variable_combo -v WRFprc from optparse import OptionParser import numpy as np from netCDF4 import Dataset as NetCDFFile import os import re import nc_var_tools as ncvar import generic_tools as gen import datetime as dtime import module_ForDiag as fdin main = 'diagnostics.py' errormsg = 'ERROR -- error -- ERROR -- error' warnmsg = 'WARNING -- warning -- WARNING -- warning' # Constants grav = 9.81 # Gneral information ## def reduce_spaces(string): """ Function to give words of a line of text removing any extra space """ values = string.replace('\n','').split(' ') vals = [] for val in values: if len(val) > 0: vals.append(val) return vals def variable_combo(varn,combofile): """ Function to provide variables combination from a given variable name varn= name of the variable combofile= ASCII file with the combination of variables [varn] [combo] [combo]: '@' separated list of variables to use to generate [varn] [WRFdt] to get WRF time-step (from general attributes) >>> variable_combo('WRFprls','/home/lluis/PY/diagnostics.inf') deaccum@RAINNC@XTIME@prnc """ fname = 'variable_combo' if varn == 'h': print fname + '_____________________________________________________________' print variable_combo.__doc__ quit() if not os.path.isfile(combofile): print errormsg print ' ' + fname + ": file with combinations '" + combofile + \ "' does not exist!!" quit(-1) objf = open(combofile, 'r') found = False for line in objf: linevals = reduce_spaces(line) varnf = linevals[0] combo = linevals[1].replace('\n','') if varn == varnf: found = True break if not found: print errormsg print ' ' + fname + ": variable '" + varn + "' not found in '" + combofile +\ "' !!" combo='ERROR' objf.close() return combo # Mathematical operators ## def compute_accum(varv, dimns, dimvns): """ Function to compute the accumulation of a variable compute_accum(varv, dimnames, dimvns) [varv]= values to accum (assuming [t,]) [dimns]= list of the name of the dimensions of the [varv] [dimvns]= list of the name of the variables with the values of the dimensions of [varv] """ fname = 'compute_accum' deacdims = dimns[:] deacvdims = dimvns[:] slicei = [] slicee = [] Ndims = len(varv.shape) for iid in range(0,Ndims): slicei.append(slice(0,varv.shape[iid])) slicee.append(slice(0,varv.shape[iid])) slicee[0] = np.arange(varv.shape[0]) slicei[0] = np.arange(varv.shape[0]) slicei[0][1:varv.shape[0]] = np.arange(varv.shape[0]-1) vari = varv[tuple(slicei)] vare = varv[tuple(slicee)] ac = vari*0. for it in range(1,varv.shape[0]): ac[it,] = ac[it-1,] + vare[it,] return ac, deacdims, deacvdims def compute_deaccum(varv, dimns, dimvns): """ Function to compute the deaccumulation of a variable compute_deaccum(varv, dimnames, dimvns) [varv]= values to deaccum (assuming [t,]) [dimns]= list of the name of the dimensions of the [varv] [dimvns]= list of the name of the variables with the values of the dimensions of [varv] """ fname = 'compute_deaccum' deacdims = dimns[:] deacvdims = dimvns[:] slicei = [] slicee = [] Ndims = len(varv.shape) for iid in range(0,Ndims): slicei.append(slice(0,varv.shape[iid])) slicee.append(slice(0,varv.shape[iid])) slicee[0] = np.arange(varv.shape[0]) slicei[0] = np.arange(varv.shape[0]) slicei[0][1:varv.shape[0]] = np.arange(varv.shape[0]-1) vari = varv[tuple(slicei)] vare = varv[tuple(slicee)] deac = vare - vari return deac, deacdims, deacvdims def derivate_centered(var,dim,dimv): """ Function to compute the centered derivate of a given field centered derivate(n) = (var(n-1) + var(n+1))/(2*dn). [var]= variable [dim]= which dimension to compute the derivate [dimv]= dimension values (can be of different dimension of [var]) >>> derivate_centered(np.arange(16).reshape(4,4)*1.,1,1.) [[ 0. 1. 2. 0.] [ 0. 5. 6. 0.] [ 0. 9. 10. 0.] [ 0. 13. 14. 0.]] """ fname = 'derivate_centered' vark = var.dtype if hasattr(dimv, "__len__"): # Assuming that the last dimensions of var [..., N, M] are the same of dimv [N, M] if len(var.shape) != len(dimv.shape): dimvals = np.zeros((var.shape), dtype=vark) if len(var.shape) - len(dimv.shape) == 1: for iz in range(var.shape[0]): dimvals[iz,] = dimv elif len(var.shape) - len(dimv.shape) == 2: for it in range(var.shape[0]): for iz in range(var.shape[1]): dimvals[it,iz,] = dimv else: print errormsg print ' ' + fname + ': dimension difference between variable', \ var.shape,'and variable with dimension values',dimv.shape, \ ' not ready !!!' quit(-1) else: dimvals = dimv else: # dimension values are identical everywhere! # from: http://stackoverflow.com/questions/16807011/python-how-to-identify-if-a-variable-is-an-array-or-a-scalar dimvals = np.ones((var.shape), dtype=vark)*dimv derivate = np.zeros((var.shape), dtype=vark) if dim > len(var.shape) - 1: print errormsg print ' ' + fname + ': dimension',dim,' too big for given variable of ' + \ 'shape:', var.shape,'!!!' quit(-1) slicebef = [] sliceaft = [] sliceder = [] for id in range(len(var.shape)): if id == dim: slicebef.append(slice(0,var.shape[id]-2)) sliceaft.append(slice(2,var.shape[id])) sliceder.append(slice(1,var.shape[id]-1)) else: slicebef.append(slice(0,var.shape[id])) sliceaft.append(slice(0,var.shape[id])) sliceder.append(slice(0,var.shape[id])) if hasattr(dimv, "__len__"): derivate[tuple(sliceder)] = (var[tuple(slicebef)] + var[tuple(sliceaft)])/ \ ((dimvals[tuple(sliceaft)] - dimvals[tuple(slicebef)])) print (dimvals[tuple(sliceaft)] - dimvals[tuple(slicebef)]) else: derivate[tuple(sliceder)] = (var[tuple(slicebef)] + var[tuple(sliceaft)])/ \ (2.*dimv) # print 'before________' # print var[tuple(slicebef)] # print 'after________' # print var[tuple(sliceaft)] return derivate def rotational_z(Vx,Vy,pos): """ z-component of the rotatinoal of horizontal vectorial field \/ x (Vx,Vy,Vz) = \/xVy - \/yVx [Vx]= Variable component x [Vy]= Variable component y [pos]= poisition of the grid points >>> rotational_z(np.arange(16).reshape(4,4)*1., np.arange(16).reshape(4,4)*1., 1.) [[ 0. 1. 2. 0.] [ -4. 0. 0. -7.] [ -8. 0. 0. -11.] [ 0. 13. 14. 0.]] """ fname = 'rotational_z' ndims = len(Vx.shape) rot1 = derivate_centered(Vy,ndims-1,pos) rot2 = derivate_centered(Vx,ndims-2,pos) rot = rot1 - rot2 return rot # Diagnostics ## def var_clt(cfra): """ Function to compute the total cloud fraction following 'newmicro.F90' from LMDZ using 1D vertical column values [cldfra]= cloud fraction values (assuming [[t],z,y,x]) """ ZEPSEC=1.0E-12 fname = 'var_clt' zclear = 1. zcloud = 0. dz = cfra.shape[0] for iz in range(dz): zclear =zclear*(1.-np.max([cfra[iz],zcloud]))/(1.-np.min([zcloud,1.-ZEPSEC])) clt = 1. - zclear zcloud = cfra[iz] return clt def compute_clt(cldfra, dimns, dimvns): """ Function to compute the total cloud fraction following 'newmicro.F90' from LMDZ compute_clt(cldfra, dimnames) [cldfra]= cloud fraction values (assuming [[t],z,y,x]) [dimns]= list of the name of the dimensions of [cldfra] [dimvns]= list of the name of the variables with the values of the dimensions of [cldfra] """ fname = 'compute_clt' cltdims = dimns[:] cltvdims = dimvns[:] if len(cldfra.shape) == 4: clt = np.zeros((cldfra.shape[0],cldfra.shape[2],cldfra.shape[3]), \ dtype=np.float) dx = cldfra.shape[3] dy = cldfra.shape[2] dz = cldfra.shape[1] dt = cldfra.shape[0] cltdims.pop(1) cltvdims.pop(1) for it in range(dt): for ix in range(dx): for iy in range(dy): zclear = 1. zcloud = 0. ncvar.percendone(it*dx*dy + ix*dy + iy, dx*dy*dt, 5, 'diagnosted') clt[it,iy,ix] = var_clt(cldfra[it,:,iy,ix]) else: clt = np.zeros((cldfra.shape[1],cldfra.shape[2]), dtype=np.float) dx = cldfra.shape[2] dy = cldfra.shape[1] dy = cldfra.shape[0] cltdims.pop(0) cltvdims.pop(0) for ix in range(dx): for iy in range(dy): zclear = 1. zcloud = 0. ncvar.percendone(ix*dy + iy, dx*dy*dt, 5, 'diagnosted') clt[iy,ix] = var_clt(cldfra[:,iy,ix]) return clt, cltdims, cltvdims def Forcompute_clt(cldfra, dimns, dimvns): """ Function to compute the total cloud fraction following 'newmicro.F90' from LMDZ via a Fortran module compute_clt(cldfra, dimnames) [cldfra]= cloud fraction values (assuming [[t],z,y,x]) [dimns]= list of the name of the dimensions of [cldfra] [dimvns]= list of the name of the variables with the values of the dimensions of [cldfra] """ fname = 'Forcompute_clt' cltdims = dimns[:] cltvdims = dimvns[:] if len(cldfra.shape) == 4: clt = np.zeros((cldfra.shape[0],cldfra.shape[2],cldfra.shape[3]), \ dtype=np.float) dx = cldfra.shape[3] dy = cldfra.shape[2] dz = cldfra.shape[1] dt = cldfra.shape[0] cltdims.pop(1) cltvdims.pop(1) clt = fdin.module_fordiagnostics.compute_clt4d2(cldfra[:]) else: clt = np.zeros((cldfra.shape[1],cldfra.shape[2]), dtype=np.float) dx = cldfra.shape[2] dy = cldfra.shape[1] dy = cldfra.shape[0] cltdims.pop(0) cltvdims.pop(0) clt = fdin.module_fordiagnostics.compute_clt3d1(cldfra[:]) return clt, cltdims, cltvdims def var_cllmh(cfra, p): """ Fcuntion to compute cllmh on a 1D column """ fname = 'var_cllmh' ZEPSEC =1.0E-12 prmhc = 440.*100. prmlc = 680.*100. zclearl = 1. zcloudl = 0. zclearm = 1. zcloudm = 0. zclearh = 1. zcloudh = 0. dvz = cfra.shape[0] cllmh = np.ones((3), dtype=np.float) for iz in range(dvz): if p[iz] < prmhc: cllmh[2] = cllmh[2]*(1.-np.max([cfra[iz], zcloudh]))/(1.- \ np.min([zcloudh,1.-ZEPSEC])) zcloudh = cfra[iz] elif p[iz] >= prmhc and p[iz] < prmlc: cllmh[1] = cllmh[1]*(1.-np.max([cfra[iz], zcloudm]))/(1.- \ np.min([zcloudm,1.-ZEPSEC])) zcloudm = cfra[iz] elif p[iz] >= prmlc: cllmh[0] = cllmh[0]*(1.-np.max([cfra[iz], zcloudl]))/(1.- \ np.min([zcloudl,1.-ZEPSEC])) zcloudl = cfra[iz] cllmh = 1.- cllmh return cllmh def Forcompute_cllmh(cldfra, pres, dimns, dimvns): """ Function to compute cllmh: low/medium/hight cloud fraction following newmicro.F90 from LMDZ via Fortran subroutine compute_clt(cldfra, pres, dimns, dimvns) [cldfra]= cloud fraction values (assuming [[t],z,y,x]) [pres] = pressure field [dimns]= list of the name of the dimensions of [cldfra] [dimvns]= list of the name of the variables with the values of the dimensions of [cldfra] """ fname = 'Forcompute_cllmh' cllmhdims = dimns[:] cllmhvdims = dimvns[:] if len(cldfra.shape) == 4: dx = cldfra.shape[3] dy = cldfra.shape[2] dz = cldfra.shape[1] dt = cldfra.shape[0] cllmhdims.pop(1) cllmhvdims.pop(1) cllmh = fdin.module_fordiagnostics.compute_cllmh4d2(cldfra[:], pres[:]) else: dx = cldfra.shape[2] dy = cldfra.shape[1] dz = cldfra.shape[0] cllmhdims.pop(0) cllmhvdims.pop(0) cllmh = fdin.module_fordiagnostics.compute_cllmh3d1(cldfra[:], pres[:]) return cllmh, cllmhdims, cllmhvdims def compute_cllmh(cldfra, pres, dimns, dimvns): """ Function to compute cllmh: low/medium/hight cloud fraction following newmicro.F90 from LMDZ compute_clt(cldfra, pres, dimns, dimvns) [cldfra]= cloud fraction values (assuming [[t],z,y,x]) [pres] = pressure field [dimns]= list of the name of the dimensions of [cldfra] [dimvns]= list of the name of the variables with the values of the dimensions of [cldfra] """ fname = 'compute_cllmh' cllmhdims = dimns[:] cllmhvdims = dimvns[:] if len(cldfra.shape) == 4: dx = cldfra.shape[3] dy = cldfra.shape[2] dz = cldfra.shape[1] dt = cldfra.shape[0] cllmhdims.pop(1) cllmhvdims.pop(1) cllmh = np.ones(tuple([3, dt, dy, dx]), dtype=np.float) for it in range(dt): for ix in range(dx): for iy in range(dy): ncvar.percendone(it*dx*dy + ix*dy + iy, dx*dy*dt, 5, 'diagnosted') cllmh[:,it,iy,ix] = var_cllmh(cldfra[it,:,iy,ix], pres[it,:,iy,ix]) else: dx = cldfra.shape[2] dy = cldfra.shape[1] dz = cldfra.shape[0] cllmhdims.pop(0) cllmhvdims.pop(0) cllmh = np.ones(tuple([3, dy, dx]), dtype=np.float) for ix in range(dx): for iy in range(dy): ncvar.percendone(ix*dy + iy,dx*dy, 5, 'diagnosted') cllmh[:,iy,ix] = var_cllmh(cldfra[:,iy,ix], pres[:,iy,ix]) return cllmh, cllmhdims, cllmhvdims def var_virtualTemp (temp,rmix): """ This function returns virtual temperature in K, temp: temperature [K] rmix: mixing ratio in [kgkg-1] """ fname = 'var_virtualTemp' virtual=temp*(0.622+rmix)/(0.622*(1.+rmix)) return virtual def var_mslp(pres, psfc, ter, tk, qv): """ Function to compute mslp on a 1D column """ fname = 'var_mslp' N = 1.0 expon=287.04*.0065/9.81 pref = 40000. # First find where about 400 hPa is located dz=len(pres) kref = -1 pinc = pres[0] - pres[dz-1] if pinc < 0.: for iz in range(1,dz): if pres[iz-1] >= pref and pres[iz] < pref: kref = iz break else: for iz in range(dz-1): if pres[iz] >= pref and pres[iz+1] < pref: kref = iz break if kref == -1: print errormsg print ' ' + fname + ': no reference pressure:',pref,'found!!' print ' values:',pres[:] quit(-1) mslp = 0. # We are below both the ground and the lowest data level. # First, find the model level that is closest to a "target" pressure # level, where the "target" pressure is delta-p less that the local # value of a horizontally smoothed surface pressure field. We use # delta-p = 150 hPa here. A standard lapse rate temperature profile # passing through the temperature at this model level will be used # to define the temperature profile below ground. This is similar # to the Benjamin and Miller (1990) method, using # 700 hPa everywhere for the "target" pressure. # ptarget = psfc - 15000. ptarget = 70000. dpmin=1.e4 kupper = 0 if pinc > 0.: for iz in range(dz-1,0,-1): kupper = iz dp=np.abs( pres[iz] - ptarget ) if dp < dpmin: exit dpmin = np.min([dpmin, dp]) else: for iz in range(dz): kupper = iz dp=np.abs( pres[iz] - ptarget ) if dp < dpmin: exit dpmin = np.min([dpmin, dp]) pbot=np.max([pres[0], psfc]) # zbot=0. # tbotextrap=tk(i,j,kupper,itt)*(pbot/pres_field(i,j,kupper,itt))**expon # tvbotextrap=virtual(tbotextrap,qv(i,j,1,itt)) # data_out(i,j,itt,1) = (zbot+tvbotextrap/.0065*(1.-(interp_levels(1)/pbot)**expon)) tbotextrap = tk[kupper]*(psfc/ptarget)**expon tvbotextrap = var_virtualTemp(tbotextrap, qv[kupper]) mslp = psfc*( (tvbotextrap+0.0065*ter)/tvbotextrap)**(1./expon) return mslp def compute_mslp(pressure, psurface, terrain, temperature, qvapor, dimns, dimvns): """ Function to compute mslp: mean sea level pressure following p_interp.F90 from WRF var_mslp(pres, ter, tk, qv, dimns, dimvns) [pressure]= pressure field [Pa] (assuming [[t],z,y,x]) [psurface]= surface pressure field [Pa] [terrain]= topography [m] [temperature]= temperature [K] [qvapor]= water vapour mixing ratio [kgkg-1] [dimns]= list of the name of the dimensions of [cldfra] [dimvns]= list of the name of the variables with the values of the dimensions of [pres] """ fname = 'compute_mslp' mslpdims = list(dimns[:]) mslpvdims = list(dimvns[:]) if len(pressure.shape) == 4: mslpdims.pop(1) mslpvdims.pop(1) else: mslpdims.pop(0) mslpvdims.pop(0) if len(pressure.shape) == 4: dx = pressure.shape[3] dy = pressure.shape[2] dz = pressure.shape[1] dt = pressure.shape[0] mslpv = np.zeros(tuple([dt, dy, dx]), dtype=np.float) # Terrain... to 2D ! terval = np.zeros(tuple([dy, dx]), dtype=np.float) if len(terrain.shape) == 3: terval = terrain[0,:,:] else: terval = terrain for ix in range(dx): for iy in range(dy): if terval[iy,ix] > 0.: for it in range(dt): mslpv[it,iy,ix] = var_mslp(pressure[it,:,iy,ix], \ psurface[it,iy,ix], terval[iy,ix], temperature[it,:,iy,ix],\ qvapor[it,:,iy,ix]) ncvar.percendone(it*dx*dy + ix*dy + iy, dx*dy*dt, 5, 'diagnosted') else: mslpv[:,iy,ix] = psurface[:,iy,ix] else: dx = pressure.shape[2] dy = pressure.shape[1] dz = pressure.shape[0] mslpv = np.zeros(tuple([dy, dx]), dtype=np.float) # Terrain... to 2D ! terval = np.zeros(tuple([dy, dx]), dtype=np.float) if len(terrain.shape) == 3: terval = terrain[0,:,:] else: terval = terrain for ix in range(dx): for iy in range(dy): ncvar.percendone(ix*dy + iy,dx*dy, 5, 'diagnosted') if terval[iy,ix] > 0.: mslpv[iy,ix] = var_mslp(pressure[:,iy,ix], psurface[iy,ix], \ terval[iy,ix], temperature[:,iy,ix], qvapor[:,iy,ix]) else: mslpv[iy,ix] = psfc[iy,ix] return mslpv, mslpdims, mslpvdims def compute_OMEGAw(omega, p, t, dimns, dimvns): """ Function to transform OMEGA [Pas-1] to velocities [ms-1] tacking: https://www.ncl.ucar.edu/Document/Functions/Contributed/omega_to_w.shtml [omega] = vertical velocity [in ms-1] (assuming [t],z,y,x) [p] = pressure in [Pa] (assuming [t],z,y,x) [t] = temperature in [K] (assuming [t],z,y,x) [dimns]= list of the name of the dimensions of [q] [dimvns]= list of the name of the variables with the values of the dimensions of [q] """ fname = 'compute_OMEGAw' rgas = 287.058 # J/(kg-K) => m2/(s2 K) g = 9.80665 # m/s2 wdims = dimns[:] wvdims = dimvns[:] rho = p/(rgas*t) # density => kg/m3 w = -omega/(rho*g) return w, wdims, wvdims def compute_prw(dens, q, dimns, dimvns): """ Function to compute water vapour path (prw) [dens] = density [in kgkg-1] (assuming [t],z,y,x) [q] = mixing ratio in [kgkg-1] (assuming [t],z,y,x) [dimns]= list of the name of the dimensions of [q] [dimvns]= list of the name of the variables with the values of the dimensions of [q] """ fname = 'compute_prw' prwdims = dimns[:] prwvdims = dimvns[:] if len(q.shape) == 4: prwdims.pop(1) prwvdims.pop(1) else: prwdims.pop(0) prwvdims.pop(0) data1 = dens*q prw = np.sum(data1, axis=1) return prw, prwdims, prwvdims def compute_rh(p, t, q, dimns, dimvns): """ Function to compute relative humidity following 'Tetens' equation (T,P) ...' [t]= temperature (assuming [[t],z,y,x] in [K]) [p] = pressure field (assuming in [hPa]) [q] = mixing ratio in [kgkg-1] [dimns]= list of the name of the dimensions of [t] [dimvns]= list of the name of the variables with the values of the dimensions of [t] """ fname = 'compute_rh' rhdims = dimns[:] rhvdims = dimvns[:] data1 = 10.*0.6112*np.exp(17.67*(t-273.16)/(t-29.65)) data2 = 0.622*data1/(0.01*p-(1.-0.622)*data1) rh = q/data2 return rh, rhdims, rhvdims def compute_td(p, temp, qv, dimns, dimvns): """ Function to compute the dew point temperature [p]= pressure [Pa] [temp]= temperature [C] [qv]= mixing ratio [kgkg-1] [dimns]= list of the name of the dimensions of [p] [dimvns]= list of the name of the variables with the values of the dimensions of [p] """ fname = 'compute_td' # print ' ' + fname + ': computing dew-point temperature from TS as t and Tetens...' # tacking from: http://en.wikipedia.org/wiki/Dew_point tk = temp data1 = 10.*0.6112*np.exp(17.67*(tk-273.16)/(tk-29.65)) data2 = 0.622*data1/(0.01*p-(1.-0.622)*data1) rh = qv/data2 pa = rh * data1 td = 257.44*np.log(pa/6.1121)/(18.678-np.log(pa/6.1121)) tddims = dimns[:] tdvdims = dimvns[:] return td, tddims, tdvdims def turbulence_var(varv, dimvn, dimn): """ Function to compute the Taylor's decomposition turbulence term from a a given variable x*=_t-(_t)^2 turbulence_var(varv,dimn) varv= values of the variable dimvn= names of the dimension of the variable dimn= names of the dimensions (as a dictionary with 'X', 'Y', 'Z', 'T') >>> turbulence_var(np.arange((27)).reshape(3,3,3),['time','y','x'],{'T':'time', 'Y':'y', 'X':'x'}) [[ 54. 54. 54.] [ 54. 54. 54.] [ 54. 54. 54.]] """ fname = 'turbulence_varv' timedimid = dimvn.index(dimn['T']) varv2 = varv*varv vartmean = np.mean(varv, axis=timedimid) var2tmean = np.mean(varv2, axis=timedimid) varvturb = var2tmean - (vartmean*vartmean) return varvturb def compute_turbulence(v, dimns, dimvns): """ Function to compute the rubulence term of the Taylor's decomposition ...' x*=_t-(_t)^2 [v]= variable (assuming [[t],z,y,x]) [dimns]= list of the name of the dimensions of [v] [dimvns]= list of the name of the variables with the values of the dimensions of [v] """ fname = 'compute_turbulence' turbdims = dimns[:] turbvdims = dimvns[:] turbdims.pop(0) turbvdims.pop(0) v2 = v*v vartmean = np.mean(v, axis=0) var2tmean = np.mean(v2, axis=0) turb = var2tmean - (vartmean*vartmean) return turb, turbdims, turbvdims def compute_wds(u, v, dimns, dimvns): """ Function to compute the wind direction [u]= W-E wind direction [ms-1, knot, ...] [v]= N-S wind direction [ms-1, knot, ...] [dimns]= list of the name of the dimensions of [u] [dimvns]= list of the name of the variables with the values of the dimensions of [u] """ fname = 'compute_wds' # print ' ' + fname + ': computing wind direction as ATAN2(v,u) ...' theta = np.arctan2(v,u) theta = np.where(theta < 0., theta + 2.*np.pi, theta) wds = 360.*theta/(2.*np.pi) wdsdims = dimns[:] wdsvdims = dimvns[:] return wds, wdsdims, wdsvdims def compute_wss(u, v, dimns, dimvns): """ Function to compute the wind speed [u]= W-E wind direction [ms-1, knot, ...] [v]= N-S wind direction [ms-1, knot, ...] [dimns]= list of the name of the dimensions of [u] [dimvns]= list of the name of the variables with the values of the dimensions of [u] """ fname = 'compute_wss' # print ' ' + fname + ': computing wind speed as SQRT(v**2 + u**2) ...' wss = np.sqrt(u*u + v*v) wssdims = dimns[:] wssvdims = dimvns[:] return wss, wssdims, wssvdims def timeunits_seconds(dtu): """ Function to transform a time units to seconds timeunits_seconds(timeuv) [dtu]= time units value to transform in seconds """ fname='timunits_seconds' if dtu == 'years': times = 365.*24.*3600. elif dtu == 'weeks': times = 7.*24.*3600. elif dtu == 'days': times = 24.*3600. elif dtu == 'hours': times = 3600. elif dtu == 'minutes': times = 60. elif dtu == 'seconds': times = 1. elif dtu == 'miliseconds': times = 1./1000. else: print errormsg print ' ' + fname + ": time units '" + dtu + "' not ready !!" quit(-1) return times ####### ###### ##### #### ### ## # comboinf="\nIF -d 'variable_combo', provides information of the combination to obtain -v [varn] with the ASCII file with the combinations as -f [combofile]" parser = OptionParser() parser.add_option("-f", "--netCDF_file", dest="ncfile", help="file to use", metavar="FILE") parser.add_option("-d", "--dimensions", dest="dimns", help="[dimtn]@[dtvn],[dimzn]@[dzvn],[...,[dimxn]@[dxvn]], ',' list with the couples [dimDn]@[dDvn], [dimDn], name of the dimension D and name of the variable [dDvn] with the values of the dimension ('WRFtime', for WRF time copmutation)" + comboinf, metavar="LABELS") parser.add_option("-v", "--variables", dest="varns", help=" [varn1]|[var11]@[...[varN1]],[...,[varnM]|[var1M]@[...[varLM]]] ',' list of variables to compute [varnK] and its necessary ones [var1K]...[varPK]", metavar="VALUES") (opts, args) = parser.parse_args() ####### ####### ## MAIN ####### availdiags = ['ACRAINTOT', 'accum', 'clt', 'cllmh', 'deaccum', 'LMDZrh', 'mslp', \ 'OMEGAw', 'RAINTOT', \ 'rvors', 'td', 'turbulence', 'WRFgeop', 'WRFp', 'WRFrvors', 'ws', 'wds', 'wss', \ 'WRFheight', 'WRFheightrel', 'WRFua', 'WRFva'] methods = ['accum', 'deaccum'] # Variables not to check NONcheckingvars = ['cllmh', 'deaccum', 'TSrhs', 'TStd', 'TSwds', 'TSwss', 'WRFbils', \ 'WRFdens', 'WRFgeop', \ 'WRFp', 'WRFtd', \ 'WRFpos', 'WRFprc', 'WRFprls', 'WRFrh', 'LMDZrh', 'LMDZrhs', 'WRFrhs', 'WRFrvors', \ 'WRFt', 'WRFtime', 'WRFua', 'WRFva', 'WRFwds', 'WRFwss', 'WRFheight'] NONchkvardims = ['WRFtime'] ofile = 'diagnostics.nc' dimns = opts.dimns varns = opts.varns # Special method. knowing variable combination ## if opts.dimns == 'variable_combo': print warnmsg print ' ' + main + ': knowing variable combination !!!' combination = variable_combo(opts.varns,opts.ncfile) print ' COMBO: ' + combination quit(-1) if not os.path.isfile(opts.ncfile): print errormsg print ' ' + main + ": file '" + opts.ncfile + "' does not exist !!" quit(-1) ncobj = NetCDFFile(opts.ncfile, 'r') # Looking for specific variables that might be use in more than one diagnostic WRFgeop_compute = False WRFp_compute = False WRFt_compute = False WRFrh_compute = False WRFght_compute = False WRFdens_compute = False WRFpos_compute = False WRFtime_compute = False # File creation newnc = NetCDFFile(ofile,'w') # dimensions dimvalues = dimns.split(',') dnames = [] dvnames = [] for dimval in dimvalues: dn = dimval.split('@')[0] dnv = dimval.split('@')[1] dnames.append(dn) dvnames.append(dnv) # Is there any dimension-variable which should be computed? if dnv == 'WRFgeop':WRFgeop_compute = True if dnv == 'WRFp': WRFp_compute = True if dnv == 'WRFt': WRFt_compute = True if dnv == 'WRFrh': WRFrh_compute = True if dnv == 'WRFght': WRFght_compute = True if dnv == 'WRFdens': WRFdens_compute = True if dnv == 'WRFpos': WRFpos_compute = True if dnv == 'WRFtime': WRFtime_compute = True # diagnostics to compute diags = varns.split(',') Ndiags = len(diags) for idiag in range(Ndiags): if diags[idiag].split('|')[1].find('@') == -1: depvars = diags[idiag].split('|')[1] if depvars == 'WRFgeop':WRFgeop_compute = True if depvars == 'WRFp': WRFp_compute = True if depvars == 'WRFt': WRFt_compute = True if depvars == 'WRFrh': WRFrh_compute = True if depvars == 'WRFght': WRFght_compute = True if depvars == 'WRFdens': WRFdens_compute = True if depvars == 'WRFpos': WRFpos_compute = True if depvars == 'WRFtime': WRFtime_compute = True else: depvars = diags[idiag].split('|')[1].split('@') if gen.searchInlist(depvars, 'WRFgeop'): WRFgeop_compute = True if gen.searchInlist(depvars, 'WRFp'): WRFp_compute = True if gen.searchInlist(depvars, 'WRFt'): WRFt_compute = True if gen.searchInlist(depvars, 'WRFrh'): WRFrh_compute = True if gen.searchInlist(depvars, 'WRFght'): WRFght_compute = True if gen.searchInlist(depvars, 'WRFdens'): WRFdens_compute = True if gen.searchInlist(depvars, 'WRFpos'): WRFpos_compute = True if gen.searchInlist(depvars, 'WRFtime'): WRFtime_compute = True # Dictionary with the new computed variables to be able to add them dictcompvars = {} if WRFgeop_compute: print ' ' + main + ': Retrieving geopotential value from WRF as PH + PHB' dimv = ncobj.variables['PH'].shape WRFgeop = ncobj.variables['PH'][:] + ncobj.variables['PHB'][:] # Attributes of the variable Vvals = gen.variables_values('WRFgeop') dictcompvars['WRFgeop'] = {'name': Vvals[0], 'standard_name': Vvals[1], \ 'long_name': Vvals[4].replace('|',' '), 'units': Vvals[5]} if WRFp_compute: print ' ' + main + ': Retrieving pressure value from WRF as P + PB' dimv = ncobj.variables['P'].shape WRFp = ncobj.variables['P'][:] + ncobj.variables['PB'][:] # Attributes of the variable Vvals = gen.variables_values('WRFp') dictcompvars['WRFgeop'] = {'name': Vvals[0], 'standard_name': Vvals[1], \ 'long_name': Vvals[4].replace('|',' '), 'units': Vvals[5]} if WRFght_compute: print ' ' + main + ': computing geopotential height from WRF as PH + PHB ...' WRFght = ncobj.variables['PH'][:] + ncobj.variables['PHB'][:] # Attributes of the variable Vvals = gen.variables_values('WRFght') dictcompvars['WRFgeop'] = {'name': Vvals[0], 'standard_name': Vvals[1], \ 'long_name': Vvals[4].replace('|',' '), 'units': Vvals[5]} if WRFrh_compute: print ' ' + main + ": computing relative humidity from WRF as 'Tetens'" + \ ' equation (T,P) ...' p0=100000. p=ncobj.variables['P'][:] + ncobj.variables['PB'][:] tk = (ncobj.variables['T'][:] + 300.)*(p/p0)**(2./7.) qv = ncobj.variables['QVAPOR'][:] data1 = 10.*0.6112*np.exp(17.67*(tk-273.16)/(tk-29.65)) data2 = 0.622*data1/(0.01*p-(1.-0.622)*data1) WRFrh = qv/data2 # Attributes of the variable Vvals = gen.variables_values('WRFrh') dictcompvars['WRFrh'] = {'name': Vvals[0], 'standard_name': Vvals[1], \ 'long_name': Vvals[4].replace('|',' '), 'units': Vvals[5]} if WRFt_compute: print ' ' + main + ': computing temperature from WRF as inv_potT(T + 300) ...' p0=100000. p=ncobj.variables['P'][:] + ncobj.variables['PB'][:] WRFt = (ncobj.variables['T'][:] + 300.)*(p/p0)**(2./7.) # Attributes of the variable Vvals = gen.variables_values('WRFt') dictcompvars['WRFt'] = {'name': Vvals[0], 'standard_name': Vvals[1], \ 'long_name': Vvals[4].replace('|',' '), 'units': Vvals[5]} if WRFdens_compute: print ' ' + main + ': computing air density from WRF as ((MU + MUB) * ' + \ 'DNW)/g ...' # Just we need in in absolute values: Size of the central grid cell ## dxval = ncobj.getncattr('DX') ## dyval = ncobj.getncattr('DY') ## mapfac = ncobj.variables['MAPFAC_M'][:] ## area = dxval*dyval*mapfac mu = (ncobj.variables['MU'][:] + ncobj.variables['MUB'][:]) dnw = ncobj.variables['DNW'][:] WRFdens = np.zeros((mu.shape[0], dnw.shape[1], mu.shape[1], mu.shape[2]), \ dtype=np.float) levval = np.zeros((mu.shape[1], mu.shape[2]), dtype=np.float) for it in range(mu.shape[0]): for iz in range(dnw.shape[1]): levval.fill(np.abs(dnw[it,iz])) WRFdens[it,iz,:,:] = levval WRFdens[it,iz,:,:] = mu[it,:,:]*WRFdens[it,iz,:,:]/grav # Attributes of the variable Vvals = gen.variables_values('WRFdens') dictcompvars['WRFdens'] = {'name': Vvals[0], 'standard_name': Vvals[1], \ 'long_name': Vvals[4].replace('|',' '), 'units': Vvals[5]} if WRFpos_compute: # WRF positions from the lowest-leftest corner of the matrix print ' ' + main + ': computing position from MAPFAC_M as sqrt(DY*j**2 + ' + \ 'DX*x**2)*MAPFAC_M ...' mapfac = ncobj.variables['MAPFAC_M'][:] distx = np.float(ncobj.getncattr('DX')) disty = np.float(ncobj.getncattr('DY')) print 'distx:',distx,'disty:',disty dx = mapfac.shape[2] dy = mapfac.shape[1] dt = mapfac.shape[0] WRFpos = np.zeros((dt, dy, dx), dtype=np.float) for i in range(1,dx): WRFpos[0,0,i] = distx*i/mapfac[0,0,i] for j in range(1,dy): i=0 WRFpos[0,j,i] = WRFpos[0,j-1,i] + disty/mapfac[0,j,i] for i in range(1,dx): # WRFpos[0,j,i] = np.sqrt((disty*j)**2. + (distx*i)**2.)/mapfac[0,j,i] # WRFpos[0,j,i] = np.sqrt((disty*j)**2. + (distx*i)**2.) WRFpos[0,j,i] = WRFpos[0,j,i-1] + distx/mapfac[0,j,i] for it in range(1,dt): WRFpos[it,:,:] = WRFpos[0,:,:] if WRFtime_compute: print ' ' + main + ': computing time from WRF as CFtime(Times) ...' refdate='19491201000000' tunitsval='minutes' timeobj = ncobj.variables['Times'] timewrfv = timeobj[:] yrref=refdate[0:4] monref=refdate[4:6] dayref=refdate[6:8] horref=refdate[8:10] minref=refdate[10:12] secref=refdate[12:14] refdateS = yrref + '-' + monref + '-' + dayref + ' ' + horref + ':' + minref + \ ':' + secref dt = timeobj.shape[0] WRFtime = np.zeros((dt), dtype=np.float) for it in range(dt): wrfdates = gen.datetimeStr_conversion(timewrfv[it,:],'WRFdatetime', 'matYmdHMS') WRFtime[it] = gen.realdatetime1_CFcompilant(wrfdates, refdate, tunitsval) tunits = tunitsval + ' since ' + refdateS # Attributes of the variable dictcompvars['WRFtime'] = {'name': 'time', 'standard_name': 'time', \ 'long_name': 'time', 'units': tunits, 'calendar': 'gregorian'} ### ## # # Going for the diagnostics ### ## # print ' ' + main + ' ...' varsadd = [] for idiag in range(Ndiags): print ' diagnostic:',diags[idiag] diag = diags[idiag].split('|')[0] depvars = diags[idiag].split('|')[1].split('@') if diags[idiag].split('|')[1].find('@') != -1: depvars = diags[idiag].split('|')[1].split('@') if depvars[0] == 'deaccum': diag='deaccum' if depvars[0] == 'accum': diag='accum' for depv in depvars: if not ncobj.variables.has_key(depv) and not \ gen.searchInlist(NONcheckingvars, depv) and \ not gen.searchInlist(methods, depv) and not depvars[0] == 'deaccum' \ and not depvars[0] == 'accum': print errormsg print ' ' + main + ": file '" + opts.ncfile + \ "' does not have variable '" + depv + "' !!" quit(-1) else: depvars = diags[idiag].split('|')[1] if not ncobj.variables.has_key(depvars) and not \ gen.searchInlist(NONcheckingvars, depvars) and \ not gen.searchInlist(methods, depvars): print errormsg print ' ' + main + ": file '" + opts.ncfile + \ "' does not have variable '" + depvars + "' !!" quit(-1) print "\n Computing '" + diag + "' from: ", depvars, '...' # acraintot: accumulated total precipitation from WRF RAINC, RAINNC if diag == 'ACRAINTOT': var0 = ncobj.variables[depvars[0]] var1 = ncobj.variables[depvars[1]] diagout = var0[:] + var1[:] dnamesvar = var0.dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) ncvar.insert_variable(ncobj, 'pracc', diagout, dnamesvar, dvnamesvar, newnc) # accum: acumulation of any variable as (Variable, time [as [tunits] # from/since ....], newvarname) elif diag == 'accum': var0 = ncobj.variables[depvars[0]] var1 = ncobj.variables[depvars[1]] dnamesvar = var0.dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_accum(var0,dnamesvar,dvnamesvar) CFvarn = ncvar.variables_values(depvars[0])[0] # Removing the flux if depvars[1] == 'XTIME': dtimeunits = var1.getncattr('description') tunits = dtimeunits.split(' ')[0] else: dtimeunits = var1.getncattr('units') tunits = dtimeunits.split(' ')[0] dtime = (var1[1] - var1[0])*timeunits_seconds(tunits) ncvar.insert_variable(ncobj, CFvarn + 'acc', diagout*dtime, diagoutd, diagoutvd, newnc) # cllmh with cldfra, pres elif diag == 'cllmh': var0 = ncobj.variables[depvars[0]] if depvars[1] == 'WRFp': var1 = WRFp else: var01 = ncobj.variables[depvars[1]] if len(size(var1.shape)) < len(size(var0.shape)): var1 = np.brodcast_arrays(var01,var0)[0] else: var1 = var01 diagout, diagoutd, diagoutvd = Forcompute_cllmh(var0,var1,dnames,dvnames) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] for nonvd in NONchkvardims: if gen.searchInlist(diagoutvd,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'cll', diagout[0,:], diagoutd, diagoutvd, newnc) ncvar.insert_variable(ncobj, 'clm', diagout[1,:], diagoutd, diagoutvd, newnc) ncvar.insert_variable(ncobj, 'clh', diagout[2,:], diagoutd, diagoutvd, newnc) # clt with cldfra elif diag == 'clt': var0 = ncobj.variables[depvars] diagout, diagoutd, diagoutvd = Forcompute_clt(var0,dnames,dvnames) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] for nonvd in NONchkvardims: if gen.searchInlist(diagoutvd,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'clt', diagout, diagoutd, diagoutvd, newnc) # deaccum: deacumulation of any variable as (Variable, time [as [tunits] # from/since ....], newvarname) elif diag == 'deaccum': var0 = ncobj.variables[depvars[1]] var1 = ncobj.variables[depvars[2]] dnamesvar = var0.dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_deaccum(var0,dnamesvar,dvnamesvar) # Transforming to a flux if depvars[2] == 'XTIME': dtimeunits = var1.getncattr('description') tunits = dtimeunits.split(' ')[0] else: dtimeunits = var1.getncattr('units') tunits = dtimeunits.split(' ')[0] dtime = (var1[1] - var1[0])*timeunits_seconds(tunits) ncvar.insert_variable(ncobj, depvars[3], diagout/dtime, diagoutd, diagoutvd, newnc) # LMDZrh (pres, t, r) elif diag == 'LMDZrh': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] diagout, diagoutd, diagoutvd = compute_rh(var0,var1,var2,dnames,dvnames) ncvar.insert_variable(ncobj, 'hur', diagout, diagoutd, diagoutvd, newnc) # LMDZrhs (psol, t2m, q2m) elif diag == 'LMDZrhs': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_rh(var0,var1,var2,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'hurs', diagout, diagoutd, diagoutvd, newnc) # mslp: mean sea level pressure (pres, psfc, terrain, temp, qv) elif diag == 'mslp' or diag == 'WRFmslp': var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] var4 = ncobj.variables[depvars[4]][:] if diag == 'WRFmslp': var0 = WRFp var3 = WRFt dnamesvar = ncobj.variables['P'].dimensions else: var0 = ncobj.variables[depvars[0]][:] var3 = ncobj.variables[depvars[3]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_mslp(var0, var1, var2, var3, var4, \ dnamesvar, dvnamesvar) ncvar.insert_variable(ncobj, 'psl', diagout, diagoutd, diagoutvd, newnc) # OMEGAw (omega, p, t) from NCL formulation (https://www.ncl.ucar.edu/Document/Functions/Contributed/omega_to_w.shtml) elif diag == 'OMEGAw': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_OMEGAw(var0,var1,var2,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'wa', diagout, diagoutd, diagoutvd, newnc) # raintot: instantaneous total precipitation from WRF as (RAINC + RAINC) / dTime elif diag == 'RAINTOT': var0 = ncobj.variables[depvars[0]] var1 = ncobj.variables[depvars[1]] if depvars[2] != 'WRFtime': var2 = ncobj.variables[depvars[2]] else: var2 = np.arange(var0.shape[0], dtype=int) var = var0[:] + var1[:] dnamesvar = var0.dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_deaccum(var,dnamesvar,dvnamesvar) # Transforming to a flux if var2.shape[0] > 1: if depvars[2] != 'WRFtime': dtimeunits = var2.getncattr('units') tunits = dtimeunits.split(' ')[0] dtime = (var2[1] - var2[0])*timeunits_seconds(tunits) else: var2 = ncobj.variables['Times'] time1 = var2[0,:] time2 = var2[1,:] tmf1 = '' tmf2 = '' for ic in range(len(time1)): tmf1 = tmf1 + time1[ic] tmf2 = tmf2 + time2[ic] dtdate1 = dtime.datetime.strptime(tmf1,"%Y-%m-%d_%H:%M:%S") dtdate2 = dtime.datetime.strptime(tmf2,"%Y-%m-%d_%H:%M:%S") diffdate12 = dtdate2 - dtdate1 dtime = diffdate12.total_seconds() print 'dtime:',dtime else: print warnmsg print ' ' + fname + ": only 1 time-step for '" + diag + "' !!" print ' leaving a zero value!' diagout = var0*0. dtime=1. ncvar.insert_variable(ncobj, 'pr', diagout/dtime, diagoutd, diagoutvd, newnc) # rhs (psfc, t, q) from TimeSeries files elif diag == 'TSrhs': p0=100000. var0 = ncobj.variables[depvars[0]][:] var1 = (ncobj.variables[depvars[1]][:])*(var0/p0)**(2./7.) var2 = ncobj.variables[depvars[2]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_rh(var0,var1,var2,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'hurs', diagout, diagoutd, diagoutvd, newnc) # td (psfc, t, q) from TimeSeries files elif diag == 'TStd' or diag == 'td': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] - 273.15 var2 = ncobj.variables[depvars[2]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_td(var0,var1,var2,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'tds', diagout, diagoutd, diagoutvd, newnc) # td (psfc, t, q) from TimeSeries files elif diag == 'TStdC' or diag == 'tdC': var0 = ncobj.variables[depvars[0]][:] # Temperature is already in degrees Celsius var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_td(var0,var1,var2,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'tds', diagout, diagoutd, diagoutvd, newnc) # wds (u, v) elif diag == 'TSwds' or diag == 'wds' : var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_wds(var0,var1,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'wds', diagout, diagoutd, diagoutvd, newnc) # wss (u, v) elif diag == 'TSwss' or diag == 'wss': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_wss(var0,var1,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'wss', diagout, diagoutd, diagoutvd, newnc) # turbulence (var) elif diag == 'turbulence': var0 = ncobj.variables[depvars][:] dnamesvar = list(ncobj.variables[depvars].dimensions) dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_turbulence(var0,dnamesvar,dvnamesvar) valsvar = gen.variables_values(depvars) newvarn = depvars + 'turb' print main + '; Lluis newvarn:', newvarn ncvar.insert_variable(ncobj, newvarn, diagout, diagoutd, diagoutvd, newnc) print main + '; Lluis variables:', newnc.variables.keys() varobj = newnc.variables[newvarn] attrv = varobj.long_name attr = varobj.delncattr('long_name') newattr = ncvar.set_attribute(varobj, 'long_name', attrv + \ " Taylor decomposition turbulence term") # WRFbils fom WRF as HFX + LH elif diag == 'WRFbils': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] diagout = var0 + var1 dnamesvar = list(ncobj.variables[depvars[0]].dimensions) dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) ncvar.insert_variable(ncobj, 'bils', diagout, dnamesvar, dvnamesvar, newnc) # WRFgeop geopotential from WRF as PH + PHB elif diag == 'WRFgeop': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] # de-staggering geopotential diagout0 = var0 + var1 dt = diagout0.shape[0] dz = diagout0.shape[1] dy = diagout0.shape[2] dx = diagout0.shape[3] diagout = np.zeros((dt,dz-1,dy,dx), dtype=np.float) diagout = 0.5*(diagout0[:,1:dz,:,:]+diagout0[:,0:dz-1,:,:]) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnames) for nonvd in NONchkvardims: if gen.searchInlist(dvnames,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'zg', diagout, dnames, diagoutvd, newnc) # WRFp pressure from WRF as P + PB elif diag == 'WRFp': diagout = WRFp ncvar.insert_variable(ncobj, 'pres', diagout, dnames, dvnames, newnc) # WRFpos elif diag == 'WRFpos': dnamesvar = ncobj.variables['MAPFAC_M'].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) ncvar.insert_variable(ncobj, 'WRFpos', WRFpos, dnamesvar, dvnamesvar, newnc) # WRFprw WRF water vapour path WRFdens, QVAPOR elif diag == 'WRFprw': var0 = WRFdens var1 = ncobj.variables[depvars[1]] dnamesvar = list(var1.dimensions) dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_prw(var0, var1, dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'prw', diagout, diagoutd, diagoutvd, newnc) # WRFrh (P, T, QVAPOR) elif diag == 'WRFrh': dnamesvar = list(ncobj.variables[depvars[2]].dimensions) dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) ncvar.insert_variable(ncobj, 'hur', WRFrh, dnames, dvnames, newnc) # WRFrhs (PSFC, T2, Q2) elif diag == 'WRFrhs': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] dnamesvar = list(ncobj.variables[depvars[2]].dimensions) dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) diagout, diagoutd, diagoutvd = compute_rh(var0,var1,var2,dnamesvar,dvnamesvar) ncvar.insert_variable(ncobj, 'hurs', diagout, diagoutd, diagoutvd, newnc) # rvors (u10, v10, WRFpos) elif diag == 'WRFrvors': var0 = ncobj.variables[depvars[0]] var1 = ncobj.variables[depvars[1]] diagout = rotational_z(var0, var1, distx) dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) ncvar.insert_variable(ncobj, 'rvors', diagout, dnamesvar, dvnamesvar, newnc) # WRFt (T, P, PB) elif diag == 'WRFt': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] p0=100000. p=var1 + var2 WRFt = (var0 + 300.)*(p/p0)**(2./7.) dnamesvar = list(ncobj.variables[depvars[0]].dimensions) dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnames) for nonvd in NONchkvardims: if gen.searchInlist(dvnames,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'ta', WRFt, dnames, diagoutvd, newnc) # WRFua (U, V, SINALPHA, COSALPHA) to be rotated !! elif diag == 'WRFua': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] var3 = ncobj.variables[depvars[3]][:] # un-staggering variables unstgdims = [var0.shape[0], var0.shape[1], var0.shape[2], var0.shape[3]-1] ua = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar0 = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar1 = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar0 = 0.5*(var0[:,:,:,0:var0.shape[3]-1] + var0[:,:,:,1:var0.shape[3]]) unstgvar1 = 0.5*(var1[:,:,0:var1.shape[2]-1,:] + var1[:,:,1:var1.shape[2],:]) for iz in range(var0.shape[1]): ua[:,iz,:,:] = unstgvar0[:,iz,:,:]*var3 - unstgvar1[:,iz,:,:]*var2 dnamesvar = ['Time','bottom_top','south_north','west_east'] dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnames) for nonvd in NONchkvardims: if gen.searchInlist(dvnames,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'ua', ua, dnames, diagoutvd, newnc) # WRFua (U, V, SINALPHA, COSALPHA) to be rotated !! elif diag == 'WRFva': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] var3 = ncobj.variables[depvars[3]][:] # un-staggering variables unstgdims = [var0.shape[0], var0.shape[1], var0.shape[2], var0.shape[3]-1] va = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar0 = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar1 = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar0 = 0.5*(var0[:,:,:,0:var0.shape[3]-1] + var0[:,:,:,1:var0.shape[3]]) unstgvar1 = 0.5*(var1[:,:,0:var1.shape[2]-1,:] + var1[:,:,1:var1.shape[2],:]) for iz in range(var0.shape[1]): va[:,iz,:,:] = unstgvar0[:,iz,:,:]*var2 + unstgvar1[:,iz,:,:]*var3 dnamesvar = ['Time','bottom_top','south_north','west_east'] dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnames) for nonvd in NONchkvardims: if gen.searchInlist(dvnames,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'va', va, dnames, diagoutvd, newnc) # WRFtime elif diag == 'WRFtime': diagout = WRFtime dnamesvar = ['Time'] dvnamesvar = ['Times'] ncvar.insert_variable(ncobj, 'time', diagout, dnamesvar, dvnamesvar, newnc) # ws (U, V) elif diag == 'ws': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] # un-staggering variables unstgdims = [var0.shape[0], var0.shape[1], var0.shape[2], var0.shape[3]-1] va = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar0 = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar1 = np.zeros(tuple(unstgdims), dtype=np.float) unstgvar0 = 0.5*(var0[:,:,:,0:var0.shape[3]-1] + var0[:,:,:,1:var0.shape[3]]) unstgvar1 = 0.5*(var1[:,:,0:var1.shape[2]-1,:] + var1[:,:,1:var1.shape[2],:]) dnamesvar = ['Time','bottom_top','south_north','west_east'] diagout = np.sqrt(unstgvar0*unstgvar0 + unstgvar1*unstgvar1) # dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnamesvar) for nonvd in NONchkvardims: if gen.searchInlist(dvnamesvar,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'ws', diagout, dnamesvar, diagoutvd, newnc) # wss (u10, v10) elif diag == 'wss': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] diagout = np.sqrt(var0*var0 + var1*var1) dnamesvar = ncobj.variables[depvars[0]].dimensions dvnamesvar = ncvar.var_dim_dimv(dnamesvar,dnames,dvnames) ncvar.insert_variable(ncobj, 'wss', diagout, dnamesvar, dvnamesvar, newnc) # WRFheight height from WRF geopotential as WRFGeop/g elif diag == 'WRFheight': diagout = WRFgeop/grav # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnames) for nonvd in NONchkvardims: if gen.searchInlist(dvnames,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'zhgt', diagout, dnames, diagoutvd, newnc) # WRFheightrel relative-height from WRF geopotential as WRFgeop(PH + PHB)/g-HGT 'WRFheightrel|PH@PHB@HGT elif diag == 'WRFheightrel': var0 = ncobj.variables[depvars[0]][:] var1 = ncobj.variables[depvars[1]][:] var2 = ncobj.variables[depvars[2]][:] dimz = var0.shape[1] diagout = np.zeros(tuple(var0.shape), dtype=np.float) for iz in range(dimz): diagout[:,iz,:,:] = (var0[:,iz,:,:]+ var1[:,iz,:,:])/grav - var2 # Removing the nonChecking variable-dimensions from the initial list varsadd = [] diagoutvd = list(dvnames) for nonvd in NONchkvardims: if gen.searchInlist(dvnames,nonvd): diagoutvd.remove(nonvd) varsadd.append(nonvd) ncvar.insert_variable(ncobj, 'zhgtrel', diagout, dnames, diagoutvd, newnc) else: print errormsg print ' ' + main + ": diagnostic '" + diag + "' not ready!!!" print ' available diagnostics: ', availdiags quit(-1) newnc.sync() # Adding that additional variables required to compute some diagnostics which # where not in the original file for vadd in varsadd: if not gen.searchInlist(newnc.variables.keys(),vadd): attrs = dictcompvars[vadd] vvn = attrs['name'] if not gen.searchInlist(newnc.variables.keys(), vvn): iidvn = dvnames.index(vadd) dnn = dnames[iidvn] if vadd == 'WRFtime': dvarvals = WRFtime[:] newvar = newnc.createVariable(vvn, 'f8', (dnn)) newvar[:] = dvarvals for attn in attrs.keys(): if attn != 'name': attv = attrs[attn] ncvar.set_attribute(newvar, attn, attv) # end of diagnostics # Global attributes ## atvar = ncvar.set_attribute(newnc, 'program', 'diagnostics.py') atvar = ncvar.set_attribute(newnc, 'version', '1.0') atvar = ncvar.set_attribute(newnc, 'author', 'Fita Borrell, Lluis') atvar = ncvar.set_attribute(newnc, 'institution', 'Laboratoire Meteorologie ' + \ 'Dynamique') atvar = ncvar.set_attribute(newnc, 'university', 'Universite Pierre et Marie ' + \ 'Curie -- Jussieu') atvar = ncvar.set_attribute(newnc, 'centre', 'Centre national de la recherche ' + \ 'scientifique') atvar = ncvar.set_attribute(newnc, 'city', 'Paris') atvar = ncvar.set_attribute(newnc, 'original_file', opts.ncfile) gorigattrs = ncobj.ncattrs() for attr in gorigattrs: attrv = ncobj.getncattr(attr) atvar = ncvar.set_attribute(newnc, attr, attrv) ncobj.close() newnc.close() print '\n' + main + ': successfull writting of diagnostics file "' + ofile + '" !!!'