cap program drop gen_graphviz_dot
program define gen_graphviz_dot
	version 13
	syntax [if] [in], dotout(str) input_groups(int) output_groups(int) input_groups_viz(int) output_groups_viz(int) showedges(int) lhs(int) rhs(int)

* List of categories in each group
* Input (number of groups might not be the same for input and output, so keeping separate
forvalues i = 1/`input_groups' {
	levelsof input_grp_lvl_`i', local(inp_`i')
	local input_grp_lvl_`i'_cnt : word count `inp_`i''
	di "`input_grp_lvl_`i'_cnt'"
	di `inp_`i''
}

* Output
forvalues i = 1/`output_groups' {
	levelsof output_grp_lvl_`i', local(out_`i')
	local output_grp_lvl_`i'_cnt : word count `out_`i''
	di "`output_grp_lvl_`i'_cnt'"
	di `out_`i''
}

* Find the level of the node
gen input_grp_lvl = .
forvalues i = `input_groups' (-1) 1 {
	replace input_grp_lvl = `i' if missing(input_grp_lvl) & !missing(input_grp_lvl_`i')
}
replace input_grp_lvl = 0 if missing(input_grp_lvl)

gen output_grp_lvl = .
forvalues i = `output_groups' (-1) 1 {
	replace output_grp_lvl = `i' if missing(output_grp_lvl) & !missing(output_grp_lvl_`i')
}
replace output_grp_lvl = 0 if missing(output_grp_lvl)


* file with edges
if `showedges' {
preserve
keep if input_grp_lvl <= `input_groups_viz' & output_grp_lvl <= `output_groups_viz'
keep predictor outcome
duplicates drop
tempfile edges
save `edges'
restore
}

* Initialize the file
qui file open outfile using `dotout'.dot, write text replace

* header with settings
file write outfile "digraph {" _n
file write outfile _tab "rankdir=LR;" _n
file write outfile _tab "nodesep=0.05;" _n
file write outfile _tab "ranksep=1.4;" _n
file write outfile _tab "splines=true;" _n
* file write outfile _tab `"sep="+25,25";"' _n
* file write outfile _tab "overlap=scalexy;" _n



* Build the groups-nodes

* input level 1
if `rhs' {
* loop over the groups at level 1
levelsof input_grp_lvl_1, local(inp_1)
local input_grp_lvl_1_cnt : word count `inp_1'
forvalues i = 1/`input_grp_lvl_1_cnt' {
	local subgroup_1 : word `i' of `inp_1'
	file write outfile _tab "subgraph cluster_in_`i' {" _n
	file write outfile _tab _tab "penwidth=3;" _n
	file write outfile _tab _tab `"label = "`subgroup_1'";"' _n

	* List any nodes at this level (i.e., in this group )
	levelsof predictor if input_grp_lvl == 1 & input_grp_lvl_1 == "`subgroup_1'", local(inp_nodes_1)
	di `inp_nodes_1'
	local inp_nodes_1_cnt : word count `inp_nodes_1'
	forvalues x = 1/`inp_nodes_1_cnt' {
		local node_out : word `x' of `inp_nodes_1'
		di "`node_out'"
		file write outfile _tab _tab `""`node_out'";"' _n
	}

	if `input_groups_viz' > 1 {

		* Level 2
		* Calculate the number of groups at level 2 that are in level 1
		levelsof input_grp_lvl_2 if input_grp_lvl_1 == "`subgroup_1'", local(inp_2)
		local input_grp_lvl_2_cnt : word count `inp_2'
		forvalues j = 1/`input_grp_lvl_2_cnt' {
			levelsof input_grp_lvl_2 if input_grp_lvl_1 == "`subgroup_1'", local(inp_subgrp_2)
			local subgroup_2 : word `j' of `inp_subgrp_2'
			file write outfile _tab _tab "subgraph cluster_in_`i'_`j' {" _n
			file write outfile _tab _tab _tab "penwidth=2;" _n
			file write outfile _tab _tab _tab `"label = "`subgroup_2'";"' _n


			* List any nodes at this level
			levelsof predictor if input_grp_lvl == 2 & input_grp_lvl_2 == "`subgroup_2'", local(inp_nodes_2)
			di `inp_nodes_2'
			local inp_nodes_2_cnt : word count `inp_nodes_2'
			forvalues y = 1/`inp_nodes_2_cnt' {
				local node_out : word `y' of `inp_nodes_2'
				di "`node_out'"
				file write outfile _tab _tab _tab `""`node_out'";"' _n
			}

			if `input_groups_viz' > 2 {

				* Level 3
				* Calculate the number of groups at level 3 that are in this particular level 2
				levelsof input_grp_lvl_3 if input_grp_lvl_2 == "`subgroup_2'", local(inp_3)
				local input_grp_lvl_3_cnt : word count `inp_3'
				forvalues k = 1/`input_grp_lvl_3_cnt' {
					levelsof input_grp_lvl_3 if input_grp_lvl_1 == "`subgroup_1'" & input_grp_lvl_2 == "`subgroup_2'", local(inp_subgrp_3)
					local subgroup_3 : word `k' of `inp_subgrp_3'
					file write outfile _tab _tab _tab `"subgraph cluster_in_`i'_`j'_`k' {"' _n
					file write outfile _tab _tab _tab _tab "penwidth=1;" _n
					file write outfile _tab _tab _tab _tab `"label = "`subgroup_3'";"' _n

				* List any nodes at this level
				levelsof predictor if input_grp_lvl == 3 & input_grp_lvl_3 == "`subgroup_3'", local(inp_nodes_3)
				di `inp_nodes_3'
				local inp_nodes_3_cnt : word count `inp_nodes_3'
				forvalues z = 1/`inp_nodes_3_cnt' {
					local node_out : word `z' of `inp_nodes_3'
					di "`node_out'"
					file write outfile _tab _tab _tab _tab `""`node_out'";"' _n
				}
				file write outfile _tab _tab _tab "}" _n
				} // close conditional for level 3
			} // Close level 3
			file write outfile _tab _tab "}" _n
		} // close conditional for level 2
	} // Close level 2
	file write outfile _tab "}" _n
}	// Close level 1
}

