*! version 1.6.1 22Aug2005 - renamed to prgen1 - see prgen with CIs
*! version 1.6.0 1/17/01

capture program drop prgen1
program define prgen1, rclass
    version 6
    tempname temp inc xval addbase tobase tobase2

*=> classify each valid type of model
    if "`e(cmd)'"=="cloglog"  { local io = "typical binary" }
    if "`e(cmd)'"=="cnreg"    { local io = "typical tobit" }
    if "`e(cmd)'"=="fit"      { local io = "typical regress" }
    if "`e(cmd)'"=="gologit"  { local io = "typical ordered" }
    if "`e(cmd)'"=="intreg"   { local io = "typical tobit" }
    if "`e(cmd)'"=="logistic" { local io = "typical binary" }
    if "`e(cmd)'"=="logit"    { local io = "typical binary" }
    if "`e(cmd)'"=="mlogit"   { local io = "typical nominal" }
    if "`e(cmd)'"=="nbreg"    { local io = "typical count" }
    if "`e(cmd)'"=="ologit"   { local io = "typical ordered" }
    if "`e(cmd)'"=="oprobit"  { local io = "typical ordered" }
    if "`e(cmd)'"=="poisson"  { local io = "typical count" }
    if "`e(cmd)'"=="probit"   { local io = "typical binary" }
    if "`e(cmd)'"=="regress"  { local io = "typical regress" }
    if "`e(cmd)'"=="tobit"    { local io = "typical tobit" }
    if "`e(cmd)'"=="zinb"     { local io = "twoeq count" }
    if "`e(cmd)'"=="zip"      { local io = "twoeq count" }

    if "`io'"=="" {
        di
        di in r "prgen1 does not work for the last type of model estimated."
        exit
    }
    local input : word 1 of `io'   /* input routine to _pepred */
    local output : word 2 of `io'  /* output routine */

*=> get info about variables
    _perhs
    local nrhs = `r(nrhs)'
    local rhsnms "`r(rhsnms)'"
    if "`input'"=="twoeq" {
        local nrhs2 = `r(nrhs2)'
        local rhsnms2 "`r(rhsnms2)'"
    }
    *get info from pecats if depvar not continuous
    if "`output'" != "regress" & "`output'" != "tobit" {
        _pecats
        local ncats = r(numcats)
        local catnms8 `r(catnms8)'
        local catvals `r(catvals)'
        local catnms `r(catnms)'
    }

*=> decode specified input
    syntax [varlist(numeric min=1 max=1)] [if] [in] /*
    */ , Generate(string) [x(passthru) Rest(passthru) /*
    */ Level(passthru) MAXcnt(passthru) all /*
    */ Brief noBAse Ncases(integer 11) Inteff(varname numeric) /*
    */ From(real -867.5309) To(real 867.5309) ]

    *get root() for generating new variables
    local root = substr("`generate'",1,29)
    cap version 7
    if _rc != 0 {
        local root = substr("`generate'",1,5)
    }
    version 6

    *call tobase to convert input into base values
    _pebase `if' `in', `x' `rest' `choices' `all'
    mat `tobase' = r(pebase)
    if "`input'"=="twoeq" { mat `tobase2' = r(pebase2) }

    *fix if to take e(sample) and if conditions into account
    _peife `if', `all'
    local if "`r(if)'"

    * set from and to to min and max of chngvar if unspecified
    qui sum `varlist' `if'
    if `from' == -867.5309 { local from = r(min) }
    if `to' == 867.5309 { local to = r(max) }

    * take care of from to and maxcnt
    if `from'>=`to' {
        di in r "from() must be < to()"
        exit
     }
    if `ncases' < 3 {
        di in r "ncases() must be greater than 3"
        exit 198
    }
    if `ncases' > _N { set obs `ncases' }
    sca `inc' = (`to'-`from')/(`ncases'-1)

    *locate specified variable among rhs variables
    local found "no"
    local varnum -1
    *look in main equation, if not there: varnum == -1
    local i2 = 1
    local i2_to : word count `rhsnms'
    while `i2' <= `i2_to' {
        local varchk : word `i2' of `rhsnms'
        unab varchk : `varchk', max(1)
        if "`varlist'"=="`varchk'" {
            local found "yes"
            local varnum = `i2'
            local i2 = `i2_to'
        }
        local i2 = `i2' + 1
    }
    * if zip,zinb look in inflate equation, if not there: varnum2 == -1
    if "`input'"=="twoeq" {
        local i3 = 1
        local i3_to : word count `rhsnms2'
        local varnum2 -1
        while `i3' <= `i3_to' {
            local varchk : word `i3' of `rhsnms2'
            unab varchk : `varchk', max(1)
            if "`varlist'"=="`varchk'" {
                local found "yes"
                local varnum2 = `i3'
                local i3 = `i3_to'
            }
            local i3 = `i3' + 1
        }
    } /* if "`input'"=="twoeq" */
    if "`found'"=="no" {
        di in r "`var' not rhs variable"
        exit 198
    }

