cgre-aachen/open_AR_Sandbox

imshow and labels from contour lines raise exception and stop thread

danielsk78 opened this issue · 6 comments

In the main thread, when the cmap_frame module and the contour lines module are on, without the aruco detection working, the thread stops and rises 'NoneType' object has no attribute 'dpi'.
from: matplotlib\text.py", line 852, in get_prop_tup
self.figure.dpi, weakref.ref(renderer),

to recreate the error:
Delete all the plt.pause(...) that you can find in the MainThread Module and other modules. And be sure to have the labels from the contour lines activated. Otherwise, there is no error.

partial fix is to introduce a time of waiting with plt.pause(0.1) instead of detecting the arucos so it have time to synchronise the server with the matplotlib figure.

Traceback (most recent call last):
Traceback (most recent call last): File "C:\Users\Admin\Miniconda3\envs\sandbox\lib\threading.py", line 926, in _bootstrap_inner self.run() File "C:\Users\Admin\Miniconda3\envs\sandbox\lib\threading.py", line 870, in run self._target(*self._args, **self._kwargs) File "../../..\sandbox\main_thread.py", line 161, in thread_loop self.update() File "../../..\sandbox\main_thread.py", line 127, in update self.projector.trigger() File "../../..\sandbox\projector\projector.py", line 199, in trigger self.figure.canvas.draw_idle() File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\backend_bases.py", line 1931, in draw_idle self.draw(*args, **kwargs) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\backends\backend_agg.py", line 393, in draw self.figure.draw(self.renderer) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\artist.py", line 38, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\figure.py", line 1736, in draw renderer, self, artists, self.suppressComposite) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\image.py", line 137, in _draw_list_compositing_images a.draw(renderer) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\artist.py", line 38, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\axes\_base.py", line 2630, in draw mimage._draw_list_compositing_images(renderer, self, artists) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\image.py", line 137, in _draw_list_compositing_images a.draw(renderer) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\artist.py", line 38, in draw_wrapper return draw(artist, renderer, *args, **kwargs) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\text.py", line 685, in draw bbox, info, descent = textobj._get_layout(renderer) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\text.py", line 278, in _get_layout key = self.get_prop_tup(renderer=renderer) File "C:\Users\Admin\AppData\Roaming\Python\Python37\site-packages\matplotlib\text.py", line 852, in get_prop_tup self.figure.dpi, weakref.ref(renderer), AttributeError: 'NoneType' object has no attribute 'dpi'

"A Matplotlib pane renders a matplotlib figure to png and wraps the base64 encoded data in a bokeh Div model". So when updating the frame. Plotting all the text contour labels takes more time or is incomplete, having the problem or the NoneType:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/IPython/core/formatters.py in __call__(self, obj)
    339                 pass
    340             else:
--> 341                 return printer(obj)
    342             # Finally look for special method names
    343             method = get_real_method(obj, self.print_method)

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
    246 
    247     if 'png' in formats:
--> 248         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    249     if 'retina' in formats or 'png2x' in formats:
    250         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
    130         FigureCanvasBase(fig)
    131 
--> 132     fig.canvas.print_figure(bytes_io, **kw)
    133     data = bytes_io.getvalue()
    134     if fmt == 'svg':

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2215                     orientation=orientation,
   2216                     bbox_inches_restore=_bbox_inches_restore,
-> 2217                     **kwargs)
   2218             finally:
   2219                 if bbox_inches and restore_bbox:

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/backend_bases.py in wrapper(*args, **kwargs)
   1637             kwargs.pop(arg)
   1638 
-> 1639         return func(*args, **kwargs)
   1640 
   1641     return wrapper

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py in print_png(self, filename_or_obj, metadata, pil_kwargs, *args)
    507             *metadata*, including the default 'Software' key.
    508         """
--> 509         FigureCanvasAgg.draw(self)
    510         mpl.image.imsave(
    511             filename_or_obj, self.buffer_rgba(), format="png", origin="upper",

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/backends/backend_agg.py in draw(self)
    405              (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    406               else nullcontext()):
--> 407             self.figure.draw(self.renderer)
    408             # A GUI class may be need to update a window using this draw, so
    409             # don't forget to call the superclass.

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     39                 renderer.start_filter()
     40 
---> 41             return draw(artist, renderer, *args, **kwargs)
     42         finally:
     43             if artist.get_agg_filter() is not None:

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/figure.py in draw(self, renderer)
   1862             self.patch.draw(renderer)
   1863             mimage._draw_list_compositing_images(
-> 1864                 renderer, self, artists, self.suppressComposite)
   1865 
   1866             renderer.close_group('figure')

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     39                 renderer.start_filter()
     40 
---> 41             return draw(artist, renderer, *args, **kwargs)
     42         finally:
     43             if artist.get_agg_filter() is not None:

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/cbook/deprecation.py in wrapper(*inner_args, **inner_kwargs)
    409                          else deprecation_addendum,
    410                 **kwargs)
--> 411         return func(*inner_args, **inner_kwargs)
    412 
    413     return wrapper

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
   2746             renderer.stop_rasterizing()
   2747 
-> 2748         mimage._draw_list_compositing_images(renderer, self, artists)
   2749 
   2750         renderer.close_group('axes')

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
    130     if not_composite or not has_images:
    131         for a in artists:
--> 132             a.draw(renderer)
    133     else:
    134         # Composite any adjacent images together

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
     39                 renderer.start_filter()
     40 
---> 41             return draw(artist, renderer, *args, **kwargs)
     42         finally:
     43             if artist.get_agg_filter() is not None:

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/text.py in draw(self, renderer)
    677 
    678         with _wrap_text(self) as textobj:
--> 679             bbox, info, descent = textobj._get_layout(renderer)
    680             trans = textobj.get_transform()
    681 

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/text.py in _get_layout(self, renderer)
    270         of a rotated text when necessary.
    271         """
--> 272         key = self.get_prop_tup(renderer=renderer)
    273         if key in self._cached:
    274             return self._cached[key]

~/anaconda3/envs/sandbox-gempy/lib/python3.7/site-packages/matplotlib/text.py in get_prop_tup(self, renderer)
    844                 hash(self._fontproperties),
    845                 self._rotation, self._rotation_mode,
--> 846                 self.figure.dpi, weakref.ref(renderer),
    847                 self._linespacing
    848                 )

AttributeError: 'NoneType' object has no attribute 'dpi'

Panel is printing the matplotlib figure as a .png file first and then load this figure to panel, and that is what is projected.
So the sandbox is plotting a new figure when panel is still saving the .png file, so the sandbox already changed the figure and panel cannot find the previous anymore.

Solution: before sandbox changes the axes again, let panel find the figure and display the figure.
That is why the plt.pause(..) was sometimes working because it gave Panel time to find the figure.

What takes the most time for plotting are the contour labels, so that is why turning them off solved the problem.

The figure takes too much time to be drawn when too many labels in the contour lines are desired.
Solution was to implement a pause proportional to the number of contour lines to be drawn. This is nearly unperceptive for the user. If any other solutions available please modify, or feel free to open the issue again.

is async/await an option or are these threads entirely seperate?
In the latter case we might get around it by creating a deep copy of the figure to pass to panel so it is independent of the figure that is overwritten