Home > Enterprise >  'AxesSubplot' object has no attribute 'colorbar'
'AxesSubplot' object has no attribute 'colorbar'

Time:12-20

I'm trying to run a python code to build a ternary vertex diagram A, B and C, in which I want to visualize a scatterplot, using the matplotlib library, but I'm getting the error AttributeError: 'AxesSubplot' object has no attribute 'colorbar '

The error message is

AttributeError                            Traceback (most recent call last)
<ipython-input-52-e3818f5603ff> in <module>
    136 bounds = [1, 2, 3, 4, 5, 10]
    137 norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
--> 138 ter.plot2(ax, fig, cmap, norm, bounds)

<ipython-input-52-e3818f5603ff> in plot2(self, ax, fig, cmap, norm, bounds, scale_factor, weight_label, color_label, label, tet_marks, graduation_step, show_scale, show_legend)
     78         divider = make_axes_locatable(ax)
     79         cax = divider.append_axes('right', size='5%', pad=0.05)
---> 80         cbar = fig.colorbar(dat, cax=cax, format='%.2f', ticks=bounds)
     81         cbar.ax.tick_params(labelsize=12)
     82         if len(self.labels) > 0:

AttributeError: 'AxesSubplot' object has no attribute 'colorbar'
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
import matplotlib.cm as cm
import numpy as np
import matplotlib as mpl
import pandas as pd
import matplotlib as mpl 
from math import sqrt
from matplotlib.ticker import LogFormatter
from mpl_toolkits.axes_grid1 import make_axes_locatable

dataset = pd.read_excel('/content/Sequecia BC74 teste v2.xlsx')

