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.

(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:

Google Finance page for AAPL, with a volume chart and the "Slow Stochastic Oscillator"

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.

I'm in the process of reading, experimenting, and further exploring based on comments on these threads:

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:

Non-uniform 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?

share|improve this question
    
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
add comment

3 Answers 3

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]]]
   }]
 ]

some plots

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.

share|improve this answer
    
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
add comment
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];
  )]
]

enter image description here

share|improve this answer
    
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
show 3 more comments
up vote 0 down vote accepted

@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.

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.