/*** DO NOT EDIT THIS LINE -----------------------------------------------------
Title: makediagram
Description: generates DOT diagram file from data sets
----------------------------------------------------- DO NOT EDIT THIS LINE ***/


/***
Syntax
======

{p 8 16 2}
{cmd: makediagram} [{help using} {it:filename}] {cmd:,}
{it:export(filename)} [ {it:replace} {it:graphtype(name)}
{it:style(filename)} ]
{p_end}

{* the new Stata help format of putting detail before generality}{...}
{synoptset 20 tabbed}{...}
{synopthdr}
{synoptline}
{synopt:{opt e:xport(filename)}}export the DOT diagram file. {p_end}
{synopt:{opt graphtype(name)}}specifies the type of the graph which can
be {bf:digraph} (default) or {bf:graph} (i.e. undirected). {p_end}
{synopt:{opt replace}}replace the exported DOT file{p_end}
{synopt:{opt style(filename)}}appends an external DOT style sheet to the DOT file.{p_end}
{synoptline}
{p2colreset}{...}

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

__makediagram__ generates a [DOT](http://en.wikipedia.org/wiki/Dot) file from
a data set that can be rendered to a graphical file using {help diagram} program
within Stata. the data set should be prepared as explained in the next section.


Variable discription
====================

The data set should have 5 variables named __cluster__ (numeric), __from__
(numeric or string), __to__ (numeric or string), __label__ (string), and
__properties__ (string). The numeric variables can have labels which also changes
the labels in the DOT file.


   cluster     from       to        label     properties
   ---------   --------   --------  -------   -----------
   numeric     numeric    numeric   string    string
   or          or         or
   string      string     string



the __cluster__, __label__, and __properties__ can be missing. however, the
__from__ and __to__ variables specifies which nodes are connected to one another.
in directed graphs, the direction is __"from"__ towards __"to"__. However, in
undirected graphs, this direction is of no significance and only shows a connection.

the __cluster__ variable defines in which subgraph the connection takes place
(see the examples)

the __from__ and __to__ variables specify the nodes where the connection begines and
ends. the variables can be numeric, e.g. the nodes can be {bf:1 -> 2} or strings
such as {bf:A -> B} or {bf:"Node A" -> "Node B"}. If the variables are numeric,
their label is automatically used to alter the labels of the DOT graph (see the examples).

the __label__ variable simply "labels the connection". this merely specifies the "label" or
"value" for the arrow. the label of the connection can also be specified within the
__properties__ variable, but due to its common use and importance
(_and to make life easier for those who don't wish to learn the DOT language_),
it is made available as a separate variable. yet, adding __label="__ _label_ __"__
in the __properties__ variable can change the connection label.

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

the [diagram torture test](https://raw.githubusercontent.com/haghish/diagram/master/torture_test.do)
includes several examples and example data sets for testing the package.

    exporting a directed DOT script file from a data set
        . makediagram using name.dta, export("name.txt") label("diagram's label")

    exporting undirected DOT script file
        . makediagram using name.dta, export("name.txt") graphtype(graph)

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 {help markdoc:MarkDoc Literate Programming package}
***/

