Hello,
I have been creating an application that involves the user to select columns to use in building a model, for select PQAs, through the use of modal windows, as in the attached JMP file with the toy data and script titled "Model for Select PQAs and Columns".
This model is supposed to create custom output for each PQA selected for any dataset with any spelling of column names. Which the script is run, a pop-up comes up asking the user to select specific columns. This window is shown in the figure below:
The next window asks the user to set the PQAs, storage condition, and asks if the user wants to view the subset dataset for each PQA - storage condition or not. That is, for each PQA selected, a subset dataset is created in the background. Then, model and graph results are produced and then appended at each iteration of the for loop to a window with the customized and formatted data (with the LSL and USL y-axis lines and y-axis labels with measurements).
Here is the JSL script code that produces the output given the user input from the windows mentioned above:
//select the data in the original data table
Names Default To Here( 1 );
dt = Current Data Table();
//get the unique PQAs
col9 = Column(dt, "PQA");
unique_pqa = Associative Array( col9 ) << get keys;
/////////////////////////////////////////////////////////////
//User Selection Menu(s)
/////////////////////////////////////////////////////////////
//Part 1: ask user for column names in a new window nw1
//possible Group column name (should be character)
character_col_names = dt << Get Column names(character, String);
//possible result column name (should be numeric)
numeric_col_names = dt << Get Column names(Numeric, String);
nw1 = New Window("Column names",
<<Modal,
Text Box ("select the column with the results"),
result_col = Radio Box(numeric_col_names),
Text Box ("select the column with the time interval"),
time_col = Radio Box(numeric_col_names),
Text Box ("select the column with the group of interest, such as the batches/lots or the mfg group"),
groupby_col = Radio Box(character_col_names),
Text Box (" select the column with the measurement units"),
units_col = Radio Box(character_col_names),
Text Box (" select the column with the storage conditions units"),
storage_condition_col = Radio Box(character_col_names),
Text Box ("Note that it is assumed that the Product Quality Attribute column is named 'PQA'"),
H List Box(
Button Box("OK",
answers = Eval List(
{
set_resultcol = result_col << get selected,
set_time = time_col << get selected,
set_groupby = groupby_col << get selected,
set_units_col = units_col << get selected,
set_storage_condition_col = storage_condition_col << get selected
}
);
nw1 << close window;
),
Button Box("Cancel")
),
//change popup window size
<<Size Window(500,700)
);
// If cancel or red X was clicked, stop the script
If( nw1 == {Button( -1 )}, Stop() );
//Part 2: Select PQA(s), storage condition, and other options.
//Get the unique storage conditions
col_stor_cond = Column(dt, set_storage_condition_col);
unique_stor_cond = Associative Array(col_stor_cond) << get keys;
invisible_window_options = {"invisible", "visible"};
nw2 = New Window( "Select PQAs",
<<Modal,
Text Box("Set PQA(s):"),
variablebox1_pqa = Check Box( unique_pqa ),
H List Box(
variablebox1_pqa_all = Check Box(
" ",
<<SetFunction(
function({this},
variablebox1_pqa << Set All( this << Get, run script( 1 ) )
)
)
),
Text Box(
"Select All PQAs",
<<Set Width( 90 ),
<<Set Wrap( 90 )
)
),
Text Box("Set Storage Condition:"),
variablebox2_stor_cond = Radio Box( unique_stor_cond ),
Text Box( "Do you want the subset dataset to be visible?"),
variablebox1_subset_visibility = Radio Box( invisible_window_options ),
H List Box(
//get all saved variable values when the user
//selects the OK button from the menu
Button Box( "OK",
answers = Eval List({
selected_pqa = variablebox1_pqa << get selected,
selected_stor_cond = variablebox2_stor_cond << get selected,
selected_visibility = variablebox1_subset_visibility << get selected
});
nw << close window;
),
Button Box( "Cancel")
),
//change popup window size
<<Size Window(600,600)
);
// If cancel or red X was clicked, stop the script
If( nw2 == {Button( -1 )}, Stop() );
/////////////////////////////////////////////////////////////
//Production of Output
/////////////////////////////////////////////////////////////
//initialize a jmp report window
nw= New Window("JMP report results for each PQA",
container = V List Box()
);
For( i = 1, i <= N Items( selected_pqa ), i++,
//select the data in the original data table (the current data table in this case,
//that the user clicks this script from)
//with the user selected PQA and Storage Condition
content = V List Box(
pqa_val = selected_pqa[i];
dt << Select Where(:PQA == pqa_val & column(dt, set_storage_condition_col) == selected_stor_cond);
//subset the selected data, into a new dataset with
//the columns selected that are specified below,
//either character (char) or numeric (num) data types:
// - variable effect 1 (i.e. process) (char)
// - formulation of the drug (char)
// - manufacturing site of the drug (char)
// - the lot number or batch number (char)
// - the storage condition (char)
// - interval (num)
// - result (num)
// - measurement units (char)
listDT = if(selected_visibility == "invisible",
dt << Subset(
invisible,
Selected rows only( 1 ),
Selected columns only( 1 ),
columns(
:PQA,
column(dt, set_storage_condition_col),
column(dt, set_resultcol),
column(dt, set_groupby),
column(dt, set_units_col),
column(dt, set_time),
:LSL,
:USL
)),
dt << Subset(
//invisible,
Selected rows only( 1 ),
Selected columns only( 1 ),
columns(
:PQA,
//set_storage_condition_col,
column(dt, set_storage_condition_col),
//set_resultcol,
column(dt, set_resultcol),
//set_groupby,
column(dt, set_groupby),
column(dt, set_units_col),
//set_units_col,
column(dt, set_time),
//set_time,
:LSL,
:USL
)
)
);
/*************************Model Fit Section***************************/
/*
This file is used to generate the Fixed model of result of a PQA vs. time interval,
grouped by storage condition for assessing stability of the PQA.
It has no interaction and no lot number.
**********************************************************************
PROCEDURE
1. Define the variables to be used in the fit model
- maxinterval
- units
- max_result
- min_result
- get_minimum_val
- get_maximum_val
2. Fit the model with requested/wanted output options selected, such as:
- Summary of Fit
- Analysis of Variance
- Plot Actual by Predicted
- Plot Residual by Predicted
- Plot Studentized Residuals
- Plot Residual by Normal Quantiles
- Show All Confidence Intervals
3. Modify the presentation settings.
- generalize spec limits on plot
- rename y-axis label
- rescale y-axis and x-axis
NOTES:
- using the user selected input from above, variables:
- selected_pqa
- selected_stor_cond
- selected_lsl
- selected_usl
******************************************************************
*/
/*************** Variable lists of selected rows. ****************/
/*
- Selected the provided time Interval column in the
data table.
- Saved the column as col3
- Defined the max interval as the column maximum form the
col3 saved above.
*/
col3 = column(listDT, set_time);
maxinterval = col max(col3);
/*
- Selected the provided Measurement Units in the
data table.
- Saved the first values from each of the columns mentioned
as col4.
*/
col4 = Column( listDT, set_units_col);
units = col4[1];
// if units not null, concateninate with parentheses within the script. Else, do not concatenate.
// save the results of this if else statement as a string to variable called units_formatted.
// this should be after the units value is created in a line above.
// NOTE: switched the conditions around for the algorithm to work.
units_formatted = If(Is Missing(units), "", Is String(units), " (" || units || ") ");
//get the spec limits
selected_lsl = :LSL[1];
selected_usl = :USL[1];
/*
- Selected the Result colum, stored in col7
- Saved the column max and the column min
of the whole column, in max_result and min_result, respectively
- Compare the min and max results to the lower and upper spec limits
respectively.
*/
col7 = Column( listDT, set_resultcol);
max_result = col max(col7);
min_result = col min(col7);
get_minimum_val = Minimum(min_result, selected_lsl);
get_maximum_val = Maximum(max_result, selected_usl);
//set the significance level based on the number of spec limits present
alpha_level_a = If(!Is Missing(selected_lsl) & !Is Missing(selected_usl), 0.05, 0.1);
/*Fit full mixed model*/
listDT << Fit Model(
Y( Column( listDT, set_resultcol) ),
Effects( column(listDT, set_time) ),
Center Polynomials( 0 ),
NoBounds( 1 ),
Personality( "Standard Least Squares" ),
Method( "REML" ),
Emphasis( "Minimal Report" ),
Set Alpha Level(alpha_level_a),
Run(
Profiler(
1,
Confidence Intervals( 1 ),
Term Value( Interval( 2.3333, Lock( 0 ), Show( 1 ) ) )
),
Column( listDT, set_resultcol) << {Summary of Fit( 1 ), Analysis of Variance( 1 ), Parameter Estimates( 0 ),
Indicator parameterization Estimates( 1 ), Scaled Estimates( 0 ),
Plot Actual by Predicted( 1 ), Plot Regression( 1 ), Plot Residual by Predicted( 1 ),
Plot Studentized Residuals( 1 ), Plot Effect Leverage( 0 ), Plot Effect Leverage( 1 ),
Plot Residual by Normal Quantiles( 1 ), Box Cox Y Transformation( 0 ),
Show All Confidence Intervals( 1 )
}
),
Where ( :PQA == pqa_val & column(listDT, set_storage_condition_col) == selected_stor_cond ), // added 4/29/2022 to use in tinkering
//^^ how to retrieve actual values of pqa_val and selected_stor_cond to be in quotes when the script is saved
// see https://www.jmp.com/support/help/zh/15.2/index.shtml#page/jmp/extract-values-from-a-window.shtml
SendToReport(
Dispatch(
{},
"Response " || set_resultcol,
OutlineBox,
{Set Title( "Response " || set_resultcol || " for " || pqa_val )}
),
Dispatch(
{},
// generalize spec limits on plot and scale y-axis
"2",
ScaleBox,
{Min( get_minimum_val - 0.1*get_minimum_val ), Max( get_maximum_val + 0.1*get_maximum_val),
Minor Ticks( 0 ),
Inc( 1 ),
Add Ref Line( selected_lsl, "Dashed", "Medium Dark Red", "LSL (" || char(selected_lsl) || ")", 1 ),
Add Ref Line( selected_usl, "Dashed", "Medium Dark Red", "USL (" || char(selected_usl) || ")", 1 )}
),
// scale x-axis
Dispatch(
{},
"1",
ScaleBox,
{Min(-1), Max(Modulo(maxinterval, 3) + maxinterval + 1)} //, Inc( 3 ), Minor Ticks( 2 )}
),
Dispatch(
{},
"FitLS Regression Plot",
FrameBox,
{Frame Size( 500, 300 ),
Row Legend(
Lot Number,
Color( 1 ),
Color Theme( "JMP Default" ),
Marker( 0 ),
Marker Theme( "" ),
Continuous Scale( 0 ),
Reverse Scale( 0 ),
Excluded Rows( 0 )
)
}
),
// rename y-axis of plots
//prediction profiler
Dispatch(
{"Response Result", "Prediction Profiler"},
"Result",
TextEditBox,
{Set Text( pqa_val || units_formatted )}
),
//actual by predicted plot
Dispatch(
{"Response Result", "Actual by Predicted Plot"},
"Result Actual",
TextEditBox,
{Set Text( pqa_val || units_formatted || " Actual Result" )}
),
//residual by predicted plot
Dispatch(
{"Response Result", "Residual by Predicted Plot"},
"Result Residual",
TextEditBox,
{Set Text( pqa_val || units_formatted || " Result Residual" )}
),
//regression plot (if applicable)
Dispatch(
{"Response Result", "Regression Plot"},
"Result",
TextEditBox,
{Set Text( pqa_val || units_formatted )}
),
Dispatch(
{},
"Effect Tests",
OutlineBox,
{Close( 0 )}
)
)
)
); //this belongs to v list box on line 174.
//append each output into the initialized nw window above.
container << Append(content)
); //this belongs to for loop on line 170.
With my output window created, I want to be able to save the script to the original data table with all data in it (that the subset data is dependent on). However, when I save the scripts for all output to script window, I get the following results:
Notice the
Where ( :PQA == pqa_val & column(listDT, set_storage_condition_col) == selected_stor_cond )
statement does not allow the script to work.
I want this statement in this script to have the particular output. For example, in the toy dataset I have attached, the
column(listDT, set_storage_condition_col)
is equal to :Storage Condition
Additionally, if I were to select A as the pqa_val
( so that :PQA == "A"
) and 5C as the selected_stor_cond
(so that :Storage Condition == "5C"
).
However, the output script produced would not be existent, even though I am referring to the user input. Why isn't JMP writing these values as in this example above into the script for each particular instance in the loop?