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
Ole
Ole
Level III

adding graphic to a graph box using a for-loop

Hi,

 

I'm trying to add graphics (rectangles) to a graph box by using a for-loop. The expected outcome is a cross made of 31 rectangles. I have a working script where I wrote the code out line by line but would like to make it shorter and more scalable.

The script below is running but only the last rectangle will be displayed in the graph box.

When I write the script with 2 lines of "Add Graphics Script" (commented out at the bottom of the script) instead of the for-loop it does add 2 rectangles. I would have expected a for-loop to do the same. How can I get it do do so?

 

Names default to here(1);

//dt that holds the parameters for the rectangles
dt_loc = open (momo_dir || "rectangle_locations.csv" );


//create a graphic box
base_box = graph Box(
Frame Size( 400, 400 ), 
XName(""), XScale(19,81), yScale(19,91), SuppressAxes, Pen Color( 1 ); 

);

//define the frame box in which the rectangles will e displayed
framebox = base_box[frame box( 1 )];

//ran a for loop for all 31 rectangles to be added to the Base_box
For( f = 1, f <= N Rows(dt_loc), f++,

//f=1;

//location/sizes of each box is defined here based on a csv file
rec_left = dt_loc:left[f];
rec_top = dt_loc:top[f];
rec_right = dt_loc:right[f];
rec_bottom = dt_loc:bottom[f];

//add the graphic script to the base_box for each row (aka rectangle) in the table
framebox << Add Graphics Script(Rect(rec_left, rec_top, rec_right, rec_bottom, fill = 0););

); //end f for loop

try(close(dt_loc, no save));

//Running the following 2 lines will add 2 rectangles 
	//framebox << Add Graphics Script(Rect(40,75,50,70, fill = 0););
	//framebox << Add Graphics Script(Rect(40,70,50,65, fill = 0););

cross_rep = New window ("Cross", vlistbox(base_box));
2 ACCEPTED SOLUTIONS

Accepted Solutions
txnelson
Super User

Re: adding graphic to a graph box using a for-loop

You have made the script far more complex than it needs to be.  Below are 2 reworks of your script.  The first one is taking your flow, and just converting it into a working model.  The second is making it very concise(small) as you also requested.

Names Default To Here( 1 );

//dt that holds the parameters for the rectangles
dt_loc = Open( momo_dir || "rectangle_locations.csv" );

//create a graphic box
base_box = Graph Box(
	Frame Size( 400, 400 ),
	XName( "" ),
	X Scale( 19, 81 ),
	Y Scale( 19, 91 ),
	SuppressAxes,
	Pen Color( 1 ); 

	//ran a for loop for all 31 rectangles to be added to the Base_box
	For( f = 1, f <= N Rows( dt_loc ), f++, 
	
		// location/sizes of each box is defined here based on a csv file
		rec_left = dt_loc:left[f];
		rec_top = dt_loc:top[f];
		rec_right = dt_loc:right[f];
		rec_bottom = dt_loc:bottom[f];
		
		// Draw the rectangle
		Rect( rec_left, rec_top, rec_right, rec_bottom, fill = 0 );

	);
);

Try( Close( dt_loc, no save ) );

cross_rep = New Window( "Cross", V List Box( base_box ) );
Names Default To Here( 1 );

//dt that holds the parameters for the rectangles
dt_loc = Open( momo_dir || "rectangle_locations.csv" );

cross_rep = New Window( "Cross", 
//create a graphic box
	base_box = Graph Box(
		Frame Size( 400, 400 ),
		XName( "" ),
		X Scale( 19, 81 ),
		Y Scale( 19, 91 ),
		SuppressAxes,
		Pen Color( 1 ); 

		//ran a for loop for all 31 rectangles to be added to the Base_box
		For( f = 1, f <= N Rows( dt_loc ), f++, 
	
			// location/sizes of each box is defined here based on a csv file
			Rect( dt_loc:left[f], dt_loc:top[f], dt_loc:right[f], dt_loc:bottom[f] );

		);
	)
);
Try( Close( dt_loc, no save ) );
Jim

View solution in original post

Craige_Hales
Super User

Re: adding graphic to a graph box using a for-loop

