# Hovering mouse cursor over a plot to display a “corresponding” point in another plot

(Apologies for not having gotten around to responding to and accepting answers on my other recent questions—as a meticulous and thorough type, I'd like to take my time to fully comprehend and play with all answers before responding. I'll definitely follow up.)

I'm trying to reproduce a variant of this view, where hovering the mouse over a point highlights its "corresponding" point on all plots:

In my case, the additional complexion is that the x-axes are not the same (i.e. they're not all time), though they do all increase monotonically.

However, I've yet to understand (though perhaps the answer may be in one of those threads) how one would affect a plot based on an event triggered on another plot. Any pointers would be greatly appreciated. I'll post my solution when I figure it out, though I'm sure it won't be the best one could do, as I'm still new to Mathematica.

After @ssch's answer was posted, I realized I left out some critical details/clarifications.

First, I'm working with discreet data, i.e. two ListPlots. That doesn't seem to matter, though. @ssch's example worked for me, using ListPlot.

Second, and more importantly, the two x-axes are not linear images—_i.e._they do not increase uniformly. For example:

The above plots graph the same y-axes, but based on different x-axes. (The dotted gray lines correspond, so one can see how certain areas are "stretched" or "compressed" in the second graph.)

Is there a way to get a corresponding cursor in such a case?

-
But still n-th point in first plot is referring to the n-th point in the second? – Kuba Oct 21 '13 at 6:33
I found my answer in another thread: mathematica.stackexchange.com/questions/34611/…. But I will post back here when I get it working with a hovering cursor. – Andrew Cheong Oct 24 '13 at 8:05

Using Scaled coordinates can be quite helpful:

DynamicModule[{
loc = Scaled[{0.5, 0.5}]},
Column[{
Plot[
x, {x, 1, 2},
Epilog -> Dynamic[ Point[Scaled[{loc[[1, 1]], loc[[1, 1]]}]] ]],
Plot[
x^2, {x, -1, 2},
Epilog -> Dynamic@Locator[Dynamic[loc]]]
}]
]


See how the point in the first coordinates follows quite nicely even though their ranges are completely different.

You can of course use EventHandler with MousePosition, which supports "GraphicsScaled" coordinates, instead of a Locator.

-
Thanks for the starter, @ssch! Indeed, your example worked up to the point of getting a locator to correspond to a depicted point on another graph. I wasn't aware of DynamicModule's use in this way. However, I've edited my question to reflect a more involved aspect of my problem: my x-axes are not linear multiples of one another! Would you have any suggestion(s) as to how to approach this problem? Thank you. – Andrew Cheong Oct 21 '13 at 2:24
@acheong87 I'd start by defining an invertible mapping between the two plotranges and use that to transform the location data. – ssch Oct 21 '13 at 2:49
data = Table[{i, 5 Sin[i/10] + RandomReal[]}, {i, 100}];
data2 = {Log[#], #2} & @@@ data;


In case when you don't know how both axes are related to each other but only have point sets you can do something like:

Deploy@With[{opts = {Axes -> False, Frame -> True, ImageSize -> {300, 300/GoldenRatio},
AspectRatio -> 1/GoldenRatio}},
DynamicModule[{sel = 1, mark},
Column[{
Graphics[{PointSize@.02, Dynamic@mark[data],
Red, PointSize@.05, Dynamic@Point[data[[sel]]]}, opts],
Graphics[{PointSize@.02, Dynamic@mark[data2],
Red, PointSize@.05, Dynamic@Point[data2[[sel]]]}, opts]
}]
, Initialization :> (
mark[data_] := MapIndexed[Dynamic@{If[CurrentValue["MouseOver"], sel = First@#2];,
Point[#]} &, data];
)]
]


-
I apologize I haven't had a chance to return to my project since the workweek began! I'll get to it later today, but this already looks like it's gonna do what I want. You guessed correctly that I have only point sets that map one-to-one, not a continuous function of any sort (though, I recall seeing an Interpolate function in Mathematica that might help with that). Can't wait to try this. (And I'll delete this otherwise frivolous comment.) – Andrew Cheong Oct 22 '13 at 14:09
@acheong87 I'm looking forward hearing how it fits your needs :) If any improvements need to be done, just tell me. Good luck. – Kuba Oct 22 '13 at 14:33
Your code, using 100 sample points, works. Unfortunately however, when I up the number of points to 6,300 (the typical size of my lists), Mathematica hangs at the "Formatting Notebook Contents" dialog, bringing up the "Disable Dynamic Evaluation" dialog every 10 seconds. Do you think perhaps the mouseover aspect consumes a lot of processing power? (I'm trying to remove that now, as I don't necessarily need hovering (clicking is sufficient). Or is it something else? – Andrew Cheong Oct 23 '13 at 2:13
@acheong87 hi, sorry for delay, could you tell more about the data? Is the sampling constant etc? or you want a solution for just two list with arbitrary points related with pairs? – Kuba Oct 24 '13 at 6:56
No problem! I should thank you. I learned a ton over the past two days, starting from your code, and trying to modify it in various ways to do the minimum processing necessary. I know I probably could have been clearer about my data, too; I apologize. Two days ago, I didn't see my data that way, but yes, you're right, I have two arbitrarily lists, say {{1,2},{3,4},{5,6},...} and {{10,20},{30,40},{50,60},...} and need corresponding pairs to be "related," e.g. {1,2} and {10,20}. However, while asking a sub-question on another thread, @belisarius provided yet another answer, which I – Andrew Cheong Oct 24 '13 at 7:03

@belisarius answered my question in another thread. The following is his code with one modification: replacing MouseDown with MouseMoved.

opts = {Axes -> False, Frame -> True, ImageSize -> {300, 200},  AspectRatio -> 1/GoldenRatio};
td1 = Table[{x, 5 Sin[x] + RandomReal[]}, {x, 1, 10, (10 - 1)/500}];
td2 = {Log[#], #2} & @@@ td1;
f = Nearest[td1 -> Automatic];
g = Nearest[td2 -> Automatic];
DynamicModule[{pt1 = {0, 0}, pt2 = {0, 0}, x1 = First@td1, x2 = First@td2},
Row@{
Deploy@EventHandler[Dynamic@
Graphics[{Point@td1 , Red, PointSize[Large], Point[x1]}, opts, GridLines -> {{x1[[1]]}, {}}],
"MouseMoved" :> ({x1, x2} = {td1[[#]], td2[[#]]} &@ f[MousePosition["Graphics"], 1])],
Deploy@EventHandler[Dynamic@
Graphics[{Point@td2, Green,  PointSize[Large], Point[x2]}, opts ,GridLines -> {{x2[[1]]}, {}}],
"MouseMoved" :> ({x1, x2} = {td1[[#]], td2[[#]]} &@ g[MousePosition["Graphics"], 1])]
}]


I'm only copying the answer here for posterity, as a comment may be overlooked (especially as I plan to accept @Kuba's answer for the time being, as his led me in the right direction). I will delete this answer if @belisarius chooses to move his answer here.

-