*! NJC 1.5.1 13 October 1999
program def mdensity, rclass
    version 6.0
    syntax varlist [if] [in] [fw aw], [ AT(varname) N(integer 50) /*
    */ BY(varname) MISSing Width(numlist >=0) Range(numlist asc min=2 max=2) /*
    */ LOG LOGIT a(real 0) b(real 1) Zero BIweight COSine EPan GAUss /*
    */ RECtangle PARzen TRIangle L1title(str) Intensity * ]

    tokenize `varlist'
    local nvars : word count `varlist'

    if "`by'" != "" & `nvars' > 1 {
        di in r "too many variables specified"
        exit 103
    }

    if "`log'" != "" & "`logit'" != "" {
    	di in r "must specify only one of log and logit"
	exit 198
    }

    if "`width'" == "" { local width 0 }
    local nw : word count `width'

    tempvar touse
    mark `touse' `if' `in'
    if "`missing'" == "" {
        if "`by'" != "" { markout `touse' `by', strok }
    }
    else {
        if "`by'" == "" { di in bl "missing only applies with by( )" }
    }

    if "`at'" == "" {
    	if "`range'" != "" {
	    local min : word 1 of `range'
	    local max : word 2 of `range'
	}
	else {
    	    su `1' if `touse', meanonly
	    local min = r(min)
	    local max = r(max)
    	    local i = 2
	    while `i' <= `nvars' {
		su ``i'' if `touse', meanonly
		local min = min(`min',r(min))
		local max = max(`max',r(max))
		local i = `i' + 1
	    }
	}
        tempvar at
	if `n' <= 1 { local n = 50 }
	if `n' > _N {
	    local n = _N
	    di in g "n( ) set to `n'"
	}
	qui range `at' `min' `max' `n'
	if `nvars' == 1 { _crcslbl `at' `1' }
	else label var `at' "`varlist'"
    }

    if "`log'" != "" {
    	tempvar logat
	qui gen `logat' = log(`at')
	local what "`logat'"
    }
    else if "`logit'" != "" {
    	tempvar logitat
	qui gen `logitat' = log((`at' -`a')/(`b' - `at'))
	local what `logitat'
	local numer = `b' - `a'
    }
    else local what "`at'"

    if "`by'" == "" { /* no `by' option */
    	if `nw' < `nvars' {
	    if `nw' == 1 { local width : di _dup(`nvars') "`width' " }
            else {
	        local nextra = `nvars' - `nw'
	        local extra : di _dup(`nextra') " 0"
	        local width "`width'`extra'"
	    }
	}

        local i 1
        qui while `i' <= `nvars' {
            tempvar d`i'
	    if "`log'" != "" {
	    	tempvar log`i'
		gen `log`i'' = log(``i'')
		local which "`log`i''"
	    }
	    else if "`logit'" != "" {
	    	tempvar logit`i'
		gen `logit`i'' = log((``i'' - `a')/(`b' - ``i''))
		local which "`logit`i''"
	    }
	    else local which "``i''"
            local w : word `i' of `width'
	    kdensity `which' if `touse' [`weight' `exp'], /*
        */ `biweight' `cosine' `epan' `gauss' `rectangle' `parzen' /*
	*/ `triangle' width(`w') nograph gen(`d`i'') at(`what')
	    local widths "`widths'`r(width)' "
	    local ns "`ns'`r(n)' "
	    local scales "`scales'`r(scale)' "
	    if "`log'" != "" { replace `d`i'' = `d`i'' / `at' }
	    else if "`logit'" != "" {
	        replace `d`i'' = (`d`i'' * `numer') / ((`at' - `a') * (`b' - `at'))
	    }
	    if "`intensity'" != "" {
	        count if `touse' & `which' < .
	        replace `d`i'' = `d`i'' *  r(N)
	    }
	    if "`zero'" == "" { replace `d`i'' = . if `d`i'' == 0 }
	    _crcslbl `d`i'' ``i''
            local dlist "`dlist'`d`i'' "
            local i = `i' + 1
        }

        if `"`l1title'"' == `""' {
            if `nvars' == 1 {
	        local l1title : variable label `varlist'
		if `"`l1title'"' == `""' { local l1title "`varlist'" }
		if "`intensity'" != "" {
			local l1title `"Intensity of `l1title'"'
		}
		else local l1title `"Density of `l1title'"'
	    }
            else if length("`varlist'") < 25 {
	    	if "`intensity'" != "" {
			local l1title `"Intensity of `varlist'"'
		}
                else local l1title "Density of `varlist'"
            }
            else if "`intensity'" != "" {
	    	local l1title "Intensity"
	    }
	    else local l1title "Density"
        }
    }

    else { /* by( ) */
    	tempvar group
        sort `touse' `by'
        qui by `touse' `by': gen byte `group' = _n == 1 if `touse'
        qui replace `group' = sum(`group')
        local ng = `group'[_N]
        local bylab : value label `by'
        local vallab : value label `varlist'

	if `nw' < `ng' {
	    if `nw' == 1 { local width : di _dup(`ng') "`width' " }
            else {
		local nextra = `ng' - `nw'
		local extra : di _dup(`nextra') " 0"
		local width "`width'`extra'"
            }
	}

	if "`log'" != "" {
	    	tempvar logvar
		qui gen `logvar' = log(`varlist')
		local which "`logvar'"
        }
	else if "`logit'" != "" {
		tempvar lgtvar
		qui gen `lgtvar' = log((`varlist' - `a')/(`b' - `varlist'))
		local which "`lgtvar'"
	}
        else local which "`varlist'"

        local i 1
        qui count if !`touse'
        local j = 1 + r(N)
        qui while `i' <= `ng' {
            tempvar d`i'
	    local w : word `i' of `width'
	    kdensity `which' if `group' == `i' [`weight' `exp'] , /*
        */ `biweight' `cosine' `epan' `gauss' `rectangle' `parzen' /*
	*/ `triangle' width(`w') nograph gen(`d`i'') at(`what')
            local widths "`widths'`r(width)' "
	    local ns "`ns'`r(n)' "
	    local scales "`scales'`r(scale)' "
	    sort `touse' `by' /* -kdensity- 2.3.3 often resorts */
	    if "`log'" != "" { replace `d`i'' = `d`i'' / `at' }
            else if "`logit'" != "" {
	        replace `d`i'' = (`d`i'' * `numer') / ((`at' - `a') * (`b' - `at'))
	    }
	    count if `group' == `i'
	    local n = r(N)
	    if "`intensity'" != "" { replace `d`i'' = `d`i'' * `n' }
	    if "`zero'" == "" { replace `d`i'' = . if `d`i'' == 0 }
            local dlist "`dlist' `d`i''"
            local byval = `by'[`j']
            if "`bylab'" != "" { local byval : label `bylab' `byval' }
            label var `d`i'' `"`byval'"'
            if "`vallab'" != "" { label val `d`i'' `vallab' }
            local j = `j' + `n'
            local i = `i' + 1
        }

        if `"`l1title'"' == `""' {
            local l1title : variable label `varlist'
            if `"`l1title'"' == `""' { local l1title "`varlist'" }
            if length(`"`l1title'"') < 25 {
	    	if "`intensity'" != "" {
		    local l1title `"Intensity of `l1title'"'
		}
                else local l1title `"Density of `l1title'"'
            }
	    else if "`intensity'" != "" { local l1title "Intensity" }
	    else local l1title "Density"
        }
   }

   gra `dlist' `at' , l1(`"`l1title'"') `options'
   local widths = trim("`widths'")
   local ns = trim("`ns'")
   local scales = trim("`scales'")
   return local widths "`widths'"
   return local ns "`ns'"
   return local scales "`scales'"
end