class Ternary:
    font_size = 12
    plot_size = 12

    def __init__(self, label_A: str = "A", label_B: str = "B", label_C: str = "C",
                 min_ternary: float = 0):
        self.label_A = label_A
        self.label_B = label_B
        self.label_C = label_C
        self.min_ternary = min_ternary
        self.weights = []
        self.colors = []
        self.labels = []
        self.X = []
        self.Y = []
        self.Z = []

    def append_data(self, A, B, C, weights=None, colors=None, tick_label: list=[]):
        self.weights = []
        self.colors = []
        self.labels = []
        if len(A) != len(B) or len(B) != len(C):
            print("ERROR in append_data, table length are different")
        else:
            for i in range(len(A)):
                if A[i]   B[i]   C[i] >= self.min_ternary:
                    self.X.append(0.5 * (2 * C[i]   B[i]) / (A[i]   B[i]   C[i]))
                    self.Y.append(sqrt(3) * 0.5 * B[i] / (A[i]   B[i]   C[i]))
                    if weights is not None:
                        self.weights.append(weights[i])
                    else:
                        self.weights.append(1)
                    if colors is not None:
                        self.colors.append(colors[i])
                    else:
                        self.colors.append(1)
                    if len(tick_label) > 0:
                        self.labels.append(tick_label[i])

    def plot2(self, ax, fig, cmap, norm, bounds, scale_factor: int = 1, weight_label: str = None, color_label: str = None,
              label: str = "Ter", tet_marks: bool = False, graduation_step: float = 10,  show_scale: bool = True, 
              show_legend: bool = True):
        self.plot_frame(ax=ax, graduation_step=graduation_step, tetrahedron_marks=tet_marks)
        #
        #Label
        label_points = label   " - "   str(len(self.X))   " inclusions"
        if weight_label is not None:
            label_mean = "Mean "   weight_label   ": "   str(np.round(np.mean(np.asarray(self.weights)), 2))
        else:
            label_mean = "Mean"
        if color_label is not None:
            label_mean  = " / color coding: "   color_label
        #
        #Plot data
        if len(self.labels) > 0:
            if len(np.unique(np.asarray(self.labels))) > 10:
                cmap = cm.tab20
            else:
                cmap = cm.tab10
            unique, index, inverse = np.unique(self.colors, return_index=True, return_inverse=True)
            self.colors = inverse
            bounds = range(len(np.unique(np.asarray(self.labels)[index])))
        dat = ax.scatter(self.X, self.Y, s=[x * scale_factor for x in self.weights], label=label_points, c=self.colors,
                         cmap=cmap, norm=norm, edgecolors="k", linewidth=0.25)
        divider = make_axes_locatable(ax)
        cax = divider.append_axes('right', size='5%', pad=0.05)
        cbar = fig.colorbar(dat, cax=cax, format='%.2f', ticks=bounds)
        cbar.ax.tick_params(labelsize=12)
        if len(self.labels) > 0:
            cbar.ax.set_yticklabels(np.asarray(self.labels)[index])
        #
        #Plot Mean
        ax.scatter(np.mean(np.asarray(self.X)), np.mean(np.asarray(self.Y)),
                   s=scale_factor * np.mean(self.weights), label=label_mean, edgecolors="k", linewidth=0.25,
                   color="black")
        ax.legend(fontsize="large", loc="upper right")
        return dat


    def plot_frame(self, ax, graduation_step: float = 10, tetrahedron_marks: bool = False):
        T1 = [0, 0.5]
        TT1 = [x * sqrt(3) for x in T1]
        T2 = [0.5, 1]
        TT2 = [(-x * (sqrt(3)))   sqrt(3) for x in T2]
        T3 = [0, 1]
        TT3 = [0 * x for x in T3]
        ax.plot(T1, TT1, c='black', lw=0.5)
        ax.plot(T2, TT2, c='black', lw=0.5)
        ax.plot(T3, TT3, c='black', lw=0.5)
        for x in np.linspace(graduation_step, 100 - graduation_step, int((100 / graduation_step) - 1)):
            x = x/100
            T = [x, x   0.5 * (1 - x)]
            TT = [sqrt(3) * (y - x) for y in T]
            ax.plot(T, TT, c='grey', lw=0.2)
            T = [0.5 * x, 1 - 0.5 * x]
            TT = [sqrt(3) * 0.5 * x for y in T]
            ax.plot(T, TT, c='grey', lw=0.2)
            T = [(1 - x) * 0.5, 1 - x]
            TT = [-sqrt(3) * y   sqrt(3) * (1 - x) for y in T]
            ax.plot(T, TT, c='grey', lw=0.2)
        ax.axis([-0.1, 1.1, -0.025, 1])
        ax.text(-0.05, 0, self.label_A, fontsize=self.font_size)
        ax.text(0.5, (0.5 * sqrt(3)) * (1   0.02), self.label_B, fontsize=self.font_size)
        ax.text(1   0.02, 0, self.label_C, fontsize=self.font_size)
        if tetrahedron_marks:
            T1 = [0, 0.5]
            TT1 = [x * 2 * sqrt(1 / 12) for x in T1]
            T2 = [0.5, 1]
            TT2 = [(-x * 2 * sqrt(1 / 12)   2 * sqrt(1 / 12)) for x in T2]
            T3 = [0.5, 0.5]
            TT3 = [sqrt(1 / 12), sqrt(3) / 2]
            ax.plot(T1, TT1, c='black', lw=0.5)
            ax.plot(T2, TT2, c='black', lw=0.5)
            ax.plot(T3, TT3, c='black', lw=0.5)
        ax.set_aspect(aspect="equal")
        ax.axis("off")

ter = Ternary()    
ter.append_data(dataset['CaOMnOMgO'], dataset['SiO2'], dataset['Al2O3'],dataset['Tamanho'],dataset['O2'])
fig = plt.subplot()
ax = plt.subplot()
cmap = mpl.cm.coolwarm
bounds = [1, 2, 3, 4, 5, 10]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
ter.plot2(ax, fig, cmap, norm, bounds)

My goal is to generate this ternary diagram (attached image)enter image description here

CodePudding user response:

This issue is how you create your fig object. Here you are calling the plt.subplot() function twice:

fig = plt.subplot()
ax = plt.subplot()

This will create to Axes instances, one called fig, and one called ax. What you actually want is a Figure instance and an Axes instance. You can use the plt.subplots() function to get both in one go.

fig, ax = plt.subplots()

Then your code should work as expected; .colorbar() is a function of the Figure class, not the Axes class.

  • Related