*! version 1.1.0 28aug2000
*! enhanced table interface to cs for more than 2 groups
*! authors Jens M. Lauritsen & Thomas J. Steichen

program define csjl
	version 6
	syntax varlist(min=2 max=2 num) [if] [in] [fweight] [, /*
		*/ rr rd at TYpe(string) Ref(int 1) Case(int 2)   /*
		*/ MISsing Level(int $S_level) by(varlist) SUBTab /*
		*/ SUBPct TABle TABPct CHI EXact TOtal DEC(int 2) ]

	tokenize `varlist'
	local xdat1 "`1'"
	local xdat2 "`2'"

	if "`exp'" != "" {local wtopt "[fw `exp']"}

	local chitab = "`chi'"
	if "`exact'" == "exact" { local chi = "" }

	if "`type'" == "" {
		if "`rr'" != "" { local type = " rr"}
		if "`rd'" != "" { local type = "`type'" + " rd"}
		if "`at'" != "" { local type = "`type'" + " at"}
		}
	else {
		local wctyp: word count "`type'"
		local wc = 1
		while `wc' <= `wctyp' {
			local wty: word `wc' of `type'
			if "`wty'" != "rr" & "`wty'" != "rd" & "`wty'" != "at" {
				di _n in re "type() has invalid value: " in ye "`wty'"
				exit
				}
			local wc = `wc' + 1
			}
		}

	local stype = trim("`type'" + " `chi'" + " `exact'")

	local by = cond("`by'" == "", "ovr12345", "ovr12345" + " `by'")

	if "`stype'" == "" {
		di _n in bl " Warning: no risk estimates specified," _c
		di in wh " rr" in bl " assumed"
		local stype = "rr"
		}

	local lb: var label `xdat1'
	di _n " `xdat1' " _col(12) "`lb'"
	local lb: var label `xdat2'
	di    " `xdat2' " _col(12) "`lb'"

* show overall tables if desired:
	if "`table'" != "" {
		di _n in ye "table is:" _c
		noi tabulate `xdat2' `xdat1' `if' `in' `wtopt', `missing' `chitab'
		}

	if "`tabpct'" != "" {
		di _n in ye "table with row percentage is:" _c
		noi tab `xdat2' `xdat1' `if' `in' `wtopt', `chitab' row `missing'
		}

* main by loop
* create heading for overall table:
* make a subtable for each level of a by variable:

while "`by'" ~= "" {

* find out which current by variable (note overall table called ovr12345).
	if index("`by'"," ") > 0 { local byvar = substr("`by'",1,index("`by'"," "))}
	else {local byvar = substr("`by'",1,length("`by'"))}
	local byvars =trim("`byvar'")
*get type for -byvar-
	cap confirm string var `byvar'
*if string, temp encode
	if _rc == 0 {
		tempvar byvare
		encode `byvar', gen(`byvare')
		local byvar "`byvare'"
		}

*diminish by for next table:
	local by = cond(index("`by'"," ") > 0,trim(substr("`by'",index("`by'"," ")+1,20)),"")
	if trim("`byvar'") == "ovr12345" {
		local byj = 1
		local outtab = cond("`if'" == "", "","`if'")
		}
	else { /* select create matrix with levels of byvargrp */
		qui tab `byvar' `if' `in' `wtopt', matrow(byrow) `missing'
		local byj = rowsof(byrow)
		local byt: val l `byvar'
* which label value is first, 0 or 1 ?
		local bylabn = 0
		if "`byt'" != "" {
			local bylab: label `byt' 0 8
			if trim("`bylab'") == "0" {
				local bylabn = 1
				}
			}
		}

