def linearInterpolation(A,I,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000], status=None): """ Linear interpolation to interpolate a field from some levels to another set of levels Value below "surface" are masked Input A : array to interpolate I : interpolation field (usually Pressure or depth) from TOP (level 0) to BOTTOM (last level), i.e P value going up with each level levels : levels to interplate to (same units as I), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000] I and levels must have same units Output array on new levels (levels) Examples: A=interpolate(A,I,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]) """ try: nlev=len(levels) # Number of pressure levels except: nlev=1 # if only one level len(levels) would breaks levels=[levels,] order=A.getOrder() A=A(order='z...') I=I(order='z...') sh=list(I.shape) nsigma=sh[0] #number of sigma levels sh[0]=nlev t=MV2.zeros(sh,typecode=MV2.float32) sh2=I[0].shape prev=-1 for ilev in range(nlev): # loop through pressure levels if status is not None: prev=genutil.statusbar(ilev,nlev-1.,prev) lev=levels[ilev] # get value for the level Iabv=MV2.ones(sh2,MV2.float) Aabv=-1*Iabv # Array on sigma level Above Abel=-1*Iabv # Array on sigma level Below Ibel=-1*Iabv # Pressure on sigma level Below Iabv=-1*Iabv # Pressure on sigma level Above Ieq=MV2.masked_equal(Iabv,-1) # Area where Pressure == levels for i in range(1,nsigma): # loop from second sigma level to last one a = MV2.greater_equal(I[i], lev) # Where is the pressure greater than lev b = MV2.less_equal(I[i-1],lev) # Where is the pressure less than lev # Now looks if the pressure level is in between the 2 sigma levels # If yes, sets Iabv, Ibel and Aabv, Abel a=MV2.logical_and(a,b) Iabv=MV2.where(a,I[i],Iabv) # Pressure on sigma level Above Aabv=MV2.where(a,A[i],Aabv) # Array on sigma level Above Ibel=MV2.where(a,I[i-1],Ibel) # Pressure on sigma level Below Abel=MV2.where(a,A[i-1],Abel) # Array on sigma level Below Ieq= MV2.where(MV2.equal(I[i],lev),A[i],Ieq) val=MV2.masked_where(MV2.equal(Ibel,-1.),numpy.ones(Ibel.shape)*lev) # set to missing value if no data below lev if there is tl=(val-Ibel)/(Iabv-Ibel)*(Aabv-Abel)+Abel # Interpolation if ((Ieq.mask is None) or (Ieq.mask is MV22.nomask)): tl=Ieq else: tl=MV2.where(1-Ieq.mask,Ieq,tl) t[ilev]=tl.astype(MV2.float32) ax=A.getAxisList() autobnds=cdms2.getAutoBounds() cdms2.setAutoBounds('off') lvl=cdms2.createAxis(MV2.array(levels).filled()) cdms2.setAutoBounds(autobnds) try: lvl.units=I.units except: pass lvl.id='plev' try: t.units=I.units except: pass ax[0]=lvl t.setAxisList(ax) t.id=A.id for att in A.listattributes(): setattr(t,att,getattr(A,att)) return t(order=order)
def linearInterpolation(A, I, levels=[ 100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000 ], status=None): """ Linear interpolation to interpolate a field from some levels to another set of levels Value below "surface" are masked Input A : array to interpolate I : interpolation field (usually Pressure or depth) from TOP (level 0) to BOTTOM (last level), i.e P value going up with each level levels : levels to interplate to (same units as I), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000] I and levels must have same units Output array on new levels (levels) Examples: A=interpolate(A,I,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]) """ try: nlev = len(levels) # Number of pressure levels except: nlev = 1 # if only one level len(levels) would breaks levels = [ levels, ] order = A.getOrder() A = A(order='z...') I = I(order='z...') sh = list(I.shape) nsigma = sh[0] #number of sigma levels sh[0] = nlev t = MV2.zeros(sh, typecode=MV2.float32) sh2 = I[0].shape prev = -1 for ilev in range(nlev): # loop through pressure levels if status is not None: prev = genutil.statusbar(ilev, nlev - 1., prev) lev = levels[ilev] # get value for the level Iabv = MV2.ones(sh2, MV2.float) Aabv = -1 * Iabv # Array on sigma level Above Abel = -1 * Iabv # Array on sigma level Below Ibel = -1 * Iabv # Pressure on sigma level Below Iabv = -1 * Iabv # Pressure on sigma level Above Ieq = MV2.masked_equal(Iabv, -1) # Area where Pressure == levels for i in range(1, nsigma): # loop from second sigma level to last one a = MV2.greater_equal( I[i], lev) # Where is the pressure greater than lev b = MV2.less_equal(I[i - 1], lev) # Where is the pressure less than lev # Now looks if the pressure level is in between the 2 sigma levels # If yes, sets Iabv, Ibel and Aabv, Abel a = MV2.logical_and(a, b) Iabv = MV2.where(a, I[i], Iabv) # Pressure on sigma level Above Aabv = MV2.where(a, A[i], Aabv) # Array on sigma level Above Ibel = MV2.where(a, I[i - 1], Ibel) # Pressure on sigma level Below Abel = MV2.where(a, A[i - 1], Abel) # Array on sigma level Below Ieq = MV2.where(MV2.equal(I[i], lev), A[i], Ieq) val = MV2.masked_where( MV2.equal(Ibel, -1.), numpy.ones(Ibel.shape) * lev) # set to missing value if no data below lev if there is tl = (val - Ibel) / (Iabv - Ibel) * (Aabv - Abel) + Abel # Interpolation if ((Ieq.mask is None) or (Ieq.mask is MV22.nomask)): tl = Ieq else: tl = MV2.where(1 - Ieq.mask, Ieq, tl) t[ilev] = tl.astype(MV2.float32) ax = A.getAxisList() autobnds = cdms2.getAutoBounds() cdms2.setAutoBounds('off') lvl = cdms2.createAxis(MV2.array(levels).filled()) cdms2.setAutoBounds(autobnds) try: lvl.units = I.units except: pass lvl.id = 'plev' try: t.units = I.units except: pass ax[0] = lvl t.setAxisList(ax) t.id = A.id for att in A.listattributes(): setattr(t, att, getattr(A, att)) return t(order=order)
def logLinearInterpolation(A,P,levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000],status=None): """ Log-linear interpolation to convert a field from sigma levels to pressure levels Value below surface are masked Input A : array on sigma levels P : pressure field from TOP (level 0) to BOTTOM (last level) levels : pressure levels to interplate to (same units as P), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000] P and levels must have same units Output array on pressure levels (levels) Examples: A=logLinearInterpolation(A,P),levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]) """ try: nlev=len(levels) # Number of pressure levels except: nlev=1 # if only one level len(levels) would breaks levels=[levels,] order=A.getOrder() A=A(order='z...') P=P(order='z...') sh=list(P.shape) nsigma=sh[0] #number of sigma levels sh[0]=nlev t=MV2.zeros(sh,typecode=MV2.float32) sh2=P[0].shape prev=-1 for ilev in range(nlev): # loop through pressure levels if status is not None: prev=genutil.statusbar(ilev,nlev-1.,prev) lev=levels[ilev] # get value for the level Pabv=MV2.ones(sh2,MV2.float) Aabv=-1*Pabv # Array on sigma level Above Abel=-1*Pabv # Array on sigma level Below Pbel=-1*Pabv # Pressure on sigma level Below Pabv=-1*Pabv # Pressure on sigma level Above Peq=MV2.masked_equal(Pabv,-1) # Area where Pressure == levels for i in range(1,nsigma): # loop from second sigma level to last one a=MV2.greater_equal(P[i], lev) # Where is the pressure greater than lev b= MV2.less_equal(P[i-1],lev) # Where is the pressure less than lev # Now looks if the pressure level is in between the 2 sigma levels # If yes, sets Pabv, Pbel and Aabv, Abel a=MV2.logical_and(a,b) Pabv=MV2.where(a,P[i],Pabv) # Pressure on sigma level Above Aabv=MV2.where(a,A[i],Aabv) # Array on sigma level Above Pbel=MV2.where(a,P[i-1],Pbel) # Pressure on sigma level Below Abel=MV2.where(a,A[i-1],Abel) # Array on sigma level Below Peq= MV2.where(MV2.equal(P[i],lev),A[i],Peq) val=MV2.masked_where(MV2.equal(Pbel,-1),numpy.ones(Pbel.shape)*lev) # set to missing value if no data below lev if there is tl=MV2.log(val/Pbel)/MV2.log(Pabv/Pbel)*(Aabv-Abel)+Abel # Interpolation if ((Peq.mask is None) or (Peq.mask is MV2.nomask)): tl=Peq else: tl=MV2.where(1-Peq.mask,Peq,tl) t[ilev]=tl.astype(MV2.float32) ax=A.getAxisList() autobnds=cdms2.getAutoBounds() cdms2.setAutoBounds('off') lvl=cdms2.createAxis(MV2.array(levels).filled()) cdms2.setAutoBounds(autobnds) try: lvl.units=P.units except: pass lvl.id='plev' try: t.units=P.units except: pass ax[0]=lvl t.setAxisList(ax) t.id=A.id for att in A.listattributes(): setattr(t,att,getattr(A,att)) return t(order=order)
def create_amount_freq_PDF(mv, binedges, binwidthtype=None, bincentertype=None, vid=None, vid2=None, vid3=None): """Takes in geospatial data (mv) with dimensions of lat, lon, and time, and creates a PDF of the mv based on binedges at each lat/lon grid point. binedges defines the edges of the bin, except for the bin with maximum value, where it is open. binwidth option allows user to define whether the PDF is scaled by the 'arithmetic' bin width or the 'logarithmic' bin width. (dN/dx vs. dN/dlogx) default: 'logarithmic' The bincenter option allows one to use the 'geometric' or the 'arithmetic' mean to define the edge. The bin with maximum value will have a bin center equidistant from the max bin edge as from the center of the previous bin. PDFs will not be normalized over the histogram, but over all available data. For example, if there is data below the minimum bin edge, then the PDF will be normalized, having included the data that lies below the minimum bin edge. vid = variable ID, which will typically be the variable name of the when output as a netcdf """ #Step 1 input data and figure out the time dimensions in the data if vid is None: vid = mv.id vid2 = ''.join([mv.id, '2']) #Do get domain and find which axis corresponds to time, lat and lon time_index = mv.getAxisIndex('time') lat_index = mv.getAxisIndex('lat') lon_index = mv.getAxisIndex('lon') #obtain long_name, standard_name, typecode of the variable to eventually feed into output variables var_long_name = mv.long_name var_standard_name = mv.standard_name mv_typecode = mv.typecode() mv_lat = mv.getAxis(lat_index) mv_lon = mv.getAxis(lon_index) mv_att = mv.attributes mv_grid = mv.getGrid() #Step 2 loop over the bin widths and add up the number of data points in each bin #Create an array with the shape of (lat,lon,binedges,and corresponding bincenter) mapped_precip_freqpdf = numpy.zeros( (mv.shape[lat_index], mv.shape[lon_index], len(binedges))) mapped_precip_amntpdf = numpy.zeros( (mv.shape[lat_index], mv.shape[lon_index], len(binedges))) bincenter = numpy.zeros(len(binedges)) #Count up total first counts_index = MV2.greater_equal(mv, 0.) logger.debug(counts_index.shape) data_counts = numpy.zeros((mv.shape)) data_counts[counts_index] = 1. counts_total = numpy.sum(data_counts, axis=time_index) #specify what the binmean, bincenter, and binwidths are based on log and arith scaling binwidth = numpy.zeros(len(binedges)) bincenter = numpy.zeros(len(binedges)) binmean = numpy.zeros(len(binedges)) #Calculate bin mean for amount PDF binmean[:-1] = (binedges[1:] + binedges[:-1]) / 2 binmean[-1] = binedges[-1] + (binedges[-1] - binedges[-2]) / 2 #Calculate bin width based on type if binwidthtype is 'arithmetic': binwidth[:-1] = binedges[1:] - binedges[:-1] binwidth[-1] = binedges[-1] - binedges[-2] elif binwidthtype is 'logarithmic' or binwidthtype is None: binwidth[:-1] = numpy.log10(binedges[1:] / binedges[:-1]) binwidth[-1] = numpy.log10(binedges[-1] / binedges[-2]) #Calculate bin center based on type if bincentertype is 'arithmetic' or bincentertype is None: bincenter = binmean elif bincentertype is 'geometric': bincenter[:-1] = numpy.sqrt(binedges[1:] * binedges[:-1]) bincenter[-1] = binedges[-1] + (binedges[-1] - binedges[-2]) / 2 #Count up the number of days of precip in each precip bin **Most work done here for i in range(len(binedges)): precip_index = numpy.ones( mv.shape ) #locate the index where precip rate is between the bin edges toolow_index = mv < binedges[i] precip_index[toolow_index] = 0 if i != (len(binedges) - 1): toohigh_index = mv >= binedges[i + 1] precip_index[toohigh_index] = 0 precip_total = numpy.sum(precip_index, axis=time_index) precip_fraction = numpy.divide(precip_total, counts_total) precip_freqpdf = precip_fraction / binwidth[i] precip_amntpdf = precip_fraction / binwidth[i] * binmean[i] mapped_precip_freqpdf[:, :, i] = precip_freqpdf mapped_precip_amntpdf[:, :, i] = precip_amntpdf precip_freqpdf = None precip_amntpdf = None #Step 3 attach all necessary attributes to data (create data as a transient variable) #First, specify a new axis for the PDF binbound_all = numpy.append(binedges, numpy.max(mv)) binbounds = numpy.zeros((len(binedges), 2)) binbounds[:, 0] = binbound_all[:-1] binbounds[:, 1] = binbound_all[1:] mv_hist = cdms2.createAxis( bincenter, bounds=binbounds, id='binvalue') #mv_hist is the axes for precip rate ouput_mapped_precip_freqpdf = cdms2.createVariable( mapped_precip_freqpdf, typecode=mv_typecode, grid=mv_grid, axes=[mv_lat, mv_lon, mv_hist], attributes=mv_att, id=vid) ouput_mapped_precip_amntpdf = cdms2.createVariable( mapped_precip_amntpdf, typecode=mv_typecode, grid=mv_grid, axes=[mv_lat, mv_lon, mv_hist], attributes=mv_att, id=vid2) bincenter = cdms2.createVariable(bincenter, typecode=mv_typecode, axes=[mv_hist], attributes=mv_att, id=vid3) ouput_mapped_precip_freqpdf.units = 'frequency' ouput_mapped_precip_amntpdf.units = 'amount' ouput_mapped_precip_freqpdf.long_name = ''.join( ['Frequency as a function of ', var_long_name]) ouput_mapped_precip_amntpdf.long_name = ''.join( ['Amount as a function of ', var_long_name]) ouput_mapped_precip_freqpdf.standard_name = ''.join( [var_standard_name, '_frequency']) ouput_mapped_precip_amntpdf.standard_name = ''.join( [var_standard_name, '_amount']) #Step 4 output data return bincenter, ouput_mapped_precip_freqpdf, ouput_mapped_precip_amntpdf
def logLinearInterpolation(A, P, levels=[ 100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000 ], status=None): """ Log-linear interpolation to convert a field from sigma levels to pressure levels Value below surface are masked Input A : array on sigma levels P : pressure field from TOP (level 0) to BOTTOM (last level) levels : pressure levels to interplate to (same units as P), default levels are:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000] P and levels must have same units Output array on pressure levels (levels) Examples: A=logLinearInterpolation(A,P),levels=[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000]) """ try: nlev = len(levels) # Number of pressure levels except: nlev = 1 # if only one level len(levels) would breaks levels = [ levels, ] order = A.getOrder() A = A(order='z...') P = P(order='z...') sh = list(P.shape) nsigma = sh[0] #number of sigma levels sh[0] = nlev t = MV2.zeros(sh, typecode=MV2.float32) sh2 = P[0].shape prev = -1 for ilev in range(nlev): # loop through pressure levels if status is not None: prev = genutil.statusbar(ilev, nlev - 1., prev) lev = levels[ilev] # get value for the level Pabv = MV2.ones(sh2, MV2.float) Aabv = -1 * Pabv # Array on sigma level Above Abel = -1 * Pabv # Array on sigma level Below Pbel = -1 * Pabv # Pressure on sigma level Below Pabv = -1 * Pabv # Pressure on sigma level Above Peq = MV2.masked_equal(Pabv, -1) # Area where Pressure == levels for i in range(1, nsigma): # loop from second sigma level to last one a = MV2.greater_equal( P[i], lev) # Where is the pressure greater than lev b = MV2.less_equal(P[i - 1], lev) # Where is the pressure less than lev # Now looks if the pressure level is in between the 2 sigma levels # If yes, sets Pabv, Pbel and Aabv, Abel a = MV2.logical_and(a, b) Pabv = MV2.where(a, P[i], Pabv) # Pressure on sigma level Above Aabv = MV2.where(a, A[i], Aabv) # Array on sigma level Above Pbel = MV2.where(a, P[i - 1], Pbel) # Pressure on sigma level Below Abel = MV2.where(a, A[i - 1], Abel) # Array on sigma level Below Peq = MV2.where(MV2.equal(P[i], lev), A[i], Peq) val = MV2.masked_where( MV2.equal(Pbel, -1), numpy.ones(Pbel.shape) * lev) # set to missing value if no data below lev if there is tl = MV2.log(val / Pbel) / MV2.log( Pabv / Pbel) * (Aabv - Abel) + Abel # Interpolation if ((Peq.mask is None) or (Peq.mask is MV2.nomask)): tl = Peq else: tl = MV2.where(1 - Peq.mask, Peq, tl) t[ilev] = tl.astype(MV2.float32) ax = A.getAxisList() autobnds = cdms2.getAutoBounds() cdms2.setAutoBounds('off') lvl = cdms2.createAxis(MV2.array(levels).filled()) cdms2.setAutoBounds(autobnds) try: lvl.units = P.units except: pass lvl.id = 'plev' try: t.units = P.units except: pass ax[0] = lvl t.setAxisList(ax) t.id = A.id for att in A.listattributes(): setattr(t, att, getattr(A, att)) return t(order=order)
def generateSurfaceTypeByRegionMask(mask,sftbyrgn=None,sftbyrgnmask=215,regions=range(201,223),maximum_regions_per_cell=4,extend_up_to=3,verbose=True): """ Maps a "regions" dataset onto a user provided land/sea mask or grid Usage: ----- mapped,found = generateSurfaceTypeByRegionMask(mask,sftbyrgn=None,sftbyrgnmask=None,regions=None,maximum_regions_per_cell=4,extend_up_to=3,verbose=True) Input: ----- mask User provided land/sea mask (100/0) or grid (the land/sea mask will be generated automagically) which will be mapped using the "sftbyrgn" internal dataset (will generate a land/sea mask for you) sftbyrgn Mask you wish to map onto your grid (if None uses internal "sftbyrgn" dataset (old ezget type)) sftbyrgnmask Land/sea mask for sftbyrgn (or a number specifying value limits for sftbyrgn which indicates land/sea threshold (greater values are land) - see URL below for integer region map) regions Numbers from sftbyrgn array that you want to map onto mask (integers from 201-222) maximum_regions_per_cell Maximum number of regions considered for a single cell extend_up_to How many grid cells around a cell can we extend to identify a guess verbose Prints to the screen what's going on (default is True) Output: ----- mapped Mapped input grid/mask using provided (or default) regions - sftbyrgn -> user provided grid/mask found Matrix containing number of regions matched for each output cell Notes: ----- - More detailed information, including a region map and tabulated region numbers are available from http://www-pcmdi.llnl.gov/publications/pdf/34.pdf """ cdat_info.pingPCMDIdb("cdat","cdutil.generateSurfaceTypeByRegionMask") ## OK first determine which regions are available ## Must be integer values if isinstance(mask,cdms2.grid.TransientRectGrid): mask = cdutil.generateLandSeaMask(mask)*100. if sftbyrgn is None: sftbyrgn = cdms2.open(os.path.join(cdat_info.get_prefix(),'share','cdutil','sftbyrgn.nc'))('sftbyrgn') if regions is None: if verbose: print 'Preparing regions' #regions = range(201,223) regions = [] for i in range(0,10000): genutil.statusbar(i,9999) c = float(MV2.sum(MV2.ravel(MV2.equal(sftbyrgn,i)),0)) if c != 0: regions.append(i) if verbose: print 'Regions:',regions ## If no mask passed fr sftbyrgn, assumes everything greater 5000 is land) if isinstance(sftbyrgnmask,int): split = sftbyrgnmask n = MV2.maximum(mask) sftbyrgnmask = MV2.greater_equal(sftbyrgn,sftbyrgnmask)*n else: split = MV2.maximum(sftbyrgnmask)/2. ## Now guess the type for each regions keys = {} ## ## Nice way to do it ## for r in regions: ## c=MV2.not_equal(sftbyrgn,r) ## c=MV2.masked_where(c,sftbyrgnmask) ## n=MV2.count(c) ## c=float(MV2.sum(MV2.ravel(c),0)/n) ## print r,c,n ## keys[r]=c ## Fast but not so "general" way to do it for r in regions: if r< split: keys[r] = 0. else: keys[r] = 100. sh = list(mask.shape) sh.insert(0,maximum_regions_per_cell) potential = MV2.ones(sh,dtype='d')*-999 potential_reg = MV2.ones(sh,dtype='d')*-999 g1 = sftbyrgn.getGrid() g2 = mask.getGrid() r1 = regrid2.Horizontal(g1,g2) w = cdutil.area_weights(sftbyrgn) if verbose: print 'First pass' itmp = 0. for ireg in keys.keys(): genutil.statusbar(itmp,len(keys.keys())-1) itmp += 1. c = MV2.equal(sftbyrgn,ireg) w2 = 1.-c*w s2,w3 = r1(sftbyrgn,mask=w2.filled(),returnTuple=1) c2 = MV2.equal(mask,keys[ireg]) loop(potential,potential_reg,c2,w3,ireg) found = MV2.zeros(sh[1:],typecode='f') for i in range(maximum_regions_per_cell): found = found+MV2.not_equal(potential[i],-999) sh2 = list(sh) for k in range(extend_up_to): sh2[1] = sh[1]+2*(k+1) sh2[2] = sh[2]+2*(k+1) ## Form the possible i/j couples ! s = MV2.sum(MV2.ravel(MV2.equal(potential[0],-999)),0) if verbose: print 'Expanding up to',k+1,'cells while trying to fix',s,'cells' #if dump: #f=cdms2.open('tmp_'+str(k)+'.nc','w') #f.write(sumregions(potential_reg,potential).astype('f'),id='sftbyrgn',axes=mask.getAxisList()) #f.close() #g=sumregions(potential_reg,potential).astype('d') #g=MV2.masked_equal(g,-999) #g=MV2.greater(g,4999)*100. #g=MV2.absolute(mask-g) #g=MV2.masked_equal(g,0.) #print 'Number of differences:',MV2.count(g) if float(s) != 0: c0 = MV2.equal(potential[0],-999) couples = [] sft2 = MV2.zeros(sh2[1:],dtype='d')-888. sft2[k+1:-k-1,k+1:-k-1] = mask for i in range(-k-1,k+2): for j in range(-k-1,k+2): if abs(i)>k or abs(j)>k: couples.append([i,j]) ntot = len(keys.keys())*len(couples)-1 itmp = 0 for ireg in keys.keys(): c = MV2.equal(sftbyrgn,ireg) w2 = 1.-c*w s2,w3 = r1(sftbyrgn,mask=w2.filled(),returnTuple=1) w4 = MV2.zeros(sh2[1:],typecode='d') w4[k+1:-k-1,k+1:-k-1] = w3 for i,j in couples: if verbose: genutil.statusbar(itmp,ntot) itmp += 1. c2 = MV2.equal(sft2[j+k+1:j+k+1+sh[1],i+k+1:i+k+1+sh[2]],keys[ireg]) c3 = MV2.equal(sft2[j+k+1:j+k+1+sh[1],i+k+1:i+k+1+sh[2]],mask) c2 = MV2.logical_and(c2,c3) c2 = MV2.logical_and(c2,c0) loop(potential,potential_reg,c2,w4[j+k+1:j+k+1+sh[1],i+k+1:i+k+1+sh[2]],ireg) found = MV2.where(MV2.equal(potential[0],-999),found-1,found) out = sumregions(potential_reg,potential) out.setAxisList(mask.getAxisList()) out.id = 'sftbyrgn' out = out.astype('i') out.missing_value = -999 found.setAxisList(mask.getAxisList()) found.id = 'found' found = found.astype('i') found.missing_value = -999 del(out.name) del(found.name) return out,found
def create_amount_freq_PDF(mv, binedges, binwidthtype=None, bincentertype=None, vid=None, vid2=None, vid3=None): """Takes in geospatial data (mv) with dimensions of lat, lon, and time, and creates a PDF of the mv based on binedges at each lat/lon grid point. binedges defines the edges of the bin, except for the bin with maximum value, where it is open. binwidth option allows user to define whether the PDF is scaled by the 'arithmetic' bin width or the 'logarithmic' bin width. (dN/dx vs. dN/dlogx) default: 'logarithmic' The bincenter option allows one to use the 'geometric' or the 'arithmetic' mean to define the edge. The bin with maximum value will have a bin center equidistant from the max bin edge as from the center of the previous bin. PDFs will not be normalized over the histogram, but over all available data. For example, if there is data below the minimum bin edge, then the PDF will be normalized, having included the data that lies below the minimum bin edge. vid = variable ID, which will typically be the variable name of the when output as a netcdf """ #Step 1 input data and figure out the time dimensions in the data if vid is None: vid = mv.id vid2 = ''.join([mv.id,'2']) #Do get domain and find which axis corresponds to time, lat and lon time_index=mv.getAxisIndex('time') lat_index=mv.getAxisIndex('lat') lon_index=mv.getAxisIndex('lon') #obtain long_name, standard_name, typecode of the variable to eventually feed into output variables var_long_name=mv.long_name var_standard_name=mv.standard_name mv_typecode=mv.typecode() mv_lat=mv.getAxis(lat_index) mv_lon=mv.getAxis(lon_index) mv_att=mv.attributes mv_grid=mv.getGrid() #Step 2 loop over the bin widths and add up the number of data points in each bin #Create an array with the shape of (lat,lon,binedges,and corresponding bincenter) mapped_precip_freqpdf=numpy.zeros((mv.shape[lat_index],mv.shape[lon_index],len(binedges))) mapped_precip_amntpdf=numpy.zeros((mv.shape[lat_index],mv.shape[lon_index],len(binedges))) bincenter=numpy.zeros(len(binedges)) #Count up total first counts_index=MV2.greater_equal(mv,0.) print counts_index.shape data_counts=numpy.zeros((mv.shape)) data_counts[counts_index]=1. counts_total=numpy.sum(data_counts,axis=time_index) #specify what the binmean, bincenter, and binwidths are based on log and arith scaling binwidth=numpy.zeros(len(binedges)) bincenter=numpy.zeros(len(binedges)) binmean=numpy.zeros(len(binedges)) #Calculate bin mean for amount PDF binmean[:-1]=(binedges[1:]+binedges[:-1])/2 binmean[-1]=binedges[-1] + (binedges[-1]-binedges[-2])/2 #Calculate bin width based on type if binwidthtype is 'arithmetic': binwidth[:-1]=binedges[1:]-binedges[:-1] binwidth[-1]=binedges[-1]-binedges[-2] elif binwidthtype is 'logarithmic' or binwidthtype is None: binwidth[:-1]=numpy.log10(binedges[1:]/binedges[:-1]) binwidth[-1]=numpy.log10(binedges[-1]/binedges[-2]) #Calculate bin center based on type if bincentertype is 'arithmetic' or bincentertype is None: bincenter=binmean elif bincentertype is 'geometric': bincenter[:-1]=numpy.sqrt(binedges[1:]*binedges[:-1]) bincenter[-1]=binedges[-1] + (binedges[-1]-binedges[-2])/2 #Count up the number of days of precip in each precip bin **Most work done here for i in range(len(binedges)): precip_index=numpy.ones(mv.shape) #locate the index where precip rate is between the bin edges toolow_index=mv<binedges[i] precip_index[toolow_index]=0 if i!=(len(binedges)-1): toohigh_index=mv>=binedges[i+1] precip_index[toohigh_index]=0 precip_total=numpy.sum(precip_index,axis=time_index) precip_fraction=numpy.divide(precip_total,counts_total) precip_freqpdf=precip_fraction/binwidth[i] precip_amntpdf=precip_fraction/binwidth[i]*binmean[i] mapped_precip_freqpdf[:,:,i]=precip_freqpdf mapped_precip_amntpdf[:,:,i]=precip_amntpdf precip_freqpdf=None precip_amntpdf=None #Step 3 attach all necessary attributes to data (create data as a transient variable) #First, specify a new axis for the PDF binbound_all=numpy.append(binedges,numpy.max(mv)) binbounds=numpy.zeros((len(binedges),2)) binbounds[:,0]=binbound_all[:-1] binbounds[:,1]=binbound_all[1:] mv_hist=cdms2.createAxis(bincenter,bounds=binbounds,id='binvalue') #mv_hist is the axes for precip rate ouput_mapped_precip_freqpdf=cdms2.createVariable(mapped_precip_freqpdf,typecode=mv_typecode, grid=mv_grid,axes=[mv_lat,mv_lon,mv_hist],attributes=mv_att,id=vid) ouput_mapped_precip_amntpdf=cdms2.createVariable(mapped_precip_amntpdf,typecode=mv_typecode, grid=mv_grid,axes=[mv_lat,mv_lon,mv_hist],attributes=mv_att,id=vid2) bincenter=cdms2.createVariable(bincenter,typecode=mv_typecode, axes=[mv_hist],attributes=mv_att,id=vid3) ouput_mapped_precip_freqpdf.units='frequency' ouput_mapped_precip_amntpdf.units='amount' ouput_mapped_precip_freqpdf.long_name=''.join(['Frequency as a function of ',var_long_name]) ouput_mapped_precip_amntpdf.long_name=''.join(['Amount as a function of ',var_long_name]) ouput_mapped_precip_freqpdf.standard_name=''.join([var_standard_name,'_frequency']) ouput_mapped_precip_amntpdf.standard_name=''.join([var_standard_name,'_amount']) #Step 4 output data return bincenter, ouput_mapped_precip_freqpdf, ouput_mapped_precip_amntpdf
def linearInterpolation(A, Idx, levels=[ 100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000 ], status=None, axis='z'): """ Linear interpolation to interpolate a field from some levels to another set of levels Values below "surface" are masked. :param A: array to interpolate :type A: :param I: interpolation field (usually Pressure or depth) from TOP (level 0) to BOTTOM (last level) i.e P value going up with each level. :type I: :param levels: levels to interpolate to (same units as I). Default levels:[100000, 92500, 85000, 70000, 60000, 50000, 40000, 30000, 25000, 20000, 15000, 10000, 7000, 5000, 3000, 2000, 1000] :type levels: :param axis: Axis over which to do the linear interpolation. Can provide either an int representing axis index, or the axis name. Default: 'z'. :type axis: str or int .. note:: I and levels must have same units :returns: array on new levels (levels) :Examples: .. doctest:: vertical_linearInterpolation >>> A=interpolate(A,I) # interpolates A over default levels """ try: nlev = len(levels) # Number of pressure levels except BaseException: nlev = 1 # if only one level len(levels) would breaks levels = [ levels, ] order = A.getOrder() A = A(order='%s...' % axis) Idx = Idx(order='%s...' % axis) sh = list(Idx.shape) nsigma = sh[0] # number of sigma levels sh[0] = nlev t = MV2.zeros(sh, typecode=MV2.float32) sh2 = Idx[0].shape prev = -1 for ilev in range(nlev): # loop through pressure levels if status is not None: prev = genutil.statusbar(ilev, nlev - 1., prev) lev = levels[ilev] # get value for the level Iabv = MV2.ones(sh2, MV2.float) Aabv = -1 * Iabv # Array on sigma level Above Abel = -1 * Iabv # Array on sigma level Below Ibel = -1 * Iabv # Pressure on sigma level Below Iabv = -1 * Iabv # Pressure on sigma level Above Ieq = MV2.masked_equal(Iabv, -1) # Area where Pressure == levels for i in range(1, nsigma): # loop from second sigma level to last one a = MV2.greater_equal( Idx[i], lev) # Where is the pressure greater than lev b = MV2.less_equal(Idx[i - 1], lev) # Where is the pressure less than lev # Now looks if the pressure level is in between the 2 sigma levels # If yes, sets Iabv, Ibel and Aabv, Abel a = MV2.logical_and(a, b) Iabv = MV2.where(a, Idx[i], Iabv) # Pressure on sigma level Above Aabv = MV2.where(a, A[i], Aabv) # Array on sigma level Above Ibel = MV2.where(a, Idx[i - 1], Ibel) # Pressure on sigma level Below Abel = MV2.where(a, A[i - 1], Abel) # Array on sigma level Below Ieq = MV2.where(MV2.equal(Idx[i], lev), A[i], Ieq) val = MV2.masked_where(MV2.equal(Ibel, -1.), numpy.ones(Ibel.shape) * lev) # set to missing value if no data below lev if # there is tl = (val - Ibel) / (Iabv - Ibel) * \ (Aabv - Abel) + Abel # Interpolation if ((Ieq.mask is None) or (Ieq.mask is MV2.nomask)): tl = Ieq else: tl = MV2.where(1 - Ieq.mask, Ieq, tl) t[ilev] = tl.astype(MV2.float32) ax = A.getAxisList() autobnds = cdms2.getAutoBounds() cdms2.setAutoBounds('off') lvl = cdms2.createAxis(MV2.array(levels).filled()) cdms2.setAutoBounds(autobnds) try: lvl.units = Idx.units except BaseException: pass lvl.id = 'plev' try: t.units = Idx.units except BaseException: pass ax[0] = lvl t.setAxisList(ax) t.id = A.id for att in A.listattributes(): setattr(t, att, getattr(A, att)) return t(order=order)
def generateSurfaceTypeByRegionMask(mask, sftbyrgn=None, sftbyrgnmask=215, regions=range(201, 223), maximum_regions_per_cell=4, extend_up_to=3, verbose=True): """ Maps a "types" dataset onto a landsea mask Usage: mapped,found = generateSurfaceTypeByRegionMask(mask,sftbyrgn,sftbyrgnmask=None,regions=None,maximum_regions_per_cell=4,extend_up_to=3,verbode=True) Input: mask : land/sea mask (100/0) onto you wish to map our grid (will generate a ld/sea mask for you) sftbyrgn: mask you wish to map if None then uses our own "sftbyrgn" dataset (old ezget type) sftbyrgnmask: land/sea mask for sftbyrgn or a number specifying limit in values of sftbygrn which indicate the threshold land/sea (greater values are land) regions: Numbers from sftbyrgn array that you want to map onto mask maximum_regions_per_cell: maximum number f regions concidered in a cell extend_up_to : how many grid cells away around a cell can we extent to identify a guess verbose: prints to the screen what's going on (default is True) Output: mapped : mapped input mask found : ??? """ ## OK first determine which regions are available ## Must be integer values if isinstance(mask, cdms2.grid.TransientRectGrid): mask = cdutil.generateLandSeaMask(mask) * 100. if sftbyrgn is None: sftbyrgn = cdms2.open( os.path.join(sys.prefix, 'sample_data', 'sftbyrgn.nc'))('sftbyrgn') if regions is None: if verbose: print 'Preparing regions' ## regions = range(201,223) regions = [] for i in range(0, 10000): genutil.statusbar(i, 9999) c = float(MV2.sum(MV2.ravel(MV2.equal(sftbyrgn, i)), 0)) if c != 0: regions.append(i) if verbose: print 'Regions:', regions ## If no mask passed fr sftbyrgn, assumes everything greater 5000 is land) if isinstance(sftbyrgnmask, int): split = sftbyrgnmask n = MV2.maximum(mask) sftbyrgnmask = MV2.greater_equal(sftbyrgn, sftbyrgnmask) * n else: split = MV2.maximum(sftbyrgnmask) / 2. ## Now guess the type for each regions keys = {} ## ## Nice way to do it ## for r in regions: ## c=MV2.not_equal(sftbyrgn,r) ## c=MV2.masked_where(c,sftbyrgnmask) ## n=MV2.count(c) ## c=float(MV2.sum(MV2.ravel(c),0)/n) ## print r,c,n ## keys[r]=c ## Fast but not so "general" way to do it for r in regions: if r < split: keys[r] = 0. else: keys[r] = 100. sh = list(mask.shape) sh.insert(0, maximum_regions_per_cell) potential = MV2.ones(sh, dtype='d') * -999 potential_reg = MV2.ones(sh, dtype='d') * -999 g1 = sftbyrgn.getGrid() g2 = mask.getGrid() r1 = regrid2.Regridder(g1, g2) w = cdutil.area_weights(sftbyrgn) if verbose: print 'First pass' itmp = 0. for ireg in keys.keys(): genutil.statusbar(itmp, len(keys.keys()) - 1) itmp += 1. c = MV2.equal(sftbyrgn, ireg) w2 = 1. - c * w s2, w3 = r1(sftbyrgn, mask=w2.filled(), returnTuple=1) c2 = MV2.equal(mask, keys[ireg]) loop(potential, potential_reg, c2, w3, ireg) found = MV2.zeros(sh[1:], typecode='f') for i in range(maximum_regions_per_cell): found = found + MV2.not_equal(potential[i], -999) sh2 = list(sh) for k in range(extend_up_to): sh2[1] = sh[1] + 2 * (k + 1) sh2[2] = sh[2] + 2 * (k + 1) ## Form the possible i/j couples ! s = MV2.sum(MV2.ravel(MV2.equal(potential[0], -999)), 0) if verbose: print 'Expanding up to', k + 1, 'cells while trying to fix', s, 'cells' ## if dump: ## f=cdms2.open('tmp_'+str(k)+'.nc','w') ## f.write(sumregions(potential_reg,potential).astype('f'),id='sftbyrgn',axes=mask.getAxisList()) ## f.close() ## g=sumregions(potential_reg,potential).astype('d') ## g=MV2.masked_equal(g,-999) ## g=MV2.greater(g,4999)*100. ## g=MV2.absolute(mask-g) ## g=MV2.masked_equal(g,0.) ## print 'Number of differences:',MV2.count(g) if float(s) != 0: c0 = MV2.equal(potential[0], -999) couples = [] sft2 = MV2.zeros(sh2[1:], dtype='d') - 888. sft2[k + 1:-k - 1, k + 1:-k - 1] = mask for i in range(-k - 1, k + 2): for j in range(-k - 1, k + 2): if abs(i) > k or abs(j) > k: couples.append([i, j]) ntot = len(keys.keys()) * len(couples) - 1 itmp = 0 for ireg in keys.keys(): c = MV2.equal(sftbyrgn, ireg) w2 = 1. - c * w s2, w3 = r1(sftbyrgn, mask=w2.filled(), returnTuple=1) w4 = MV2.zeros(sh2[1:], typecode='d') w4[k + 1:-k - 1, k + 1:-k - 1] = w3 for i, j in couples: if verbose: genutil.statusbar(itmp, ntot) itmp += 1. c2 = MV2.equal( sft2[j + k + 1:j + k + 1 + sh[1], i + k + 1:i + k + 1 + sh[2]], keys[ireg]) c3 = MV2.equal( sft2[j + k + 1:j + k + 1 + sh[1], i + k + 1:i + k + 1 + sh[2]], mask) c2 = MV2.logical_and(c2, c3) c2 = MV2.logical_and(c2, c0) loop( potential, potential_reg, c2, w4[j + k + 1:j + k + 1 + sh[1], i + k + 1:i + k + 1 + sh[2]], ireg) found = MV2.where(MV2.equal(potential[0], -999), found - 1, found) out = sumregions(potential_reg, potential) out.setAxisList(mask.getAxisList()) found.setAxisList(mask.getAxisList()) found = found.astype('i') found.missing_value = -999 found.id = 'found' out.id = 'sftbyrgn' out = out.astype('i') out.missing_value = -999 del (out.name) del (found.name) return out, found
def generateSurfaceTypeByRegionMask(mask,sftbyrgn=None,sftbyrgnmask=215,regions = range(201,223), maximum_regions_per_cell=4,extend_up_to=3,verbose=True): """ Maps a "types" dataset onto a landsea mask Usage: mapped,found = generateSurfaceTypeByRegionMask(mask,sftbyrgn,sftbyrgnmask=None,regions=None,maximum_regions_per_cell=4,extend_up_to=3,verbode=True) Input: mask : land/sea mask (100/0) onto you wish to map our grid (will generate a ld/sea mask for you) sftbyrgn: mask you wish to map if None then uses our own "sftbyrgn" dataset (old ezget type) sftbyrgnmask: land/sea mask for sftbyrgn or a number specifying limit in values of sftbygrn which indicate the threshold land/sea (greater values are land) regions: Numbers from sftbyrgn array that you want to map onto mask maximum_regions_per_cell: maximum number f regions concidered in a cell extend_up_to : how many grid cells away around a cell can we extent to identify a guess verbose: prints to the screen what's going on (default is True) Output: mapped : mapped input mask found : ??? """ ## OK first determine which regions are available ## Must be integer values if isinstance(mask, cdms2.grid.TransientRectGrid): mask = cdutil.generateLandSeaMask(mask)*100. if sftbyrgn is None: sftbyrgn = cdms2.open(os.path.join(sys.prefix,'sample_data','sftbyrgn.nc'))('sftbyrgn') if regions is None: if verbose: print 'Preparing regions' ## regions = range(201,223) regions=[] for i in range(0,10000): genutil.statusbar(i,9999) c=float(MV2.sum(MV2.ravel(MV2.equal(sftbyrgn,i)),0)) if c!=0: regions.append(i) if verbose: print 'Regions:',regions ## If no mask passed fr sftbyrgn, assumes everything greater 5000 is land) if isinstance(sftbyrgnmask,int): split = sftbyrgnmask n=MV2.maximum(mask) sftbyrgnmask=MV2.greater_equal(sftbyrgn,sftbyrgnmask)*n else: split = MV2.maximum(sftbyrgnmask)/2. ## Now guess the type for each regions keys={} ## ## Nice way to do it ## for r in regions: ## c=MV2.not_equal(sftbyrgn,r) ## c=MV2.masked_where(c,sftbyrgnmask) ## n=MV2.count(c) ## c=float(MV2.sum(MV2.ravel(c),0)/n) ## print r,c,n ## keys[r]=c ## Fast but not so "general" way to do it for r in regions: if r< split: keys[r]=0. else: keys[r]=100. sh=list(mask.shape) sh.insert(0,maximum_regions_per_cell) potential=MV2.ones(sh,dtype='d')*-999 potential_reg=MV2.ones(sh,dtype='d')*-999 g1=sftbyrgn.getGrid() g2=mask.getGrid() r1=regrid2.Regridder(g1,g2) w=cdutil.area_weights(sftbyrgn) if verbose: print 'First pass' itmp=0. for ireg in keys.keys(): genutil.statusbar(itmp,len(keys.keys())-1) itmp+=1. c=MV2.equal(sftbyrgn,ireg) w2=1.-c*w s2,w3=r1(sftbyrgn,mask=w2.filled(),returnTuple=1) c2=MV2.equal(mask,keys[ireg]) loop(potential,potential_reg,c2,w3,ireg) found=MV2.zeros(sh[1:],typecode='f') for i in range(maximum_regions_per_cell): found=found+MV2.not_equal(potential[i],-999) sh2=list(sh) for k in range(extend_up_to): sh2[1]=sh[1]+2*(k+1) sh2[2]=sh[2]+2*(k+1) ## Form the possible i/j couples ! s=MV2.sum(MV2.ravel(MV2.equal(potential[0],-999)),0) if verbose: print 'Expanding up to',k+1,'cells while trying to fix',s,'cells' ## if dump: ## f=cdms2.open('tmp_'+str(k)+'.nc','w') ## f.write(sumregions(potential_reg,potential).astype('f'),id='sftbyrgn',axes=mask.getAxisList()) ## f.close() ## g=sumregions(potential_reg,potential).astype('d') ## g=MV2.masked_equal(g,-999) ## g=MV2.greater(g,4999)*100. ## g=MV2.absolute(mask-g) ## g=MV2.masked_equal(g,0.) ## print 'Number of differences:',MV2.count(g) if float(s)!=0: c0=MV2.equal(potential[0],-999) couples=[] sft2=MV2.zeros(sh2[1:],dtype='d')-888. sft2[k+1:-k-1,k+1:-k-1]=mask for i in range(-k-1,k+2): for j in range(-k-1,k+2): if abs(i)>k or abs(j)>k: couples.append([i,j]) ntot=len(keys.keys())*len(couples)-1 itmp=0 for ireg in keys.keys(): c=MV2.equal(sftbyrgn,ireg) w2=1.-c*w s2,w3=r1(sftbyrgn,mask=w2.filled(),returnTuple=1) w4=MV2.zeros(sh2[1:],typecode='d') w4[k+1:-k-1,k+1:-k-1]=w3 for i,j in couples: if verbose: genutil.statusbar(itmp,ntot) itmp+=1. c2=MV2.equal(sft2[j+k+1:j+k+1+sh[1],i+k+1:i+k+1+sh[2]],keys[ireg]) c3=MV2.equal(sft2[j+k+1:j+k+1+sh[1],i+k+1:i+k+1+sh[2]],mask) c2=MV2.logical_and(c2,c3) c2=MV2.logical_and(c2,c0) loop(potential,potential_reg,c2,w4[j+k+1:j+k+1+sh[1],i+k+1:i+k+1+sh[2]],ireg) found=MV2.where(MV2.equal(potential[0],-999),found-1,found) out=sumregions(potential_reg,potential) out.setAxisList(mask.getAxisList()) found.setAxisList(mask.getAxisList()) found=found.astype('i') found.missing_value=-999 found.id='found' out.id='sftbyrgn' out=out.astype('i') out.missing_value=-999 del(out.name) del(found.name) return out,found