iematch : added input test for grpdummy()

Tested that group dummy is a numeric variable and that it is eiter 1, 0
or missing

	clear

	*command starts here

	cap program drop 	iematch
	    program define	iematch

		syntax    , ///
			GRPdummy(varname) 		///
			MATCHcont(varname) 		///
			[						///
			idvar(varname)			///
			matchidname(string)		///
			matchdiffname(string)	///
			]

		*****
		*1. [if] [in]
		*2 make match only on obs with group
		*3 m:1 match

		noi di "Syntax OK!"

		qui {

		********************************
		*
		*	Checking groupvar
		*
		********************************

		*Test that the group dummy is 1, 0 or missing
		cap assert inlist(`grpdummy', 1, 0, .) | `grpdummy' > .

		if _rc != 0 {

			di as error "The variable in grpdummy(`grpdummy') is not a dummy variable. The variable is only allowed to have the values 1, 0 or missing. Observations with missing varaibles in the grpdummy are ignored by this command."
			error _rc
		}

		********************************
		*
		*	Checking ID var
		*
		********************************

		*Checking set-up for the ID var used for _matchID
		if "`idvar'" == "" {

			*Copy this name
			local idvar _ID

			*Make sure that the default name _ID is not already used
			cap confirm variable `idvar'
			if _rc == 0 {

				di as error "A variable with name `idvar' is already defined. Either drop this variable or specify a variable using idvar() that fully and uniquely identifies the data set."
				error 110

			}

			*Generate the ID var from row number
			gen `idvar' = _n

		}
		else {

			*Make sure that user specified ID is uniquely and fully identifying the observations
			cap isid `idvar'
			if _rc != 0 {

				di as error "Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. Meaning that `idvar' is not allowed to have any duplicates or missing values. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using if or in."
				error 450

			}
		}

		********************************
		*
		*	Checking and generating the MatchID and the MatchDiff var
		*
		********************************

		*See function below
		iematchMatchVarCheck `matchidname' _matchID
		local matchIDname "`r(validVarName)'"
		gen  `matchIDname' = .

		iematchMatchVarCheck `matchdiffname' _matchDiff
		local matchDiffName "`r(validVarName)'"
		gen `matchDiffName' = .

		********************************
		*
		*	Creating tempvar used
		*
		********************************

		tempvar hi_diff lo_diff pref match newMatch

		gen `hi_diff' = .
		gen `lo_diff' = .

		gen `pref' = .
		gen byte `match' = 0
		gen byte `newMatch' = 0

		********************************
		*
		*	Start matching
		*
		********************************

		count if `grpdummy' == 1 & `match' == 0
		local left2Match = `r(N)'

		while (`left2Match' > 0) {

			sort `match' `matchcont'

			replace `lo_diff' 	= .
			replace `hi_diff' 	= .
			replace `pref'		= . if `match' == 0
			replace `newMatch' 	= 0

			replace `lo_diff' = abs(`matchcont' - `matchcont'[_n-1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n-1]
			replace `hi_diff' = abs(`matchcont' - `matchcont'[_n+1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n+1]

			replace `pref' = `idvar'[_n-1] if `match' == 0 & `lo_diff' <  `hi_diff'
			replace `pref' = `idvar'[_n+1] if `match' == 0 & `lo_diff' >= `hi_diff'

			replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n-1] & `pref'[_n-1] == `idvar'
			replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n+1] & `pref'[_n+1] == `idvar'

			replace `match' = 1 							if `newMatch' == 1
			replace `matchDiffName' = min(`lo_diff', `hi_diff') 	if `newMatch' == 1
			replace `matchIDname' = `idvar' 						if `newMatch' == 1 & `grpdummy' == 1
			replace `matchIDname' = `pref' 						if `newMatch' == 1 & `grpdummy' == 0

			*order _match* , last

		noi	count if `grpdummy' == 1 & `match' == 0
			local left2Match = `r(N)'

			*pause

		}
	}

	end

	*Cheack matchVar input
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName optionName

		*Testing that the option name is not the same as the other variable's default name.
		if "`defaultName'" == "_matchID" & "`optionName'" == "_matchDiff" {

			noi di as error "The new name specified in matchidname() is not allowed to be _matchDiff"
			error 198
		}
		if "`defaultName'" == "_matchDiff" & "`optionName'" == "_matchID" {

			noi di as error "The new name specified in matchdiffname() is not allowed to be _matchID"
			error 198
		}

		*Checking set-up for the ID var used for _matchID
		if "``optionName''" == "" {

			*CSet the default name
			local validMatchVarname `defaultName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "A variable with name `validMatchVarname' is already defined. Either drop this variable or specify a new variable name using `optionName'()."
				error 110

			}

		}

		else {

			*CSet the default name
			local validMatchVarname `optionName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "The variable name `validMatchVarname' specified in `optionName'() is already defined in the data set. Either drop this variable or specify a another variable name using `optionName'()."
				error 110

			}

		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "The variable name specified is not a valid variable name."
			error _rc

		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end

	clear

*	set seed 1235324

	set obs 10000

	gen id = _n

	gen rand1 = uniform()

	gen tmt = (rand1 < .40)
	replace tmt = . if (rand1 < .2)
	replace tmt = .a if (rand1 < .1)

	drop rand1
	tab tmt

	gen p_hat = uniform()

	iematch if id < 5532  , grp(tmt) match(p_hat) idvar(id)

	clear

	*command starts here

	cap program drop 	iematch
	    program define	iematch

		syntax    , ///
			GRPdummy(varname) 		///
			MATCHcont(varname) 		///
			[						///
			idvar(varname)			///
			matchidname(string)		///
			matchdiffname(string)	///
			]

		*****
		*1. [if] [in]
		*2 make match only on obs with group
		*3 m:1 match

		noi di "Syntax OK!"

		qui {

		********************************
		*
		*	Checking ID var
		*
		********************************

		*Checking set-up for the ID var used for _matchID
		if "`idvar'" == "" {

			*Copy this name
			local idvar _ID

			*Make sure that the default name _ID is not already used
			cap confirm variable `idvar'
			if _rc == 0 {

				di as error "A variable with name `idvar' is already defined. Either drop this variable or specify a variable using idvar() that fully and uniquely identifies the data set."
				error 110

			}

			*Generate the ID var from row number
			gen `idvar' = _n

		}
		else {

			*Make sure that user specified ID is uniquely and fully identifying the observations
			cap isid `idvar'
			if _rc != 0 {

				di as error "Variable `idvar' specified in idvar() does not fully and uniquely identify the observations in the data set. Meaning that `idvar' is not allowed to have any duplicates or missing values. Make `idvar' uniquly and fully idnetifying or exclude the varaibleas using if or in."
				error 450

			}
		}

		********************************
		*
		*	Checking and generating the MatchID and the MatchDiff var
		*
		********************************

		*See function below
		iematchMatchVarCheck `matchidname' _matchID
		local matchIDname "`r(validVarName)'"
		gen  `matchIDname' = .

		iematchMatchVarCheck `matchdiffname' _matchDiff
		local matchDiffName "`r(validVarName)'"
		gen `matchDiffName' = .

		********************************
		*
		*	Creating tempvar used
		*
		********************************

		tempvar hi_diff lo_diff pref match newMatch

		gen `hi_diff' = .
		gen `lo_diff' = .

		gen `pref' = .
		gen byte `match' = 0
		gen byte `newMatch' = 0

		********************************
		*
		*	Start matching
		*
		********************************

		count if `grpdummy' == 1 & `match' == 0
		local left2Match = `r(N)'

		while (`left2Match' > 0) {

			sort `match' `matchcont'

			replace `lo_diff' 	= .
			replace `hi_diff' 	= .
			replace `pref'		= . if `match' == 0
			replace `newMatch' 	= 0

			replace `lo_diff' = abs(`matchcont' - `matchcont'[_n-1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n-1]
			replace `hi_diff' = abs(`matchcont' - `matchcont'[_n+1]) if `match' == 0 & `grpdummy' != `grpdummy'[_n+1]

			replace `pref' = `idvar'[_n-1] if `match' == 0 & `lo_diff' <  `hi_diff'
			replace `pref' = `idvar'[_n+1] if `match' == 0 & `lo_diff' >= `hi_diff'

			replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n-1] & `pref'[_n-1] == `idvar'
			replace `newMatch' = 1 if `match' == 0 & `pref' == `idvar'[_n+1] & `pref'[_n+1] == `idvar'

			replace `match' = 1 							if `newMatch' == 1
			replace `matchDiffName' = min(`lo_diff', `hi_diff') 	if `newMatch' == 1
			replace `matchIDname' = `idvar' 						if `newMatch' == 1 & `grpdummy' == 1
			replace `matchIDname' = `pref' 						if `newMatch' == 1 & `grpdummy' == 0

			*order _match* , last

		noi	count if `grpdummy' == 1 & `match' == 0
			local left2Match = `r(N)'

			*pause

		}
	}

	end

	*Cheack matchVar input
	cap program drop 	iematchMatchVarCheck
		program define 	iematchMatchVarCheck  , rclass

		args defaultName optionName

		*Testing that the option name is not the same as the other variable's default name.
		if "`defaultName'" == "_matchID" & "`optionName'" == "_matchDiff" {

			noi di as error "The new name specified in matchidname() is not allowed to be _matchDiff"
			error 198
		}
		if "`defaultName'" == "_matchDiff" & "`optionName'" == "_matchID" {

			noi di as error "The new name specified in matchdiffname() is not allowed to be _matchID"
			error 198
		}

		*Checking set-up for the ID var used for _matchID
		if "``optionName''" == "" {

			*CSet the default name
			local validMatchVarname `defaultName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "A variable with name `validMatchVarname' is already defined. Either drop this variable or specify a new variable name using `optionName'()."
				error 110

			}

		}

		else {

			*CSet the default name
			local validMatchVarname `optionName'

			*Make sure that the default name _ID is not already used
			cap confirm variable `validMatchVarname'
			if _rc == 0 {

				noi di as error "The variable name `validMatchVarname' specified in `optionName'() is already defined in the data set. Either drop this variable or specify a another variable name using `optionName'()."
				error 110

			}

		}

		*Testing that the new name is valid by creating a variable that is dropped immedeatly afterwards
		cap gen `validMatchVarname' = .

		if _rc != 0 {

			noi di as error "The variable name specified is not a valid variable name."
			error _rc

		}
		drop `validMatchVarname'

		return local validVarName 	"`validMatchVarname'"

	end

	set seed 1235324

	set obs 10000

	gen id = _n

	gen rand1 = uniform()

	gen tmt = (rand1 < .40)

	drop rand1
	tab tmt

	gen p_hat = uniform()

	iematch if id < 5532  , grp(tmt) match(p_hat) idvar(id)


