<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: How to programmatically traverse a Graph builder tree structure and associate frameboxes with their titles. in Discussions</title>
    <link>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697352#M88290</link>
    <description>&lt;P&gt;GFrameBoxes are sorted in specific order (might be a good idea to force it using Value Order column property). You can get the framebox index based on that order&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;cluster_rows = Loc(dt[0, "ENT_CLUSTER"], "XXX104_CLUSTER1");
fb_idx = Contains(clusters, "XXX104_CLUSTER1"); // framebox idx // might not work in all cases!
fbs = Report(myGraphBox) &amp;lt;&amp;lt; XPath("//FrameBox");
Eval(EvalExpr(
	fbs[fb_idx] &amp;lt;&amp;lt; Add Graphics Script(
		Pen Color("Black");
		Fill Color("Red");
		Transparency(0.1);
		Rect(Expr(left), Expr(top), Expr(right), Expr(bot), 0);
		Rect(Expr(left), Expr(top), Expr(right), Expr(bot), 1);
	);	
));&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Also remember to evaluate the values into graphic script, so you won't end up with this.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_0-1699875428523.png" style="width: 400px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/58630iC3B3C6A9E5FFE0FE/image-size/medium?v=v2&amp;amp;px=400" role="button" title="jthi_0-1699875428523.png" alt="jthi_0-1699875428523.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In general&amp;nbsp;GraphBuilderGroupBox are very difficult to access/manipulate and I would try to avoid it as much as possible. You can get the titles with XPath, but there can be extra titles&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;(Report(myGraphBox) &amp;lt;&amp;lt; XPath("//GraphBuilderGroupBox/text()"))&lt;/CODE&gt;&lt;/PRE&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;{"ENTITY", "XXX101", "XXX102", "XXX103", "XXX104", "XXX105", "XXX106", "XXX107","XXX112", "XXX118", "XXX119"}&lt;/CODE&gt;&lt;/PRE&gt;</description>
    <pubDate>Mon, 13 Nov 2023 11:41:21 GMT</pubDate>
    <dc:creator>jthi</dc:creator>
    <dc:date>2023-11-13T11:41:21Z</dc:date>
    <item>
      <title>How to programmatically traverse a Graph builder tree structure and associate frameboxes with their titles.</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697329#M88289</link>
      <description>&lt;P&gt;I have a piece of analysis (see below) where I want to annotate specific charts using a script I have written. For example, I want to add annotation to XXX104 and XXX107. On both of these charts I will add a custom graphic and text to identify a cluster of points I want to draw attention to.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chart.jpg" style="width: 999px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/58617iF15ABE38B25C2B91/image-size/large?v=v2&amp;amp;px=999" role="button" title="chart.jpg" alt="chart.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Using the command '&amp;lt;&amp;lt; show tree structure' I can identify the frameboxs which have each chart. However, I do not see the chart 'name' associated with them. For example, I want to be able to traverse this tree using the chart names (e.g. XXX107) as a lookup and identify the associated framebox (e.g. FrameBox(7)) so I can reference it and add my annotation in an automated fashion.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chart2.jpg" style="width: 520px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/58619iFBD00B3C9F1480E1/image-size/large?v=v2&amp;amp;px=999" role="button" title="chart2.jpg" alt="chart2.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;In fact in the entire tree I do not see any 'tree nodes' which have the 'chart names' such as XXX107&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Ultimately the chart below is what I want to achieve&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="chart.jpg" style="width: 999px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/58621i7BDA43687841FE41/image-size/large?v=v2&amp;amp;px=999" role="button" title="chart.jpg" alt="chart.jpg" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here is the code which I used to do this manually. The file is also uploaded.&amp;nbsp;&lt;/P&gt;&lt;P&gt;My issue is I cannot figure out how to reference a framebox by identifying it's corresponding 'title' in the display tree.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Cheers, Troy&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;clearLog();
try(close(DT, noSave));
DT = open("PRE_CLEAN_DATA.jmp", invisible);
DT &amp;lt;&amp;lt; newColumn("ENT_CLUSTER", character, nominal, formula(:ENTITY || "_" || :CLUSTER));

