*! version 1.0.2 PR 30sep2004.
program define micombine7, eclass
version 7

if replay() {
	if "`e(cmd)'"!="micombine7" {
		error 301
	}
	di as text _n "Multiple imputation parameter estimates (" e(m) " imputations)"
	estimates display, `e(eform)'
	exit
}

gettoken cmd 0 : 0
if "`cmd'"=="stpm" {
	local dist 7
	local glm 0
	local qreg 0
	local xtgee 0
	local normal 0
}
else {
	cmdchk7 `cmd'
	if `s(bad)' {
		di as error "invalid or unrecognised command, `cmd'"
		exit 198
	}
	/*
		dist=0 (normal), 1 (binomial), 2 (poisson), 3 (cox), 4 (glm),
		5 (xtgee), 6(ereg/weibull).
	*/
	local dist `s(dist)'
	local glm `s(isglm)'
	local qreg `s(isqreg)'
	local xtgee `s(isxtgee)'
	local normal `s(isnorm)'
}
syntax varlist(min=1 numeric) [if] [in] [aw fw pw iw] , [ IMPid(string) /*
*/ CC(varlist) noCONStant DEAD(varname) DETail Eform(passthru) Genxb(string) LRR * ]

if "`impid'"=="" {
	local impid _j
}
cap confirm var `impid'
if _rc {
	di as err "imputation identifier `impid' not found"
	exit 601
}

chkrowid
local I `s(I)'

if "`detail'"!="" {
	local detail noisily
}
else local detail
frac_cox "`dead'" `dist'
if "`constant'"=="noconstant" {
	if "`cmd'"=="fit" | "`cmd'"=="cox" {
		di as error "noconstant invalid with `cmd'"
		exit 198
	}
	local options "`options' noconstant"
}
if `dist'==7 {	/* stcox, streg, stpm */
	local y
	local yname _t
	local xvars `varlist'
}
else {
	gettoken y xvars : varlist
	local yname `y'
}

tempvar touse
quietly {
	marksample touse
	markout `touse' `varlist' `dead' `cc'
	if "`dead'"!="" {
		local dead "dead(`dead')"
	}

* Deal with weights.
	frac_wgt `"`exp'"' `touse' `"`weight'"'
	local wgt `r(wgt)'

	tempvar J
	egen int `J'=group(`impid') if `touse'
	sum `J', meanonly
	local m=r(max)
	if `m'<2 {
		di as error "there must be at least 2 imputations"
		exit 198
	}

	local nxvar: word count `xvars'
	if `nxvar'<1 {
		di as err "there must be at least one covariate"
		exit 198
	}
	local ncc: word count `cc'		/* could legitimately be zero */
	local nvar=`nxvar'+`ncc'		/* number of covariates in model */

	count if `touse'==1 & `J'==1
	local nobs=r(N)

