i need to color annotate as in the image below (from a panel of two plots) in a single plot.
so, i would want to turn this image below
to this, in terms of the color annotation of each point on the plot, also adding a legend just as the image below
my full code is:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches
from matplotlib.pyplot import figure
figure(figsize=(10, 8), dpi=120)
from scipy.stats import t
plt.close('all')
data = np.array([
[22.8, 22.8],
[19.6, 0.3],
[0.3, 3.1],
[8.9, -1.7],
[13.7, 4.8],
[14.7, -0.7],
[1.9, -2.6],
[-1.8, -0.03],
[-3, -5.7],
[-5.9, -1.5],
[-13.4, -3.9],
[-5.7, -21.5],
[-6.8, -7.7],
])
custom_annotations = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
plt.scatter(data[:,0], data[:,1], marker='o', c=data[:,1], edgecolors='black', linewidths=1, alpha=0.75)
#plt.colorbar(orientation='horizontal')
plt.xlabel(r'$\Delta V_{0.5}$ Apo wild-type mHCN2 (mV)')
plt.ylabel(r'$\Delta \psi$ cAMP-bound wild-type mHCN2 (mV)')
plt.axvline(0, c=(.5, .5, .5), ls= '--')
plt.axhline(0, c=(.5, .5, .5), ls= '--')
classes = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
class_colours = ["r", "r", "r", "r", "r", "r", "g", "g", "b", "b", "b", "b", "b"]
plt.annotate(txt, (data[i,0], data[i,1]))
plt.legend(recs,classes,loc=(1.04,0))
plt.show()
something in the for loop is missing or written in an incorrect way, the wished plot should be the same as the image in the post, with respect to points color annotation and the legend, which should be placed outside the plot.
CodePudding user response:
First, to produce separate annotations, your problem is that there was no loop. You need to put for i, txt in enumerate(classes):
before the plt.annotate
To produce exactly what you want, however, you need to execute the scatter command for each point, and associate a label to each point as follows:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches
from matplotlib.pyplot import figure
figure(figsize=(10, 8), dpi=120)
from scipy.stats import t
plt.close('all')
data = np.array([
[22.8, 22.8],
[19.6, 0.3],
[0.3, 3.1],
[8.9, -1.7],
[13.7, 4.8],
[14.7, -0.7],
[1.9, -2.6],
[-1.8, -0.03],
[-3, -5.7],
[-5.9, -1.5],
[-13.4, -3.9],
[-5.7, -21.5],
[-6.8, -7.7],
])
custom_annotations = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
class_colours = ["r", "r", "r", "r", "r", "r", "g", "g", "b", "b", "b", "b", "b"]
for i, point in enumerate(data):
plt.scatter(point[0], point[1], marker='o', label=custom_annotations[i], c=class_colours[i], edgecolors='black', linewidths=1, alpha=0.75)
plt.annotate(custom_annotations[i], (data[i,0], data[i,1]))
plt.xlabel(r'$\Delta V_{0.5}$ Apo wild-type mHCN2 (mV)')
plt.ylabel(r'$\Delta \psi$ cAMP-bound wild-type mHCN2 (mV)')
plt.axvline(0, c=(.5, .5, .5), ls= '--')
plt.axhline(0, c=(.5, .5, .5), ls= '--')
plt.legend(ncol=3)
plt.show()
You'll need to make some minor font adjustment so everything fits, perhaps splitting the long legend in two or three columns.
However, for the legend, what you show in the picture seems redundant. It seems like you want to indicate three different groups of data. I recommend to separate your data into the three different types (classes in your code) and execute scatter three separate times and put in the legend the class descriptions. Here is how I would do it:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches
from matplotlib.pyplot import figure
plt.close('all')
data = np.array([
[22.8, 22.8],
[19.6, 0.3],
[0.3, 3.1],
[8.9, -1.7],
[13.7, 4.8],
[14.7, -0.7],
[1.9, -2.6],
[-1.8, -0.03],
[-3, -5.7],
[-5.9, -1.5],
[-13.4, -3.9],
[-5.7, -21.5],
[-6.8, -7.7],
])
custom_annotations = ["K464E", "K472E", "R470E", "K464A", "M155E", "K472A", "M155A", "Q539A", "M155R", "D244A", "E247A", "E247R", "D244K"]
class_colours = ["r", "r", "r", "r", "r", "r", "g", "g", "b", "b", "b", "b", "b"]
class_desc = ['description 1', 'description 2', 'description 3']
dataclass = np.array([0,0,0,0,0,0,1,1,2,2,2,2,2,])
colorclass = ['r','g','b']
for datac in range(3):
plt.scatter(data[dataclass==datac][:,0],data[dataclass==datac][:,1], c=colorclass[datac], label=class_desc[datac])
for i, point in enumerate(data):
# plt.scatter(point[0], point[1], marker='o', label=custom_annotations[i], c=class_colours[i], edgecolors='black', linewidths=1, alpha=0.75)
plt.annotate(custom_annotations[i], (data[i,0], data[i,1]))
plt.xlabel(r'$\Delta V_{0.5}$ Apo wild-type mHCN2 (mV)')
plt.ylabel(r'$\Delta \psi$ cAMP-bound wild-type mHCN2 (mV)')
plt.axvline(0, c=(.5, .5, .5), ls= '--')
plt.axhline(0, c=(.5, .5, .5), ls= '--')
plt.legend(fontsize=12)
plt.show()
producing this: