! version 1.0.6 Juni 17, 2021 @ 15:23:42 UK
*! Multilevel Analysis With 2 Step Approach

// History
// twostep 1.0.6: Option -method()- not used for edv in prefix. -> fixed (thanks Ben Jann)
// twostep 1.0.5: Check if clustervars are constant
// twostep 1.0.4: Add -unitregby- plot added (Bowers/Drake's fig 3)
// twostep 1.0.2: Again new syntax, mkdata -> mk2nd, 2ndlevl->edv, coefplot -> dot
// twostep 1.0.1: New syntax -> prefix style; 2ndlevel depname prefixed with _b_ , version 16
// twostep 1.0.0: New command design
// Initial version: -edvreg_joe- added Factor Variable Notation
// Predecessor: -edvreg- by Lewis/Linzer

// Syntax: twostep varlist [, stats(string)]: model depvar indepvars [options] || secondlevelcmd

* Caller for subprogramms

program twostep, eclass
version 16

	// Check if Prefix
	capture _on_colon_parse `0'
	if _rc == 198 {
		twostep_edv  `0'
		exit
	}

	// All the prefixed commands
	local bystring `s(before)'
	local 0 `s(after)'
	gettoken firstlevelstring secondlevelstring: 0, parse("||")
	local secondlevelstring: subinstr local secondlevelstring "||" "", all

	ParseFirst `firstlevelstring'
	local firstcmd `r(subcmd)'

 	ParseSecond `secondlevelstring'
	local clear `r(clear)'
	local secondcmd `r(subcmd)'

	// Call Subprograms
	if "`r(subcmd)'" == "mk2nd" {
		quietly d, s
		if r(changed) == 1 & "`clear'" == "" {
			display "{err}no; data in memory would be lost"
			exit 4
		}

		twostep_mk2nd `bystring': `firstlevelstring' || `secondlevelstring'

		exit
	}

	// Run the Models and Perform Lewis Linzer
	else if "`secondcmd'" == "edv"  {
		ParseFirst `firstlevelstring'
		local model `r(subcmd)'

		preserve
		tempvar touse
		mark `touse' `firstif' `firstin'
		quietly keep if `touse'

		twostep_mk2nd `bystring': `firstlevelstring' || `secondlevelstring'

		ParseSecond `secondlevelstring'
		twostep_edv `r(secondlevelvars)' `r(if)' `r(in)', method(`r(method)') `r(options)'

		if substr("`model'",1,3) != "reg" display `"{txt}Warning: First level model not -regress-. Use on own risk"'
		ereturn repost
		exit
	}


	// Component-plus-Residual Plot for all the 1st Level models
	else if "`firstcmd'" == "unitcpr" {
		gettoken litter firstlevelstring: firstlevelstring

		preserve
		tempvar touse
		mark `touse' `firstif' `firstin'
		quietly keep if `touse'

		twostep_unitcpr `bystring': `firstlevelstring' || `secondlevelstring'
		exit
	}

	// Component-plus-Residual Plot for the 2nd level linear regression
	if "`secondcmd'" == "clustercpr" {

		ParseFirst `firstlevelstring'
		local model `r(subcmd)'

		preserve
		tempvar touse wgt
		mark `touse' `firstif' `firstin'
		quietly keep if `touse'

		twostep_mk2nd `bystring': `firstlevelstring' || `secondlevelstring'

		ParseSecond `secondlevelstring'
		quietly twostep_edv `r(secondlevelvars)' `r(if)' `r(in)', `r(options)' keepweights(`wgt') method(`r(method)')

		if substr("`model'",1,3) != "reg" display `"{txt}Warning: First level model not -regress-. Use on own risk"'
		ereturn repost

		gettoken litter allsecondlevelopts : secondlevelstring, parse(",")
		twostep_clustercpr `wgt' `allsecondlevelopts'

	}

	// The -unitregby- Plots (i.e. Bowers/Drakes figure 3)
	else if "`secondcmd'" == "unitregby" {
		preserve
		tempvar touse
		mark `touse' `firstif' `firstin'
		quietly keep if `touse'

		ParseSecond `secondlevelstring'
		local secondlevelvars `r(secondlevelvars)'
		gettoken seconddepvar secondindepvar: secondlevelvars
		local unitby `r(unitby)'

		local secondlevelstring = subinstr("`secondlevelstring'","`seconddepvar'","_all",.)

		summarize `=subinstr("`seconddepvar'","_b_","",.)', meanonly
		local min = r(min)
		local max = r(max)

		twostep_mk2nd `unitby' `bystring': `firstlevelstring' ||  `secondlevelstring'
		ParseByString `bystring'
		local byvars  `r(byvar)'

		gettoken secondlevelstring allsecondlevelopts : secondlevelstring, parse(",")
		local allsecondlevelopts = subinstr("`allsecondlevelopts'",",","",1)

		twostep_unitregby `secondlevelvars' ///
		  , min(`min') max(`max') `allsecondlevelopts' _byvars(`byvars') unitby(`unitby')
	}


	// Dot chart for the requested 1st level coeficient
	else if "`secondcmd'" == "dot" {
		preserve
		tempvar touse
		mark `touse' `firstif' `firstin'
		quietly keep if `touse'

		twostep_mk2nd `bystring': `firstlevelstring' || `secondlevelstring'
		ParseByString `bystring'
		local byvar  `r(byvar)'

		gettoken secondlevelstring allsecondlevelopts : secondlevelstring, parse(",")
		local allsecondlevelopts = subinstr("`allsecondlevelopts'",",","",1)

		twostep_dot `secondlevelstring', over(`byvar') `allsecondlevelopts'
	}

	// An arbitrary Fallback command for the 2nd level
	else {
		preserve
		tempvar touse
		mark `touse' `firstif' `firstin'
		quietly keep if `touse'

		twostep_mk2nd `bystring': `firstlevelstring' || `secondlevelstring'
		twostep_fallback `secondlevelstring'

	}
