def __init__(self, data, typecode=None, copy=0, savespace=0, mask=None, fill_value=None, axes=None, attributes=None, id=None, copyaxes=1, bounds=None): """Create a transient 2D axis. All arguments are as for TransientVariable. 'bounds' is the bounds array, having shape (m,n,nvert) where data.shape is (m,n) and nvert is the max number of vertices per cell. """ AbstractAxis2D.__init__(self, None, None, bounds=bounds) TransientVariable.__init__(self, data, typecode=typecode, copy=copy, savespace=savespace, mask=mask, fill_value=fill_value, axes=axes, attributes=attributes, id=id, copyaxes=copyaxes) if axes is not None: self.setBounds(bounds)
def average (a, axis=None, weights=None, returned=False): axis = _conv_axis_arg(axis) ta = _makeMaskedArg(a) maresult = numpy.ma.average(ta, axis, weights, returned) axes, attributes, id, grid = _extractMetadata(a, omit=axis, omitall=(axis is None)) if returned: maresult, wresult = maresult F=getattr(a,"fill_value",1.e20) r1 = TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id,no_update_from=True, fill_value=F) if returned: F=getattr(a,"fill_value",1.e20) w1 = TransientVariable(wresult, axes=axes, grid=grid, id=id,no_update_from=True, fill_value=F) return r1, w1 else: return r1
def outerproduct(a, b): """outerproduct(a,b) = {a[i]*b[j]}, has shape (len(a),len(b))""" ta = asVariable(a, writeable=1) tb = asVariable(b, writeable=1) maresult = numpy.ma.outerproduct(ta, tb) axes = (ta.getAxis(0), tb.getAxis(0)) return TransientVariable(maresult, axes=axes)
def masked_values(data, value, rtol=1.e-5, atol=1.e-8, copy=1, savespace=0, axes=None, attributes=None, id=None): """ masked_values(data, value, rtol=1.e-5, atol=1.e-8) Create a masked array; mask is None if possible. May share data values with original array, but not recommended. Masked where abs(data-value)<= atol + rtol * abs(value) """ maresult = numpy.ma.masked_values(_makeMaskedArg(data), value, rtol=rtol, atol=atol, copy=copy) axes, attributes, id, grid = _extractMetadata(data, axes, attributes, id) F = getattr(data, "fill_value", 1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def power (a, b, third=None): "a**b" ta = _makeMaskedArg(a) tb = _makeMaskedArg(b) maresult = numpy.ma.power(ta,tb,third) axes, attributes, id, grid = _extractMetadata(a) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id)
def right_shift (a, n): "Right shift n bits" ta = _makeMaskedArg(a) tb = _makeMaskedArg(n) maresult = numpy.ma.right_shift(ta,numpy.ma.filled(tb)) axes, attributes, id, grid = _extractMetadata(a) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id)
def masked_inside(x, v1, v2): "x with mask of all values of x that are inside [v1,v2]" tx = _makeMaskedArg(x) maresult = numpy.ma.masked_inside(tx, v1, v2) axes, attributes, id, grid = _extractMetadata(x) F=getattr(x,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def masked_not_equal(x, value): "masked_not_equal(x, value) = x masked where x != value" tx = _makeMaskedArg(x) maresult = numpy.ma.masked_not_equal(tx, value) axes, attributes, id, grid = _extractMetadata(x) F=getattr(x,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def compress(a, b): __doc__ = numpy.ma.__doc__ import warnings warnings.warn( "arguments order for compress function has changed\nit is now: MV2.copmress(array,condition), if your code seems to not react or act wrong to a call to compress, please check this", Warning) return TransientVariable(numpy.ma.compress(a, b), copy=1)
def diagonal (a, offset = 0, axis1=0, axis2 = 1): """diagonal(a, offset=0, axis1=0, axis2 = 1) returns the given diagonals defined by the two dimensions of the array. """ F=getattr(a,"fill_value",1.e20) return TransientVariable(numpy.ma.diagonal(_makeMaskedArg(a), offset, axis1, axis2), fill_value=F)
def product (a, axis = 0, dtype=None): "Product of elements along axis." ta = _makeMaskedArg(a) maresult = numpy.ma.product(ta, axis, dtype=dtype) axes, attributes, id, grid = _extractMetadata(a, omit=axis) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id, fill_value=F)
def sum (a, axis = None, fill_value=0, dtype=None): "Sum of elements along a certain axis." axis = _conv_axis_arg(axis) ta = _makeMaskedArg(a) maresult = numpy.ma.sum(ta, axis, dtype=dtype) axes, attributes, id, grid = _extractMetadata(a, omit=axis, omitall=(axis is None)) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id, fill_value=F)
def __call__(self, a): axes, attributes, id, grid = _extractMetadata(a) maresult = self.mafunc(_makeMaskedArg(a)) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid)
def where (condition, x, y): "where(condition, x, y) is x where condition is true, y otherwise" ## axes = commonDomain(x,y) ## grid = commonGrid(x,y,axes) maresult = numpy.ma.where(condition, _makeMaskedArg(x), _makeMaskedArg(y)) axes, attributes, id, grid = _extractMetadata(condition) F=getattr(x,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id, fill_value=F)
def min (a, axis=None): axis = _conv_axis_arg(axis) ta = _makeMaskedArg(a) maresult = numpy.ma.min(ta, axis) axes, attributes, id, grid = _extractMetadata(a, omit=axis, omitall=(axis is None)) F=getattr(a,"fill_value",1.e20) r1 = TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id,no_update_from=True, fill_value=F) return r1
def concatenate(arrays, axis=0, axisid=None, axisattributes=None): """Concatenate the arrays along the given axis. Give the extended axis the id and attributes provided - by default, those of the first array.""" tarrays = [_makeMaskedArg(a) for a in arrays] maresult = numpy.ma.concatenate(arrays, axis=axis) if len(arrays) > 1: varattributes = None varid = None axes = commonDomain(tarrays[0], tarrays[1], omit=axis) grid = commonGrid(tarrays[0], tarrays[1], axes) for i in range(len(arrays) - 2): if axes is None: break axes = commonAxes(tarrays[i + 2], axes, omit=axis) grid = commonGrid1(a, grid, axes) else: axes = tarrays[0].getAxisList() varattributes = tarrays[0].attributes varid = tarrays[0].id if (isinstance(tarrays[0], TransientVariable)): grid = tarrays[0].getGrid() else: grid = None if axes is not None: if axisid is None: axisid = tarrays[0].getAxis(axis).id allunitsequal = True try: allunits = tarrays[0].getAxis(axis).units except: allunits = None for t in tarrays[1:]: try: tunits = t.getAxis(axis).units except: tunits = None if tunits != allunits: allunitsequal = False if allunitsequal: if axisattributes is None: axisattributes = tarrays[0].getAxis(axis).attributes axes[axis] = axisConcatenate([t.getAxis(axis) for t in tarrays], axisid, axisattributes) # If the grid doesn't match the axislist (e.g., catenation was on latitude) then omit it. if grid is not None: for item in grid.getAxisList(): if item not in axes: grid = None F = getattr(arrays[0], "fill_value", 1.e20) return TransientVariable(maresult, axes=axes, attributes=varattributes, id=varid, grid=grid, fill_value=F)
def accumulate(self, target, axis=0): ttarget = _makeMaskedArg(target) maresult = self.mafunc.accumulate(ttarget, axis=axis) axes, attributes, id, grid = _extractMetadata(target, omit=axis) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid)
def __call__ (self, a, b): id = "variable_%i" % TransientVariable.variable_count TransientVariable.variable_count+=1 axes = commonDomain(a,b) grid = commonGrid(a,b,axes) ta = _makeMaskedArg(a) tb = _makeMaskedArg(b) maresult = self.mafunc(ta,tb) return TransientVariable(maresult, axes=axes, grid=grid,no_update_from=True,id=id)
def masked_equal(x, value): """masked_equal(x, value) = x masked where x == value For floating point consider masked_values(x, value) instead. """ tx = _makeMaskedArg(x) maresult = numpy.ma.masked_equal(tx, value) axes, attributes, id, grid = _extractMetadata(x) F=getattr(x,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def masked_array (a, mask=None, fill_value=None, axes=None, attributes=None, id=None): """masked_array(a, mask=None) = array(a, mask=mask, copy=0, fill_value=fill_value) Use fill_value(a) if None. """ maresult = numpy.ma.masked_array(_makeMaskedArg(a), mask=mask, fill_value=fill_value) axes, attributes, id, grid = _extractMetadata(a, axes, attributes, id) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def reshape (a, newshape, axes=None, attributes=None, id=None, grid=None): ignore, attributes, id, ignore = _extractMetadata(a, axes, attributes, id) if axes is not None: axesshape = [len(item) for item in axes] if axesshape!=list(newshape): raise CDMSError, 'axes must be shaped %s'%`newshape` ta = _makeMaskedArg(a) maresult = numpy.ma.reshape(ta, newshape) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, no_update_from=True, fill_value=F)
def argsort (x, axis = -1, fill_value=None): """Treating masked values as if they have the value fill_value, return sort indices for sorting along given axis. if fill_value is None, use fill_value(x) """ tx = _makeMaskedArg(x) maresult = numpy.ma.argsort(tx,axis=axis,fill_value=fill_value) axes, attributes, id, grid = _extractMetadata(x) F=getattr(x,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def choose(indices, t): """Returns an array shaped like indices containing elements chosen from t. If an element of t is the special element masked, any element of the result that "chooses" that element is masked. The result has only the default axes. """ maresult = numpy.ma.choose(indices, map(_makeMaskedArg, t)) return TransientVariable(maresult)
def masked_where(condition, x, copy=1): """Return x as an array masked where condition is true. Also masked where x or condition masked. """ tx = _makeMaskedArg(x) tcondition = _makeMaskedArg(condition) maresult = numpy.ma.masked_where(tcondition, tx, copy) axes, attributes, id, grid = _extractMetadata(x) F=getattr(x,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def count (a, axis = None): "Count of the non-masked elements in a, or along a certain axis." if axis is None: return numpy.ma.count(a,axis) else: ta = _makeMaskedArg(a) maresult = numpy.ma.count(ta,axis) axes, attributes, id, grid = _extractMetadata(a,omit=axis) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id, fill_value=F)
def sort (a, axis=-1): ta = _makeMaskedArg(a) maresult = numpy.ma.sort(a.asma(), axis) axes, attributes, id, grid = _extractMetadata(a) sortaxis = axes[axis] if (grid is not None) and (sortaxis in grid.getAxisList()): grid = None axes[axis] = TransientAxis(numpy.arange(len(sortaxis))) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, grid=grid, id=id, fill_value=F)
def arrayrange(start, stop=None, step=1, typecode=None, axis=None, attributes=None, id=None, dtype=None): """Just like range() except it returns a variable whose type can be specfied by the keyword argument typecode. The axis of the result variable may be specified. """ dtype = _convdtype(dtype, typecode) if stop is None: maresult = numpy.ma.arange(start, step=step, dtype=dtype) else: maresult = numpy.ma.arange(start, stop=stop, step=step, dtype=dtype) return TransientVariable(maresult, axes=(axis,), attributes=attributes, id=id)
def masked_outside(x, v1, v2): "x with mask of all values of x that are outside [v1,v2]" tx = _makeMaskedArg(x) maresult = numpy.ma.masked_outside(tx, v1, v2) axes, attributes, id, grid = _extractMetadata(x) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid)
def masked_less_equal(x, value): "masked_less_equal(x, value) = x masked where x <= value" tx = _makeMaskedArg(x) maresult = numpy.ma.masked_less_equal(tx, value) axes, attributes, id, grid = _extractMetadata(x) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid)
def asarray(data, typecode=None, dtype=None): """asarray(data, typecode=None, dtype=None) is equivalent to array(data, dtype=None, copy=0) Returns data if dtype is None or data is a MaskedArray of the same dtype. typecode arg is for backward compatibility. """ dtype = _convdtype(dtype, typecode) if isinstance(data, AbstractVariable) and (dtype is None or sctype2char(dtype) == data.dtype.char): return data else: F=getattr(data,"fill_value",1.e20) return TransientVariable(data, dtype=dtype, copy=0, fill_value=F)
def resize (a, new_shape, axes=None, attributes=None, id=None, grid=None): """resize(a, new_shape) returns a new array with the specified shape. The original array's total size can be any size.""" ignore, attributes, id, ignore = _extractMetadata(a, axes, attributes, id) if axes is not None: axesshape = [len(item) for item in axes] if axesshape!=list(new_shape): raise CDMSError, 'axes must be shaped %s'%`newshape` ta = _makeMaskedArg(a) maresult = numpy.ma.resize(ta, new_shape) F=getattr(a,"fill_value",1.e20) return TransientVariable(maresult, axes=axes, attributes=attributes, id=id, grid=grid, fill_value=F)
def subRegion (self, *specs, **keys): speclist = self._process_specs (specs, keys) slicelist = self.reg_specs2slices (speclist) squeeze = keys.get ('squeeze', 0) raw = keys.get('raw',0) order = keys.get('order', None) grid = keys.get('grid', None) raweasy = raw==1 and order is None and grid is None if grid is not None and order is None: order = grid.getOrder() # Check if any slice wraps around. wrapdim = -1 axes = [] circulardim = None for idim in range(len(slicelist)): item = slicelist[idim] axis = self.getAxis(idim) axislen = len(axis) if(axis.isCircular()): circulardim=idim wraptest1 = ( axis.isCircular() and speclist[idim] != unspecified) start, stop = item.start, item.stop wraptest2 = not ((start is None or (0<=start<axislen)) and (stop is None or (0<=stop<=axislen))) if ( wraptest1 and wraptest2): if wrapdim >= 0: raise CDMSError, "Too many dimensions wrap around." wrapdim = idim break else: # No wraparound, just read the data # redo the speclist -> slice if passed circular test but not wrapped test if(circulardim is not None): slicelist = self.reg_specs2slices (speclist,force=circulardim) d = {'raw':raw, 'squeeze':squeeze, 'order':order, 'grid':grid, } return self.subSlice(*slicelist, **d) # # get the general wrap slice (indices that are neg -> pos and vica versa) # wrapslice = slicelist[wrapdim] wrapaxis = self.getAxis(wrapdim) length = len(wrapaxis) # # shift the wrap slice to the positive side and calc number of cycles shifted # wb=wrapslice.start we=wrapslice.stop ws=wrapslice.step size=length cycle=self.getAxis(wrapdim).getModulo() # # ncycle: # number of cycles for slicing purposes and # resetting world coordinate from the positive only direction # # ncyclesrev: # resetting the world coordinate for reversed direction # ncycles=0 ncyclesrev=0 if(ws>0): if(wb>0): ncycles=1 while(wb>=0): wb=wb-size we=we-size ncycles=ncycles-1 else: ncycles=0 while(wb<0): wb=wb+size we=we+size ncycles=ncycles+1 if(wb < 0): wb=wb+size we=we+size # reversed direction else: # do the ncycles for resetting world coordinate wbrev=wb werev=we werevNoneTest=0 if(werev is None): werev=0 werevNoneTest=1 ncycleRevStart=1 if(wbrev > 0): ncyclesrev=ncycleRevStart while(wbrev>=0): wbrev=wbrev-size werev=werev-size ncyclesrev=ncyclesrev-1 else: ncyclesrev=0 while(wbrev<0): wbrev=wbrev+size werev=werev+size ncyclesrev=ncyclesrev+1 while(werev < 0): wbrev=wbrev+size werev=werev+size # number of cycles to make the slice positive while( we<0 and we != None ): wb=wb+size we=we+size ncycles=ncycles+1 wb=wbrev we=werev if(werevNoneTest): we=None wrapslice=slice(wb,we,ws) # # calc the actual positive slices and create data array # donew=1 if(donew): wraps = splitSliceExt(wrapslice, length) for kk in range(0,len(wraps)): sl=wraps[kk] slicelist[wrapdim] = sl if(kk == 0): ar1 = self.getSlice(squeeze=0, *slicelist) result=ar1 else: ar2 = self.getSlice(squeeze=0, *slicelist) result = numpy.ma.concatenate((result,ar2),axis=wrapdim) else: wrap1, wrap2 = splitSlice(wrapslice, length) slicelist[wrapdim] = wrap1 ar1 = self.getSlice(squeeze=0, *slicelist) slicelist[wrapdim] = wrap2 ar2 = self.getSlice(squeeze=0, *slicelist) result = numpy.ma.concatenate((ar1,ar2),axis=wrapdim) if raweasy: return self._returnArray(result, squeeze) #---------------------------------------------------------------------- # # set ALL the axes (transient variable) # #---------------------------------------------------------------------- wrapspec=speclist[wrapdim] axes = [] for i in range(self.rank()): if squeeze and numpy.ma.size(result, i) == 1: continue sl = slicelist[i] if i == wrapdim: axis = self.getAxis(i).subAxis(wb, we, ws) if(ws > 0): delta_beg_wrap_dimvalue = ncycles*cycle else: delta_beg_wrap_dimvalue = ncyclesrev*cycle axis.setBounds(axis.getBounds() - delta_beg_wrap_dimvalue) axis[:]= (axis[:] - delta_beg_wrap_dimvalue).astype(axis.typecode()) else: axis = self.getAxis(i).subaxis(sl.start, sl.stop, sl.step) axes.append(axis) result = self._returnArray(result, squeeze) result = TransientVariable(result, copy=0, fill_value = self.missing_value, axes=axes, attributes=self.attributes, id = self.id) if grid is not None: order2 = grid.getOrder() if order is None: order = order2 elif order != order2: raise CDMSError, 'grid, order options not compatible.' result = result.reorder(order).regrid(grid) if raw == 0: return result else: return result.getSlice(squeeze=0, raw=1)
def subSlice (self, *specs, **keys): speclist = self._process_specs (specs, keys) numericSqueeze = keys.get('numericSqueeze',0) # Get a list of single-index specs if numericSqueeze: singles = self._single_specs(specs) else: singles = None slicelist = self.specs2slices(speclist,force=1) d = self.expertSlice (slicelist) squeeze = keys.get ('squeeze', 0) raw = keys.get('raw',0) order = keys.get('order', None) grid = keys.get('grid', None) forceaxes = keys.get('forceaxes', None) # Force result to have these axes raweasy = raw==1 and order is None and grid is None if not raweasy: if forceaxes is None: axes = [] allaxes = [None]*self.rank() for i in range(self.rank()): slice = slicelist[i] if squeeze and numpy.ma.size(d, i) == 1: continue elif numericSqueeze and i in singles: continue # Don't wrap square-bracket slices axis = self.getAxis(i).subaxis(slice.start, slice.stop, slice.step, wrap=(numericSqueeze==0)) axes.append(axis) allaxes[i] = axis else: axes = forceaxes # Slice the grid, if non-rectilinear. Don't carry rectilinear grids, since # they can be inferred from the domain. selfgrid = self.getGrid() if selfgrid is None or isinstance(selfgrid, AbstractRectGrid): resultgrid = None else: alist = [item[0] for item in self.getDomain()] gridslices, newaxes = selfgrid.getGridSlices(alist, allaxes, slicelist) # If one of the grid axes was squeezed, the result grid is None if None in newaxes: resultgrid = None else: resultgrid = apply(selfgrid.subSlice, gridslices, {'forceaxes': newaxes}) resultArray = self._returnArray(d, squeeze, singles=singles) if self.isEncoded(): resultArray = self.decode(resultArray) newmissing = resultArray.fill_value else: newmissing = self.getMissing() if raweasy: return resultArray elif len(axes)>0: # If forcing use of input axes, make sure they are not copied. # Same if the grid is not rectilinear - this is when forceaxes is set. copyaxes = (forceaxes is None) and (resultgrid is None) result = TransientVariable(resultArray, copy=0, fill_value = newmissing, axes=axes, copyaxes = copyaxes, grid = resultgrid, attributes=self.attributes, id = self.id) if grid is not None: order2 = grid.getOrder() if order is None: order = order2 elif order != order2: raise CDMSError, 'grid, order options not compatible.' result = result.reorder(order).regrid(grid) if raw == 0: return result else: return result.getSlice(squeeze=0, raw=1) else: # Return numpy.ma for zero rank, so that __cmp__ works. return resultArray