local bylist
local byi = 1
while `byi' <= `byj' {
	if trim("`byvar'") == "ovr12345" {
		local missing = cond("`missing'" == "","","missing")
		qui tab `xdat2' `xdat1' `in' `if' `wtopt', matcell(tabel) matrow(colval) `missing'
		local byi = `byi' + 2
		}
	else {
		if "`byt'" != "" { local bylab: label `byt' `bylabn' 8 }
		else { local bylab = byrow[`byi',1] }
		if byrow[`byi',1] == . { local bylab = byrow[`byi',1] }
		local byval = byrow[`byi',1]
		local byif = cond(trim("`if'") == "","if ","`if' & ") + "(`byvar' == `byval' )"
		qui tab `xdat2' `xdat1' `in' `byif' `wtopt', matcell(tabel) matrow(colval) `missing'

	if "`bylist'" == "" & "`byvar'" != "ovr12345" {
		local lb: var label `byvars'
		di _n in gr "by " in ye "`byvars' (`lb')"
		local bylist = "listed"
		}

		di _n in gr "  `byvars'" in ye " == " in gr "`bylab'"
		local byi = `byi' + 1
		local bylabn = `bylabn' + 1
		}

	local mx2 = rowsof(tabel)
	local mx1 = colsof(tabel)

* check approprateness of variables and types of output:
	if `mx1' != 2 {
		di in yel "   insufficient data."
		}
	else {
		local ref = cond(`ref' > `mx2',`mx2',`ref')
		local case = cond(`case' != 2, min(`case',2),2)
		if "`subtab'" != "" & trim("`byvar'") != "ovr12345" {
			di _n in ye "table is:" _c
			noi tab `xdat2' `xdat1' `byif' `in' `wtopt', `missing' `chitab'
			}
		if "`subpct'" != "" & trim("`byvar'") != "ovr12345" {
			di _n in ye "table with row percentage is:" _c
			noi tab `xdat2' `xdat1' `byif' `in' `wtopt', `chitab' row `missing'
			}

* list subtable by categories of stratify variable:

* make table:
		local i = rowsof(tabel)
		matrix col = J(`i',1,0)
		matrix row = J(2,1,0)

* create sums
		local i = 0
		while `i' < `mx2' {
			local i = `i' + 1
			mat col[`i',1] = tabel[`i',1] + tabel[`i',2]
			mat row[1,1] = row[1,1] + tabel[`i',1]
			mat row[2,1] = row[2,1] + tabel[`i',2]
			}

* ready to create results.
		matrix outrr  = J(`i',1,0)
		matrix lowrr  = J(`i',1,0)
		matrix highrr = J(`i',1,0)
		matrix outrd  = J(`i',1,0)
		matrix lowrd  = J(`i',1,0)
		matrix highrd = J(`i',1,0)
		matrix outat  = J(`i',1,0)
		matrix lowat  = J(`i',1,0)
		matrix highat = J(`i',1,0)
		matrix Chi    = J(`i',1,0)
		matrix p_chi  = J(`i',1,0)

		local i = 1
		while `i' <= `mx2' {
			if `i' != `ref' {
				local a = tabel[`i',  `case']
				local b = tabel[`ref',`case']
				local c = cond(`case' == 1, tabel[`i',2],   tabel[`i',1])
				local d = cond(`case' == 1, tabel[`ref',2], tabel[`ref',1])
				if tabel[`i',1] > 0 & tabel[`i',2] > 0 {
					qui csi `a' `b' `c' `d', `exact' level(`level')
					if r(rr) != . {
						mat  outrr[`i',1] = r(rr)
						mat  lowrr[`i',1] = r(lb_rr)
						mat highrr[`i',1] = r(ub_rr)
						mat  outrd[`i',1] = r(rd)
						mat  lowrd[`i',1] = r(lb_rd)
						mat highrd[`i',1] = r(ub_rd)
						mat  outat[`i',1] = r(afe)
						mat  lowat[`i',1] = r(lb_afe)
						mat highat[`i',1] = r(ub_afe)
						}
					if "`exact'" == "" {
						mat   Chi[`i',1] = r(chi2)
						mat p_chi[`i',1] = r(p)
						}
					else { mat Chi[`i',1] = 0
						mat p_chi[`i',1] = r(p_exact)
						}
					if `b' == 0 { mat p_chi[`i',1] = -1.0 }
					}
				else {
					mat  outrr[`i',1] = 0
					mat  lowrr[`i',1] = 0
					mat highrr[`i',1] = 0
					mat  outrd[`i',1] = 0
					mat  lowrd[`i',1] = 0
					mat highrd[`i',1] = 0
					mat  outat[`i',1] = 0
					mat  lowat[`i',1] = 0
					mat highat[`i',1] = 0
					mat    Chi[`i',1] = 0
					mat 	p_chi[`i',1] = -1.0
					}
				}
				local i = `i' + 1
			}

* output table
* step through levels of the table
* find size of largest estimate:
		local      i = 0
		local  sizrr = 0
		local  sizrd = 0
		local  sizat = 0
		local sizrrm = 0
		local sizrdm = 0
		local sizatm = 0
		while `i' < `mx2' {
			local i = `i' + 1
			local sizrr = max(length(trim(string(int(highrr[`i',1])))),`sizrr')
			local sizrd = max(length(trim(string(int(highrd[`i',1])))),`sizrd')
			local sizat = max(length(trim(string(int(highat[`i',1])))),`sizat')
			if `sizrrm' == 0 { local sizrrm = cond(lowrr[`i',1] < 0,1,0) }
			if `sizrdm' == 0 { local sizrdm = cond(lowrd[`i',1] < 0,1,0) }
			if `sizatm' == 0 { local sizatm = cond(lowat[`i',1] < 0,1,0) }
			}
		local sizrr = max(5, `sizrr' + `dec' + 1 + `sizrrm')
		local sizrd = max(5, `sizrd' + `dec' + 1 + `sizrdm')
		local sizat = max(5, `sizat' + `dec' + 1 + `sizatm')
		local fmtrr = "%`sizrr'.`dec'f"
		local fmtrd = "%`sizrd'.`dec'f"
		local fmtat = "%`sizat'.`dec'f"

* conditional output of header
		if trim("`byvar'") == "ovr12345" | "`subtab'" != "" | "`subpct'" != "" {
			top 15 `level' "`stype'" `xdat1' `xdat2' `sizrr' `sizrd' `sizat' `dec'
			if length(trim("`by'")) > 0 {di in gr "unstratified"}
			}

* label:
 		local vallab: value label `xdat2'
		local i = 0
		while `i' < `mx2' {
			local i = `i' + 1
			local valnum = colval[`i',1]
			if "`vallab'" != "" { local labx: label `vallab' `valnum' 12 }
				else { local labx = colval[`i',1] }
			di in ye %12s "`labx'" _col(15) _c
* counts:
			di in ye %6.0f col[`i',1] %8.0f tabel[`i',`case'] "    " _c
			if `i' == `ref' { di in ye "  ref. group" _c }

* user specified outcome measures, when #cases > 0:
			if p_chi[`i',1] == -1 { di "  insufficient data" }
			else {
				parse "`stype'", parse(" ")
				while "`1'" ~= "" {
					if index("`1'","rr") > 0 {
						estout `fmtrr' outrr[`i',1] lowrr[`i',1] highrr[`i',1] `i' `ref'
						}
					if index("`1'","rd") > 0 {
						estout `fmtrd' outrd[`i',1] lowrd[`i',1] highrd[`i',1] `i' `ref'
						}
					if index("`1'","at") > 0 {
						estout `fmtat' outat[`i',1] lowat[`i',1] highat[`i',1] `i' `ref'
						}
					if `i' != `ref' {
						if index("`1'","chi") > 0 {
							di "  " %5.1f Chi[`i',1] %7.3f p_chi[`i',1] _c
							}
						if "`1'" == "exact" { di "   " %7.3f p_chi[`i',1] _c }
						}
					macro shift
					}
				di " "
				}
			}

		if "`total'" != "" { local x = (row[1,1] + row[2,1] )
		di in ye %12s "totals" _col(15) in ye %6.0f `x' %8.0f row[`case',1]
		}

	}

} /* end of bygroup level */

} /* end of current by variable */


line $S_line
if $S_line > 79 & "$S_csw" != "Y" {
	di in bl "You can define a wider line format with the commands: " in wh _n /*
		*/ "set log linesize $S_line " _n "set display linesize $S_line"
	qui push set log linesize $S_line
	qui push set display linesize $S_line
	global S_csw = "Y"
	}
global S_line
end


program define estout, rclass
	if `5' != `6' {
		di " " `1' `2' " " `1' `3' " " `1' `4' _c
		}
end


program define line
	di in gr _dup(`1') "-"
end


program define top, rclass
* write out first line of table
* idea is to let user decide sequence of estimates or tests:
	local tab =  `1'
	local lev =  `2'
	local  ty = "`3'"
	local   Y = "`4'"
	local   X = "`5'"
	local srr =  `6'
	local srd =  `7'
	local sat =  `8'
	local dec =  `9'

	di _n " Outcome: `Y' " _col(34) _c
	local varno: word count `ty'
	local i = 34
	parse "`ty'", parse(" ")
	while "`1'" ~= "" {
		if index("`1'","rr") > 0 {
			local s = (`srr' + 1) * 3 - 10
			local t = int(`s'/2)
			di _dup(`t') " " _c
			di in gr "Risk Ratio" _c
			local t = `s' - `t'
			di _dup(`t') " " _c
			local i = `i' + `s' + 10
			}
		if index("`1'","rd") > 0 {
			local s = (`srd' + 1) * 3 - 15
			local t = int(`s'/2)
			di _dup(`t') " " _c
			di in gr "Risk Difference" _c
			local t = `s' - `t'
			di _dup(`t') " " _c
			local i = `i' + `s' + 15
			}
		if index("`1'","at") > 0 {
			local s = (`srd' + 1) * 3 - 17
			local t = int(`s'/2)
			di _dup(`t') " " _c
			di in gr "Attributable Risk" _c
			local t = `s' - `t'
			di _dup(`t') " " _c
			local i = `i' + `s' + 17
			}
		if index("`1'","ex")  > 0 { local i = `i' + 10 }
		if index("`1'","chi") > 0 { local i = `i' + 14 }
		macro shift
		}
	di " "
	line `i'

* column headers:
	di in gr _col(3) "`X'" _col(`tab') "     N   cases    " _c
	parse "`ty'", parse(" ")
	while "`1'" ~= "" {
		if index("`1'","rr") > 0 {
			local s = `srr' - `dec'
			if `s' > 0 { di _dup(`s') " " _c }
			di in gr "`1'" _c
			local s = `dec'
			if `s' > 0 { di _dup(`s') " " _c }
			di in gr "[" _c
			local s = 2 * (`srr' + 1) - 8 - 1
			local t = int(`s'/2)
			if `t' > 0 { di _dup(`t') " " _c }
			di in gr "`lev'% CI" _c
			local t = `s' - `t'
			if `t' > 0 { di _dup(`t') " " _c }
			di in gr "]" _c
			}
		if index("`1'","rd") > 0 {
			local s = `srd' - `dec'
			if `s' > 0 { di _dup(`s') " " _c }
			di in gr "`1'" _c
			local s = `dec'
			if `s' > 0 { di _dup(`s') " " _c }
			di in gr "[" _c
			local s = 2 * (`srd' + 1) - 8 - 1
			local t = int(`s'/2)
			if `t' > 0 { di _dup(`t') " " _c }
			di in gr "`lev'% CI" _c
			local t = `s' - `t'
			if `t' > 0 { di _dup(`t') " " _c }
			di in gr "]" _c
			}
		if index("`1'","at") > 0 {
			local s = `sat' - `dec'
			if `s' > 0 { di _dup(`s') " " _c }
			di in gr "`1'" _c
			local s = `dec'
			if `s' > 0 { di _dup(`s') " " _c }
			di in gr "[" _c
			local s = 2 * (`sat' + 1) - 8 - 1
			local t = int(`s'/2)
			if `t' > 0 { di _dup(`t') " " _c }
			di in gr "`lev'% CI" _c
			local t = `s' - `t'
			if `t' > 0 { di _dup(`t') " " _c }
			di in gr "]" _c
			}
		if index("`1'","exact") > 0 { di in gr "   exact p " _c }
		else if index("`ty'","exact") == 0 & index("`1'","chi") > 0 {
			di in gr "   Chi2    p " _c
			}
		macro shift
		}
	di " "
	line `i'
	global S_line = `i'
end