# Tai Sakuma <tai.sakuma@cern.ch>
import itertools

##__________________________________________________________________||
class GenericKeyComposerB(object):
    """This class is a faster version of GenericKeyComposer.

    This class can be used with BEvents.

    This class supports inclusive indices '*'

    (this docstring is under development.)

    """
    def __init__(self, branchNames, binnings, indices = None):
        self.branchNames = branchNames
        self.binnings = binnings
        self.indices = indices if indices is not None else [None]*len(self.branchNames)

    def begin(self, event):
        self._zip = self._zipArrays(event)

    def __call__(self, event):
        if self._zip is None: return ()
        bins_list = [ ]
        for branche, binning, index in self._zip:
            bins = self._bins(branche, binning, index)
            if not bins: return ()
            bins_list.append(bins)
        return tuple(itertools.product(*bins_list))

    def _bins(self, branche, binning, index):
        if index is None:
            vars = [branche[0]]
        elif index == '*':
            vars = [branche[i] for i in  range(len(branche))]
        else:
            if len(branche) <= index:
                vars = [ ]
            else:
                vars = [branche[index]]
        bins = [binning(var) for var in vars]
        bins = [b for b in bins if b is not None]
        return bins

    def _zipArrays(self, event):
        self.branches = [ ]
        for varname in self.branchNames:
            try:
                branch = getattr(event, varname)
            except AttributeError, e:
                import logging
                logging.warning(e)
                return None
            self.branches.append(branch)
        return zip(self.branches, self.binnings, self.indices)

##__________________________________________________________________||

@@ -803,27 +803,27 @@
             
-bin
+val
 s = self._bi
@@ -820,19 +820,19 @@
 = self._
-bin
+val
 s(branch
@@ -826,32 +826,69 @@
 ._vals(branche, 
+index)%0A            bins = self._bins(
 binning, index)%0A
@@ -880,21 +880,20 @@
 inning, 
-index
+vals
 )%0A      
@@ -1018,19 +1018,19 @@
    def _
-bin
+val
 s(self, 
@@ -1033,33 +1033,24 @@
 lf, branche,
- binning,
  index):%0A   
@@ -1078,33 +1078,33 @@
 :%0A            va
-r
+l
 s = %5Bbranche%5B0%5D%5D
@@ -1137,33 +1137,33 @@
 :%0A            va
-r
+l
 s = %5Bbranche%5Bi%5D 
@@ -1171,17 +1171,16 @@
 or i in 
- 
 range(le
@@ -1258,25 +1258,25 @@
           va
-r
+l
 s = %5B %5D%0A    
@@ -1307,17 +1307,17 @@
       va
-r
+l
 s = %5Bbra
@@ -1329,16 +1329,73 @@
 index%5D%5D%0A
+        return vals%0A%0A    def _bins(self, binning, vals):%0A
         
@@ -1416,17 +1416,17 @@
 g(va
-r
+l
 ) for va
 r in
@@ -1425,16 +1425,16 @@
 r va
-r
+l
  in va
-r
+l
 s%5D%0A 

split _bins() into _vals() and _bins() in GenericKeyComposerB