*! version 1.2 30mar2026
*! Ben A. Dwamena: bdwamena@umich.edu
*! midas_con2bin - Convert Continuous Test Results to 2x2 Tables
*! v1.2: fix type mismatch r(109) when id() is numeric
*! v1.1: fix variable-already-defined error; display results; leave data in memory

capture program drop midas_con2bin
program define midas_con2bin, rclass byable(recall) sortpreserve
version 9
// n1 x1 sd1 n0 x0 sd0
syntax varlist(min=6 max=6 numeric) [if] [in] , ID(string) ///
[ SAVEData(string) * ]

marksample touse, novarlist

quietly keep if `touse'

// unpack varlist
tokenize `varlist'
local n1 `1'
local x1 `2'
local sd1 `3'
local n0 `4'
local x0 `5'
local sd0 `6'

tempvar ahat bhat bvar inside nsen nspe

quietly {
    // basic binormal parameters
    gen double `ahat' = `x1' - `x0'
    gen double `bhat' = `sd1' / `sd0'
    gen double `bvar' = `bhat'^2 - 1

    // argument inside the square root
    gen double `inside' = `ahat'^2 + `bvar'*(`sd0'^2)*ln(`bhat'^2)

    // threshold
    capture drop thresh
    gen double thresh = .
    replace thresh = ((`x1'*`bvar') - `ahat' + `bhat'*sqrt(`inside')) / `bvar' ///
        if `bhat' != 1 & `inside' > 0

    // fallback: equal variances or numerically problematic case
    replace thresh = (`x1' + `x0')/2 if `bhat' == 1 | `inside' <= 0

    // implied sensitivity and specificity under binormal model
    gen double `nsen' = 1 - normal((thresh - `x1')/`sd1')
    gen double `nspe' = normal((thresh - `x0')/`sd0')

    // convert to integer counts
    capture drop tp fn tn fp
    gen tp = int(`n1'*`nsen')
    gen fn = int(`n1' - tp)
    gen tn = int(`n0'*`nspe')
    gen fp = int(`n0' - tn)
}

// display results
di as txt _n "{hline 60}"
di as txt "  con2bin: Continuous to 2x2 table conversion"
di as txt "  Studies: " as res _N
di as txt "{hline 60}"
list `id' tp fp fn tn, noobs separator(0)
di as txt "{hline 60}"

if "`savedata'" != "" {
    quietly {
        capture drop studyid
        // Handle both string and numeric ID variables
        capture confirm string variable `id'
        if _rc == 0 {
            gen str80 studyid = `id'
        }
        else {
            gen studyid = `id'
        }
        preserve
        keep studyid tp fp fn tn
        save "`savedata'", replace
        restore
    }
    di as txt "  Saved to: " as res "`savedata'"
}

return scalar N = _N
end