Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

The Mathematica code

f := #1 + Sin[2 #1] &;
inflectionPoints = Table[{x, f[x]}, {x, -Pi, Pi, Pi/2}];
stationaryPoints = Union[
   Table[{x, f[x]}, {x, -2 Pi/3, Pi/3, Pi}], 
   Table[{x, f[x]}, {x, -Pi/3, 2 Pi/3, Pi}]];
Show[Plot[f[x], {x, -Pi - 1, Pi + 1}], 
     ListPlot[{stationaryPoints, inflectionPoints}, 
     PlotStyle -> {{Red}, {Blue}}, 
  PlotMarkers -> {Automatic, 15}]]

produces:

original

The points (circles and squares) are supposed to be at the critical points, but (as can be seen most clearly via the point at the origin) the points are too far down and too far left.

After manually adjusting the points, I expect the original output should look more like this: enter image description here

Question

Why are the points being rendered at the wrong positions? How can this be fixed?

(First) Response to answers

First off, yoda suggested that this might be OS dependent. I am using Ubuntu 9.10 32-bit with Mathematica 8.0.1.0.

Mr. Wizard's code looks correct in my Mathematica, but if I remove the frame, then the points are rendered too far to the left:

enter image description here

belisarius's code from his machine looks good (see picture in his answer), but on my Mathematica, the points are again rendered too far to the left:

enter image description here

Mr. Wizard and belisarius (and others), do these new facts change your answer?

Conclusion

I believe Mr. Wizard's (as explained in more detail by Alexey Popkov) provides the correct answer. My example (above) of Mr. Wizard's code having points slightly shifted to the left seems to be a different problem. Namely, the picture is so small that Mathematica cannot position things properly. Using a larger image size, everything appears to be in the correct position.

share|improve this question
    
my eyesight is not good enough to see the displacement in your (my) Graphics@Point ... But if Graphics[{PointSize[Large], Point@{0, 0}}, Axes -> True] is not centered in your machine ... the problem is really big –  belisarius Oct 18 '11 at 3:37
    
@belisarius Your code in the above comment works as expected...the point appears centered. –  Tyson Williams Oct 19 '11 at 14:11
    
but the blue point at {0,0} in your last plot is not centered, and it is generated using the same expression –  belisarius Oct 19 '11 at 14:33
    
@belisarius Yes, I think that image suffers from the same problem I just mentioned in the new Conclusion section...that points are now placed correctly for smaller image sizes. –  Tyson Williams Oct 19 '11 at 15:03
    
I see the left-shift you are taking about. I shall try to find an explanation or workaround. –  Mr.Wizard Oct 19 '11 at 15:56
show 1 more comment

migrated from stackoverflow.com Feb 23 '12 at 17:14

This question came from our site for professional and enthusiast programmers.

4 Answers

up vote 20 down vote accepted

This appears to be an issue with the default PlotMarkers. I do not see similar offsets using this:

Show[
 ListPlot[{stationaryPoints, inflectionPoints}, Frame -> True, 
  PlotMarkers -> {{Graphics@{Red, Disk[]}, 
     0.05}, {Graphics@{Blue, Rectangle[]}, 0.05}}],
 Plot[f[x], {x, -Pi - 1, Pi + 1}],
 ImageSize -> 500
]

enter image description here

You can see from this that the default PlotMarkers are actually font based, rather than Graphics primitives:

Graphics`PlotMarkers[] // InputForm
Graphics`PlotMarkers[][[1, 1]] // ToCharacterCode

I believe that these font glyphs are inherently prone to misalignment with Graphics primitives, due to a different rendering pipeline.


Addressing your question about (mis)alignment of PlotMarkers constructed from primitives, I believe this is the result of the chosen antialiasing scheme. One can see by magnifying a screen capture that orthogonal lines use "pixel snapping" or "hinting". This increases apparent sharpness, but sacrifices precise placement.

enter image description here

On my Windows system, a distinct "judder" is apparent in the following animation. Both the placement and the shape of the rectangles changes with ImageSize.

Show[ListPlot[{stationaryPoints, inflectionPoints}, 
          PlotMarkers ->
              {{Graphics@{Red, Disk[]}, 0.05},
               {Graphics@{Blue, Rectangle[]}, 0.05}}], 
     Plot[f[x], {x, -Pi - 1, Pi + 1}],
     Ticks -> None,
     ImageSize -> d
] ~Animate~ {d, 200, 300, 1}

I am not aware of a method to change the 2D antialiasing scheme. However, one work-around is to rasterize the image at a higher resolution, and then resample to the target size.

share|improve this answer
    
