*!  version 0.2.0 2005-02-03 jsl
    * pe2 to pe

//  collect information and place in matrix

capture program drop _pecollect
program define _pecollect, rclass
    version 8
    tempname temp values mu xb prall0 nrhs2

    syntax , level(real) inout(string) maxcount(string) [Diff reps(int 500)]

//
// petype - global string with model type
//

    * petype is the same for the saved and current model so the
    * diff option does not need to be considered
    global petype "`e(cmd)' `inout'"
    local input : word 2 of $petype // is it a typical or twoeq model?
    local output : word 3 of $petype // what is the output type?
    local colnm1 "1values 2prob 3misc 4sav_prob 5sav_misc 6dif_prob 7dif_misc"

//
// peinfo - global matrix with numeric information about the model
//
// Row 1: current model
// Row 2: saved model
// Row 3: values for current - values for saved
//

    * level for confidence interval for current model
    local level = r(level)

    * nrhs: # of rhs variables for current model
    local colnms: colnames(PE_in)
    local nrhs: word count `colnms'
    local nrhs = `nrhs' // no _cons included

    * number of categories for current model
    if "`output'"=="count" {
        local ncat = `maxcount'+1
    }
    else if "`output'"=="regress" | "`output'"=="tobit" {
        local ncat = 1
    }
    else {
        _pecats
        local catvals = r(catvals)
        local ncat = r(numcats)
        * get back returns from _pepred
        _return restore pepred, hold
    }

    * # of rhs if zip or zinb
    local nrhs2 = .
    if "`input'"=="twoeq" {
        local colnms2: colnames(PE_in2)
        local nrhs2: word count `colnms2'
        local nrhs2 = `nrhs2' // no _cons included
    }

    * mlogit base category for current model
    local basecat = .
    if "`e(cmd)'"=="mlogit" {
        local basecat = e(basecat)
    }

    * if diff, move from row 1 into row 2 for saved model

    if "`diff'" == "diff" {

        * get data current saved
        tempname r1 r2 r3
        mat `r1' = peinfo[1,1...] // current
        mat `r2' = peinfo[2,1...] // saved
        mat `r3' = peinfo[3,1...] // diff

        * Move what had been stored in row 1 into row 2 for saved.
        * Rows 1 and 3 will be updated later.
        mat peinfo = `r1' \ `r1' \ `r3'
        matrix rownames peinfo = Current Saved Cur-Saved

    } // "`diff'" == "diff"

    * if not diff, define peinfo matrix
    if "`diff'" != "diff" {

        mat def peinfo = J(3,12,.)
        matrix rownames peinfo = Current Saved Cur-Saved
        matrix colnames peinfo = 1nrhs 2numcats 3level 4z_level ///
            5nrhs2 6nocon 7basecat 8stdp 9reps 10repsdone 11maxcount ///
            12blank

    } // "`diff'" != "diff"

    * put current data into row 1
    matrix peinfo[1,1] = `nrhs' // nrhs - columns for pebase
    matrix peinfo[1,2] = `ncat' // numcats   -- from _pecats
    matrix peinfo[1,3] = `level'*100 // level as 95 not .95
    matrix peinfo[1,4] = -invnorm((1-`level')/2) // z @ level for ci
    matrix peinfo[1,5] = `nrhs2' // nrhs2
    matrix peinfo[1,6] = . // nocon
    matrix peinfo[1,7] = `basecat' // base category for mlogit
    matrix peinfo[1,8] = . // stdp for binary model
    matrix peinfo[1,9] = `reps' // requested # of replications for bootstrap
    matrix peinfo[1,10] = . // completed # of replications for bootstrap
                             // this will be added after _peciboot is called
    matrix peinfo[1,11] = `maxcount'

    * if diff, put current-saved into row 3
    if "`diff'" == "diff" {

        tempname r1 r2 r3
        mat `r1' = peinfo[1,1...] // current
        mat `r2' = peinfo[2,1...] // saved
        mat `r3' = `r1' - `r2'

        * move current into saved
        mat peinfo = `r1' \ `r2' \ `r3'
        matrix rownames peinfo = Current Saved Cur-Saved

    } // "`diff'" == "diff"

//
//  pebase and pebase2 - global matrices with base values
//

    * if diff option, row 1 initially contains values for saved model
    if "`diff'" == "diff" {
        tempname basesave basesave2
        mat `basesave' = pebase[1,1...]
        if "`input'" == "twoeq" {
            mat `basesave2' = pebase2[1,1...]
        }
    }

    * fill in with two blank rows for later saved and dif values
    mat pebase = PE_in \ J(1,`nrhs',.) \ J(1,`nrhs',.)
    matrix rownames pebase = Current Saved Cur-Saved

    if "`input'" == "twoeq" {
        * fill in with two blank rows for later saved and dif values
        mat pebase2 = PE_in2 \ J(1,`nrhs2',.) \ J(1,`nrhs2',.)
        matrix rownames pebase2 = Current Saved Cur-Saved
    }

    * if diff, compute difference
    if "`diff'" == "diff" {
        tempname dif
        mat `dif' = pebase[1,1...] - `basesave'
        mat pebase = PE_in \ `basesave' \ `dif'
        matrix rownames pebase = Current Saved Cur-Saved
        mat `basesave' = pebase
        if "`input'" == "twoeq" {
            mat `dif' = pebase2[1,1...] - `basesave2'
            mat pebase2 = PE_in2 \ `basesave2' \ `dif'
            matrix rownames pebase2 = Current Saved Cur-Saved
        }
    }

//
//  pepred: global matrix with predictions
//

    * missing by default
    scalar `xb' = .
    scalar `mu' = .
    scalar `prall0' = .

    * info on mu for count models
    if "`output'"=="count" {
        mat `temp' = r(mu)
        scalar `mu' = `temp'[1,1]
    }
    if  "`e(cmd)'"=="poisson" ///
        | "`e(cmd)'"=="nbreg" {
        mat `temp' = r(xb)
        scalar `xb' = `temp'[1,1]
    }
    * info on zip and zinb
    if "`input'"=="twoeq" {
        scalar `xb' = log(`mu')
        mat `temp' = r(always0)
        scalar `prall0' = `temp'[1,1]
    }

    * get xb for models with a single xb
    if "`output'"=="binary" ///
        | "`output'"=="regress" ///
        | "`output'"=="tobit" ///
        | "`output'"=="ordered" {
        mat `temp' = r(xb)
        scalar `xb' = `temp'[1,1]
    }

