connecting data points...

Hi everyone: I was wondering whether it is possible to tell

    > matplotlib how/when to connect data points. Consider this
    > simple script:

    > from matplotlib.matlab import * figure(1) t =
    > [0,1,2,3,4,5,105,106,107] s = [1,4,5,3,9,11,-5,-8,3]
    > plot(t, s, antialiased=False) grid(True) show()

    > There are no data points between t=5 and t=105. By default
    > the points (5,11) and (105,-5) are connected, but I would
    > like to tell matplotlib NOT to do so. In my case I would
    > like to pass the plot function a variable telling it what
    > to do. So for example would have:

    > plot(t, s, max_delta=40)

    > This would mean that the points are only to be connected if
    > the difference between the adjacent t values is less than
    > 40. In my case this is relevant because sometimes there
    > are "holes" in my data, and connecting the points makes the
    > plots look very messy.

    > Would anyone find something like this useful? Would it be
    > difficult to implement?

Certainly not difficult, and probably useful enough to put in the
standard distro. Eg, in a stock market trading example, you would
have lots of quotes, minute by minute, punctuated by long intervals
overnight where the market is closed. If you set maxdelta
appropriately, you could draw connected lines only within trading
days.

Here is a sample implementation

from matplotlib.matlab import *
def segplot(x, y, fmt, maxdelta, **kwargs):
    """
    Plot x versus y, breaking the plot at any point where x[i] -
    x[i-1] > maxdelta. kwargs are passed on to plot
    """
    x = asarray(x)
    y = asarray(y)
    d = diff(x)
    lines =
    ind = nonzero(greater(d, maxdelta))
    ind = ind+1
    if not len(ind):
        lines.extend( plot(x,y,fmt,**kwargs) )
    else:
        allind = [0]
        allind.extend(ind)
        allind.append(len(x))
        for i1,i2 in zip(allind[:-1], allind[1:]):
            lines.extend( plot(x[i1:i2], y[i1:i2], fmt, **kwargs) )
    return lines

t = [0,1,2,3,4,5,105,106,107,187, 200, 212, 300, 320]
s = [1,4,5,3,9,11,-5,-8,3,12, 15, 12, -1, 3]
segplot(t, s, 'b-o', 40, antialiased=False)
grid(True)
show()

I'm inclined not to make this part of plot, since plot processes a
variable number of arguments it makes it a little difficult.
Certainly doable, but I'm hesitant to put too much on plot because it
might become unwieldy. But a new function, like segment plot, would
be easy enough to include.

Any suggestions for a name, or additional functionality?

JDH

John Hunter wrote:

[snip]

Here is a sample implementation

from matplotlib.matlab import *
def segplot(x, y, fmt, maxdelta, **kwargs):
   """
   Plot x versus y, breaking the plot at any point where x[i] -
   x[i-1] > maxdelta. kwargs are passed on to plot
   """
   x = asarray(x)
   y = asarray(y)
   d = diff(x)
   lines =
   ind = nonzero(greater(d, maxdelta))
   ind = ind+1
   if not len(ind):
       lines.extend( plot(x,y,fmt,**kwargs) ) else:
       allind = [0]
       allind.extend(ind)
       allind.append(len(x))
       for i1,i2 in zip(allind[:-1], allind[1:]):
           lines.extend( plot(x[i1:i2], y[i1:i2], fmt, **kwargs) )
   return lines

t = [0,1,2,3,4,5,105,106,107,187, 200, 212, 300, 320]
s = [1,4,5,3,9,11,-5,-8,3,12, 15, 12, -1, 3]
segplot(t, s, 'b-o', 40, antialiased=False)
grid(True)
show()

I'm inclined not to make this part of plot, since plot processes a
variable number of arguments it makes it a little difficult.
Certainly doable, but I'm hesitant to put too much on plot because it
might become unwieldy. But a new function, like segment plot, would
be easy enough to include.

Any suggestions for a name, or additional functionality?

Thanks for the quick solution. I think the name is just fine.

Best,

···

--
Peter Groszkowski Gemini Observatory
Tel: +1 808 974-2509 670 N. A'ohoku Place
Fax: +1 808 935-9235 Hilo, Hawai'i 96720, USA