Group Abstract Group Abstract

Message Boards Message Boards

0
|
614 Views
|
4 Replies
|
6 Total Likes
View groups...
Share
Share this post:

Slide show preparation and presentation tips

I think these are easy questions for an experienced presenter.

  1. What are best hookup choices when using a single-screen Windows laptop to control a presentation on a classroom screen projection system that accepts both HDMI and WiFi remote display?
  2. What’s best practice for controlling a slide show on the Window laptop single display? Can the palette be concealed from the projected display. Do combination laser pointers and remote PowerPoint page turners work with Mathematica slide presentations?
  3. How is dynamic content best managed so that it animates smoothly when it is that slide’s turn and does not lock up the computer at any time during the presentation. This is the most important and most complicated of these questions. It involves options within dynamic content, options in the notebook and initializing function definitions. It may even involve things that should be done during a presentation.
  4. Related to no. 3, what is the difference in the meaning of the thick black line on dynamic content cells? Sometimes it’s not there when animation is animating and sometimes it is there when the animation is idle and the notebook is not running.
  5. In the Classic Slide Show palette, all resolution options are ¾ aspect ratio. Is there a best choice? What’s the best way to make maximum use of available display area? How is ImageSize->Full handled in dynamic content? Is there some ugly skewing or cropping that can results when a projector has a different aspect ratio from the presenter computer running Mathematica?
  6. Are there predictable pitfalls to avoid?
POSTED BY: Jay Gourley
4 Replies

º4. The cell bracket is highlighted when the Front End is waiting for the Kernel to finish a dynamic update. For instance:

Manipulate[
 If[TrueQ[y > 0],
  y = Sin[y],
  y = 1.];
 a,
 {a, 0, 1}
 ]

Because y is changed at each update, the updates continue indefinitely. It appears in the Front End that Manipulate[] is doing nothing, since the new value of y does not affect the output.

How to fix it? That's depends on the code. Adding the option TrackedSymbols :> {a} will fix this case. So does localizing y in a Module[] inside Manipulate[]. So does removing the If[] statement. In cases where this actually arises, localizing y defeats the purpose of remembering the value of y from update to update (should that be the purpose); and removing the code is usually not possible, either.


A more complicated example:

Updates indefinitely because data is changed:

Manipulate[
 SeedRandom[a];
 data = RandomReal[10, 100]; (* Mathematica treats Random*[] specially *)
 data = Sort@data^2; (* this causes the repeated updates *)
 lm = LinearModelFit[data, x, x];
 Show[
  ListPlot[data],
  Plot[lm[x], {x, 1, 100}],
  PlotRange -> {-21, 121}
  ],
 {a, 0, 1000, 1}
 ]

Minimal fix:

Manipulate[
 SeedRandom[a];
 data = Sort@RandomReal[10, 100]^2; (* data not trigger new update *)
 lm = LinearModelFit[data, x, x];  (* depends on data which does not need an update *)
 Show[
  ListPlot[data],
  Plot[lm[x], {x, 1, 100}],
  PlotRange -> {-21, 121}
  ],
 {a, 0, 1000, 1}
 ]

