# How can I get precise frame rates in dynamic?

I've been the Spritz sdk in my ios apps, and I love it. For funsies I wanted to see how much less code a mathematica version would take! Using dynamic I get a nice result, shown below in code.

However, I'm not so sure about the accuracy of the reading rate that I display (in words per minutes). How can I check and see if it is displaying an accurate frame rate with my usage of Dynamic[]? Also, What should the upper limit of the rate in the slider be calculated?

aliceInWonderlandWords = StringSplit@ExampleData[{"Text","AliceInWonderland"}];
optimalRecognitionPoint[w_String] := With[{len = StringLength[w]},
Which[len==1||len==2, len, len==3, 2, True, Round[len*0.49,1]]
]

$maxLength = 20; flashWord[word_String, maxWordLength_:20] := Module[ {redIndex = optimalRecognitionPoint[word], leftPart, rightPart, chars, row}, leftPart =$maxLength/2-redIndex;
rightPart = \$maxLength-(leftPart+StringLength[word]);
chars = MapIndexed[Style[#1, If[First[#2]==redIndex, Red, Black]]&, Characters@word];
row = ArrayPad[chars, {leftPart, rightPart}," "];
Style[
Dividers -> {(maxWordLength/2+1) -> True,False}, Spacings->{.2,.5}],
FontFamily -> "Monaco", FontSize -> 24 (* This must be a fixed width font! *)
]
];

spritzDemo[words_] := DynamicModule[
{rate = 500/60},
Panel @ Column[{
Row[{Slider[Dynamic[rate], {500/60, 2000/60}, Appearance-> Large,ImageSize->140],
" ", Dynamic[IntegerPart[rate*60]], " words per minute"}," "],
Animate[flashWord[words[[progress]]], {progress, 1, Length[words],1}, AnimationRate -> Dynamic@rate]
}]
]
spritzDemo[aliceInWonderlandWords]


And for bonus points - how could I shorten the code and put the controls into a single panel?

-
Your code does not run on V 9.01, I get error ArrayPad::mlens: Padding amount {10-orp[here ],6+orp[here should be an integer, pair of integers, or list of pairs of integers. screen shot !Mathematica graphics – Nasser Apr 11 '14 at 18:34
@Nasser & @M.R.: orp should be optimalRecognitionPoint? – kglr Apr 11 '14 at 20:37
@kguler I do not know. This is how it showed up on my console: screen shot !Mathematica graphics – Nasser Apr 11 '14 at 20:42
@Nasser, if you change optimalRecognitionPoint to orp you get a working animation. – kglr Apr 11 '14 at 20:44
@Murta's code on Wolfram community should be mentioned here. – bobthechemist Apr 11 '14 at 22:05

This measures frame rate using simple Manipulate that does very little computation other than calculating FPS and then display an image. It finds fps as number of refreshes made so far divided by number of seconds elapsed.

I did not use a moving average here, just kept a record of the number of times Manipulate is called and the time since start. This needs 1-2 seconds to settle down to a stable FPS.

The Manipulate expression runs at full throttle using one control variable tick that updates itself each time Manipulate refreshes. Hence this should run as fast as Dynamics/FE is able to.

You will notice that FPS depends on what is being displayed in Dynamics. Simple text gives about 170 FPS on my system, while 3D images and combination of images, this drops down to 2 fps.

The more image content that needs to be displayed, the smaller FPS becomes.

Feel free to try different content to see its effect.

Manipulate[
tick;
Module[{fps = 0},
If[running,
tick = Not[tick];
nFrame++;
fps = nFrame/(AbsoluteTime[] - startTime)
];
Grid[{
{Row[{"FPS=", fps}]},
{image}
}, Frame -> All, Spacings -> {1, 1}
]
],
Grid[{
{Button["run", {startTime = AbsoluteTime[]; nFrame = 0; running = True;
tick = Not[tick]}],
Button["stop", {running = False; tick = Not[tick]}]
},
{"select display",
image, {startTime = AbsoluteTime[]; nFrame = 0; tick = Not[tick];
running = False; image = #} &], {image1 -> "text",
image2 -> "3D", image3 -> "2D", image4 -> "binary image", image5 -> "combined"}]}
}],

{{tick, False}, None},
{{nFrame, 0}, None},
{{running, False}, None},
{{startTime, 0}, None},
{{currentTime, 0}, None},
{{image, image1}, None},
TrackedSymbols :> {tick},
Initialization :>
{
image1 = Date[];
image2 = Import["ExampleData/CTengine.tiff", "Image3D"];
image3 = Import["ExampleData/lena.tif"];
image4 = Image[CellularAutomaton[30, {{1}, 0}, 40], "Bit"];
image5 = GraphicsGrid[{{image2}, {image3}, {image4}}]
}
]

-
Nice trick. I wish there was a way to force the WPM rate to be exactly true though. – M.R. Apr 12 '14 at 1:56