Source code for regrid2.pressure

# Automatically adapted for numpy.oldnumeric Aug 02, 2007 by
import cdms2
import numpy
# from . import _regrid
import regrid2._regrid as _regrid
from .error import RegridError
import copy

[docs]class PressureRegridder: """ PURPOSE: To perform all the tasks required to regrid the input data into the ouput data along the pressure dimension only. PROCEDURE: Step One: Make an instance of class PressureRegridder passing it input and output grid information Step Two: Pass the input data with some descriptive parameters and get the output data in return """ def __init__(self, axisIn, axisOut): """ #----------------------------------------------------------------------------------------------- # # PURPOSE: To make an instance which entails setting up the input and output grids # # DEFINITION: # # def __init__(self, levIn, levOut): # # PROCEDURE: # # The user must assemble two pieces of information: # # axisIn - the input level axis # # axisOut - the output level axis # # USAGE: # # To make an instance preparing for a regrid along the level dimension pnly, type # # r = PressureRegridder(levIn, levOut) # #------------------------------------------------------------------------------------------------ """ # --- set the instance grid data attributes used to describe input and output grid sizes self.axisIn = axisIn self.axisOut = axisOut self.nlevi = len(axisIn) self.nlevo = len(axisOut) def __call__(self, ar, missing=None, order=None, method="log"): """ Call the pressure regridder function. ar is the input array, a variable, masked array, or numpy array. missing is the missing data value, if any. It defaults to the missing/fill value defined for the input array, if any. order is of the form "tzyx", "tyx", etc. method is either 'log' to interpolate in the log of pressure, or 'linear' for linear interpolation. """ from cdms2.avariable import AbstractVariable from cdms2.tvariable import TransientVariable # Save Variable metadata for output if isinstance(ar, AbstractVariable): attrs = copy.copy(ar.attributes) varid = axislist = ar.getAxisList() inputIsVariable = 1 if order is None: order = ar.getOrder() # this expects contiguous arrays if isinstance( ar, TransientVariable) and ar.iscontiguous() is False: ar = ar.ascontiguous() else: inputIsVariable = 0 # Turn ar into a numpy array. if armiss = ar.fill_value ar = elif isinstance(ar, AbstractVariable): tempar = ar.getValue(squeeze=0) armiss = ar.getMissing() ar = elif isinstance(ar, numpy.ndarray): armiss = None else: raise RegridError( "Input array is not a Variable,, or numpy array") # Set missing value if missing is None: missing = armiss if isinstance(missing, numpy.ndarray): missing = missing[0] rank = len(ar.shape) assert 3 <= rank <= 4, 'Array rank is %i, must be 3 or 4' % rank # Set the default order to match the input grid order if order is None: if rank == 3: order = "zyx" elif rank == 4: order = "tzyx" assert rank == len( order), 'Order must be same length as array rank: %i' % len(ar.shape) order = order.lower() # Map order to positionIn positionIn = [None] * 4 for i in range(len(order)): if order[i] == 'x': positionIn[0] = i elif order[i] == 'y': positionIn[1] = i elif order[i] == 'z': positionIn[2] = i if inputIsVariable: axislist[i] = self.axisOut else: positionIn[3] = i # Regrid if method == 'log': logYes = 'yes' else: logYes = 'no' outar = self.rgrd(ar, missing, 'greater', logYes, positionIn) # Reconstruct the same class as on input if inputIsVariable == 1: result = cdms2.createVariable(outar, fill_value=missing, axes=axislist, attributes=attrs, id=varid) else: result =, fill_value=missing) return result
[docs] def rgrd(self, dataIn, missingValueIn, missingMatch, logYes='yes', positionIn=None, missingValueOut=None): """ To perform all the tasks required to regrid the input data, dataIn, into the ouput data, dataout along the level dimension only. Parameters ---------- dataIn : data to regrid missingValueIn : the missing data value to use in setting missing in the mask. It is required. * None -- there is no missing data * A number -- if the value to use in the search for possible missing data. The presence of missing data at a grid point leads to recording 0.0 in the mask. missingMatch : the comparison scheme used in searching for missing data in dataIn using the value passed in as missingValueIn. * None -- used if None is the entry for missingValueIn * exact -- used if missingValue is the exact value from the file * greater -- the missing data value is equal to or greater than missingValueIn * less -- the missing data value is equal to or less than missingValueIn logYes : choose the level regrid as linear in log of level or linear in level. * Set to 'yes' for log. Anything else is linear in level. positionIn : a tuple with the numerical position of the dimensions * in C or Python order specified in the sequence longitude, latitude, level and time. Longitude and Latitude are required. If time is missing submit None in its slot in the tuple. Notice that the length of the tuple is always four. Explicitly, in terms of the shape of dataIn as returned by python's shape function positionIn[0] contains the position of longitude in dataIn positionIn[1] contains the position of latitude in dataIn positionIn[2] contains the position of level in dataIn or None positionIn[3] contains the position of time in dataIn or None If the c order shape of 4D data is * (number of longitudes, number of times, number of levels, number of latitudes) submit * (0, 3, 2, 1). If the c order shape of 3D data is * (number of longitudes, number of times, number of latitudes) submit * (0, 2, 1, None). Send in None if the shape is a subset of (time, level, latitude, longitude) which is evaluated as follows: * 3D -- code assumes (2,1,0,None) * 4D -- code assumes (3,2,1,0) missingValueOut : the value for the missing data used in writing the output data. * If left at the default entry, None, the code uses missingValueIn * If present or as a last resort 1.0e20 Returns ------- dataOut : the regridded data Example ------- To regrid dataIn into dataOut using all the defaults where None, None signifies no missing data. * dataOut = x.rgrd(dataIn, None, None) To regrid dataIn into dataOut using 1.0e20 and greater as the missing data * dataOut = x.rgrd(dataIn, 1.e20, 'greater') Note: This code does not regrid cross sections which have a single dummy longitude value! """ # check the required input -- dataIn, missingValueIn and missingMatch # make sure that dataIn is an array try: len(dataIn) except TypeError: sendmsg('Error in calling the rgrd method -- dataIn must be an array') raise TypeError # check the missingValueIn pass if missingValueIn is not None: try: abs(missingValueIn) except TypeError: sendmsg( 'Error in calling the rgrd method -- missingvalueIn must be None or a number. Now it is ', missingValueIn) raise TypeError # check the missingMatch pass missingPossibilities = ['greater', 'equal', 'less', None] if missingMatch not in missingPossibilities: msg = 'Error in missingMatch -- it must be None or the string greater, equal, or less. Now it is ' sendmsg(msg, missingMatch) raise ValueError # --- Check data type and change to float if necessary ---- if dataIn.dtype.char != 'f': dataIn = dataIn.astype(numpy.float32) dataShape = dataIn.shape numberDim = len(dataShape) if numberDim < 2: msg = 'Error in call to rgrd -- data must have at least 2 dimensions' sendmsg(msg) raise TypeError # --- evaluate positionIn ---- # --- make standard positionIn as a check---- positionList = [] for n in range(numberDim): # insert a sequence of numbers positionList.append(n) positionList.reverse() for n in range(numberDim, 4): # fill end of list with Nones positionList.append(None) positionCheck = tuple(positionList) standardPosition = 0 # transpose required if positionIn is None: # construct the default positionIn tuple positionIn = positionCheck standardPosition = 1 # no need for a transpose with this data else: if positionIn == positionCheck: # compare to the standard standardPosition = 1 # no need for a transpose with this data if len(positionIn) != 4: msg = 'Error in call to rgrd -- positionIn must be a tuple of length 4' sendmsg(msg) raise TypeError # transpose data to the standard order (t,z,y,x) if standardPosition == 0: newOrder, inverseOrder = checkorder(positionIn) # transpose data to standard order (t,z,y,x) dataIn = numpy.transpose(dataIn, newOrder) dataIn = numpy.array( dataIn.astype( numpy.float32), numpy.float32) # make contiguous # set dimension sizes and check for consistency if positionIn[0] is not None: self.nlon = (dataShape[positionIn[0]]) else: self.nlon = 0 if positionIn[1] is not None: self.nlat = (dataShape[positionIn[1]]) else: self.nlat = 0 if positionIn[2] is not None: if self.nlevi != (dataShape[positionIn[2]]): msg = 'Level size is inconsistent with input data' sendmsg(msg) raise ValueError if positionIn[3] is not None: self.ntime = (dataShape[positionIn[3]]) else: self.ntime = 0 # allocate memory for dataOut -- the array with new number of levels outList = list(dataIn.shape) for i in range(len(outList)): if outList[i] == self.nlevi: outList[i] = self.nlevo break dataOut = numpy.zeros( tuple(outList), numpy.float32) # memory for aout if missingMatch is None: # if no missing do not pass None missingMatch = 'none' # if no missing do not pass None if missingValueIn is None: missingValueIn = 1.333e33 if logYes != 'yes': logYes = 'no' levIn = self.axisIn[:].astype(numpy.float64) levOut = self.axisOut[:].astype(numpy.float64) _regrid.rgdpressure( self.nlevi, self.nlevo, self.nlat, self.nlon, self.ntime, missingValueIn, missingMatch, logYes, levIn, levOut, dataIn, dataOut) # if no missing do not pass None if missingMatch == 'none': missingMatch = None if missingValueIn == 1.333e33: missingValueIn = None if standardPosition == 0: # transpose data to original order dataOut = numpy.transpose(dataOut, inverseOrder) dataOut = numpy.array( dataOut.astype( numpy.float32), numpy.float32) # make contiguous if missingValueOut is not None: # set the missing value in data to missingValueOut if missingMatch == 'greater': if missingValueIn > 0.0: missing = 0.99 * missingValueIn else: missing = 1.01 * missingValueIn dataOut = numpy.where( numpy.greater( dataOut, missing), missingValueOut, dataOut) elif missingMatch == 'equal': missing = missingValueIn dataOut = numpy.where( numpy.equal( dataOut, missing), missingValueOut, dataOut) elif missingMatch == 'less': if missingValueIn < 0.0: missing = 0.99 * missingValueIn else: missing = 1.01 * missingValueIn dataOut = numpy.where( numpy.less( dataOut, missing), missingValueOut, dataOut) return dataOut
[docs]def checkorder(positionIn): """ Purpose : construct the tuples for transposing the data to standard dimension order and the inverse for transposing it back to the original dimension order Usage : newOrder, inverseOrder = checkorder(positionIn) Passed : positionIn -- array with location of longitude, latitude. level and time respectively in the sense of the python shape of the data Returns ------- newOrder : tuple to transpose data to the order (t,z,y,x) inverseOrder : tuple to transpose data to back to the original order """ # remove the None values from positionIn and reverse the order reducedPosition = [] for item in positionIn: if item is not None: reducedPosition.append(item) reducedPosition.reverse() # make the newOrder tuple newOrder = tuple(reducedPosition) # ----- Determine the inverse to this new order for use in mathtogeo ----- xform = [] for i in range(len(newOrder)): xform.append([newOrder[i], i]) xform.sort() inverse_shapelist = [] for item in xform: inverse_shapelist.append(item[1]) inverseOrder = tuple(inverse_shapelist) return newOrder, inverseOrder
[docs]def sendmsg(msg, value1=None, value2=None): """ Purpose : send the same message to the screen Passed : msg - the string value - the number associated with the string Returns ------- return """ print('*******************************************************************') if value1 is None: print(msg) elif value2 is None: print((msg, value1)) else: print((msg, value1, value2)) print('*******************************************************************') return None