di "Are we here??????"

* output level 1
if `lhs' {
* loop over the groups at level 1
levelsof output_grp_lvl_1, local(out_1)
local output_grp_lvl_1_cnt : word count `out_1'
forvalues i = 1/`output_grp_lvl_1_cnt' {
	local subgroup_1 : word `i' of `out_1'
	file write outfile _tab "subgraph cluster_out_`i' {" _n
	file write outfile _tab _tab "penwidth=3;" _n
	file write outfile _tab _tab `"label = "`subgroup_1'";"' _n

	* List any nodes at this level (i.e., in this group )
	levelsof outcome if output_grp_lvl == 1 & output_grp_lvl_1 == "`subgroup_1'", local(out_nodes_1)
	di `out_nodes_1'
	local out_nodes_1_cnt : word count `out_nodes_1'
	forvalues x = 1/`out_nodes_1_cnt' {
		local node_out : word `x' of `out_nodes_1'
		di "`node_out'"
		file write outfile _tab _tab `""`node_out'";"' _n
	}

	if `output_groups_viz' > 1 {

		* Level 2
		* Calculate the number of groups at level 2 that are in level 1
		levelsof output_grp_lvl_2 if output_grp_lvl_1 == "`subgroup_1'", local(out_2)
		local output_grp_lvl_2_cnt : word count `out_2'
		forvalues j = 1/`output_grp_lvl_2_cnt' {
			levelsof output_grp_lvl_2 if output_grp_lvl_1 == "`subgroup_1'", local(out_subgrp_2)
			local subgroup_2 : word `j' of `out_subgrp_2'
			file write outfile _tab _tab "subgraph cluster_out_`i'_`j' {" _n
			file write outfile _tab _tab _tab "penwidth=2;" _n
			file write outfile _tab _tab _tab `"label = "`subgroup_2'";"' _n


			* List any nodes at this level
			levelsof outcome if output_grp_lvl == 2 & output_grp_lvl_2 == "`subgroup_2'", local(out_nodes_2)
			di `out_nodes_2'
			local out_nodes_2_cnt : word count `out_nodes_2'
			forvalues y = 1/`out_nodes_2_cnt' {
				local node_out : word `y' of `out_nodes_2'
				di "`node_out'"
				file write outfile _tab _tab _tab `""`node_out'";"' _n
			}

			if `output_groups_viz' > 2 {

				* Level 3
				* Calculate the number of groups at level 3 that are in this particular level 2
				levelsof output_grp_lvl_3 if output_grp_lvl_2 == "`subgroup_2'", local(out_3)
				local output_grp_lvl_3_cnt : word count `out_3'
				forvalues k = 1/`output_grp_lvl_3_cnt' {
					levelsof output_grp_lvl_3 if output_grp_lvl_1 == "`subgroup_1'" & output_grp_lvl_2 == "`subgroup_2'", local(out_subgrp_3)
					local subgroup_3 : word `k' of `out_subgrp_3'
					file write outfile _tab _tab _tab `"subgraph cluster_out_`i'_`j'_`k' {"' _n
					file write outfile _tab _tab _tab _tab "penwidth=1;" _n
					file write outfile _tab _tab _tab _tab `"label = "`subgroup_3'";"' _n

				* List any nodes at this level
				levelsof outcome if output_grp_lvl == 3 & output_grp_lvl_3 == "`subgroup_3'", local(out_nodes_3)
				di `out_nodes_3'
				local out_nodes_3_cnt : word count `out_nodes_3'
				forvalues z = 1/`out_nodes_3_cnt' {
					local node_out : word `z' of `out_nodes_3'
					di "`node_out'"
					file write outfile _tab _tab _tab _tab `""`node_out'";"' _n
				}
				file write outfile _tab _tab _tab "}" _n
				} // close conditional for level 3
			} // Close level 3
			file write outfile _tab _tab "}" _n
		} // close conditional for level 2
	} // Close level 2
	file write outfile _tab "}" _n
}	// Close level 1
}




* Build the edges
if `showedges' {
	use `edges', replace
	local cnt = _N
	forvalues i = 1/`cnt' {
		local pred = predictor[`i']
		local outc = outcome[`i']
		* Add this back once the group structure is built
		file write outfile `"	"`pred'"->"`outc'";"' _n
	}
}

* Close the file
file write outfile "}"
file close outfile

end