8
$\begingroup$

I need to have a few Manipulates in different cells synchronize on a few variables.

I have a report with several Manipulates in different sections showing different views/summaries of the data. Some of the selection variables are common to all Manipulates. When the reader updates one of these common in any of the Manipulates I would like all Manipulates to update the value of that variable and execute (or maybe execute on "MouseMoved" so the CDF doesn't crawl).

Using a Notebook level variable (I have CellContext set to Notebook in Global Preferences) I can see that the sync variable is syncing but I can't seem to get the Manipulates to use it.

sync = 1;

DynamicModule[{d = Range[10]},
 Manipulate[
  Column[{d[[;; j]], sync}],
  {{j, 1}, 1, 10, 1, 
   TrackingFunction -> {(j = sync) &, (j = #) &, (j = #; sync = #) &}}
  ],
 SaveDefinitions -> True
 ]

DynamicModule[{d = Range[10, 100, 10]},
 Manipulate[
  Column[{d[[;; i]], sync}],
  {{i, 1}, 1, 10, 1, 
   TrackingFunction -> {(i = sync) &, (i = #) &, (i = #; sync = #) &}}
  ],
 SaveDefinitions -> True
 ]

There is the new Channel-Based Communication in version 11 that might help but I don't have that installed yet (and it is experimental). I'll take an 10.4.1 or an 11 solution but I need it to work in CDF. Not certain there is Player Pro for version 11 yet.

$\endgroup$
  • $\begingroup$ @Kuba To move the Slider in a Manipulate and have that Manipulate update interactively. When the Slider is released the other Manipulates should get the final value of sync from the Manipulate that was manipulated and then update themselves to that value of sync. $\endgroup$ – Edmund Aug 9 '16 at 17:31
  • $\begingroup$ @Kuba The selected range of d[[;; i]] in the first and d[[;; j]] in the second does not update. If I move the Slider in the first to $6$. Then I want the d[[;; j]] in the second to evaluate d[[;; 6]] when I release the Slider. Likewise if I more the Silder in the second to $3$ then I want the d[[;; i]] in the first to evaluate d[[;; 3]] when I release the Slider. $\endgroup$ – Edmund Aug 9 '16 at 17:38
  • $\begingroup$ @Kuba If I d[[;; sync]] then the Manipulate slider can't access it without localizing it and then it can't be used to sync across cells. $\endgroup$ – Edmund Aug 9 '16 at 17:58
  • $\begingroup$ @Kuba That is not updating the d[[;;i|j]] with that TrackingFunction. $\endgroup$ – Edmund Aug 9 '16 at 18:10
  • $\begingroup$ Any particular reason you need Manipulate? I may be easier to work with Slider etc. directly. $\endgroup$ – Mr.Wizard Aug 9 '16 at 21:09
5
$\begingroup$

Another approach is to localize the context of the CDF and use LocalizeVariables -> False in Manipulate. You have to remember to manually localize controls in the Manipulate that you don't want to share.

SetOptions[EvaluationNotebook[], CellContext -> Notebook]

DynamicModule[{d = Range[10], offset},
 Manipulate[d[[;; j]] + offset,
  {{j, 1}, 1, 10, 1}, {offset, 0, 1},
  LocalizeVariables -> False],
 SaveDefinitions -> True]

DynamicModule[{d = Range[10, 100, 10], offset},
 Manipulate[d[[;; j]] + offset,
  {{j, 1}, 1, 10, 1}, {offset, 0, 1},
  LocalizeVariables -> False],
 SaveDefinitions -> True]

Mathematica graphics

I'm not sure which way will be too much trouble, maintaining the TrackingFunctions (e.g. Kuba's answers) or the scope of variables. Someone on the site once said Manipulate is a beast (in part because it automatically rewrites your code, which is probably why the OP had trouble). The typical advice here when things get complicated is to abandon Manipulate and do it all yourself with DynamicModule[].

$\endgroup$
  • $\begingroup$ This is a good solution as well. I would have to place all my variables I wanted localized in the DynamicModule list. A little easier to maintain for a larger number of syncing variables. Also allows the syncing variable to be the same in all the Manipulates. (+1) $\endgroup$ – Edmund Aug 9 '16 at 21:37
5
$\begingroup$

Since j and i have to be synchronized with sync one can add j = sync; and i = sync; at the beginning of parent Manipulates bodies:

DynamicModule[{d = Range[10]},
   Manipulate[
     j = sync; (*this is triggered when `sync` gets a values from the second M*)
     Column[{d[[;; j]], sync}], 
     {{j, 1}, 1, 10, 1, TrackingFunction -> ((j = sync = #) &)}
   ],
   SaveDefinitions -> True
]

DynamicModule[{d = Range[10, 100, 10]}, 
 Manipulate[
   i = sync; 
    Column[{d[[;; i]], sync}], 
    {{i, 1}, 1, 10, 1, TrackingFunction -> ((i = sync = #) &)}
 ], 
 SaveDefinitions -> True
]
$\endgroup$
  • $\begingroup$ This is works! I just have to tweak the TrackingFunction so sync only updates at the end of manipulating. I'll wait a bit to see what else pops up; just in case. :-) (+1) $\endgroup$ – Edmund Aug 9 '16 at 18:45
  • $\begingroup$ Sure, no hurry, I'm glad it fits your needs :) $\endgroup$ – Kuba Aug 9 '16 at 18:46
  • $\begingroup$ I have decided to go with @MichaelE2 answer as it shares the synced variables across all Manipulates and does not require TrackingFunction. I believe this approach will be easier to manage and maintain. $\endgroup$ – Edmund Aug 11 '16 at 12:06

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.