def __setitem__(self, indexes_or_slice, v): if self.errors() is None: raise NotImplementedError , "__setitem__: errors is None" # if indexes_or_slice is iterable, # we should assume that it is trying to do slicing. # This also means no axis can use iterables as values. if self.dimension() == 1 and '__iter__' not in dir(indexes_or_slice): indexes_or_slice = (indexes_or_slice,) # We also allow use of dictionary. This is a convenient and flexible way # to get or set a slice. if isinstance(indexes_or_slice, dict): s = _slicingInfosFromDictionary(indexes_or_slice, self.axes()) else: s = _makeSlicingInfos( indexes_or_slice, self.dimension() ) pass # end if #at this point, s is a tuple of SlicingInfo instances. slicingInfos = s # check sanity of inputs if not isinstance(s, tuple) or len(s) != self.dimension(): raise NotImplementedError , "Histogram[ %s ]. my dimension: %s" % ( s, self.dimension()) mydatasets = self.datasets() # slicingInfo tuple --> a tuple of index slices indexSlices = self.slicingInfos2IndexSlices( slicingInfos ) #now we want to know if user is requesting for a real slice #or just an element #this is done by trying to get a slice of the dataset self._data aslice = self._data[indexSlices] #1. element, not slice if isNumber(aslice) and isNumberList(v) : if len(v) == 2: self._data[indexSlices] = v[0] self._errors[indexSlices] = v[1] pass elif len(v) == len(mydatasets): for i, ds in enumerate(mydatasets): ds[indexSlices] = v[i] pass else: raise RuntimeError , \ "shape mismatch in histogram[ indexes ] = value tuple. "\ "len(value tuple) = %s, but histogram has %s datasets" \ % (len(v), len(mydatasets)) return v #2. slice #shape = aslice.shape() #get shape # for slice, we would require the right hand side to be a list of datasets if isHistogram( v ): v = v.data(), v.errors() # try to set slice, defer to dataset's __setitem__ # but first we must assert length of arrays match assert len(v) == len(mydatasets), \ "rhs must be a %s-tuple of datasets, "\ "instead of a %s-tuple" % ( len( mydatasets ), len(v) ) for lhs, rhs in zip(mydatasets, v): if rhs is not None : lhs[ indexSlices ] = rhs else: debug.log( 'indefinite behavior: setting to None' ) continue return self[ indexes_or_slice ]
def isNumberList( l ): return reduce(operator.and_, [isNumber(i) for i in l])
def __getitem__(self, s): """Slicing h[ (3.0, 4.0), () ] h[ 3.0, () ] h[ (), () ] h[ (None, 4.0), (999., None ) ] """ if self.errors() is None: raise NotImplementedError , "__getitem__: errors is None" # if s is iterable, we should assume that it is trying to do slicing. # This also means no axis can use iterables as values. if self.dimension() == 1 and '__iter__' not in dir(s): s = (s,) # We also allow use of dictionary. This is a convenient and flexible way # to get or set a slice. if isinstance(s, dict): s = _slicingInfosFromDictionary(s, self.axes()) else: s = _makeSlicingInfos( s, self.dimension() ) #at this point, s is a tuple of SlicingInfo instances. # check sanity of inputs if not isinstance(s, tuple) or len(s) != self.dimension(): raise NotImplementedError , "Histogram[ %s ]. my dimension: %s" % ( s, self.dimension()) # a more meaningful name slicingInfos = s # slicingInfo tuple --> a tuple of index slices indexSlices = self.slicingInfos2IndexSlices( slicingInfos ) #the following line will fail if a dataset is None #should define a special NoneDataset to solve this problem newdatasets = [dataset[indexSlices] for dataset in self.datasets()] #if requested for item instead of slice, return the item now. if isNumber(newdatasets[0]) or isDimensional(newdatasets[0]): return newdatasets #meta data need to be passed to the new histogram newAttrs = self._attributes.copy() #axes of new histogram newAxes = [] for slicingInfo, name in zip(slicingInfos, self.axisNameList()): axis = self.axisFromName( name ) if not isSlicingInfo( slicingInfo ): # if it is not a slicingInfo instance, # it must be a value indexable in this axis. # This is already tested in method "slicingInfo2IndexSlices" value = '%s' % slicingInfo name = axis.name() newAttrs[name] = value else: newAxes.append( axis[ slicingInfo ] ) pass continue #name of new histogram newName = "%s in %s" % ( self.name(), ["%s(%s)"%(axisName, slicingInfo) for axisName, slicingInfo \ in zip(self.axisNameList(), slicingInfos)]) #new histogram new = Histogram( name = newName, unit = self.unit(), data = newdatasets[0], errors = newdatasets[1], axes = newAxes, attributes = newAttrs, slice = True) #addtional datasets. This is not tested yet!!! #probably we should really limit histogram to have only two datasets!!! for i in range(2, len(newdatasets)): ds = newdatasets[i] new.addDataset( ds.name(), ds ) continue return new