Skip to main content
Commonmark migration
Source Link

3. Converting Tooltip displays to static labels at custom positions##positions

3. Converting Tooltip displays to static labels at custom positions##

3. Converting Tooltip displays to static labels at custom positions

replaced http://mathematica.stackexchange.com/ with https://mathematica.stackexchange.com/
Source Link

For this, I'll use the same idea as in my answer to this questionthis question, but modified to get a dynamically updated graphic that includes labels wherever I click on a Tooltip-decorated line:

For this, I'll use the same idea as in my answer to this question, but modified to get a dynamically updated graphic that includes labels wherever I click on a Tooltip-decorated line:

For this, I'll use the same idea as in my answer to this question, but modified to get a dynamically updated graphic that includes labels wherever I click on a Tooltip-decorated line:

Added two sections dealing with Tooltip and how to convert it to static labels
Source Link
Jens
  • 97.9k
  • 7
  • 215
  • 510

I'm revisiting this topic because I have a new solution at the bottom of the post. The outline of this answer is:

Interactively labeling contours

  1. Using the graphics editor
  2. Using Tooltip
  3. Converting Tooltip displays to static labels at custom positions

Section 1 was my original answer, the other two are new.

1. Using the graphics editor

What I usually do is label the contours by hand with the help of the drawing tools. For that you first have to know what labels belong to which contour. In your example, the label you want is the parameter t, so to get myself oriented I first defined a ContourLabels function that can display that number:

EditHow permanent are these annotations?

The conclusion from this is that the manual labor involved in making the labels as I showed above is not completely wasted when you re-draw the contour plot, because copying your work preserves the coordinates of the insets.

2. Using Tooltip

Normally, Tooltip is the easiest way to label contours because that's the default behavior of ContourPlot when no ContourLabels option is specified.

However, we want to label contours by a Tooltip showing a custom quantity, not the default which is contour height. In the documentation for ContourLabels (under Details), you find that custom tool tips should be available by specifying

ContourLabels -> {f, g}

where the second function, g, is used "as a tooltip for each complete contour line." This is very ambiguously worded, and it seems to have had people stumped (see the MathGroup archive). It turns out that g isn't the function that specifies the argument for the Tooltip, it actually has to be of Head Tooltip.

So in the example of the question, for a Table of several contour plots where each contour is custom labeled by the Table index t, we can get a tooltip-labeled plot like this:

