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)
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.