Hello,
I am plotting a series of different devices and their signal response responses as a function of time. I wish to pull from each smoother plot the time value once the plot crosses a value, say 3100. The scatter data is too coarse to get the time at which this occurs however if there is a function behind the smoother fit for each device then this information should be available.
Does anyone know if this is possible and if so how to get this done?
JMP does give the functions Spline Coef() and Spline Eval(). You can use Spline Coef() to get the spline parameters, then evaluate that spline at any desired point. You could easily use this with Newtons' method to determine when each spline crosses some value (say 3100).
Just beware that you'll want to normalize the x-data (zero mean, std-dev = 1) before this so that the spline lambda can match what you'd normally expect.
Here is an example that I just threw together that I believe does what you're asking:
Names Default to Here( 1 );
determine crossover = Function( {table, value, spline lambda, x col, y col, group, precision = 0.1},
{Default Local},
spline number = 64;
max runs = 10;
rows = table << Get Rows Where( Excluded( Row State() ) == 0 );
groups = Associative Array( Column( table, group )[rows] ) << Get Keys;
curves = [=>];
For( i = 1, i <= N Items( groups ), i++,
item = groups[i];
Eval( Parse( Eval Insert( JSL Quote(
rows = table << Get Rows Where( Excluded( Row State() ) == 0 & :Name("^group^") == "^item^" )
) ) ) );
curves[item] = [=>];
curves[item]["rows"] = rows;
curves[item]["abcissa"] = Column( table, x col )[rows];
curves[item]["ordinate"] = Column( table, y col )[rows];
curves[item]["abcissa mean"] = Mean( curves[item]["abcissa"] );
curves[item]["abcissa stddev"] = Std Dev( curves[item]["abcissa"] );
If( curves[item]["abcissa stddev"] == 0, curves[item]["abcissa"] = 1 );
curves[item]["abcissa"] = (curves[item]["abcissa"] - curves[item]["abcissa mean"]) / curves[item]["abcissa stddev"];
first = Min( curves[item]["abcissa"] );
last = Max( curves[item]["abcissa"] );
curves[item]["crossover abcissa"] = .;
curves[item]["crossover ordinate"] = -1932870987120;
run = 1;
While( Abs( value - curves[item]["crossover ordinate"] ) > precision * value & run <= max runs,
run++;
points = first :: last :: (last - first) / spline number;
coef = Spline Coef( curves[item]["abcissa"], curves[item]["ordinate"], spline lambda );
spline = Spline Eval(
points,
coef
);
For( j = 1, j <= spline number, j++,
If( spline[j] > value,
first = If( j == 1, first, points[j - 1] );
last = points[j];
Break();
,
If( Abs( value - spline[j] ) < Abs( value - curves[item]["crossover ordinate"] ),
curves[item]["crossover abcissa"] = points[j] * curves[item]["abcissa stddev"] + curves[item]["abcissa mean"];
curves[item]["crossover ordinate"] = spline[j];
)
)
);
If( first == last, Break() );
);
first = Min( curves[item]["abcissa"] );
last = Max( curves[item]["abcissa"] );
points = first :: last :: (last - first) / spline number;
curves[item]["spline ordniate"] = Spline Eval(
points,
coef
);
curves[item]["spline abcissa"] = points * curves[item]["abcissa stddev"] + curves[item]["abcissa mean"];
curves[item]["abcissa"] = curves[item]["abcissa"] * curves[item]["abcissa stddev"] + curves[item]["abcissa mean"];
);
curves
);
dt = Open("$SAMPLE_DATA/Nonlinear Examples/Algae Mitscherlich.jmp");
lambda = 1;
Current Data Table( dt );
gb = Graph Builder(
Size( 516, 450 ),
Show Control Panel( 0 ),
Variables( X( :Days ), Y( :Algae density ), Overlay( :Treatment ) ),
Elements( Points( X, Y, Legend( 18 ) ), Smoother( X, Y, Legend( 19 ), Lambda( lambda ) ) ),
SendToReport(
Dispatch(
{},
"Algae density",
ScaleBox,
{Add Ref Line( 3, "Solid", "Black", "", 1 )}
)
)
);
curves = determine crossover( dt, 3, lambda, "Days", "Algae density", "Treatment", 0.001 );
gbr = Report( gb );
dt << Color or Mark by Column( :Treatment );
{y min, y max} = Eval List( {gbr[Axis Box( 2 )] << Get Min, gbr[Axis Box( 2 )] << Get Max} );
key = curves << First;
While( !Is Empty( key ),
Print( Eval List( {key, curves[key]["crossover abcissa"], curves[key]["crossover ordinate"]} ) );
color = Color Of( Row State( curves[key]["rows"][1] ) );
Eval( Eval Expr(
gbr[Frame Box( 1 )] << Add Graphics Script(
Pen Color( Expr( color ) );
Pen Size( 2 );
Line( {Expr( curves[key]["crossover abcissa"] ), Expr( y min )}, {Expr( curves[key]["crossover abcissa"] ), Expr( y max )} )
)
) );
key = curves << Next( key )
)
The Functional Data Explorer in JMP Pro provides a lot of tools for working with functions, profiles, and curves.