Skip to content

Conversation

@GuillaumeFavelier
Copy link
Contributor

@GuillaumeFavelier GuillaumeFavelier commented Jan 27, 2020

This PR adds a toggle to save the scene displayed in _TimeViewer as a GIF using PyVista movie feature. The shortcut for the toggle is o.

TL:DR: for implementation specific reason, I would push more for offline save_movie() instead, similar to PySurfer. I would like to have your opinion on this @larsoner

Note/Known issue

From my experience of this feature, the interface stutters using the default GIF-PIL (Pillow) format for imageio append_data(). This is probably because disk access is performed at each call. I had better success with GIL-FI (FreeImage) format: the interface was still responsive during recording and suffers for lag only while saving to disk (end of recording).

For reference:

It's an item of #7162

@GuillaumeFavelier GuillaumeFavelier self-assigned this Jan 27, 2020
@GuillaumeFavelier GuillaumeFavelier changed the title Add toggle to save_movie in _TimeViewer WIP: Add toggle to save_movie in _TimeViewer Jan 27, 2020
@codecov
Copy link

codecov bot commented Jan 27, 2020

Codecov Report

Merging #7257 into master will decrease coverage by 0.01%.
The diff coverage is 85.93%.

@@            Coverage Diff             @@
##           master    #7257      +/-   ##
==========================================
- Coverage   90.13%   90.12%   -0.02%     
==========================================
  Files         454      454              
  Lines       81535    81701     +166     
  Branches    13015    13042      +27     
==========================================
+ Hits        73493    73634     +141     
- Misses       5210     5222      +12     
- Partials     2832     2845      +13

@larsoner
Copy link
Member

TL:DR: for implementation specific reason, I would push more for offline save_movie() instead, similar to PySurfer. I would like to have your opinion on this @larsoner

I think there are two complementary use cases here. One where you want to save a movie the way PySurfer does (save_movie) with clear use cases. The other is more of a "screencast" mode, where you can click and do various things in order to produce a movie (better for data exploration probably). So it would be nice to have both, but we definitely want the former, and the latter is just a "nice to have" since you could in principle actually use a generic screen-casting tool to get this functionality.

I had better success with GIL-FI (FreeImage) format: the interface was still responsive during recording and suffers for lag only while saving to disk (end of recording).

I'd say we could do one or two of:

  1. add to our environment that imageio get installed with FreeImage support
  2. raise an error when doing o if it's not
  3. check for FreeImage but fall back to PIL if not available, probably with a warn about bad performance

I would vote for 1 and 3.

@GuillaumeFavelier
Copy link
Contributor Author

we definitely want the former, and the latter is just a "nice to have"

I'll go for an offline save_movie() function first and go for screencast in a second phase.

I would vote for 1 and 3.

Sounds like a plan.

@GuillaumeFavelier
Copy link
Contributor Author

GuillaumeFavelier commented Mar 5, 2020

The latest changes:

  • Add an offline save_movie() function to _Brain similar to PySurfer
  • Set the default time interpolation to nearest for set_time_point()
  • Update the overview tables of _Brain and set_backend

@GuillaumeFavelier
Copy link
Contributor Author

GuillaumeFavelier commented Mar 5, 2020

Now that save_movie is available in _Brain, should we connect it to the _TimeViewer frontend?

I was thinking of two ways to handle that:

  1. Through a FileDialog to get the output file path
  2. Through a shortcut with a default file path (probably cwd)

But save_movie() has a few parameters so none of my options seems to fit:

def save_movie(self, fname, time_dilation=4., tmin=None, tmax=None,
framerate=24, interpolation='quadratic', codec=None,
bitrate=None, **kwargs):
"""Save a movie (for data with a time axis).
The movie is created through the :mod:`imageio` module. The format is
determined by the extension, and additional options can be specified
through keyword arguments that depend on the format. For available
formats and corresponding parameters see the imageio documentation:
http://imageio.readthedocs.io/en/latest/formats.html#multiple-images
.. Warning::
This method assumes that time is specified in seconds when adding
data. If time is specified in milliseconds this will result in
movies 1000 times longer than expected.
Parameters
----------
fname : str
Path at which to save the movie. The extension determines the
format (e.g., `'*.mov'`, `'*.gif'`, ...; see the :mod:`imageio`
documenttion for available formats).
time_dilation : float
Factor by which to stretch time (default 4). For example, an epoch
from -100 to 600 ms lasts 700 ms. With ``time_dilation=4`` this
would result in a 2.8 s long movie.
tmin : float
First time point to include (default: all data).
tmax : float
Last time point to include (default: all data).
framerate : float
Framerate of the movie (frames per second, default 24).
interpolation : str
Interpolation method (``scipy.interpolate.interp1d`` parameter,
one of 'linear' | 'nearest' | 'zero' | 'slinear' | 'quadratic' |
'cubic', default 'quadratic').
**kwargs :
Specify additional options for :mod:`imageio`.
"""

