0

The pandas dataframe rows correspond to successive time samples of a Kalman filter. I want to display the trajectory (truth, measurements and filter estimates) in a stream.

def show_tracker(index,data=run_tracker()):
    i = int(index)
    sleep(0.1)
    p = \
    hv.Scatter(data[0:i], kdims=['x'],      vdims=['y'])(style=dict(color='r')) *\
    hv.Curve  (data[0:i], kdims=['x.true'], vdims=['y.true']) *\
    hv.Scatter(data[0:i], kdims=['x.est'],  vdims=['y.est'])(style=dict(color='darkgreen')) *\
    hv.Curve  (data[0:i], kdims=['x.est'],  vdims=['y.est'])(style=dict(color='lightgreen'))
    return p

%%opts Scatter [width=600,height=280]
ndx=TimeIndex()
hv.DynamicMap(show_tracker, kdims=[], streams=[ndx])

for i in range(N):
    ndx.update(index=i)
  • Issue 1: Axes are automatically set to the bounds of the data. Consequently, trajectory updates occur at the very edge of the plot boundaries. Is there a setting to allow some slop, or do I have to compute appropriate bounds in the show_tracker function?

  • Issue 2: Bokeh backend; I can zoom and pan, but "Reset" causes the data set to be lost. How do I fix that?

  • Issue 3: The default data argument to show_tracker requires the function to be reexecuted to generate a new dataframe. Is there an easy way to address that?

user
  • 1
  • 2
  • adressed Issue 3 by replacing the data=run_tracker() argument to **show_tracker** with def rerun_tracker(N): def _run(i): if i % N == 0: _run.data = run_tracker(N,sensor,tracker) return _run.data _run.data = run_tracker(N) return _run – user Apr 09 '17 at 04:37
  • Added Jupyter notebook at https://github.com/ea42gh/KalmanFilterExample – user Apr 09 '17 at 05:35

1 Answers1

0

Issue 1

This is one of the last outstanding issues for the 1.7 release coming next week, track this issue for updates. However we also just changed how the ranges are updated on a DynamicMap, if you want to update the ranges make sure to set %%opts Scatter {+framewise} or norm=dict(framewise=True) on one of the displayed objects as you're already doing for the style options.

Issue 2

This is an unfortunate shortcoming of the reset tool in bokeh, you can track this issue for updates.

Issue 3:

That depends on what exactly you're doing, has the data already been generated or are you updating it on the fly? If you just have to generate the data once you can just create it outside function, which means it will be in scope:

data = run_tracker()

def show_tracker(index):
    i = int(index)
    sleep(0.1)
    ...
    return p

If you actually want to generate new data dynamically the easiest thing to do is write a little class to keep track of the state. You can even make that class a Stream so you don't have to define it separately. Here's what that might look like:

class KalmanTracker(hv.streams.Stream):

    index = param.Integer(default=1)

    def __init__(self, **params):
        # Initializes empty data and parameters
        self.data = None
        super(KalmanTracker, self).__init__(**params)

    def update_data(self, index):
        # Update self.data here

    def get_view(self, index):
        # Update index exceeds data length and
        # create a holoviews view of the data
        if self.data is None or len(self.data) < index:
            self.update_data(index)
        data = self.data[:index]
        ....
        return hv_obj

    def show(self):
        # Create DynamicMap to display and
        # pass in self as the Stream
        return hv.DynamicMap(self.get_view, kdims=[],
                             streams=[self])

tracker = KalmanTracker()
tracker.show()

# Should update data and plot
tracker.update(index=10)

Once you've done that you can also use the paramnb library to generate widgets from this class. You'd simply do this:

tracker = KalmanTracker()
paramnb.Widgets(tracker, callback=tracker.update)
tracker.show()
philippjfr
  • 3,997
  • 14
  • 15
  • nice! I presume **tracker.update** should be **tracker.view**. I'll update the notebook on github once I get this working fully – user Apr 09 '17 at 22:04
  • ``tracker.update`` is correct, since that updates the Stream. Btw for support questions join us [Gitter](https://gitter.im/ioam/holoviews). – philippjfr Apr 09 '17 at 23:59
  • got this interface up and running. New version at https://github.com/ea42gh/KalmanFilterExample/blob/master/KalmanFilterExampleV2.ipynb – user Apr 10 '17 at 01:34