Choose Language Hide Translation Bar
Saving a list of control charts as graphic files

The goal here is to save a series of control charts (or any other report) as graphics file that can be used somewhere else.

For example, I have a PowerPoint slide deck with 10 control charts in it. Every Monday I need to update the control charts in the slide deck. I could make the charts in JMP and then copy and paste them into the deck each week, or I could take advantage of the Insert and link function available in most MS products. 


Screen Shot 2016-12-08 at 11.03.49 AM.png



To do this I could make the control chart, save it as figure1.png, then open PowerPoint where I would insert the picture using the "insert and link" option (little down arrow on the Insert button). I would do this for each of the 10 slides.   Next week I would just make each control chart, and save each one to a graphic file (i.e. figure1.png, figure2.png...).  Then when I open the slide deck in PowerPoint, the new version of figure1.png etc, would get pulled into the deck.


Sounds tedious?  Yes, that would be horrible, it would be easier to just save all 10 charts as a PowerPoint file in JMP and copy and paste the graphs in. However!  With a little JSL, this all gets really easy and I'm going to show you how. 


Before we get started, lets look at a simple script to make a control chart and understand whats going on:


Control ChartGroup Size( 1 ), Chart Col( :Metric 1, Individual Measurement ))


Lets peel this apart:

The outer most layer is Control Chart(), and inside that layer there are two parts, Group Size(1), and Chart Col().

Each of the elements have arguments, for example Group Size has one argument, "1". Chart Col() has two arguments. The first one is a column reference and the type of control chart to make with that column. Conceptually there are layers of functions, and one way to script is to build your "onion" from the inside out.


There are probably 100 and 1 ways to write this script, and some might be easier and less verbose that what I'm going to do here. The approach I'm using here tends to work with nearly every platform in JMP, but it requires a little different way of thinking about scripting... scripting from the inside out.


1. alist={};  this is where I'm supplying a list of column names I want to make control charts from. A more complex example might have a dialog that is used to generate the list, or maybe logic filter to pick continuous columns from a table, but that's for another blog post.


2. a=expr();  Here I'm just taking each of the functions used in the control chart and defining them but leaving them empty.

a=expr(control chart()); gives me a place to put arguments.  b=expr(group size(1)); is one element I'm going to insert into Control chart( ), and c=expr(chart col(...  is also going to be inserted into "a".   The "expr( )" function is important to understand. What ever is inside there doesn't get evaluated, isn't "read" and made to be something.  For example if   Speak( "Hello" ); were in your script, JMP would say "hello", but if s=expr(Speak( "Hello" )); were in your script, nothing would happen until you evaluated "s" or explicitly scripted, eval(s).  (more to the point, if "s;" were on one line of your code, JMP would evaluate it, and say "hello"). Here I'm using expr( ) to hold onto  parts I want to use later.


3. Insert into (c, alist[i],1); Here, "c" is an unevaluated argument, chartcol( individual measurement). Insert into, inserts the first thing in the list variable "alist" into the contents of "c". So now c is chartcol(:Metric 1, individual measurement). 

This is a good place to take a step back and explain where the "i" in "alist[i]" came from.  

     For (i=1, i<=nitems(alist), i++  is the beginning of a For Next Loop, or For this set of conditions, keep doing this until the condition isn't true. So, i=1, and while i is less than or equal to the number of things in "alist", do the next thing. The variable "i" is increased by one in each loop, and we can use this counter variable for other things in the loop.  In the first loop, i=1, so we use it to get the first thing in "alist" by saying "alist, subscript, i". Later in the script we are going to use i in name of the file we save.  I want a serial list of file names (figure1, figure2, figure3...)  To get this I concatenate the prefix with I. Except there is a problem, we can't concatenate a number, so we have to say "path/figure"||char(i)||".png"  the numeric i has to be wrapped in char( ), then as a character, it can be concatenated with other characters. (things wrapped in quotes.)


4. obj=eval(a);  at this point in the script the control chart() function has been packed will all the arguments I need and its time to evaluate it. Note that "obj", a variable, can be used as a "handle" to talk to the control chart that was just generated. 


5. obj<<save picure(...   this last step save the contents of obj as a ,png picture file.    note that the file name has a .png extension, and then right after the file name, the next argument is "png".  This means that its possible to save a file with a .gif extension but as a .png file type. I highly recommend not mismatching the extension and file type.


6. obj<<close window;  This is just clean up. If you wanted to see the JMP reports that you made, then this would be commented out.


7. The final bit is ");"  this is the closing parenthesis for the beginning For(.   In practice, when you're coding, its a good idea to leave yourself a comment at the close of the loop, some thing like  "//end of i loop"  This is especially important if you happen to be iterating inside of other loops, it helps to keep things from getting loopy.



alist={:Metric  1, :Metric  2, :Metric  3};
for(i=1, i<=nitems(alist), i++,	
	a=expr(control chart());
	b=expr(group size(1));
	c=expr(chart col(individual measurement));
	insert into(c,alist[i],1);
	insert into(a,nameexpr(b));
	insert into(a,nameexpr(c));
	obj<< Save Picture( "/Users/bywing/Byron Wingerd/Examples/example"||char(i)||".png", "png" );
obj<< Close Window; );