@agramfort
Copy link
Member

you want to have a save_movie "button" in the 3d window? Not sure what you have in mind

@larsoner
Copy link
Member

larsoner commented Mar 5, 2020

I would make it a menu file dialog File->Save movie (ctrl-shift-s)... below a File->Save image (ctrl-s) ...) dialog

@GuillaumeFavelier
Copy link
Contributor Author

I would make it a menu file dialog

The time for me to design the proof of concept and show the screenshot here but @larsoner explained exactly what I meant with 1)

@larsoner
Copy link
Member

larsoner commented Mar 5, 2020

... and then maybe after you pick a path we have another "options" screen where you can set the other parameters.

But I would say this is a (much) lower priority than some of the other stuff, the high priority would be brain.save_movie as a Python command, and later (lower prio) we can make it nicely accessible via a GUI

@agramfort
Copy link
Member

agramfort commented Mar 5, 2020 via email

@GuillaumeFavelier
Copy link
Contributor Author

The key binding to ctrl-shift-s is not available yet

times = np.arange(n_frames, dtype=float)
times /= framerate * time_dilation
times += tmin
interp_func = interp1d(self._times, np.arange(self._n_times))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to pass interpolation here

except (ImportError, ModuleNotFoundError):
has_imageio = False
warn("The imageio module is not found, "
"save_movie() will return the image sequence instead")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't do this. Let's just raise an error, say that it's required for movie saving, and add to requirements.txt/environment.yml/README.rst

@GuillaumeFavelier GuillaumeFavelier changed the title WIP: Add toggle to save_movie in _TimeViewer MRG: Add toggle to save_movie in _TimeViewer Mar 5, 2020
@agramfort
Copy link
Member

it works already reasonably well. Now 2 things:

  • it prints stuff at each frame and I suspect it's debug stuff
  • the framerate in the movie does not match the framerate of the play button. So by default the movie are way too fast. So it's not really usable as it is.

Copy link
Member

@agramfort agramfort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although I would suggest to add an entry in the latest.inc page and write some sentences
in https://mne.tools/dev/auto_tutorials/source-modeling/plot_visualize_stc.html#sphx-glr-auto-tutorials-source-modeling-plot-visualize-stc-py saying that movies can be produced.

@GuillaumeFavelier GuillaumeFavelier changed the title Add toggle to save_movie in _TimeViewer WIP: Add toggle to save_movie in _TimeViewer Mar 13, 2020
GuillaumeFavelier and others added 2 commits March 13, 2020 17:13
Co-Authored-By: Alexandre Gramfort <alexandre.gramfort@m4x.org>
@GuillaumeFavelier GuillaumeFavelier changed the title WIP: Add toggle to save_movie in _TimeViewer MRG: Add toggle to save_movie in _TimeViewer Mar 13, 2020
@larsoner
Copy link
Member

Pushed a commit to fix https://circleci.com/gh/mne-tools/mne-python/18592 but @GuillaumeFavelier there are merge conflicts

@GuillaumeFavelier
Copy link
Contributor Author

This was expected. I did a moderate refactor on the latest merged pr about time_viewer. I'll take care of it and rename.

@GuillaumeFavelier GuillaumeFavelier changed the title MRG: Add toggle to save_movie in _TimeViewer WIP: Add toggle to save_movie in _TimeViewer Mar 13, 2020
@agramfort
Copy link
Member

agramfort commented Mar 14, 2020 via email

@GuillaumeFavelier GuillaumeFavelier changed the title WIP: Add toggle to save_movie in _TimeViewer MRG: Add toggle to save_movie in _TimeViewer Mar 16, 2020
@larsoner larsoner merged commit 7f6120b into mne-tools:master Mar 16, 2020
@larsoner
Copy link
Member

Thanks @GuillaumeFavelier

if time.shape != (array.shape[-1],):
raise ValueError('time has shape %s, but need shape %s '
'(array.shape[-1])' %
(time.shape, (array.shape[-1],)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GuillaumeFavelier this merge commit that you made undid the nice refactoring that made use of _time_interp_funcs, we had a single path for interpolation in place and this undid it. It's why CircleCI is headed for failure on master:

https://circleci.com/gh/mne-tools/mne-python/18662

Can you look to see if this can be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm on it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad for the regression

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait are you sure though? because I added _interpolate_data afterwards.

I fixed it in: 82b016a

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I opened #7462

GuillaumeFavelier added a commit to GuillaumeFavelier/mne-python that referenced this pull request Mar 17, 2020
agramfort pushed a commit that referenced this pull request Mar 17, 2020
* Revert "MRG: Add toggle to save_movie in _TimeViewer (#7257)"

This reverts commit 7f6120b.

* Revert _interpolate_data signature
@GuillaumeFavelier GuillaumeFavelier deleted the time_viewer_movie branch June 11, 2020 09:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants