version 11.2

cap program drop _eventols
program define _eventols, rclass
	#d;
	syntax varlist(fv ts numeric) [aw fw pw] [if] [in], /* Proxy for eta and covariates go in varlist. Can add fv ts later */
	Panelvar(varname) /* Panel variable */
	Timevar(varname) /* Time variable */
	POLicyvar(varname) /* Policy variable */
	LWindow(integer) /* Estimation window. Need to set a default, but it has to be based on the dataset */
	RWindow(integer) /* Estimation window. Need to set a default, but it has to be based on the dataset */
	[
	nofe /* No fixed effects */
	note /* No time effects */
	TRend(string) /* trend(a -1) Include a linear trend from time a to -1. Method can be either GMM or OLS*/
	SAVek(string) /* Generate the time-to-event dummies, trend and keep them in the dataset */
	nogen /* Do not generate k variables */
	kvars(string) /* Stub for event dummies to include, if they have been generated already */
	nodrop /* Do not drop _k variables */
	norm(integer -1) /* Coefficiente to normalize */
	reghdfe /* Use reghdfe for estimation */
	impute(string) /*imputation on policyvar*/
	addabsorb(string) /* Absorb additional variables in reghdfe */
	DIFFavg /* Obtain regular DiD estimate implied by the model */
	cohort(varname) /* categorical variable indicating cohort */
	control_cohort(varname) /* dummy variable indicating the control cohort */
  REPeatedcs /*indicate that the input data is a repeated cross-sectional dataset*/

	*
	]
	;
	#d cr

	marksample touse


	tempname delta Vdelta bb VV
	* delta - event coefficients
	* bb - regression coefficients
	tempvar esample	tousegen

	* For eventgenvars, ignore missings in varlist
	mark `tousegen' `if' `in'


	**** parsers
	*parse savek
	if "`savek'"!="" parsesavek `savek'
	foreach ll in savek noestimate saveint{
		loc `ll' = r(`ll'l)
		if "``ll''"=="." loc `ll' ""
		return loc `ll' = "``ll''"
	}

	*error messages for incorrect specification of noestimate
	if "`noestimate'"!="" & "`diffavg'"!="" {
		di as err _n "{bf:noestimate} and {bf: diffavg} not allowed simultaneously"
		exit 301
	}
	if "`noestimate'"!="" & "`trend'"!="" {
		di as err _n "{bf:noestimate} and {bf:trend} not allowed simultaneously"
		exit 301
	}


	*parse trend
	if "`trend'"!="" parsetrend `trend'
	loc trcoef = r(trcoef)
	loc methodt = r(methodt)
	loc saveov = r(saveoverlay)
	if "`saveov'"=="." loc saveov ""
	return loc saveov = "`saveov'"

	*error messages for incorrect specification of the trend option
	if "`trend'"!="" {
		tempvar ktrend trendy trendx
		if `trcoef'<`lwindow'-1 | `trcoef'>`rwindow'+1 {
			di as err "{bf:trend} is outside estimation window."
			exit 301
		}

		if `trcoef'>=0 {
			di as err "trend coefficient must be smaller than 0"
			exit 301
		}
		if `trcoef'==-1 {
			di as err "Trend extrapolation requires at least two pre-treatment points."
			exit 301
		}
		if !inlist("`methodt'","ols","gmm"){
			di as err "{bf:method(`methodt')} is not a valid suboption."
			exit 301
		}
		if "`methodt'"=="ols" {
			loc ttrend "_ttrend"
		}
		else loc ttrend ""
	}

	* error messages for sun_abraham
	loc sun_abraham ""
	if "`cohort'"!="" & "`control_cohort'"!="" {
		di as text _n "You have specified {bf:cohort} and {bf:control_cohort} options. Event-time coefficients will be estimated with the Interaction Weighted Estimator of Sun and Abraham (2021)."
		loc sun_abraham "sun_abraham"
	}
	if "`saveint'"!="" & "`sun_abraham'"==""{
		di as err _n "Suboption {bf:saveint} can only be specified if options {bf:cohort} and {bf:control_cohort} have been specified as well."
		exit 301
	}
	* Check for vars named _interact
	if "`saveint'"!=""{
		cap unab old_interact_vars : `savek'_interact*
		if !_rc {
			di as err _n "You have variable names with the {bf:`savek'_interact} prefix. {bf:`savek'_interact} is reserved for the interaction variables in Sun-and-Abraham estimation."
			di as err _n "Please rename or drop these variables before proceeding."
			exit 110
		}
	}
	*gen & kvars
	if ("`gen'"!="" & "`kvars'"=="") |  ("`gen'"=="" & "`kvars'"!="") {
		di as err _n "Options -nogen- and -kvars- must be specified together"
		exit 301
	}

	loc i = "`panelvar'"
	loc t = "`timevar'"
	loc z = "`policyvar'"

	if "`gen'" != "nogen" {
		if "`impute'"!=""{
			tempvar rr
			qui gen double `rr'=.
		}

		_eventgenvars if `tousegen', panelvar(`panelvar') timevar(`timevar') policyvar(`policyvar') lwindow(`lwindow') rwindow(`rwindow') trcoef(`trcoef') methodt(`methodt') norm(`norm') impute(`impute') rr(`rr') `repeatedcs'
		loc included=r(included)
		loc names=r(names)
		loc komittrend=r(komittrend)
		loc bin = r(bin)
		if "`komittrend'"=="." loc komittrend = ""

		*bring the imputed policyvar
		loc impute=r(impute)
		if "`impute'"=="." loc impute = ""
		*if imputation succeeded:
		if "`impute'"!="" {
			tempvar zimp
			qui gen double `zimp'=`rr'
			loc z="`zimp'"
		}
		else loc z = "`policyvar'"

	}
	else {
		loc kvstub "`kvars'"
		loc j=1
		loc names ""
		loc included ""
		foreach var of varlist `kvstub'* {
			if `norm' < 0 loc kvomit = "m`=abs(`norm')'"
			else loc kvomit "p`=abs(`norm')'"
			if "`var'"=="`kvstub'_evtime" | "`var'" == "`kvstub'_eq_`kvomit'" continue
			if "`kvstub'"!="_k" {
				loc sub : subinstr local var "`kvstub'" "_k", all
				qui clonevar `sub' = `var'
			}
			else {
				loc sub = "`var'"
			}
			if `j'==1 loc names `""`sub'""'
			else loc names `"`names'.."`sub'""'
			* "
			loc included "`included' `sub'"
			loc ++ j
		}
	}
	loc komit "`norm'`komittrend'"
	loc komit = strtrim("`komit'")

	*split varlist (depvar and independentvars): change variables' order in the regression. Necessary for GMM matrix operations
	loc nvars: word count(`varlist')
	tokenize `varlist'
	loc depenvar `1'
	if `nvars'>1 {
		forval k=2(1)`nvars'{
			loc indepvars "`indepvars' ``k''"
		}
	}
	else loc indepvars ""

	******** SA *******
	if "`sun_abraham'"!=""{
		* Parse the dependent variable
		local lhs = "`depenvar'"
		local rel_time_list = "`included'"

		* Convert the varlist of relative time indicators to nvarlist
		local nvarlist "" // copies of relative time indicators with control cohort set to zero
		local dvarlist "" // for display
		foreach l of varlist `rel_time_list' {
			local dvarlist "`dvarlist' `l'"
			tempname n`l'
			qui gen `n`l'' = `l'
			qui replace `n`l'' = 0 if  `control_cohort' == 1
			local nvarlist "`nvarlist' `n`l''"
		}

		* Get cohort count  and count of relative time
		qui levelsof `cohort' if  `control_cohort' == 0, local(cohort_list)
		local nrel_times: word count `nvarlist'
		local ncohort: word count `cohort_list'

		**** step 2
		* Initiate empty matrix for weights
		tempname bb ff_w

		* Loop over cohort and get cohort shares for relative times
		local nresidlist ""
		foreach yy of local cohort_list {
			tempvar cohort_ind resid`yy'
			qui gen `cohort_ind'  = (`cohort' == `yy')
			qui _regress `cohort_ind' `nvarlist'  if `touse' & `control_cohort' == 0 [`weight'`exp']  , nocons
			mat `bb' = e(b)
			matrix `ff_w'  = nullmat(`ff_w') \ `bb'
			*di "`yy'"
			*mat li `ff_w'
			qui predict double `resid`yy'', resid
			local nresidlist "`nresidlist' `resid`yy''" //list of variables of residuals
		}

		* Get VCV estimate for the cohort shares using avar
		* In case users have not set relative time indicators to zero for control cohort
		* Manually restrict the sample to non-control cohort
		tempname XX Sxx Sxxi S KSxxi Sigma_ff
		qui mat accum `XX' = `nvarlist' if  `touse' & `control_cohort' == 0 [`weight'`exp'], nocons
		mat `Sxx' = `XX'*1/r(N)
		mat `Sxxi' = syminv(`Sxx')
		qui avar (`nresidlist') (`nvarlist')  if `touse' & `control_cohort' == 0 [`weight'`exp'], nocons robust
		mat `S' = r(S)
		mat `KSxxi' = I(`ncohort')#`Sxxi'
		mat `Sigma_ff' = `KSxxi'*`S'*`KSxxi'*1/r(N)
		// Note that the normalization is slightly different from the paper
		// The scaling factor is 1/N for N the obs of cross-sectional units
		// But here estimates are on the panel, which is why it is 1/NT instead
		// Should cancel out for balanced panel, but unbalanced panel is a TODO
		// as of Jan 23, 2023, Sun and Abraham have not updated this code section.
		//According to the expression for the asymptotic variance in the proof of proposition 6 (https://arxiv.org/pdf/1804.05785v2.pdf#page=50), the scaling factor is 1/N.

		**** step 1
		* Prepare interaction terms for the interacted regression
		local cohort_rel_varlist "" // hold the temp varnames
		foreach l of varlist `rel_time_list' {
			foreach yy of local cohort_list {
				tempvar n`n`l''_`yy'
				qui gen `n`n`l''_`yy''  = (`cohort' == `yy') * `n`l' '
				// TODO: might be more efficient to use the c. operator if format w/o missing
				local cohort_rel_varlist "`cohort_rel_varlist' `n`n`l''_`yy''"
				if "`saveint'"!=""{
					loc lnumber=substr("`l'",7,2)
					qui gen _interact_`lnumber'_c`yy' = `n`n`l''_`yy''
				}
			}
		}
		local bcohort_rel_varlist "" // hold the interaction varnames
		foreach l of varlist `rel_time_list'  {
			foreach yy of local cohort_list {
					local bcohort_rel_varlist "`bcohort_rel_varlist' `l'_x_`yy'"
			}
		}
		* Estimate the interacted regression as an xtevent regression:
	}


	***** Main regression
	tempname reg_base

	if "`noestimate'"==""{

		if "`te'" == "note" loc te ""
		else loc te "i.`t'"

		* If gmm trend run regression before adjustment quietly
		if ("`methodt'"=="gmm" | "`sun_abraham'"!="") loc q "quietly"
		else loc q ""

		if "`reghdfe'"=="" {
			if "`fe'" == "nofe" {
				loc abs ""
				loc cmd "regress"
			}
			else {
				loc abs "absorb(`i')"
				loc cmd "areg"
			}

			`q' `cmd' `depenvar' `included' `indepvars' `te' `ttrend' [`weight'`exp'] if `touse', `abs' `options'
			_estimates hold `reg_base', copy
			if "`sun_abraham'"!=""{
				qui `cmd' `depenvar' `cohort_rel_varlist' `indepvars' `te' `ttrend' [`weight'`exp'] if `touse', `abs' `options'
			}
		}
		else {
			loc cmd "reghdfe"
			loc noabsorb ""
			*absorb nothing
			if "`fe'" == "nofe" & "`te'"=="" & "`addabsorb'"=="" {
				loc noabsorb "noabsorb"
				loc abs ""
			}
			*absorb only one
			else if "`fe'" == "nofe" & "`te'"=="" & "`addabsorb'"!="" {
				loc abs "absorb(`addabsorb')"
			}
			else if "`fe'" == "nofe" & "`te'"!="" & "`addabsorb'"=="" {
				loc abs "absorb(`t')"
			}
			else if "`fe'" != "nofe" & "`te'"=="" & "`addabsorb'"=="" {
				loc abs "absorb(`i')"
			}
			*absorb two
			else if "`fe'" == "nofe" & "`te'"!="" & "`addabsorb'"!="" {
				loc abs "absorb(`t' `addabsorb')"
			}
			else if "`fe'" != "nofe" & "`te'"=="" & "`addabsorb'"!="" {
				loc abs "absorb(`i' `addabsorb')"
			}
			else if "`fe'" != "nofe" & "`te'"!="" & "`addabsorb'"=="" {
				loc abs "absorb(`i' `t')"
			}
			*absorb three
			else if "`fe'" != "nofe" & "`te'"!="" & "`addabsorb'"!="" {
				loc abs "absorb(`i' `t' `addabsorb')"
			}
			*
			else {
				loc abs "absorb(`i' `t' `addabsorb')"
			}
			`q' reghdfe `depenvar' `included' `indepvars' `ttrend' [`weight'`exp'] if `touse', `abs' `noabsorb' `options'
			_estimates hold `reg_base', copy
			if "`sun_abraham'"!=""{
				qui reghdfe `depenvar' `cohort_rel_varlist' `indepvars' `ttrend' [`weight'`exp'] if `touse', `abs' `noabsorb' `options'
			}
		}

	*** SA: combine cohort shares and output from the interacted regression
	if "`sun_abraham'"!=""{
		tempname evt_bb b evt_VV V
		local bcohort_rel_varlist "`bcohort_rel_varlist' `covariates'" // TODO: does not catch the constant term if reghdfe includes a constant.
		mat `b' = e(b)
		mata st_matrix("`V'",diagonal(st_matrix("e(V)"))')
		* Convert the delta estimate vector to a matrix where each column is a relative time
		local end = 0
		forval i = 1/`nrel_times' {
			local start = `end'+1
			local end = `start'+`ncohort'-1
			mat `b'`i' = `b'[.,`start'..`end']
			mat `evt_bb'  = nullmat(`evt_bb') \ `b'`i'
			mat `V'`i' = `V'[.,`start'..`end']
			mat `evt_VV'  = nullmat(`evt_VV') \ `V'`i'

		}
		mat `evt_bb' = `evt_bb''
		mat `evt_VV' = `evt_VV''

		* Take weighted average for IW estimators
		tempname w delta b_iw nc nr
		mata: `w' = st_matrix("`ff_w'")
		mata: `delta' = st_matrix("`evt_bb'")
		mata: `b_iw' = colsum(`w':* `delta')
		mata: st_matrix("`b_iw'", `b_iw')
		mata: `nc' = rows(`w')
		mata: `nr' = cols(`w')

		* Ptwise variance from cohort share estimation and interacted regression
		tempname VV  wlong V_iw V_iw_diag

		* VCV from the interacted regression
		mata: `VV' = st_matrix("e(V)")
		mata: `VV' = `VV'[1..`nr'*`nc',1..`nr'*`nc'] // in case reghdfe reports _cons
		mata: `wlong' = `w'':*J(1,`nc',e(1,`nr')') // create a "Toeplitz" matrix convolution
		forval i=2/`nrel_times' {
			mata: `wlong' = (`wlong', `w'':*J(1,`nc',e(`i',`nr')'))
		}
		mata: `V_iw' = `wlong'*`VV'*`wlong''
		* VCV from cohort share estimation
		tempname Vshare Vshare_evt share_idx Sigma_l
		mata: `Vshare' = st_matrix("`Sigma_ff'")
		mata: `Sigma_l' = J(0,0,.)
		mata: `share_idx' = range(0,(`nc'-1)*`nr',`nr')
		forval i=1/`nrel_times' {
			forval j=1/`i' {
				mata: `Vshare_evt' = `Vshare'[`share_idx':+`i', `share_idx':+`j']
				mata: `V_iw'[`i',`j'] = `V_iw'[`i',`j'] + (`delta'[,`i'])'*`Vshare_evt'*(`delta'[,`j'])
	// 			mata: `Sigma_l' = blockdiag(`Sigma_l',`Vshare_evt')
			}
		}
		mata: `V_iw' = makesymmetric(`V_iw')
	// 	mata: `V_iw' = `V_iw''
	// 	mata: st_matrix("`Sigma_l'", `Sigma_l')
		mata: st_matrix("`V_iw'", `V_iw')

		mata: `V_iw_diag' = diag(`V_iw')
		mata: st_matrix("`V_iw_diag'", `V_iw_diag')
		mata: mata drop `b_iw' `VV' `nc' `nr' `w' `wlong' `Vshare' `share_idx' `delta' `Vshare_evt' `Sigma_l' `V_iw' `V_iw_diag'

		matrix colnames `b_iw' =  `dvarlist'
		matrix colnames `V_iw' =  `dvarlist'
		matrix rownames `V_iw' =  `dvarlist'

		matrix rownames `ff_w' =  `cohort_list'
		matrix colnames `ff_w' =  `dvarlist'
		matrix rownames `Sigma_ff' =  `cohort_list'
		matrix colnames `Sigma_ff' =  `cohort_list'

		matrix colnames `evt_bb' =  `dvarlist'
		matrix rownames `evt_bb' =  `cohort_list'
		matrix colnames `evt_VV' =  `dvarlist'
		matrix rownames `evt_VV' =  `cohort_list'

		*insert SA's estimations into base regresion
		tempname b_sa_adj v_sa_adj est_sun_abraham
		_estimates unhold `reg_base'
		mat `b_sa_adj'=e(b)
		mat `v_sa_adj'=e(V)

		loc deltanames : colnames(`b_iw')
		foreach i in `deltanames' {
			mat `b_sa_adj'[1,colnumb("`b_sa_adj'","`i'")]=`b_iw'[1,"`i'"]
			foreach j in `deltanames' {
			mat `v_sa_adj'[rownumb("`v_sa_adj'","`j'"),colnumb("`v_sa_adj'","`i'")]= `V_iw'["`j'","`i'"]
			}
		}

		repostdelta `b_sa_adj' `v_sa_adj'
		* Display results
		if "`methodt'"=="gmm" loc qq "quietly"
		`qq' _coef_table_header
		`qq' _coef_table , bmatrix(e(b)) vmatrix(e(V))
		_estimates hold `est_sun_abraham', copy
}

		* Return coefficients and variance matrix of the delta k estimates separately
		mat `bb'=e(b)
		mat `VV'=e(V)
		mat `delta' = `bb'[1,`names']
		mat `Vdelta' = `VV'[`names',`names']
		loc df = e(df_r)

		gen byte `esample' = e(sample)
	}

	* DiD estimate

	if "`diffavg'"!=""{
		unab pre : _k_eq_m*
		unab post_p : _k_eq_p*
		loc norma = abs(`norm')
		if `norm' < 0{
			loc pre : subinstr local pre "_k_eq_m`norma'" "", all
			loc pre_plus : subinstr local pre " " " + ", all
			loc reverse = ustrreverse("`pre_plus'")
			loc reverse = subinstr("`reverse'", " + ", "", 1)
			loc pre_plus = ustrreverse("`reverse'")
		}
		if `norm' >= 0{
			loc post_p : subinstr local post_p "_k_eq_p`norma' " "", all
			loc pre_plus : subinstr local pre " " " + ", all
		}
		loc post_plus : subinstr local post_p " " " + ", all
		loc lwindow = abs(`lwindow')
		loc rwindow = `rwindow'
		di as text _n "Difference in pre and post-period averages from lincom:"
		lincom ((`post_plus') / (`rwindow' + 2)) - ((`pre_plus') / (`lwindow' + 1)), cformat(%9.4g)
	}

	* Trend adjustment by GMM

	if "`methodt'"=="gmm" {

		tempname deltatoadj Vtoadj deltaadj Vadj bbadj VVadj

		loc gmmtrendsc = `trcoef'
		loc start = "_k_eq_m`=abs(`trcoef')'"
		* Notice that here I am requiring normalization in -1
		mat `deltatoadj' = `delta'[1,"`start'".."_k_eq_m2"]
		mat `deltatoadj' = [`deltatoadj',0]
		mat `deltatoadj' = `deltatoadj''
		mat `Vtoadj' = `Vdelta'["`start'".."_k_eq_m2","`start'".."_k_eq_m2"]
		mat `Vtoadj' = [`Vtoadj',J(`=abs(`trcoef')-1',1,0)]
		mat `Vtoadj' = (`Vtoadj'\J(1,`=abs(`trcoef')',0))

		* Get vector of other coefficients, and their variance
		tempname Omegapsi_st Omegadeltapsi_st Valladj gmm_trcoefs
		loc deltanames : colnames(`delta')
		loc deltanames1: word 1 of `deltanames'
		loc deltanamesw: word count `deltanames'
		loc deltanamesl: word `deltanamesw' of `deltanames'
		loc Vnames : colnames(`VV')
		loc psinames: list Vnames - deltanames
		loc psinames1 : word 1 of `psinames'
		mat psi = `bb'[1,"`psinames1'"...]
		mat `Omegapsi_st' = `VV'["`psinames1'"...,"`psinames1'"...]
		mat `Omegadeltapsi_st' = `VV'["`deltanames1'".."`deltanamesl'","`psinames1'"...]

		mata: adjdelta(`gmmtrendsc',`lwindow',`rwindow',"`deltatoadj'","`Vdelta'","`Vtoadj'","`delta'","`Omegapsi_st'","`Omegadeltapsi_st'","`gmm_trcoefs'","`deltaadj'","`Vadj'","`Valladj'")

		* Post the new results
		loc dnames : colnames(`delta')
		*change column an row names
		mat colnames `deltaadj' = `dnames'
		mat colnames `gmm_trcoefs' = `dnames'
		mat colnames `Vadj' = `dnames'
		mat rownames `Vadj' = `dnames'
		mat `bbadj' = `bb'
		mat `VVadj' = `VV'
		*insert adjusted values
		foreach i in `dnames' {
			mat `bbadj'[1,colnumb("`bb'","`i'")]= `deltaadj'[1,"`i'"]
			foreach j in `dnames' {
				mat `VVadj'[rownumb("`VVadj'","`j'"),colnumb("`VVadj'","`i'")]= `Vadj'["`j'","`i'"]
			}
		}

		* Post the new results (V matrix for all coeffs)
		tempname VValladj
		loc allnames : colnames(`bb')
		mat colnames `Valladj' = `allnames'
		mat rownames `Valladj' = `allnames'
		mat `VValladj' = `VV'
		foreach i in `allnames' {
			foreach j in `allnames' {
				mat `VValladj'[rownumb("`VValladj'","`j'"),colnumb("`VValladj'","`i'")]= `Valladj'["`j'","`i'"]
			}
		}

		*reset delta & Vdelta so xteventplot will plot the right coefficients
		mat `delta' = `bbadj'[1,`names']
		mat `Vdelta' = `VVadj'[`names',`names']

		*reset b and V so the returned matrices are the adjusted ones
		mat `bb'=`bbadj'
		mat `VV'=`VValladj'

		*repostdelta `bbadj' `VVadj'
		repostdelta `bbadj' `VValladj'

		`cmd'

	}

	* Variables for overlay plot if trend

	if "`saveov'"!="" {
		_estimates hold mainols
		unab included2 : _k*
		loc toexc "_k_eq_m1"
		loc included2: list local included2 - toexc
		*estimate the contrafactual: no adjusting by trend. only exclude event-time dummy -1
		*trend excludes from trend (e.g. -3) to -1
		if "`sun_abraham'"!="" _estimates unhold `est_sun_abraham' //call the SA estimations that have not been corrected by trend
		else {
			if "`reghdfe'"== "" {
				qui _regress `varlist' `included2' `te' [`weight'`exp'] if `touse', `abs' `options'
			}
			else {
				qui reghdfe `varlist' `included2' [`weight'`exp'] if `touse', `abs' `noabsorb' `options'
			}
		}
		loc j=1
		loc names2 ""
		foreach var in `included2' {
			if `j'==1 loc names2 `""`var'""'
			else loc names2 `"`names2'.."`var'""'
			* "
			loc ++ j
		}
		* Generate the trend to plot
		qui gen double `trendy'=.
		qui gen int `trendx'=.
		loc j=1
		forv c=`trcoef'(1)-1 {
			loc absc = abs(`c')
			if "`methodt'"=="ols"{
				if `c'!=-1 qui replace `trendy'=_b[_k_eq_m`absc'] in `j'
				else if `c'==-1 qui replace `trendy'=0 in `j'
			}
			else if "`methodt'"=="gmm"{
				if `c'!=-1 qui replace `trendy'=`gmm_trcoefs'[1,"_k_eq_m`absc'"] in `j'
				else if `c'==-1 qui replace `trendy'=0 in `j'
			}
			qui replace `trendx'=`c' in `j'
			loc ++ j
		}
		tempname bbov VVov deltaov Vdeltaov mattrendy mattrendx
		mat `bbov'=e(b)
		mat `VVov'=e(V)
		mat `deltaov' = `bbov'[1,`names2']
		mat `Vdeltaov' = `VVov'[`names2',`names2']
		mkmat `trendy', matrix(`mattrendy') nomiss
		mkmat `trendx', matrix(`mattrendx') nomiss
		_estimates unhold mainols
	}

	*save a temporary copy of the event-time dummy corresponding to the normalized period before dropping that dummy variable
	tempvar temp_k
	loc absnorm=abs(`norm')
	qui gen `temp_k'=_k_eq_m`absnorm'

	* Drop variables
	if "`savek'" == "" & "`drop'"!="nodrop" {
		cap confirm var _k_eq_p0
		if !_rc drop _k_eq*
		cap confirm var __k
		if !_rc qui drop __k
		if "`methodt'"=="ols" qui drop _ttrend
		if "`saveint'"!="" qui drop _interact*
	}
	else if "`savek'" != "" & "`drop'"!="nodrop"  {
		ren __k `savek'_evtime
		ren _k_eq* `savek'_eq*

		if "`methodt'"=="ols" ren _ttrend `savek'_trend
		if "`saveint'"!="" ren _interact* `savek'_interact*
	}

	*skip the rest of the program if the user indicated not to estimate
	return local noestimate "`noestimate'"
	if "`noestimate'"!="" exit

	* Calculate mean before change in policy for 2nd axis in plot
	* This needs to be relative to normalization

	tokenize `varlist'
	loc depvar "`1'"
	qui su `1' if `temp_k'!=0 & `temp_k'!=. & `esample', meanonly
	loc y1 = r(mean)

	* Returns
	return matrix b = `bb'
	return matrix V = `VV'
	return matrix delta=`delta'
	return matrix Vdelta = `Vdelta'
	loc names: subinstr local names ".." " ", all
	loc names: subinstr local names `"""' "", all
	return local names = "`names'"
	return local cmd "`cmd'"
	return local df =  `df'
	return local komit = "`komit'"
	return local kmiss = "`kmiss'"
	return local y1 = `y1'
	return local depvar = "`depvar'"
	if "`sun_abraham'"!=""{
		return matrix b_interact `evt_bb' //interactions: cohort-relative time effects
		return matrix V_interact `evt_VV' // variance of the interactions
		return matrix ff_w `ff_w' //cohort shares
		return matrix Sigma_ff `Sigma_ff' //variance estimate of the cohort share estimators
		return loc sun_abraham = "sun_abraham"
	}
	if "`saveov'"!="" {
		return matrix deltaov = `deltaov' //user:delta coefs from unadjusted regression. excludes only norm=-1
		return matrix Vdeltaov = `Vdeltaov'
		return matrix mattrendy = `mattrendy'
		return matrix mattrendx = `mattrendx'
	}
	if "`trend'"!="" return local trend = "trend"
	return local method = "ols"
end


mata

	void adjdelta( real scalar trend,
					real scalar lwindow,
					real scalar rwindow,
					string scalar getDeltaL,
					string scalar getOmega,
					string scalar getOmegaL,
					string scalar getdelta,
					string scalar getOmegapsi,
					string scalar getOmegadeltapsi,
					string scalar gmm_trcoefs,
					string scalar deltaadj,
					string scalar Vadj,
					string scalar Valladj)
	{

	real matrix deltaL, Omega, OmegaL, delta, Omegapsi, Omegadeltapsi, HL, W, Vphi_hat, LambdaL, phi_hat, H, delta_star, Lambda, Vdelta_star, V_star11, V_star12, V_star21, V_star22, V_star, H_phi_hat

	deltaL = st_matrix(getDeltaL)
	Omega = st_matrix(getOmega)
	OmegaL = st_matrix(getOmegaL)
	delta = st_matrix(getdelta)
	delta = delta'

	Omegapsi=st_matrix(getOmegapsi)
	Omegadeltapsi=st_matrix(getOmegadeltapsi)
	/*
	deltaL
	Omega
	OmegaL
	delta

	Omegapsi
	Omegadeltapsi
	*/

	/* Build H_L */
	HL = range(trend+1,0,1)

	W= invsym(OmegaL)
	/* Solve for phi_hat */

	Vphi_hat = invsym(HL'*W*HL)

	LambdaL = Vphi_hat*HL'*W

	phi_hat = LambdaL*deltaL


	/* Get adjusted delta */
	H= (range(lwindow,-1,1)\range(1,rwindow+2,1))
	st_matrix("H",H)
	st_matrix("phi_hat",phi_hat)
	delta_star = delta - H*phi_hat

	/* Get variance of the adjusted deltas */

	Lambda = (J(rows(phi_hat),1,0),LambdaL,J(rows(phi_hat),rows(delta)-1-cols(LambdaL),0))
	Vdelta_star = Omega - H*Lambda*Omega - Omega'*Lambda'*H' + H*Lambda*Omega*Lambda'*H'

	/* Get variance of entire adjusted vector. Other coefs do not change but their covariance with delta does */
	V_star11 = (I(rows(delta)) - H*Lambda)* Omega * (I(rows(delta)) - Lambda'*H')
	V_star12 = (I(rows(delta)) - H*Lambda) * Omegadeltapsi
	V_star21 = Omegadeltapsi' * (I(rows(delta)) - Lambda'*H')
	V_star22 = Omegapsi
	V_star = (V_star11,V_star12\V_star21,V_star22)
	/* Average to kill eps errors */
	V_star = 0.5*(V_star + V_star')

	/* values of the trend for overlay plot */
	H_phi_hat=H*phi_hat

	/* return trend coeffcients*/
	st_matrix(gmm_trcoefs,H_phi_hat')

	/*return adjusted matrices*/
	st_matrix(deltaadj,delta_star')
	st_matrix(Vadj,Vdelta_star)
	st_matrix(Valladj,V_star)


	}

end

cap program drop repostdelta
program define repostdelta, eclass
	ereturn repost b=`1' V=`2'
end

* Program to parse trend
cap program drop parsetrend
program define parsetrend, rclass

	syntax [anything] , [method(string) SAVEOVerlay]

	return local trcoef "`anything'"
	if "`method'"=="" loc method "gmm"
	return local methodt "`method'"
	return local saveoverlay "`saveoverlay'"
end

*program to parse savek
cap program drop parsesavek
program define parsesavek, rclass

	syntax [anything] , [NOEstimate SAVEINTeract]

	return local savekl "`anything'"
	return local noestimatel "`noestimate'"
	return local saveintl "`saveinteract'"
end