Repository: dynamiqs/dynamiqs

Issue:
Fix imageio "fps" deprecation warning.
In older versions, the `fps` keyword is deprecated, which raises a bug when running `dq.plot_wigner_gif`.

Closes https://linear.app/dynamiqs/issue/DYN-175/fix-fps-warning-when-running-tests.


Discussion:
<p><a href="https://linear.app/dynamiqs/issue/DYN-175/fix-fps-warning-when-running-tests">DYN-175 Fix "fps" warning when running tests</a></p>
This is not the same bug. If you go to older `imageio` versions it raises a `TypeError`, not a warning.

```
(base) ➜  dynamiqs git:(main) pytest dynamiqs/plots/plots_wigner.py

Test session starts (platform: darwin, Python 3.11.4, pytest 7.4.2, pytest-sugar 0.9.7)
rootdir: /Users/rgautier/Code/dynamiqs
configfile: pytest.ini
plugins: jaxtyping-0.2.25, typeguard-2.13.3, xdist-3.3.1, sugar-0.9.7
collected 47 items                                                                                                   

 dynamiqs/plots/plots_wigner.py ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓                                 83% ████████▍ 

――――――――――――――――――――――――――――――――――――――――― plots_wigner.py line=276 column=1 ――――――――――――――――――――――――――――――――――――――――――

Example at /Users/rgautier/Code/dynamiqs/dynamiqs/plots/plots_wigner.py, line 276, column 1 did not evaluate as expected:
Exception raised:
    Traceback (most recent call last):
      File "/Users/rgautier/miniconda3/lib/python3.11/doctest.py", line 1351, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest /Users/rgautier/Code/dynamiqs/dynamiqs/plots/plots_wigner.py[0]>", line 1, in <module>
        dq.plot_wigner_gif(
      File "/Users/rgautier/Code/dynamiqs/dynamiqs/plots/plots_wigner.py", line 343, in plot_wigner_gif
        iio.v3.imwrite(filename, frames, format='GIF', fps=fps, loop=0)
      File "/Users/rgautier/miniconda3/lib/python3.11/site-packages/imageio/v3.py", line 147, in imwrite
        encoded = img_file.write(image, **kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/rgautier/miniconda3/lib/python3.11/site-packages/imageio/plugins/pillow.py", line 383, in write
        raise TypeError(
    TypeError: The keyword `fps` is no longer supported. Use `duration`(in ms) instead, e.g. `fps=50` == `duration=20` (1000 * 1/50).

dynamiqs/plots/plots_wigner.py:276: SybilFailure
------------------------------------------------ Captured stderr call ------------------------------------------------
100%|██████████| 125/125 [00:27<00:00,  4.57it/s]

 dynamiqs/plots/plots_wigner.py ⨯✓✓✓✓✓✓                                                                 98% █████████▊

――――――――――――――――――――――――――――――――――――――――― plots_wigner.py line=294 column=1 ――――――――――――――――――――――――――――――――――――――――――

Example at /Users/rgautier/Code/dynamiqs/dynamiqs/plots/plots_wigner.py, line 294, column 1 did not evaluate as expected:
Exception raised:
    Traceback (most recent call last):
      File "/Users/rgautier/miniconda3/lib/python3.11/doctest.py", line 1351, in __run
        exec(compile(example.source, filename, "single",
      File "<doctest /Users/rgautier/Code/dynamiqs/dynamiqs/plots/plots_wigner.py[0]>", line 1, in <module>
        dq.plot_wigner_gif(
      File "/Users/rgautier/Code/dynamiqs/dynamiqs/plots/plots_wigner.py", line 343, in plot_wigner_gif
        iio.v3.imwrite(filename, frames, format='GIF', fps=fps, loop=0)
      File "/Users/rgautier/miniconda3/lib/python3.11/site-packages/imageio/v3.py", line 147, in imwrite
        encoded = img_file.write(image, **kwargs)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/rgautier/miniconda3/lib/python3.11/site-packages/imageio/plugins/pillow.py", line 383, in write
        raise TypeError(
    TypeError: The keyword `fps` is no longer supported. Use `duration`(in ms) instead, e.g. `fps=50` == `duration=20` (1000 * 1/50).

dynamiqs/plots/plots_wigner.py:294: SybilFailure
------------------------------------------------ Captured stderr call ------------------------------------------------
100%|██████████| 250/250 [00:21<00:00, 11.48it/s]

 dynamiqs/plots/plots_wigner.py ⨯                                                                      100% ██████████
================================================== warnings summary ==================================================
../../miniconda3/lib/python3.11/site-packages/cmasher/utils.py:859: 110 warnings
  /Users/rgautier/miniconda3/lib/python3.11/site-packages/cmasher/utils.py:859: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
    cmap = mplcm.get_cmap(cmap)

../../miniconda3/lib/python3.11/site-packages/cmasher/utils.py:1194: 57 warnings
  /Users/rgautier/miniconda3/lib/python3.11/site-packages/cmasher/utils.py:1194: MatplotlibDeprecationWarning: The register_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps.register(name)`` instead.
    mplcm.register_cmap(cmap=cmap_mpl)

../../miniconda3/lib/python3.11/site-packages/cmasher/utils.py:1201: 57 warnings
  /Users/rgautier/miniconda3/lib/python3.11/site-packages/cmasher/utils.py:1201: MatplotlibDeprecationWarning: The register_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps.register(name)`` instead.
    mplcm.register_cmap(cmap=cmap_mpl_r)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============================================== short test summary info ===============================================
FAILED dynamiqs/plots/plots_wigner.py::line:276,column:1
FAILED dynamiqs/plots/plots_wigner.py::line:294,column:1

Results (66.57s (0:01:06)):
      45 passed
       2 failed
         - dynamiqs/plots/plots_wigner.py:277 plots_wigner.py line=276 column=1
         - dynamiqs/plots/plots_wigner.py:295 plots_wigner.py line=294 column=1
(base) ➜  dynamiqs git:(main) pip list | grep imageio              
imageio                       2.31.0
(base) ➜  dynamiqs git:(main) 
```
Actually it was somewhat the same bug. [This](https://github.com/dynamiqs/dynamiqs/pull/520/commits/14008d4585c278f22d5dee9c7c454caa7a289c50) fixes it, and doesn't require a new version of imageio anymore.

Resolving patch:
diff --git a/dynamiqs/plots/plots_wigner.py b/dynamiqs/plots/plots_wigner.py
--- a/dynamiqs/plots/plots_wigner.py
+++ b/dynamiqs/plots/plots_wigner.py
@@ -340,8 +340,7 @@ def plot_wigner_gif(
             frames.append(frame)
 
         # loop=0: loop the GIF forever
-        duration = gif_duration * 1e3  # in ms
-        iio.v3.imwrite(filename, frames, format='GIF', duration=duration, loop=0)
+        iio.v3.imwrite(filename, frames, format='GIF', duration=gif_duration, loop=0)
         if display:
             ipy.display(ipy.Image(filename))
     finally:


Test patch: