Source code for regrid2.scrip

# Automatically adapted for numpy.oldnumeric Aug 02, 2007 by

import cdms2
# from . import _scrip
import regrid2._scrip as _scrip
from .error import RegridError
import numpy
from functools import reduce

"""Regrid support for nonrectangular grids, based on the SCRIP package."""


[docs]class ScripRegridder: def __init__(self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=None, sourceFrac=None, destFrac=None): self.outputGrid = outputGrid self.remapMatrix = remapMatrix self.sourceAddress = sourceAddress self.destAddress = destAddress self.inputGrid = inputGrid self.sourceFrac = sourceFrac self.destFrac = destFrac def __call__(self, input): import numpy.ma from cdms2 import isVariable from cdms2.tvariable import TransientVariable # If input is a variable, make it a TV if isVariable(input) and not isinstance(input, TransientVariable): input = input.subSlice() isvar = isinstance(input, TransientVariable) if isvar: domain = tuple(input.getAxisList()) if self.inputGrid is not None: ingrid = self.inputGrid else: ingrid = input.getGrid() if ingrid is None: raise RegridError( "Input variable must have an associated grid.") rank = len(ingrid.shape) gridsize = ingrid.size() outgridshape = self.outputGrid.shape # Check that the grid matches the last dimension(s) of input if input.shape[-rank:] != ingrid.shape: raise RegridError( 'Last dimensions of input array must match grid shape: %s' % repr( ingrid.shape)) # this expects contiguous arrays if input.iscontiguous() is False: input = input.ascontiguous() else: rank = 1 # If not a TV, last dimension is the 'cell' dimension gridsize = input.shape[-1] outgridshape = ( reduce( lambda x, y: x * y, self.outputGrid.shape, 1), ) # If input is an numpy.ma, make it Numeric if numpy.ma.isMaskedArray(input): input = input.filled() restoreShape = input.shape[:-rank] restoreLen = reduce(lambda x, y: x * y, restoreShape, 1) oldshape = input.shape newshape = (restoreLen, gridsize) input.shape = newshape # Regrid output = self.regrid(input) # Reshape output and restore input shape input.shape = oldshape outshape = restoreShape + outgridshape output.shape = outshape # If the input was a variable, so is the output if isvar: outdomain = domain[:-rank] + (self.outputGrid,) output = TransientVariable(output, axes=outdomain) return output
[docs] def getOutputGrid(self): return self.outputGrid
[docs] def getInputGrid(self): return self.inputGrid
[docs] def getSourceFraction(self): return self.sourceFrac
[docs] def getDestinationFraction(self): return self.destFrac
[docs]class ConservativeRegridder(ScripRegridder): """First-order conservative regrid. By default, the normalize option ="fracarea", and array 'normal' is not specified. If 'normal' is specified, it should be a one-dimensional array of the same length as the output grid size, with values: 1.0 for normalize="fracarea", grid_frac for normalize="destarea", or grid_frac*grid_area for normalize="none". Parameters ---------- sourceArea is the area of the source grid cells destArea is the area of the destination grid cells """ def __init__(self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=None, sourceFrac=None, destFrac=None, normalize="fracarea", normal=None, sourceArea=None, destArea=None): if normalize not in ["fracarea", "destarea", "none"]: raise RegridError("Invalid normalization option: %s" % normalize) ScripRegridder.__init__( self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=inputGrid, sourceFrac=sourceFrac, destFrac=destFrac) self.normalize = normalize self.normal = None self.sourceArea = sourceArea self.destArea = destArea
[docs] def getSourceArea(self): return self.sourceArea
[docs] def getDestinationArea(self): return self.destArea
[docs] def regrid(self, input): """ call regridder """ if self.normal is None: # print "On input, num_links = %d"%(len(self.sourceAddress)) # print "On input, nextra = %d"%(input.shape[0]) # print "On input, ninput = %d"%(input.shape[1]) # print "On input, noutput = %d"%(self.outputGrid.size()) # print "On input, shape(input) = %s"%`input.shape` # print "On input, shape(output) = %s"%`self.outputGrid.shape` # print "On input, shape(remap_matrix) = %s"%`self.remapMatrix.shape` # print "On input, shape(src_address) = %s"%`self.sourceAddress.shape` # print "On input, shape(dst_address) = # %s"%`self.destAddress.shape` result = _scrip.conserv_regrid( self.outputGrid.size(), input, self.remapMatrix, self.sourceAddress, self.destAddress) else: result = _scrip.conserv_regrid_normal( self.outputGrid.size(), input, self.remapMatrix, self.sourceAddress, self.destAddress, self.normal) return result
[docs]class BilinearRegridder(ScripRegridder): def __init__(self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=None, sourceFrac=None, destFrac=None): ScripRegridder.__init__( self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=inputGrid, sourceFrac=sourceFrac, destFrac=destFrac)
[docs] def regrid(self, input): result = _scrip.bilinear_regrid( self.outputGrid.size(), input, self.remapMatrix, self.sourceAddress, self.destAddress) return result
[docs]class BicubicRegridder(ScripRegridder): """Bicubic regrid. Parameters ---------- gradLat: df/di gradLon: df/dj gradLatlon: d(df)/(di)(dj) """ def __init__(self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=None, sourceFrac=None, destFrac=None): ScripRegridder.__init__( self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=inputGrid, sourceFrac=sourceFrac, destFrac=destFrac) def __call__(self, input, gradLat, gradLon, gradLatlon): import numpy.ma from cdms2 import isVariable from cdms2.tvariable import TransientVariable if (gradLat.shape != input.shape or gradLon.shape != input.shape or gradLatlon.shape != input.shape): raise RegridError( "All input arrays must have shape %s" % repr( input.shape)) if (not isinstance(gradLat, type(input)) or not isinstance(gradLon, type(input)) or not isinstance(gradLatlon, type(input))): raise RegridError( "All input arrays must have type %s" % repr( type(input))) # If input is a variable, make it a TV if isVariable(input) and not isinstance(input, TransientVariable): input = input.subSlice() gradLat = gradLat.subSlice() gradLon = gradLon.subSlice() gradLatlon = gradLatlon.subSlice() isvar = isinstance(input, TransientVariable) if isvar: domain = tuple(input.getAxisList()) if self.inputGrid is not None: ingrid = self.inputGrid else: ingrid = input.getGrid() if ingrid is None: raise RegridError( "Input variable must have an associated grid.") rank = len(ingrid.shape) gridsize = ingrid.size() outgridshape = self.outputGrid.shape # Check that the grid matches the last dimension(s) of input if input.shape[-rank:] != ingrid.shape: raise RegridError( 'Last dimensions of input array must match grid shape: %s' % repr( ingrid.shape)) else: rank = 1 # If not a TV, last dimension is the 'cell' dimension gridsize = input.shape[-1] outgridshape = ( reduce( lambda x, y: x * y, self.outputGrid.shape, 1), ) # If input is an numpy.ma, make it Numeric if numpy.ma.isMaskedArray(input): input = input.filled() gradLat = gradLat.filled() gradLon = gradLon.filled() gradLatlon = gradLatlon.filled() restoreShape = input.shape[:-rank] restoreLen = reduce(lambda x, y: x * y, restoreShape, 1) oldshape = input.shape newshape = (restoreLen, gridsize) input.shape = newshape gradLat.shape = newshape gradLon.shape = newshape gradLatlon.shape = newshape # Regrid output = _scrip.bicubic_regrid( self.outputGrid.size(), input, self.remapMatrix, self.sourceAddress, self.destAddress, gradLat, gradLon, gradLatlon) # Reshape output and restore input shape input.shape = oldshape gradLat.shape = oldshape gradLon.shape = oldshape gradLatlon.shape = oldshape outshape = restoreShape + outgridshape output.shape = outshape # If the input was a variable, so is the output if isvar: outdomain = domain[:-rank] + (self.outputGrid,) output = TransientVariable(output, axes=outdomain) return output
[docs]class DistwgtRegridder(ScripRegridder): def __init__(self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=None, sourceFrac=None, destFrac=None): ScripRegridder.__init__( self, outputGrid, remapMatrix, sourceAddress, destAddress, inputGrid=inputGrid, sourceFrac=sourceFrac, destFrac=destFrac)
[docs] def regrid(self, input): result = _scrip.distwgt_regrid( self.outputGrid.size(), input, self.remapMatrix, self.sourceAddress, self.destAddress) return result
[docs]def readRegridder(fileobj, mapMethod=None, checkGrid=1): """Read a regridder from an open fileobj. Parameters ---------- mapMethod : is one of "conservative", "bilinear", "bicubic", or "distwgt". If unspecified, it defaults to the method defined in the file. If 'checkGrid' is 1 (default), the grid cells are checked for convexity, and 'repaired' if necessary. """ if isinstance(fileobj, str): fileobj = cdms2.open(fileobj) elif not isinstance(fileobj, cdms2.dataset.CdmsFile): raise RegridError( "fileobj arguments must be a cdms2 file or a string pointing to a file") if mapMethod is None: mapString = fileobj.map_method.strip().lower() if mapString[0:12] == "conservative": mapMethod = "conservative" elif mapString[0:8] == "bilinear": mapMethod = "bilinear" elif mapString[0:7] == "bicubic": mapMethod = "bicubic" elif mapString[0:8] == "distance" or mapString[0:7] == "distwgt": mapMethod = "distwgt" else: raise RegridError("Unrecognized map method: %s" % mapString) convention = 'SCRIP' if list(fileobj.variables.keys()).count('S'): convention = 'NCAR' if convention == 'SCRIP': remapMatrix = fileobj('remap_matrix').filled() srcAddress = fileobj('src_address').filled() dstAddress = fileobj('dst_address').filled() srcfrac = fileobj('src_grid_frac') dstfrac = fileobj('dst_grid_frac') else: remapMatrix = fileobj('S').filled() srcAddress = fileobj('col').filled() dstAddress = fileobj('row').filled() srcfrac = fileobj('frac_a') dstfrac = fileobj('frac_b') ingrid = fileobj.readScripGrid(whichGrid="source", checkGrid=checkGrid) outgrid = fileobj.readScripGrid( whichGrid="destination", checkGrid=checkGrid) if mapMethod == "conservative": if convention == 'SCRIP': srcarea = fileobj('src_grid_area') dstarea = fileobj('dst_grid_area') else: # NCAR stuff if "S2" in list(fileobj.variables.keys()): remapMatrix = fileobj("S2") sh = list(remapMatrix.shape) if len(sh) == 2 and sh[-1] == 2: sh[-1] = 1 S = fileobj("S").filled() S.shape = sh remapMatrix = numpy.concatenate((S, remapMatrix), axis=1) srcarea = fileobj('area_a') dstarea = fileobj('area_b') regridder = ConservativeRegridder( outgrid, remapMatrix, srcAddress, dstAddress, inputGrid=ingrid, sourceFrac=srcfrac, destFrac=dstfrac, sourceArea=srcarea, destArea=dstarea) elif mapMethod == "bilinear": regridder = BilinearRegridder( outgrid, remapMatrix, srcAddress, dstAddress, inputGrid=ingrid, sourceFrac=srcfrac, destFrac=dstfrac) elif mapMethod == "bicubic": regridder = BicubicRegridder( outgrid, remapMatrix, srcAddress, dstAddress, inputGrid=ingrid, sourceFrac=srcfrac, destFrac=dstfrac) elif mapMethod == "distwgt": regridder = DistwgtRegridder( outgrid, remapMatrix, srcAddress, dstAddress, inputGrid=ingrid, sourceFrac=srcfrac, destFrac=dstfrac) else: raise RegridError("Unrecognized map method: %s" % mapMethod) return regridder