Coder Social home page Coder Social logo

Comments (12)

mscheltienne avatar mscheltienne commented on July 19, 2024 1

the bottleneck should be the number shown not the number present overall

Exactly.

I'm short on time at the moment, but yes I will profile both backends, probably next week, with priority given to the Qt backend. Except if someone wants to take a stab at it in the meantime ;)

from mne-qt-browser.

larsoner avatar larsoner commented on July 19, 2024 1

I think it depends on how much faster (2) was. If we're talking (1) as being < 100 us faster than (2) for common use cases, it doesn't matter and we should use (2) all the time.

But a less invasive change is probably to continue with (2) but setVisible(False) all annotations. First we should make sure this alleviates the bottleneck (it should, but we should check). Then we use NumPy vectorized math to figure out which annotations are in a specific window/view (fast) and setVisible(False) the set of annotations that were shown in the previous view, and .setVisible(True) the annotations visible in the new view. I don't think this will add much complexity -- I'll give it a try hopefully this week.

from mne-qt-browser.

mscheltienne avatar mscheltienne commented on July 19, 2024 1

I took a very quick look through the codebase today, and one potential bottleneck is the (numerous) for loops on the entire set of AnnotRegion in self.mne.regions. e.g. this one which seems to toggle them visible/not visible:

def _update_regions_visible(self):
for region in self.mne.regions:
region.update_visible(
self.mne.visible_annotations[region.description])
self.mne.overview_bar.update_annotations()

Instead, looping on the regions in the current view would be faster, but we need to keep track of the onset/offset of each region to be able to use some numpy math to select the annotations in the current view.

from mne-qt-browser.

cbrnr avatar cbrnr commented on July 19, 2024

What is the performance of the Matplotlib-based browser in these cases?

from mne-qt-browser.

mscheltienne avatar mscheltienne commented on July 19, 2024

It does suffer heavily as well. 1-2 seconds between horizontal scroll.

from mne-qt-browser.

larsoner avatar larsoner commented on July 19, 2024

Agreed we should optimize this, the bottleneck should be the number shown not the number present overall. Can you line profile to figure out the issue or want some help? If the latter, if you could recreate this issue with sample (e.g., by adding 1000 0.1 sec annotations or whatever) I can look

from mne-qt-browser.

larsoner avatar larsoner commented on July 19, 2024

... if you've never line profiled and want to try, this is what I suggested in another thread:

mne-tools/mne-bids-pipeline#609 (comment)

it's fun :)

from mne-qt-browser.

cbrnr avatar cbrnr commented on July 19, 2024

I know this is the wrong repository, but while someone is already profiling, could we also take a look at the Matplotlib backend?

from mne-qt-browser.

marsipu avatar marsipu commented on July 19, 2024

In early development, I benchmarked multiple ways of updating the shown annotations in Qt for best scroll performance:

  1. Only add AnnotRegion (which is a child of pyqtgraph's LinearRegionItem, which handles drawing with QPainter.drawRect) to the PlotItem (which manages adding QGraphicsItems to the QGraphicsScene) when in shown time range.
  2. Always add all AnnotRegions for all annotations from the file to PlotItem.

1. had the advantage of being more scalable, but 2. was faster for common amounts of annotations so we discussed the most common usecase and went for 2. as the current solution. With large amounts of AnnotRegions added to the PlotItem, even the Qt probably struggles under the hood with that many items to be drawn or not drawn in the current viewing window.

As part of a solution we could reimplement solution 1. above a yet to be determined limit of no. annotations.

But this would still not speed up the second usecase you describe, when you want to improve speed for drawing a lot of annotations on the screen. Maybe creating our own implementation of a Rectangle-Class with calling directly QPainter.drawRect might reduce a bit of overhead from pyqtgraph. But I doubt it would speed up drawing much, since the guys from pyqtgraph usually already did a good job in optimizing performance. I think the bottleneck is the qt-backend there. Considering an alternative backend like vispy might be an option for the future. But that would require a new backend adaption, since the code here relies heavily on pyqtgraph and the Qt-API.

from mne-qt-browser.

cbrnr avatar cbrnr commented on July 19, 2024

I just found py-spy, a very low-overhead line profiler with nice outputs (flame graphs etc.). It might be worth a try.

from mne-qt-browser.

larsoner avatar larsoner commented on July 19, 2024

Okay on macOS with:

$ root# HOME=/Users/larsoner MNE_DATASETS_SAMPLE_PATH="/Users/larsoner/mne_data" py-spy top -s -r 1000 -- python -u /Users/larsoner/Desktop/rep.py 10000
Collecting samples from 'python -u /Users/larsoner/Desktop/rep.py 10000' and subprocesses
Total Samples 41950
GIL: 72.90%, Active: 100.00%, Threads: 1, Processes 1

  %Own   %Total  OwnTime  TotalTime  Function (filename)                                                                                                        
  0.00%   0.00%   0.000s    40.99s   <module> (rep.py)
  0.00%   0.00%   0.000s    37.03s   plot_raw (<decorator-gen-199>)
  0.00%   0.00%   0.000s    37.03s   plot_raw (mne/viz/raw.py)
  0.00%   0.00%   0.000s    37.03s   plot (mne/io/base.py)
  0.00%   0.00%   0.000s    37.02s   _get_browser (mne/viz/_figure.py)
  0.00%   0.00%   0.000s    33.31s   _init_browser (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.001s    33.12s   func (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.273s    33.12s   __init__ (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.026s    25.34s   _init_annot_mode (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.305s    20.03s   _add_region (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.009s    10.35s   __iter__ (mne/annotations.py)
  0.00%   0.00%   0.086s    10.34s   __getitem__ (mne/annotations.py)
  0.00%   0.00%    2.81s    10.23s   _any_ch_names (mne/annotations.py)
  0.00%   0.00%    3.33s     8.91s   addItem (pyqtgraph/graphicsItems/PlotItem/PlotItem.py)
  0.00%   0.00%    7.42s     7.42s   <genexpr> (mne/annotations.py)
  0.00%   0.00%   0.252s     7.23s   update_annotations (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.316s     6.84s   _get_color (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.113s     5.94s   update_color (mne_qt_browser/_pg_figure.py)
  0.00%   0.00%   0.073s     5.58s   addItem (pyqtgraph/graphicsItems/ViewBox/ViewBox.py)
  0.00%   0.00%    1.18s     5.56s   itemChange (pyqtgraph/graphicsItems/GraphicsObject.py)
...

We have some good candidates for speedups. I'll see what I can do...

from mne-qt-browser.

larsoner avatar larsoner commented on July 19, 2024

... and based on the addItem being a bottleneck, I think adding all then hiding the not-shown won't fix the problem. I think we need to dynamically add and remove. It looks like this is already done in the AnnotationBar actually, so hopefully we can re-use some code somehow.

from mne-qt-browser.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.