*! v 3.0.0 2024feb24 Thanks to Ian R. Dohoo & Javier Sanchez for correcting some typos
*! v.1.0.0 N.Orsini 7aug2007

capture program drop episens_mcsa_unc
program episens_mcsa_unc, rclass
version 9.2

        syntax anything [ , obs(integer 5000) spexp(string) spunexp(string) srrcd(string) sorce(string) scorrprev(string)  ///
			          apprr(string) applb(string) appub(string) studytype(string) seed(string) GRaph DStat ]

        drop _all
        qui set obs `obs'
	  if "`seed'" != "" set seed `seed'

* get the cell counts

	gettoken a 0 : 0, parse(" ,")
	gettoken b 0 : 0, parse(" ,")
	gettoken c 0 : 0, parse(" ,")
	gettoken d 0 : 0, parse(" ,")

* di "`a'   `b'  `c'   `d'"

	local m1 = `a' + `b'
	local m0 = `c' + `d'

* get the observed RR

	tempname arrdx  albdx aubdx
  	scalar `arrdx' = `apprr'
	scalar `albdx' = `applb'
	scalar `aubdx' = `appub'

* Generate a pairs of 0,1 random variables with user-specified correlation

tempvar h1 h2 h3 p1 p0
tempname rprev

forv i = 1/3 {
gen `h`i'' = logit(uniform())
}

