You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Marker edge overlaps with marker and the edge appears to be double the width specified. This becomes obvious when you use alpha transparency and a very larger point marker with a large edge width or in the case where I noticed it a small figure (about 2 inches wide) with the default rcParams.
Actual outcome
In this figure I have markersize=200 and markeredgewith=50. There is an ugly ring and it looks as if the marker edges are two times wider (100 instead of 50) than I asked.
Now in this figure I have markersize=200 and markeredgewidth=99. There is a single pixel in the center that is faded blue thus the markeredges are definitely twice what I asked for. If I set the markeredgewith to 100 I get a solid core.
Expected outcome
I would expect that the marker edge would line up perfectly with the marker core. In this plot I set markersize to 300 (200 plus 2*50 edges) to get the same size as the original without the ugly ring.
The line is drawn along the edge of the marker. It's common practice in vector graphics that half of the line width is to either side of the drawing path. The "ring" is the overlaid color of the filled area and the edge. This is also standard behavior see e.g. this red circle with a semi-transparent green edge produced in inkscape:
2. Sizes are incorrect
What actually does not work correctly are the sizes, e.g.
I see, that makes sense. I agree that the sizes are incorrect. In inkscape if the stroke width is 1/4 of the object size that stroke overlays half on the object and half off thus adding exactly its width to the objects width (unlike in matplotlib which currently adds 2*mew to the marker size).
What actually does not work correctly are the sizes, e.g.
That's because your example is using '.', or "point" markers, which are intentionally smaller. Using 'o', or "circle" markers, ms=100 comes out the same size as lw=100.
Note: the actual sizes are rather undocumented except if you look at the table here (which is really just an implicit thing, and not explicitly spelled out.)
@QuLogic So I see now that if using 'o' as the marker then matplotlib matches Inkscape's behavior. The line width is the same as the marker size and the marker edge overlaps half-on/half-off. In that case I believe it to be a bit strange that matplotlib includes markers like '.' that break this behavior. Also it does seem that the '.' marker is currently "broken" in that the marker edge doesn't scale by half its value as does the marker size. In code I'm saying plt.plot(1, 1, 'o', ms=50, mew=0) and plt.plot(1, 1, '.', ms=100, mew=0) are identical yet plt.plot(1, 1, 'o', ms=50, mew=10) and plt.plot(1, 1, '.', ms=100, mew=20) are not. For the point marker the marker size is scaled by 1/2 but the marker edge width is not. Why is that?
The "." marker is a "o" marker, scaled by a factor of 0.5.
The edge is applied after the scaling. So the edgewidth is the same in both cases.
Meaning, each of the following produces a circle with 60 points diameter
As for the reason for the factor of 0.5, I can only speculate: If you specify ms=1 and no edgewidth, the default edgewidth of 1 point will lead to a 1pt large dot in the figure.
The logic breaks of course once you use the default (or any other) markersize (e.g. ".", ms=5, mew=1 will be a dot with 3.5pt diameter).
Anyways, that logic got introduced 14 years ago and before that it looks like it was even less comprehensible.
I think anyone is welcome to document the factor of 0.5 in the marker documentation.
Just out of curiosity: why should it be good that the edge overlaps the marker filling by half? An edge is an edge, and the current behavior is counter intuitive, especially if the edge color is the same as the fill color.
I know that this is a very old feature and users have gotten used to it. Adding a bit of control could not harm, though. How about a parameter markeredgeoffset with the default choice reproducing the current behavior, a value 'aligned' (or similar) ensuring that the outer ring does not overlap, and scalar values controlling the offset of the outer ring?
As written above #13360 (comment), the edge overlapping the marker half is common practice.
It‘s also much simpler to perform: The edge is a line drawn at the shape coordinates. If you put the line to the inner or outer side of the shape, it‘s point coordinates become dependent on the line width and even worse on the angles of the connecting segments. And even if done correctly, there may be interpolation artifacts at the interface if the body and the line do not overlap.
I think it's not only common practice but it's really the only way to unambiguously define an edge. If you consider the below shape consisting of 4 points, and start to do an "outer" edge, it will soon become an "inner" edge for some part of the shape.
Activity
timhoffm commentedon Feb 6, 2019
1. Overlapping not an issue
The line is drawn along the edge of the marker. It's common practice in vector graphics that half of the line width is to either side of the drawing path. The "ring" is the overlaid color of the filled area and the edge. This is also standard behavior see e.g. this red circle with a semi-transparent green edge produced in inkscape:
2. Sizes are incorrect
What actually does not work correctly are the sizes, e.g.
mew = 1/4 msbut the plotted edgewidth is 1/2 the marker diameter.krrk commentedon Feb 6, 2019
I see, that makes sense. I agree that the sizes are incorrect. In inkscape if the stroke width is 1/4 of the object size that stroke overlays half on the object and half off thus adding exactly its width to the objects width (unlike in matplotlib which currently adds
2*mewto the marker size).QuLogic commentedon Feb 6, 2019
That's because your example is using
'.', or "point" markers, which are intentionally smaller. Using'o', or "circle" markers, ms=100 comes out the same size as lw=100.QuLogic commentedon Feb 6, 2019
Note: the actual sizes are rather undocumented except if you look at the table here (which is really just an implicit thing, and not explicitly spelled out.)
krrk commentedon Feb 28, 2019
@QuLogic So I see now that if using
'o'as the marker then matplotlib matches Inkscape's behavior. The line width is the same as the marker size and the marker edge overlaps half-on/half-off. In that case I believe it to be a bit strange that matplotlib includes markers like'.'that break this behavior. Also it does seem that the'.'marker is currently "broken" in that the marker edge doesn't scale by half its value as does the marker size. In code I'm sayingplt.plot(1, 1, 'o', ms=50, mew=0)andplt.plot(1, 1, '.', ms=100, mew=0)are identical yetplt.plot(1, 1, 'o', ms=50, mew=10)andplt.plot(1, 1, '.', ms=100, mew=20)are not. For the point marker the marker size is scaled by 1/2 but the marker edge width is not. Why is that?ImportanceOfBeingErnest commentedon Mar 1, 2019
The
"."marker is a"o"marker, scaled by a factor of 0.5.The edge is applied after the scaling. So the edgewidth is the same in both cases.
Meaning, each of the following produces a circle with 60 points diameter
As for the reason for the factor of 0.5, I can only speculate: If you specify
ms=1and no edgewidth, the default edgewidth of 1 point will lead to a 1pt large dot in the figure.The logic breaks of course once you use the default (or any other) markersize (e.g.
".", ms=5, mew=1will be a dot with 3.5pt diameter).Anyways, that logic got introduced 14 years ago and before that it looks like it was even less comprehensible.
I think anyone is welcome to document the factor of 0.5 in the marker documentation.
normanius commentedon Aug 16, 2019
Just out of curiosity: why should it be good that the edge overlaps the marker filling by half? An edge is an edge, and the current behavior is counter intuitive, especially if the edge color is the same as the fill color.
I know that this is a very old feature and users have gotten used to it. Adding a bit of control could not harm, though. How about a parameter
markeredgeoffsetwith the default choice reproducing the current behavior, a value'aligned'(or similar) ensuring that the outer ring does not overlap, and scalar values controlling the offset of the outer ring?timhoffm commentedon Aug 16, 2019
As written above #13360 (comment), the edge overlapping the marker half is common practice.
It‘s also much simpler to perform: The edge is a line drawn at the shape coordinates. If you put the line to the inner or outer side of the shape, it‘s point coordinates become dependent on the line width and even worse on the angles of the connecting segments. And even if done correctly, there may be interpolation artifacts at the interface if the body and the line do not overlap.
ImportanceOfBeingErnest commentedon Aug 16, 2019
I think it's not only common practice but it's really the only way to unambiguously define an edge. If you consider the below shape consisting of 4 points, and start to do an "outer" edge, it will soon become an "inner" edge for some part of the shape.
timhoffm commentedon Aug 16, 2019
Closing as intended behavior.
mzechmeister commentedon Feb 17, 2022
Plotting the points twice once without edge and once without face is a workaround:
But a legend will become tricky.
timhoffm commentedon Feb 17, 2022
Another option is to only make the face color transparent and keep the edge solid. This is likely acceptable appearance in many cases: