Subscribe Bookmark
Craige_Hales

Staff

Joined:

Mar 21, 2013

Animated GIF JMP 13

More on JMP 13:  Preview JMP 13 | JMP​    and   Announcing JMP 13, live from Discovery Summit | JMP

john.ponte​ added some animated GIF capability to JMP 13 on Windows,

Save a Bubble Plot animation as an animated GIF​​

Save a Data Filter animation as an animated GIF

Here's another example.

Almost every browser less than 100 years old supports animated GIFs.  JMP 13 has support for building them.  The attached JSL shows one way to capture the bitmaps from a graph's frame (no axes, no title) and store them in the animated GIF.

Every frame in the animation can have its own duration; generally all frames should have the same duration.  The number of loops can be specified.  As you can see, looping forever gets annoying.  Loops can only play in one direction.  If you see a GIF that appears to reverse, or bounce, it is because the one directional loop has frames that go forwards and backwards.  The loop above is for a single sin wave (not the three periods it appears to be).  Even so, it is a moderately large file: 19 frames in 130K bytes.

The following should be the same as the attachment.  You can see how the loop in the last 1/3 of the script is changing the data in the data table to manipulate the graph builder output, then taking a picture.  The middle 1/3 is setting up graph builder and probably did not need to be that complicated since the image was taken from inside the frame and ignores the axes and labels.  The first bit is a set of parameters you can play with.  The last line attempts to open the graph.

// This script requires Windows JMP 13, which can save animated gif files. 

// Unfortunately the Mac version of JMP doesn't support this GIF feature yet.

nBars = 50; // how many animating bars?

xsize=800; // picture dimensions

ysize=100;

nFrames = 19; // how many frames in loop

frameMS = 1000/24; // duration of frame in 1/1000 of a second (1000/24 == 24 FPS)

periods=3; // must be an integer for smooth animation loop

targetFile = "$desktop/DeleteMeAnimated.gif";

// make a data table template for the animation

dt = New Table( "animate", addrows(nBars), New Column( "ID", formula(row()) ), New Column( "Value", formula(sin(2*pi()*row()/nBars)) ) );

dt<<runformulas; dt:Value<<deleteformula; // remove the formula.  non-missing initial data is needed for graph builder

// make a placeholder graph.  NOTE: use interactive Graph Builder to make the graph, and

// use Save Script to make this JSL!  Do minor edits later.

gb = dt<<Graph Builder(

    Size( xsize, ysize ), Show Control Panel( 0 ), Show Legend( 0 ), Show Footer( 0 ), Lock Scales( 1 ),

    Variables( X( :ID ), Y( :Value ), Color( :Value ) ), Elements( Bar( X, Y, Legend( 9 ) ) ),

    SendToReport( Dispatch( {}, "ID", ScaleBox,

            {Min( 0 ), Max( nBars+1 ), Inc( 2 ), Minor Ticks( 1 ), Label Row(

                {Automatic Font Size( 0 ), Automatic Tick Marks( 0 ), Show Major Labels( 0 ), Show Major Ticks( 0 ), Show Minor Ticks( 0 )}

            )} ),

        Dispatch( {}, "Value", ScaleBox,

            {Min( -1.092929 ), Max( 1.10606060606061 ), Inc( 0.5 ), Minor Ticks( 1 ), Label Row(

                {Automatic Font Size( 0 ), Automatic Tick Marks( 0 ), Show Major Labels( 0 ), Show Major Ticks( 0 ), Show Minor Ticks( 0 )}

            )} ),

        Dispatch( {}, "400", ScaleBox, {Legend Model( 9, Properties( 0,

                    {gradient( {Color Theme( "Green to Black to Red" ), Scale Values( [-1 1] ), Label Format( "Fixed Dec", 15, 1 ),

                        Reverse Gradient( 1 ), N Labels( 5 )}

                    )} ) )} ),

        Dispatch( {}, "graph title", TextEditBox, {Set Text( "" )} ),

        Dispatch( {}, "X title", TextEditBox, {Set Text( "" )} ),

        Dispatch( {}, "Y title", TextEditBox, {Set Text( "" )} )

    )

);

// make the frame box the exact size needed; later

// the <<crop will make it xsize by ysize and remove the

// unwanted border line

(report(gb)[framebox(1)])<<framesize(xsize+2,ysize+2);

wait(0); // make sure the graph is visible.  Not required, but shows progress.

For( iFrame = 1, iFrame <= nFrames, iFrame++,

    frameFraction = iFrame / (periods*nFrames);

  // makes the bars all out of phase

    For( iPhase = 1, iPhase <= nBars, iPhase++,

        phaseFraction = iPhase / nBars;

        dt:Value[iPhase] = Sin( periods * (frameFraction * 2 * Pi() + phaseFraction * 2 * Pi()) );

    );

  // the bars have new heights; take a picture

    gb << updatewindow;

    img = ( report(gb)[framebox( 1 )] )<<getimage;

    fullsize = img<<size;

    // crop the 3 pixel border and the border line.  A little trial-and-error...

    img<<crop( left(3), top(3), right(fullsize[1]-3), bottom(fullsize[2]-3));

    //newsize=img<<size; // figuring out the size and crop

    //show(fullsize,newsize); // parameters

    if ( iFrame == 1,

        finalImage = img; // start the animated gif with the first image

    , // else

        finalImage<<addFrame; // add frames for subsequent images and set the new frame's

        finalImage<<setPixels(img<<getPixels); // pixel data from the current image data.

    );

    finalImage<<setFrameDuration(frameMS); // set the duration for each frame

);

gb<<closewindow;

close(dt,nosave);

finalImage<<saveImage( targetFile,"gif");

show(filesize(targetFile));

open(targetFile); // demo in a browser, maybe.



1 Comment
Community Member

Nice Craige!  Thanks!  Can't wait to get JMP 13.

Article Tags