// 1.0.1  JRF & AHF  01 FEB 2010
// Calculate Kendall's partial tau for an arbitrary number of confounders.

version 10.0
program define parttau, eclass sortpreserve

syntax varlist(numeric) [if] [in] [, CLuster(string) WCluster ///
			PC ESTimate(string) Level(cilevel) TRANSformation(string) ///
			SHOW Weight(string) RUN2 ]
marksample touse
	local vnum : word count `varlist'

	if `"`wcluster'"' == "" {
		local funtype = "bcluster"
	}
	else {
		local funtype = "wcluster"
	}
	if `"`transformation'"' == "" | `"`transformation'"' == "iden" {
		local transformation "identity"
		local transfText "None"
	}
	else if `"`transformation'"' == "sin" | `"`transformation'"' == "rho" {
		local transformation "rho"
		local transfText "Greiner's rho"
	}
	else if `"`transformation'"' == "arcsin" | `"`transformation'"' == "arsin" | `"`transformation'"' == "asin" {
		local transformation "asin"
		local transfText " Daniels' arcsine"
	}
	else if `"`transformation'"' == "z" {
		local transformation "z"
		local transfText "Fisher's z"
	}
	else if `"`transformation'"' == "zrho" {
		local transformation "zrho"
		local transfText "z-transform of Greiner's rho"
	}
	else if `"`transformation'"' == "c" {
		local transformation "c"
		local transfText "Harrell's c"
	}
	else {
		noi di ""
		noi di as error _column(4) "The given transformation does not match any of the offered transformations."
		noi di as error _column(4) "(Note that synonyms or truncations allowed in somersd might not be allowed here.)"
		exit
	}

	if `vnum' < 2 {
		noi di ""
		noi di _skip(4) as error "This command requires at least two variables."
		exit
	}
	else if `vnum' == 2 {
		local x : word 1 of `varlist'
		local y : word 2 of `varlist'
		qui replace `touse' = 0 if (`x' == . | `y' == . )
		qui count if `touse' == 1
		local N = r(N)

		capture somersd `x' `y' if `touse' != 0, taua level(`level') ///
					transf(`transformation') cluster(`cluster') funtype(`funtype')

		if _rc == 0 {
			noi di ""
			noi di _skip(4) `"With just two variables, we'll run "somersd" with the "taua" option."'
			noi di ""

			somersd, level(`level')
		}
		else if `"`run2'"' != "" {
			local run2 = 1
		}
	}
	if `vnum' > 2 | `"`run2'"' != "" {
		unab variablelist : `varlist'
		tokenize `variablelist'

		qui count if `touse' == 1
		local N = r(N)

		local tistring ""
		local thetastring ""
		local numComps = comb(`vnum',2) + `vnum'
		forv i = 1(1)`numComps' {
			tempvar tiplus`i'
			qui gen `tiplus`i'' = .
			local tistring "`tistring'`tiplus`i'' "
			tempvar theta`i'
			qui gen `theta`i'' = .
			local thetastring "`thetastring'`theta`i'' "
		}
		if `"`cluster'"' == "" {
			tempvar clustertemp
			qui egen `clustertemp' = seq() if `touse'
			local nclusters = `N'
		}
		else {
			tempvar clustertemp
			qui egen `clustertemp' = group(`cluster') if `touse'
			qui summ `clustertemp'
			local nclusters = r(max)
		}
		sort `clustertemp'
		if `"`pc'"' == "" {
			local pc = 0
		}
		else {
			local pc = 1
		}
		if `"`estimate'"' == "" {
			tempvar estimate
			qui gen `estimate' = .
		}
		else {
			capture confirm variable `estimate'
			if _rc == 0 {
				noi di `"Note: the variable "`estimate'" already exists and is being replaced."'
			}
			else {
				qui gen `estimate' = .
			}
			qui replace `estimate' = .
			local estimate = "`estimate'"
		}
		if `"`level'"' != "" {
			local hival = 0.5 + `level' / 200
			local cifactor = invnormal(`hival')
		}
		else {
			local cifactor = 1.96
		}
		if `"`weight'"' == "" {
			tempvar weight
			qui gen `weight' = 1
			local weight "`weight'"
		}
		else {
			capture confirm numeric variable `weight'
			if _rc != 0 {
				noi di "{error}The given weight variable does not exist or is not numeric."
				exit
			}
			qui summ `weight'
			if r(min) < 0 {
				noi di "{error}Weights must be nonnegative."
			}
		}
		tempvar viplus
		qui gen `viplus' = .

		tempname pointEsts

		mata: main(`pc', "`clustertemp'", "`funtype'", `vnum', "`thetastring'", "`variablelist'", ///
					"`tistring'", "`viplus'", "`estimate'", "`weight'", "`transformation'", `cifactor', ///
					"`pointEsts'", "`touse'")

		matrix Sigma = J(`vnum',`vnum',.)
		local counter = 0
		forv i = 1(1)`vnum' {
			forv j = `i'(1)`vnum' {
				local counter = `counter' + 1
				matrix Sigma[`i',`j'] = taus[1,`counter']
				matrix Sigma[`j',`i'] = taus[1,`counter']
			}
		}
		matrix drop taus

		tempname primaryvars confounders
		local `primaryvars' = word("`variablelist'",1) + " " + word("`variablelist'",2)
		local `confounders' ""
		forv i=3(1)`vnum' {
			local `confounders' = "``confounders'' " + word("`variablelist'",`i')
		}

		noi di ""
		noi di "{text}Primary variables: {result}``primaryvars''"
		noi di "{text}Confounders: {result}``confounders''"
		noi di "{text}Transformation: {result}`transfText'"
		noi di "{text}No. of obs.: {result}`N'"
		if `"`cluster'"' != "" {
			noi di "{text}No. of clusters: {result}`nclusters'"
		}
		noi di ""

		if `"`show'"' != "" {
			noi di "{text}Pairwise taus:"
			noi di "{text}{hline 48}"
			noi di "{text}{col 3}#{col 10}Name{col 40}Estimate"
			noi di "{text}{hline 48}"
			forv i = 1(1)`vnum' {
				local name1 = word("`variablelist'",`i')
				local length1 = length("`name1'")
				local dilen1 = min(`length1' + 2,8)
				local name1 = substr("`name1'",1,`dilen1')
				forv j = `i'(1)`vnum' {
					local name2 = word("`variablelist'",`j')
					local length2 = length("`name2'")
					local dilen2 = min(`length2' + 2,8)
					local name2 = substr("`name2'",1,`dilen2')
					noi di "{text}{col 2}`i',`j'{col 10}tau( " ///
							%`dilen1's "`name1', " %`dilen2's "`name2' )" ///
							_column(39) %10.7f as result Sigma[`i',`j']
				}
			}
			noi di "{text}{hline 48}"
			noi di ""
			noi di "{text}Partial tau:"
		}

		local rows = rowsof(`pointEsts')

		noi di "{text}{hline 13}{c TT}{hline 67}"
		noi di "{col 14}{text}{c |}{text}{col 31}Jackknife"
		noi di "{text}Interval:{col 14}{text}{c |}{col 22}Coef.{col 31}Std. Err.{col 46}z{col 52}P>|z|{col 62}[95% Conf. Interval]"
		noi di "{text}{hline 13}{c +}{hline 67}"
		noi di "{text}   symmetric{col 14}{text}{c |}{col 17}{result}" %10.7f `pointEsts'[1,1] _column(30) %10.7f `pointEsts'[1,2]  ///
				_column(43) %5.2f `pointEsts'[1,1]/`pointEsts'[1,2] ///
				_column(52) %5.3f 2 * (1 - normal(abs(`pointEsts'[1,1]/`pointEsts'[1,2]))) ///
				_column(61) %8.6f `pointEsts'[1,3] "    " %8.6f `pointEsts'[1,4]
		if "`transformation'" != "identity" & "`transformation'" != "rho"  & `"`transformation'"' != "c" {
			noi di "{text}  asymmetric{col 14}{text}{c |}{col 17}{result}" %10.7f `pointEsts'[2,1] as result ///
						_column(61) %8.6f `pointEsts'[2,3] "    " %8.6f `pointEsts'[2,4]
		}
		noi di "{text}{hline 13}{c BT}{hline 67}"
		if `"`transformation'"' != "identity" {
			noi di ""
			if "`transformation'" == "rho" | "`transformation'" == "c" {
				noi di as text "Results for partial tau are in the transformed space."
			}
			else if "`transformation'" == "zrho" {
				noi di as text "1st line is in the transformed, zrho, space."
				noi di as text "2nd line is in the space of rho.
			}
			else {
				noi di as text "1st line is in the transformed space."
				noi di as text "2nd line is in the original space.
			}
		}
		noi di ""

		tempname colnames colsofb
		local `colnames' "tau"

		matrix V = (`pointEsts'[1,2]^2)
		matrix colnames V = "``colnames''"
		matrix rownames V = "``colnames''"
		matrix colnames b = "``colnames''"

		matrix rownames Sigma = `varlist'
		matrix colnames Sigma = `varlist'

		ereturn post b V, esample(`touse')
		ereturn matrix taus = Sigma

		ereturn scalar SE = `pointEsts'[1,2]
		ereturn scalar N = `N'
		ereturn scalar N_clust = `nclusters'

		ereturn local cluster_type = `"`funtype'"'
		ereturn local primaryvars = "``primaryvars''"
		ereturn local confounders = "``confounders''"
		ereturn local vcetype = "Jackknife"
		ereturn local transf = "`transformation'"
		ereturn local cmd = "npt"
	}
end

mata:
	void main(real scalar pc, string scalar clusterv, string scalar funtype, ///
				real scalar nvars, string scalar thetas, string scalar varnames, ///
				string scalar tipluses, string scalar viplusv, string scalar estimatev, ///
				string scalar weightv, string scalar transformation, real scalar cifactor, ///
				string scalar matname, string scalar tousev)
	{
		st_view(cluster, ., clusterv, tousev)
		clpanel = panelsetup(cluster, 1)
		clstats = panelstats(clpanel)

		st_view(V, ., tokens(varnames), tousev)
		st_view(Ti, ., tokens(tipluses), tousev)
		st_view(Th, ., tokens(thetas), tousev)
		st_view(estimate, ., estimatev, tousev)
		st_view(weight, ., weightv, tousev)
		st_view(viplus, ., viplusv, tousev)

		numComps = comb(nvars,2) + nvars

		taus = J(1,numComps,.)

		viplus[.] = makeweight(weight)

		allphis = J(clstats[1],2 * (numComps + 1), .)

		counter = 0
		for (i1 = 1; i1 <= nvars; i1++) {
			for (i2 = i1; i2 <= nvars; i2++) {
				counter = counter + 1
				st_subview(x, V, ., i1)
				st_subview(y, V, ., i2)
				st_subview(tiplus, Ti, ., counter)
				st_subview(thetaj, Th, ., counter)

				tiplus[.] = maketiplus(x, y)
				phis = makephi(cluster, tiplus, x, y, viplus, weight)
				if (nvars == 2) {
					colOne = 2 * counter - 1
					colTwo = 2 * counter
					allphis[., colOne::colTwo] = phis[.,1::2]
				}
				if (funtype == "bcluster") {
					taus[counter] = (colsum(phis[.,1]) - colsum(phis[.,2])) / (colsum(phis[.,3]) - colsum(phis[.,4]))
				}
				else if (funtype == "wcluster") {
					taus[counter] = colsum(phis[.,2]) / colsum(phis[.,4])
				}
				if (i1 == i2 & pc == 1) {
					for (i3 = 1; i3 <= clstats[1]; i3++) {
						thetaj[i3] = 1
					}
				}
				else {
					thetaj[1..clstats[1]] = makethetaj(phis, funtype)
				}
			}
		}
		st_matrix("taus",taus)
		if (nvars == 2) {
			allphis[.,7::8] = phis[.,3::4]
			influence = makeInfluence(allphis, funtype)
			dispersion = makeDispersion(influence, allphis, clstats[1], funtype, transformation)
			st_matrix("disp",dispersion)
			results = makeResults2by2(dispersion, taus, cifactor, transformation)
		}
		else {
			estimate[.] = makeSigma(Th, nvars)
			overallEst = makeSigma(taus, nvars)
			results = makeResults(overallEst, estimate, cifactor, transformation)
		}
		st_matrix(matname, results)
	}

	real colvector makeweight(real colvector weight)
	{
		nobs = rows(weight)

		viplus = J(nobs,1,.)
		for (i1 = 1; i1 <= nobs; i1++) {
			viplus[i1] = 0
			for (i2 = 1; i2 < i1; i2++) {
				viplus[i1] = viplus[i1] + 1
				viplus[i2] = viplus[i2] + 1
			}
		}
		return(viplus)
	}

	real colvector maketiplus(real colvector x, real colvector y)
	{
		nobs = rows(x)

		tiplus = J(nobs,1,.)
		for (i1 = 1; i1 <= nobs; i1++) {
			tiplus[i1] = 0
			x1 = x[i1]
			y1 = y[i1]
			for (i2 = 1; i2 < i1; i2++) {
				x2 = x[i2]
				y2 = y[i2]
				xsign = (x1 < x2) - (x2 < x1)
				ysign = (y1 < y2) - (y2 < y1)
				tiplus[i1] = tiplus[i1] + xsign * ysign
				tiplus[i2] = tiplus[i2] + xsign * ysign
			}
		}
		return(tiplus)
	}

	real matrix makephi(real colvector cluster, real colvector tiplus, ///
						real colvector x, real colvector y, ///
						real colvector viplus, real colvector weight)
	{
		clpanel = panelsetup(cluster, 1)
		clstats = panelstats(clpanel)

		phikk = J(clstats[1],1,.)
		phijplus = J(clstats[1],1,.)

		phiVkk = J(clstats[1],1,.)
		phiVjplus = J(clstats[1],1,.)

		phis = J(clstats[1],4,.)

		for (i1 = 1; i1 <= clstats[1]; i1++) {
			cl_tiplus = tiplus[clpanel[i1,1]..clpanel[i1,2]]
			cl_viplus = viplus[clpanel[i1,1]..clpanel[i1,2]]
			phijplus[i1] = colsum(cl_tiplus[.])
			phiVjplus[i1] = colsum(cl_viplus[.])

			cl_x = x[clpanel[i1,1]..clpanel[i1,2]]
			cl_y = y[clpanel[i1,1]..clpanel[i1,2]]
			wcl_tiplus = J(rows(cl_x), 1, .)
			wcl_tiplus[.] = maketiplus(cl_x, cl_y)

			cl_weight = weight[clpanel[i1,1]..clpanel[i1,2]]
			wcl_viplus = J(rows(cl_weight), 1, .)
			wcl_viplus[.] = makeweight(cl_weight)

			phikk[i1] = colsum(wcl_tiplus[.])
			phiVkk[i1] = colsum(wcl_viplus[.])
		}

		phis[.,1] = phijplus[.]
		phis[.,2] = phikk[.]
		phis[.,3] = phiVjplus[.]
		phis[.,4] = phiVkk[.]

		return(phis)
	}

	real colvector makethetaj(real matrix phis, string scalar funtype)
	{
		phikk = phis[.,2]
		phiVkk = phis[.,4]

		phikksum = colsum(phikk[.])
		phiVkksum = colsum(phiVkk[.])

		thetaj = J(rows(phis),1,.)
		if (funtype == "bcluster") {
			phijplus = phis[.,1]
			phiVjplus = phis[.,3]
			phiplusplus = colsum(phijplus[.])
			phiVplusplus = colsum(phiVjplus[.])
			for (i1 = 1; i1 <= rows(phis); i1++) {
				thetajNumer = (phiplusplus - phikksum) - 2 * (phijplus[i1] - phikk[i1])
				thetajDenom = (phiVplusplus - phiVkksum) - 2 * (phiVjplus[i1] - phiVkk[i1])
				thetaj[i1] = thetajNumer / thetajDenom
			}
		}
		else if (funtype == "wcluster") {
			for (i1 = 1; i1 <= rows(phis); i1++) {
				thetajNumer = (phikksum - phikk[i1])
				thetajDenom = (phiVkksum - phiVkk[i1])
				thetaj[i1] = thetajNumer / thetajDenom
			}
		}
		return(thetaj)
	}

	real colvector makeSigma(real matrix Th, real scalar nvars)
	{
		Sigma = J(nvars, nvars, .)
		estimate = J(rows(Th),1,.)

		for (i1 = 1; i1 <= rows(Th); i1++) {
			counter = 0
			for (i2 = 1; i2 <= nvars; i2++) {
				for (i3 = i2; i3 <= nvars; i3++) {
					counter = counter + 1
					Sigma[i2,i3] = Th[i1,counter]
					Sigma[i3,i2] = Th[i1,counter]
				}
			}
			if (nvars > 2) {
				Sigma11 = Sigma[1..2,1::2]
				Sigma12 = Sigma[1..2,3::nvars]
				Sigma21 = Sigma[3..nvars,1::2]
				Sigma22 = Sigma[3..nvars,3::nvars]
				invSigma22 = invsym(Sigma22)

				Sigma_11dot2 = Sigma11 - Sigma12 * invSigma22 * Sigma21
				estimate[i1] = Sigma_11dot2[1,2] / sqrt(Sigma_11dot2[1,1] * Sigma_11dot2[2,2])
			}
			else {
				estimate[i1] = Sigma[1,2]
			}
		}
		return(estimate)
	}

	real matrix makeInfluence(real matrix allPhis, string scalar funtype)
	{
		nrows = rows(allPhis)
		ncols = cols(allPhis)

		phiVkk = allPhis[., ncols]
		phiXkk = allPhis[., 2]
		phiYkk = allPhis[., 4]

		psiV = J(nrows,1,.)
		psiX = J(nrows,1,.)
		psiY = J(nrows,1,.)

		if (funtype == "bcluster") {
			phiVjplus = allPhis[., ncols - 1]
			phiVplusplus = colsum(allPhis[., ncols - 1])
			phiVkksum = colsum(allPhis[., ncols])
			phiXjplus = allPhis[., 1]
			phiXplusplus = colsum(allPhis[., 1])
			phiXkksum = colsum(allPhis[., 2])
			phiYjplus = allPhis[., 3]
			phiYplusplus = colsum(allPhis[., 3])
			phiYkksum = colsum(allPhis[., 4])
			for (i1 = 1; i1 <= nrows; i1++) {
				psiV[i1] = (phiVplusplus - phiVkksum) / (nrows - 1) ///
							- ((phiVplusplus - phiVkksum) - 2 * (phiVjplus[i1] - phiVkk[i1])) / (nrows - 2)
				psiX[i1] = (phiXplusplus - phiXkksum) / (nrows - 1) ///
							- ((phiXplusplus - phiXkksum) - 2 * (phiXjplus[i1] - phiXkk[i1])) / (nrows - 2)
				psiY[i1] = (phiYplusplus - phiYkksum) / (nrows - 1) ///
							- ((phiYplusplus - phiYkksum) - 2 * (phiYjplus[i1] - phiYkk[i1])) / (nrows - 2)
			}
		}
		if (funtype == "wcluster") {
			for (i1 = 1; i1 <= nrows; i1++) {
				psiV[i1] = phiVkk[i1]
				psiX[i1] = phiXkk[i1]
				psiY[i1] = phiYkk[i1]
			}
		}

		influence = J(nrows,3,.)
		influence[.,1] = psiV :- (colsum(psiV[.]) / nrows)
		influence[.,2] = psiX :- (colsum(psiX[.]) / nrows)
		influence[.,3] = psiY :- (colsum(psiY[.]) / nrows)

		return(influence)
	}

	real matrix makeDispersion(real matrix influence, real matrix allPhis, real scalar n_cl, ///
							   string scalar funtype, string scalar transformation)
	{
		if (funtype == "bcluster") {
			Txx = (colsum(allPhis[.,1]) - colsum(allPhis[.,2])) / (n_cl * (n_cl - 1))
			Txy = (colsum(allPhis[.,3]) - colsum(allPhis[.,4])) / (n_cl * (n_cl - 1))
			V = (colsum(allPhis[.,7]) - colsum(allPhis[.,8])) / (n_cl * (n_cl - 1))
		}
		if (funtype == "wcluster") {
			Txx = colsum(allPhis[.,2]) / n_cl
			Txy = colsum(allPhis[.,4]) / n_cl
			V = colsum(allPhis[.,8]) / n_cl
		}
		derivs = (- Txx / (V ^ 2), 1 / V, 0      \  ///
				  - Txy / (V ^ 2), 0    , 1 / V)
		dispersion = derivs * influence' * influence * derivs' / (n_cl * (n_cl - 1))

		return(dispersion)
	}

	real matrix makeResults2by2(real matrix dispersion, real matrix taus, ///
									real scalar cifactor, string scalar transformation)
	{
		tausApprox = J(1,cols(taus),.)
		for (i = 1; i <= cols(taus); i++) {
			if (taus[i] == 1) {
				tausApprox[i] = 0.999999
			}
			else if (taus[i] == -1) {
				tausApprox[i] = -0.999999
			}
			else {
				tausApprox[i] = taus[i]
			}
		}

		if (transformation == "identity") {
			zeta = tausApprox[2]
			lopt = zeta - cifactor * sqrt(dispersion[2,2])
			hipt = zeta + cifactor * sqrt(dispersion[2,2])
			returnMat = (zeta, sqrt(dispersion[2,2]), lopt, hipt)
		}
		else if (transformation == "z") {
			transDerivs = (1 / (1 - tausApprox[1]^2) , 0  \  ///
						   0, 1 / (1 - tausApprox[2]^2))
			transDispersion = transDerivs * dispersion * transDerivs
			zeta = atanh(tausApprox[2])
			slopt = zeta - cifactor * sqrt(transDispersion[2,2])
			shipt = zeta + cifactor * sqrt(transDispersion[2,2])
			alopt = tanh(zeta - cifactor * sqrt(transDispersion[2,2]))
			ahipt = tanh(zeta + cifactor * sqrt(transDispersion[2,2]))
			returnMat = (zeta, sqrt(transDispersion[2,2]), slopt, shipt \
						 taus[2], 						., alopt, ahipt)
		}
		else if (transformation == "asin") {
			transDerivs = (1 / ((1 - tausApprox[1]^2)^(1/2)), 0  \  ///
						   0, 1 / ((1 - tausApprox[2]^2)^(1/2)))
			transDispersion = transDerivs * dispersion * transDerivs
			zeta = asin(tausApprox[2])
			slopt = zeta - cifactor * sqrt(transDispersion[2,2])
			shipt = zeta + cifactor * sqrt(transDispersion[2,2])
			alopt = sin(zeta - cifactor * sqrt(transDispersion[2,2]))
			ahipt = sin(zeta + cifactor * sqrt(transDispersion[2,2]))
			returnMat = (zeta, sqrt(transDispersion[2,2]), slopt, shipt \
						 taus[2], 						., alopt, ahipt)
		}
		else if (transformation == "rho") {
			transDerivs = (pi() / 2 * cos(pi() * tausApprox[1] / 2), 0   \  ///
						   0, pi() / 2 * cos(pi() * tausApprox[2] / 2))
			transDispersion = transDerivs * dispersion * transDerivs
			zeta = sin(pi() / 2 * tausApprox[2])
			slopt = zeta - cifactor * sqrt(transDispersion[2,2])
			shipt = zeta + cifactor * sqrt(transDispersion[2,2])
			returnMat = (zeta, sqrt(transDispersion[2,2]), slopt, shipt)
		}
		else if (transformation == "zrho") {
			transDerivs = ( pi() / 2 * cos(pi() * tausApprox[1] / 2) / (1 - sin(pi() * tausApprox[1] / 2)^2), 0  \  ///
							0, pi() / 2 * cos(pi() * tausApprox[2] / 2) / (1 - sin(pi() * tausApprox[2] / 2 )^2))
			transDispersion = transDerivs * dispersion * transDerivs
			zeta = atanh(sin(pi() / 2 * tausApprox[2]))
			slopt = zeta - cifactor * sqrt(transDispersion[2,2])
			shipt = zeta + cifactor * sqrt(transDispersion[2,2])
			rho = sin(pi() / 2 * tausApprox[2])
			alopt = tanh(zeta - cifactor * sqrt(transDispersion[2,2]))
			ahipt = tanh(zeta + cifactor * sqrt(transDispersion[2,2]))
			returnMat = (zeta, sqrt(transDispersion[2,2]), slopt, shipt \ rho, ., alopt, ahipt)
		}
		else if (transformation == "c") {
			transDerivs = ( 1/2, 0  \  ///
							0, 1/2)
			transDispersion = transDerivs * dispersion * transDerivs
			zeta = (tausApprox[2] + 1) / 2
			slopt = zeta - cifactor * sqrt(transDispersion[2,2])
			shipt = zeta + cifactor * sqrt(transDispersion[2,2])
			returnMat = (zeta, sqrt(transDispersion[2,2]), slopt, shipt)
		}
		st_matrix("b",(zeta))
		return(returnMat)
	}

	real matrix makeResults(real scalar overallEst, real colvector estimate, ///
									real scalar cifactor, string scalar transformation)
	{
		if (abs(overallEst) - 1 <= 1e-6) {
			approxTau = 0.999999 * overallEst
		}
		numEsts = rows(estimate) - missing(estimate)
		jkEstimates =  (estimate :* (1 - numEsts)) :+ (numEsts * overallEst)
		jkVar = variance(jkEstimates) / numEsts
		if (transformation == "identity") {
			zeta = overallEst
			zetaVec = jkEstimates
			SE = sqrt(jkVar * 1)
			lopt = zeta - cifactor * SE
			hipt = zeta + cifactor * SE
			returnMat = (zeta, SE, lopt, hipt)
		}
		else if (transformation == "z") {
			zeta = atanh(overallEst)
			zetaVec = atanh(jkEstimates)
			SE = sqrt(jkVar * 1 / (1 - approxTau^2)^2)
			slopt = zeta - cifactor * SE
			shipt = zeta + cifactor * SE
			alopt = tanh(zeta - cifactor * SE)
			ahipt = tanh(zeta + cifactor * SE)
			returnMat = (zeta, SE, slopt, shipt \
						 overallEst, ., alopt, ahipt)
		}
		else if (transformation == "asin") {
			zeta = asin(overallEst)
			zetaVec = asin(jkEstimates)
			SE = sqrt(jkVar * 1 / (1 - approxTau^2))
			slopt = zeta - cifactor * SE
			shipt = zeta + cifactor * SE
			alopt = sin(zeta - cifactor * SE)
			ahipt = sin(zeta + cifactor * SE)
			returnMat = (zeta, SE, slopt, shipt \
						 overallEst, ., alopt, ahipt)
		}
		else if (transformation == "rho") {
			zeta = sin(overallEst * pi() / 2)
			zetaVec = sin(jkEstimates :* pi() / 2)
			SE = sqrt(jkVar * (pi() / 2 * cos(pi() / 2 * approxTau))^2)
			slopt = zeta - cifactor * SE
			shipt = zeta + cifactor * SE
			returnMat = (zeta, SE, slopt, shipt)
		}
		else if (transformation == "zrho") {
			zeta = atanh(sin(overallEst * pi() / 2))
			zetaVec = atanh(sin(jkEstimates :* pi() / 2))
			SE = sqrt(jkVar * (pi() / 2 * cos(pi() / 2 * approxTau) / (1 - (sin(pi() / 2 * approxTau))^2))^2)
			slopt = zeta - cifactor * SE
			shipt = zeta + cifactor * SE
			rho = sin(overallEst * pi() / 2)
			alopt = tanh(zeta - cifactor * SE)
			ahipt = tanh(zeta + cifactor * SE)
			returnMat = (zeta, SE, slopt, shipt \ rho, ., alopt, ahipt)
		}
		else if (transformation == "c") {
			zeta = (overallEst + 1) / 2
			zetaVec = (jkEstimates :+ 1) :/ 2
			SE = sqrt(jkVar / 4)
			slopt = zeta - cifactor * SE
			shipt = zeta + cifactor * SE
			returnMat = (zeta, SE, slopt, shipt)
		}
		st_matrix("b",(zeta))
		return(returnMat)
	}
end