3

I'm trying to manipulate all colorbar instances contained in a figure. There is fig.get_axes() to obtain a list of axes, but I cannot find anything similar for colorbars.

This answer, https://stackoverflow.com/a/19817573/7042795, only applies to special situations, but not the general case.

Consider this MWE:

import matplotlib.pyplot as plt
import numpy as np

data = np.random.random((10,10)) # Generate some random data to plot

fig, axs = plt.subplots(1,2)

im1 = axs[0].imshow(data)    
cbar1 = fig.colorbar(im1)

im2 = axs[1].imshow(2*data)    
cbar2 = fig.colorbar(im2)

fig.show()

How can I get cbar1 and cbar2 from fig?

What I need is a function like:

def get_colorbars(fig):
  cbars = fig.get_colorbars()
  return cbars

cbars = get_colorbars(fig)
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Bastian
  • 901
  • 7
  • 23
  • You already did when you use `cbar1 = fig.colorbar(im)` and `cbar2 = fig.colorbar(im)`. Look at [this](https://stackoverflow.com/a/34059167/4932316) answer perhaps – Sheldore Dec 20 '18 at 14:36
  • @Bazingaa, `fig.colorbar(im)` creates a colorbar, returning the handle, yes, but I need to extract handles for existing colorbars from a figure – Bastian Dec 20 '18 at 15:09
  • I clarified the intention behind my question – Bastian Dec 20 '18 at 15:27
  • 1
    If you create 2 colorbars for the same mappable (image) there is indeed no way to get the first one of them back, in case you haven't stored a handle (`cbar1` here) to it. Of course this leads to the question: Why would you create two colorbars for the same thing? – ImportanceOfBeingErnest Dec 20 '18 at 17:03
  • @ImportanceOfBeingErnest mh, then my MWE is not very suitable. The situations I actually intend to address is when multiple things are plotted using different colorscales and thus colorbars. Let me update my MWE – Bastian Dec 21 '18 at 07:44
  • Related but not dupe: https://stackoverflow.com/q/19816820/2988730 – Mad Physicist Dec 21 '18 at 07:59
  • So in that case, the answer linked to in the very first comment is actually the solution. – ImportanceOfBeingErnest Dec 21 '18 at 09:52

2 Answers2

3

You would have no choice but to check each object present in the figure whether it has a colorbar or not. This could look as follows:

def get_colorbars(fig):
    cbs = []
    for ax in fig.axes:
        cbs.extend(ax.findobj(lambda obj: hasattr(obj, "colorbar") and obj.colorbar))
    return [a.colorbar for a in cbs]

This will give you all the colorbars that are tied to an artist. There may be more colorbars in the figure though, e.g. created directly from a ScalarMappble or multiple colorbars for the same object; those cannot be found.

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
0

Since the only place I'm reasonably sure that colorbar references are retained is as an attribute of the artist they are tied to, the best solution I could think of is to search all artists in a figure. This is best done recursively:

def get_colorbars(fig):
    def check_kids(obj, bars):
        for child in obj.get_children():
            if isinstance(getattr(child, 'colorbar', None), Colorbar):
                bars.append(child.colorbar)
            check_kids(child, bars)
        return bars
     return check_kids(fig, [])

I have not had a chance to test this code, but it should at least point you in the right direction.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264