Skip to content

ValueError Randomly Occurs When Plotting Field Lines Traced by FortranTracer Using ax.plot_coord #92

@NyankoSong

Description

@NyankoSong

Describe the bug

Hi!

I'm not sure if this is a bug of the FortranTracer or matplotlib or jupyterlab, since the coord of field lines traced by FortranTracer looks fine, and this error seems to be raised after all code to be run but before the figure to be rendered... But when I changed to PythonTracer, this weird error disappeared.

Here is the log

Error in callback <function _draw_all_if_interactive at 0x749c50b18180> (for post_execute), with arguments args (),kwargs {}:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/pyplot.py:268, in _draw_all_if_interactive()
    266 def _draw_all_if_interactive() -> None:
    267     if matplotlib.is_interactive():
--> 268         draw_all()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/_pylab_helpers.py:131, in Gcf.draw_all(cls, force)
    129 for manager in cls.get_all_fig_managers():
    130     if force or manager.canvas.figure.stale:
--> 131         manager.canvas.draw_idle()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/backend_bases.py:1905, in FigureCanvasBase.draw_idle(self, *args, **kwargs)
   1903 if not self._is_idle_drawing:
   1904     with self._idle_draw_cntx():
-> 1905         self.draw(*args, **kwargs)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/backends/backend_agg.py:387, in FigureCanvasAgg.draw(self)
    384 # Acquire a lock on the shared font cache.
    385 with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
    386       else nullcontext()):
--> 387     self.figure.draw(self.renderer)
    388     # A GUI class may be need to update a window using this draw, so
    389     # don't forget to call the superclass.
    390     super().draw()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/figure.py:3162, in Figure.draw(self, renderer)
   3159             # ValueError can occur when resizing a window.
   3161     self.patch.draw(renderer)
-> 3162     mimage._draw_list_compositing_images(
   3163         renderer, self, artists, self.suppressComposite)
   3165     renderer.close_group('figure')
   3166 finally:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/image.py:132, 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
    135     image_group = []

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:39, in _prevent_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     36     renderer.stop_rasterizing()
     37     renderer._rasterizing = False
---> 39 return draw(artist, renderer, *args, **kwargs)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/astropy/visualization/wcsaxes/core.py:595, in WCSAxes.draw(self, renderer)
    592 # We need to make sure that that frame path is up to date
    593 self.coords.frame._update_patch_path()
--> 595 super().draw(renderer)
    597 self._drawn = True

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/axes/_base.py:3143, in _AxesBase.draw(self, renderer)
   3140 if artists_rasterized:
   3141     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3143 mimage._draw_list_compositing_images(
   3144     renderer, self, artists, self.figure.suppressComposite)
   3146 renderer.close_group('axes')
   3147 self.stale = False

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/image.py:132, 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
    135     image_group = []

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/lines.py:770, in Line2D.draw(self, renderer)
    767 renderer.open_group('line2d', self.get_gid())
    768 if self._lineStyles[self._linestyle] != '_draw_nothing':
    769     tpath, affine = (self._get_transformed_path()
--> 770                      .get_transformed_path_and_affine())
    771     if len(tpath.vertices):
    772         gc = renderer.new_gc()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/transforms.py:2793, in TransformedPath.get_transformed_path_and_affine(self)
   2787 def get_transformed_path_and_affine(self):
   2788     """
   2789     Return a copy of the child path, with the non-affine part of
   2790     the transform already applied, along with the affine part of
   2791     the path necessary to complete the transformation.
   2792     """
-> 2793     self._revalidate()
   2794     return self._transformed_path, self.get_affine()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/transforms.py:2769, in TransformedPath._revalidate(self)
   2763 def _revalidate(self):
   2764     # only recompute if the invalidation includes the non_affine part of
   2765     # the transform
   2766     if (self._invalid == self._INVALID_FULL
   2767             or self._transformed_path is None):
   2768         self._transformed_path = \
-> 2769             self._transform.transform_path_non_affine(self._path)
   2770         self._transformed_points = \
   2771             Path._fast_from_codes_and_verts(
   2772                 self._transform.transform_non_affine(self._path.vertices),
   2773                 None, self._path)
   2774     self._invalid = 0

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/transforms.py:2445, in CompositeGenericTransform.transform_path_non_affine(self, path)
   2443     return path
   2444 elif not self._a.is_affine and self._b.is_affine:
-> 2445     return self._a.transform_path_non_affine(path)
   2446 else:
   2447     return self._b.transform_path_non_affine(
   2448                             self._a.transform_path(path))

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/astropy/visualization/wcsaxes/transforms.py:54, in CurvedTransform.transform_path(self, path)
     40 def transform_path(self, path):
     41     """
     42     Transform a Matplotlib Path.
     43 
   (...)
     52         The resulting path
     53     """
