/*** DO NOT EDIT THIS LINE -----------------------------------------------------
Version:
Title: semdiagram
Description: executes {help sem} one-factor measurement model and produces
 dynamic path diagram for
 [diagram](www.haghish.com/diagram/diagram.php) package
----------------------------------------------------- DO NOT EDIT THIS LINE ***/


/***
Syntax
======

{p 8 16 2}
{cmd: semdiagram} [:] _{help sem} or {help gsem} command_
{p_end}

Description
===========

The __semdiagram__ provides an "example" for generating dynamic path diagram, using
Stata __sem__ command. It takes a Stata __sem__ or __gsem__ command and
produces a dynamic path diagram. Currently, it is only supporting a
_one-factor measurement model_. Similar to __sem__ and __gsem__ commands,
the path direction can be from right to left or left to write (see the example).
__semdiagram__ produces a dynamic path diagram named _semdiagram.gv_ that can be rendered
and exported to a graphical file using {help diagram} package.

This program was meant to be used as an example for automating path diagrams
from Stata. If you wish to improve the program to support more sophisticated
__sem__ models, [fork diagram package on GitHub](https://github.com/haghish/diagram).

Example(s)
=================

    Setup
        . webuse sem_1fmm

    A one-factor measurement model
        . semdiagram sem (X->x1) (X->x2) (X->x3) (X->x4)

    Or alternatively
        . semdiagram sem (x1<-X) (x2<-X) (x3<-X) (x4<-X)

    semdiagram creates {it:semdiagram.gv} file which can be exported to a graphical image
        . diagram using semdiagram.gv, export(semdiagram.png)

Stored results
=================

__semdiagram__ stores the SEM output in a matrix:

{synoptset 20 tabbed}{...}
{p2col 5 20 24 2: Matrix}{p_end}
{synopt:{cmd:r(table)}}results of the SEM command{p_end}

Author
======

__E. F. Haghish__
Center for Medical Biometry and Medical Informatics
University of Freiburg, Germany
_and_
Department of Mathematics and Computer Science
University of Southern Denmark
haghish@imbi.uni-freiburg.de

[http://www.haghish.com/markdoc](http://www.haghish.com/statistics/stata-blog/reproducible-research/markdoc.php)
Package Updates on [Twitter](http://www.twitter.com/Haghish)

- - -

_This help file was dynamically produced by[MarkDoc Literate Programming package](http://www.haghish.com/markdoc/)_
***/




*cap prog drop semdiagram
program define semdiagram, rclass
  *version 8

   // -------------------------------------------------------------------------
	// Syntax processing
	// =========================================================================

	// Check if the command includes Colon in the beginning
	if substr(trim(`"`macval(0)'"'),1,1) == ":" {
		local 0 : subinstr local 0 ":" ""
	}

	local command `"`macval(0)'"'

	if substr(trim("`0'"),1,3) == "sem" {
		local 0 : subinstr local 0 "sem" ""
	}
	else if substr(trim("`0'"),1,4) == "gsem" {
		local 0 : subinstr local 0 "gsem" ""
	}

	// Execute the code
	`command'
	mat define R = r(table)

	scalar ncols = colsof(R)


	// Export the filename!
	tempfile edited
	tempname knot
	qui file open `knot' using "`edited'", write text replace
	file write `knot' "digraph G {" _n  ///
		`"fontname="sans-serif";splines="line";penwidth="0.1";"' _n ///
		`"edge [arrowsize="0.7", fontname="sans-serif", fontsize=10, colorscheme="greys5", color="2", fontcolor="5"];"' _n ///
		`"node [fontname="serif", fontsize=12,fillcolor="1",colorscheme="greys3",color="2", fontcolor="4",style="filled"];"' _n




	local i 0		// for variable numbers
	local j 0 		// for columns of the matrix
	local k : di 2*((ncols-1)/3)

	local latentvar

	while "`0'" ~= "" {
		gettoken open 0 : 0, parse("(")
		if `"`open'"' != "(" {
			error 198
		}
		gettoken next 0 : 0, parse(")")

		while `"`next'"' != ")" {
			if `"`next'"'=="" {
				error 198
			}
		  local list `next'
		  gettoken next 0 : 0, parse(")")
		}

		// Memorize the list of latent variables. The graph is developed in a loop
		// and information about the same latent variable should not be rewritten.
		// ---------------------------------------------------------------------


		local i `++i'
		local jump 								//reset
		file write `knot' _n					// add an empty line

		local j `++j'
		local b = R[1,`j']
		local b : di round(R[1,`j'],.1)

		local j `++j'
		local con : di %2.1g R[1,`j']
		local con : di trim("`con'")

		local k `++k'
		local e : di round(R[1,`k'])

		// REPLACE THE DIRECTION
		if strpos("`list'","<-") != 0 {
			local br = strpos("`list'","<-")
			local l1 = trim(substr("`list'",1, `br'-1))
			local l2 = trim(substr("`list'",`br'+2,.))
			local list = `"    `macval(l2)' -> `macval(l1)' [label="`b'"];"'
		}
		else if strpos("`list'","->") != 0 {
			local br = strpos("`list'","->")
			local l2 = trim(substr("`list'",1, `br'-1))
			local l1 = trim(substr("`list'",`br'+2,.))
			local list = `"    `macval(l2)' -> `macval(l1)' [label="`b'"];"'
		}


		if missing("`latentvar'") {
				local lat : di %2.1g R[1,ncols]
				local lat : di trim("`lat'")
				file write `knot' `"    `l2' [width="1.05", height="0.7", label="`l2'\n`lat'"];"' _n(2)
				local latentvar = "`l2'"
				local jump 1
			}
			else {
				local latentvar "`latentvar' `l2'"
				tokenize "`latentvar'"
				while "`1'" != "" {
					if "`1'" == "`l2'" {
						local jump 1
						break
					}
					macro shift
				}
			}

			// Write the additional latent variables
			if missing("`jump'") {
				file write `knot' `"    `l2' [width="1.05", height="0.7", label="`l2'\n`lat'"];"' _n
			}

			// Write the Node
			file write `knot' `"    `l1' [width="1.05", shape="plain", height="0.6", label="`l1'\n`con'"];"' _n

			// Write the error Node
			file write `knot' `"    e`i' [width="0.3", shape="circle",fontsize="8",label="e`i'\n`e'"];"' _n

			* di as err `"First Group:`i':`list'"'

			file write `knot' `"`macval(list)'"' _n

			// Adding the errors
			file write `knot' `"    `l1' -> e`i'  [dir="back"];"' _n

	}

	file write `knot' "}"
	qui file close `knot'
	copy "`edited'" semdiagram.gv, replace

	return matrix table = R

	// report the results
	cap confirm file "semdiagram.gv"
	if _rc == 0 {
		di as txt "(sempdiagram created "`"{bf:{browse "semdiagram.gv"}})"' _n
	}
	else display as err "sempdiagram could not produce semdiagram.gv" _n


end

/*
*use "http://www.ats.ucla.edu/stat/data/hsb2", clear
*pathreg2 (read write[dir="both"])(math read[] write[])(science math[] read[] write[])

*semdiagram : sem (x1<-X) (x2 <- X) (x3<-X) (x4<-X)


markdoc semdiagram.ado, export(sthlp) replace