As one way. First, take the boolean array that you have:
In [11]: a Out[11]: array([0, 0, 0, 2, 2, 0, 2, 2, 2, 0]) In [12]: a1 = a > 1
Move it to the left (to get the following state for each index) using roll :
In [13]: a1_rshifted = np.roll(a1, 1) In [14]: starts = a1 & ~a1_rshifted
Where it is non-zero - this is the beginning of each True batch (or, accordingly, the final batch):
In [16]: np.nonzero(starts)[0], np.nonzero(ends)[0] Out[16]: (array([3, 6]), array([5, 9]))
And squeezing them together:
In [17]: zip(np.nonzero(starts)[0], np.nonzero(ends)[0]) Out[17]: [(3, 5), (6, 9)]
source share