Subscribe Bookmark RSS Feed

Force Legend with marker and color of row state

ptijerome

Community Trekker

Joined:

Jun 17, 2014

Hello,

 

I am trying to make a legend with markers and colors, but I'd like to choose them. I thought it will be easy thanks to row state (color state, marker state,combine states). But once color and marker are assigned to each row, I am not able to find a way to force them in the legend.

I would like to do it by script (I was thinking to add a box with the legend), but I am not able to find a way to handle the "markers" I have created.

 

Thanks

 

  

1 ACCEPTED SOLUTION

Accepted Solutions
ian_jmp

Staff

Joined:

Jun 23, 2011

Solution

As an alternative, you might consider using 'MarkerSeg'. In the code below 'dt' is a table of all the distinct levels of the column you wish to colour and mark by. You could use 'Tables > Summary' and make this invisible.

 

NamesDefaultToHere(1);

// Example data table (markers and colors assigned by 'Lot ID')
dt = New Table( "Rows With Colors and Markers",
					Add Rows( 12 ),
					New Column( "Lot ID",
						Character,
						"Nominal",
						Set Values(
							{"lot1", "lot10", "lot11", "lot12", "lot13", "lot2", "lot3", "lot4",
							"lot5", "lot6", "lot7", "lot8"}
						),
						Lock( 1 )
					),
					Set Row States(
						[896.813481688499, 1104.17848521471, 34064.2516910434, 1584.79095828533,
						1856.1745531559, 34848.5869575739, 35120.7292968035, 2704.17450988293,
						2976.75480300188, 3200.51829791069, 3408.21706777811, 36368.77437675]
					)
				);

// Make legend window with MarkerSeg
n = NRow(dt);
xx = J(n, 1, 1);
yy = Transpose(1::n);
legendList = Column(dt, "Lot ID") << getValues;
			gb = Graph Box(
					FrameSize( 150, 300*(n/16) ),
					Y Scale( 0, n+1 ),
					X Scale( 0, 6 ),
					Y Name(" "),
					X Name(" "),
					Y Axis(ShowLabels(0), ShowMajorTicks(0), ShowMinorTicks(0)),
					X Axis(ShowLabels(0), ShowMajorTicks(0), ShowMinorTicks(0)),
					Marker Seg( xx, yy, Row States( dt ) ),
					For( i = 1, i<=n, i++, Text( {1.5, i-0.1}, legendList[i] ) )
				);
db = PanelBox("Row State Colours and Markers for 'Lot ID'", gb);
New Window( "My Legend", db);

 

9 REPLIES
txnelson

Super User

Joined:

Jun 22, 2012

The easiest way that I found for JMP to handle this, is to modify the legend, and therefore the graph using JSL, to match your Row States.  Here is a script that shows how to modify the legend in Graph Builder.

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA\big class.jmp" );
Graph Builder(
	Show Control Panel( 0 ),
	Variables( X( :height ), Y( :weight ), Overlay( :sex ) ),
	Elements( Points( X, Y, Legend( 1 ) ), Smoother( X, Y, Legend( 1 ) ) ),
	SendToReport(
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				1,
				Properties( 0, {Marker( "FilledTall" )} ),
				Properties( 1, {Line Color( 1 ), Line Style( "Dashed" ), Marker( "Filled Diamond" )} )
			), Legend Model(
				1,
				Properties( 0, {Marker( "FilledTall" )} ),
				Properties( 1, {Line Color( 1 ), Line Style( "Dashed" ), Marker( "Filled Diamond" )} )
			)}
		),
		Dispatch( {}, "400", LegendBox, {Legend Position( {1, [2, 3], 1, [0, 1]} ), Position( {2, 3, 0, 1} )} )
	)
);

It produces the following

Graph Builder Legend Manipulation.jpg

Jim
ptijerome

Community Trekker

Joined:

Jun 17, 2014

Thanks for the quick answer,

1/ It can work provided I have a full set of marker names (I found in the documentation the standards JMP colors). Do you know where I can find something equivalent for marker names?