the graphics script runs later, whenever the graph needs to update (zooming, etc). You've specified variables in one case, and hard coded numbers in the other. You can convert the variables to numbers in a bunch of ways. The way I usually do this looks something like this:

eval(evalexpr(
framebox << Add Graphics Script(Rect(expr(rec_left), expr(rec_top), expr(rec_right), expr(rec_bottom), fill = 0););
));

which wraps the variables with expr(...), uses evalexpr(...) to replace expr(...) with actual value, and uses eval(...) to evaluate the expression returned by evalexpr(...). Likely other people will show their preferred ways. <edit> I like @txnelson 2nd answer.

Craige

View solution in original post

5 REPLIES 5
txnelson
Super User

Re: adding graphic to a graph box using a for-loop

You have made the script far more complex than it needs to be.  Below are 2 reworks of your script.  The first one is taking your flow, and just converting it into a working model.  The second is making it very concise(small) as you also requested.

Names Default To Here( 1 );

//dt that holds the parameters for the rectangles
dt_loc = Open( momo_dir || "rectangle_locations.csv" );

//create a graphic box
base_box = Graph Box(
	Frame Size( 400, 400 ),
	XName( "" ),
	X Scale( 19, 81 ),
	Y Scale( 19, 91 ),
	SuppressAxes,
	Pen Color( 1 ); 

	//ran a for loop for all 31 rectangles to be added to the Base_box
	For( f = 1, f <= N Rows( dt_loc ), f++, 
	
		// location/sizes of each box is defined here based on a csv file
		rec_left = dt_loc:left[f];
		rec_top = dt_loc:top[f];
		rec_right = dt_loc:right[f];
		rec_bottom = dt_loc:bottom[f];
		
		// Draw the rectangle
		Rect( rec_left, rec_top, rec_right, rec_bottom, fill = 0 );

	);
);

Try( Close( dt_loc, no save ) );

cross_rep = New Window( "Cross", V List Box( base_box ) );
Names Default To Here( 1 );

//dt that holds the parameters for the rectangles
dt_loc = Open( momo_dir || "rectangle_locations.csv" );

cross_rep = New Window( "Cross", 
//create a graphic box
	base_box = Graph Box(
		Frame Size( 400, 400 ),
		XName( "" ),
		X Scale( 19, 81 ),
		Y Scale( 19, 91 ),
		SuppressAxes,
		Pen Color( 1 ); 

		//ran a for loop for all 31 rectangles to be added to the Base_box
		For( f = 1, f <= N Rows( dt_loc ), f++, 
	
			// location/sizes of each box is defined here based on a csv file
			Rect( dt_loc:left[f], dt_loc:top[f], dt_loc:right[f], dt_loc:bottom[f] );

		);
	)
);
Try( Close( dt_loc, no save ) );
Jim
Ole
Ole
Level III

Re: adding graphic to a graph box using a for-loop

I agree. The 2nd script is really concise and to the point. I tried the for-loop in the graph box as well but must have had an error in the script that prevented it from working.

 

Thanks a lot.

Ole

Ole
Ole
Level III

Re: adding graphic to a graph box using a for-loop

One follow up question/comment.

 

The dt_loc variable is not passed into the graph box. I found two options to get it to work:

- open the dt_loc table inside the graph box (which works if I only use the table at that part of the script)

- make dt_loc a global variable (::dt_loc)

 

Is there any other way to make the dt_loc variable available inside the graph box?

 

Thanks

Ole

Craige_Hales
Super User

Re: adding graphic to a graph box using a for-loop

the graphics script runs later, whenever the graph needs to update (zooming, etc). You've specified variables in one case, and hard coded numbers in the other. You can convert the variables to numbers in a bunch of ways. The way I usually do this looks something like this:

eval(evalexpr(
framebox << Add Graphics Script(Rect(expr(rec_left), expr(rec_top), expr(rec_right), expr(rec_bottom), fill = 0););
));

which wraps the variables with expr(...), uses evalexpr(...) to replace expr(...) with actual value, and uses eval(...) to evaluate the expression returned by evalexpr(...). Likely other people will show their preferred ways. <edit> I like @txnelson 2nd answer.

Craige
Ole
Ole
Level III

Re: adding graphic to a graph box using a for-loop

Perfect. That worked. Thank you very much.

 

Ole