Example #1
0
    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 ]
Example #2
0
def isNumberList( l ):
    return reduce(operator.and_, [isNumber(i) for i in l])
Example #3
0
    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