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
BHarris
Level VI

Drawing other shapes in graph-builder

I have an example table that looks like this:

 

datasetxycxcycRad
10.17390.87210.49850.50270.4918
10.49590.01090.49850.50270.4918
10.34980.22490.49850.50270.4918
10.40050.31350.49850.50270.4918
10.65580.23980.49850.50270.4918
10.51590.68670.49850.50270.4918
10.71650.2360.49850.50270.4918
10.74670.1460.49850.50270.4918
10.68120.16840.49850.50270.4918
10.9020.74580.49850.50270.4918
10.46380.78620.49850.50270.4918
10.58230.64820.49850.50270.4918
10.99020.49480.49850.50270.4918
40.12750.81690.49620.49580.489
40.91760.24770.49620.49580.489
40.84930.15750.49620.49580.489
50.20.80.50.50.4243
50.20.20.50.50.4243
50.80.80.50.50.4243
50.80.20.50.50.4243

 

In Graph Builder, I drag x to X, y to Y, and make a local filter for dataset.

 

I'd like to draw a circle (oval?) centered at cx, cy, with radius cRad.  I right-clicked the plot, "Customize", and added this script:

 

circle({:cx[1],:cy[1]},:cRad[1]); 

 

It works with the subscripts ("[1]") in there, but doesn't update when I change the local filter.  If I take out the subscripts it stops working altogether.  Is there a way to make this work? 

1 ACCEPTED SOLUTION

Accepted Solutions
ian_jmp
Level X

Re: Drawing other shapes in graph-builder

Looks like you actually need 'Make Filter Change Handler()'. Please find an example:

NamesDefaultToHere(1);

// Example table
dt = New Table( "Test Circles",
			Add Rows( 20 ),
			New Column( "dataset",
				Numeric,
				"Nominal",
				Format( "Best", 12 ),
				Set Values( [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 5, 5, 5, 5] )
			),
			New Column( "x",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.1739, 0.4959, 0.3498, 0.4005, 0.6558, 0.5159, 0.7165, 0.7467, 0.6812,
					0.902, 0.4638, 0.5823, 0.9902, 0.1275, 0.9176, 0.8493, 0.2, 0.2, 0.8,
					0.8]
				)
			),
			New Column( "y",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.8721, 0.0109, 0.2249, 0.3135, 0.2398, 0.6867, 0.236, 0.146, 0.1684,
					0.7458, 0.7862, 0.6482, 0.4948, 0.8169, 0.2477, 0.1575, 0.8, 0.2, 0.8,
					0.2]
				)
			),
			New Column( "cx",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985,
					0.4985, 0.4985, 0.4985, 0.4985, 0.4962, 0.4962, 0.4962, 0.5, 0.5, 0.5,
					0.5]
				)
			),
			New Column( "cy",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027,
					0.5027, 0.5027, 0.5027, 0.5027, 0.4958, 0.4958, 0.4958, 0.5, 0.5, 0.5,
					0.5]
				)
			),
			New Column( "cRad",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918,
					0.4918, 0.4918, 0.4918, 0.4918, 0.489, 0.489, 0.489, 0.4243, 0.4243,
					0.4243, 0.4243]
				)
			)
		);

// Initial parameters for drawing a circle (used when there is no selection in the data filter)
cx = cy = cRad = 0.0;

// Graph Builder with locked scales . . .
gb = dt << Graph Builder(
					Show Control Panel( 0 ),
					Lock Scales( 1 ),
					Variables( X( :x ), Y( :y ) ),
					Elements( Points( X, Y, Legend( 7 ) ) )
				);
gbRep = Report(gb);

// Add graphics script for a circle
gbRep[FrameBox(1)] << Add Graphics Script(
								2,
								Description( "Circle" ),
								Pen Color( "Blue" );
								Circle( {cx, cy}, cRad );
							);

// Add Local Data Filter . . .
ldf = gb << Local Data Filter();

// Add the filter column, and get a reference to the filter column object ('fc' is not actually used)
ldf << Add Filter( columns(:dataset));
fc = ldf << GetFilterColumn(:dataset);

// Function to get new circle parameters from the Local Data Filter selection
getCircleFromFilter = 
Function( {x},
	theseRows = ldf << getFilteredRows;
	if(IsMatrix(theseRows),
		// Assume it's safe to get the required values from just the first row in the current selection
		cx = Column(dt, "cx")[theseRows[1]];
		cy = Column(dt, "cy")[theseRows[1]];
		cRad = Column(dt, "cRad")[theseRows[1]];
		,
		// No selection should give no visible circle
		cx = cy = cRad = 0.0;
		);
	// Force the graphics script to be revaluated with the current parameters of the circle
	gbRep[FrameBox(1)] << reShow;
);

// Assign the Filter Change Handler to the local data filter to do the work
rsh = ldf << Make Filter Change Handler(getCircleFromFilter);

View solution in original post

6 REPLIES 6
Thierry_S
Super User

Re: Drawing other shapes in graph-builder

Hi,

I have only figured out a small part of the solution by iterating through the table with this short script (can be added in the Customize > Script input window).

for (i= 1 , i <= N Row (), i++,
	circle({:cx[i],:cy[i]},:cRad[i]); 
 );

Unfortunately, I could not find a function that dynamically returns the state of the row selection in the GB Local Filter. You may want to ask specifically about that topic in a new post: there has to be a way. 

