*! 1.3.0 Ariel Linden 23Sep2019 // changed instances of "bsubstr()" to "substr()" because of Stata version issues
*! 1.2.0 Ariel Linden 05Aug2019 // made "rare" the default for OR and HR, and made "common" the user-specified option
								// added CI to figure

*! 1.1.0 Ariel Linden 26Jan2019 // added figure option, streamlined code
*! 1.0.0 Ariel Linden 24Jan2019

program define evalue, rclass
version 11.0

			syntax anything  [, 				///
				Lcl(numlist max=1)				///
				Ucl(numlist max=1)				///
				SE(numlist max=1)				///
				COMMon							///
				TRue(numlist max=1)				///
				LEVel(cilevel)					///
				GRid(real 0.0001)				///
				FIGure FIGure2(str asis)		///
				]


		gettoken estype anything : anything, parse(" ")
        local lcmd = length("`estype'")

		// Confirm numeric arguments, depending on model type
		if "`estype'" == substr("rd", 1, max(2,`lcmd')) {
			numlist "`anything'", min(4) max(4)
			tokenize `anything', parse(" ")

			local a `1'
			local b `2'
			local c `3'
			local d `4'

			confirm integer number `a'
			confirm integer number `b'
			confirm integer number `c'
			confirm integer number `d'

			if `a'<0 | `b'<0 | `c'<0 | `d'<0 {
                di in red "negative numbers invalid"
                exit 411
			}
		}
		else numlist "`anything'", min(1) max(1)


		// Confirm that point estimate and true estimates are positive for RR, OR, and HR
		if inlist("`estype'", substr("rr", 1, max(2,`lcmd')), substr("or", 1, max(2,`lcmd')), substr("hr", 1, max(2,`lcmd'))) {
			if `anything' < 0 {
				di as err "point estimate cannot be negative"
				exit 411
			}
			if "`true'" != "" {
				if `true' < 0 {
					di as err "true value cannot be negative"
				exit 411
				}
			}

			// Confirm that point estimate is within the confidence interval
			if "`lcl'" != "" {
				if `anything' < `lcl' {
				di as err "point estimate cannot be lower than LCL"
				exit 198
				}
			}
			if "`ucl'" != "" {
				if `anything' > `ucl' {
				di as err "point estimate cannot be higher than UCL"
				exit 198
				}
			}

		} // end inlist

		// set default true value to 0 for RD and SMD, and 1 for all other models
		if inlist("`estype'", substr("rd", 1, max(2,`lcmd')), substr("smd", 1, max(3,`lcmd'))) & "`true'" == "" {
				local true = 0
		}
		if !inlist("`estype'", substr("rd", 1, max(2,`lcmd')), substr("smd", 1, max(3,`lcmd'))) & "`true'" == "" {
				local true = 1
		}


		tempname estimate ci
		// set ci to null for later use in return scalar
		scalar `ci' = .

		*************************
		**  risk or rate ratio **
        *************************
		if "`estype'" == substr("rr", 1, max(2,`lcmd')) {

			// if point estimate <= 1
			if inrange(`anything',0, 1) {

				* when true is lower than point estimate
				if `true' < `anything' {
					scalar `estimate' = (`anything'/`true') + sqrt((`anything'/`true') * ((`anything'/`true') - 1))
				}
				else scalar `estimate' = 1/(`anything'/`true') + sqrt( 1/(`anything'/`true') * (1/(`anything'/`true') - 1))

				if `true' < `anything' & "`lcl'" != "" {
					local ll = (`lcl'/`true') + sqrt((`lcl'/`true') * ((`lcl'/`true') - 1))
				}
				else if "`lcl'" != "" {
					local ll = 1/(`lcl'/`true') + sqrt( 1/(`lcl'/`true') * (1/(`lcl'/`true') - 1))
				}
				if `true' < `anything' & "`ucl'" != "" {
						local ul = (`ucl'/`true') + sqrt((`ucl'/`true') * ((`ucl'/`true') - 1))
				}
				else if "`ucl'" != "" {
					local ul = 1/(`ucl'/`true') + sqrt( 1/(`ucl'/`true') * (1/(`ucl'/`true') - 1))
				}
			} // end <=1


			// if point estimate > 1
			else if `anything' > 1 {

				* when true is higher than point estimate
				if `true' > `anything' {
					scalar `estimate' = (`true'/`anything') + sqrt((`true'/`anything') * ((`true'/`anything') - 1))
				}
				else scalar `estimate' = (`anything'/`true') + sqrt((`anything'/`true') * ((`anything'/`true') - 1))

				if `true' > `anything' & "`lcl'" != "" {
					local ll = (`true'/`lcl') + sqrt((`true'/`lcl') * ((`true'/`lcl') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (`lcl'/`true') + sqrt((`lcl'/`true') * ((`lcl'/`true') - 1))
				}
				if `true' > `anything' & "`ucl'" != "" {
					local ul = (`true'/`ucl') + sqrt((`true'/`ucl') * ((`true'/`ucl') - 1))
				}
				else if "`ucl'" != "" {
					local ul = (`ucl'/`true') + sqrt((`ucl'/`true') * ((`ucl'/`true') - 1))
				}
			} // end >1

		} // end RR

		*****************
		**  odds ratio **
        *****************
         else if "`estype'" == substr("or", 1, max(2,`lcmd')) {

			// if point estimate <= 1 & common
			if inrange(`anything',0, 1) & "`common'" != "" {
				// if point estimate <= 1 & common
				if `true' < `anything' {
					scalar `estimate' = sqrt(`anything'/`true') + sqrt(sqrt(`anything'/`true') * (sqrt(`anything'/`true') - 1))
				}
				else scalar `estimate' = (sqrt(1/`anything') + sqrt(sqrt(1/`anything') * (sqrt(1/`anything') - sqrt(1/`true')))) / sqrt(1/`true')

				if `true' < `anything' & "`lcl'" != "" {
					local ll = sqrt(`lcl'/`true') + sqrt(sqrt(`lcl'/`true') * (sqrt(`lcl'/`true') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (sqrt(1/`lcl') + sqrt(sqrt(1/`lcl') * (sqrt(1/`lcl') - sqrt(1/`true')))) / sqrt(1/`true')
				}
				if `true' < `anything' & "`ucl'" != "" {
					local ul = sqrt(`ucl'/`true') + sqrt(sqrt(`ucl'/`true') * (sqrt(`ucl'/`true') - 1))
				}
				else if "`ucl'" != "" {
					local ul = (sqrt(1/`ucl') + sqrt(sqrt(1/`ucl') * (sqrt(1/`ucl') - sqrt(1/`true')))) / sqrt(1/`true')
				}
			} // end <=1

			// if point estimate > 1 & common
			else if `anything' > 1 & "`common'" != "" {
				if `true' > `anything' {
					scalar `estimate' = sqrt(`true'/`anything') + sqrt(sqrt(`true'/`anything') * (sqrt(`true'/`anything') - 1))
				}
				else scalar `estimate' = (sqrt(`anything') + sqrt(sqrt(`anything') * (sqrt(`anything') - sqrt(`true')))) / sqrt(`true')

				if `true' > `anything' & "`lcl'" != "" {
					local ll = sqrt(`true'/`lcl') + sqrt(sqrt(`true'/`lcl') * (sqrt(`true'/`lcl') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (sqrt(`lcl') + sqrt(sqrt(`lcl') * (sqrt(`lcl') - sqrt(`true')))) / sqrt(`true')
				}
				if `true' > `anything' & "`ucl'" != "" {
					local ul = sqrt(`true'/`ucl') + sqrt(sqrt(`true'/`ucl') * (sqrt(`true'/`ucl') - 1))
				}
				else if "`ucl'" != "" {
					local ul = (sqrt(`ucl') + sqrt(sqrt(`ucl') * (sqrt(`ucl') - sqrt(`true')))) / sqrt(`true')
				}

			} // end >1

			// if point estimate <= 1 & rare
			else if inrange(`anything',0, 1) & "`common'" == "" {
				if `true' < `anything' {
					scalar `estimate' = (`anything'/`true') + sqrt((`anything'/`true') * ((`anything'/`true') - 1))
				}
				else scalar `estimate' = (1/`anything' + sqrt(1/`anything' * (1/`anything' - 1/`true'))) / (1/`true')

				if `true' < `anything' & "`lcl'" != "" {
					local ll = (`lcl'/`true') + sqrt((`lcl'/`true') * ((`lcl'/`true') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (1/`lcl' + sqrt(1/`lcl' * (1/`lcl' - 1/`true'))) / (1/`true')
				}
				if `true' < `anything' & "`ucl'" != "" {
					local ul = (`ucl'/`true') + sqrt((`ucl'/`true') * ((`ucl'/`true') - 1))
				}
				else if "`ucl'" != "" {
					local ul = (1/`ucl' + sqrt(1/`ucl' * (1/`ucl' - 1/`true'))) / (1/`true')
				}
			} // end <=1

			// if point estimate > 1 & common
			else if `anything' > 1 & "`common'" == "" {
				if `true' > `anything' {
					scalar `estimate' = (`true'/`anything') + sqrt((`true'/`anything') * ((`true'/`anything') - 1))
				}
				else scalar `estimate' = (`anything' + sqrt(`anything' * (`anything' - `true'))) / `true'

				if `true' > `anything' & "`lcl'" != "" {
					local ll = (`true'/`lcl') + sqrt((`true'/`lcl') * ((`true'/`lcl') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (`lcl' + sqrt(`lcl' * (`lcl' - `true'))) / `true'
				}
				if `true' > `anything' & "`ucl'" != "" {
					local ul = (`true'/`ucl') + sqrt((`true'/`ucl') * ((`true'/`ucl') - 1))
				}
				else if "`ucl'" != "" {
					local ul = (`ucl' + sqrt(`ucl' * (`ucl' - `true'))) / `true'
				}
			} // end >1

		} // end OR

		*******************
		**  hazard ratio **
        *******************
        else if "`estype'" == substr("hr", 1, max(2,`lcmd')) {

			// Conversion if prevalence > 15% (common)
			if "`common'" != "" {
				local anything = (1 - 0.5^sqrt(`anything')) / ( 1 - 0.5^sqrt(1/`anything'))
				local true = (1 - 0.5^sqrt(`true')) / ( 1 - 0.5^sqrt(1/`true'))

				if "`lcl'" != "" {
					local lcl = (1 - 0.5^sqrt(`lcl')) / ( 1 - 0.5^sqrt(1/`lcl'))
				}
				if "`ucl'" != "" {
					local ucl = (1 - 0.5^sqrt(`ucl')) / ( 1 - 0.5^sqrt(1/`ucl'))
				}
			}
			// if point estimate <= 1
			if inrange(`anything',0, 1) {
				if `true' < `anything' {
					scalar `estimate' = (`anything'/`true') + sqrt((`anything'/`true') * ((`anything'/`true') - 1))
				}
				else scalar `estimate' = (1/`anything' + sqrt(1/`anything' * (1/`anything' - 1/`true'))) / (1/`true')

				if `true' < `anything' & "`lcl'" != "" {
					local ll = (`lcl'/`true') + sqrt((`lcl'/`true') * ((`lcl'/`true') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (1/`lcl' + sqrt(1/`lcl' * (1/`lcl' - 1/`true'))) / (1/`true')
				}
				if `true' < `anything' & "`ucl'" != "" {
					local ul = (`ucl'/`true') + sqrt((`ucl'/`true') * ((`ucl'/`true') - 1))
				}
				else if "`ucl'" != "" {
						local ul = (1/`ucl' + sqrt(1/`ucl' * (1/`ucl' - 1/`true'))) / (1/`true')
				}
			} // end <=1

			// if point estimate > 1
			else if `anything' > 1  {
				if `true' > `anything' {
					scalar `estimate' = (`true'/`anything') + sqrt((`true'/`anything') * ((`true'/`anything') - 1))
				}
				else scalar `estimate' = (`anything' + sqrt(`anything' * (`anything' - `true'))) / `true'

				if `true' > `anything' & "`lcl'" != "" {
					local ll = (`true'/`lcl') + sqrt((`true'/`lcl') * ((`true'/`lcl') - 1))
				}
				else if "`lcl'" != "" {
					local ll = (`lcl' + sqrt(`lcl' * (`lcl' - `true'))) / `true'
				}
				if `true' > `anything' & "`ucl'" != "" {
					local ul = (`true'/`ucl') + sqrt((`true'/`ucl') * ((`true'/`ucl') - 1))
				}
				else if "`ucl'" != "" {
					local ul = (`ucl' + sqrt(`ucl' * (`ucl' - `true'))) / `true'
				}
			} // end >1

		} // end HR

		***********************************
		**  Standardized mean difference **
        ***********************************
		else if "`estype'" == substr("smd", 1, max(3,`lcmd')) {

			// Conversions to rr
			if "`se'" != "" {
				if `se' < 0 {
					di as err "se cannot be negative"
					exit 411
				}
				local lcl = exp( 0.91 * `anything' - 1.78 * `se' )
				local ucl = exp( 0.91 * `anything' + 1.78 * `se' )
			}
			local anything = exp(0.91 * `anything')
			local true = exp(0.91 * `true')

			// if point estimate <= 1
			if `anything' <= 1 {
				if `true' < `anything' {
					scalar `estimate' = (`anything'/`true') + sqrt((`anything'/`true') * ((`anything'/`true') - 1))
				}
				else scalar `estimate' = (1/`anything' + sqrt(1/`anything' * (1/`anything' - 1/`true'))) / (1/`true')

				if `true' < `anything' & "`se'" != "" {
					local ll = (`lcl'/`true') + sqrt((`lcl'/`true') * ((`lcl'/`true') - 1))
					local ul = (`ucl'/`true') + sqrt((`ucl'/`true') * ((`ucl'/`true') - 1))
				}
				else if "`se'" != "" {
					local ll = (1/`lcl' + sqrt(1/`lcl' * (1/`lcl' - 1/`true'))) / (1/`true')
					local ul = (1/`ucl' + sqrt(1/`ucl' * (1/`ucl' - 1/`true'))) / (1/`true')
				}
			} // end <=1

			// if point estimate > 1
			else if `anything' > 1 {
				if `true' > `anything' {
					scalar `estimate' = (`true'/`anything') + sqrt((`true'/`anything') * ((`true'/`anything') - 1))
				}
				else scalar `estimate' = (`anything' + sqrt(`anything' * (`anything' - `true'))) / `true'

				if `true' > `anything' & "`se'" != "" {
					local ll = (`true'/`lcl') + sqrt((`true'/`lcl') * ((`true'/`lcl') - 1))
					local ul = (`true'/`ucl') + sqrt((`true'/`ucl') * ((`true'/`ucl') - 1))
				}
				else if "`se'" != "" {
					local ll = (`lcl' + sqrt(`lcl' * (`lcl' - `true'))) / `true'
					local ul = (`ucl' + sqrt(`ucl' * (`ucl' - `true'))) / `true'
				}
			} // end >1

		} // end SMD

		**********************
		**  Risk difference **
        **********************
		else if "`estype'" == substr("rd", 1, max(2,`lcmd')) {

			quietly {

				tempvar bfsearch rdsearch fsearch lowsearch

				preserve
				clear

				local iz = invnorm(1-(1-`level'/100)/2)
				local n1 = `a' + `b'
				local n0 = `c' + `d'
				local N = `a' + `b' + `c' + `d'

				local f = (`n1') / (`N')
				local p1 = `a' / (`n1')
				local p0 = `c' / (`n0')
				local rd = `p1' - `p0'

				if `p1' < `p0' {
					di as err "RD < 0; please relabel the exposure such that the risk difference > 0."
					exit 198
				}

				if `rd' <= `true' {
					local rd1 = round(`rd',.0001)
					di as err " To compute the risk difference, the true value must be less than or equal to the point estimate (`rd1') "
					exit 198
				}


				local se_p0 = sqrt( `p0' * (1-`p0') / `n0' )
				local se_p1 = sqrt( `p1' * (1-`p1') / `n1' )
				local se_f = `f'*(1-`f')/`N'
				local s2_p1  = `se_p1'^2
				local s2_p0  = `se_p0'^2
				local s2_f = `se_f'^2
				local diff = `p0' * (1 - `f') - `p1' * `f'
				local low_ci = `rd' - `iz' * sqrt(`s2_p1' + `s2_p0')

				local B = ( sqrt( ( `true' + `diff' )^2 + 4 * `p1' * `p0' * `f' * (1-`f') ) - ( `true' + `diff' ) ) / (2 * `p0' * `f')
				scalar `estimate' = (`B') + sqrt((`B') * ((`B') - 1))

				local obs = 1 + ceil((`B'- 1)/`grid')
				set obs `obs'
				gen `bfsearch' = 1 + (_n - 1) * `grid'
				drop if (`bfsearch' > `B')

				gen `rdsearch' = `p1' - `p0' * `bfsearch'
				gen `fsearch' = `f' + (1- `f') / `bfsearch'
				gen `lowsearch' = `rdsearch' * `fsearch' - `iz' * sqrt((`s2_p1' + `s2_p0' * `bfsearch'^2) * `fsearch'^2 + `rdsearch'^2 * (1-(1/`bfsearch'))^2 * `s2_f' )

				sum	`bfsearch' if `lowsearch' > `true', meanonly
				local lcl = r(max)
				scalar `ci' = (`lcl') + sqrt((`lcl') * ((`lcl') - 1))

				restore
			} // end qui
		} // end RD

		******************
		* invalid command
		******************
		else {
			di as err `"unknown subcommand of {bf:evalue}: `estype'"'
			exit 198
		}

		******************************************************************
		// Presenting E-values for point estimate and confidence interval
		******************************************************************
		di as txt "   E-value (point estimate): " as result %5.3f `estimate'

		*************
		// CI For SMD
		*************
		if "`estype'" == substr("smd", 1, max(3,`lcmd')) {
			if "`se'" != "" {
				if `anything' <= 1 {
					if `true' <= `anything' {
						if `ll' ==. scalar `ci' = 1
						else scalar `ci' = `ll'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
					else if `true' > `anything' {
						if `ul' ==. scalar `ci' = 1
						else scalar `ci' = `ul'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				} // <=1

				if `anything' > 1 {
					if `true' <= `anything' {
						if `ll' ==. scalar `ci' = 1
						else scalar `ci' = `ll'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
					else if `true' > `anything' {
						if `ul' ==. scalar `ci' = 1
						else scalar `ci' = `ul'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				} // >1
			}	// end if se != ""
		} // end smd

		*************
		// CI For RD
		*************

		else if "`estype'" == substr("rd", 1, max(2,`lcmd')) {
			if `low_ci' <= `true' scalar `ci' = 1
			di as txt "   E-value (CI): " as result %5.3f `ci'
		}

		***********************************
		// CI for other models (RR, OR, HR)
		***********************************
		else if inlist("`estype'", substr("rr", 1, max(2,`lcmd')), substr("or", 1, max(2,`lcmd')), substr("hr", 1, max(2,`lcmd'))) {

			if `anything' <= 1 {
				if `true' == `anything' {
					if "`lcl'" != "" | "`ucl'" != "" {
						scalar `ci' = 1
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				}
				else if `true' < `anything' {
					if "`lcl'" != "" {
						if `ll' ==. scalar `ci' = 1
						else scalar `ci' = `ll'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				}
				else if `true' > `anything' {
					if "`ucl'" != "" {
						if `ul' ==. scalar `ci' = 1
						else scalar `ci' = `ul'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				}
			} // <=1
			if `anything' > 1 {
				if `true' == `anything' {
					if "`lcl'" != "" | "`ucl'" != "" {
						scalar `ci' = 1
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				}
				if `true' < `anything' {
					if "`lcl'" != "" {
						if `ll' ==. scalar `ci' = 1
						else scalar `ci' = `ll'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				}
				else if `true' > `anything' {
					if "`ucl'" != "" {
						if `ul' ==. scalar `ci' = 1
						else scalar `ci' = `ul'
						di as txt "   E-value (CI): " as result %5.3f `ci'
					}
				}
			} // >1
		} // end estype not SMD

		**********************
		// Generate figure
		**********************
		if `"`figure'`figure2'"' != "" {

		  quietly {
			preserve
			clear

			tempvar x y c

			** RR, SMD, OR/HR with rare outcomes
			if "`estype'" == substr("rr", 1, max(2,`lcmd')) | "`estype'" == substr("hr", 1, max(2,`lcmd')) ///
				| "`estype'" == substr("or", 1, max(2,`lcmd')) & "`common'" == "" | "`estype'" == substr("smd", 1, max(3,`lcmd')) {

				* for estimate
				local B = `anything' / `true'
				if `B' < 1 local B = 1/`B'

				* for CI
				if `anything' < 1 & "`ucl'" !="" {
					local C = `ucl' / `true'
					if `C' < 1 local C = 1/`C'
				}
				if `anything' > 1 & "`lcl'" !="" {
					local C = `lcl' / `true'
					if `C' < 1 local C = 1/`C'
				}

			} // end RR, SMD, OR/HR with rare outcomes

			** OR with common outcomes
			if "`estype'" == substr("or", 1, max(2,`lcmd')) & "`common'" != "" {

				* for estimate
				local B = sqrt(`anything' / `true')
				if `B' < 1 local B = 1/`B'

				* for CI
				if `anything' < 1 & "`ucl'" !="" {
					local C = sqrt(`ucl' / `true')
					if `C' < 1 local C = 1/`C'
				}
				if `anything' > 1 & "`lcl'" !="" {
					local C = sqrt(`lcl' / `true')
					if `C' < 1 local C = 1/`C'
				}

			} // end OR with common outcomes


			** RD
			if "`estype'" == substr("rd", 1, max(2,`lcmd')) {

				* for estimate
				local B = `B'
				if `B' < 1 local B = 1/`B'

				* for CI
				local C = `lcl'

			}

			local E = round(`estimate', 0.01)
			local xmin = 1
			local xmax = `E' * 3

			local grid = 0.01
			local obs = 1 + ceil((`xmax'- 1)/`grid')
			set obs `obs'
			gen `x' = `xmin' + (_n - 1) * `grid'
			gen `y' = (`B' * (1 - `x'))/(`B' - `x')


			if  "`C'" !="" & `ci' != 1 {

				local CI = round(`ci', 0.01)
				gen `c' = (`C' * (1 - `x'))/(`C' - `x')

				* if CI is available, then plug these lines into twoway code
				local cline (line `c' `x' if inrange(`c', `xmin',`xmax'))
				local cscati (scatteri `CI' `CI' (2) "E-value (CI): (`CI', `CI')", mlabgap(*3))

			}

			* Plot it
			tw(line `y' `x' if inrange(`y', `xmin',`xmax')) ///
				`cline'  ///
				`cscati' ///
				(scatteri `E' `E' (2) "E-value: (`E', `E')", mlabgap(*3)), ///
				ytitle(Risk ratio for confounder-outcome relationship) xtitle(Risk ratio for exposure-confounder relationship) ///
				legend(off) `figure2'


			restore

		  } // end quietly
		} // end figure

		******************
		// Return results
		******************
		return scalar eval_est = `estimate'
  		if `ci' != . {
			return scalar eval_ci = `ci'
		}
end