Creates a linear list/np.array of timestamps and a list of integers, specifying the sequence 
        and number of levels.

        The levels are first rotated on the first dimension, then the second and so on. If the 
        last dimension is -1, the number of levels is computed from the timestamps.

        returns a 2 dimensional array with len(ranges) + 1 columns
            * the timestamp is in the first column
            * the following columns contain the specific level for this time stamp

        Example:

            utils.create_timing_signals(range(100),[2,5,-1])

        will return a matrix with the first column being the nubmers from 0 to 99, 
        the second alternates between 0 and 1 (eg. whether the number is odd), the third column 
        contains numbers 0 to 4, each bracketing a block of 2*5 = 10 numbers. The last column is
        computed according to the length of the timeseries (in this case 100/(2*5) is 10, ie the 
        column counts blocks of 10 numbers).

def create_timing_signals(timings,ranges=[3,8]):
    """
        Creates a linear list/np.array of timestamps and a list of integers, specifying the sequence 
        and number of levels.

        The levels are first rotated on the first dimension, then the second and so on. If the 
        last dimension is -1, the number of levels is computed from the timestamps.

        returns a 2 dimensional array with len(ranges) + 1 columns
            * the timestamp is in the first column
            * the following columns contain the specific level for this time stamp

        Example:

            utils.create_timing_signals(range(100),[2,5,-1])

        will return a matrix with the first column being the nubmers from 0 to 99, 
        the second alternates between 0 and 1 (eg. whether the number is odd), the third column 
        contains numbers 0 to 4, each bracketing a block of 2*5 = 10 numbers. The last column is
        computed according to the length of the timeseries (in this case 100/(2*5) is 10, ie the 
        column counts blocks of 10 numbers).
    """
    if ranges[-1] == -1:
        ranges[-1] = np.floor(len(timings)/float(np.prod(ranges[:-1]))) + 1
    return np.array([([t]+[cc for cc in c]) for t,c in zip(timings,icartesian([range(int(r)) for r in ranges]))]).transpose()