cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Browse apps to extend the software in the new JMP Marketplace
Choose Language Hide Translation Bar
qspringleaf
Level III

how to generate a data table through a graph which is a plot of some data?

if I only have a photo graph which is a plot of some data, but not have a its original raw data. can help to suggest how to generate a data set use this graph?

My purpose is to generate a data set that can represent its profile, and join with others then can do a new plot to combine all togehter.

can use jmp script or through its basic function tools? thanks a lot.

qspringleaf_1-1622996228420.png

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Craige_Hales
Super User

Re: how to generate a data table through a graph which is a plot of some data?

I think there is a lot of unknown information, so there may not be any great answers.

  • is this a smoothed curve?
  • how many data points were there?
  • what resolution did the data have?

Perhaps just using the cross hair tool and a new data table would be good enough for 10 to 20 points.

 

If you believe there are 100s of valid points, on the plotted line, you can recover them with a bit of JSL. Read the comments; study the results and make sure they make sense.

//
// this is NOT a general solution; it is tailored for this particular bitmap
//
img = Open( "https://community.jmp.com/t5/image/serverpage/image-id/33300i4DE1ABDC20B74778" );
New Window( "Make sure this is the right image", img ); // view the img
// work with r,g,b arrays of pixel data...
{r, g, b} = img << getpixels( "rgb" );
// https://community.jmp.com/t5/JSL-Cookbook/Using-Loc-with-a-2D-Matrix/ta-p/195207
// explains the 1D vs 2D matrix/loc stuff...
nr = N Rows( b );
nc = N Cols( b );
// using the MS paint eyedropper, the blue-est of the pixels in the blue line have rgb=(56,89,165)
bluelocs = (Loc( r < (60 / 255) & g < (95 / 255) & b > (160 / 255) ) - 1); // bluelocs is a matrix of 1D indexes (0-based)
blueRowlocs = Floor( (bluelocs) / nc ) + 1; // nc is the number of columns in the 2D pixmat
blueCollocs = Mod( (bluelocs), nc ) + 1; // rowlocs and collocs are 2D indexes (1-based)
// the grid lines have rgb=(215,215,215) (the frame is darker, 165,165,165)
gridlocs = (Loc( r == (215 / 255) & g == (215 / 255) & b == (215 / 255) ) - 1);
gridRowlocs = Floor( (gridlocs) / nc ) + 1; // nc is the number of columns in the 2D pixmat
gridCollocs = Mod( (gridlocs), nc ) + 1; // rowlocs and collocs are 2D indexes (1-based)
// locate the top, bottom, left, and right gray grid lines; their values are hard-coded below...
MINRAD = 5;
MAXRAD = 140;
MINTHK = 595;
MAXTHK = 715;
// CAUTION: this works because there is not a lot of other gray pixels of this shade.
// the while-loop removes a couple that get in the way.
// a different source graph will have different problems.
dtGRAY = As Table( gridRowlocs || gridCollocs, <<columnnames( {"THK", "Radius"} ) );
// sorting, first by thk, makes the first and last gray pixels be for the first and last VERTICAL lines...
dtGRAY << sort( by( THK ), replacetable );
While( dtGRAY:THK[1] != dtGRAY:THK[2], dtGRAY << deleterows( 1 ) ); // already OK for this image
RADminPixel = dtGRAY:radius[1];
Write( "\!nradius(min) is x pixel ", RADminPixel );
RADmaxPixel = dtGRAY:radius[N Rows( dtGRAY )];
Write( "\!nradius(max) is x pixel ", RADmaxPixel );
// sorting, by radius, makes the first and last gray pixels be for the first and last HORIZONTAL lines...
dtGRAY << sort( by( radius ), replacetable );
While( dtGRAY:radius[1] != dtGRAY:radius[2], dtGRAY << deleterows( 1 ) ); // clears some misc text at the left edge
THKmaxPixel = dtGRAY:THK[1];
Write( "\!nTHK(max) is y pixel ", THKmaxPixel );
THKminPixel = dtGRAY:THK[N Rows( dtGRAY )];
Write( "\!nTHK(min) is y pixel ", THKminPixel );
Close( dtGRAY, nosave );

// scale the data. this is a standard linear interpolation, on the matrix values.
blueRowlocs = (blueRowlocs - THKminPixel) / (THKmaxPixel - THKminPixel) * (MAXTHK - MINTHK) + MINTHK;
blueCollocs = (blueCollocs - RADminPixel) / (RADmaxPixel - RADminPixel) * (MAXRAD - MINRAD) + MINRAD;

// make a table
dtBLUE = As Table( blueRowlocs || blueCollocs, <<columnnames( {"THK", "Radius"} ) );

// and the graph.
dtBLUE << Graph Builder(
    Size( 1354, 820 ),
    Show Control Panel( 0 ),
    Variables( X( :Radius ), Y( :THK ) ),
    Elements( Points( X, Y, Legend( 4 ) ) ),
    SendToReport(
        Dispatch( {}, "Radius", ScaleBox, {Min( 0 ), Max( 150 ), Inc( 5 ), Minor Ticks( 0 ), Label Row( Show Major Grid( 1 ) )} ),
        Dispatch({},"THK",ScaleBox,{Min(590),Max(720),Inc(5),MinorTicks(1),LabelRow({AutomaticTickMarks(0),ShowMajorGrid(1),ShowMinorTicks(0)})}),
        Dispatch( {}, "Graph Builder", FrameBox, {Marker Size( 0 ), Marker Drawing Mode( "Normal" )} )
    )
);

Graph of recovered data from blue lineGraph of recovered data from blue line

 