Indentation

Indentation

cap	program drop	iegraph
	program define 	iegraph
	preserve
	syntax varlist, [noconfbars TItle(string) save(string) confbarsnone(varlist) *]

	mat beta_ = e(b)

	local counter = 0
	//local textfile = "Mrijan"

	qui{
		if "`confbars'" 			!= "" {
		local CONFINT_BAR 	= 0
		}
		else if "`confbars'" 			== "" {
		local CONFINT_BAR 	= 1
		}

		local varTest : list confbarsnone in varlist

		if `varTest' == 0 {
					noi display as error "{phang} Variables defined in confbarsnone cannot be found in the graph variable list. {p_end}"
					noi display ""
					error 111
					 }

		foreach var of local varlist{
			cap assert inlist(`var',0,1) | missing(`var')
				if _rc {
					noi display as error "{phang} The variable `var' is not a dummy. Treatment variable needs to be a dummy(0 or 1) variable. {p_end}"
					noi display ""
					error 149
					}
				else {
					}

		local counter = `counter' + 1
		di `counter'

		scalar coeff_`var' = _b[`var']
		//noi display coeff_`var'

		scalar coeff_se_`var' = _se[`var']
		//noi display coeff_se_`var'

		count if e(sample) == 1 & `var' == 1 //Count one tmt group at the time
		scalar obs_`var' = r(N)
		//noi display obs_`var'

	}

	local count: word count `varlist'
	local graphCount = `count' + 1
	//tokenize "`varlist'"
	//noi di `count'

	//Make all vars tempvars (maybe do later)
	//Make sure that missing is properly handled
	tempvar anyTMT
	egen `anyTMT' = rowmax(`varlist') if e(sample) == 1
	tempvar control
	gen `control' = (`anyTMT' == 0) if !missing(`anyTMT')

	sum `e(depvar)' if e(sample) == 1 & `control' == 1
	scalar ctl_N		= r(N)
	scalar ctl_mean	  	= r(mean)
	scalar ctl_mean_sd 	= r(sd)

		foreach var of local varlist {
			scalar  conf_int_min_`var'   =	coeff_`var'-(1.96*coeff_se_`var') + ctl_mean
			scalar  conf_int_max_`var'   =	coeff_`var'+(1.96*coeff_se_`var') + ctl_mean

			test `var'
			local star_`var' " "

			scalar  pvalue =r(p)
			if pvalue < 0.10 {
				local star_`var' "*"
			}
			if pvalue < 0.05 {
				local star_`var' "**"
			}
			if pvalue < 0.01 {
				local star_`var' "***"
			}
			*noi display "`star_`var''"
			scalar tmt_mean_`var' = ctl_mean + coeff_`var'
		}

	tempname 	newHandle
	tempfile	newTextFile
	cap file close 	`newHandle'
	file open  	`newHandle' using "`newTextFile'", text write append

	*Write headers and control value
	file write `newHandle' ///
		"order" 	_tab "xLabeled"	_tab "mean" _tab "coeff" _tab "conf_int_min" _tab "conf_int_max" _tab "obs" _tab "star" _n 	///
		%9.3f (1) _tab "Control"  _tab %9.3f (ctl_mean)      _tab  		 			_tab 		 			  	  _tab 			 				_tab %9.3f (ctl_N) 	   _tab			  	  _n

	tempvar newCounter
	gen `newCounter' = 2  //First tmt group starts at 2 (1 is control)

	foreach var in `varlist' {
	     if `: list var in confbarsnone' {
		file write `newHandle' ///
			%9.3f (`newCounter') _tab "`var'" _tab %9.3f (tmt_mean_`var') _tab  %9.3f (coeff_`var')  _tab %9.3f  _tab _tab %9.3f (obs_`var')   _tab "`star_`var''"  _n

		replace `newCounter' = `newCounter' + 1
			}
		else {
		file write `newHandle' ///
			%9.3f (`newCounter') _tab "`var'" _tab %9.3f (tmt_mean_`var') _tab  %9.3f (coeff_`var')  _tab %9.3f (conf_int_min_`var') _tab %9.3f (conf_int_max_`var') _tab %9.3f (obs_`var')   _tab "`star_`var''"  _n

		replace `newCounter' = `newCounter' + 1
		}
	}

	file close `newHandle'

	copy "`newTextFile'"  "mainMasterDofile.txt" , replace

	/*************************************

		Create the graph

	*************************************/

	insheet using mainMasterDofile.txt, clear

	local tmtGroupBars 	""
	local xAxisLabels 	`"xlabel( "'
	local legendLabels	`"lab(1 "`obsLabelControl'")"'
	local legendNumbers	""

	forval tmtGroupCount = 1/`graphCount' {

		************
		*Create the bar for this group

		colorPicker `tmtGroupCount' `graphCount'

		local tmtGroupBars `"`tmtGroupBars' (bar mean order if order == `tmtGroupCount', color("`r(color)'")) "'

		************
		*Create labels etc. for this group

		local obs 			= obs[`tmtGroupCount']
		local stars 		= star[`tmtGroupCount']
		local legendLabel 	= xlabeled[`tmtGroupCount']

		local xAxisLabels 	`"`xAxisLabels' `tmtGroupCount' "(N = `obs') `stars'" "'
		local legendLabels 	`"`legendLabels' lab(`tmtGroupCount' "`legendLabel'") "'
		local legendNumbers	`"`legendNumbers' `tmtGroupCount'"'
	}

	*Close or comple some strings
	local xAxisLabels `"`xAxisLabels' ,noticks labsize(medsmall)) "'
	local legendOption `"legend(order(`legendNumbers') `legendLabels')"'

	*Create the confidence interval bars
	if `CONFINT_BAR' == 0 {
		//local confIntGraph == `"(scatter mean order,  msym(none)  mlabs(medium) mlabpos(10) mlabcolor(black)), xtitle("") ytitle("`e(depvar)'") "'
		local confIntGraph = ""
	}
		else if `CONFINT_BAR' == 1 {
		local confIntGraph = `"(rcap conf_int_max conf_int_min order, lc(gs)) (scatter mean order,  msym(none)  mlabs(medium) mlabpos(10) mlabcolor(black))"'
	}

	local titleOption `" , xtitle("") ytitle("`e(depvar)'") "'

	if "`save'" != "" {
		local saveOption saving("`save'", replace)
	}

	noi di `" graph twoway `tmtGroupBars' `confIntGraph' `titleOption' `options' `legendOption' `xAxisLabels' `saveOption' title("`title'")   "'
	graph twoway `tmtGroupBars' `confIntGraph' `titleOption' `options' `legendOption' `xAxisLabels' `saveOption' title("`title'")
	//noi di 	`"graph twoway `tmtGroupBars' `legendOption' (scatter mean order,  msym(none)  mlabs(medium) mlabpos(10) mlabcolor(black))), xtitle("") ytitle("`e(depvar)'") `xAxisLabels' `saveOption' title("`title'")  "'

	restore
}

end

