program def anovaplot7, sort 
*! renamed 14 Feb 2003  
*! 1.1.2 NJC 27 Sept 2001 
	version 7.0
	syntax [varlist(max=3 numeric default=none)] /* 
	*/ [ , Connect(str) L1title(str) Symbol(str) XLAbel XLAbel(str) /* 
	*/ YLAbel YLabel(str) SOrt TItle(str) * ]

	* initial checking and picking up what -anova- leaves behind 
	if "`e(cmd)'" != "anova" { 
		di as err "anova estimates not found" 
		exit 301 
	} 

	local covars "`e(varnames)'" 
	local ncovars : word count `covars'
	if `ncovars' > 3 { 
		di as err "too many covariates: should be 1, 2 or 3" 
		di as txt "(covariates: `covars')" 
		exit 103 
	} 	

	if "`varlist'" != "" { 
		local nvars : word count `varlist' 
		if `nvars' != `ncovars' { 
			Nomatch "`varlist'" "`covars'" 
		}	
         	foreach var of local varlist {
			local found = 0 
			foreach cov of local covars { 
				if "`cov'" == "`var'" { 
					local found = 1 
				}	
			}
			if !`found' { 
				Nomatch "`varlist'" "`covars'"  
			}
		}
		local covars "`varlist'" 
	}	

	local response "`e(depvar)'" 
	tokenize `response' `covars' 
	args y x1 x2 x3

	if "`x2'" != "" {
		qui tab `x2' if e(sample) 
		if r(r) > 19 { 
			di as error "too many groups in `x2': maximum 19" 
			exit 198 
		}
		local nlines = r(r) 
	}	
	else local nlines = 1 

	* get fit 
        tempvar fit
	qui predict `fit' if e(sample) 

	* this depends on Stata 7 dropping variables with a tempname as stub 
	if "`x2'" != "" { 
		tempname sep 
		qui separate `fit', by(`x2') gen(`sep')
	        unab fits : `sep'* 
		
		* fix variable labels 
		foreach v of varlist `fits' { 
			local label : variable label `v'
			local pos = index(`"`label'"',",") 
			local label = substr(`"`label'"',`pos' + 2,.)
			label variable `v' `"`label'"' 
		} 
	} 
	else local fits "`fit'"

	* set up graph defaults 
	if "`connect'" == "" { 
		local l : di _dup(`nlines') "l" 
		local connect ".`l'" 
	}
	
	* -anova_terms- added to Stata 6 Sept 2001
	if "`symbol'" == "" { 
		capture anova_terms 
		if _rc == 0 { 
			if "`x1'" == "`r(continuous)'" { 
				local nfits : word count `fits' 
				local invis : di _dup(`nfits') "i" 
			} 	
		} 	
		if "`invis'" == "" { 
			if "`x2'" != "" { 
				local symbol "[`x2']OSTopxdOSTopxdOSTop" 
			} 	
			local symbol "OSTopxdOSTopxdOSTopx"
		} 	
		else { 
			if "`x2'" != "" { 
				local symbol "[`x2']`invis'" 
			} 	
			else local symbol "O`invis'" 
		} 	
	}
	
	if `"`l1title'"' == "" { 
		local what : variable label `y'
		if `"`what'"' == "" { local what "`y'" } 
		if substr("`symbol'",1,1) == "i" { 
			local l1title "fit for `what'" 
		}
		else local l1title "data and fit for `what'" 
	} 
	
	if "`ylabel'" == "" { local yl "ylabel" } 
	else if "`ylabel'" != "ylabel" { local yl "yla(`ylabel')" }
	
	if "`xlabel'" == "" { local xl "xlabel" } 
	else if "`xlabel'" != "xlabel" { local xl "xla(`xlabel')" } 

	if "`x3'" != "" { 
		local byby "by(`x3')" 
		sort `x3'  
	} 

	if "`title'" == "" { local title " " } 
	
	* graph
	gra `y' `fits' `x1' if e(sample), co(`connect') l1(`"`l1title'"') /* 
	*/ ti(`"`title'"') sort `xl' `yl' s(`symbol') `byby' `options'  

end

program def Nomatch 
	version 7
	args v c 
	di as txt "`v'" as err " not a permutation of " as txt "`c'"
	exit 498 
end

/* Possibilities for future, suggested by Ken Higbee 7 Sept 2001: 

For small datasets plotting the points can be helpful, but even in those cases,
I find that the data labels (or even just plain numbers) fill up the plot to
the point that you can not see the forest because of all the trees.  I think
that an easier to view plot could be produced using more of an approach like
the -serrbar- command.  I am thinking along the lines of using -adjust- which
in addition to giving you the linear predictions can also give the errors.
[...]   
I would probably have some option that allowed you to get the data points
plotted and/or the error bars for each adjusted cell prediction.

With more than 3 vars, I believe to get meaningful views you need to set the
extra vars to some value (by default their mean for continuous vars and one of
the levels for a categorical var).  I would have it default to means for
continuous vars and first level for categorical vars with some syntax that
would allow users to specify if they desire something else.

*/