---> 54     return Path(self.transform(path.vertices), path.codes)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/path.py:130, in Path.__init__(self, vertices, codes, _interpolation_steps, closed, readonly)
    101 """
    102 Create a new path with the given vertices and codes.
    103 
   (...)
    127     and codes as read-only arrays.
    128 """
    129 vertices = _to_unmasked_float_array(vertices)
--> 130 _api.check_shape((None, 2), vertices=vertices)
    132 if codes is not None:
    133     codes = np.asarray(codes, self.code_type)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/_api/__init__.py:161, in check_shape(shape, **kwargs)
    158 if len(shape) == 1:
    159     text_shape += ","
--> 161 raise ValueError(
    162     f"{k!r} must be {len(shape)}D with shape ({text_shape}), "
    163     f"but your input has shape {v.shape}"
    164 )

ValueError: 'vertices' must be 2D with shape (N, 2), but your input has shape (2, 0)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/IPython/core/formatters.py:343, in BaseFormatter.__call__(self, obj)
    341     pass
    342 else:
--> 343     return printer(obj)
    344 # Finally look for special method names
    345 method = get_real_method(obj, self.print_method)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/IPython/core/pylabtools.py:152, in print_figure(fig, fmt, bbox_inches, base64, **kwargs)
    149     from matplotlib.backend_bases import FigureCanvasBase
    150     FigureCanvasBase(fig)
--> 152 fig.canvas.print_figure(bytes_io, **kw)
    153 data = bytes_io.getvalue()
    154 if fmt == 'svg':

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/backend_bases.py:2175, in FigureCanvasBase.print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, pad_inches, bbox_extra_artists, backend, **kwargs)
   2172     # we do this instead of `self.figure.draw_without_rendering`
   2173     # so that we can inject the orientation
   2174     with getattr(renderer, "_draw_disabled", nullcontext)():
-> 2175         self.figure.draw(renderer)
   2176 if bbox_inches:
   2177     if bbox_inches == "tight":

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:95, in _finalize_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     93 @wraps(draw)
     94 def draw_wrapper(artist, renderer, *args, **kwargs):
---> 95     result = draw(artist, renderer, *args, **kwargs)
     96     if renderer._rasterizing:
     97         renderer.stop_rasterizing()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/figure.py:3162, in Figure.draw(self, renderer)
   3159             # ValueError can occur when resizing a window.
   3161     self.patch.draw(renderer)
-> 3162     mimage._draw_list_compositing_images(
   3163         renderer, self, artists, self.suppressComposite)
   3165     renderer.close_group('figure')
   3166 finally:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/image.py:132, 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
    135     image_group = []

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:39, in _prevent_rasterization.<locals>.draw_wrapper(artist, renderer, *args, **kwargs)
     36     renderer.stop_rasterizing()
     37     renderer._rasterizing = False
---> 39 return draw(artist, renderer, *args, **kwargs)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/astropy/visualization/wcsaxes/core.py:595, in WCSAxes.draw(self, renderer)
    592 # We need to make sure that that frame path is up to date
    593 self.coords.frame._update_patch_path()
--> 595 super().draw(renderer)
    597 self._drawn = True

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/axes/_base.py:3143, in _AxesBase.draw(self, renderer)
   3140 if artists_rasterized:
   3141     _draw_rasterized(self.figure, artists_rasterized, renderer)
-> 3143 mimage._draw_list_compositing_images(
   3144     renderer, self, artists, self.figure.suppressComposite)
   3146 renderer.close_group('axes')
   3147 self.stale = False

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/image.py:132, 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
    135     image_group = []

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/artist.py:72, in allow_rasterization.<locals>.draw_wrapper(artist, renderer)
     69     if artist.get_agg_filter() is not None:
     70         renderer.start_filter()
---> 72     return draw(artist, renderer)
     73 finally:
     74     if artist.get_agg_filter() is not None:

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/lines.py:770, in Line2D.draw(self, renderer)
    767 renderer.open_group('line2d', self.get_gid())
    768 if self._lineStyles[self._linestyle] != '_draw_nothing':
    769     tpath, affine = (self._get_transformed_path()
--> 770                      .get_transformed_path_and_affine())
    771     if len(tpath.vertices):
    772         gc = renderer.new_gc()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/transforms.py:2793, in TransformedPath.get_transformed_path_and_affine(self)
   2787 def get_transformed_path_and_affine(self):
   2788     """
   2789     Return a copy of the child path, with the non-affine part of
   2790     the transform already applied, along with the affine part of
   2791     the path necessary to complete the transformation.
   2792     """
-> 2793     self._revalidate()
   2794     return self._transformed_path, self.get_affine()

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/transforms.py:2769, in TransformedPath._revalidate(self)
   2763 def _revalidate(self):
   2764     # only recompute if the invalidation includes the non_affine part of
   2765     # the transform
   2766     if (self._invalid == self._INVALID_FULL
   2767             or self._transformed_path is None):
   2768         self._transformed_path = \