This works on the original graph you uploaded, not on the reduced resolution graph you most likely see in the discussion.

Craige

View solution in original post

3 REPLIES 3
Craige_Hales
Super User

Re: how to generate a data table through a graph which is a plot of some data?

I think there is a lot of unknown information, so there may not be any great answers.

  • is this a smoothed curve?
  • how many data points were there?
  • what resolution did the data have?

Perhaps just using the cross hair tool and a new data table would be good enough for 10 to 20 points.

 

If you believe there are 100s of valid points, on the plotted line, you can recover them with a bit of JSL. Read the comments; study the results and make sure they make sense.

//
// this is NOT a general solution; it is tailored for this particular bitmap
//
img = Open( "https://community.jmp.com/t5/image/serverpage/image-id/33300i4DE1ABDC20B74778" );
New Window( "Make sure this is the right image", img ); // view the img
// work with r,g,b arrays of pixel data...
{r, g, b} = img << getpixels( "rgb" );
// https://community.jmp.com/t5/JSL-Cookbook/Using-Loc-with-a-2D-Matrix/ta-p/195207
// explains the 1D vs 2D matrix/loc stuff...
nr = N Rows( b );
nc = N Cols( b );
// using the MS paint eyedropper, the blue-est of the pixels in the blue line have rgb=(56,89,165)
bluelocs = (Loc( r < (60 / 255) & g < (95 / 255) & b > (160 / 255) ) - 1); // bluelocs is a matrix of 1D indexes (0-based)
blueRowlocs = Floor( (bluelocs) / nc ) + 1; // nc is the number of columns in the 2D pixmat
blueCollocs = Mod( (bluelocs), nc ) + 1; // rowlocs and collocs are 2D indexes (1-based)
// the grid lines have rgb=(215,215,215) (the frame is darker, 165,165,165)
gridlocs = (Loc( r == (215 / 255) & g == (215 / 255) & b == (215 / 255) ) - 1);
gridRowlocs = Floor( (gridlocs) / nc ) + 1; // nc is the number of columns in the 2D pixmat
gridCollocs = Mod( (gridlocs), nc ) + 1; // rowlocs and collocs are 2D indexes (1-based)
// locate the top, bottom, left, and right gray grid lines; their values are hard-coded below...
MINRAD = 5;
MAXRAD = 140;
MINTHK = 595;
MAXTHK = 715;
// CAUTION: this works because there is not a lot of other gray pixels of this shade.
// the while-loop removes a couple that get in the way.
// a different source graph will have different problems.
dtGRAY = As Table( gridRowlocs || gridCollocs, <<columnnames( {"THK", "Radius"} ) );
// sorting, first by thk, makes the first and last gray pixels be for the first and last VERTICAL lines...
dtGRAY << sort( by( THK ), replacetable );
While( dtGRAY:THK[1] != dtGRAY:THK[2], dtGRAY << deleterows( 1 ) ); // already OK for this image
RADminPixel = dtGRAY:radius[1];
Write( "\!nradius(min) is x pixel ", RADminPixel );
RADmaxPixel = dtGRAY:radius[N Rows( dtGRAY )];
Write( "\!nradius(max) is x pixel ", RADmaxPixel );
// sorting, by radius, makes the first and last gray pixels be for the first and last HORIZONTAL lines...
dtGRAY << sort( by( radius ), replacetable );
While( dtGRAY:radius[1] != dtGRAY:radius[2], dtGRAY << deleterows( 1 ) ); // clears some misc text at the left edge
THKmaxPixel = dtGRAY:THK[1];
Write( "\!nTHK(max) is y pixel ", THKmaxPixel );
THKminPixel = dtGRAY:THK[N Rows( dtGRAY )];
Write( "\!nTHK(min) is y pixel ", THKminPixel );
Close( dtGRAY, nosave );

// scale the data. this is a standard linear interpolation, on the matrix values.
blueRowlocs = (blueRowlocs - THKminPixel) / (THKmaxPixel - THKminPixel) * (MAXTHK - MINTHK) + MINTHK;
blueCollocs = (blueCollocs - RADminPixel) / (RADmaxPixel - RADminPixel) * (MAXRAD - MINRAD) + MINRAD;

// make a table
dtBLUE = As Table( blueRowlocs || blueCollocs, <<columnnames( {"THK", "Radius"} ) );

// and the graph.
dtBLUE << Graph Builder(
    Size( 1354, 820 ),
    Show Control Panel( 0 ),
    Variables( X( :Radius ), Y( :THK ) ),
    Elements( Points( X, Y, Legend( 4 ) ) ),
    SendToReport(
        Dispatch( {}, "Radius", ScaleBox, {Min( 0 ), Max( 150 ), Inc( 5 ), Minor Ticks( 0 ), Label Row( Show Major Grid( 1 ) )} ),
        Dispatch({},"THK",ScaleBox,{Min(590),Max(720),Inc(5),MinorTicks(1),LabelRow({AutomaticTickMarks(0),ShowMajorGrid(1),ShowMinorTicks(0)})}),
        Dispatch( {}, "Graph Builder", FrameBox, {Marker Size( 0 ), Marker Drawing Mode( "Normal" )} )
    )
);

Graph of recovered data from blue lineGraph of recovered data from blue line

 

This works on the original graph you uploaded, not on the reduced resolution graph you most likely see in the discussion.

Craige
qspringleaf
Level III

Re: how to generate a data table through a graph which is a plot of some data?

Hi, so thankful Craige_Hales for this gift, it works well.

Re: how to generate a data table through a graph which is a plot of some data?

Here is a thread with another example of this-- Can JSL restore the value of the curve? 

 

Cheers,

Brady