Switching antialiasing off by wrapping graphics with Style[...,Antialiasing->False] does not remove the "judder" in this animation. So I think it is due to Mathematica's rendering method, not due to antialiasing scheme. –  Alexey Popkov Oct 20 '11 at 7:57
1  
@Alexey, you are correct. Perhaps I should have said it is caused by the antialiasing scheme that is NOT used. That is to say, I believe there is a scheme, without hinting or pixel-snapping, that would greatly reduce the judder, but make the image seem less sharp. Does this make sense? In the enlargement I included above, the blue rectangles should/could have fuzzy edges to approximate correctly placed squares, but they do not. –  Mr.Wizard Oct 20 '11 at 15:27
    
Good explanation! I believe that Adobe Acrobat already has such a correct antialiasing scheme because I never faced similar problems with it rendering and exporting. –  Alexey Popkov Oct 20 '11 at 17:48
add comment

This bug was already reported earlier in the official newsgroup several times. For example:

Dear all:

FYI, on Mathematica 8.0.1.0 (Linux x86-64), the following gives plot markers which are not centered on the line; they fall slightly below:

ListPlot[Transpose@Table[{1, 2, 3}, {x, 1, 10}], PlotMarkers -> {Automatic, 12}, Joined -> True]

On Mathematica 8.0.1.0 (Mac OS X), the plot markers are properly centered. I will use this as a workaround for now.

It is clear from this report that this behavior is OS-dependent. The reason for this was explained by Szabolcs Horvát:

Precise positioning is not really achievable when glyphs from a font are used as plot markers. The problem can be cured by using graphics objects:

PlotMarkers -> {Graphics[Circle[]], .05}

Or if you need disks as plot markers, then just use a larger point size.

The problem with the font-based Graphics`PlotMarkers[] is even worse than it should be because their resizing is implemented through the FontSize option which gives no smooth scaling for the font used:

In[8]:= Cases[ListPlot[{1}, PlotMarkers -> {Automatic, 12.5}], _Inset, 
  Infinity] // InputForm

Out[8]//InputForm=
{Inset[Style["\[FilledCircle]", FontSize -> 12.5], 3], 
    Inset[Style["\[FilledCircle]", FontSize -> 12.5], 4]}

One workaround for this is to implement your own scaling function:

PlotMarkers -> (Graphics`PlotMarkers[] /. {m_, s_} :> {m, s/2})

(in this example I made plot markers 2 times smaller).

But of course it does not solve the general problem with that Mathematica is unable to position font glyphs precisely. There are two workarounds: we could convert glyphs into outlines or define our own plot markers based on Graphics primitives. Here is my attempt to make a set of nice triangle-based plot markers:

align = Sequence[AlignmentPoint -> {0, 0}, AxesOrigin -> {0, 0}, 
   BaselinePosition -> Axis];
size = Sequence[PlotRange -> {{-2, 2}, {-2, 2}}, 
   PlotRangePadding -> Scaled[edgeThickness/2 + plotRangePadding], 
   ImagePadding -> 0, ImageMargins -> 0];
plotRangePadding = .01;
edgeThickness = .1;
size = Sequence[PlotRange -> {{-2, 2}, {-2, 2}}, 
   PlotRangePadding -> Scaled[edgeThickness/2 + plotRangePadding], 
   ImagePadding -> 0, ImageMargins -> 0];
halfTr = {Graphics[{EdgeForm[], FaceForm[Opacity[1]], 
     Polygon[{{0, 2}, {2/Sqrt[3], 0}, {-(2/Sqrt[3]), 0}}], 
     EdgeForm[{Opacity[1], Thickness[edgeThickness], 
       JoinForm["Round"]}], FaceForm[], 
     Polygon[{{0, 2}, {Sqrt[3], -1}, {-Sqrt[3], -1}}]}, align, 
    "size"], 
   Graphics[{EdgeForm[], FaceForm[Opacity[1]], 
     Polygon[{{2, 0}, {-1, 0}, {-1, Sqrt[3]}}], 
     EdgeForm[{Opacity[1], Thickness[edgeThickness], 
       JoinForm["Round"]}], FaceForm[], 
     Polygon[{{2, 0}, {-1, -Sqrt[3]}, {-1, Sqrt[3]}}]}, align, 
    "size"], 
   Graphics[{EdgeForm[], FaceForm[Opacity[1]], 
     Polygon[{{-Sqrt[3], 1}, {-(2/Sqrt[3]), 0}, {2/Sqrt[3], 0}, {Sqrt[
        3], 1}}], 
     EdgeForm[{Opacity[1], Thickness[edgeThickness], 
       JoinForm["Round"]}], FaceForm[], 
     Polygon[{{0, -2}, {-Sqrt[3], 1}, {Sqrt[3], 1}}]}, align, "size"],
    Graphics[{EdgeForm[], FaceForm[Opacity[1]], 
     Polygon[{{-2, 0}, {1, 0}, {1, Sqrt[3]}}], 
     EdgeForm[{Opacity[1], Thickness[edgeThickness], 
       JoinForm["Round"]}], FaceForm[], 
     Polygon[{{-2, 0}, {1, -Sqrt[3]}, {1, Sqrt[3]}}]}, align, "size"]};