-> 2769             self._transform.transform_path_non_affine(self._path)
   2770         self._transformed_points = \
   2771             Path._fast_from_codes_and_verts(
   2772                 self._transform.transform_non_affine(self._path.vertices),
   2773                 None, self._path)
   2774     self._invalid = 0

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/transforms.py:2445, in CompositeGenericTransform.transform_path_non_affine(self, path)
   2443     return path
   2444 elif not self._a.is_affine and self._b.is_affine:
-> 2445     return self._a.transform_path_non_affine(path)
   2446 else:
   2447     return self._b.transform_path_non_affine(
   2448                             self._a.transform_path(path))

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/astropy/visualization/wcsaxes/transforms.py:54, in CurvedTransform.transform_path(self, path)
     40 def transform_path(self, path):
     41     """
     42     Transform a Matplotlib Path.
     43 
   (...)
     52         The resulting path
     53     """
---> 54     return Path(self.transform(path.vertices), path.codes)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/path.py:130, in Path.__init__(self, vertices, codes, _interpolation_steps, closed, readonly)
    101 """
    102 Create a new path with the given vertices and codes.
    103 
   (...)
    127     and codes as read-only arrays.
    128 """
    129 vertices = _to_unmasked_float_array(vertices)
--> 130 _api.check_shape((None, 2), vertices=vertices)
    132 if codes is not None:
    133     codes = np.asarray(codes, self.code_type)

File /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/matplotlib/_api/__init__.py:161, in check_shape(shape, **kwargs)
    158 if len(shape) == 1:
    159     text_shape += ","
--> 161 raise ValueError(
    162     f"{k!r} must be {len(shape)}D with shape ({text_shape}), "
    163     f"but your input has shape {v.shape}"
    164 )

ValueError: 'vertices' must be 2D with shape (N, 2), but your input has shape (2, 0)
<Figure size 2000x2000 with 1 Axes>

To Reproduce

https://docs.sunpy.org/projects/sunkit-magex/en/latest/generated/gallery/using_sunkit_magex_pfss/plot_gong.html

import os

import matplotlib.pyplot as plt
import numpy as np

import astropy.units as u
from astropy.coordinates import SkyCoord

import sunpy.map

import sunkit_magex.pfss
import sunkit_magex.pfss.tracing as tracing
from sunkit_magex.pfss.sample_data import get_gong_map

gong_fname = get_gong_map()
gong_map = sunpy.map.Map(gong_fname)

nrho = 25
rss = 2.5

pfss_in = sunkit_magex.pfss.Input(gong_map, nrho, rss)
pfss_out = sunkit_magex.pfss.pfss(pfss_in)

fig = plt.figure()
ax = plt.subplot(projection=m)
m.plot()

tracer = tracing.FortranTracer()
r = 1.2 * u.R_sun
lat = np.linspace(-np.pi / 2, np.pi / 2, 8, endpoint=False)
lon = np.linspace(0, 2 * np.pi, 8, endpoint=False)
lat, lon = np.meshgrid(lat, lon, indexing='ij')
lat, lon = lat.ravel() * u.rad, lon.ravel() * u.rad

seeds = SkyCoord(lon, lat, r, frame=pfss_out.coordinate_frame)

field_lines = tracer.trace(seeds, pfss_out)

for field_line in field_lines:
    color = {0: 'black', -1: 'tab:blue', 1: 'tab:red'}.get(field_line.polarity)
    coords = field_line.coords
    coords.representation_type = 'cartesian'
    # ax.plot(coords.x / const.R_sun,
    #         coords.y / const.R_sun,
    #         coords.z / const.R_sun,
    #         color=color, linewidth=1)
    ax.plot_coord(coords, c=color, lw=1)

ax.set_title('PFSS solution')

SOMETIMES (with different seeds or pfss_out), this would lead to ValueError. This error can be stable reproduced by using the same seeds and pfss_out.

Screenshots

No response

System Details

==============================
sunpy Installation Information

General
#######
OS: Ubuntu (24.04, Linux 6.8.0-52-generic)
Arch: 64bit, (x86_64)
sunpy: 5.1.4
Installation path: /opt/miniconda3/envs/spcphys/lib/python3.11/site-packages/sunpy-5.1.4.dist-info

Required Dependencies
#####################
astropy: 7.0.0
numpy: 1.26.4
packaging: 24.0
parfive: 2.1.0
pyerfa: 2.0.1.4

Optional Dependencies
#####################
asdf: 3.2.0
asdf-astropy: 0.6.1
beautifulsoup4: 4.12.3
cdflib: 1.3.1
dask: 2024.4.1
drms: 0.6.4
glymur: 0.12.9.post2
h5netcdf: 1.3.0
h5py: 3.11.0
lxml: 5.1.0
matplotlib: 3.9.1
mpl-animators: 1.1.1
pandas: 2.2.3
python-dateutil: 2.9.0
reproject: 0.13.1
scikit-image: 0.24.0
scipy: 1.14.1
sqlalchemy: 2.0.29
tqdm: 4.67.0
zeep: 4.2.1

sunkit-magex=1.0.0

Installation method

conda

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions