cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Have your say in shaping JMP's future by participating in the new JMP Wish List Prioritization Survey
Choose Language Hide Translation Bar

How to pull discreet numbers from "smoother" fit from scatter chart

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?device vs time.png

2 REPLIES 2
ErraticAttack
Level VI

Re: How to pull discreet numbers from "smoother" fit from scatter chart

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},
	/*
		Determines the x-value for which each spline crosses a threshold
	table:
	value: 			<number>	threshold value to determine at which point each spline crosses
	spline lambda:	<number>	normalized lambda
	x col:			<string>	x-axis for spline (table column name)
	y col:			<string>	y-value for spline (table column name)
	group:			<string>	name of column holding the categorical by-groups of the splines
	precision = 0.1 <number>	Relative precision to search till (relative to value)
	*/
	{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;
		coef = Spline Coef( curves[item]["abcissa"], curves[item]["ordinate"], spline lambda );
		While( Abs( value - curves[item]["crossover ordinate"] ) > precision * value & run <= max runs,
			run++;
			points = first :: last :: (last - first) / spline number;
			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
);


// example table 
dt = Open("$SAMPLE_DATA/Nonlinear Examples/Algae Mitscherlich.jmp");

// example lamba to use
lambda = 1;
value = 3.7;


// example plot (with lambda from above)
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( value, "Solid", "Black", "", 1 )}
		)
	)
);

// Call the function with the various inputs
curves = determine crossover( dt, value, lambda, "Days", "Algae density", "Treatment", 0.001 );


// Put the lines into the graph to double-check the values
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 )
)

ErraticAttach_0-1650000730777.png

 

 

Jordan

Re: How to pull discreet numbers from "smoother" fit from scatter chart

The Functional Data Explorer in JMP Pro provides a lot of tools for working with functions, profiles, and curves.