halfTr = Flatten[{halfTr, 
     Table[halfTr /. 
       p : {_?NumericQ, _?NumericQ} :> 
        RotationMatrix[\[Theta]].p, {\[Theta], {Pi, Pi/2, -Pi/2}}]}, 
    2] /. "size" -> size;
Magnify[#, .1] & /@ halfTr
ListPlot[Flatten[Table[{{n, y}}, {y, Range[1, 3]}, {n, 20}], 1], 
 PlotMarkers -> Table[{s, 0.07}, {s, halfTr}], 
 PlotStyle -> ColorData[60, "ColorList"], 
 GridLines -> {Range[20], Range[3]}, PlotRange -> {{0, 21}, {0, 4}}, 
 Axes -> False, Frame -> True]

screenshot

I wonder: why a set of precise plot markers is not included in Mathematica by default? It is not too hard to implement such functionality but it takes significant time from an ordinary user to implement this...

share|improve this answer
2  
That is a nice set of markers, although if I scale them down some of them still don't look great. I used {s, 0.04} for the markers. For example, the "down" pointing triangles in the second row seem too low, and the triangle at (14,2) looks a bit too far to the right. It looks much better if I wrap everything with Style[..., Antialiasing -> True. (By default your glyphs get antialiases, but the frame and gridlines aren't. Although I wouldn't expect this to be an issue for markers on the curve in a plot.) –  Brett Champion Oct 18 '11 at 15:15
    
@Brett Magnifying the Notebook up to 300% reveals that all the triangles are correctly positioned. The inaccurate positioning at lower resolution obviously is an artifact of Mathematica's rendering method. But exporting to PDF gives well-looking plot. –  Alexey Popkov Oct 18 '11 at 16:01
add comment
f := #1 + Sin[2 #1] &;
inflectionPoints =       Table[{x, f[x]}, {x, -Pi, Pi, Pi/2}];
stationaryPoints = Union[Table[{x, f[x]}, {x, -2 Pi/3,   Pi/3, Pi}], 
                         Table[{x, f[x]}, {x, -  Pi/3, 2 Pi/3, Pi}]];
Show[
 Plot[f[x], {x, -Pi - 1, Pi + 1}], 
 Graphics[{Red,  PointSize[Large], Point /@ stationaryPoints,
           Blue, PointSize[Large], Point /@ inflectionPoints}]]

enter image description here

The problem is the ListPlot marker placement function:

Show[
 ListPlot[{stationaryPoints, inflectionPoints}, 
           PlotStyle   -> {{Yellow}, {Green}}, 
           PlotMarkers -> {Automatic, 15}], 
 Graphics[{Black, PointSize[Large], Point /@ stationaryPoints, 
           Black, PointSize[Large], Point /@ inflectionPoints}]]

enter image description here

share|improve this answer
2  
I don't think there is anything wrong with the marker placement function. Please see my answer. Rather, I think that the default markers, being font based, are prone to misalignment. –  Mr.Wizard Oct 18 '11 at 1:12
    
@Mr. I believe the "correct" algorithm should take into account the barycenter of the plot markers, notwithstanding how they are defined. Surely the problem can be interpreted both ways, though. –  belisarius Oct 18 '11 at 1:19
1  
I am not sure I can agree with that. Glyphs are placed relative to a baseline; frankly I would find it disconcerting of the difference in baseline position between e.g. "^" and "," was eliminated. –  Mr.Wizard Oct 18 '11 at 1:22
    
@Mr. May be, but really I can't imagine any use for an eccentric plot marker right now. –  belisarius Oct 18 '11 at 1:28
add comment

Maybe you could do something with Epilog. For example, this

Plot[f[x], {x, -Pi - 1, Pi + 1}, 
 Epilog -> {Translate[
      Inset[Graphics[#1], {0, 0}, {0, 0}, Scaled[0.04]], #2] & @@@ 
       {{{Red, Disk[]}, stationaryPoints},
       {{Blue, Rectangle[{-1, -1}, {1, 1}]}, inflectionPoints}}},
 ImageSize -> 500]

produces this (on my Mac at least)

Mathematica graphics

If the markers are still off you could fine tune their placement by adjusting the second or third argument of Inset.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.