Exemplo n.º 1
0
    def slicingInfo2IndexSlice(self, slicingInfo):
        """slicingInfo2Range(slicingInfo) --> slice instance
        note: slicing is inclusive
        """
        unit = self.unit()

        start, end = slicingInfo.start, slicingInfo.end

        # if axis has dimensional unit, convert start and end to pure numbers if necessary
        if isDimensional(unit):
            if isDimensional(start): start = start/unit
            if isDimensional(end): end = end/unit

        # if axis' unit is a number. it is assumed that the start and end are always given with unit
        # so we need to divide them by the unit
        if isNumber(unit) and unit not in [1, 1.0]:
            if isNumber(start): start = start/unit
            if isNumber(end): end = end/unit

        # if start and end are special objects, convert to numbers as well
        bc = self.binCenters()
        if start == front: start = bc[0]
        if end == back: end = bc[-1]

        # at this point, start and end should all be numbers
        if not isNumber(start) or not isNumber(end):
            raise RuntimeError, "At this point, start and end should all be numbers: start=%s(%s), end=%s(%s)" % (start, type(start), end, type(end))
        #slice. +1 is due to the difference of bin boundaries and bin centers
        s = ( self.cellIndexFromValue( start ),
              self.cellIndexFromValue( end ) + 1 )
        return s
Exemplo n.º 2
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