1
$\begingroup$

How can "ContourLabels" be added into regular curves given by Plot or ListLinePlot?

Note: It is also important to comfortably control the location, density and alignment of the labels.

For example:

ListLinePlot[Table[Table[i^j, {i,0,5,.1}],{j,1,3}],PlotRange->{0, 10}]

gives:

enter image description here

How can it be plotted as:

enter image description here

$\endgroup$
  • $\begingroup$ ListLinePlot[Table[Table[{i, i^j}, {i, 0, 5, .1}], {j, 1, 3}], PlotRange -> {0, All}, PlotLabels -> {Placed[Text["j=1", Background -> White], {4, 4}], Placed[Text["j=2", Background -> White], {4, 4^2}], Placed[Text["j=3", Background -> White], {4, 4^3}]}] This could be a starting point $\endgroup$ – Fraccalo Aug 20 '18 at 13:41
  • $\begingroup$ You can simply use the function burnTooltip from my answer here, if you generate your plot as (in the notation of that answer) toolPlot = ListLinePlot[ Table[Tooltip[Table[i^j, {i, 0, 5, .1}], Row[{"j \[LongEqual] ", j}]], {j, 1, 3}], PlotRange -> {0, 10}]. Although that linked question was about ContourPlot, my answer works for any plot. It may also be worth mentioning Callout as another option. $\endgroup$ – Jens Aug 24 '18 at 16:35
4
$\begingroup$

From the manual of Plot:

The following wrappers can be used for the plotted function f:

  • Labeled[f,label] - label the function
  • Labeled[f,label,pos] -place the label at relative position pos
Plot[
 Evaluate@Table[
   Labeled[i^j, StringTemplate["j=``"][j], 5 - j/2],
   {j, 1, 3}
   ],
 {i, 0, 5}]

enter image description here

Mathmatica takes care of the placement for you, but using the third argument of Labeled you can override it the way you want. The acceptet format for the postition argument is given in the manual for Plot. The best are perhaps Above, Below, Before and After, which remove any need for manual position adjustment.

I took liberty to implement the same figure with Plot instead of ListPlot as I find it more elegent to leave the proper sampling to Mathematica. However, the same wrappers are also supported by ListPlot if you should need.

Edit I guess the rotation of the label is not very important, but just for the heck of it I also wanted to propose a way it could be done:

dataAspectRatio = 20
labelf[f_, label_, arg_, labelArg_] := 
 Labeled[f[arg], 
  Rotate[Style[label, Background -> White], 
   ArcTan[D[f[x], x]/dataAspectRatio /. x -> labelArg]], {labelArg, 
   f[labelArg]}]
Plot[
 Evaluate@Table[
   labelf[#^j &, StringTemplate["j=``"][j], i, 5 - j/2],
   {j, 1, 3}
   ],
 {i, 0, 5}]

enter image description here

Note, that white background can be removed by removing Background -> White.

$\endgroup$
2
$\begingroup$

Try this:

points = {};

Manipulate[DynamicModule[{pts = {{10, 2}, {20, 4}, {30, 6}}},
  Column[{
    LocatorPane[Dynamic[pts],

     Dynamic@
      ListLinePlot[Table[Table[i^j, {i, 0, 5, .1}], {j, 1, 3}], 
       PlotRange -> {0, 10}, ImageSize -> 300,
       Epilog -> {Inset[
          Rotate[Panel[Style["j=1", Italic, 18], 
            Background -> White], \[Alpha]], pts[[1]]],
         Inset[
          Rotate[Panel[Style["j=2", Italic, 18], 
            Background -> White], \[Beta]], pts[[2]]],
         Inset[
          Rotate[Panel[Style["j=3", Italic, 18], 
            Background -> White], \[Gamma]], pts[[3]]]
                        }
                                                  ]
      ],

    Button["Copy the list of points", Clear[points]; points = pts; 
     Print[points]]

             }]

  ], {\[Alpha], 0, \[Pi]}, {\[Beta], 0, \[Pi]}, {\[Gamma], 0, \[Pi]}]

yielding the following

enter image description here

You act as follows:

  1. With locators position the labels on their places.

  2. With sliders adjust the angles of the labels

  3. Press the button and a set of points will appear below the panel. Pick up the points and insert them under the ListLinePlot statement instead of pts[1],pts[2] and pts[[3]].

  4. By clicking on the Animation Control Box (containing the sign "+") open the controls, pick up the values of alpha, beta and gamma and insert them under the ListLinePlot statement.

  5. Copy-paste the ListLinePlot statement in another place.

ListLinePlot[Table[Table[i^j, {i, 0, 5, .1}], {j, 1, 3}], PlotRange -> {0, 10}, ImageSize -> 300, Epilog -> { Inset[Rotate[Panel[Style["j=1", Italic, 18], Background -> White], 0.383274], {31.95, 3.24}], Inset[Rotate[Panel[Style["j=2", Italic, 18], Background -> White], 1.04929], {28.15, 7.62`}], Inset[Rotate[Panel[Style["j=3", Italic, 18], Background -> White], 1.31004], {19.65, 7.02}] }]

You will see this:

enter image description here

Done. Have fun!

$\endgroup$
  • $\begingroup$ This is very cool, definitely far from my abilities. However, there are many problems, the white panels for example, do not fit when there are dense contours, and in general the whole process is time consuming. $\endgroup$ – jarhead Aug 20 '18 at 19:50
  • 1
    $\begingroup$ @jarhead That's exactly what you demanded. You should formulate your requirements more precisely. $\endgroup$ – Alexei Boulbitch Aug 21 '18 at 9:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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