if "`scorrprev'" != "" 	scalar `rprev' = `scorrprev'
	else scalar `rprev' = 0

gen `p1' = invlogit( sqrt(`rprev')*`h1'+ sqrt(1-`rprev')*`h2')
gen `p0' = invlogit( sqrt(`rprev')*`h1'+ sqrt(1-`rprev')*`h3')

if "`spexp'" != "" {

	tempvar rn_spexp

	local wn : word count `sseca'

    	tokenize "`spexp'"
	local dist = "`1'"

	if "`dist'" == "Constant" qui gen double `rn_spexp' = `2'

 	if "`dist'" == "Uniform"  {
		local min = `2'
		local max = `3'
		qui gen double `rn_spexp' = `max'-(`max'-`min')*`p1'
	}

	if ("`dist'" == "Triangular")  | ("`dist'" == "Trapezoidal") {
		local min  = `2'
		local mod1 = `3'
		local mod2 = `4'
		local max  = `5'
 		qui gen double `rn_spexp' =  (`p1'*(`max'+`mod2'-`min'-`mod1') + (`min' + `mod1') )/2
		qui replace `rn_spexp' = `min' + sqrt((`mod1'-`min')*(2*`rn_spexp'-`min'-`mod1')) if `rn_spexp' < `mod1'
		qui replace `rn_spexp' = `max' - sqrt( 2*(`max'-`mod2')*(`rn_spexp'-`mod2')) if `rn_spexp' > `mod2'
	}

	if "`dist'" == "Logit-Logistic" {
		local m = `2'
		local s = `3'
		local bl = `4'
		local bu = `5'
		gen double `rn_spexp'  = `bl' + (`bu'-`bl')*invlogit(`m' + logit(`p1')*`s' )
	}

	if "`dist'" == "Logit-Normal"  {
		local m = `2'
		local s = `3'
		local bl = `4'
		local bu = `5'
		gen double `rn_spexp' = `bl' + (`bu'-`bl')*invlogit(`m' + invnorm(`p1')*`s' )
	}

}

if "`spunexp'" != "" {

	tempvar rn_spunexp

	local wn : word count `spunexp'

    	tokenize "`spunexp'"

	local dist = "`1'"

	if "`dist'" == "Constant" qui gen double `rn_spunexp' = `2'

 	if "`dist'" == "Uniform"  {
		local min = `2'
		local max = `3'
		qui gen double `rn_spunexp' = `max'-(`max'-`min')*`p0'
	}

	if ("`dist'" == "Triangular")  | ("`dist'" == "Trapezoidal") {
		local min  = `2'
		local mod1 = `3'
		local mod2 = `4'
		local max  = `5'
 		qui gen double `rn_spunexp' =  (`p0'*(`max'+`mod2'-`min'-`mod1') + (`min' + `mod1') )/2
		qui replace `rn_spunexp' = `min' + sqrt((`mod1'-`min')*(2*`rn_spunexp'-`min'-`mod1')) if `rn_spunexp' < `mod1'
		qui replace `rn_spunexp' = `max' - sqrt( 2*(`max'-`mod2')*(`rn_spunexp'-`mod2')) if `rn_spunexp' > `mod2'
	}

	if "`dist'" == "Logit-Logistic"  {
		local m = `2'
		local s = `3'
		local bl = `4'
		local bu = `5'
		gen double `rn_spunexp' = `bl' + (`bu'-`bl')*invlogit(`m' + invnorm(`p0')*`s' )
	}

	if "`dist'" == "Logit-Normal"   {
		local m = `2'
		local s = `3'
		local bl = `4'
		local bu = `5'
		gen double `rn_spunexp' = `bl' + (`bu'-`bl')*invlogit(`m' + invnorm(`p0')*`s' )
	}


}

if "`srrcd'" != "" {

	tempvar rn_srrcd

	local wn : word count `srrcd'

    	tokenize "`srrcd'"

	local distsrrcd = "`1'"

	if "`distsrrcd'" == "Constant" qui gen double `rn_srrcd' = `2'

 	if "`distsrrcd'" == "Uniform"  {
		local blsrrcd = `2'
		local busrrcd = `3'
		local min = `2'
		local max = `3'
		qui gen double `rn_srrcd' = `max'-(`max'-`min')*uniform()
	}

	if ("`distsrrcd'" == "Triangular")  | ("`distsrrcd'" == "Trapezoidal") {

		local min  = `2'
		local mod1 = `3'
		local mod2 = `4'
		local max  = `5'
		local blsrrcd = `2'
		local busrrcd = `5'

		qui gen double `rn_srrcd' =  (uniform()*(`max'+`mod2'-`min'-`mod1') + (`min' + `mod1') )/2
		qui replace `rn_srrcd' = `min' + sqrt((`mod1'-`min')*(2*`rn_srrcd'-`min'-`mod1')) if `rn_srrcd' < `mod1'
		qui replace `rn_srrcd' = `max' - sqrt( 2*(`max'-`mod2')*(`rn_srrcd'-`mod2')) if `rn_srrcd' > `mod2'

	}

	if "`distsrrcd'" == "Log-Normal"    {
		local m = `2'
		local s = `3'
		gen double `rn_srrcd' = exp( `m' + invnorm(uniform())*`s')
		tempvar log_rn_srrcd
		gen `log_rn_srrcd' = log(`rn_srrcd')
	}

	if "`distsrrcd'" == "Log-Logistic"    {
		local m = `2'
		local s = `3'
		gen double `rn_srrcd' = exp( `m' + logit(uniform())*`s')
		tempvar log_rn_srrcd
		gen `log_rn_srrcd' = log(`rn_srrcd')
	}

}

if "`sorce'" != "" {

	tempvar rn_sorce u

	gen `u' = uniform()

	local wn : word count `sorce'

    	tokenize "`sorce'"

	local distsorce = "`1'"

	if "`distsorce'" == "Constant" qui gen double `rn_sorce' = `2'

 	if "`distsorce'" == "Uniform"  {
		local blsorce = `2'
		local busorce = `3'
		local min = `2'
		local max = `3'
		qui gen double `rn_sorce' = `max'-(`max'-`min')*uniform()
	}

	if ("`distsorce'" == "Triangular")  | ("`distsorce'" == "Trapezoidal") {
		local min  = `2'
		local mod1 = `3'
		local mod2 = `4'
		local max  = `5'
		local blsorce = `2'
		local busorce = `5'

		qui gen double `rn_sorce' =  (uniform()*(`max'+`mod2'-`min'-`mod1') + (`min' + `mod1') )/2
		qui replace `rn_sorce' = `min' + sqrt((`mod1'-`min')*(2*`rn_sorce'-`min'-`mod1')) if `rn_sorce' < `mod1'
		qui replace `rn_sorce' = `max' - sqrt( 2*(`max'-`mod2')*(`rn_sorce'-`mod2')) if `rn_sorce' > `mod2'
	}


	if ("`distsorce'" == "Log-Normal")    {
		local m = `2'
		local s = `3'
		gen double `rn_sorce' = exp( `m' + invnorm(uniform())*`s' )
		tempvar log_rn_sorce
		gen `log_rn_sorce' = log(`rn_sorce')
	}

	if ("`distsorce'" == "Log-Logistic")    {
		local m = `2'
		local s = `3'
		gen double `rn_sorce' = exp( `m' + logit(uniform())*`s' )
		tempvar log_rn_sorce
		gen `log_rn_sorce' = log(`rn_sorce')
	}

}

di "`spexp'"
di "`spunexp'"
di "`srrcd'"
di in y "`sorce'"


		tempname rhoprev
		qui corr `rn_spexp' `rn_spunexp'
		scalar `rhoprev' = r(rho)

	if "`dstat'" != "" {
		qui corr `rn_spexp' `rn_spunexp'
		di as text "Correlation prevalences : " %3.2f r(rho)
		tabstat `rn_spexp' `rn_spunexp'  , stat(min median max ) format(%3.2f)
	}

if "`graph'" != "" qui hist   `rn_spexp'
if "`graph'" != "" qui hist   `rn_spunexp'
if "`graph'" != "" qui hist  `log_rn_srrcd'
if "`graph'" != "" & "`sorce'" != "" qui hist  `log_rn_sorce'

* keep a random subset of the bias parameters

	qui sample 1, count

* From whatever prior distribution the bias parameter are coming from put the values into scalars for the final calculations

	tempname  prz1 prz0 rrdz orze rrdx rrxz  percent_bias adj_factor  b11 b01 a11 a01

	scalar `prz1' = `rn_spexp'[1]
	scalar `prz0' = `rn_spunexp'[1]
	scalar `rrdz' = `rn_srrcd'[1]
	scalar `orze' = `rn_sorce'[1]

if "`sorce'" != "" {

  	 scalar `rrdx' = `arrdx'/[ (`rrdz'*`orze'*`prz0'+1-`prz0') / ( (`rrdz'*`prz0'+1-`prz0')*( `orze'*`prz0'+1-`prz0') ) ]

}

