*! 1.0.0 Ariel Linden 05Aug2022

capture program drop power_cmd_twospec
program power_cmd_twospec, rclass

version 11.0


        /* obtain settings */
		syntax anything(id="numlist"),	///
			[ Alpha(real 0.05) 		/// significance level
			n(string) 				/// total sample size
			FRACtion(real 0.5)		/// fraction of total sample assigned to test 1
			Power(string)  			///
			PREV(real 0.5)			/// prevalence of disease
			ONESIDed				///
			init(real 10)			/// initial value for estimating power
			]						///

			gettoken spec1 rest : anything
			gettoken spec2 rest : rest

			numlist "`anything'", min(2) max(2)

			if `spec1' < 0.0 | `spec1' > 1.0 {
				di as err "spec1 must be a number between 0 and 1"
				exit 198
			}

			if `spec2' < 0.0 | `spec2' > 1.0 {
				di as err "spec2 must be a number between 0 and 1"
				exit 198
			}

			if `init' < 0 {
				di as err "init() must be a positive number"
				exit 198
			}

			if `fraction' < 0.0 | `fraction' > .999 {
				di as err "fraction must be a number greater than 0 and less than 1"
				exit 198
			}


			// set default test type to "twosided"
			if "`onesided'" != "" {
				local test = `alpha'
			}
			else local test = `alpha' / 2

			tempname fract1 fract2
			scalar `fract1' = `fraction' // * the fraction of subjects that will be assigned to group 1
			scalar `fract2' = 1 - `fract1' // the fraction of subjects assigned to group 2


			*******************************
			**** compute sample size ******
			*******************************
			if (`"`n'"' == "") {

				tempname delta n1 n0 n
				scalar `delta' = `spec2' - `spec1'
				scalar `n0' = ceil(((invnorm(1-`test')*sqrt((`spec1'*`fract1'+`fract2'*`spec2')*(1-`spec1'*`fract1'-`spec2'*`fract2')*(1/`fract1'+1/`fract2')) ///
					+invnorm(`power')*sqrt(`spec2'*(1-`spec2') /`fract2'+`spec1'*(1-`spec1')/`fract1')) / (`spec2'-`spec1'))^2)
				scalar `n' = ceil(`n0' / (1 - `prev')) // (method 0) Li & Fine (2004)
				scalar `n1' = ceil(`n' - `n0')

			} // end sample size

/*
			*************************
			**** compute power ******
			*************************
			else if (`"`n'"' != "") {
				tempname delta p k s n1 n0 power
				scalar `delta' = `sens1' - `sens0'
				scalar `p' = 0
				forvalues k = 0 / `n' {
					scalar `s' = sqrt(`k' * `sens0' * (1 - `sens0')) * invnorm(1 - `test') + `k' * `sens0'
					scalar `p' = `p' + (1 - binomial(`k',`s', `sens1')) * binomialp(`n',`k',`prev')
				}
				scalar `n1' = ceil(`n' * `prev')
				scalar `n0' = ceil(`n' - `n1')
				scalar `power' = `p'
			} // end power
*/

			else if (`"`n'"' != "") {

				tempname delta n1 n0 power
				scalar `delta' = `spec2' - `spec1'

				local nlast = 0
				while `nlast' <= `n'  & `init' <= 10000 {
					scalar `n0' = ceil(((invnorm(1-`test')*sqrt((`spec1'*`fract1'+`fract2'*`spec2')*(1-`spec1'*`fract1'-`spec2'*`fract2')*(1/`fract1'+1/`fract2')) ///
						+invnorm(`init'/10000)*sqrt(`spec2'*(1-`spec2') /`fract2'+`spec1'*(1-`spec1')/`fract1')) / (`spec2'-`spec1'))^2)
					local nlast = ceil(`n0' / (1-`prev')) // (method 0) Li & Fine (2004)
					local plast `init'
					local ++init
				}  // end while

				scalar `n1' = ceil(`n' - `n0')
				scalar `power' = `plast' / 10000

			} // end power


			// saved results
			return scalar N = `n'
			return scalar N1 = `n1'
			return scalar N0 = `n0'
			return scalar alpha = `alpha'
			return scalar power = `power'
			return scalar spec1 = `spec1'
			return scalar spec2 = `spec2'
			return scalar delta = `delta'
			return scalar prev = `prev'
			return scalar fraction = `fract1'
			return scalar init = `init'

end