Back to the main page.

Bug 2878 - ft_databrowser: redrawing is several times slower for viewmode = vertical than butterfly

Reported 2015-04-16 02:27:00 +0200
Modified 2015-10-06 00:40:54 +0200
Product: FieldTrip
Component: plotting
Version: unspecified
Hardware: PC
Operating System: Windows
Importance: P5 normal
Assigned to: Roemer van der Meij
Depends on: 2065
Blocks: 2314
See also:

Roemer van der Meij - 2015-04-16 02:27:32 +0200

As title. This shouldn't really be the case, as the amount of data that is plotted is identical. And plotting the data should be the slowest processes, according to my intuition. Presumably calculating displacement of the y-axis data is inefficient. Will look into. Additional info: Clearly noticeable (2-5 times as slow) using: ~100 channels ~1000 data points per channel to be plotted.

Robert Oostenveld - 2015-04-16 08:53:14 +0200

that seems to make sense, since "vertical" goes with a for loop through ft_plot_vector where all channel data still need to be repositioned. E.g. consider the following time = 1:1000; figure tic for i=1:100 cla disp(i) dat = randn(100, 1000); ft_plot_vector(time, dat); drawnow end toc hpos = rand(100,1); vpos = rand(100,1); width = 0.1 * ones(100,1); height = 0.1 * ones(100,1); tic for i=1:100 cla disp(i) dat = randn(100, 1000); for i=1:100 ft_plot_vector(time, dat(i,:), 'hpos', hpos(i), 'vpos', vpos(i), 'width', width(i), 'height', height(i)); end drawnow end I suggest you try this also without axis repositioning, and also with plot instead of ft_plot_vector, to see whether the additional overhead is in the repeated *calls* to the low-level plot function, or whether the overhead is *inside* the low-level plot function.

Roemer van der Meij - 2015-04-16 20:34:16 +0200

The second one is indeed a bit slower. If you place the drawnow after the loop however, they take about the same time actually (which I found was the case in the browser using profiling). Some profiling resulted for the interested reader and my ref: Viewmode = butterfly, ~100 channels, ~1000 samples, 20 flips through trials ft_databrowser>redraw_cb 21 4.234s 1.932s Inside redraw_cb 1922 drawnow 21 1.591s 37.6% 1694 ft_plot_vector(tim, dat, 'box'... 21 1.351s 31.9% 1490 dat = ft_fetch_data(opt.orgdat... 21 0.560s 13.2% 1685 delete(findobj(h,'tag', 'timec... 21 0.200s 4.7% Viewmode = vertical ft_databrowser>keyboard_cb 20 20.510s 0.000s Inside redraw_cb 1733 lh = ft_plot_vector(tim, dat(d... 2163 6.747s 31.0% 1727 if numel(findobj(h,'tag', 'cha... 2163 6.003s 27.5% 1575 opt.laytime = ft_prepare_layou... 21 5.810s 26.7% 1922 drawnow 21 1.270s 5.8% The plotting itself does take more than twice as long though. There's more to it. Looks like there's some more speedups possible. Looking more into it (posting this quickly for my own reference, tbc)

Roemer van der Meij - 2015-04-16 22:32:48 +0200

I've sped it up several fold (in my example), by adding a "changed the channels" flag, and only draw labels and prep the layout when the channels were changed. It's a workaround, but it's decent, and better than the one I implemented before (bug 2065, added as dep). I'll test it a bit more (I'm sure I missed a 'changing channels event' somewhere), and commit it in a few days when I get my new laptop and coding/svn/git environment running. It's still a bit slow however, which is simply caused by calling ft_plot_vector for each channel, relating to the example from Robert above. This can only be solved by calling ft_plot_vector once. This can only be achieved if vpos is applied to the data before calling plot vector (hpos luckily doesn't change, which would be impossible to apply). Whether this is desired however, is an open question.

Robert Oostenveld - 2015-04-17 08:56:07 +0200

right now the interface allows for specifying a single hpos/vpos for all channels. Looking at line 259, it is clear that hpos/vpos are assumed to be scalar, otherwise that would not work. How about extending it such that hpos etc can be a vector? That would apply to % 'hpos' = horizontal position of the center of the local axes % 'vpos' = vertical position of the center of the local axes % 'width' = width of the local axes % 'height' = height of the local axes % 'hlim' = horizontal scaling limits within the local axes % 'vlim' = vertical scaling limits within the local axes It is not 100% trivial in the code, since just as in "plot" it should plot along columns (single input matrix) or along rows (two inputs). But interface-wise I don't think that there would be any ambiguity. So something like >> ft_plot_vector(randn(10,20), 'hpos', rand(1,10), 'vpos', rand(1,20)) although the 10 and 20 might have to be swapped.

Robert Oostenveld - 2015-04-17 08:58:16 +0200

(In reply to Robert Oostenveld from comment #4) note that this must then be changed consistently in all ft_plot functions that use local axes. So also mac011> grep -l vpos *.m ft_plot_box.m ft_plot_lay.m ft_plot_line.m ft_plot_matrix.m ft_plot_text.m ft_plot_topo.m ft_plot_vector.m ft_uilayout.m % this one probably not You should check whether it is actually possible, given the constraints that the other functions impose on this generic functionality.

Roemer van der Meij - 2015-10-06 00:40:23 +0200

I've applied my speed fixes, which I was far too slow in doing ;). I'm closing this one and making another vpos, as it deserves its own (if we implement it in the end).