capture program drop npredcent
program npredcent, byable(recall, noheader)    /* Program to predict and center a variable on its mean */
	version 9.0
	syntax varlist [if] , REPlace(name) [contextvars(string)] [center(string)] [logit] [stackname(name)] [effects(string)] [NOStacks] [STAckid(varname)]
	
	// version 11?
	// syntax varlist(fv) [if] , REPlace(name) [contextvars(string)] [center(string)] [logit] [stackname(name)] [effects(string)] [NOStacks] [STAckid(varname)]
		

	//display in smcl
	//display as text
	//display " " _byn1() "-" _byn2()

	//display "*`nostacks'*"
	
	
	// set default centring
	if ("`center'"=="") {
		local center = "mean"
	}
	
	marksample touse
	tempvar NN MM
	
	quietly count if `touse'
	if (r(N)==0) {
		exit
	}
	
	/*
		it now should work without vallist, without errors
		it simply doesn't get labels
	*/
	
	
	capture confirm variable genstacks_item
	if !_rc {
		// action if exists
		quietly levelsof genstacks_item if `touse' 
		quietly capture vallist genstacks_item if genstacks_item == `r(levels)'
		local partyname = ""
		
		// did it break anything?
		//local partyname = substr(strtoname("`r(list)'",1),1,10)
		
	}
	else {
		if ("`nostacks'" != "") {
			local partyname = " "
		}
		else {
			if ("`stackid'"!="") {
				quietly levelsof `stackid' if `touse' 
				local partyname = ""
				// did it break anything?
				local partyname = strtoname("Stack `r(levels)'",1)
			}
			else {
				quietly levelsof genstacks_stack if `touse' 
				local partyname = ""
				// did it break anything?
				local partyname = strtoname("Stack `r(levels)'",1)
			}
		}
	}

	display "there"
	
	
	if (_by()==1) {
	// if ("`groupnum'"!="") {
		local groupnum = _byindex()
		local partyname = "_`groupnum'_`partyname'"
	}
	
	display "{bf:`partyname':}"
	
	local storemodel = "" 
	
	if ("`effects'"!="") {
		local storemodel = "eststo `partyname':"
	}
	
	/*
	// trying to make things faster:
	preserve
	noisily display "dropping unused..."
	keep if `touse'	
	//
	*/
	
	if ("`logit'"=="logit") {
		`storemodel' logit `varlist' if `touse'	
	}
	else {
		//display "`storemodel' reg `varlist' if `touse'"
		`storemodel' reg `varlist' if `touse'	
		//display "*done."
	}
	local con = _b[_cons]
	
	predict NN if `touse'	
	
	if ("`center'"=="no") {
		replace `replace'=NN if `touse'	
		drop NN
	}
	else {
		egen MM=mean(NN) if `touse'	
		
		if ("`logit'"=="logit" & "`center'"=="constant") {
			gen exponNN = logit(NN)
			replace `replace'=invlogit(exponNN-`con') if `touse'	
			capture drop exponNN
		}
		else if ("`logit'"=="logit") {
			gen exponNN = logit(NN)
			egen exponMM = mean(exponNN)
			replace `replace'=invlogit(exponNN-exponMM) if `touse'	
			capture drop exponNN exponMM
		}
		else if ("`center'"=="constant") {
			replace `replace'=NN-`con' if `touse'	
		}
		else {
			replace `replace'=NN-MM if `touse'	
		}
		drop MM NN
	}
	
	
	/*
	//
	local filename : display "tmp" _byn1() ".dta"
	save `filename', replace
	noisily display "restoring and appending tempfile..."
	restore
	drop if `touse'
	append using `filename'
	noisily display "done."
	erase `filename'
	//
	*/