* Compute model over m imputations
	tempname W Q B T QQ
	if "`genxb'"!="" {
		tempvar xb xbtmp
		gen `xb'=.
	}
	forvalues i=1/`m' {
		tempname Q`i'
		`detail' `cmd' `y' `xvars' `cc' if `touse'==1 & `J'==`i' `wgt', `options' `dead' `constant'
		if "`genxb'"!="" {
			predict `xbtmp' if `touse'==1 & `J'==`i', xb
			replace `xb'=`xbtmp' if  `touse'==1 & `J'==`i'
			drop `xbtmp'
		}
		matrix `Q`i''=e(b)
		if `i'==1 {
			matrix `Q'=e(b)
			matrix `W'=e(V)
		}
		else {
			matrix `Q'=`Q'+e(b)
			matrix `W'=`W'+e(V)
		}
	}
	if "`genxb'"!="" {
		sort `touse' `I' `J'
		by `touse' `I': gen `genxb'=sum(`xb')/`m' if `touse'==1
		by `touse' `I': replace `genxb'=`genxb'[_N] if _n<_N
		lab var `genxb' "Mean Linear Predictor (`m' imputations)"
	}
	matrix `Q'=`Q'/`m'		/* MI param estimates */
	matrix `W'=`W'/`m'
	local k=colsof(`Q')
	matrix `B'=J(`k',`k',0)
	forvalues i=1/`m' {
		matrix `QQ'=`Q`i''-`Q'
		if `i'==1 {
			matrix `B'=`QQ''*`QQ'
		}
		else matrix `B'=`B'+`QQ''*`QQ'
	}
	matrix `B'=`B'/(`m'-1)
	matrix `T'=`W'+(1+1/`m')*`B'	/* estimated VCE matrix */
	/*
		Relative increase in variance due to missing information (r) for
		each variable, and df and lambda, the fraction of missing information.
		All measures are unstable for low m. See Schafer (1997) p. 110.

		Note that BIF = sqrt(T/W) = sqrt(1 + (B/W)*(1+1/m)) = sqrt(1+r)
		is the between-imputation imprecision factor, i.e. the ratio
		of the SE derived from T to the SE derived from W,
		ignoring between-imputation variation in parameter estimates.
	*/
	tempname r lambda nu BIF
	matrix `r'=J(1,`k',0)
	matrix `lambda'=J(1,`k',0)
	matrix `nu'=J(1,`k',0)
	matrix `BIF'=J(1,`k',0)
	forvalues j=1/`k' {
		matrix `r'[1,`j']=(1+1/`m')*`B'[`j',`j']/`W'[`j',`j']
		matrix `nu'[1,`j']=(`m'-1)*(1+1/`r'[1,`j'])^2
		matrix `lambda'[1,`j']=(`r'[1,`j']+2/(`nu'[1,`j']+3))/(`r'[1,`j']+1)
		matrix `BIF'[1,`j']=sqrt(1+`r'[1,`j'])	/* = sqrt(`T'[`j',`j']/`W'[`j',`j']) */
	}
	* use all varnames
	local names: colnames(`Q1')
	matrix colnames `r'=`names'
	matrix colnames `nu'=`names'
	matrix colnames `lambda'=`names'
	matrix colnames `BIF'=`names'

	* Li, Raghunathan & Rubin (1991) estimates of T and nu1
	* for F test of all params=0 on k,nu1 degrees of freedom
	tempname r1 t BW TLRR
	matrix `BW'=`B'*syminv(`W')
	scalar `r1'=trace(`BW')*(1+1/`m')/`k'
	matrix `TLRR'=`W'*(1+`r1')
	scalar `t'=`k'*(`m'-1)

	matrix colnames `Q'=`names'
	matrix rownames `T'=`names'
	matrix colnames `T'=`names'
	matrix rownames `B'=`names'
	matrix colnames `B'=`names'
	matrix rownames `TLRR'=`names'
	matrix colnames `TLRR'=`names'

}
if `normal' {
	local dof dof(`k')
}
di as text _n "Multiple imputation parameter estimates (`m' imputations)"
if "`lrr'"!="" {
	di as text "[Using Li-Raghunathan-Rubin (LRR) estimate of VCE matrix]"
	estimates post `Q' `TLRR', depname(`yname') obs(`nobs')
	estimates matrix T `T'
}
else {
	estimates post `Q' `T', depname(`yname') obs(`nobs')
	estimates matrix TLRR `TLRR'
}
estimates display, `eform'
di as result `nobs' as text " observations."
estimates matrix B `B'
estimates matrix W `W'
estimates matrix r `r'
estimates matrix nu `nu'
estimates matrix lambda `lambda'
estimates matrix BIF `BIF'
estimates scalar r1=`r1'
estimates scalar nu1=cond(`t'>4, 4+(`t'-4)*(1+(1-2/`t')/`r1')^2, /*
 */ 0.5*`t'*(1+1/`k')*(1+1/`r1')^2)
estimates scalar m=`m'
estimates local eform `eform'
estimates local cmd micombine7
end

program define chkrowid, sclass
local I: char _dta[mi_id]
if "`I'"=="" {
	di as error "no row-identifier variable found - data may have incorrect format"
	exit 198
}
cap confirm var `I'
local rc=_rc
if `rc' {
	di as error "row-identifier variable `I' not found"
	exit `rc'
}
sret local I `I'
end