How to add text into a plot in pyqtgraph like matplotlib.plot.text() - matplotlib

Like the title said, I want to add a text into a graph which I used pyqtgraph to plot, but I didn't find any function like matplotlib.plot.text() which I could set the text and even position in the graph.
self.plt_1.setLabel('left', 'CDF')
self.plt_1.setLabel('bottom', 'Delay', units='ms')
self.plt_1.setXRange(0, 200)
self.plt_1.setYRange(0, 1)
self.plt_1.setWindowTitle('DL CDF Curve')
self.plt_1.setMouseEnabled(x=False, y=False)
self.plt_1.setMenuEnabled(False)
self.plt_1.setText(30, 20, str(self.x_dl_5g_flag))
I tried this, but it doesn't work in my case, does anyone know how to do it in pyqtgraph? thanks

self.text = pg.TextItem(str(self.x_dl_5g_flag))
self.plt_1.addItem(self.text)
self.text.setPos(30,20)

If you want to add text to a graph and define its position on the plot in coordinates relative to the plot canvas (not data coordinates) you can use LabelItem instead of TextItem, something along the following lines (with pyqtgraph imported as pg):
self.text_label = pg.LabelItem("Your text")
self.text_label.setParentItem(self.plt_1.graphicsItem())
self.text_label.anchor(itemPos=(0.4, 0.1), parentPos=(0.4, 0.1))

Related

Imshow differs drastically from applying matplolib.cm to a segmented image

Hi and thanks for reading.
What I am trying to do is to make a web app that would take an image, run it through the model and return a segmented version. I can not use imshow in the webapp though. So I tried adding colormap through matplolib.cm.viridis however it returns a much darker image.
Here are some code and images for refernce:
pred = new_model.predict(np.expand_dims(img, 0))
pred_mask = np.argmax(pred, axis=-1)
pred_mask = pred_mask[0]
This returns me a 2D grayscale image, which when put into matplolib imshow looks like this.(last picture on the right is the output of the model). Code and image below.
axs[0].imshow(m1)
axs[0].set_title('Image')
axs[1].imshow(test_label1)
axs[1].set_title('Ground Truth')
axs[2].imshow(new_pred)
axs[2].set_title('Prediction')
However, when applying colormap to an image using matplolib.cm (something I have to do for app to function) I get this image. Code and image presented below.
Adding colormap. (Viridis, as far as I know is default one from matplolib 3.5)
from matplotlib import cm
pred_mask = cm.viridis(pred_mask / 255)*255
pred_mask = np.asarray(pred_mask, dtype='uint8')
Plotting Image
fig, axs = plt.subplots(1, 3, figsize=(20, 10))
axs[0].imshow(m1)
axs[0].set_title('Image')
axs[1].imshow(test_label1)
axs[1].set_title('Ground Truth')
axs[2].imshow(pred_mask)
axs[2].set_title('Prediction')
But as you can see image is much darker, without even a hint of lighter blue or yellow, i.e. worse. How can I make it closer to imshow output?
PS. Thank you very much for reading and hope that someone has an answer to that. Any suggestions would be much appreciated though.
This is most likely related to the number range of the image or colormap, respectively.
As the prediction mask can be faintly seen my money would be on either multiplying the prediction data with 255 or to set the vmax of imshow to a smaller value. In any case, it would be useful to know the min/max value of pred_mask and additionally show a colorbar for the right plot.
I hope that gets you on the right track.

How to Superimpose on Matplotlib

I want to draw a triangle with two points inside using matplotlib. Here is the code I'm using:
plt.figure()
triangleEdges = np.array([[0,0],[1,0],[0.5,0.5*np.sqrt(3)]])
colors = ['red', 'green', 'blue']
t1 = plt.Polygon(triangleEdges, facecolor="none",
edgecolor='black', linewidth=2)
t1.set_facecolor('xkcd:salmon')
plt.gca().add_patch(t1)
drawSoftmaxPoint('blue',100,np.array([0.2,0.1,0.7]) )
drawSoftmaxPoint('red',100,np.array([0.5,0.1,0.7]))
plt.show()
Picture
According to the code, there should be two points inside the triangle, but it looks like the background is covering them. How can I make them visible?
Thank you!
you could use alpha and z-order in your polygon to make it happen (from the doc of matplotlib). just try to set the alpha value between 0 and 1 to check if you can see your points. and then maybe use z-order on your different elements to make sure the fill of the polygon is deepest (most behind). example of zorder:
https://matplotlib.org/gallery/misc/zorder_demo.html

colorbars for grid of line (not contour) plots in matplotlib