end
capture program drop genyhats
program define genyhats, sortpreserve
	version 9.0
	syntax anything(id="yhat specification") [if] , DEPvar(varname) [CONtextvars(varlist)] [STAckid(varname)] [LOGit] [REPlace] [NOStacks] [YPRefix(string)] [ADJust(string)] [NOADJUSTopt] [OUTput] [EFFects(string)] [EFMt(string)] [DEMean(varname)] [DPRefix(string)]
	// [NOCENTERopt] [CENter(string)] [centre(string)] [NOCENTREopt]
	
	display in smcl
	display as text
	
	display "{pstd}{text}"
	
	// make sense of all the centring syntax options...

	/*
	if ("`nocenteropt'`nocentreopt'" != "`nocenteropt'" & "`nocenteropt'"!="") {
		display "Options {bf:nocenter} and {bf:nocentre} cannot be specified simultaneously."
		exit
	}
	else {
		local noc = "`nocenteropt'`nocentreopt'" // will pick up the only one specified
	}
	if ("`center'`centre'" != "`center'" & "`center'"!="") {
		display "Options {bf:center()} and {bf:centre()} cannot be specified simultaneously."
		exit
	}
	else {
		local cen = "`center'`centre'" // will pick up the only one specified
	}
	*/
	
	// now: "adjust"
	local cen = "`adjust'"
	local noc = "`noadjustopt'"
		
	if ("`noc'`cen'" != "`cen'" & "`cen'"!="") {
		display "Adjustment cannot be simultaneously enabled and disabled."
		exit
	}
	else {
		if ("`noc'"!="") {
			local centring = "center(no)"
		}
		else {
			if ("`cen'" != "mean" & "`cen'" != "constant" & "`cen'" != "no"  & "`cen'" != "") {
				display "Valid adjustment options are {bf:mean}, {bf:constant} or {bf:no}."
				exit
			}
			local centring = "center(`cen')"
		}
	}
	
	local yyprefix = "y_"
	if ("`yprefix'" != "") {
		local yyprefix = "`yprefix'"
	}
	
	if ("`nostacks'" != "") {
		local stkid = ""
	}
	else {
		if ("`stackid'" == "") {
			capture confirm variable genstacks_stack
			if !_rc {
					// action if exists
					local stkid = "genstacks_stack"
			}
			else {
					// action if not
					local stkid = ""
					local nostacks = "nostacks"
			}
			//local stkid = "genstacks_stack"
		}
		else {
			local stkid = "`stackid'"
		}
	}
	
	
	if ("`contextvars'" == "") {
		if ("`nostacks'" != "") {
			gen _stk_temp = 1
			local stackvars = "_stk_temp"
		}
		else {
			local stackvars = "`stkid'"
		}
	}
	else {
		local stackvars = "`contextvars' `stkid'"
	}	
	
	if ("`depvar'" == "") {
		local dvar = "ptv"
	}
	else {
		local dvar = "`depvar'"
	}	
	
	
	display "Y-hats will be separately generated for combinations of {result:`stackvars'}."
	display ""
	
	local pipedsyntax = 0
	
	if (strpos("`anything'",":")!=0 | strpos("`anything'","||")!=0) {
		local pipedsyntax = 1
	} 
	else {
		local vars
		foreach var of varlist `anything' {
				local vars `vars' `var'
		}
		local anything `vars'
	}
	while ("`anything'" != "")  {
		
		if (`pipedsyntax'==1) {
		
			gettoken string anything : anything, parse("||") // put into 'string' all up to "\" or to end of anything
			
			//display "{pstd}{text}"

			//display "Processing {bf:`string'}:{break}"
			if (strpos("`string'",":")==0) {
				// no colon
				local indepvars `string'
				foreach var of varlist `indepvars' {
					local yhat = "`yyprefix'`var'"
					continue, break
				}
			}
			else {
				// colon
				gettoken yhat colonvars: string, parse(": ")
				gettoken colon indepvars: colonvars, parse(": ")
			}

		}
		else {
			//display "Unpiped syntax detected."
			gettoken string anything : anything
			
			local stringname=strtoname("`string'")
			local yhat = "`yyprefix'`stringname'"
			
			local indepvars = "`string'"		
		}
		
		display "{pstd}{text}"
		display "Generating {bf:`yhat'} from {bf:`indepvars'}:"
		
		//display "---"
		//display "**V `yhat' => `vars' **"
		
		// NOW EXPLICIT DEPVAR OPTION: NOT NEEDED
		//gettoken depvar indepvars : vars  // parse into depvar and indeps
		
		//capture confirm variable `indepvars'  // make sure there is at least one indep
		
		/*
		* BODY 
		*/
	
			capture quietly generate `yhat' = 0
			capture replace `yhat' = .
			
			/*
			// must make this work
			//capture replace `yhat' = .
			*/

			local eff = ""

			if ("`effects'"!="") {
				eststo clear
				local eff= "effects(`effects')"

			}
			display "Predicting {result:`dvar'} on {result:`indepvars'}, saving Y-hats in {result:`yhat'}..."
			// quietly:
			local outmode = "quietly:"
			if ("`output'"=="output") {
				local outmode = ""
			}
			
			local con = ""
			if ("`contextvars'"!="") {
				local con = "contextvars(`contextvars')"
			}

			local stid = ""
			if ("`stackid'"!="") {
				local stid = "stackid(`stackid')"
			}
			
			//display "`outmode' bysort `stackvars': npredcent `dvar' `indepvars' `if', replace(`yhat') `logit' `stid' `centring' `eff' `con' `nostacks'"
			`outmode' bysort `stackvars': npredcent `dvar' `indepvars' `if', replace(`yhat') `logit' `stid' `centring' `eff' `con' `nostacks'
			
			if ("`effects'"!="") {
				local usefile = ""
				if ("`effects'"!="window") {
					local usefile = "using `yhat'.`effects'"
				}
				else {
						display "{p_end}"
				}
				if ("`logit'"=="logit") {
					local cellfmt = "z(fmt(3) star)"
					if ("`efmt'"!="") {
						local cellfmt = "`efmt'"
					}
					esttab `usefile', cells("`cellfmt'") pr2(%8.3f) mtitles replace compress wide onecell plain label
				}
				else {
					local cellfmt = "z(fmt(3) star)"
					if ("`efmt'"!="") {
						local cellfmt = "`efmt'"
					}
					if ("`efmt'"=="beta") {
						esttab `usefile', beta(%8.3f) not constant star ar2(%8.3f) mtitles replace compress wide onecell plain label
					}
					else {
						esttab `usefile', cells("`cellfmt'") ar2(%8.3f) constant mtitles replace compress wide onecell plain label
					}
				}
				//esttab , se ar2 b(3) wide nostar label mtitles replace compress plain
			}
			
			
			display "done."
			
			if ("`demean'"!="") {
				if ("`dprefix'"!="") {
					local dpref = "`dprefix'"
				}
				else {
					local dpref = "mean_"
				}
				
				if ("`logit'"=="logit") {
					gen log`yhat'=.
					replace log`yhat'=logit(`yhat')
					bysort `demean': egen log`dpref'`yhat'=mean(log`yhat')
					replace `yhat'=invlogit(log`yhat'-log`dpref'`yhat')
					gen `dpref'`yhat'=invlogit(log`dpref'`yhat')
					//capture drop log`dpref'`yhat' log`yhat'				
				}
				else {
					bysort `demean': egen `dpref'`yhat'=mean(`yhat')
					replace `yhat'=`yhat'-`dpref'`yhat'
				}
				

			}
			
			
			if ("`replace'"=="replace") {
				display " As requested, dropping {result:`indepvars'}...{break}"
				drop `indepvars'	
			}
			
			//display "{p_end}"
			display ""
			
		/*
		* END BODY
		*/
		
		if (`pipedsyntax'==1) {
			if ("`anything'" != "") gettoken string anything : anything  // move past "\" (dk how to avoid requiring a space after "\")
		}
	}
	
	display ""
	capture drop _stk_temp
	
end