def getValue(self,extraslices=None,dataonly=False): # Resolve any lazy objects in our slice specification. slices = LazyExpression.argument2value(self.slice,dataonly=True) slices = common.processEllipsis(slices,len(self.args[0].getDimensions())) if self.simpleslices: # Slice specification is integer-based - determine the final indices based on the shape of the data. # This is *required* if this slice is to be combined with a higher level slice (extraslices argument). shape = self.args[0].getShape() if shape is not None: newslices = [] for sl,l in zip(slices,shape): if isinstance(sl,slice): start,stop,step = sl.indices(l) sl = slice(start,stop,step) newslices.append(sl) slices = tuple(newslices) if extraslices is not None: # Add the additional slices assert self.simpleslices,'LazySlice variable receives additional slice, but does not support slice combination.' shape = self.getShape() extraslices = [extraslices.get(d,slice(0,shape[i],1)) for i,d in enumerate(self.getDimensions())] slices = LazyExpression.combineSlices(slices,extraslices) # Convert list of slices to dictionary linking dimension name to corresponding slice. slices = dict(zip(self.args[0].getDimensions(),slices)) return LazyExpression.argument2value(self.args[0],slices,dataonly=dataonly)
def adjustDimensions(dimnames,slic): slic = common.processEllipsis(slic,len(dimnames)) assert len(dimnames)==len(slic), 'Number of slices (%i) does not match number of dimensions (%i).' % (len(slic),len(dimnames)) dimnames = list(dimnames) for i in range(len(dimnames)-1,-1,-1): if not isinstance(slic[i],slice): curshape = getShape(slic[i]) if curshape is not None and len(curshape)==0: del dimnames[i] return dimnames
def slices2prettystring(slices,dimnames): """This function takes a slice object and converts it to a descriptive slice specification string. """ slices = common.processEllipsis(slices,len(dimnames)) slicestrings = [] for dimname,slic in zip(dimnames,slices): res = LazyExpression.slice2string(slic) if res!=':' and res!='...': slicestrings.append('%s=%s' % (dimname,res)) return '[%s]' % ','.join(slicestrings)
def adjustShape(shape,slic): if shape is None: return None slic = common.processEllipsis(slic,len(shape)) assert len(shape)==len(slic), 'Number of slices (%i) does not match number of dimensions (%i).' % (len(slic),len(shape)) baseshape = list(shape) for i in range(len(baseshape)-1,-1,-1): if isinstance(slic[i],slice): # For non-integer slices we do not know the resulting shape if not (isinstance(slic[i].start,(int,types.NoneType)) and isinstance(slic[i].stop,(int,types.NoneType))): return None start,stop,step = slic[i].indices(baseshape[i]) baseshape[i] = (stop-start-1)/step+1 else: curshape = getShape(slic[i]) if curshape is None or len(curshape)>0: # Slice object will be an array or has unknown shape - final shape is unknown return None del baseshape[i] return baseshape
def __getitem__(self,slices): shape = self.getShape() if self.outsourceslices and shape is not None: # We are allowed to outsource the slicing to the arguments of the expression. # This takes away the need of first getting all data to operate on, and then # take a slice, which is time-consuming and memory-intensive. slices = common.processEllipsis(slices,len(shape)) newargs = [] for arg in self.args: if isinstance(arg,LazyExpression): # Argument is an expression: outsource the slicing argshape = arg.getShape() nmissing = len(shape)-len(argshape) if nmissing: argshape = [1]*nmissing+list(argshape) curslices = [] for i,s in enumerate(slices): if argshape[i]==1 and shape[i]>1: # Argument dimension length = 1, but target dimension length > 1 # NumPy will perform broadcasting: intelligently adjust the slice for the argument. if isinstance(s,slice): curslices.append(slice(0,1)) else: curslices.append(0) else: # Argument and target dimension lengths match: use the slice as given. curslices.append(s) # Slice the argument arg = arg.__getitem__(tuple(curslices[nmissing:])) newargs.append(arg) import copy copy = copy.copy(self) copy.args = tuple(newargs) return copy else: # No outsourcing of slicing: apply the slice only after this expression is done. return LazyExpression.__getitem__(self,slices)
def getSlice(self,bounds=None,dataonly=False): ndim = len(self.getDimensions()) if bounds is None: bounds = (Ellipsis,) bounds = common.processEllipsis(bounds,ndim) s = [node[bounds].getValue(dataonly=dataonly) for node in self.root] return s