//  pepred: if diff, move information for saved model

    if "`diff'" == "diff" {

        tempname r1 r2 r3 r4 r5 r6 r7
        foreach r in 1 2 3 4 5 6 7 {
            mat `r`r'' = pepred[`r',1...]
        }

        * move what had been current into saved rows
        mat pepred = `r1' \ `r2' \ `r3' \ `r2' \ `r3' \ `r6' \ `r7'
        matrix rownames pepred = ///
            1values 2prob 3misc 4sav_prob 5sav_misc 6dif_prob 7dif_misc

    } // "`diff'" == "diff"

//  pepred: if not diff, create matrix to hold predictions

    if "`diff'" != "diff" {

        mat def pepred = J(7,`ncat',.)
        matrix rownames pepred = ///
            1values 2prob 3misc 4sav_prob 5sav_misc 6dif_prob 7dif_misc
        * routines computing ci add values to peupper pelower matrices
        mat def peupper = pepred
        mat def pelower = pepred

    } // "`diff'" != "diff"

//  if diff, put current into saved for peupper and lower

    if "`diff'"=="diff" {

        local mset "upper lower"
        local method = word("$pecimethod",1)
        if "`method'"=="bootstrap" {
            local mset "upper lower upnorm lonorm upbias lobias"
        }
        foreach m in `mset' {
            * get saved rows
            foreach r in 1 2 3 4 5 6 7 {
               tempname row`r'
                mat `row`r'' = pe`m'[`r',1...]
            }
            * move current into saved
            mat pe`m' = `row1' \ `row2' \ `row3' \ `row2' \ `row3' \ `row6' \ `row7'

        } // matrix

    } // "`diff'"=="diff"

//  pepred: put information on current model into pepred

    if "`output'"=="binary" {

        * outcome values
        mat pepred[1,1] = 0
        mat pepred[1,2] = 1

        mat `temp' = r(p0)
        mat pepred[2,1] = `temp'[1,1]
        mat `temp' = r(p1)
        mat pepred[2,2] = `temp'[1,1]
        mat pepred[3,1] = `xb'
        mat `temp' = r(stdp)
        mat peinfo[1,8] = `temp'[1,1]

        mat `temp' = r(p0_lo)
        * due to error in _pepred, r(p0_lo) is really upper limit
        mat peupper[2,1] = `temp'[1,1]
        mat `temp' = r(p0_hi)
        mat pelower[2,1] = `temp'[1,1]
        mat `temp' = r(p1_hi)
        mat peupper[2,2] = `temp'[1,1]
        mat `temp' = r(p1_lo)
        mat pelower[2,2] = `temp'[1,1]

        mat `temp' = r(xb_hi)
        mat peupper[3,1] = `temp'[1,1]
        mat `temp' = r(xb_lo)
        mat pelower[3,1] = `temp'[1,1]

    }

    if "`output'"=="tobit" ///
        | "`output'"=="regress" {

        mat pepred[1,1] = . // value
        mat pepred[2,1] = . // predicted probability
        mat pepred[3,1] = `xb'
        mat `temp' = r(xb_lo)
        mat pelower[3,1] = `temp'[1,1]
        mat `temp' = r(xb_hi)
        mat peupper[3,1] = `temp'[1,1]
        mat `temp' = r(stdp)
        mat peinfo[1,8] = `temp'[1,1]
    }

    if "`output'"=="ordered"  { // also works for mlogit
        mat `temp' = r(stdp)
        mat peinfo[1,8] = `temp'[1,1]
        mat `temp' = r(xb_hi)
        mat peupper[3,1] = `temp'[1,1]
        mat `temp' = r(xb_lo)
        mat pelower[3,1] = `temp'[1,1]
        forval i=1/`ncat' {
            local v : word `i' of `catvals'
            mat pepred[1,`i'] = `v'
            mat `temp' = r(p`i')
            mat pepred[2,`i'] = `temp'[1,1]
        }
        mat pepred[3,1] = `xb'
    }

    if "`e(cmd)'"=="gologit" | "`e(cmd)'"=="mlogit" {
        forval i=1/`ncat' {
            local v : word `i' of `catvals'
            mat pepred[1,`i'] = `v'
            mat `temp' = r(p`i')
            mat pepred[2,`i'] = `temp'[1,1]
            mat pepred[2,`i'] = `temp'[1,1]
            if `i' != `ncat' {
                mat `temp' = r(xb`i')
                mat pepred[3,`i'] = `temp'[1,1]
            }
        }
    }

    if "`e(cmd)'"=="poisson" ///
        | "`e(cmd)'"=="nbreg" ///
        | "`e(cmd)'"=="zip" ///
        | "`e(cmd)'"=="zinb"  {

        * labels for headers
        forval i=1/`ncat' {
            local im1 = `i' - 1
            mat pepred[1,`i'] = `im1' // numbers 0 to ncat-1
            mat `temp'=r(p`im1')
            mat pepred[2,`i'] = `temp'[1,1]
        }
        mat pepred[3,1] = `xb'
        mat pepred[3,2] = `mu'
        mat `temp' = r(stdp)
        mat peinfo[1,8] = `temp'[1,1]
        mat `temp' = r(mu_hi)
        mat peupper[3,1] = `temp'[1,1]
        mat `temp' = r(mu_lo)
        mat pelower[3,1] = `temp'[1,1]
        if "`input'"=="twoeq" {
            mat pepred[3,4] = `prall0'
        }
    }

//  pepred: if diff, move info on saved model into row 2,
//  and current - saved into row 3

    if "`diff'"=="diff" {
        * get saved rows
        tempname r1 r2 r3 r4 r5 r6 r7
        foreach r in 1 2 3 4 5 6 7 {
            mat `r`r'' = pepred[`r',1...]
        }
        * compute current minus saved
        mat `r6' = `r2' - `r4' // cur-saved prob
        mat `r7' = `r3' - `r5' // cur-saved misc values
        * move current into saved
        mat pepred = `r1' \ `r2' \ `r3' \ `r4' \ `r5' \ `r6' \ `r7'
        matrix rownames pepred = ///
            1values 2prob 3misc 4sav_prob 5sav_misc 6dif_prob 7dif_misc
    } // "`diff'"=="diff"

//  pepred: if diff, move info on saved model into row 2,
//  and current - saved into row 3

    if "`diff'"=="diff" {
        * get saved rows
        tempname r1 r2 r3 r4 r5 r6 r7
        foreach r in 1 2 3 4 5 6 7 {
            mat `r`r'' = pepred[`r',1...]
        }
        * compute current minus saved
        mat `r6' = `r2' - `r4' // cur-saved prob
        mat `r7' = `r3' - `r5' // cur-saved misc values
        * move current into saved
        mat pepred = `r1' \ `r2' \ `r3' \ `r4' \ `r5' \ `r6' \ `r7'
        matrix rownames pepred = ///
            1values 2prob 3misc 4sav_prob 5sav_misc 6dif_prob 7dif_misc
    } // "`diff'"=="diff"

//  ADD CATEGORY NUMBERS TO FIRST ROW

    tempname r1 r2 r3
    mat `r1' = pepred[1,1...]
    mat `r2' = peupper[2...,1...]
    mat `r3' = pelower[2...,1...]
    mat peupper = `r1' \ `r2'
    mat pelower = `r1' \ `r3'

        matrix rownames peupper = ///
            1values 2up_pr 3up_misc 4up_sav_pr ///
            5up_sav_misc 6up_dif_pr 7up_dif_misc
        matrix rownames pelower = ///
            1values 2lo_pr 3lo_misc 4lo_sav_pr ///
            5lo_sav_misc 6lo_dif_pr 7lo_dif_misc

//  INFORMATION ON WHETHER CONSTANT IS IN MODEL
    _penocon
    local temp = r(nocon)
    matrix peinfo[1,6] = `temp'

end