Code does not work on new version of Matplotlib

Hello everyone,

I would need a little help on this code that works with matplotlib 3.3.2 but not with matplotlib 3.9.2.

X1 and Y1 are numpy.ndarray

contour=True

plt.figure(figname, figsize=(6,6), dpi=100)
ax = plt.gca()
ax.scatter(X1[::n1], Y1[::n1], marker='.', alpha=0.1, label='XY')
if contour:
        sns.kdeplot(x=X1[::30], y=Y1[::30], color='k', levels=levels, alpha=0.3, ax=ax, linestyles="--")
        contourdata=[]
        for i,c in enumerate(ax.collections):  
            if isinstance(c, matplotlib.collections.LineCollection):
                if len(c.get_segments())>0:
                     v = c.get_segments()[0]
                     cv=centeroidnp(v)
                     ax.plot(list(zip(*v))[0], list(zip(*v))[1], color='k', alpha=0.3, label="Outer Contour", linewidth=2.0)
                     ax.scatter(cv[0], cv[1], color='k', alpha=0.3, label="Contour center")
                     contourdata.append((i, len(v), cv))
                     break

I have two problems:

  • isinstance(c, matplotlib.collections.LineCollection) always returns False
  • c.get_segments returns an error: ‘QuadContourSet’ object has no attribute ‘get_segments’

What should I do to make it work with the 3.9.2 version of Matplotlib?

Thank you very much for your help

Hi @Leaabc, since Matplotlib v3.8, the ContourSet object returned by the contour function is itself a collection.

It looks like the allsegs attribute of the ContourSet might give you what you need.

Hi @rcomer ,

Could you please explain to me what I should change to update my code to the new Matplotlib version?

In this code, the “isinstance(c, matplotlib.collections.LineCollection)” always returns False:

ax = plt.gca()
ax.scatter(X1[::n1], Y1[::n1], marker='.', alpha=0.1, label='XY')

for i,c in enumerate(ax.collections):  
            if isinstance(c, matplotlib.collections.LineCollection):

I tried some changes which do not work, I do not understand what I should write.

Thank you for your help,
Lea

Sorry if my previous reply was not helpful. Here is a simple example that prints the same output with Matplotlib v3.4 and v3.9 (I do not have v3.3 installed). Before v3.5 contour plots were drawn with a LineCollection so we go through the first branch of the if-loop. Since v3.8 the ContourSet is a collection so we go through the second branch of the if-loop. Hopefully comparing the two branches will help you see how to adapt your code.

import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib.contour import ContourSet

fig, ax = plt.subplots()

ax.contour([[0, 1], [2, 3]], levels=[1, 2])

for coll in ax.collections:
    if isinstance(coll, LineCollection):
        segments = coll.get_segments()
        if len(segments) > 0:
            print(segments[0])

    elif isinstance(coll, ContourSet):
        for levelseg in coll.allsegs:
            if len(levelseg) > 0:
                print(levelseg[0])