*! 1.3.3 NJC/CFB 21 Jun 2003
* 1.3.2 NJC/CFB 29 July 2002 
* 1.3.1 NJC/CFB 26 July 2002 
* 1.3.0 NJC/CFB 10 Jun 2002 
* 1.2.3 NJC/CFB 30 Nov 2001 
* 1.2.2 NJC/CFB 6 Nov 2001 
* 1.2.1 NJC/CFB 6 Nov 2001 
* 1.2.0 NJC/CFB 4 Oct 2001 
* 1.1.0 NJC/CFB 17 Sept 2001 
* 1.0.1 NJC/CFB 18 June 2001 
* 1.0.0 NJC/CFB 7 June 2001   
program define tsgraph, sort 
        version 7.0
	
	qui tsset /* error if not set as time series */
	local timevar "`r(timevar)'" 
	local panelvar "`r(panelvar)'" 
	
	syntax varlist(ts num min=1) [if] [in] /* 
	*/ [, Connect(str) Symbol(str) XLAbel XLAbel(str) /* 
	*/ Rescale YLAbel YLAbel(str) YLOg L1title(str) L2title(str) /* 
	*/ Gap(int 5) SEParate(varname) BY(varname) NLAbel(int 4) * ] 
	
	* separate() option is undocumented 
	
	* novarlist to get plot whenever at least one value not missing
	marksample touse, novarlist  
	local ny : word count `varlist'

	if "`panelvar'" != "" & `ny' == 1 & "`separate'" == "" { 
		qui tab `panelvar' if `touse' 
		if r(r) <= 4 & r(r) > 1 { local separate "`panelvar'" }
	}	

	if "`separate'" != "" {
		if `ny' > 1 { 
			di as err "separate() option allowed only with" _c 
			di as err "one response variable" 
			exit 198 
		} 	
		qui tab `separate' if `touse'
		if r(r) > 20 { 
			di as err "too many groups in `separate': maximum 20" 
			exit 198 
		}
		else if r(r) == 1 { local separate } /* blank it out */ 
		local ny = r(r) 
	}	
	
	if "`connect'" == "" { 
		if `ny' == 1 { local connect "L" } 
		else if `ny' == 2 { local connect "LL[_]" }
		else if `ny' == 3 { local connect "LL[_]L[-]" } 
		else if `ny' == 4 { local connect "LL[_]L[-]L[.]" } 
		else local connect : di _dup(`ny') "L" 
	} 	
	
	if "`symbol'" == "" { 
		local symbol : di _dup(`ny') "i" 
	} 	

	if "`xlabel'" == "" {
		tempvar year 
		local format : format `timevar' 
		local which = substr("`format'",2,1)
		local which2 = substr("`format'",3,.) 

		/* formats beginning "%t", but not "%ty" */ 
		if "`which'" == "t" & "`which2'" != "y" { 			
	 		local which = substr("`format'",3,1)
			if "`which'" != "d" { 
				tempname xx
				qui gen `year' = yofd(dof`which'(`timevar')) 
				su `year' if `touse', meanonly        
				Nicenum `nlabel' 
				local X "`r(numlist)'"  
				if "`X'" != "" { 
					foreach x of local X {
						local x = int(`x')
						local la = `which'(`x'`which'1) 
						local LA "`LA'`la' " 
					}
				}
			} 
		} 
		
		/* format "%ty" */ 
		else if "`which'" == "t" & "`which2'" == "y" { 			
			su `timevar' if `touse', meanonly        
			Nicenum `nlabel' 
			local X "`r(numlist)'"  
			if "`X'" != "" { local LA "`X'" } 					
		} 
		
		/* formats beginning "%d" or "%td" */ 
		else if "`which'" == "d" { 
			qui gen `year' = yofd(`timevar')
			su `year' if `touse', meanonly        
			Nicenum `nlabel' 
			local X "`r(numlist)'"  
			if "`X'" != "" { 
				foreach x of local X {
					local la = d(1jan`x') 
					local LA "`LA'`la' " 
				}
			}
		}
	
		if "`LA'" != "" { local xlabel "xlabel(`LA')" } 
	} 
	else if "`xlabel'" != "xlabel" { local xlabel "xla(`xlabel')" } 
	
	if "`ylabel'" == "" { local ylabel "ylabel" } 
	else if "`ylabel'" != "ylabel" { 
		local ylabel "yla(`ylabel')" 
	} 

	if "`ylog'" != "" & `"`l2title'"' == "" { 
		local l2title "(log scale)"
	} 
	if `"`l2title'"' != "" { local l2title `"l2("`l2title'")"' } 
	if `"`l1title'"' == "" { 
		if `ny' == 1 | "`separate'" != "" { 
			capture local l1title : variable label `varlist'
			if `"`l1title'"' == "" { local l1title "`varlist'" } 
		}
	} 
	if `"`l1title'"' != "" { local l1title "l1(`l1title')" }

 	* this depends on Stata 7 dropping variables with a tempname as stub 
	if "`separate'" != "" { 
		tempname sep 
		qui separate `varlist' if `touse', by(`separate') gen(`sep')
	        unab varlist : `sep'* 
		
		* fix variable labels 
		foreach v of local varlist { 
			local label : variable label `v'
			local pos = index(`"`label'"',"=") 
			local label = substr(`"`label'"',`pos' + 2,.)
			label variable `v' `"`label'"' 
		} 
		
		* -separate- can mess up sort order 
		qui tsset 
	} 

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

	graph `varlist' `timevar' if `touse', /* 
	*/ c(`connect') `xlabel' `ylabel' `ylog' `byby' /* 
	*/ symbol(`symbol') `rescale' `l1title' `l2title' g(`gap') `options' 
end

* main algorithm based on -nicenum- 1.1.0 11/4/94 (STB-25: dm28)
program define Nicenum, rclass 
	version 7.0
	args nlabel
	tempname gmin gmax grange exp d f nf tmp1 tmp2
	
	* these arguments from -summarize- just earlier 
	scalar `gmin' = r(min)
	scalar `gmax' = r(max)
	
	* all within same year? no go!
	if `gmin' == `gmax' { 
		exit 0 
	} 
	
	local N = `nlabel' 
        local inter = `N' + 1
	local ntick = `inter' 
	
	scalar `grange' = `gmax' - `gmin'
	scalar `exp' = log10(`grange')
	scalar `exp' = int(`exp') - (`exp' < 0.0)
	
	scalar `f' = `grange' / (10^`exp')
	if `f' <= 1      { scalar `nf' = 1  }
	else if `f' <= 2 { scalar `nf' = 2  }
	else if `f' <= 5 { scalar `nf' = 5  }
	else             { scalar `nf' = 10 }

	scalar `grange' = `nf' * 10^`exp' 
	scalar `d' = `grange' / (`ntick' - 1)
	scalar `exp' = log10(`d')
	scalar `exp' = int(`exp') - (`exp' < 0.0)
	
	scalar `f' = `d' / (10^`exp')
	if `f' < 1.5    { scalar `nf' = 1 }
	else if `f' < 3 { scalar `nf' = 2 }
	else if `f' < 7 { scalar `nf' = 5 }
	else            { scalar `nf' = 10 }

	scalar `d' = `nf' * 10^`exp'
	scalar `gmin' = `gmin' / `d'
	scalar `gmin' = (int(`gmin') - (`gmin' < 0.0)) * `d'
	scalar `tmp1' = `gmax' / `d'
	scalar `tmp2' = int(`tmp1')
	if `tmp2' < float(`tmp1') { scalar `tmp2' = `tmp2' + 1 }
	scalar `gmax' = `tmp2' * `d'
	scalar `tmp1' = log10(`d')
	
	local nfrac = int(-`tmp1') + (`tmp1' < 0.0)
	if `nfrac' <= 0 { local nfrac = 0 }
	if `nfrac' == 0 { scalar `tmp1' = `gmin' }
	else scalar `tmp1' = `gmin' + 1 / (10^(`nfrac' + 1)) 		
	scalar `tmp2' = `gmax' + `d'/ 2
	
	while `tmp1' <= `tmp2' {
		local stub = int(`tmp1')
		if `nfrac' {
			local gminb = int(`tmp1' * (10^`nfrac'))
			local stubb = int(`stub' * (10^`nfrac'))
			local frac = `gminb' - `stubb'
			local frst = "00000000000000000000" + /*
			*/	string(`frac')
			local fstr = substr("`frst'", -`nfrac', .)
			local numlist "`numlist' `stub'.`fstr'"
		}
		else	{ 
			local tstr = string(`tmp1')
			local numlist "`numlist' `tstr'" 
		}
		scalar `tmp1' = `tmp1' + `d' 
	}  

	return local numlist "`numlist'" 
end