*=> build PE_in matrix
    mat PE_in = `tobase'
    if `varnum' != -1 { mat PE_in[1, `varnum']=`from' }
    if "`input'"=="twoeq" {
        mat PE_in2 = `tobase2'
        if `varnum2' != -1 { mat PE_in2[1, `varnum2']=`from' }
    }
    local i = 2
    local i_to = `ncases' - 1
    while `i' <= `i_to' {
        sca `xval' = `from' + (`inc'*(`i'-1))
        *will move to PE_in later
        mat `addbase' = `tobase'
        if `varnum' != -1 { mat `addbase'[1, `varnum']=`xval' }
        mat PE_in = PE_in \ `addbase'
        if "`input'"=="twoeq" {
            mat `addbase' = `tobase2'
            if `varnum2' != -1 { mat `addbase'[1, `varnum2']=`xval' }
            mat PE_in2 = PE_in2 \ `addbase'
        }
        local i = `i' + 1
    }
    mat `addbase' = `tobase'
    if `varnum' != -1 { mat `addbase'[1, `varnum']=`to' }
    *adding addbase row to PE_in as another observation
    mat PE_in = PE_in \ `addbase'
    if "`input'"=="twoeq" {
        mat `addbase' = `tobase2'
        if `varnum2' != -1 { mat `addbase'[1, `varnum2']=`to' }
        mat PE_in2 = PE_in2 \ `addbase'
    }
    *PE_vec is vector of only the values that change from()-to()
    if `varnum' != -1 { mat PE_vec = PE_in[1..., `varnum'] }
    else{ mat PE_vec = PE_in2[1..., `varnum2'] }

*=> decode inteff: will be set to equal change variable for all observations

    if "`inteff'"!="" {
        local found "no"
        local i2 = 1
        local i2_to : word count `rhsnms'
        while `i2' <= `i2_to' {
            local varchk : word `i2' of `rhsnms'
            if "`inteff'"=="`varchk'" & `varnum' != -1 {
                local i4 = 1
                local i4_to = rowsof(PE_in)
                while `i4' <= `i4_to' {
                    mat PE_in[`i4', `i2'] = PE_in[`i4', `varnum']
                    local i4 = `i4' + 1
                }
                local found "yes"
                local i2 = `i2_to'
            }
            local i2 = `i2' + 1
        } /* while `i2' < `i2_to' */
        if "`input'"=="twoeq" {
            local i3 = 1
            local i3_to : word count `rhsnms2'
            while `i3' <= `i3_to' {
                local varchk : word `i3' of `rhsnms2'
                if "`inteff'"=="`varchk'" & `varnum2' != -1 {
                    local i4 = 1
                    local i4_to = rowsof(PE_in2)
                    while `i4' <= `i4_to' {
                        mat PE_in2[`i4', `i3'] = PE_in2[`i4', `varnum2']
                        local i4 = `i4' + 1
                    }
                    local found "yes"
                    local i3 = `i3_to'
                }
                local i3 = `i3' + 1
            }
        } /* if "`input'"=="twoeq" */

        if "`found'"=="no" {
            di in r "`var' not rhs variable"
            exit 198
        }
    } /* if "inteff"!="" */

*=> use _pepred routine to get predicted values
    _pepred, `maxcnt'
    local max_i = r(maxcount)
    *generate x values using using PE_vec defined above
    svmat PE_vec, n(`root'x)
    rename `root'x1 `root'x
    label variable `root'x "Changing value of `varlist'"

*=> BINARY MODEL
    if "`output'"=="binary" {
        mat `temp' = r(p0)
        svmat `temp', n(`root'z)
        rename `root'z1 `root'p0
        local value: word 1 of `catvals'
        local lbl: word 1 of `catnms8'
        if "`lbl'"=="`value'" { local fvalue "" }
        else { local fvalue " [`value']" }
        if "label'"!="nolabel" { label variable `root'p0 "pr(`lbl')`fvalue'" }
        else { label variable `root'p0 "pr(`value')" }
        mat `temp' = r(p1)
        svmat `temp', n(`root'z)
        rename `root'z1 `root'p1
        local value: word 2 of `catvals'
        local lbl: word 2 of `catnms8'
        if "`lbl'"=="`value'" { local fvalue "" }
        else { local fvalue " [`value']" }
        if "label'"!="nolabel" { label variable `root'p1 "pr(`lbl')`fvalue'" }
        else { label variable `root'p1 "pr(`value')" }
    } /* if "`output'"=="binary" */

*=> ORDERED/NOMINAL MODEL
    if "`output'"=="ordered" | "`output'"=="nominal" {
        local i = 1
        while `i' <= `ncats' {
            local value: word `i' of `catvals'
            local k`i': word `i' of `catvals'
            if `k`i'' < -9 | `k`i'' > 99 | int(`k`i'')!=`k`i'' {
                di in red "category values must be integers between -9 and 99"
                exit 198
            }
            if `k`i'' < 0 {
                local k`i' = abs(`k`i'')
                local k`i' = "_`k`i''"
            }
            mat `temp' = r(p`i')
            svmat `temp', n(`root'z)
            rename `root'z1 `root'p`k`i''
            local lbl: word `i' of `catnms8'
            if "`lbl'"=="`value'" { local fvalue "" }
            else { local fvalue " [`value']" }
            if "label'"!="nolabel" {
                label variable `root'p`k`i'' "pr(`lbl')`fvalue'"
            }
            else { label variable `root'p`k`i'' "pr(`value')" }
            *only cumulative probabilities for ordinal model
*            if "`output'"=="ordered" {
                if `i' == 1 { qui gen `root's`k1' = `root'p`k1' }
                else {
                    local i_min1 = `i' - 1
                    qui gen `root's`k`i'' = `root'p`k`i'' + `root's`k`i_min1''
                }
                label variable `root's`k`i'' "pr(y<=`value')"
*            }
            local i = `i' + 1
        } /* while `i' <= `ncats' */
    } /* if "`output'"=="ordered" | "`output'"=="nominal" */

*=> REGRESS/TOBIT MODEL
    if "`output'"=="regress" | "`output'"=="tobit" {
        mat `temp' = r(xb)
        svmat `temp', n(`root'z)
        rename `root'z1 `root'xb
        if "`output'"=="regress" { label variable `root'xb "y-hat" }
        if "`output'"=="tobit" { label variable `root'xb "y*" }
    }

*=> COUNT MODEL
    if "`output'"=="count" {
        mat `temp' = r(mu)
        svmat `temp', n(`root'z)
        rename `root'z1 `root'mu
        label variable `root'mu "predicted rate (mu)"
        local i = 0
        while `i' <= `max_i' {
            mat `temp' = r(p`i')
            svmat `temp', n(`root'z)
            rename `root'z1 `root'p`i'
            label variable `root'p`i' "pr(`i')"
            if `i' == 0 { qui gen `root's0 = `root'p0 }
            else {
                local i_min1 = `i' - 1
                qui gen `root's`i' = `root'p`i' + `root's`i_min1'
            }
            label variable `root's`i' "pr(y<=`value')"
            local i = `i' + 1
        } /* while `i' <= `ncats' */
        if "`input'"=="twoeq" {
            mat `temp' = r(always0)
            svmat `temp', n(`root'z)
            rename `root'z1 `root'all0
            label variable `root'all0 "pr(Always-0)"
        }
    } /* if "`output'"=="count" */

*=> COMMON OUTPUT

    if "`brief'"=="" & "`base'"!="nobase" {
        if "`inteff'"=="" {
            di _n in y "`e(cmd)'" in g ": Predicted values as " /*
            */ in y "`varlist'" in g /*
             */ " varies from " in y "`from'" in g " to " /*
             */ in y "`to'" in g "."
        }
        *add inteff varname to output if specified
        if "`inteff'"!="" {
            di _n in y "`e(cmd)'" in g ": Predicted values as " /*
            */ in w "`varlist'" in g " and " in w "`inteff'" in g /*
             */ " vary from " in w "`from'" in g " to " /*
             */ in w "`to'" in g "."
        }
        *print base values
        if "`input'"=="twoeq" {
            di _n in g "base x values for count equation: "
        }
        mat rownames `tobase' = "x="
        mat _PEtemp = `tobase'
        _peabbv _PEtemp
        mat list _PEtemp, noheader
        if "`input'"=="twoeq" {
            di _n in g "base z values for binary equation: "
            mat rownames `tobase2' = "z="
            mat _PEtemp = `tobase2'
            _peabbv _PEtemp
            mat list _PEtemp, noheader
        }
    }

end