cap	program drop	colorPicker
	program define 	colorPicker , rclass

	args groupCount totalNumGroups

	if `totalNumGroups' == 2 {

		if `groupCount' == 1 return local color "215 25 28"
		if `groupCount' == 2 return local color "43 123 182"
	}
	else if `totalNumGroups' == 3 {

		if `groupCount' == 1 return local color "215 25 28"
		if `groupCount' == 2 return local color "255 255 191"
		if `groupCount' == 3 return local color "43 123 182"
	}
	else if `totalNumGroups' == 4 {

		if `groupCount' == 1 return local color "215 25 28"
		if `groupCount' == 2 return local color "255 255 191"
		if `groupCount' == 3 return local color "171 217 233"
		if `groupCount' == 4 return local color "43 123 182"
	}
	else {

		*For five or more colors we repeat the same pattern

		local colourNum = mod(`groupCount', 5)
		if `colourNum' == 1 return local color "215 25 28"
		if `colourNum' == 2 return local color "253 174 93"
		if `colourNum' == 3 return local color "255 255 191"
		if `colourNum' == 4 return local color "171 217 233"
		if `colourNum' == 0 return local color "43 123 182"

	}

end


added expolate data function

added expolate data function

program county_pop

local dat_name "${rawmaps}us.1990_2012.singleages.adjusted.txt"

local dta_name "${rawmaps}seer_pop"

local dct_name "${rawmaps}seer_pop.dct"

infile using "`dct_name'", using("`dat_name'") clear

gen str3 tmp1=string(county, "%03.0f")
gen str2 tmp2=string(stfips, "%02.0f")
gen fips = tmp2 + tmp1
drop tmp1 tmp2

drop if year < 2005
bysort year fips: egen pop_year = total(pop)

bysort year fips: drop if _n > 1
keep year fips pop_year

expolate

save ${rawmaps}county_pop, replace

end

program expolate

bysort fips: gen tmp = _N
drop if tmp < 8

local num = 3138

local new = _N + (`num'*2)
set obs `new'

sort year fips
replace fips = fips[_n-`num'*8] if fips == "" & _n < (_N+`num')

sort fips year
bysort fips: replace year = 2013 if year == . & _n == 9
bysort fips: replace year = 2014 if year == . & _n == 10

bysort fips: ipolate pop_year year, gen (y2) epolate
replace pop_year = y2 if pop_year == .

drop tmp

end

program county_pop

local dat_name "${rawmaps}us.1990_2012.singleages.adjusted.txt"

local dta_name "${rawmaps}seer_pop"

local dct_name "${rawmaps}seer_pop.dct"

infile using "`dct_name'", using("`dat_name'") clear

gen str3 tmp1=string(county, "%03.0f")
gen str2 tmp2=string(stfips, "%02.0f")
gen fips = tmp2 + tmp1
drop tmp1 tmp2

drop if year < 2005
bysort year fips: egen pop_year = total(pop)

bysort year fips: drop if _n > 1
keep year fips pop_year

save ${rawmaps}county_pop, replace

end


ieimpgraph runfile lightening seminar

ieimpgraph runfile lightening seminar

minor edit to run file for lightening seminar

	*Set standardized settings
	ieboilstart, v(11.1)
	`r(version)'

	*Create filepaths
	*global ietoolkit "C:\Users\wb503680\Box Sync\DIME WOrk\GitFolder\ietoolkit"
	global ietoolkit "C:\Users\wb462869\Box Sync\Stata\Stata work\Commands\ietoolkit"
	global testOuput "$ietoolkit/test/ieimpgraphOutput"

	*Set cd folder to catch and cd leakage
	cd "$ietoolkit\test\cdjunk"

	*Load the command
	do "$ietoolkit\ieimpgraph2.do"

	**********************
	*Graph 1 - single treatment

	*open an example data set and create a mock dummy
	sysuse auto, clear
	gen Treatment = (weight >= 3019.5)

	*Run the impact regression
	reg price  Treatment
	*Create the graph
	ieimpgraph Treatment, title("Treatment effect on price") save("$testOuput/Graph1.gph")

	**********************
	*Graph 2 - multiple treatment

	*open an example data set and create mutaually exclusive mock dummies
	sysuse auto, clear
	tab rep78, gen(d_)

	*Run the impact regression
	reg price  d_2 d_3 d_4 d_5 weight length gear_ratio
	*Create the graph
	ieimpgraph d_2 d_3 d_4 d_5, title("Treatment effect on price") save("$testOuput/Graph2.gph")

	*Set standardized settings
	ieboilstart, v(11.1)
	`r(version)'

	*Create filepaths
	*global ietoolkit "C:\Users\wb503680\Box Sync\DIME WOrk\GitFolder\ietoolkit"
	global ietoolkit "C:\Users\wb462869\Box Sync\Stata\Stata work\Commands\ietoolkit"
	global testOuput "$ietoolkit/test/ieimpgraphOutput"

	*Set cd folder to catch and cd leakage
	cd "$ietoolkit\test\cdjunk"

	*Load the command
	do "$ietoolkit\ieimpgraph2.do"

	**********************
	*Graph 1 - single treatment

	*open an example data set and create a mock dummy
	sysuse auto, clear
	gen dummy = (weight >= 3019.5)

	*Run the impact regression
	reg price  dummy
	*Create the graph
	ieimpgraph dummy, title("Treatment effect on price") save("$testOuput/Graph1.gph")

	**********************
	*Graph 2 - multiple treatment

	*open an example data set and create mutaually exclusive mock dummies
	sysuse auto, clear
	tab rep78, gen(d_)

	*Run the impact regression
	reg price  d_2 d_3 d_4 d_5 weight length gear_ratio
	*Create the graph
	ieimpgraph d_2 d_3 d_4 d_5, title("Treatment effect on price") save("$testOuput/Graph2.gph")


cv syntax fixes

cv syntax fixes

- allow i. and time series variables (which unlike most things in Stata, you need to explicitly enable, even just to pass them through untouched)
- confirm var `varlist' is wrong; syntax already enforces that varlist is a varlist, and confirm var is for single variables at a time

/* cv: cross-validated predictions from any Stata estimation command.
 *
 * Breaks a dataset into a number of subsets ("folds"), and for each
 * runs an estimator on everything but that subset, and predicts results.
 * In this way, the fit is unbiased by the estimation process, because
 * each prediction is made from data which were never involved in fitting.
 * Sometimes this is described as a way to control overfitting.
 *
 *
 * In general there are two ways to measure the performance of an estimator:
 *  looking at its residuals -- in machine learning jargon, the training error
 *  looking at its cross-validated residuals -- the cross-validation error
 * The cv error is an estimate of the generalization error --- the performance
 * of your model on data it has never seen before --- which is usually what you care about in applications.
 * The ratio of the two tells you if you are over- or under- fitting:
 *  - if training error is higher, you are underfitting---you do not have enough degrees of freedom in your model---because the training is not doing as well on the full dataset as it does on slices (this is rare)
 *  - if training error is lower, you are overfitting---you have too many degrees of freedom, and you're fitting noise instead of signal---, because the training error is underestimating the generalization error.
 *
 * (There is also a third measurement:
 *  looking at it's test-set residuals -- the testing error
 * Cross-validation is usually used in conjunction with grid-search to tune tuning-parameters.
 * This in itself can be thought of as a type of estimation, and hence keeping a spare set of data
 * purely for testing immunizes your performance from overfitting in the grid-search,
 * even though each individual section of grid-search should be immune from overfitting.)
 *
 *
 * syntax:
 * cv target estimator y x1 x2 x3 ... [if] [in], folds(#) [shuffle] [options to estimator]
 *
 * estimator should be a standard Stata estimation command which can be followed by a call to "predict target if"
 * folds is the number of folds to make. More is more accurate but slower.
 *   As a special case, pass folds(1) to simply train and predict at once.
 *   To do leave-one-out cross-validation (LOOCV), pass the number of observations (e.g. folds(`=_N'), though if you use if/in you'll need to modify that).
 *
 * to further reduce bias, consider passing shuffle, but make sure you {help set seed:seed} the RNG well
 *  (e.g. see {help clockseed} or {help truernd}).
 *
 * Example:
 *
 * . sysuse auto
 * . svm foreign headroom gear_ratio weight, type(c_svc) gamma(0.4) c(51)
 * . predict P
 * . gen err = foreign != P
 * . qui sum err
 * . di "Training error rate: `r(mean)'"
 * . drop P err
 * .
 * . cv P svm foreign headroom gear_ratio weight, folds(`=floor(_N/3)') type(c_svc) gamma(0.4) c(51)
 * . gen err = foreign != P
 * . qui sum err
 * . di "Cross-validated error rate: `r(mean)'"
 *
 * Example of if/in:
 * . cv P svm gear_ratio foreign headroom weight if gear_ratio > 3 in 22/63, folds(4) shuffle type(epsilon_svr) eps(0.5)
 *
 * You can use this with "unsupervised" estimators---ones which take no {help depvar} (y)---too.
 * cv passes whatever options you give it directly to the estimator; all it handles it the folding.
 *
 *
 * See also:
 *  {help gridsearch}
 *
 *
 * TODO:
 *  [x] 'if' and 'in'
 *  [ ] stratified folding
 *  [ ] is 'shuffle' a huge slowdown??
 *  [ ] maybe this should be called "cross_predict" because we don't actually do the validation...
 */

program define cv, eclass

  /* parse arguments */
  gettoken target 0 : 0
  gettoken estimator 0 : 0
  syntax varlist (fv ts) [if] [in], [folds(string)] [shuffle] [*]

  confirm name `estimator'
  confirm new variable `target'

  //Stata if funky: because I use [*] above, if I declare folds(int 5) and you pass a real (e.g. folds(18.5)), rather than giving the usual "option folds() incorrectly specified" error, Stata *ignores* that folds, gives the default value, and pushes the wrong folds into the `options' macro, which is really the worst of all worlds
  // instead, I take a string (i.e. anything) to ensure the folds option always,
  // and then parse manually
  if("`folds'"=="") {
    local folds = 5
  }
  confirm integer number `folds'

  //di as txt "folds= `folds' options=`options'" //DEBUG

  qui count `if' `in'
  if(`folds'<1 | `folds'>=`r(N)') {
    di as error "Invalid number of folds: `folds'. Must be between 2 and the number of active observations `r(N)'."
    exit 1
  }

  if(`folds'==1) {
    // special case: 1-fold is the same as just traing
    `estimator' `varlist' `if' `in', `options'
    predict `target'
    exit
  }

  if("`strata'" != "") {
    confirm variable `strata'
    di as error "cv: stratification not implemented."
    exit 2
  }

  /* generate folds */
  // the easiest way to do this in Stata is simply to mark a new column
  // and stamp out id numbers into it
  // the tricky part is dealing with if/in
  // and the trickier (and currently not implemented) part is dealing with
  // stratification (making sure each fold has equal proportions of a categorical variable)
  tempvar fold

  // compute the size of each group *as a float*
  // derivation:
  // we have r(N) items in total -- you can also think of this as the last item, which should get mapped to group `folds'
  // we want `folds' groups
  // if we divide each _n by `folds' then the largest ID generated is r(N)/`folds' == # of items per group
  // so we can't do that
  // if instead we divide each _n by r(N)/`folds', then the largest is r(N)/(r(N)/`folds') = `folds'
  // Also, maybe clearer, this python script empirically proves the formula:
  /*
  for G in range(1,302):
      for N in range(G,1302):
          folds = {k: len(list(g)) for k,g in groupby(int((i-1)//(N/G)+1) for i in range(1,N+1)) }
          print("N =", N, "G =", G, "keys:", set(folds.keys()));
          assert set(folds.keys()) == set(range(1,G+1))
  */
  qui count `if' `in'
  local g =  `r(N)'/`folds'
    // generate a pseudo-_n which is the observation *within the if/in subset*
    // if you do not give if/in this is should be equal to _n
  qui gen int `fold' = 1 `if' `in'

  /* shuffling */
  // this is tricky: shuffling has to happen *after* partially generating fold IDs,
  // because the shuffle invalidates the `in', but it must happen *before* the IDs
  // are actually assigned because otherwise there's no point
  if("`shuffle'"!="") {
    tempvar original_order
    tempvar random_order
    qui gen `original_order' = _n
    qui gen `random_order' = uniform()
    sort `random_order'
  }

  qui replace `fold' = sum(`fold') if !missing(`fold') //egen has 'fill()' which is more complicated than this, and so does not allow if/in. None of its other options seem to be what I want.

  // map the pseudo-_n into a fold id number
  // nopromote causes integer instead of floating point division, which is needed for id numbers
  //Stata counts from 1, which is why the -1 and +1s are there
  // (because the proper computation should happen counting from 0, but nooo)
  qui replace `fold' = (`fold'-1)/`g'+1 if !missing(`fold'), nopromote

  // because shuffling can only affect which folds data ends up in,
  // immediately after generating fold labels we can put the data back as they were.
  // (i prefer rather do this early lest something later break and the dataset be mangled)
  // (this can't use snapshot or preserve because restoring those will erase `fold')
  if("`shuffle'"!="") {
    sort `original_order'
  }

  // make sure the trickery above worked, more or less
  qui sum `fold'
  assert `r(min)'==1
  assert `r(max)'==`folds'
  qui levelsof `fold'
  assert `: word count `r(levels)''==`folds'

  /* cross-predict */
  // We don't actually predict into target directly, because most estimation commands
  // get annoyed at you trying to overwrite an old variable (even if an unused region).
  // Instead we repeatedly predict into B, copy the fold into target, and destroy B.
  //
  // We don't actually create `target' until we have done one fold, at which point we *clone* it
  // because we do not know what types/labels the predictor wants to attach to its predictions,
  // (which can lead to strangeness if the predictor is inconsistent with itself)
  tempvar B
  forvalues f = 1/`folds' {
    // train on everything that isn't the fold
    qui count if `fold' != `f'
    di "[fold `f'/`folds': training on `r(N)' observations]"
    capture `estimator' `varlist' if `fold' != `f', `options'
    if(_rc!=0) {
      di as error "`estimator' failed"
      exit _rc
    }

    // predict on the fold
    qui count if `fold' == `f'
    di "[fold `f'/`folds': predicting on `r(N)' observations]"
    predict `B' if `fold' == `f'

    // on the first fold, *clone* B to our real output
    if(`f' == 1) {
      qui clone `target' `B' if 0
    }

    // save the predictions from the current fold
    qui replace `target' = `B' if `fold' == `f'
    drop `B'
  }

  /* clean up */
  // drop e(), because its contents at this point are only valid for the last fold
  // and that's just confusing
  ereturn clear
end

/* cv: cross-validated predictions from any Stata estimation command.
 *
 * Breaks a dataset into a number of subsets ("folds"), and for each
 * runs an estimator on everything but that subset, and predicts results.
 * In this way, the fit is unbiased by the estimation process, because
 * each prediction is made from data which were never involved in fitting.
 * Sometimes this is described as a way to control overfitting.
 *
 *
 * In general there are two ways to measure the performance of an estimator:
 *  looking at its residuals -- in machine learning jargon, the training error
 *  looking at its cross-validated residuals -- the cross-validation error
 * The cv error is an estimate of the generalization error --- the performance
 * of your model on data it has never seen before --- which is usually what you care about in applications.
 * The ratio of the two tells you if you are over- or under- fitting:
 *  - if training error is higher, you are underfitting---you do not have enough degrees of freedom in your model---because the training is not doing as well on the full dataset as it does on slices (this is rare)
 *  - if training error is lower, you are overfitting---you have too many degrees of freedom, and you're fitting noise instead of signal---, because the training error is underestimating the generalization error.
 *
 * (There is also a third measurement:
 *  looking at it's test-set residuals -- the testing error
 * Cross-validation is usually used in conjunction with grid-search to tune tuning-parameters.
 * This in itself can be thought of as a type of estimation, and hence keeping a spare set of data
 * purely for testing immunizes your performance from overfitting in the grid-search,
 * even though each individual section of grid-search should be immune from overfitting.)
 *
 *
 * syntax:
 * cv target estimator y x1 x2 x3 ... [if] [in], folds(#) [shuffle] [options to estimator]
 *
 * estimator should be a standard Stata estimation command which can be followed by a call to "predict target if"
 * folds is the number of folds to make. More is more accurate but slower.
 *   As a special case, pass folds(1) to simply train and predict at once.
 *   To do leave-one-out cross-validation (LOOCV), pass the number of observations (e.g. folds(`=_N'), though if you use if/in you'll need to modify that).
 *
 * to further reduce bias, consider passing shuffle, but make sure you {help set seed:seed} the RNG well
 *  (e.g. see {help clockseed} or {help truernd}).
 *
 * Example:
 *
 * . sysuse auto
 * . svm foreign headroom gear_ratio weight, type(c_svc) gamma(0.4) c(51)
 * . predict P
 * . gen err = foreign != P
 * . qui sum err
 * . di "Training error rate: `r(mean)'"
 * . drop P err
 * .
 * . cv P svm foreign headroom gear_ratio weight, folds(`=floor(_N/3)') type(c_svc) gamma(0.4) c(51)
 * . gen err = foreign != P
 * . qui sum err
 * . di "Cross-validated error rate: `r(mean)'"
 *
 * Example of if/in:
 * . cv P svm gear_ratio foreign headroom weight if gear_ratio > 3 in 22/63, folds(4) shuffle type(epsilon_svr) eps(0.5)
 *
 * You can use this with "unsupervised" estimators---ones which take no {help depvar} (y)---too.
 * cv passes whatever options you give it directly to the estimator; all it handles it the folding.
 *
 *
 * See also:
 *  {help gridsearch}
 *
 *
 * TODO:
 *  [x] 'if' and 'in'
 *  [ ] stratified folding
 *  [ ] is 'shuffle' a huge slowdown??
 *  [ ] maybe this should be called "cross_predict" because we don't actually do the validation...
 */

program define cv, eclass

  /* parse arguments */
  gettoken target 0 : 0
  gettoken estimator 0 : 0
  syntax varlist [if] [in], [folds(string)] [shuffle] [*]

  confirm name `estimator'
  confirm new variable `target'
  confirm variable `varlist'

  //Stata if funky: because I use [*] above, if I declare folds(int 5) and you pass a real (e.g. folds(18.5)), rather than giving the usual "option folds() incorrectly specified" error, Stata *ignores* that folds, gives the default value, and pushes the wrong folds into the `options' macro, which is really the worst of all worlds
  // instead, I take a string (i.e. anything) to ensure the folds option always,
  // and then parse manually
  if("`folds'"=="") {
    local folds = 5
  }
  confirm integer number `folds'

  //di as txt "folds= `folds' options=`options'" //DEBUG

  qui count `if' `in'
  if(`folds'<1 | `folds'>=`r(N)') {
    di as error "Invalid number of folds: `folds'. Must be between 2 and the number of active observations `r(N)'."
    exit 1
  }

  if(`folds'==1) {
    // special case: 1-fold is the same as just traing
    `estimator' `varlist' `if' `in', `options'
    predict `target'
    exit
  }

  if("`strata'" != "") {
    confirm variable `strata'
    di as error "cv: stratification not implemented."
    exit 2
  }

  /* generate folds */
  // the easiest way to do this in Stata is simply to mark a new column
  // and stamp out id numbers into it
  // the tricky part is dealing with if/in
  // and the trickier (and currently not implemented) part is dealing with
  // stratification (making sure each fold has equal proportions of a categorical variable)
  tempvar fold

  // compute the size of each group *as a float*
  // derivation:
  // we have r(N) items in total -- you can also think of this as the last item, which should get mapped to group `folds'
  // we want `folds' groups
  // if we divide each _n by `folds' then the largest ID generated is r(N)/`folds' == # of items per group
  // so we can't do that
  // if instead we divide each _n by r(N)/`folds', then the largest is r(N)/(r(N)/`folds') = `folds'
  // Also, maybe clearer, this python script empirically proves the formula:
  /*
  for G in range(1,302):
      for N in range(G,1302):
          folds = {k: len(list(g)) for k,g in groupby(int((i-1)//(N/G)+1) for i in range(1,N+1)) }
          print("N =", N, "G =", G, "keys:", set(folds.keys()));
          assert set(folds.keys()) == set(range(1,G+1))
  */
  qui count `if' `in'
  local g =  `r(N)'/`folds'
    // generate a pseudo-_n which is the observation *within the if/in subset*
    // if you do not give if/in this is should be equal to _n
  qui gen int `fold' = 1 `if' `in'

  /* shuffling */
  // this is tricky: shuffling has to happen *after* partially generating fold IDs,
  // because the shuffle invalidates the `in', but it must happen *before* the IDs
  // are actually assigned because otherwise there's no point
  if("`shuffle'"!="") {
    tempvar original_order
    tempvar random_order
    qui gen `original_order' = _n
    qui gen `random_order' = uniform()
    sort `random_order'
  }

  qui replace `fold' = sum(`fold') if !missing(`fold') //egen has 'fill()' which is more complicated than this, and so does not allow if/in. None of its other options seem to be what I want.

  // map the pseudo-_n into a fold id number
  // nopromote causes integer instead of floating point division, which is needed for id numbers
  //Stata counts from 1, which is why the -1 and +1s are there
  // (because the proper computation should happen counting from 0, but nooo)
  qui replace `fold' = (`fold'-1)/`g'+1 if !missing(`fold'), nopromote

  // because shuffling can only affect which folds data ends up in,
  // immediately after generating fold labels we can put the data back as they were.
  // (i prefer rather do this early lest something later break and the dataset be mangled)
  // (this can't use snapshot or preserve because restoring those will erase `fold')
  if("`shuffle'"!="") {
    sort `original_order'
  }

  // make sure the trickery above worked, more or less
  qui sum `fold'
  assert `r(min)'==1
  assert `r(max)'==`folds'
  qui levelsof `fold'
  assert `: word count `r(levels)''==`folds'

  /* cross-predict */
  // We don't actually predict into target directly, because most estimation commands
  // get annoyed at you trying to overwrite an old variable (even if an unused region).
  // Instead we repeatedly predict into B, copy the fold into target, and destroy B.
  //
  // We don't actually create `target' until we have done one fold, at which point we *clone* it
  // because we do not know what types/labels the predictor wants to attach to its predictions,
  // (which can lead to strangeness if the predictor is inconsistent with itself)
  tempvar B
  forvalues f = 1/`folds' {
    // train on everything that isn't the fold
    qui count if `fold' != `f'
    di "[fold `f'/`folds': training on `r(N)' observations]"
    capture `estimator' `varlist' if `fold' != `f', `options'
    if(_rc!=0) {
      di as error "`estimator' failed"
      exit _rc
    }

    // predict on the fold
    qui count if `fold' == `f'
    di "[fold `f'/`folds': predicting on `r(N)' observations]"
    predict `B' if `fold' == `f'

    // on the first fold, *clone* B to our real output
    if(`f' == 1) {
      qui clone `target' `B' if 0
    }

    // save the predictions from the current fold
    qui replace `target' = `B' if `fold' == `f'
    drop `B'
  }

  /* clean up */
  // drop e(), because its contents at this point are only valid for the last fold
  // and that's just confusing
  ereturn clear
end


build before install

build before install

#!/bin/sh

redo @all
sudo install -t ${DESTDIR:-/usr/local/bin/} `sed s}^}bin/} < BIN`

#!/bin/sh

install -t ${DESTDIR:-/usr/local/bin/} `sed s}^}bin/} < BIN`


fix issue #99 - typo in help file

fix issue #99 - typo in help file

{smcl}
{* 28 Jul 2017}{...}
{hline}
help for {hi:ieboilstart}
{hline}

{title:Title}

{phang}{cmdab:ieboilstart} {hline 2} Harmonizes settings across team members in the same project to the longest extent technically possible.

{phang}{hi:DISCLAIMER} {hline 1} Due to technical reasons, it is
impossible to guarantee that different types of Stata (version number, Small/IC/SE/MP
or PC/Mac/Linux) work exactly the same in every possible context. This command does not
guarantee against any version discrepancies, it is solely a collection of common practices
to reduce the risk of the same code running differently on different computers. See more
details {help ieboilstart##comp:below}.

{marker synt}{...}
{title:Syntax}

{phang}Note that due to technical requirements in Stata, to include the most
	important setting in this command you must include the second line below.{p_end}

{pmore}
{cmdab:ieboilstart} , {cmdab:v:ersionnumber(}{it:version_number}{cmd:)}  [{it:optional_options}]{break}
`r(version)'

{phang}The second line "`r(version)'" uses the command {help version} to set the same Stata version accross all
	users. "`r(version)'" is identical to setting the version to the version number set in {cmdab:v:ersionnumber()} but
	both helps standardize this setting across different parts in the project and function as a reminder to
	set the version number. {p_end}

{marker opts}{...}
{synoptset 20}{...}
{synopthdr:options}
{synoptline}
{synopt :{cmdab:v:ersionnumber(}{it:string}{cmd:)}}sets a stable version of Stata
	for all users. This option does {ul:nothing} unless "`r(version)'" is included as in the example above.{p_end}
{synopt :{cmdab:maxvar(}{it:numlist}{cmd:)}}manually sets the maximum number of
	variables allowed in a data set. The default if omitted is 32,767.{p_end}
{synopt :{cmdab:matsize(}{it:numlist}{cmd:)}}manually sets the maximum number of
	variables allowed in an estimation command, for example {help regress:regress}.
	The default if omitted is 400.{p_end}
{synopt :{cmdab:noclear}}prevents the command to clear all data which some settings
	require. Best practice is to use this command before opening any data.{p_end}
{synopt :{cmdab:q:uietly}}suppresses the output with the disclaimer and the list
	of settings.{p_end}
{synopt :{cmdab:veryquietly}}does what {cmdab:quietly} does, but also suppresses the
	reminder to include "`r(version)'".{p_end}
{synopt :{cmdab:setmem(}{it:string}{cmd:)}}manually sets the memory for	Stata 11 users.{p_end}
{synopt :{cmdab:c:ustom(}{it:string}{cmd:)}}allows the user to enter custom lines
	of code to be added.{p_end}
{synoptline}

{marker desc}{...}
{title:Description}

{pstd}{cmdab:ieboilstart} standardizes best practice settings across all users using for a project.
	Such standardized code is usually referred to as boilerplate code, and that is
	where {cmdab:ieboilstart} lends it's name from. Standardizing the boilerplate code
	in a project reduces the risk that code behaves differently across users regardless of
	what version and type of Stata they are running.

{pstd}A command like this is impossible to make comprehensive in terms of versions control. Therefore,
	the ambition of this command is only to provide a convenient way to include boilerplate code based
	on commonly used best practices, which is much better than having no boilerplate code at all. The default
	values used are the values that are standard in boilerplate code for dofiles written or Impact
	Evaluations at DIME, World Bank. Suggestions for additions or improvements are very welcomed. See
	the {help ieboilstart##auth:author} section	for contact details.

{marker comp}{...}
{title:Compatibility Across Different Stata:}

{pstd}{cmdab:ieboilstart} sets settings that increases compatibility between Stata 11.0-15.0, Stata Small/IC/SE/MP and Stata for	PC/Mac/Linux. {it:Increase compatibility} does not mean an absolute guarantee that all code will always
	work the same in different types of Stata. That is technically impossible. {it:Increase compatibility} here means reducing the risk of code working differently in different types of Stata.

{pstd}{cmdab:ieboilstart} does sometimes apply different settings for different users as all settings does not work for all versions and types of Stata. For example, new memory settings were introduced in Stata 12 and {inp:set maxvar} is not allowed in Stata IC. {cmdab:ieboilstart} is implemented to set the settings in each version and type of Stata that reduces the risk of errors when different users run the same code, but the only way to eliminate the risk completely, is to use exactly the same version of Stata.

{pstd}In addition to version control, {cmdab:ieboilstart} allows a project to 	standardize user preference settings such as {help set varabbrev:varabbrev} that 		can cause code to behave differently across users.

{title:Important Details on Version Setting:}

{pstd}Impact Evaluations and other research projects often span over many
	years, which means that the same code is likely to run in different versions
	of Stata. Stata provides an method to reduce the risk of discrepancies due to this. See {help version:version} settings for more details. This method is included in {cmdab:ieboilstart}, however, {cmd:version} is mainly intended for making code written in Stata 11 to work
	in Stata 14 and not necessarily the other way around. Setting the version is still best practice and perhaps the most important setting in {cmdab:ieboilstart}. Read the {help ieboilstart##synt:syntax section} on the extra step required for {cmdab:ieboilstart} to set the version.{p_end}

{pstd}{hi:Warning:} Any dofiles containing randomization {ul:{hi:MUST}} set the version number
	as Stata occasionally makes updates to its randomization algorithm between versions. A dofile including random assignment
	or random sampling is therefore not necessarily stable across different versions of Stata,
	unless the dofile has a version number explicitly set in the beginning of the file.{p_end}

	{pstd}The version setting has the scope of a local, meaning that it expires when a dofile and all sub-dofiles it is calling are completed. Therefore, set the version in your master dofile {ul:and} in every single dofile using randomization. This will make your randomization stable even if another user would only run the specific dofile with the randomization.{p_end}

{title:Details on Memory Settings:}

{pstd}In Stata versions before Stata 12, memory was assigned statically from the
	computer memory, meaning that there was a fixed amount of memory assigned to Stata
	regardless if required it or not. Stata would crash if it went over that fixed limit
	when for example increasing the data set or running a complex calculation. In Stata
	12 and more recent versions, this is done dynamically, meaning that Stata is assigned
	a little bit of memory when it is starts and assigned additional memory dynamically
	as needed. The only memory limit is the hardware limits on the computer it is running
	on.

{pstd}The fixed memory in Stata 11 was assigned by the command {cmdab:set memory}. This
	command is simply ignored in Stata 12 or later. Instead the dynamic memory setting
	can be fine tuned with {cmdab:min_memory}, {cmdab:max_memory}, {cmdab:niceness} and
	{cmdab:segmentsize}, although even highly advanced users rarely have to worry about these settings as long as they are set to the recommended default values
	(which this command ensures that they are).

{p2colset 5 22 24 2}
{p2col : Memory Settings}Short explanation{p_end}
{p2line}
{pstd}{it: Basic Settings:}{p_end}
{p2col :{cmdab:set maxvar}}sets the maximum number of variables allowed. The
	default value is 32,767 the maximum allowed in Stata MP or SE. A lower maximum number can manually be set by the option {cmdab:maxvar()}. This setting is skipped using an if-statement if the dofile is executed in Stata Small or IC. See {help set maxvar:set maxvar}.{p_end}
{p2col :{cmdab:set matsize}}sets the maximum number of variables that can be included in estimation commands such as {cmd:regress}. The {cmdab:ieboilstart} default value is 400 which is the default value for Stata. The maximum number can manually be set by the option {cmdab:matsize()} as long as the number does not violate the limitations in your version of Stata. See {help set matsize:set matsize}.{p_end}
{break}
{pstd}{it: Dynamic Memory Settings (see {help memory:memory} for details and reasons for default values. Few users ever need to change these values):}{p_end}
{p2col :{cmdab:set min_memory}}sets a lower bound for the amount of memory assigned to Stata. The default value is no lower bound.{p_end}
{p2col :{cmdab:set max_memory}}sets an upper bound for the amount of memory assigned to Stata. The default is as much as the hardware of the computer allows.{p_end}
{p2col :{cmdab:set niceness}}defines how quickly Stata releases unused memory back to the computer{p_end}
{p2col :{cmdab:set segmentsize}}defines how large bundles of data is assigned each time
			Stata request more memory. Too large bundles make Stata occupy an
			unnecessary large part of the computer's memory (that otherwise could
			have been used by other applications), and too small bundles make
			Stata frequently consume processing power requesting new bundles.{p_end}
{break}
{pstd}{it: Static Memory Settings (only applicable in Stata 11)}{p_end}
{p2col :{cmdab:set memory}}sets the amount of static memory assigned to Stata. {p_end}
{p2line}

{pstd}{hi:{ul:Other Settings:}}{break}The other settings are included as they are either very
	commonly preferred or reduces the risk of errors for users that do not yet fully understand
	the implication of setting these settings to other values than what is recommended. These
	settings can be reverted to personal preferences after running {cmdab:ieboilstart} or by using the {cmd:custom()} option.{p_end}
{p2colset 5 24 26 2}
{p2col : Other Settings}Short explanation{p_end}
{p2line}
{p2col :{cmdab:set more off}}disables the default setting that Stata stops and
	waits for the user to press any key each time the output window is full. Long
	dofiles would take a very long time to run and require constant attention from
	the user without this setting. Most Stata users always disable the default
	which is {cmdab:set more on}. See {help set more:set more}.{p_end}
{p2col :{cmdab:pause on}}allows the usage of the command {cmdab:pause} which can
	be very useful during debugging. See {help pause:pause}.{p_end}
{p2col :{cmdab:set varabbrev off}}allows users to abbreviate variable names
		similarly to command names such as gen for generate and reg for regress.
		However, while command abbreviation has strict rules constant across data sets, users, and
		Stata versions; variable name abbreviation does not have the same strict rules
		and consistency. While enabling variable abbreviation can speed up coding,
		it is an error-prone technique unless all users using a dofile with
		variable abbreviations organize their coding practices exactly the same
		way. See {help set varabbrev:set varabbrev} for more details and carfully
		consider this caution before enabling variable abbreviations in a
		collaborative dofile.{p_end}
{p2line}

{title:Options}

{phang}{cmdab:v:ersionnumber(}{it:string}{cmd:)} sets a stable version of Stata
	for all users. Stata does not (for good reasons) allow a user written command
	to alter the version setting from inside a command. Therefore, this option does
	{ul:nothing} unless "`r(version)'" is included as described in the
	{help ieboilstart##synt:syntax section}. While the version number cannot be set
	inside the command code, {cmd:ieboilstart} does two things. First it reminds
	the user to set the version since it is a required command. Second, it makes
	sure that the version number used is not too old. A too old version might
	risk that there are far too big a difference in many commands. Best
	practice is therefore to keep the same version number throughout a project,
	unless there is something specific to a newer version that is required for any
	dofile. Only major and recent versions are allowed in order to reduce errors and
	complexity. The valid versions are 11.0, 11.1, 11.2, 12.0, 12.1, 13.0, 13.1,
	14.0, 14.1, 14.2, 15.0 and all versions without decimals. However, it is recommended
	to use a .1 over a .0 version. .1 is free of charge if you already have the
	corresponding .0 and .1 includes bug fixes to the functions introduced in .0.
	All versions of Stata can be set to run any older version of Stata but not a newer. {p_end}

{phang}{cmdab:maxvar(}{it:numlist}{cmd:)} manually sets the maximum number of
	variables allowed in a data set. The default is to set the number to the highest
	allowed. Reducing this number can occasionally improve performance, but modern
	computers running Impact Evaluations analysis are more likely to
	face the problem of too few variables allowed than running out of
	memory. The maximum number allowed is 2047 in Stata IC and 32,767 in Stata MP
	or SE. This setting is ignored for users that use Stata IC or Stata Small.{p_end}

{phang}{cmdab:matsize(}{it:numlist}{cmd:)} manually sets the maximum number of
	variables allowed in estimation commands, for example {help reg:regress}.
	The default is to set the number to the highest allowed in your version of Stata.
	Reducing this number can occasionally improve performance, but modern
	computers running Impact Evaluations analysis are more likely
	to run into problems allowing too few variables than running out of memory.
	Although, this is more likely the case with {cmdab:maxvar} than
	with {cmdab:matsize}. The maximum number allowed is 800 in Stata IC and 11,000 in Stata
	MP or SE.{p_end}

{phang}{cmdab:noclear} prevents the command from clearing/deleting the data set
	in working memory. No data may be in working memory in order to modify
	settings for maxvar, min_memory, max_memory and segmentsize. That is why the default
	is to clear the data set stored in working memory. Working memory is your RAM
	memory so no data saved to your hard drive will ever be deleted by this command.
	This command is intended to be placed at the very top of a dofile, so the
	data needed could be loaded into memory after running {cmd:ieboilstart}. For the
	reasons above, {cmdab:noclear} and {cmdab:maxvar()} cannot be combined.{p_end}

{phang}{cmdab:q:uietly} suppresses two of three outputs this commands generates in the result window. The first output is a disclaimer warning the user that there is no guarantee that commands will always behave identically. The second output is a list of all the settings applied and their values..{p_end}

{phang}{cmd:veryquietly} suppresses the third output this commands generates in the result window in addition to the two that {cmd:quietly} is suppressing. The third output is a reminder to set the version number using "`r(version)'" after running the command.

{phang}{cmdab:c:ustom(}{it:string}{cmd:)} allows the user to add one or multiple custom lines of code. Each line of code should be seperated with a "@". See example 2
	below for more details.{p_end}

{phang}{cmdab:c:ustom(}{it:string}{cmd:)}This option is only relevant for users of Stata 11. This value must be an integer followed by the letter B, K, M or G. The default if omitted is 50M. Cannot be used if
	versionnumber() is set to version 12.0 or more recent. See {help set memory} for more details. This link will only display options relevant to Stata 11 when clicking it in Stata 11. Otherwise it will show the options relevant to Stata 12 and later.

{title:Examples}

{pstd}{hi:Example 1.}

{pmore}{inp:ieboilstart, versionnumber(11.1)}
{break}`r(version)'

{pmore}After running the two lines of code above all users will run their version
 of Stata as if the version was  11.1. That means that anyone who bought or
 upgraded Stata after June 2010 can use the command and all commands will behave
  identically for all those users. All other settings have been set to common
	best practice values.

{pstd}{hi:Example 2.}

{pmore}{inp:ieboilstart, versionnumber(12.1) custom(ssc install estout @ ssc install winsor)}
{break}`r(version)'

{pmore}In the example above, the version is set to 12.1. When running this command, it also makes sure that the user has the two commands {inp:estout} and {inp:winsor} installed.

{title:Acknowledgements}

{phang}I would like to acknowledge the help in testing and proofreading and suggestions I
	received in relation to this command and help file from (in alphabetic order):{p_end}
{pmore}Michell Dong{break}John Dundas{break}Paula Gonzales{break}Seungmin Lee{break}Srujith Lingala{break}William Lisowski{break}Daniel Klein

{marker auth}{...}
{title:Author}

{phang}Kristoffer Bjarkefur, The World Bank, DECIE

{phang}Please send bug-reports, suggestions and requests for clarifications
		 writing "ietools ieboilstart" in the subject line to:{break}
		 kbjarkefur@worldbank.org

{phang}You can also see the code, make comments to the code, see the version
		 history of the code, and submit additions or edits to the code through
		 the github repository of ietoolkit:{break}
		 {browse "https://github.com/worldbank/ietoolkit"}

{smcl}
{* 28 Jul 2017}{...}
{hline}
help for {hi:ieboilstart}
{hline}

{title:Title}

{phang}{cmdab:ieboilstart} {hline 2} Harmonizes settings across team members in the same project to the longest extent technically possible.

{phang}{hi:DISCLAIMER} {hline 1} Due to technical reasons, it is
impossible to guarantee that different types of Stata (version number, Small/IC/SE/MP
or PC/Mac/Linux) work exactly the same in every possible context. This command does not
guarantee against any version discrepancies, it is solely a collection of common practices
to reduce the risk of the same code running differently on different computers. See more
details {help ieboilstart##comp:below}.

{marker synt}{...}
{title:Syntax}

{phang}Note that due to technical requirements in Stata, to include the most
	important setting in this command you must include the second line below.{p_end}

{pmore}
{cmdab:ieboilstart} , {cmdab:v:ersionnumber(}{it:version_number}{cmd:)}  [{it:optional_options}]{break}
`r(version)'

{phang}The second line "`r(version)'" uses the command {help version} to set the same Stata version accross all
	users. "`r(version)'" is identical to setting the version to the version number set in {cmdab:v:ersionnumber()} but
	both helps standardize this setting across different parts in the project and function as a reminder to
	set the version number. {p_end}

{marker opts}{...}
{synoptset 20}{...}
{synopthdr:options}
{synoptline}
{synopt :{cmdab:v:ersionnumber(}{it:string}{cmd:)}}sets a stable version of Stata
	for all users. This option does {ul:nothing} unless "`r(version)'" is included as in the example above.{p_end}
{synopt :{cmdab:maxvar(}{it:numlist}{cmd:)}}manually sets the maximum number of
	variables allowed in a data set. The default if omitted is 32,767.{p_end}
{synopt :{cmdab:matsize(}{it:numlist}{cmd:)}}manually sets the maximum number of
	variables allowed in an estimation command, for example {help regress:regress}.
	The default if omitted is 400.{p_end}
{synopt :{cmdab:noclear}}prevents the command to clear all data which some settings
	require. Best practice is to use this command before opening any data.{p_end}
{synopt :{cmdab:q:uietly}}suppresses the output with the disclaimer and the list
	of settings.{p_end}
{synopt :{cmdab:veryquietly}}does what {cmdab:quietly} does, but also suppresses the
	reminder to include "`r(version)'".{p_end}
{synopt :{cmdab:setmem(}{it:string}{cmd:)}}manually sets the memory for	Stata 11 users.{p_end}
{synopt :{cmdab:c:ustom(}{it:string}{cmd:)}}allows the user to enter custom lines
	of code to be added.{p_end}
{synoptline}

{marker desc}{...}
{title:Description}

{pstd}{cmdab:ieboilstart} standardizes best practice settings across all users using for a project.
	Such standardized code is usually referred to as boilerplate code, and that is
	where {cmdab:ieboilstart} lends it's name from. Standardizing the boilerplate code
	in a project reduces the risk that code behaves differently across users regardless of
	what version and type of Stata they are running.

{pstd}A command like this is impossible to make comprehensive in terms of versions control. Therefore,
	the ambition of this command is only to provide a convenient way to include boilerplate code based
	on commonly used best practices, which is much better than having no boilerplate code at all. The default
	values used are the values that are standard in boilerplate code for dofiles written or Impact
	Evaluations at DIME, World Bank. Suggestions for additions or improvements are very welcomed. See
	the {help ieboilstart##auth:author} section	for contact details.

{marker comp}{...}
{title:Compatibility Across Different Stata:}

{pstd}{cmdab:ieboilstart} sets settings that increases compatibility between Stata 11.0-15.0, Stata Small/IC/SE/MP and Stata for	PC/Mac/Linux. {it:Increase compatibility} does not mean an absolute guarantee that all code will always
	work the same in different types of Stata. That is technically impossible. {it:Increase compatibility} here means reducing the risk of code working differently in different types of Stata.

{pstd}{cmdab:ieboilstart} does sometimes apply different settings for different users as all settings does not work for all versions and types of Stata. For example, new memory settings were introduced in Stata 12 and {inp:set maxvar} is not allowed in Stata IC. {cmdab:ieboilstart} is implemented to set the settings in each version and type of Stata that reduces the risk of errors when different users run the same code, but the only way to eliminate the risk completely, is to use exactly the same version of Stata.

{pstd}In addition to version control, {cmdab:ieboilstart} allows a project to 	standardize user preference settings such as {help set varabbrev:varabbrev} that 		can cause code to behave differently across users.

{title:Important Details on Version Setting:}

{pstd}Impact Evaluations and other research projects often span over many
	years, which means that the same code is likely to run in different versions
	of Stata. Stata provides an method to reduce the risk of discrepancies due to this. See {help version:version} settings for more details. This method is included in {cmdab:ieboilstart}, however, {cmd:version} is mainly intended for making code written in Stata 11 to work
	in Stata 14 and not necessarily the other way around. Setting the version is still best practice and perhaps the most important setting in {cmdab:ieboilstart}. Read the {help ieboilstart##synt:syntax section} on the extra step required for {cmdab:ieboilstart} to set the version.{p_end}

{pstd}{hi:Warning:} Any dofiles containing randomization {ul:{hi:MUST}} set the version number
	as Stata occasionally makes updates to its randomization algorithm between versions. A dofile including random assignment
	or random sampling is therefore not necessarily stable across different versions of Stata,
	unless the dofile has a version number explicitly set in the beginning of the file.{p_end}

	{pstd}The version setting has the scope of a local, meaning that it expires when a dofile and all sub-dofiles it is calling are completed. Therefore, set the version in your master dofile {ul:and} in every single dofile using randomization. This will make your randomization stable even if another user would only run the specific dofile with the randomization.{p_end}

{title:Details on Memory Settings:}

{pstd}In Stata versions before Stata 12, memory was assigned statically from the
	computer memory, meaning that there was a fixed amount of memory assigned to Stata
	regardless if required it or not. Stata would crash if it went over that fixed limit
	when for example increasing the data set or running a complex calculation. In Stata
	12 and more recent versions, this is done dynamically, meaning that Stata is assigned
	a little bit of memory when it is starts and assigned additional memory dynamically
	as needed. The only memory limit is the hardware limits on the computer it is running
	on.

{pstd}The fixed memory in Stata 11 was assigned by the command {cmdab:set memory}. This
	command is simply ignored in Stata 12 or later. Instead the dynamic memory setting
	can be fine tuned with {cmdab:min_memory}, {cmdab:max_memory}, {cmdab:niceness} and
	{cmdab:segmentsize}, although even highly advanced users rarely have to worry about these settings as long as they are set to the recommended default values
	(which this command ensures that they are).

{p2colset 5 22 24 2}
{p2col : Memory Settings}Short explanation{p_end}
{p2line}
{pstd}{it: Basic Settings:}{p_end}
{p2col :{cmdab:set maxvar}}sets the maximum number of variables allowed. The
	default value is 32,767 the maximum allowed in Stata MP or SE. A lower maximum number can manually be set by the option {cmdab:maxvar()}. This setting is skipped using an if-statement if the dofile is executed in Stata Small or IC. See {help set maxvar:set maxvar}.{p_end}
{p2col :{cmdab:set matsize}}sets the maximum number of variables that can be included in estimation commands such as {cmd:regress}. The {cmdab:ieboilstart} default value is 400 which is the default value for Stata. The maximum number can manually be set by the option {cmdab:matsize()} as long as the number does not violate the limitations in your version of Stata. See {help set matsize:set matsize}.{p_end}
{break}
{pstd}{it: Dynamic Memory Settings (see {help memory:memory} for details and reasons for default values. Few users ever need to change these values):}{p_end}
{p2col :{cmdab:set min_memory}}sets a lower bound for the amount of memory assigned to Stata. The default value is no lower bound.{p_end}
{p2col :{cmdab:set max_memory}}sets an upper bound for the amount of memory assigned to Stata. The default is as much as the hardware of the computer allows.{p_end}
{p2col :{cmdab:set niceness}}defines how quickly Stata releases unused memory back to the computer{p_end}
{p2col :{cmdab:set segmentsize}}defines how large bundles of data is assigned each time
			Stata request more memory. Too large bundles make Stata occupy an
			unnecessary large part of the computer's memory (that otherwise could
			have been used by other applications), and too small bundles make
			Stata frequently consume processing power requesting new bundles.{p_end}
{break}
{pstd}{it: Static Memory Settings (only applicable in Stata 11)}{p_end}
{p2col :{cmdab:set memory}}sets the amount of static memory assigned to Stata. {p_end}
{p2line}

{pstd}{hi:{ul:Other Settings:}}{break}The other settings are included as they are either very
	commonly preferred or reduces the risk of errors for users that do not yet fully understand
	the implication of setting these settings to other values than what is recommended. These
	settings can be reverted to personal preferences after running {cmdab:ieboilstart} or by using the {cmd:custom()} option.{p_end}
{p2colset 5 24 26 2}
{p2col : Other Settings}Short explanation{p_end}
{p2line}
{p2col :{cmdab:set more off}}disables the default setting that Stata stops and
	waits for the user to press any key each time the output window is full. Long
	dofiles would take a very long time to run and require constant attention from
	the user without this setting. Most Stata users always disable the default
	which is {cmdab:set more on}. See {help set more:set more}.{p_end}
{p2col :{cmdab:pause on}}allows the usage of the command {cmdab:pause} which can
	be very useful during debugging. See {help pause:pause}.{p_end}
{p2col :{cmdab:set varabbrev off}}allows users to abbreviate variable names
		similarly to command names such as gen for generate and reg for regress.
		However, while command abbreviation has strict rules constant across data sets, users, and
		Stata versions; variable name abbreviation does not have the same strict rules
		and consistency. While enabling variable abbreviation can speed up coding,
		it is an error-prone technique unless all users using a dofile with
		variable abbreviations organize their coding practices exactly the same
		way. See {help set varabbrev:set varabbrev} for more details and carfully
		consider this caution before enabling variable abbreviations in a
		collaborative dofile.{p_end}
{p2line}

{title:Options}

{phang}{cmdab:v:ersionnumber(}{it:string}{cmd:)} sets a stable version of Stata
	for all users. Stata does not (for good reasons) allow a user written command
	to alter the version setting from inside a command. Therefore, this option does
	{ul:nothing} unless "`r(version)'" is included as described in the
	{help ieboilstart##synt:syntax section}. While the version number cannot be set
	inside the command code, {cmd:ieboilstart} does two things. First it reminds
	the user to set the version since it is a required command. Second, it makes
	sure that the version number used is not too old. A too old version might
	risk that there are far too big a difference in many commands. Best
	practice is therefore to keep the same version number throughout a project,
	unless there is something specific to a newer version that is required for any
	dofile. Only major and recent versions are allowed in order to reduce errors and
	complexity. The valid versions are 11.0, 11.1, 11.2, 12.0, 12.1, 13.0, 13.1,
	14.0, 14.1, 14.2, 15.0 and all versions without decimals. However, it is recommended
	to use a .1 over a .0 version. .1 is free of charge if you already have the
	corresponding .0 and .1 includes bug fixes to the functions introduced in .0.
	All versions of Stata can be set to run any older version of Stata but not a newer. {p_end}

{phang}{cmdab:maxvar(}{it:numlist}{cmd:)} manually sets the maximum number of
	variables allowed in a data set. The default is to set the number to the highest
	allowed. Reducing this number can occasionally improve performance, but modern
	computers running Impact Evaluations analysis are more likely to
	face the problem of too few variables allowed than running out of
	memory. The maximum number allowed is 2047 in Stata IC and 32,767 in Stata MP
	or SE. This setting is ignored for users that use Stata IC or Stata Small.{p_end}

{phang}{cmdab:matsize(}{it:numlist}{cmd:)} manually sets the maximum number of
	variables allowed in estimation commands, for example {help reg:regress}.
	The default is to set the number to the highest allowed in your version of Stata.
	Reducing this number can occasionally improve performance, but modern
	computers running Impact Evaluations analysis are more likely
	to run into problems allowing too few variables than running out of memory.
	Although, this is more likely the case with {cmdab:maxvar} than
	with {cmdab:matsize}. The maximum number allowed is 800 in Stata IC and 11,000 in Stata
	MP or SE.{p_end}

{phang}{cmdab:noclear} prevents the command from clearing/deleting the data set
	in working memory. No data may be in working memory in order to modify
	settings for maxvar, min_memory, max_memory and segmentsize. That is why the default
	is to clear the data set stored in working memory. Working memory is your RAM
	memory so no data saved to your hard drive will ever be deleted by this command.
	This command is intended to be placed at the very top of a dofile, so the
	data needed could be loaded into memory after running {cmd:ieboilstart}. For the
	reasons above, {cmdab:noclear} and {cmdab:maxvar()} cannot be combined.{p_end}

{phang}{cmdab:q:uietly} suppresses two of three outputs this commands generates in the result window. The first output is a disclaimer warning the user that there is no guarantee that commands will always behave identically. The second output is a list of all the settings applied and their values..{p_end}

{phang}{cmd:veryquietly} suppresses the third output this commands generates in the result window in addition to the two that {cmd:quietly} is suppressing. The third output is a reminder to set the version number using "`r(version)'" after running the command.

{phang}{cmdab:c:ustom(}{it:string}{cmd:)} allows the user to add one or multiple custom lines of code. Each line of code should be seperated with a "@". See example 4
	below for more details.{p_end}

{phang}{cmdab:c:ustom(}{it:string}{cmd:)}This option is only relevant for users of Stata 11. This value must be an integer followed by the letter B, K, M or G. The default if omitted is 50M. Cannot be used if
	versionnumber() is set to version 12.0 or more recent. See {help set memory} for more details. This link will only display options relevant to Stata 11 when clicking it in Stata 11. Otherwise it will show the options relevant to Stata 12 and later.

{title:Examples}

{pstd}{hi:Example 1.}

{pmore}{inp:ieboilstart, versionnumber(11.1)}
{break}`r(version)'

{pmore}After running the two lines of code above all users will run their version
 of Stata as if the version was  11.1. That means that anyone who bought or
 upgraded Stata after June 2010 can use the command and all commands will behave
  identically for all those users. All other settings have been set to common
	best practice values.

{pstd}{hi:Example 2.}

{pmore}{inp:ieboilstart, versionnumber(12.1) custom(ssc install estout @ ssc install winsor)}
{break}`r(version)'

{pmore}In the example above, the version is set to 12.1. When running this command, it also makes sure that the user has the two commands {inp:estout} and {inp:winsor} installed.

{title:Acknowledgements}

{phang}I would like to acknowledge the help in testing and proofreading and suggestions I
	received in relation to this command and help file from (in alphabetic order):{p_end}
{pmore}Michell Dong{break}John Dundas{break}Paula Gonzales{break}Seungmin Lee{break}Srujith Lingala{break}William Lisowski{break}Daniel Klein

{marker auth}{...}
{title:Author}

{phang}Kristoffer Bjarkefur, The World Bank, DECIE

{phang}Please send bug-reports, suggestions and requests for clarifications
		 writing "ietools ieboilstart" in the subject line to:{break}
		 kbjarkefur@worldbank.org

{phang}You can also see the code, make comments to the code, see the version
		 history of the code, and submit additions or edits to the code through
		 the github repository of ietoolkit:{break}
		 {browse "https://github.com/worldbank/ietoolkit"}


added sandbox to ghc command

added sandbox to ghc command

# Dependencies:
source=`ls *.hs`
redo-ifchange $source

PROFILE="-prof -fprof-auto -rtsopts"
PROFILE=
ROOT=`pwd`/..
SANDBOX=$ROOT/.cabal-sandbox/x86_64-osx-ghc-7.8.3-packages.conf.d
PACKAGE="-package-db=$SANDBOX"

# Compile redo.hs to filename $3 with verbosity set to low
# so there is nothing printed to standard out
ghc -O2 -v1 -Wall $PACKAGE $PROFILE -o $3 redo.hs 1>&2

# Dependencies:
source=`ls *.hs`
redo-ifchange $source

#PROFILE="-prof -fprof-auto -rtsopts"
PROFILE=

# Compile redo.hs to filename $3 with verbosity set to low
# so there is nothing printed to standard out
ghc -O2 -v0 -Wall $PROFILE -o $3 redo.hs 1>&2