end

* Create 2nd Level Data

program define twostep_mk2nd

	capture _on_colon_parse `0'
	local bystring `s(before)'
	local 0 `s(after)'

	// Parse By-String
   ParseByString `bystring'
	local byvar  `r(byvar)'
	local addstats `r(addstats)'

	// Parse First Level Information
	gettoken 0 secondlevel: 0, parse("||")
	local secondlevel: subinstr local secondlevel "||" "", all
	gettoken model 0:0

	syntax varlist(fv)  ///
	  [fweight aweight pweight]    ///
	  [if] [in] ///
	  [, vce(string) NOCONStant Hascons tsscons eform(string) clear]
	gettoken firstdepvar firstindepvar: varlist

	// Parse Second Level Information
	ParseSecond `secondlevel'
	local iflist `r(iflist)'
	local secondif `r(if)'
	local secondin `r(in)'
	local using `r(using)'
	local secondlevelvars `r(secondlevelvars)'
	gettoken seconddepvar secondindepvar: secondlevelvars

	tempfile 1stlevelcoefs 2ndlevelvars thisdata
	tempvar ifuse

	quietly {

		// Swap 2nd level data
		if `"`using'"' == `""' {
			fvexpand `secondindepvar'
			if "`r(fvops)'" != "" {
				RemoveFvBits `secondindepvar'
				local secondindepvar `r(cleanlist)'
			}
			save `thisdata'
			keep `byvar' `secondindepvar' `iflist'

			// Check cluster variables to be constant
			gen byte `ifuse' = 0
			replace `ifuse' = 1 `secondif' `secondin'
			foreach var of local secondindepvar {
				capture bys `ifuse' `byvar' (`var'): assert `var'[1]==`var'[_N] `secondif' `secondin'
				if _rc {
					noi display `"{err}`var' is not constant within `byvar'"'
					exit _rc
				}
			}

			bys `byvar': keep if _n==1
			save `2ndlevelvars'
			use `thisdata'
		}

		// Statsby does not allow pweights. I simulate them with aweights and vce(robust)
		if "`weight'" == "pweight" {
			local weight "aweight"
			if "`vce'" == "" {
				local vce vce(robust)
			}

			else {
				local vce `vce' robust
				local vce vce(`: list uniq vce')
			}

		}

		// Do we use factor-variable notation?
		fvexpand `firstindepvar'
		local fvops = "`r(fvops)'"=="true"

		// Run Within First Level Models
		statsby _b _se _n_model = e(N) `addstats', `clear' by(`byvar') saving(`1stlevelcoefs', double):  ///
		  `model' `firstdepvar' `firstindepvar' [`weight'`exp'] `if' `in',  `vce' `noconstant' `hasconstant' `tsconstant'
		use `1stlevelcoefs', clear
		if `"`using'"' == `""' {
			merge 1:1 `byvar' using `2ndlevelvars', keep(3) nogen
		}
		else merge 1:1 `byvar' `using', keep(3) nogen

		// Harmonize variable names in case of factor variable notation
		if `fvops' {
			foreach var of varlist _stat_* {
				local newname: variable label `var'
				local newname: subinstr local newname "[" "_", all
				local newname: subinstr local newname "." "_", all
				local newname: subinstr local newname "]" "", all
				local newname: subinstr local newname "#" "X", all
				rename `var' `newname'
			}
		}

		// I Harmonize the variable names a bit further, if possible
		foreach var of varlist *_b_* {
			capture ren `var' `=regexr("`var'","_*[0-9a-z]+_b_","_b_")'
		}
		foreach var of varlist *_se_* {
			capture ren `var' `=regexr("`var'","_*[0-9a-z]+_se_","_se_")'
		}
		foreach var of varlist _eq* {
			capture ren `var' `=regexr("`var'","_eq[0-9]+_","_")'
		}

		// Keep what is requested only
		if "`seconddepvar'" != "_all" {
			local seofdepvar = subinstr("`seconddepvar'","_b_","_se_",1)
			keep `byvar' `seconddepvar' `seofdepvar' _n_model  `secondindepvar' `iflist'
		}

		if "`secondin'" != "" | "`secondif'" != "" keep `secondin' `secondif'
	}