/*
	 // To be able to re-calculate the cell counts we need to back-calculate the prevalence of the confounder among the exposed - prz1
	 // I use a simple iterative method

	 tempname oz1 oz0
	 scalar `oz0' = [`prz0'/(1-`prz0')]
       local prz1 = .

	 forv i = 0(.01)1 {
		   scalar `oz1' = [`i'/(1-`i')]
		  * di "prz1 = " `i'  "    Diff =  " abs(`oz1' - (`orze'*`oz0') )
		   if abs(`oz1' - (`orze'*`oz0') ) < 1e-2  {
				 local prz1 = `i'
				 continue, break
		   }
	 }

	 if `prz1' == . {
		di as err "Not able to back-calculate the Pr(c=1|e=1)"
		exit 198
	}

}
*/

/*
	 di in g  "prz1 = " `prz1'
	 di "prz0 = " `prz0'
	 di "rrcd = " `rrdz'
	 di "orze = " `orze'
*/

 if "`spexp'" != "" & "`sorce'" == "" {

  	/*Original command - changed to get correct RR
	scalar `rrxz' = [(`prz1')*(1-`prz0')]/[(1-`prz1')*(`prz0')]
 	 scalar `b11' = `prz1' * `c'
	 scalar `b01' = `prz0' * `d'
	 scalar `a11' = (`rrdz'*`a'*`b11')/(`rrdz'*`b11' +`c'-`b11')
	 scalar `a01' = (`rrdz'*`b'*`b01')/(`rrdz'*`b01'+`d'-`b01')



	*/


	 scalar `rrxz' = [(`prz1')*(1-`prz0')]/[(1-`prz1')*(`prz0')]
   	 scalar `b11' = `prz1' * (`c'+`a')
  	 scalar `b01' = `prz0' * (`d'+`b')
	 scalar `a11' = (`rrdz'*`a'*`b11')/(`rrdz'*`b11' + ((`c'+`a')-`b11'))
	 scalar `a01' = (`rrdz'*`b'*`b01')/(`rrdz'*`b01'+ ((`d'+`b')-`b01'))


	if "`studytype'" == "cc"  scalar `rrdx' = (`a11'*`b01')/(`b11'*`a01')
	if "`studytype'" == "ir"  scalar `rrdx' = (`a11'/`b11')/(`a01'/`b01')
*	if "`studytype'" == "cs"  scalar `rrdx' = (`a11'/(`a11'+`b11'))/(`a01'/(`a01'+`b01'))
	if "`studytype'" == "cs"  scalar `rrdx' = (`a11'/(`b11'))/(`a01'/(`b01'))



 }

/*
di `a11'
di `a01'
di `b11'
di `b01'
di (`a11'*`b01')/(`b11'*`a01')
*/


	scalar `percent_bias' = (`arrdx'-`rrdx')/(`rrdx')*100
	scalar `adj_factor' = `arrdx' / `rrdx'

	 di "Adj RR = " %3.2f `rrdx'
	 di "percent bias = " %2.0f `percent_bias'
	tempname adjrrte
	scalar `adjrrte' = exp( log(`rrdx') - invnorm(uniform())*[ (log(`aubdx')-log(`albdx'))/(invnorm(.975)*2) ] )

 // Saved results

        return scalar adj_rr_unc = `rrdx'
	  return scalar adj_rr_unc_te = `adjrrte'
        return scalar adj_factor_unc = `adj_factor'
        return scalar perc_bias = `percent_bias'
	  return scalar orce = `orze'
 	  return scalar pc0 =  `prz0'
 	  return scalar rrcd = `rrdz'

 if "`spexp'" != "" & "`sorce'" == "" {
 	  return scalar a1 = `a11'
	  return scalar a0 = `a01'
	  return scalar b1 = `b11'
	  return scalar b0 = `b01'
 	  return scalar pc1 =  `prz1'
 	  return scalar orce = `rrxz'
	  return scalar rhoprev = `rhoprev'
}

end

/*

episens_mcsa_unc 45 94 257 945,  obs(5000) spexp(Constant .7) spunexp(Constant .5) srrcd(Constant 5)  apprr(1.76) studytype(cc)

episens_mcsa_unc 45 94 257 945,  obs(5000) spexp(Uniform .6 .8) spunexp(Constant .5) srrcd(Constant 5)  apprr(1.76) studytype(cc)
episens_mcsa_unc 45 94 257 945,  obs(5000) spexp(Uniform .6 .8) spunexp(Triangular .4 .5 .5 .6) srrcd(Log-Normal `=log(5)' 1)  apprr(1.76) studytype(cc)

episens_mcsa_unc 45 94 257 945,  obs(5000) spexp(Uniform .4 .7) spunexp(Uniform .4 .7) srrcd(Log-Normal 2.159 .280) ///
                                           apprr(1.76) studytype(cc)
set trace off
set tracedepth 2
episens_mcsa_unc 45 94 257 945,  obs(5000) spexp(Uniform .4 .7) spunexp(Uniform .4 .7) srrcd(Log-Normal 2.159 .280) ///
                                    sorce(Log-Normal 0 .639 )         apprr(1.76) studytype(cc)  graph

*/