Sorry for not being of much help.

Best,

TS

Thierry R. Sornasse
Thierry_S
Super User

Re: Drawing other shapes in graph-builder

I must be tired: the command "For Each Row (circle({:cx,:cy},:cRad))" is more elegant
Thierry R. Sornasse
Thierry_S
Super User

Re: Drawing other shapes in graph-builder

OK, the command "MakeRowStateHandler" seems to be what you are looking for to only draw circles for the selected items in your local filter but I have to admit that I cannot figure out the proper syntax to give you a solution.
Thierry R. Sornasse
ian_jmp
Level X

Re: Drawing other shapes in graph-builder

Looks like you actually need 'Make Filter Change Handler()'. Please find an example:

NamesDefaultToHere(1);

// Example table
dt = New Table( "Test Circles",
			Add Rows( 20 ),
			New Column( "dataset",
				Numeric,
				"Nominal",
				Format( "Best", 12 ),
				Set Values( [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 5, 5, 5, 5] )
			),
			New Column( "x",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.1739, 0.4959, 0.3498, 0.4005, 0.6558, 0.5159, 0.7165, 0.7467, 0.6812,
					0.902, 0.4638, 0.5823, 0.9902, 0.1275, 0.9176, 0.8493, 0.2, 0.2, 0.8,
					0.8]
				)
			),
			New Column( "y",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.8721, 0.0109, 0.2249, 0.3135, 0.2398, 0.6867, 0.236, 0.146, 0.1684,
					0.7458, 0.7862, 0.6482, 0.4948, 0.8169, 0.2477, 0.1575, 0.8, 0.2, 0.8,
					0.2]
				)
			),
			New Column( "cx",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985, 0.4985,
					0.4985, 0.4985, 0.4985, 0.4985, 0.4962, 0.4962, 0.4962, 0.5, 0.5, 0.5,
					0.5]
				)
			),
			New Column( "cy",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027, 0.5027,
					0.5027, 0.5027, 0.5027, 0.5027, 0.4958, 0.4958, 0.4958, 0.5, 0.5, 0.5,
					0.5]
				)
			),
			New Column( "cRad",
				Numeric,
				"Continuous",
				Format( "Best", 12 ),
				Set Values(
					[0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918, 0.4918,
					0.4918, 0.4918, 0.4918, 0.4918, 0.489, 0.489, 0.489, 0.4243, 0.4243,
					0.4243, 0.4243]
				)
			)
		);

// Initial parameters for drawing a circle (used when there is no selection in the data filter)
cx = cy = cRad = 0.0;

// Graph Builder with locked scales . . .
gb = dt << Graph Builder(
					Show Control Panel( 0 ),
					Lock Scales( 1 ),
					Variables( X( :x ), Y( :y ) ),
					Elements( Points( X, Y, Legend( 7 ) ) )
				);
gbRep = Report(gb);

// Add graphics script for a circle
gbRep[FrameBox(1)] << Add Graphics Script(
								2,
								Description( "Circle" ),
								Pen Color( "Blue" );
								Circle( {cx, cy}, cRad );
							);

// Add Local Data Filter . . .
ldf = gb << Local Data Filter();

// Add the filter column, and get a reference to the filter column object ('fc' is not actually used)
ldf << Add Filter( columns(:dataset));
fc = ldf << GetFilterColumn(:dataset);

// Function to get new circle parameters from the Local Data Filter selection
getCircleFromFilter = 
Function( {x},
	theseRows = ldf << getFilteredRows;
	if(IsMatrix(theseRows),
		// Assume it's safe to get the required values from just the first row in the current selection
		cx = Column(dt, "cx")[theseRows[1]];
		cy = Column(dt, "cy")[theseRows[1]];
		cRad = Column(dt, "cRad")[theseRows[1]];
		,
		// No selection should give no visible circle
		cx = cy = cRad = 0.0;
		);
	// Force the graphics script to be revaluated with the current parameters of the circle
	gbRep[FrameBox(1)] << reShow;
);

// Assign the Filter Change Handler to the local data filter to do the work
rsh = ldf << Make Filter Change Handler(getCircleFromFilter);
BHarris
Level VI

Re: Drawing other shapes in graph-builder

@ian_jmp:  Holy... wow.

 

I'm struggling to understand what you've done -- it looks like you've created a function that sets cx, cy, and cRad whenever the local filter changes.  That's really cool.

 

Two quick follow-on questions since I'm still learning jsl:  (1) Where does that function live once I run that script?  Is it just sitting in RAM somewhere?  Is there a place I can find it later?  A "Show list of available user functions..." option somewhere?  (2)  When I do "gb = dt << Graph Builder(...)", is there a way to see what objects are available inside the gb object?  Similar to "dir(obj)" in python?

 

Impressive!  Thank you!!

 

 

ian_jmp
Level X

Re: Drawing other shapes in graph-builder

Depending on what you already know about JSL, and how much you wish to know, there's quite a bit of implied knowledge in the example above. Aside from the 'Scripting Guide' PDF itself, 'Help > Scripting Index' is useful if you already have some code and want to understand how it works. If you have the code in the editor you can right click on a keyword to bring this up, usually with an example. This will also reveal what messages an object like the local data filter will respond to, and you can also get this by using the 'ShowProperties()' command.

 

Regarding variables and their scope, you might like to look at namespaces. JMP does everything in memory.