My better method (localized assuming I don't need to evaluate data or lm outside of Manipulate[]):

Manipulate[
 SeedRandom[a];
 With[{data = Sort@RandomReal[10, 100]^2},
  With[{lm = LinearModelFit[data, {x, x^2}, x]},
   Show[
    ListPlot[data],
    Plot[lm[x], {x, 1, 100}, PlotStyle -> Gray],
    PlotRange -> {-5, 105}
    ]
   ]],
 {a, 0, 1000, 1}
 ]

My preferred method (the extra dynamic means that data and lm won't be recomputed when the system changes $ControlActiveSetting from True to False when I let go of the a slider; only the plot needs updating when that happens):

Manipulate[
 SeedRandom[a];
 With[{data = Sort@RandomReal[10, 100]^2},
  With[{lm = LinearModelFit[data, {x, x^2}, x]},
   Dynamic@
    Show[
     ListPlot[data],
     Plot[lm[x], {x, 1, 100}, PlotStyle -> Gray],
     PlotRange -> {-5, 105}
     ]
   ]],
 {a, 0, 1000, 1}
 ]

If I need to use Dynamic[]/Manipulate[] to set a global variable such as data or lm, then I would use TrackedSymbols to expressly set the dynamic updating dependencies.

POSTED BY: Michael Rogers
Posted 27 days ago

Thanks, Michael Rogers. As an unsophisticated user, I appreciate the examples and simplicity of your explanation. You even wrapped y > 0 in TrueQ[].

From your explanation, I expected continuous updating on the first example that iterates through Sin[] but did not see that. The cell bracket was not emphasized, and Windows Task Manager didn't show Mathematica doing much work.

I like your preferred method. I don’t have much need to set a global variable inside a Manipulate. If I needed a result outside the Manipulate, I would define the function there and invoke it inside the Manipulate.

I haven’t used With[] much, but from its documentation, it looks like Module[] accomplishes the same thing. I'm more familiar with Module[]. In fact, I didn’t immediately notice anything With[] does that Module[] doesn’t do. You helped me understand the difference between With[] and Assuming[] in an earlier thread.

If you would, I’d appreciate you expanding on the role of Dynamic[] in the last example. That might explain something that’s still not clear to me. Namely, how does activating the animation internal to Manipulate[] affect the things you said about avoiding unneeded updating.

POSTED BY: Jay Gourley

Hi Jay,

Try the first example again. Somehow I changed a comma to a semicolon in my original post. I've changed it back now.

In With[{x = expr}, body], no variable x is created. Instead each symbol x that literally appears in the code body is replaced by the value of expr. (If some part of the code in body evaluates to the symbol x, that part will not be replaced by the value of expr.) After the replacement, body is evaluated, which explains the parenthesis. The code With[{x = expr}, body] is similar to Function[{x}, body][expr].

In Module[{x = expr}, body], a variable x$nnn is created, where nnn is the current $ModuleNumber Each symbol x that literally appears in the code body is replaced by the symbol x$nnn. (Like With[], if some part of the code in body evaluates to the symbol x, that part will not be replaced by the value of expr.) After the replacement, body is evaluated, and the module variable x$nnn will be evaluated or changed according to the code in body. After the Module[] is finished, the variable x$nnn will be removed by the system unless there is a reference to it, in which case the variables and its definition (value) will be preserved. This can happen if the symbol x$nnn is saved in a global variable or in the output of the Module[].

Examples: These are modified from an example in the documentation. It is a typical use of With[] with Dynamic[] to inject the current value of a variable into Dynamic[]. Since Dynamic[expr] does not allow expr to be evaluated (in the kernel), the only ways to inject the value at the time of execution in the kernel is with With[] or Function[]; otherwise, the value used will be whatever it is when the front end performs a dynamic update, which might be in a completely different kernel session years from now.

Remove["j*"]; (* clean out variables that start with j *)
a = Range[5];
"D" -> Table[Dynamic[a[[i]]], {i, Length@a}]
"M" -> Table[Module[{j = i}, Dynamic[a[[j]]]], {i, Length@a}]
"W" -> Table[With[{j = i}, Dynamic[a[[j]]]], {i, Length@a}]
Names["j*"] (* Module variables that leaked out *)
Clear["j*"] (* clear Module variables that leaked out *)
a[[-1]] = 1000;
 (* try with & without the last two lines (all combos) *)

If you omit Clear["j*"], Module[] seems to work. But it's a ruse, as Clear["j*"] demonstrates.

I'm thinking about your other question. Dynamic[] is complicated and explaining it is complicated. For a thorough understanding, you pretty much have to bite the bullet and read the four lengthy tech notes on Dynamic[] and Manipulate[] linked in docs for Manipulate[]. For me, that was only a start. It's also not necessary to understand things thoroughly. Good rules of thumb are: If Dynamic[] demos work well enough, we don't need to make them work optimally. And the simpler they are, the easier they will be to fix...probably.

POSTED BY: Michael Rogers

Suppose we have a CompoundExpression[] consisting of a sequence of expressions a1[A]; b1[A,B], which we separate into two code blocks a1[A] and b1[A,B] with the following properties:

  • a1[A] depends on only the variable A appears and not the variable B.
  • b1[A, B] depends on the variable B and the variable A.

The dependency imagined is that the values computed in b1[A,B] depend on the values computed in a1[A], and the values in a1[A] need to be recomputed only if A changes. Thus if A changes, then both a1[A] and b1[A,B] need to be executed. If B changes, then only b1[A,B] needs to be executed.

Let's consider what happens when we wrap a code block in Dynamic[]. This does two things: It restructures the expression, and it changes how and when the block will be evaluated. The first is important for understanding the second. I may be biased by my upbringing to think in code blocks. It's better to think in terms of expression trees in WL, and the addition of Dynamic[] in a1[A]; Dynamic[b1[A,B]] creates a new subtree inside the outer CompoundExpression[].

In the problem at hand, the last Manipulate[]in my first post, the initialization code a1[A] is nested in With[] statements, rather than in a CompundExpression[]. This difference is not important to how the interior Dynamic[] functions. Note that when a Manipulate[body,...] is instantiated in the front end, the body is wrapped in Dynamic[]. So the question is about adding a Dynamic[] inside an outer Dynamic[].

Manipulate[
 With[{x = a^2},(* a1[A]; A=a *)
  Pause[1];  (* expensive step *)
  Dynamic[x + b] (* b1[A,B]; B=b *)
  ],
 {a, 0, 1}, {b, 0, 1}]

enter image description here

Wrapping code in Dynamic[] creates a subtree that may be reevaluated independently, when dynamic updating and dependencies allow it. Because Dynamic[] is HoldFirst, it prevents the code block from being evaluated immediately, about which I will say more in the paragraph following the next one.

For now, observe how the Manipulate[] example above behaves. It is expensive (time-wise) to update after changes in a, but inexpensive to update after changes in b. The extra Dynamic[] allows the part that depends on b (gold-ish subtree) to be updated independently of the part that depends only on a (blue-ish components). When a changes, the change causes the With subtree, comprising the blue and gold components, to be reevaluated; the new value substituted for x then triggers an update of the contents of the gold Dynamic[], and x+b is evaluated (and displayed).

Note that when Dynamic[expr] is "evaluated" -- specifically, when it is evaluated by the kernel -- essentially nothing happens. It evaluates to the expression Dynamic[expr]. The argument expr is not evaluated because Dynamic[] has the attribute HoldFirst and does not itself evaluate expr. The functionality of Dynamic[expr] comes about only when such a dynamic expression is displayed in a notebook. The front end is responsible for when to evaluate (or update) and display expr.

For instance, wrapping the both blocks in Dynamic[], as in Dynamic[a1[A]]; Dynamic[b1[A,B]], destroys the functionality, because in evaluating the expression, the Dynamic[a1[A]] is evaluated, which does nothing, then Dynamic[b1[A,B]] is evaluated, which does nothing but is the value of theCompoundExpression[]. The expression Dynamic[a1[A]] is forgotten; if the Dynamic[b1[A,B]] is displayed, the front end will evaluate b1[A,B]. Since a1[A] is never evaluated, b1[A,B] will be evaluated without the initialization performed by a1[A] ever being done.

Clear[x];
Manipulate[ (* x is set when a changes *)
 x = a; Pause[1];(* a1[A]; A={a,x} *)
 Dynamic[x + b],(* b1[A,B]; B=b; x depends on A *)
 {a, 0, 1}, {b, 0, 1}]

enter image description here

Clear[y];
Manipulate[ (* y not set when a changes *)
 Dynamic[ (* a1[A] never evaluated, never displayed *)
  y = a; Pause[1]];
 Dynamic[y + b], (* Dynamic[b1[A,B]] is the value displayed *)
 {a, 0, 1}, {b, 0, 1}]

enter image description here

The left, gold subtree in the second "y" Manipulate[] has no effect on the operation of Manipulate[].

I don't know if that helps with your question about animation and unneeded updating, but I'll reiterate: If the unneeded updating takes a negligible amount of time, then it's probably best and simplest not to try to avoid it.

POSTED BY: Michael Rogers
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard