cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
lwx228
Level VIII

Can JSL restore the value of the curve?

If already have a given curve, How can use code to restore close to the data.
Set the number of known data, and the maximum and minimum values of data
It seems to have some artificial intelligence function.

 

Thanks Experts!

2021-05-06_21-59-15.png

1 ACCEPTED SOLUTION

Accepted Solutions

Re: Can JSL restore the value of the curve?

By the way, I should mention that if you don't care about averaging over pixels (the line in the graph here is several pixels thick in each column) and are just looking for an approximation, the processing (in this particular example) can be much faster and less cluttered with data tables. As you'll see, the graph you get is basically the same.

names default to here(1);

New Window( "Example",
	pb = Picture Box( Open( "/Users/homer.simpson@jmp.com/Downloads/graphPic.png", png ) )
);
pixMat = (pb << get image) << get pixels;
pixMat = pixMat[20 :: 265, 15 :: N Col( pixMat )];

nc = N Col( pixMat );

x = (1 :: nc)`;
y = J( nc, 1, . );
For( i = 1, i <= nc, i++,
	y[i] = Loc Min( pixMat[0, i] )
);
y = nrow( pixMat ) - y;  //"flip" y-vals to account for screen coordinate convention.

dt = As Table( x || y, <<column names( {"x", "y"} ) );

Graph Builder(
	Size( 982, 232 ),
	Show Control Panel( 0 ),
	Variables( X( :x ), Y( :y ) ),
	Elements( Points( X, Y, Legend( 5 ) ) ),
	SendToReport(
		Dispatch(
			{},
			"x",
			ScaleBox,
			{Format( "Best", 12 ), Min( 6.17686033877992 ), Max( 953.120680816302 ),
			Inc( 200 ), Minor Ticks( 1 )}
		)
	)
);

 

View solution in original post

5 REPLIES 5
MiBo
Level III

Re: Can JSL restore the value of the curve?

I'll have to admit that I don't understand enough about the question to begin to propose an answer.  If the curve is a bit map painting (.png file), then I can't imagine that JMP is the right too to try to read it.  Are you looking for some sort of optical scanning and recognition software?

 

In what format is the curve?  Are you trying to read the red curve or are you trying to read the numeric text along the bottom of the picture?

 

Maybe by asserting that JMP can't do it I'm about to learn some feature about JMP that I'm not aware of.

Re: Can JSL restore the value of the curve?

This isn't always easy but can possibly be done, depending on the graph. Here's one way to do this for the graph you've provided. There may be more efficient ways out there, as I've no background in image processing--apologies.

 

The idea is to get the pixel values for the image, and focus on differences between the background and the graph. In this case, the graph color was the minimum in any column of pixels. In other cases, you may need to derive some sort of bandpass filter, etc. For a multicolored background, even this approach might not work, if the color of the graph were the same as one of the colors in the background. At any rate, try this out.

 

This is a crude approach but should give you a starting point. Cleaning up/smoothing the data is not that hard to do after the fact. I'm sure others will find many ways to improve on the approach and performance, as well.

 

NOTE: I did not rescale x and y. Again, that is not hard to do once you've got the matrix down to the graph's data.

 

I have attached the .png I used so you can use the same file I did.

 

brady_brady_0-1620328935156.png

 

 

 

 

Cheers,

Brady


Names Default To Here( 1 );

//need to save image and put the file path in the open() function.
New Window( "Example", pb = Picture Box( Open( "/Users/brady.brady@jmp.com/Downloads/graphPic.png", png ) ) );
img = pb << get image;
pixMat = img << get pixels;

pixMat = 1000*(floor(pixMat/1000));	//smooths values; use whatever factor you like
dt = astable(pixmat);

eval(substitute (
	expr(dt << new column("Row", formula( _ROW_ - :row()))), //low rows for pixels are high. This is a fix for that.
	expr(_ROW_),
	nrow(dt)
));

dt:row << Delete Formula;
dt <<  move selected  columns({"Row"}, to first);

dt << select where (:row() <= 20 | :row() >= 265) << Delete Rows;  // top and bottom few rows of this table are not useful

stackCols = (dt << get column names)[14::ncol(dt)];

dtStack = dt << Stack(
	columns( stackCols ),
	Source Label Column( "Label" ),
	Stacked Data Column( "Data" ),
	"Non-stacked columns"n( Keep( :Row ) )
);

dtStack << select where (:data == col minimum(:data, :label)); //in this case, minimum color is the graph.

dtSub = dtStack << subset(selected rows(1), selected columns (0));

dtSub << new column("x", formula(num(substitute(:label, "Col", ""))));

summarize(dtSub, b = by(:label), yVals = mean(:Row), xVals = mean(:x));

astable(xvals || yvals, <<column names({"x", "y"}));

Graph Builder(
	Size( 982, 232 ),
	Show Control Panel( 0 ),
	Variables( X( :x ), Y( :y ) ),
	Elements( Points( X, Y, Legend( 5 ) ) ),
	SendToReport(
		Dispatch(
			{},
			"x",
			ScaleBox,
			{Format( "Best", 12 ), Min( 6.17686033877992 ), Max( 953.120680816302 ),
			Inc( 200 ), Minor Ticks( 1 )}
		)
	)
);

//now just need to scale x and y

 

lwx228
Level VIII

Re: Can JSL restore the value of the curve?

Thanks again to Brady for the power of this script.

 

I want to take this script a step further

However, the script is slightly modified to identify as data:

Identify the curve with only one pixel, an X-axis position, as long as you identify a corresponding Y value.

2021-12-09_143447.png

lwx228
Level VIII

Re: Can JSL restore the value of the curve?

And most importantly, I want to achieve how similar this curve is to another one.
The principle should be a comparison between two sets of data.
Can JMP achieve this well?

 

For example, graph with JSL below and compare with the graph above.

dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt << Sort( By( 1 ), Order( Ascending ), replacetable( 1 ) );
New Column( "A" );
Column( "A" ) << Formula( Row() );
dt << run formulas;
Column( "A" ) << deleteFormula;

p1 = Graph Builder(
	Size( 528, 450 ),
	Show Control Panel( 0 ),
	Variables( X( :age ), Y( :A ) ),
	Elements( Line( X, Y, Legend( 4 ) ) )
);

2021-12-09_194809.png

 

Thanks Experts!

Re: Can JSL restore the value of the curve?

By the way, I should mention that if you don't care about averaging over pixels (the line in the graph here is several pixels thick in each column) and are just looking for an approximation, the processing (in this particular example) can be much faster and less cluttered with data tables. As you'll see, the graph you get is basically the same.

names default to here(1);

New Window( "Example",
	pb = Picture Box( Open( "/Users/homer.simpson@jmp.com/Downloads/graphPic.png", png ) )
);
pixMat = (pb << get image) << get pixels;
pixMat = pixMat[20 :: 265, 15 :: N Col( pixMat )];

nc = N Col( pixMat );

x = (1 :: nc)`;
y = J( nc, 1, . );
For( i = 1, i <= nc, i++,
	y[i] = Loc Min( pixMat[0, i] )
);
y = nrow( pixMat ) - y;  //"flip" y-vals to account for screen coordinate convention.

dt = As Table( x || y, <<column names( {"x", "y"} ) );

Graph Builder(
	Size( 982, 232 ),
	Show Control Panel( 0 ),
	Variables( X( :x ), Y( :y ) ),
	Elements( Points( X, Y, Legend( 5 ) ) ),
	SendToReport(
		Dispatch(
			{},
			"x",
			ScaleBox,
			{Format( "Best", 12 ), Min( 6.17686033877992 ), Max( 953.120680816302 ),
			Inc( 200 ), Minor Ticks( 1 )}
		)
	)
);