Plat = newWindow("CHART",
	myGraphBox = DT &amp;lt;&amp;lt; Graph Builder(
		Size( 1446, 747 ),
		Show Control Panel( 0 ),
		Variables(
			X( :WW ),
			Y( :ENTITY_MEAN ),
			Y( :GRAND_MEAN, Position( 1 ) ),
			Wrap( :ENTITY ),
			Color( :CLUSTER )
		),
		Elements(
			Points( X, Y( 1 ), Y( 2 ), Legend( 23 ) ),
			Smoother( X, Y( 1 ), Y( 2 ), Legend( 24 ) )
		),
		SendToReport(
			Dispatch(
				{},
				"WW",
				ScaleBox,
				{Min( 202301.28 ), Max( 202320.72 ), Inc( 1 ), Minor Ticks( 1 ),
				Label Row(
					{Automatic Tick Marks( 0 ), Label Orientation( "Vertical" ),
					Show Minor Ticks( 0 )}
				)}
			)
		)
	);
	
	summarize(DT, clusters = by(:ENT_CLUSTER));
	foreach({item}, clusters,
		if(contains(item, "NON_CLUSTER"), continue());
		
		ent = word(1, item, "_");
		clust = word(2, item, "_");
		write("Entity = " || ent || "\!n");
		write("Cluster = " || clust || "\!n");
		
		left = min(DT:WW[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
		right = max(DT:WW[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
		group_mean_min = min(DT:ENTITY_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
		group_mean_max = max(DT:ENTITY_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
		grand_mean_min = min(DT:GRAND_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
		grand_mean_max = max(DT:GRAND_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
		if(group_mean_min &amp;lt; grand_mean_min, bot = group_mean_min, bot = grand_mean_min);
		if(group_mean_max &amp;gt; grand_mean_max, top = group_mean_max, top = grand_mean_max);
		write("Left, Right, Top, Bot = " || char(left) || ", " || char(right) || ", " || char(top) || ", " || char(bot) || "\!n");
		
		// ##########################################################
		// ## This is what I want to do:
		// ##########################################################
		//  1. Traverse the graphbox tree
		//  2.  Identify Frame Box for each of the entities found
		//  3.  Get the Framebox Reference
		//  4.  Add my annotation.
		

		// This is a manual Example I made using the show properties and tree structure commands
		//myGraphBox &amp;lt;&amp;lt; Show Properties();
		//myGraphBox &amp;lt;&amp;lt; Show tree structure();
		rep = myGraphBox &amp;lt;&amp;lt; report;
		framebox = rep[frame box( 7 )];
		framebox &amp;lt;&amp;lt; Add Graphics Script(
			penColor( "Black" );
			fillcolor("Blue");
			Transparency(0.1);
			rect( left, top, right, bot, 0 );
			rect( left, top, right, bot, 1 );
		);
		framebox &amp;lt;&amp;lt; Add Graphics Script(
			textSize(9);
			textColor("Blue");
			text( {left, top}, "Cluster 1" );
		);
		
		write("\!n");
	);
	
);&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 13 Nov 2023 11:11:49 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697329#M88289</guid>
      <dc:creator>thickey</dc:creator>
      <dc:date>2023-11-13T11:11:49Z</dc:date>
    </item>
    <item>
      <title>Re: How to programmatically traverse a Graph builder tree structure and associate frameboxes with their titles.</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697352#M88290</link>
      <description>&lt;P&gt;GFrameBoxes are sorted in specific order (might be a good idea to force it using Value Order column property). You can get the framebox index based on that order&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;cluster_rows = Loc(dt[0, "ENT_CLUSTER"], "XXX104_CLUSTER1");
fb_idx = Contains(clusters, "XXX104_CLUSTER1"); // framebox idx // might not work in all cases!
fbs = Report(myGraphBox) &amp;lt;&amp;lt; XPath("//FrameBox");
Eval(EvalExpr(
	fbs[fb_idx] &amp;lt;&amp;lt; Add Graphics Script(
		Pen Color("Black");
		Fill Color("Red");
		Transparency(0.1);
		Rect(Expr(left), Expr(top), Expr(right), Expr(bot), 0);
		Rect(Expr(left), Expr(top), Expr(right), Expr(bot), 1);
	);	
));&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Also remember to evaluate the values into graphic script, so you won't end up with this.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_0-1699875428523.png" style="width: 400px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/58630iC3B3C6A9E5FFE0FE/image-size/medium?v=v2&amp;amp;px=400" role="button" title="jthi_0-1699875428523.png" alt="jthi_0-1699875428523.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In general&amp;nbsp;GraphBuilderGroupBox are very difficult to access/manipulate and I would try to avoid it as much as possible. You can get the titles with XPath, but there can be extra titles&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;(Report(myGraphBox) &amp;lt;&amp;lt; XPath("//GraphBuilderGroupBox/text()"))&lt;/CODE&gt;&lt;/PRE&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;{"ENTITY", "XXX101", "XXX102", "XXX103", "XXX104", "XXX105", "XXX106", "XXX107","XXX112", "XXX118", "XXX119"}&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Mon, 13 Nov 2023 11:41:21 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697352#M88290</guid>
      <dc:creator>jthi</dc:creator>
      <dc:date>2023-11-13T11:41:21Z</dc:date>
    </item>
    <item>
      <title>Re: How to programmatically traverse a Graph builder tree structure and associate frameboxes with their titles.</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697380#M88291</link>
      <description>&lt;P&gt;Quick and dirty full example:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-jsl"&gt;Names Default To Here(1);

dt = Open("$DOWNLOADS/PRE_CLEAN_DATA.jmp", invisible);
dt &amp;lt;&amp;lt; New Column("ENT_CLUSTER", character, nominal, formula(:ENTITY || "_" || :CLUSTER));

gb = dt &amp;lt;&amp;lt; Graph Builder(
	Size(1446, 747),
	Show Control Panel(0),
	Variables(X(:WW), Y(:ENTITY_MEAN), Y(:GRAND_MEAN, Position(1)), Wrap(:ENTITY), Color(:CLUSTER)),
	Elements(Points(X, Y(1), Y(2), Legend(23)), Smoother(X, Y(1), Y(2), Legend(24))),
	SendToReport(
		Dispatch(
			{},
			"WW",
			ScaleBox,
			{Min(202301.28), Max(202320.72), Inc(1), Minor Ticks(1), Label Row(
				{Automatic Tick Marks(0), Label Orientation("Vertical"), Show Minor Ticks(0)}
			)}
		)
	)
);
rep = Report(gb);
fbtitles = (rep &amp;lt;&amp;lt; XPath("//GraphBuilderGroupBox/text()"));
Remove From(fbtitles, Contains(fbtitles, "ENTITY")); // we "know" we have wrap variable 
// or we could perform filtering using Filter Each

Summarize(dt, clusters = by(:ENT_CLUSTER));

For Each({item}, clusters,
	If(Contains(item, "NON_CLUSTER"),
		Continue()
	);
	
	ent = Word(1, item, "_");
	clust = Word(2, item, "_");
	Write("Entity = " || ent || "\!n");
	Write("Cluster = " || clust || "\!n");
	
	left = Min(DT:WW[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
	right = Max(DT:WW[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
	group_mean_min = Min(DT:ENTITY_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
	group_mean_max = Max(DT:ENTITY_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
	grand_mean_min = Min(DT:GRAND_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
	grand_mean_max = Max(DT:GRAND_MEAN[DT &amp;lt;&amp;lt; getRowsWhere(:ENT_CLUSTER == item)]);
	If(group_mean_min &amp;lt; grand_mean_min,
		bot = group_mean_min,
		bot = grand_mean_min
	);
	If(group_mean_max &amp;gt; grand_mean_max,
		top = group_mean_max,
		top = grand_mean_max
	);
	Write("Left, Right, Top, Bot = " || Char(left) || ", " || Char(right) || ", " || Char(top) || ", " || Char(bot) || "\!n");
	
	framebox = rep[frame box(Contains(fbtitles, ent);)];
	Eval(EvalExpr(
		framebox &amp;lt;&amp;lt; Add Graphics Script(
			Pen Color("Black");
			Fill Color("Blue");
			Transparency(0.1);
			Rect(Expr(left), Expr(top), Expr(right), Expr(bot), 0);
			Rect(Expr(left), Expr(top), Expr(right), Expr(bot), 1);
		);
		
	));
	Eval(EvalExpr(
		framebox &amp;lt;&amp;lt; Add Graphics Script(
			Text Size(9);
			Text Color("Blue");
			Text({Expr(left), Expr(top)}, Expr(clust));
		);
	));
	Write("\!n");
);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="jthi_0-1699879213845.png" style="width: 400px;"&gt;&lt;img src="https://community.jmp.com/t5/image/serverpage/image-id/58631i0BE6BD9EFA541B61/image-size/medium?v=v2&amp;amp;px=400" role="button" title="jthi_0-1699879213845.png" alt="jthi_0-1699879213845.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;(I have done something a bit like this earlier for wafermaps)&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 13 Nov 2023 12:41:09 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697380#M88291</guid>
      <dc:creator>jthi</dc:creator>
      <dc:date>2023-11-13T12:41:09Z</dc:date>
    </item>
    <item>
      <title>Re: How to programmatically traverse a Graph builder tree structure and associate frameboxes with their titles.</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697400#M88293</link>
      <description>&lt;P&gt;Thanks for the help Jarmo.&lt;/P&gt;&lt;P&gt;I've not done a whole pile of work on traversing these trees but the way you explain it is great.....perhaps this one could be a topic for next years scripters club :)&lt;/img&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Cheers, Troy&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 13 Nov 2023 13:23:17 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697400#M88293</guid>
      <dc:creator>thickey</dc:creator>
      <dc:date>2023-11-13T13:23:17Z</dc:date>
    </item>
    <item>
      <title>Re: How to programmatically traverse a Graph builder tree structure and associate frameboxes with their titles.</title>
      <link>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697401#M88294</link>
      <description>&lt;P&gt;Going deeper into the report layer could definitely be one good topic.&lt;/P&gt;</description>
      <pubDate>Mon, 13 Nov 2023 13:26:40 GMT</pubDate>
      <guid>https://community.jmp.com/t5/Discussions/How-to-programmatically-traverse-a-Graph-builder-tree-structure/m-p/697401#M88294</guid>
      <dc:creator>jthi</dc:creator>
      <dc:date>2023-11-13T13:26:40Z</dc:date>
    </item>
  </channel>
</rss>