toolPlot = Show[
 Table[
  ContourPlot[t*d^2 - g, {g, 0, 1}, {d, 0, 1}, Contours -> {0}, 
   ContourStyle -> Black, ContourShading -> None, 
   FrameLabel -> {"g", "d"},
   ContourLabels -> {
     None,
     Tooltip[#, t] &}
   ],
  {t, 0.1, 1, 0.1}
  ]
 ]

tool tips

The first function in ContourLabels is simply set to None so we don't get any static labels at all. The second argument shows how you get the Tooltip labeling "each complete contour line," as the documentation put it.

Now we're done debugging the mysterious documentation, and it's time for the fun part:

3. Converting Tooltip displays to static labels at custom positions##

Here we ask the question:

Given a graphics object such as toolPlot from above, can we convert the information contained in the Tooltips into static labels and position these labels interactively?

This is different from adding labels completely manually, because we're going to rely on the auto-generated information in the Tooltip and only leave the choice of position as a manual task.

For this, I'll use the same idea as in my answer to this question, but modified to get a dynamically updated graphic that includes labels wherever I click on a Tooltip-decorated line:

Options[burnTooltips] = {ImageSize -> 360, 
   "LabelFunction" -> (Framed[#, FrameStyle -> None, 
       RoundingRadius -> 8, Background -> RGBColor[1, .8, .4]] &)};

burnTooltips[plot_, opt : OptionsPattern[]] := DynamicModule[
  {
   ins = {},
   wrapper = OptionValue["LabelFunction"],
   toolRule = Function[{arg},
     Tooltip[t__] :> Button[
       Tooltip[t],
       AppendTo[
        arg,
        Inset[wrapper[Last[{t}]], MousePosition["Graphics"]]
        ]
       ],
     HoldAll]
   },
  EventHandler[
   Dynamic@Show[
     plot /. toolRule[ins],
     Graphics@ins,
     ImageSize -> OptionValue[ImageSize]
     ],
   {"MouseUp", 2} :> (toolRule = {} &)
   ]
  ]

The function burnTooltips can be applied to the contour plots of our example as follows:

burnTooltips[toolPlot]

This will display the graphic in the argument again, but now whenever you click on an object displaying a Tooltip, the displayed value appears as a static label in the graphic. When you're done adding the labels at locations where they look good to you, you may want to prevent this dynamic display from receiving any further clicks. To do that, right-click the mouse over the completed picture.

Here is what the result might look like:

tooltips to labels

To continue working with this graphic, copy it and paste it into the next Input cell. For example, to get an image to upload above, I typed

Export["picture.png",   ]

and pasted the image in the space.

There are two options you may want to play with for burnTooltips: ImageSize and "LabelFunction". The first one doesn't need explanation, and the second one should be something of the type Framed[#]& or Pane[#]& (my default setting is shown in the image). By adding the label formatting as a function (note the &), it's possible to customize the labels almost arbitrarily. For example, one could also try this:

"LabelFunction" -> (Pane[Style[#, Red, Background -> White], 
    ImageSize -> {20, 20}, ImageSizeAction -> "ResizeToFit"] &)

This method is pretty amenable to how I normally work with plots: use default labeling (i.e., Tooltip in this case) while exploring the problem, and start worrying about the exact placement of labels only at the end.

Here I showed how one can get to the finalized labeled plot from the Tooltip stage. In the function burnTooltips, the Tooltip is used as a kind of vehicle with which a new "payload" can be injected into an existing plot, turning it into a dynamic object that accumulates information about where you click to place labels containing the exact same information that the Tooltip displayed.

Generalizations

You should be able to apply burnTooltips to virtually any Graphics object, not just ContourPlots. But I think ContourPlot is one of the most important applications for this technique because even in single plots (not tables as we considered here), the automatically generated labels are often placed in awkward locations so that manual adjustment is required.

What I usually do is label the contours by hand with the help of the drawing tools. For that you first have to know what labels belong to which contour. In your example, the label you want is the parameter t, so to get myself oriented I first defined a ContourLabels function that can display that number:

Edit

The conclusion from this is that the manual labor involved in making the labels as I showed above is not completely wasted when you re-draw the contour plot, because copying your work preserves the coordinates of the insets.

I'm revisiting this topic because I have a new solution at the bottom of the post. The outline of this answer is:

Interactively labeling contours

  1. Using the graphics editor
  2. Using Tooltip
  3. Converting Tooltip displays to static labels at custom positions

Section 1 was my original answer, the other two are new.

1. Using the graphics editor

What I usually do is label the contours by hand with the help of the drawing tools. For that you first have to know what labels belong to which contour. In your example, the label you want is the parameter t, so to get myself oriented I first defined a ContourLabels function that can display that number:

How permanent are these annotations?

The conclusion from this is that the manual labor involved in making the labels as I showed above is not completely wasted when you re-draw the contour plot, because copying your work preserves the coordinates of the insets.

2. Using Tooltip

Normally, Tooltip is the easiest way to label contours because that's the default behavior of ContourPlot when no ContourLabels option is specified.

However, we want to label contours by a Tooltip showing a custom quantity, not the default which is contour height. In the documentation for ContourLabels (under Details), you find that custom tool tips should be available by specifying

ContourLabels -> {f, g}

where the second function, g, is used "as a tooltip for each complete contour line." This is very ambiguously worded, and it seems to have had people stumped (see the MathGroup archive). It turns out that g isn't the function that specifies the argument for the Tooltip, it actually has to be of Head Tooltip.

So in the example of the question, for a Table of several contour plots where each contour is custom labeled by the Table index t, we can get a tooltip-labeled plot like this:

toolPlot = Show[
 Table[
  ContourPlot[t*d^2 - g, {g, 0, 1}, {d, 0, 1}, Contours -> {0}, 
   ContourStyle -> Black, ContourShading -> None, 
   FrameLabel -> {"g", "d"},
   ContourLabels -> {
     None,
     Tooltip[#, t] &}
   ],
  {t, 0.1, 1, 0.1}
  ]
 ]

tool tips

The first function in ContourLabels is simply set to None so we don't get any static labels at all. The second argument shows how you get the Tooltip labeling "each complete contour line," as the documentation put it.

Now we're done debugging the mysterious documentation, and it's time for the fun part:

3. Converting Tooltip displays to static labels at custom positions##

Here we ask the question:

Given a graphics object such as toolPlot from above, can we convert the information contained in the Tooltips into static labels and position these labels interactively?

This is different from adding labels completely manually, because we're going to rely on the auto-generated information in the Tooltip and only leave the choice of position as a manual task.

For this, I'll use the same idea as in my answer to this question, but modified to get a dynamically updated graphic that includes labels wherever I click on a Tooltip-decorated line:

Options[burnTooltips] = {ImageSize -> 360, 
   "LabelFunction" -> (Framed[#, FrameStyle -> None, 
       RoundingRadius -> 8, Background -> RGBColor[1, .8, .4]] &)};

burnTooltips[plot_, opt : OptionsPattern[]] := DynamicModule[
  {
   ins = {},
   wrapper = OptionValue["LabelFunction"],
   toolRule = Function[{arg},
     Tooltip[t__] :> Button[
       Tooltip[t],
       AppendTo[
        arg,
        Inset[wrapper[Last[{t}]], MousePosition["Graphics"]]
        ]
       ],
     HoldAll]
   },
  EventHandler[
   Dynamic@Show[
     plot /. toolRule[ins],
     Graphics@ins,
     ImageSize -> OptionValue[ImageSize]
     ],
   {"MouseUp", 2} :> (toolRule = {} &)
   ]
  ]

The function burnTooltips can be applied to the contour plots of our example as follows:

burnTooltips[toolPlot]

This will display the graphic in the argument again, but now whenever you click on an object displaying a Tooltip, the displayed value appears as a static label in the graphic. When you're done adding the labels at locations where they look good to you, you may want to prevent this dynamic display from receiving any further clicks. To do that, right-click the mouse over the completed picture.

Here is what the result might look like:

tooltips to labels

To continue working with this graphic, copy it and paste it into the next Input cell. For example, to get an image to upload above, I typed

Export["picture.png",   ]

and pasted the image in the space.

There are two options you may want to play with for burnTooltips: ImageSize and "LabelFunction". The first one doesn't need explanation, and the second one should be something of the type Framed[#]& or Pane[#]& (my default setting is shown in the image). By adding the label formatting as a function (note the &), it's possible to customize the labels almost arbitrarily. For example, one could also try this:

"LabelFunction" -> (Pane[Style[#, Red, Background -> White], 
    ImageSize -> {20, 20}, ImageSizeAction -> "ResizeToFit"] &)

This method is pretty amenable to how I normally work with plots: use default labeling (i.e., Tooltip in this case) while exploring the problem, and start worrying about the exact placement of labels only at the end.

Here I showed how one can get to the finalized labeled plot from the Tooltip stage. In the function burnTooltips, the Tooltip is used as a kind of vehicle with which a new "payload" can be injected into an existing plot, turning it into a dynamic object that accumulates information about where you click to place labels containing the exact same information that the Tooltip displayed.

Generalizations

You should be able to apply burnTooltips to virtually any Graphics object, not just ContourPlots. But I think ContourPlot is one of the most important applications for this technique because even in single plots (not tables as we considered here), the automatically generated labels are often placed in awkward locations so that manual adjustment is required.

Show how to copy labels; edited body
Source Link
Jens
  • 97.9k
  • 7
  • 215
  • 510
Loading
Source Link
Jens
  • 97.9k
  • 7
  • 215
  • 510
Loading