*cap prog drop makediagram
prog define makediagram
	version 11
	syntax [using/] , Export(str) [replace] [GRAPHtype(name)]  		///
	[style(str)]

	// -------------------------------------------------------------------------
	// Make sure the data is .dta; initiate the diagram text file
	// =========================================================================
	if !missing("`using'") {
		if (!index(lower("`using'"),".dta")) {
			di as err "specified data is not supported"
			err 198
		}
	}
	if "`graphtype'" == "graph" {
		local source "graph G {"
		local sign --
	}
	else if "`graphtype'" == "digraph" | missing("`graphtype'") {
		local source "digraph G {"
		local sign ->
	}
	else {
		di as err "{bf:graphtype} invalid"
		err 198
	}

	tempfile tmp
	tempname knot
	qui file open `knot' using "`tmp'", write replace
	file write `knot' "`source'" _n

	// adding external style
	// -------------------------------------------------------------------------
	if !missing("`style'") {
		confirm file "`style'"
		tempname hitch
		qui file open `hitch' using "`style'", read
		file read `hitch' line
		while r(eof)==0 {
			*local source = `"`macval(source)'"' +  `"`macval(line)'"'
			file write `knot' `"`macval(line)'"' _n
			file read `hitch' line
		}
	}


	// -------------------------------------------------------------------------
	// Loading the specified data set, if specified
	// =========================================================================
	if !missing("`using'") {
		preserve
		qui use "`using'", clear
	}

	// -------------------------------------------------------------------------
	// Testing the data set variables
	// =========================================================================

	// Check if cluster variable exists:
	// IF cluster variable exists and it is missing, OR IF it does not exist:
	// ELSE if it exists and not missing:
	// -------------------------------------------------------------------------
	capture confirm variable cluster
	if _rc == 0 {
		if missing(cluster) {
			file close `knot'
			diagramconnection , tempfile("`tmp'") sign(`sign')
			file open `knot' using "`tmp'", write append
		}
		else {

			//check if cluster is string
			cap confirm string variable cluster
			if _rc == 0 local clusterisstring 1
			qui drop if missing(cluster)							//drop missing values

			*sort cluster
			tempfile master
			qui save `master'
			clear
			qui use `master'

			//first evaluate when cluster observation is not missing
			//if cluster is string, the missings come first

			local current : di cluster[1]
			while !missing(cluster[1]) {

				qui keep if cluster == cluster[1]

				if missing("`clusterisstring'") {
					local nme : di "`: label (cluster) `=cluster[1]''" // label
				}
				if !missing("`clusterisstring'") {
					if substr(cluster[1], 1,1) == `"""' {
						local current : di substr(`"`macval(current)'"',2,.)
					}
					if substr(cluster[1], -1,1) == `"""' {
						local current : di substr(`"`macval(current)'"',1,strlen(`"`macval(current)'"')-1)
					}
					local nme `"`macval(current)'"' 					// label

					//remove white space
					local current : subinstr local current " " "", all
				}


					file write `knot' "    subgraph cluster_`current' {" _n
					if !missing("`nme'") file write `knot' `"        label="`nme'";"' _n

					file close `knot'
					diagramconnection , tempfile("`tmp'") sign(`sign') indent("    ")
					file open `knot' using "`tmp'", write append
					file write `knot' "    }" _n

					qui use `master', clear
					qui drop if cluster == cluster[1]
					qui save `master', replace
					local current : di cluster[1]
			}

			*else {
			*	qui drop if missing(cluster)
			*}

			//evaluate for observations with missing cluster
			*qui use "`using'", clear
			if !missing("`using'") {
				qui use "`using'", clear
			}

			//evaluate arguments when cluster is missing
			qui keep if missing(cluster)
			file close `knot'
			diagramconnection , tempfile("`tmp'") sign(`sign')
			file open `knot' using "`tmp'", write append
		}
	}

	//if missing cluster variable...
	else {
		file close `knot'
		diagramconnection , tempfile("`tmp'") sign(`sign')
		file open `knot' using "`tmp'", write append
	}


	file close `knot'
	if !missing("`using'") local use using "`using'"
	diagramnode `use' , tempfile("`tmp'")
	file open `knot' using "`tmp'", write append

	file write `knot' "}" _n
	file close `knot'
	copy "`tmp'" "`export'", `replace'

	if !missing("`using'") restore

	cap confirm file "`export'"
	if _rc == 0 {
		di as txt "{p}({bf:makediagram} created "`"{bf:{browse "`export'"}})"' _n
	}
	else display as err "{bf:makediagram} could not produce `export'" _n
end



* markdoc makediagram.ado, export(sthlp) replace ascii
* markdoc makediagram.ado, export(pdf) replace style(stata)  linesize(200)

*makediagram, export(sth.txt) replace