end

* edv (Re-Implentation of Lewis/Linzer's edvreg)
program define twostep_edv

	syntax varlist(fv) [if] [in] [, Method(string) level(passthru) vce(passthru) NOCONStant Hascons keepweights(string) *]
	gettoken depvar indepvars: varlist
	local sename = subinstr("`depvar'", "_b","_se",.)

	tempvar omegavar sumomegavar weight

	if "`method'" == "" local method fgls1
  local creator = cond("`method'"=="fgls2","(1/_n_model)^2","`sename'^2")  // DEBUG line
*	local creator = cond("`method'"=="fgls2","(1/_n_model)^2","`sename'^2 * _n_model") // DEBUG line

	quietly {
		gen double `omegavar'  = `creator' `if' `in'
		sum `omegavar', meanonly
		local sumomegavar = r(sum)

		regress `depvar' `indepvars' `if' `in'
		local dof = e(df_r) // DEBUG line
		local rss = e(rss)

		// Remove base-categories from varlist
		fvexpand `indepvars'
		local list=r(varlist)
		if "`r(fvops)'" == "true" {
			foreach varname of local list {
				local x `x' `= regexr(`"`varname'"',`".+b\..+"',`""')'
			}
			local indepvars `x'
		}

		// Create the weighting variable using one of the methods.
		gen double `weight' = .
		twostep_`method' `indepvars' `if' `in' ///
		  , omega(`omegavar') rss(`rss') sumomegavar(`sumomegavar') dof(`dof') weight(`weight')
		local sigma2 = r(sigma2)
		local omega2 = r(omega2)
	}
	regress `depvar' `indepvars' [aw=`weight'] `if' `in', `level' `vce' `noconstant' `hascons' `options'
	disp "{txt}Sampling Variance Proportion = {res}" %4.0g `omega2'/(`omega2' + `sigma2')

	if "`keepweights'" != "" gen double `keepweights' = `weight' if e(sample)
end

* cprplot for first level regressions
program define twostep_unitcpr

	capture _on_colon_parse `0'
	local bystring `s(before)'
	local 0 `s(after)'

	// Parse First Level Information
	gettoken 0 secondlevel: 0, parse("||")
	local secondlevel: subinstr local secondlevel "||" "", all

	syntax varlist(fv)  ///
	  [fweight aweight pweight]    ///
	  [if] [in] ///
	  [using]  ///
	  [ , vce(string) NOCONStant Hascons tsscons eform(string) ]
	gettoken firstdepvar firstindepvar: varlist

	// Parse Second Level Information
	ParseSecond `secondlevel'
	local iflist `r(iflist)'
	local using `r(using)'
	local secondif `r(if)'
	local secondin `r(in)'
	local seconddepvar `r(subcmd)'
	local secondindepvar  `r(secondlevelvars)'
	local scopts `r(scopts)'
	local allopts `r(allopts)'
	local regopts `r(regopts)'
	local lowessopts `r(lowessopts)'
	local byopts `r(byopts)'
	local options `r(options)'
	local title `r(title)'
   local ytitle `r(ytitle)'
   local legend  `r(legend)'
   local note  `r(note)'

	gettoken order: secondindepvar
	local seconddepvar = subinstr("`seconddepvar'","_b_","",.)

	ParseByString `bystring'
	local byvar `r(byvar)'
	local statlist `r(statlist)'


	quietly {

		tempvar totalresid totalcpr totalcprhat ///
		  withincpr withinb withinresid  ///
		  rank

		// Overall regression
		regress `firstdepvar' `firstindepvar' [`weight'`exp'] `firstin' `firstif', `vce' `noconstant' `hasconstant' `tsconstant'
		predict double  `totalresid', resid
		gen `totalcpr' = _b[`seconddepvar']*`seconddepvar' + `totalresid'
		regress `totalcpr' `seconddepvar'
		predict double  `totalcprhat'
		drop `totalresid' `totalcpr'

		// Within Regressions
		levelsof `byvar', local(K)
		gen `withincpr' = .
		gen `withinb' = .
		if "`statlist'" != "" {
			foreach stat in `statlist' {
				gen _stat_`stat' = .
			}
		}


		foreach k of local K {
			regress `firstdepvar' `firstindepvar' if `byvar' == `k' [`weight'`exp'],  `vce' `noconstant' `hasconstant' `tsconstant'
			predict double  `withinresid', resid
			replace `withincpr' = _b[`seconddepvar']*`seconddepvar' + `withinresid' if `byvar' == `k'
			replace `withinb' = _b[`seconddepvar'] if `byvar' == `k'
			if "`statlist'" != "" {
				foreach stat in `statlist' {
					replace _stat_`stat' = e(`stat') if `byvar' == `k'
				}
			}
			drop `withinresid'
		}

		if "`order'" == "" {
			local order `withinb'
			local x = "b_" + "`seconddepvar'"
			local byname `seconddepvar'
		}
		else {
			local x =regexr("`order'","_[0-9A-Za-z]+_","")
			local byname `order'
		}

		egen `rank' = rank(-`order') `secondif' `secondin', field  // UK: We should remove this with lower levels
		tempvar label
		decode `byvar', gen(`label')
		replace `label' = `label' + ", `x' = " +  strofreal(`order',"%8.0g")
		labmask `rank' `secondif' `secondin', value(`label')   // UK: We should remove this with lower levels
		local order `withinb'
	}


	// Default options
	if "`scopts'"== "" local scopts ms(oh) mcolor(gs8)
   if "`allopts'"== "" local allopts lcolor(gs12) sort
   if "`regopts'"== "" local regopts lcolor(black) lpattern(dash)
   if "`lowessopts'"== "" local lowessopts lcolor(black) lpattern(solid)
	if "`title'"== "" local title Within Clusters Component-Plus-Residual Plots
   if "`ytitle'"== "" local ytitle Component plus residual
   if "`legend'"== "" local legend order(2 "Linear Fit (All)" 3 "Linear Fit (Within)" 4 "LOWESS (Within)")
	if "`note'" == "" local note Plots ordered by field rank of `byname'
	if "`byopts'"== "" local byopts compact title(`title') note(`note')

	label variable `withincpr' "Residual + Component"
	label variable `totalcprhat' "Overall Regression"

	graph twoway ///
	  || scatter `withincpr' `seconddepvar', `scopts'  ///
	  || line `totalcprhat' `seconddepvar', `allopts' ///
	  || lfit `withincpr' `seconddepvar', `regopts'  ///
	  || lowess `withincpr' `seconddepvar', `lowessopts' ///
	  || , by(`rank', `byopts') ///
	  ytitle(`ytitle')  ///
	  legend(`legend') ///
	  `options'
end

* cprplot for second level regression
program define twostep_clustercpr
	local cmdline `e(cmdline)'
	gettoken cmd varlist: cmdline
	gettoken depvar indepvars: varlist
	gettoken interestvar rest: indepvars

	ParseSecond `0'
	local scopts `r(scopts)'
	local regopts `r(regopts)'
	local lowessopts `r(lowessopts)'
	local options `r(options)'
	local title `r(title)'
   local ytitle `r(ytitle)'
   local legend  `r(legend)'
	local method `r(method)'

	tempname resid cpr
	predict double  `resid', resid
	gen `cpr' = `resid' + _b[`interestvar'] * `interestvar'

	// Default options
	if "`scopts'"== "" local scopts ms(Oh) mcolor(gs8)
   if "`regopts'"== "" local regopts lcolor(black) sort lpattern(dash)
   if "`lowessopts'"== "" local lowessopts lcolor(black) lpattern(solid)
	if "`title'"== "" local title Cluster Level Component Plus Residual Plot
   if "`ytitle'"== "" local ytitle Component plus residual
   if "`legend'"== "" local legend order(2 "Linear Fit" 3 "Within LOWESS")

	graph twoway ///
	  || scatter `cpr' `interestvar' [aweight=`1'], `scopts' ///
	  || lfit `cpr' `interestvar'  [aweight=`1'], `regopts' ///
	  || lowess `cpr' `interestvar', `lowessopts' ///
	  || if e(sample),  ///
	  title(`title')  ///
	  ytitle(`ytitle')  ///
	  legend(`legend') ///
	  `options'

end

* Unitregby-plot
program define twostep_unitregby
	syntax varlist [if] [in]   ///
	  [ , min(real 0) max(real 1)  ///
	  _byvars(varlist) Unitby(varlist) NQuantiles(int 2)  ///
      DIscrete(varlist) *]

	gettoken depvar indepvars: varlist
	gettoken order: indepvars

	local levelby: list _byvars - unitby

	// Graph defaults
	ParseSecond, `options'
   local byopts `r(byopts)'
	local options `r(options)'
	local title `r(title)'
   local xtitle `r(xtitle)'
   local ytitle `r(ytitle)'
   local regopts `r(regopts)'
	local allopts `r(allopts)'

	if "`byopts'" == "" local byopts legend(off)
	else local byopts legend(off) `byopts'
	if "`title'" != "" local byopts `byopts' title(`title')

	if "`regopts'" == "" local regopts c(L)
	else local regopts c(L) `regopts'

	if "`allopts'" == "" local allopts c(L) lcolor(gs14)
	else local allopts c(L) `allopts'

	if "`xtitle'" == "" local xtitle `=subinstr("`depvar'","_b_","",.)'
	if "`ytitle'" == "" local ytitle Predicted values (all other covariates to zero)

	tempname x phat

	forv i = 1/`=`nquantiles'-1'{
		local cutpoints `cutpoints' , r(r`i')
	}

	forv i = 1/`=`nquantiles'' {
		if `i'==1 local grouplab `"`i' "1{super:st}""'
		else if `i'== 2 local grouplab `"`grouplab' `i' "2{super:nd}""'
		else if `i'== 3 local grouplab `"`grouplab' `i' "3{super:rd}""'
		else local grouplab `"`grouplab' `i' "`i'{super:th}""'
	}
	label define grouplab `grouplab'

	quietly {
		foreach var of local indepvars {
			tempvar `var'

			if strpos("`discrete'","`var'") == 0 {
				_pctile `var', nquantile(`nquantiles')
				gen int ``var'' = irecode(`var' `cutpoints') + 1
				label var ``var'' " `var' (`nquantiles' quantiles)"
				label val ``var'' grouplab
			}
			else {
				clonevar ``var''=`var'
			}
			local groupvars `groupvars' ``var''
		}

		fillin `_byvars' `unitby' `groupvars'
		sort  `_byvars' `unitby' `depvar'
		replace `depvar' = `depvar'[_n-1] if _fillin
		replace _b_cons = _b_cons[_n-1] if _fillin

		expand 2
		bys `_byvars' `unitby' `groupvars': gen `x' = cond(_n==1,`min',`max')
		gen `phat' = _b_cons + `depvar' * `x'
	}

	graph twoway ///
	  || line `phat' `x' if _fillin, `allopts'  ///
	  || line `phat' `x' if !_fillin, `regopts'  ///
	  || , by(`groupvars' `unitby', `byopts') ///
	  ytitle(`"`ytitle'"')  ///
	  xtitle(`xtitle')  ///
	  `options'

end


* dot of Coefs with C.I.
program define twostep_dot
	syntax anything [if] [in] [, over(varname) level(int 95) *]
	gettoken cmd varlist: anything
	gettoken depvar indepvars: varlist
	gettoken order: indepvars

	ParseSecond , `options'
	local scopts `r(scopts)'
	local ciopts `r(ciopts)'
	local options `r(options)'
	local title `r(title)'
   local xtitle `r(xtitle)'

	local tix = cond(strpos("`depvar'","_b_"),"Coefficient","Statistic")

	if "`ciopts'" == "" local ciopts lcolor(black)
	if "`scopts'" == "" local scopts ms(O) mcolor(black)
	if "`xtitle'" == "" local xtitle `depvar'
	if "`title'" == "" local title `tix' of unit level models

	tempvar lb ub rank

	quietly {
		local cif = invnorm((100-`level')/200)

		if strpos("`depvar'","_b_") {

			local sename = subinstr("`depvar'","_b","_se",.)

			gen `lb' = `depvar' - `cif'*`sename' `if' `in'
			gen `ub' = `depvar' + `cif'*`sename' `if' `in'

			local rcap 	 || rcap `lb' `ub' `rank', horizontal `ciopts'

		}

		summarize `depvar' `if' `in', meanonly
		local mean = r(mean)

		if "`order'" == "" {
			local order `depvar'
			local note Groups ordered by size of within regression coefficients
		}
		else {
			local note Groups ordered by rank of `order'
		}

		egen `rank' = rank(-`order') `if' `in', unique
		labmask `rank' `if' `in', value(`over')  decode


		levelsof `rank', local(K)
		graph twoway ///
		  `rcap'   ///
		  || scatter `rank' `depvar', `scopts'  ///
		  || `if' `in', ylab(`K', valuelabel angle(0) grid gstyle(dot))  ///
		  ytitle(`"`ytitle'"')  ///
		  xtitle(`xtitle')  ///
		  xline(`mean', lcolor(gs12)) legend(off)  ///
		  title(`title') ///
		  `options'
	}
end

* Fallback mode
program define twostep_fallback
	syntax anything [if] [in] [, *]
	gettoken cmd varlist: anything
	`cmd' `varlist' `if' `in', `options'
end


* edv_OLS
program define twostep_ols, rclass
	syntax varlist(fv) [if] [in] ///
	  [, weight(varname) omega(varname) rss(real 1) sumomegavar(real 1) dof(real 1) ]
	replace `weight' = 1
	return local sigma2 1
	return local omega2 0
end

* edv_WLS
program define twostep_wls, rclass
syntax varlist(fv)  [if] [in]  ///
  [, weight(varname) omega(varname) rss(real 1) sumomegavar(real 1) dof(real 1) ]

	replace `weight' = 1/`omega' `if' `in'
	return local sigma2 0
	return local omega2 1
end

* edv_borjas
program define twostep_borjas, rclass
syntax varlist(fv)  [if] [in]  ///
  [, weight(varname) omega(varname) rss(real 1) sumomegavar(real 1) dof(real 1) ]

	tempname XpX

	matrix accum `XpX' = `varlist' `if' `in'

	local sigma2 = cond((`rss'-`sumomegavar')/`dof'<0, 0,  (`rss'-`sumomegavar')/`dof')

	replace `weight' = 1/(`sigma2' + `omega') `if' `in'

	return local sigma2 `sigma2'
	return local omega2 `sumomegavar'
end

* edv_FGLS-1
program define twostep_fgls1, rclass
	syntax varlist(fv) [if] [in] ///
	  [, weight(varname) omega(varname) rss(real 1) sumomegavar(real 1) dof(real 1) ]

	tempname XpX XpGX tr

	matrix accum `XpX' = `varlist' `if' `in'
	matrix accum `XpGX' = `varlist' [iw = `omega'] `if' `in'
	matrix `tr' = trace(invsym(`XpX') * `XpGX')

	local sigma2 =  cond( ///
	  ((`rss'-`sumomegavar' + `tr'[1,1]) / `dof') < 0, ///
	  0,  ///
	  (`rss'-`sumomegavar' + `tr'[1,1]) / `dof')


	replace `weight' = 1/(`sigma2' + `omega')

	sum `weight', meanonly

	// noi display "{txt} Sum of squared residual is {res}" %16.0g `rss'
	// noi display "{txt} Sum of omegasquared is  {res}" %16.0g `sumomegavar'
	// noi display "{txt} DF is {res}" `dof'
	// noi display "{txt} trace of inverse is {res}" %16.0g `tr'[1,1]
	// noi display "{txt} nominator of sigmasq-equation is {res}" %16.0g (`rss'-`sumomegavar' + `tr'[1,1])
	// noi display "{txt} sigmasq is {res}" %16.0g (`rss'-`sumomegavar' + `tr'[1,1]) / `dof'

	// noi display "{txt} Sum of weights shouch be 3788651.304 and is {res}" %16.0g `=r(sum)'

	return local sigma2 `sigma2'
	return local omega2 `sumomegavar'
end

* edv_FGLS-2
program define twostep_fgls2, rclass
	syntax varlist [if] [in] ///
	  [, weight(varname) omega(varname) rss(real 1) sumomegavar(real 1) dof(real 1) ]

	tempvar e v omegahat

	predict double `e' if e(sample), resid
	replace `e' = `e'^2
	reg `e' `omega' `if' `in'
	if _b[_cons] < 0 {
		reg `e' `omega' `if' `in', nocons
		local sigma2 = 0
	}
	else {
		local sigma2 = _b[_cons]
	}

	predict double `v' if e(sample)
	replace `weight' = 1/(`v') if e(sample)

	gen double `omegahat' = sum((_b[`omega']*`omega')^2)

	return local sigma2 `sigma2'
	return local omega2 `=`omegahat'[_N]'

end


* Parse Firstlevelcommand
program define ParseFirst, rclass
	syntax anything [if] [in] [aweight fweight pweight] [, *]
	gettoken subcmd firstlevelvars: anything

	return local subcmd `subcmd'
	return local firstlevelvars `firstlevelvars'
	return local if `if'
	return local in `in'
	return local weight `weight'`exp'
	return local options `options'

end

* Parse Secondlevelcommand
program define ParseSecond, rclass
	syntax [anything] [if] [in] [using] [aweight] [, clear  ///
	  BYopts(string) ///
	  LOWESSopts(string)  ///
	  REGopts(string)  ///
	  SCopts(string)  ///
	  TItle(string) ///
	  XTItle(string) ///
	  YTItle(string) ///
	  ALLopts(string)  ///
	  CIopts(string) ///
	  legend(string) ///
	  unitby(string) ///
	  Method(string) ///
	  * ]

	gettoken subcmd secondlevelvars: anything

	if "`if'" != "" {
		GrepIfVarnames `if'
		return local iflist `r(iflist)'
	}

	return local allopts `allopts'
	return local byopts `byopts'
	return local ciopts `ciopts'
	return local clear `clear'
	return local if `if'
	return local in `in'
	return local legend `legend'
	return local lowessopts `lowessopts'
	return local note `note'
	return local options `options'
	return local regopts `regopts'
	return local scopts `scopts'
	return local secondlevelvars `secondlevelvars'
	return local subcmd `subcmd'
	return local title `title'
	return local using `using'
	return local xtitle `xtitle'
	return local ytitle `ytitle'
	return local unitby `unitby'
	return local method `method'

end

* Parse By-String
program define ParseByString, rclass
	syntax anything [, stats(string)]
	foreach name of local stats {
		local addstats `addstats' _stat_`name' = e(`name')
	}

   return local byvar `anything'
   return local addstats `addstats'
	return local statlist `stats'
end

* Grep variable names from if Option
program define GrepIfVarnames, rclass
	syntax if/

	local maybe 1
	while `maybe' == 1 {
		local maybe = regexm("`if'","[A-Za-z0-9_]+")
		if `maybe' != 0 {
			local candidate = regexs(0)
			capture confirm variable `candidate'
			if !_rc {
				local iflist `iflist' `candidate'
			}
			local if: subinstr local if "`candidate'" "", all
		}
	}

	return local iflist `iflist'
end

* Remove FV notation to have the unique varnames

program define RemoveFvBits, rclass
	syntax anything(name=secondindepvar)

	local cleansecondindepvars: subinstr local secondindepvar "#" " ", all
	foreach var of local cleansecondindepvars {
		local cleanlist `cleanlist' `=regexr("`var'","[bcio0-9()#]+\."," ")'
	}
		return local cleanlist `: list uniq cleanlist'
end