Histogram with overlapping bins

Hi, some time ago I needed the same thing and hacked the function
histogram (from numpy). Here goes my function, I hope it will result useful

Cheers,
  Juan

## Calculates the histogram allowing for overlapping bins, which are
given by

···

#
# @param a
# @param bins a sequence of pairs (left,right), limits for each bin
#
# @return hist (numpy array)
# bin_centers (numpy array)
def myhistogram(a, bins):
  """
  Compute the histogram of a set of data.

  Parameters
  ----------
  a : array_like
      Input data.
  bins : sequence of pairs
      It defines the bin edges (left,right), allowing for non-uniform
bin widths.

  Returns
  -------
  hist : array
    The values of the histogram. See `normed` and `weights` for a
    description of the possible semantics.
  bin_centers : array of dtype float
    Return the bin centers ``(length(hist))``.

  Notes
  -----
  All but the last (righthand-most) bin is half-open. In other words, if
  `bins` is::

    [1, 2, 3, 4]

  then the first bin is ``[1, 2)`` (including 1, but excluding 2) and the
  second ``[2, 3)``. The last bin, however, is ``[3, 4]``, which *includes*
  4.

  Examples
  --------
  >>> myhistogram([1,2,1], bins=[(0,1),(1,1.5),(1.5,2.5),(2,3)])
  (array([0.5, 1.25, 2, 2.5]), array([0, 0, 1, 2, 3]))
  """
  bins = np.asarray(bins) # bins are 2-dimensional arrays
of shape (n,2)
  if len(bins.shape) != 2 or bins.shape[1] != 2:
    raise AttributeError, 'bins must be a list/array of 2-tuples.'

  a = np.asarray(a)
  a = a.ravel()
  n = np.zeros(len(bins), int)

  block = 65536
  for i in np.arange(0, len(a), block):
    sa = np.sort(a[i:i+block])
    n += np.r_[sa.searchsorted(bins[:-1,1], 'left'),
sa.searchsorted(bins[-1,1], 'right')]\
         - np.r_[sa.searchsorted(bins[:-1,0], 'left'),
sa.searchsorted(bins[-1,0], 'right')]
  return n, (bins[:,0]+bins[:,1])/2.