I'm having trouble giving colorbars to a grid of line plots in Matplotlib.
I have a grid of plots, which each shows 64 lines. The lines depict the penalty value vs time when optimizing the same system under 64 different values of a certain hyperparameter h.
Since there are so many lines, instead of using a standard legend, I'd like to use a colorbar, and color the lines by the value of h. In other words, I'd like something that looks like this:
The above was done by adding a new axis to hold the colorbar, by calling figure.add_axes([0.95, 0.2, 0.02, 0.6]), passing in the axis position explicitly as parameters to that method. The colorbar was then created as in the example code here, by instantiating a ColorbarBase(). That's fine for single plots, but I'd like to make a grid of plots like the one above.
To do this, I tried doubling the number of subplots, and using every other subplot axis for the colorbar. Unfortunately, this led to the colorbars having the same size/shape as the plots:
Is there a way to shrink just the colorbar subplots in a grid of subplots like the 1x2 grid above?
Ideally, it'd be great if the colorbar just shared the same axis as the line plot it describes. I saw that the colorbar.colorbar() function has an ax parameter:
ax
parent axes object from which space for a new colorbar axes will be stolen.
That sounds great, except that colorbar.colorbar() requires you to pass in a imshow image, or a ContourSet, but my plot is neither an image nor a contour plot. Can I achieve the same (axis-sharing) effect using ColorbarBase?
It turns out you can have different-shaped subplots, so long as all the plots in a given row have the same height, and all the plots in a given column have the same width.
You can do this using gridspec.GridSpec, as described in this answer.
So I set the columns with line plots to be 20x wider than the columns with color bars. The code looks like:
grid_spec = gridspec.GridSpec(num_rows,
num_columns * 2,
width_ratios=[20, 1] * num_columns)
colormap_type = cm.cool
for (x_vec_list,
y_vec_list,
color_hyperparam_vec,
plot_index) in izip(x_vec_lists,
y_vec_lists,
color_hyperparam_vecs,
range(len(x_vecs))):
line_axis = plt.subplot(grid_spec[grid_index * 2])
colorbar_axis = plt.subplot(grid_spec[grid_index * 2 + 1])
colormap_normalizer = mpl.colors.Normalize(vmin=color_hyperparam_vec.min(),
vmax=color_hyperparam_vec.max())
scalar_to_color_map = mpl.cm.ScalarMappable(norm=colormap_normalizer,
cmap=colormap_type)
colorbar.ColorbarBase(colorbar_axis,
cmap=colormap_type,
norm=colormap_normalizer)
for (line_index,
x_vec,
y_vec) in zip(range(len(x_vec_list)),
x_vec_list,
y_vec_list):
hyperparam = color_hyperparam_vec[line_index]
line_color = scalar_to_color_map.to_rgba(hyperparam)
line_axis.plot(x_vec, y_vec, color=line_color, alpha=0.5)
For num_rows=1 and num_columns=1, this looks like:

Draw points and lines in legend text?

Is there any possibility to get lines and points into a legend text in matplotlib?
I had something in mind like the following
x=np.linspace(0,10,100)
ys=np.sin(x)
yc=np.cos(x)
pl.plot(x,ys,'--',label='sin')
pl.plot(x,yc,':',label='derivative of --')
pl.legend()
pl.show()
except that instead of the -- there should be the same symbol with the corresponding color just as in front of the legend label sin.
After reading around in the matplotlib source code I finally found a solution that works perfect for me and that does not need any position tweaking etc. as it used matplotlibs internal V- and HPackers.
import numpy as np
import pylab as pl
x=np.linspace(0,10,100)
ys=np.sin(x)
yc=np.cos(x)
pl.plot(x,ys,'--',label='sin')
pl.plot(x,yc,':',label='derivative of')
leg=pl.legend()
# let the hacking begin
legrows = leg.get_children()[0].get_children()[1]\
.get_children()[0].get_children()
symbol = legrows[0].get_children()[0]
childs = legrows[1].get_children().append(symbol)
pl.show()
The result looks as follows:
This is a little bit of a hack, but it accomplishes your goal and places all of the pieces (i.e. the legend and the text) on the plot in the appropriate order.
import pylab
pl.plot(x,ys,'--',label='sin', color='green')
pl.plot(x,yc,':',label='derivative of --',color='blue')
line1= pylab.Line2D(range(10), range(10), marker='None', linestyle='--',linewidth=2.0, color="green")
line2= pylab.Line2D(range(10), range(10), marker='None', linestyle=':',linewidth=2.0, color="blue")
leg = pl.legend((line1,line2),('sin','derivative of '),numpoints=1, loc=1)
pylab.text(9.4, 0.73, '- -', color='green')
leg.set_zorder(2)
pl.show()
Instead of relying on the default colors for the lines, I set them such that they can be referenced specifically in the legend. There are extra spaces left in the text for 'the derivative' for the second line in the legend, so we can place text (aka corresponding symbol/color of the sin line) on top of it. Then you specify the symbol/color of the text and place it such that it lines up with the text in the legend. Finally you specify the order, via zorder, to set the text on top.

Matplotlib - transform bbox

I printed some text into a plot. Now I want to make a copy of this text and move it to different coordinates. I guess I'll have to do this with tranform, but did not find a solution yet.
here is the code:
props = dict( facecolor='#DDDDDD', alpha=1,edgecolor='#FFFFFF',boxstyle="Square,pad=0.5")
text2=plt.text(4, 4, "text",va='top', ha='left',bbox=props)
plt.draw()
bb2=text2.get_bbox_patch().get_window_extent().transformed(ax.transData.inverted()).get_points()
To move the text to different coordinates you only need:
text2.set_position((new_x,new_y))
you could also use:
text2.set_x(new_x)
text2.set_y(new_y)