Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linestyle in plot and annotate are not equal in matplotlib

I am using PyPlot in Julia which basically relies on matplotlib. However, I suspect the issue is the same in Python: When I plot a line and an annotate arrow (without head) using the same linestyle attribute, I expected the two objects to have the same line style. But this is obviously not the case:

using PyPlot
plot([0,1],[-0.05,-0.05],linestyle="--",linewidth=1)
annotate("",xy=(1,0.05),xytext=(0,0.05),xycoords="data",
  arrowprops=Dict("arrowstyle"=>"-","linestyle"=>"--","linewidth"=>1))
ylim(-0.5,0.5)

Result:

enter image description here

  • The dashed black line of the annotate object appears somehow rounded
  • The dashed blue line of the plot curve appears with sharp edges

Weired enough that the two lines seem not to have the same horizontal begin and end in the graph, even though the specified horizontal coordinates are the same. This is not that much of an issue to me, but may be related with my line style issue as well.

Does anyone have an idea how to create exact equal line patterns by plot and annotate?

I need the two lines to have the exact same pattern for a couple graphs in publications.

like image 943
christiankral Avatar asked Sep 20 '25 03:09

christiankral


1 Answers

There are two issues. (Note that I'm using python syntax here, as I have little experience with Julia)

Make the lines equally long.

By default annotate uses lines which are shortenend on both ends, which is useful in the usual cases where you want to annotate something and not want the line to overlap with the object to annotate or the annotation text. To make sure the line is not shrunk you may use the shrinkA and shrinkB properties:

arrowprops={"arrowstyle" : "-", "linestyle" : "--",
            "shrinkA": 0, "shrinkB": 0}

Make the lines equally styled.

By default the Line2D created by plot has a "butted" capstyle, while the annotation line has a rounded capstyle.

Setting a "rounded" capstyle for bothis relatively easy. Use the dash_capstyle="round" option for the plot:

import matplotlib.pyplot as plt

plt.plot([0,1],[-0.05,-0.05],linestyle="--",linewidth=3, dash_capstyle="round")
plt.annotate("",xy=(1,0.05),xytext=(0,0.05),xycoords="data",
             arrowprops={"arrowstyle" : "-", "linestyle" : "--",
                         "linewidth" : 3, "shrinkA": 0, "shrinkB": 0})
plt.ylim(-0.5,0.5)
plt.show()

enter image description here

Making both capstyles "butted" is currently not possible. The reason is that the line of the annotation is a Patch which does not have this property. Of course any annotation with a line can be mimicked by a plot and a text, so if that is required, a workaround needs to be used.

like image 87
ImportanceOfBeingErnest Avatar answered Sep 21 '25 17:09

ImportanceOfBeingErnest