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 command

Plot[x^2, {x, -3, 3}, PlotStyle -> Arrowheads[{-.025, .025}]] /.Line -> Arrow

produces this output.

enter image description here

What I don't understand is what Line has to do with anything. It must be the case that the Plot command produces Line objects that can be replaced with Arrow. I haven't seen anything in the documentation for Plot that suggests this is the case.

Without /.Line->Arrow the plot won't have arrowheads at the ends of the graph of the function.

share|improve this question
4  
According to the documentation for Plot, Plot normally returns Graphics[{Line[...],...}]. See the last two bullet points under "Details and Options." –  Michael E2 Jul 22 at 5:28
    
I missed that. Thank you for pointing that out. Though it does say, "normally returns...". I hope I don't encounter an abnormal case! Looking at the documentation for Line I think I understand the workings of the /.Line->Arrow. –  YequalsX Jul 22 at 5:50
2  
Related: "How does Plot work?" –  Alexey Popkov Jul 22 at 7:54

2 Answers 2

up vote 6 down vote accepted

As far as I know the specific output format of Plot (and similar commands) is not documented. I believe it has changed between versions therefore any post-processing (such as your replacement rule) must be considered potentially version dependent.

As Michael comments above the documentation does state:

Plot normally returns Graphics[{Line[...],...}].

With a Filling specification given, Plot returns Graphics[{GraphicsComplex[...], ...}].

This tells you the basic format and informs you that GraphicsComplex may be used, therefore you should at least account for that in your post-processing.

Typically the best way to learn the output form of such functions is to view it yourself using InputForm. You can use Short or Shallow to limit the size of the expression returned:

Shallow[
 Plot[{x, 2 x}, {x, 1, 5}] // InputForm,
 {100, 10}
]

You can also replace parts you don't want to view, e.g. Line objects:

Plot[{x, 2 x}, {x, 1, 5}] /. _Line :> "Line[]" // InputForm

Everything in the output expression can be manipulated, including Graphics primitives and options. See:

Some aspects of Plot are not obvious or intuitive such as details of the styling chosen. See:

And as linked from my answer there:


Plot with arrows

You asked specifically about adding arrowheads to plot lines. Although post-processing is the only approach I know for this, meaning I am not aware of an option for Plot itself, I think it is a good method and I have used many time.

The syntax for Line and Arrow is similar, and both work with GraphicsComplex, therefore the replacement should be reliable. However to make the replacement more robust you should focus it only on the part of the Graphics object that will contain Plot-generated Line expressions, since for example a Prolog or Epilog might also contain Line expressions. Here with MapAt:

MapAt[# /. Line -> Arrow &, Plot[{x, 2 x, 3 x}, {x, 1, 7}], 1]

Or if you have version 10, the operator form:

arrows = MapAt[# /. Line -> Arrow &, 1];

Plot[{x, 2 x, 3 x}, {x, 1, 7}] // arrows

Worth noting is that even though (AFAIK) you cannot generate Arrow expression from within Plot you can still provide style directives that will take affect after the replacement:

Plot[{x, 2 x, 3 x}, {x, 1, 7},
 PlotStyle -> Array[Arrowheads[#/20] &, 3]
] // arrows

enter image description here

share|improve this answer
    
My goal is to have arrow heads at the ends of plots of functions. Is there a way to do this without resorting to /.Line->Arrow and potentially having things break in future versions? I have custom plot functions that I use make things look the way I want and I use /.Line->Arrow. –  YequalsX Jul 22 at 12:16
1  
@YequalsX Please see the update. –  Mr.Wizard Jul 22 at 12:52

I can add to Mr.Wizards' answer that when InputForm is wrapped by any head like List (// InputForm // List) the output is much more readable because in this case it is represented in StandardForm instead of pure textual representation. StandardForm allows semantical selection by double-clicking. From the other hand it is worth to know that the width of the standard InputForm output can be controlled via the PageWidth options of "stdout" as shown here.

For inspecting the low-level structure of graphics I find handy my shortInputForm function originally published here:

ClearAll[shortInputForm];
shortInputForm[expr_] := 
  Module[{result, shdwMessageOn, 
    tempContext = SymbolName[Unique["myTemp"]] <> "`"},
   Block[{$ContextPath = Prepend[$ContextPath, tempContext]},
    If[Head[General::shdw] === String, shdwMessageOn = True; 
     Off[General::shdw]];
    result = 
     RawBoxes@
      ToBoxes[Replace[
         expr //. {left___, {}, right___} :> {left, right},
         {s : (Point | Line | Arrow | Rectangle | Parallelogram | 
              Triangle | JoinedCurve | FilledCurve | BezierCurve | 
              BSplineCurve | BSplineSurface | Raster | Raster3D | 
              Polygon | Disk | Circle | Sphere | Ball | Ellipsoid | 
              Cylinder | Tetrahedron | Cuboid | Parallelepiped | 
              Hexahedron | Prism | Pyramid | Simplex | 
              ConicHullRegion | Cone | InfiniteLine | HalfLine | 
              InfinitePlane | HalfPlane | Tube | GraphicsComplex | 
              GraphicsGroup | Graphics | Graphics3D | 
              SurfaceGraphics | Text | Inset) :> 
           Interpretation[Style[HoldForm[s], Bold], s], 
          s_Symbol /; List =!= Unevaluated[s] :> 
           Symbol[tempContext <> SymbolName[Unevaluated@s]]}, {0, 
          Infinity}, Heads -> True] /.
        {lst : {x_, y__} /; MatrixQ[lst, NumberQ] && Length[lst] > 3 :>
          {x /. v : {a_, b__} /; Length[v] > 3 :>
             {a, 
              Interpretation[Style[Skeleton[Length[{b}]], Gray], 
               Sequence @@ {b}]},   
           Interpretation[Style[Skeleton[Length[{y}]], Gray], 
            Sequence @@ {y}]},
         lst : {x_, y__} /; VectorQ[lst, NumberQ] && Length[lst] > 3 :>
          {x, Interpretation[Style[Skeleton[Length[{y}]], Gray], 
            Sequence @@ {y}]}}];
    Remove @@ Names[tempContext <> "*"];
    If[shdwMessageOn, On[General::shdw]]]; result];

Here is how it formats the output:

screenshot

shortInputForm not just displays a shortened and formatted version of InputForm but also allows to select and copy parts of the shortened code into new input cell and use this code as it would be the full code without abbreviations:

screenshot

It is implemented through Interpretation.

share|improve this answer
    
I should have been using this function. Good stuff! +1 –  Mr.Wizard Jul 22 at 8:25
2  
Regarding the // InputForm // List thing, that's a nice trick, but you can also select the graphic and Convert to InputForm (Ctrl+Shift+I) for an editable InputForm. –  Mr.Wizard Jul 22 at 8:33
1  
Good alternative. Convert to InputForm gives the fixed-width output (what may be desired in some cases) while // InputForm // List gives window-width wrapping. –  Alexey Popkov Jul 22 at 8:38

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.