2/ In that case if colors and markers are written in a dedicated table I am able to modify each line of the legend  through an (eval(substitute(expr(graphbuilder(color1,marker1),expr(color1),mycolor, expr(marker1),mymarker))). It works, nice step forward, but I need to know the number of item in the legend in order to make the substitution. 

 

To make it more clear for "big class" file, if the overlay is made with :AGE, and if I don't know the AGE(s) in the file, how can I do?

 

I could maybe do it in a loop (after the graph builder), if I was able to send a message to the legendbox. But I cannot find in the documentation  messages that modify the item...And finally the tree node is "empty" in the legendbox node.

txnelson

Super User

Joined:

Jun 22, 2012

1. The markers are numbered as can be seen in the chart below.  This was generated by a script, as demonstrated int the scripting guide

     Help==>Books==>Scripting Guide

Markers.jpg

Some of the markers have names assigned to them, which you have seen in the Graph Builder script.  I don't know of any listing of those name, but you can always interactively run a Graph Builder and assign the marker you want, and then view the script it produced and see if it gives you a name and not just a number.

2.  The legend is going to be listed out in alphabetical or numeric order, unless Value ordering or Row Order Level is turned on.  Programatically, you can determine that, and then adjust your code.  As far as finding out the ages in the data table, the Summarize() function is what I use most of the time

     summarize(dt,bygroup = By(:Age));

The variable "bygroup" will have a list of all of the different ages found.

     N Items(bygroup);

Gives you the number of different ages found

Jim
ptijerome

Community Trekker

Joined:

Jun 17, 2014

Thanks Jim

 

1. I agree it is not a real issue... I can get the list with some work!

2. Maybe I wasn't clear enough. I can easily, as you mention, get the number (N) of item in need to modify in the legend. It means I will need to  create N lines in the script making the graphbuilder (I need to dispatch N lines with "legend box(properties(0...N)"). But if I build a graph with N+1 lines in the legend box it will work partly (the N+1th line will not be modified). Thus I need to make a loop either within the script making the graphbuilder (is it feasible?) or after the script making the graphbuilder (it makes more sense, but I am not able to find message(s) I can send to legendbox).

txnelson

Super User

Joined:

Jun 22, 2012

If you look at

     Help==>Scripting Index

and look at both the Graph Builder and the Legend Box() elements, manipulating the legend after the Graph Builder has run, is limited.  However, you can use a technique that works for anything, but is a bit cumbersom.  If you generate a literal string, that contains the code you need to get the Graph Builder to do what you want, you can then run that literal string.  Here is a very primitive example, but I think you will see what kinds of things you can do with it

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA\big class.jmp" );
Summarize( dt, groups = by( dt:sex ) );
numofgroups = N Items( groups );

TheCode =
"Graph Builder(
	Show Control Panel( 0 ),
	Variables( X( :height ), Y( :weight ), Overlay( :sex ) ),
	Elements( Points( X, Y, Legend( 1 ) ), Smoother( X, Y, Legend( 1 ) ) ),
	SendToReport(
		Dispatch(
			{},
			\!"400\!",
			ScaleBox,
			{Legend Model(
				1,";
For( i = 0, i <= numofgroups - 1, i++,
	Show( i );
	TheCode = TheCode || "Properties(" || Char( i ) || ", {Line Color (" || Char( i + 3 ) || "),Marker( " || Char( 16 - i ) || ")}),";
);
TheCode = TheCode || "Dispatch( {}, \!"400\!", LegendBox, {Legend Position( {1, [2, 3], 1, [0, 1]} ), Position( {2, 3, 0, 1} )} ))';";
Eval( Parse( TheCode ) );
Jim
ptijerome

Community Trekker

Joined:

Jun 17, 2014

It seems to be a good solution. I need now to adapt it to my case. Thanks a lot!

Just disappointed by row state!

ian_jmp

Staff

Joined:

Jun 23, 2011

Solution

As an alternative, you might consider using 'MarkerSeg'. In the code below 'dt' is a table of all the distinct levels of the column you wish to colour and mark by. You could use 'Tables > Summary' and make this invisible.

 

NamesDefaultToHere(1);

// Example data table (markers and colors assigned by 'Lot ID')
dt = New Table( "Rows With Colors and Markers",
					Add Rows( 12 ),
					New Column( "Lot ID",
						Character,
						"Nominal",
						Set Values(
							{"lot1", "lot10", "lot11", "lot12", "lot13", "lot2", "lot3", "lot4",
							"lot5", "lot6", "lot7", "lot8"}
						),
						Lock( 1 )
					),
					Set Row States(
						[896.813481688499, 1104.17848521471, 34064.2516910434, 1584.79095828533,
						1856.1745531559, 34848.5869575739, 35120.7292968035, 2704.17450988293,
						2976.75480300188, 3200.51829791069, 3408.21706777811, 36368.77437675]
					)
				);

// Make legend window with MarkerSeg
n = NRow(dt);
xx = J(n, 1, 1);
yy = Transpose(1::n);
legendList = Column(dt, "Lot ID") << getValues;
			gb = Graph Box(
					FrameSize( 150, 300*(n/16) ),
					Y Scale( 0, n+1 ),
					X Scale( 0, 6 ),
					Y Name(" "),
					X Name(" "),
					Y Axis(ShowLabels(0), ShowMajorTicks(0), ShowMinorTicks(0)),
					X Axis(ShowLabels(0), ShowMajorTicks(0), ShowMinorTicks(0)),
					Marker Seg( xx, yy, Row States( dt ) ),
					For( i = 1, i<=n, i++, Text( {1.5, i-0.1}, legendList[i] ) )
				);
db = PanelBox("Row State Colours and Markers for 'Lot ID'", gb);
New Window( "My Legend", db);

 

vince_faller

Super User

Joined:

Mar 17, 2015

I haven't figured out how to do it with a script but if you go to Rows>Color or Mark By Column
you get the following

 

3-14-2017 4-26-44 PM.png

 

Now you can right click on the legend and change it to whatever you want, and if you have "Make Window with Legend" selected it will create a legend for you.  This has the added benefit of selecting in the table anything you've selected in the legend.  

 

You can do the same inside scripting with:

Names Default to here(1);
dt = Open("$SAMPLE_DATA\Big CLass.jmp");
legend = dt << Marker By Column(:age);
new window("Not Really", 
	Hlistbox(
		bivariate(Y(:height), X(:weight)), 
		legend
	)
)

But you lose (at least I haven't found a way to do it) the customizabilty that you're after

 

ptijerome

Community Trekker

Joined:

Jun 17, 2014

Thanks Ian,

 

it is closer to my initial idea and it is easy to integrate in my script.

 

So I slightly prefer this solution, even though the other one works well.