*! version 0.5.1 jsl 2010-10-24
* gridwidth to gridxwidth
*  2010-10-24 pvdata to pvdata4
* version 0.5.0 jsl 2010-02-12

// = TO DO pvplot.ado ====================================================
//
//  DO 1:   currently lines from lower categories are on top of higher;
//          PVI works the opposite. Can this be changed?
//
//  DO 2:   find way to get rid of the comma
//
//  DO 3:   If command is number, find a way to record that drop was used
//          to drop an option in interactive mode
//
//  DO 6: with auto(#) allow sort in reverse order
//

// = NOTES ==============================================================
//
// 1) To drop an existing string option, use drop as the entered
//         string colvar(drop)
//
// 2) To drop number options, enter -99
//

/* == NOTATION used in code ==================================================

HIDE/SHOW
    hideC   hide color
    hideI   hide intensity

ITEMS
    itemNM - item names
    itemK - item # of items
    itemC - # of categoreis

    itemSTx - name of variable with start x-coord of item
    itemENx - name of variable with end x-coord of item

CATEGORIES
    catK - # of categories
    catMAX
    catMIN
    catSTy      - name of variable with start y-coord for category
    catENy      - name of variable with end y-coord for category
    catSTyoff   - name of variable with start y-coord offset for category
    catENyoff   - name of variable with end y-coord offset for category

INTENSITY
    intNM   - name of intensity variable
    intV    - intensity values
    intON   - intensity is being used
    intMAX  - max of intensity variable
    intMIN  - min ...
    intK    - # of categories
    intSET  - set of intensities

COLORS
    clrNM   - name of color variable
    clrI    - color intensity
    clrISET - set of color intensity
    clrV    - color values
    clrVSET - set of color values
    clrK    - # of categories in clrNM
    clrMIN  - min cat of color var
    clrMAX

DELTA
    delta

GRID
    gridC color
    gridXW width
    gridYW width
    gridS space
    gridX x locations of grid
    gridY y locations of grid
    gridYMAX max location of y
    gridXMAX
    gridYMIN
    gridXMIN

PLOT COMMANDS ARE BUILD USING THESE LOCALS
    Pgrid
    Pxyline
    Pxaxis
    Pyaxis

PATHS
    matrix catitemN # of paths for row category and column item
    matrix catMAXN  max # of paths in that category

============================================================================ */

//  globals
//
//  pvinteractive : 1 if existing graph is being modified in interactive mode
//  pvexportnum :   # of export graph
/*
    pvhideC         "`hideC'"
    pvhideC         "`hideC'"
    pvcolors        "`colors'"
    pvcolvar        "`colvar'"
    pvcolintensity  "`colintensity'"
    pvintensity     "`intensity'"
    pvintvar        "`intvar'"
    pvshowif        "`showif'"
    pvhideif        "`hideif'"
    pvhidecolor     "`hidecolor'"
    pvhideintensity "`hideintensity'"
    pvcaption       "`caption'"
    pvtitle         "`title'"
    pvsubtitle      "`subtitle'"
    pvnote          "`note'"
    pvgridcolor     "`gridcolor'"
    pvgridxwidth =   `gridxwidth'
    pvgridywidth =  `gridywidth'
    pvgridspace =   `gridspace'
    pvborder        "`border'"
    pvylaboffset =  `ylaboffset'
    pvlabelsize     "`labelsize'"
    pvpathwidth =   `pathwidth'
    pvexport        "`export'"
    pvoptions       "`options'"
    pvaspectratio = `aspectratio'
    pvdelta =       `delta'
    pvsample =      `sample'
    pvdebug         "`debug'"
    pvangle         "`angle'"
    pvintrange      "`intrange'"
    pvcolrange      "`colrange'"

VARIABLES

    _pv_showif  indicate if case is plotted

*/

capture program drop pvplot4
program define pvplot4
    version 9.2
    local qui "qui"

    syntax , ///
///     COLORS
            [COLors(string)]            /// colors for categories
            [COLVar(varname)]           /// colors vary by this variable
            [COLRange(string)]          /// start and end value of colvar;
                                        ///  only needed if colvar has gaps
            [COLIntensity(string)]      /// intensities corresponding to colors
                                        ///     such as (1 .2 .5 etc)
///     INTENSITY
            [INTensity(string)]         /// intensities corresponding to values
                                        ///     of intvar
            [INTVar(varname)]           /// variable controlling path intensity
            [INTRange(string)]          /// start and end value of colvar; only
                                        ///     needed if intvar has gaps
///     HIDDEN AND SHOWN CASES
            [SHOWIF(string)]            /// conditions for active vars; use a
                                        ///     standard stata if/in statement
            [HIDEIF(string)]            /// conditions for hide vars; use a
                                        ///     standard stata if/in statement
            [HIDEColor(string)]         /// color of hide lines (gs15 default)
            [HIDEINTensity(string)]     /// intensity of hide lines
///     TITLES
            [CAPtion(passthru)]         /// caption pass through to stata graph
            [TItle(passthru)]           /// title passthrough
            [SUBtitle(passthru)]        /// subtitle passthrough
            [note(passthru)]            /// notepassthrough
///     GRID, AXES LABELS AND BORDER
            [GRIDColor(string)]         /// color of grid - default is black
            [GRIDXWidth(real .3)]        /// width of horizontal grid line
            [GRIDYWidth(real .2)]       /// width of vertical grid line
            [GRIDSpace(integer 2)]      /// space from grid to paths
            [BORDER]                    /// add shading around graph
            [YLABOFFset(real .25)]      /// offset for ylabel offset
            [LABELSize(string)]         /// size of axes labels
                                        /// --> tiny vsmall small medsmall medium
                                        /// --> medlarge large vlarge
            [ANGLE]                     /// show labels on an angle
            [EQUAL]                     ///  use equal spacing of axes; default
                                        ///     is condensed
///     PATHS, EXPORT, ETC
            [PATHWidth(real .01)]       /// path width
            [EXport(string)]            /// name of export file
            [OPTions(string)]           /// added graph options here
            [ASPECTratio(real 1)]       /// aspect ratio
            [Delta(real -99)]           /// size of offset between lines
                                        ///     overwrites computed value
///     MISC
            [SAMPLE(integer 100)]       /// sample this percent of cases
            [DEBUG]                     /// test mode
            [TEST]                      /// test mode
            [intoff]                    /// turn off interactive mode
            [Reset]                     /// reset options (same as intoff)
            [Quietly]                   /// do not show graph
            [EXPAdd]                    // add number to export

    if "`test'"=="test" { // test and debug are equivalent
        local debug "debug"
    }

//  #1  create export increment number added to name of export file;
//      allows automatic naming of export files when interactcive mode

    * if not expadd, set export number to 0 and prior number to 0
    if "`expadd'"=="" {
        local priorexpnum = 0
        global pvexportnum = 0
    }
    * if expadd number is 1 or 1 larger
    else {
        * if no prior number, make prior 0 & current 1
        if "$pvexportnum"=="" {
            local priorexpnum = 0
            global pvexportnum = 1
        }
        * global exists so increment by 1
        else {
            local priorexpnum = $pvexportnum
            global pvexportnum = $pvexportnum + 1
        }
    }

//  #2  control interactive mode

    * reset and intoff are the same
    if "`reset'"=="reset" {
        local intoff "intoff" // interactive is off
    }
    * turn off interactive mode
    if "`intoff'"=="intoff" {
        global pvinteractive = 0 // interactive is off
    }

//  #2a - grab globals to specify options in interative mode

    if $pvinteractive==1 { // if modify current model

        * if local is null, use value in global

        if "`angle'"=="" {
            local angle "$pvangle"
        }
        if "`intrange'"=="" {
            local intrange "$pvintrange"
        }
        if "`colrange'"=="" {
            local colrange "$pvcolrange"
        }
        if "`hidecolor'"=="" {
            local hidecolor "$pvhideC"
        }
        if "`colors'" == "" {
            local colors "$pvcolors"
        }
        if "`colvar'" == "" {
            local colvar "$pvcolvar"
        }
        if "`colintensity'" == "" {
            local colintensity "$pvcolintensity"
        }
        if "`intensity'" == "" {
            local intensity "$pvintensity"
        }
        if "`intvar'" == "" {
            local intvar "$pvintvar"
        }
        if "`showif'" == "" {
            local showif "$pvshowif"
        }
        if "`hideif'" == "" {
            local hideif "$pvhideif"
        }
        if "`hidecolor'" == "" {
            local hidecolor "$pvhidecolor"
        }
        if "`hideintensity'" == "" {
            local hideintensity "$pvhideintensity"
        }
        if "`caption'" == "" {
            local caption "$pvcaption"
        }
        if `"`title'"' == "" {
            local title `"$pvtitle"'
        }
        if "`subtitle'" == "" {
            local subtitle "$pvsubtitle"
        }
        if "`note'" == "" {
            local note "$pvnote"
        }
        if "`gridcolor'" == "" {
            local gridcolor "$pvgridcolor"
        }
        if `gridywidth'==.2 {
            local gridywidth = $pvgridywidth
        }
        if `gridxwidth'==.3 {
            local gridxwidth = $pvgridxwidth
        }
        if `gridspace'==2 { // if default, use save value
            local gridspace = $pvgridspace
        }
        if "`border'" == "" {
            local border "$pvborder"
        }
        if `ylaboffset'==.25 {
            local ylaboffset = $pvylaboffset
        }
        if "`labelsize'" == "" {
            local labelsize "$pvlabelsize"
        }
        if `pathwidth'==.01 {
            local pathwidth = $pvpathwidth
        }
        if "`export'" == "" {
            local export "$pvexport"
        }
        if "`options'" == "" {
            local options "$pvoptions"
        }
        if `aspectratio'==1 {
            local aspectratio = $pvaspectratio
        }
        if `delta'==-99 {
            local delta = $pvdelta
        }
        if `sample'==100 {
            local sample = $pvsample
        }
        if "`debug'" == "" {
            local debug "$pvdebug"
        }

//  #2b to drop existing option in interactive mode, use drop

        if "`angle'"=="drop" {
            local angle ""
        }
        if "`intrange'"=="drop" {
            local intrange ""
        }
        if "`colrange'"=="drop" {
            local colrange ""
        }
        if "`hidecolor'"=="drop" {
            local hidecolor ""
        }
        if "`colors'" == "drop" {
            local colors ""
        }
        if "`colvar'" == "drop" {
            local colvar ""
        }
        if "`colintensity'" == "drop" {
            local colintensity ""
        }
        if "`intensity'" == "drop" {
            local intensity ""
        }
        if "`intvar'" == "drop" {
            local intvar ""
        }
        if "`showif'" == "drop" {
            local showif ""
        }
        if "`hideif'" == "drop" {
            local hideif ""
        }
        if "`hidecolor'" == "drop" {
            local hidecolor ""
        }
        if "`hideintensity'" == "drop" {
            local hideintensity ""
        }
        * For text options must use `"`xx'"' not "`xx'" (don't ask why!)
        if `"`caption'"' == "drop" {
            local caption ""
        }
        if `"`title'"' == "drop" {
            local title ""
        }
        if `"`subtitle'"' == "drop" {
            local subtitle ""
        }
        if `"`note'"' == "drop" {
            local note ""
        }
        if "`gridcolor'" == "drop" {
            local gridcolor ""
        }
        if "`border'" == "drop" {
            local border ""
        }
        if `gridspace' == -99 { // reset to default
            local gridspace = 2
        }
        if `ylaboffset' == -99 { // reset to default
            local ylaboffset = .25
        }
        if `pathwidth' == -99 { // reset to default
            local pathwidth = .01
        }
        if `aspectratio' == -99 { // reset to default
            local aspectratio = 1
        }
        if `sample' == -99 { // reset to default
            local sample = 100
        }
        if "`labelsize'" == "drop" {
            local labelsize "" // will grab default below
        }
        if "`export'" == "drop" {
            local export ""
        }
        if "`options'" == "drop" {
            local options ""
        }
        if "`debug'" == "drop" {
            local debug ""
        }
    } // end if $pvinteractive==1

//  #3 rename syntax locals to make later code easier to read

    local intNM     "`intvar'"
    local intR      "`intrange'"
    local intV      "`intensity'"
    local clrNM     "`colvar'"
    local clrV      "`colors'"
    local clrR      "`colrange'"
    local clrI      "`colintensity'"
    local hideI     "`hideintensity'"
    local hideC     "`hidecolor'"
    local gridC     "`gridcolor'"
    local gridXW     "`gridxwidth'"
    local gridYW    "`gridywidth'"
    local gridS     "`gridspace'"

//  #4  increment number for export file

    * if increment export name
    if "`expadd'"=="expadd" & "`export'"!="" {

        * if no prior export number
        if `priorexpnum'==0 {
            * nothing was added to the export name before
            local priorlabel ""
        }
        * if prior export number
        else {
            * export name had - and number added
            local priorlabel "-`priorexpnum'"
        }
        * increment within export
        local export = subinstr("`export'","`priorlabel'.","-$pvexportnum.",1)
    }

//  #5  indicates that interactive mode has begun (why needed here?)

    global pvinteractive = 1

//  #6  SAMPLE CASES for testing

    if `sample'<100 {
        set seed 11
        tempvar r
        gen `r' = uniform()
        keep if `r'<.`sample'
        drop `r'
    }

//  #7  SET DEFAULTS IF OPTION NOT SET

    * default hide line color
    if "`hideC'"=="" {
        local hideC "gs13"
    }
    * default labelsize
    if "`labelsize'"=="" {
        local labelsize "vsmall"
    }

//  #8  CREATE VARIABLE INDICATING IF PATH IS SHOWN or HIDDEN

    capture drop _pv_showif

    * if showif blank, show all
    if "`showif'"=="" {
        gen _pv_showif = 1
        label var _pv_showif "Line is shown?"
    }

    * if showif specified, hide unless condition showif holds
    else {
        gen _pv_showif = 0
        label var _pv_showif "Line is shown?"
        qui replace _pv_showif = 1 if `showif'
    }

    * if hideif specified hide if condition is met
    if "`hideif'"!="" {
        qui replace _pv_showif = 0 if `hideif'
    }

    * locals used to select active and hide cases
    local activeyes "& _pv_showif==1"
    local activeno    "_pv_showif==0"

//  #9  INFORMATION ON DATA BEING PLOTTED

//  #9a : names of items

    local i = 0
    local itemNM ""
    `qui' sum itemSTx
    local itemK = r(max) + 1
    forvalues k = 1(1)`itemK' {
        * get variable names from value label
        local tmplbl : label itemlbl `k'
        local itemNM "`itemNM' `tmplbl'"
    }

//  #9b : if no color variable specified, use first item

    if "`clrNM'"=="" {
        local clrNM : word 1 of `itemNM'
    }

//  #9c : check ranges for intvar and colvar to avoid problem
//  when the smallest category is missing in the current
//  dataset.

    * find min and max for intensity variable
    if "`intNM'"!="" {
        sum `intNM'
        local intMIN = r(min)
        local intMAX = r(max)
        if "`intR'"!="" { // if intrange specified, use that
            local intMIN : word 1 of `intR'
            local intMAX : word 2 of `intR'
        }
    }
    * ditto for color variable
    if "`clrNM'"!="" {
        sum `clrNM'
        local clrMIN = r(min)
        local clrMAX = r(max)
        if "`clrR'"!="" {
            local clrMIN : word 1 of `clrR'
            local clrMAX : word 2 of `clrR'
        }
    }

//  #9d : determine number of categories in data being plotted

    local catK = 0
    local catMAX = -9999
    local catMIN =  9999
    forvalues itemnum = 1(1)`itemK' { // check all items
        local tmpvar : word `itemnum' of `itemNM'
        `qui' tab `tmpvar'
        local tmpcats = r(r)
        if `tmpcats'>`catK' {
            local catK = r(r)
        }
        `qui' sum `tmpvar'
        local tmpmax = r(max)
        if `tmpmax'>`catMAX' {
            local catMAX = r(max)
        }
        local tmpmin = r(min)
        if `tmpmin'<`catMIN' {
            local catMIN = r(min)
        }
    } // loop through items

    * check number of categories a second way
    local tmpncat = `catMAX' - `catMIN' + 1
    if `catK'!=`tmpncat' {
        di in red "ERROR: category values must be sequential"
        tab `tmpvar'
        exit
    }

//  #9e : INTENSITY - by default no variation in intensity

    * is intensity on?
    local intON = 0
    if "`intNM'"!="" {
        local intON = 1
    }
    if `intON' {
        * get range of intNM
        local intK = `intMAX' - `intMIN' + 1
        * if no intensity, make it all 1's
        if "`intV'"=="" {
            local intV "1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"
        }
        * create set of intensity values
        local intSET ""
        foreach i in `intV' {
            if "`i'"=="hi" {
                local intSET "`intSET' 1"
            }
            else if "`i'"=="medhi" {
                local intSET "`intSET' .8"
            }
            else if "`i'"=="med" {
                local intSET "`intSET' .6"
            }
            else if "`i'"=="medlo" {
                local intSET "`intSET' .4"
            }
            else if "`i'"=="low" {
                local intSET "`intSET' .2"
            }
            else if "`i'"=="lo" {
                local intSET "`intSET' .2"
            }
            else if "`i'"=="vlo" {
                local intSET "`intSET' .1"
            }
            else {
                local intSET "`intSET' `i'"
            }
        }
        local tmpn : word count `intSET'
        while `tmpn'<`intK' {
            * if too few values, duplicate what we have
            local intSET "`intSET' `intSET'"
            local tmpn : word count `intSET'
        }

    } // intensity on

//  #9f - COLORS USED BY COLOR VARIABLE
//        Default vary colors by values of first item

    * if no colors indicated, use these as defaults
    if "`clrV'"=="" {
        *local clrV "red green blue cyan magenta yellow"
        local clrV "red blue green magenta ltblue gold orange purple mint"
    }
    else if "`clrV'"=="2cat" {
        local clrV "red blue"
    }
    else if "`clrV'"=="3cat" {
        local clrV "red blue green"
    }
    else if "`clrV'"=="4cat" {
        local clrV "red blue green gold"
    }
    else if "`clrV'"=="5cat" {
        local clrV "red blue green gold purple"
    }
    else if "`clrV'"=="bw" {
        local clrV "gs14 gs10 gs6 gs2"
    }
    * make sure there are enough colors
    `qui' tab `clrNM'
    local clrK = r(r)
    local clrK = r(max) - r(min) + 1
    local clrK = `clrMAX' - `clrMIN' + 1

    if "`debug'"=="debug" {
        di "catMAX: `catMAX'"
        di "catMIN: `catMIN'"
        di "clrMAX: `clrMAX'"
        di "clrMIN: `clrMIN'"
        di "clrK:   `clrK'"
    }

    local clrVSET `clrV'
    local tmpn : word count `clrVSET'
    while `tmpn'<`clrK' {
        local clrVSET "`clrVSET' `clrV'"
        local tmpn : word count `clrVSET'
    }

//  #9g - intensity of color

    * dummy up intensity if it isn't defined
    if "`clrI'"=="" {
        local clrI "1.0"
    }
    local clrISET
    * translate abbreviations to intensities
    foreach i in `clrI' {

        if "`i'"=="hi" {
            local clrISET "`clrISET' 1"
        }
        else if "`i'"=="medhi" {
            local clrISET "`clrISET' .8"
        }
        else if "`i'"=="med" {
            local clrISET "`clrISET' .6"
        }
        else if "`i'"=="low" {
            local clrISET "`clrISET' .2"
        }
        else if "`i'"=="medlo" {
            local clrISET "`clrISET' .4"
        }
        else if "`i'"=="lo" {
            local clrISET "`clrISET' .2"
        }
        else if "`i'"=="vlo" {
            local clrISET "`clrISET' .1"
        }
        else {
            local clrISET "`clrISET' `i'"
        }
    }

    * make sure there are enough color intensity
    local tmpn : word count `clrISET'
    while `tmpn'<`clrK' {
        local clrISET "`clrISET' `clrISET'"
        local tmpn : word count `clrISET'
    }

//  #9h - HIDDEN PATHS (unselected)

    * intensity for hidden paths
    if "`hideI'"=="" {
        local hideI = 1
    }
    else if "`hideI'"=="hi" {
        local hideI = 1
    }
    else if "`hideI'"=="medhi" {
        local hideI = .8
    }
    else if "`hideI'"=="med" {
        local hideI = .6
    }
    else if "`hideI'"=="medlo" {
        local hideI = .4
    }
    else if "`hideI'"=="low" {
        local hideI = .2
    }
    else if "`hideI'"=="lo" {
        local hideI = .2
    }
    else if "`hideI'"=="vlo" {
        local hideI = .1
    }

//  #10 DETERMINE DELTA FOR DISTANCE BETWEEN PATHS

    if `delta'==-99 { // if -99 computes delta

        * # of paths for given cateogry for given item
        mat def catitemN = J(`catK',`itemK',.) // # paths
        mat def catMAXN = J(1,`catK',-999) // max paths in this category

        * find max N for a given category of any item
        local maxcatn = 0
        local ii = 0
        foreach v in `itemNM' { // loop over items
            local ++ii
            local ci = 0
            forvalues c = `catMIN'(1)`catMAX' { // loop through categories
                local ++ci
                `qui' count if `v'==`c' & itemSTx==1
                mat catitemN[`ci',`ii'] = r(N)
                local catmax = catMAXN[1,`ci'] // max in cat ci
                if r(N)>`catmax' {
                    mat catMAXN[1,`ci'] = r(N)
                }
                if r(N)>`maxcatn' {
                    local maxcatn = r(N)
                }
            }
        }

        * if equal axes, delta = 1/(max # paths in category + grid spacing)
        if "`equal'"=="equal" {
            local delta = 1/((2*`gridS')+`maxcatn') // space above and below
                *local delta = 1/(`gridS'+`maxcatn')
                *local delta = 1/`maxcatn'
        }
        * if condensed spacing, divide total space by total lines
        else {
            local totalpaths = 0
            forvalues i = 1(1)`catK' {
                local totalpaths = `totalpaths' + catMAXN[1,`i']
            }
            *              #cats / ((space above and below) + paths )
            local delta = `catK'/((2*`catK'*`gridS')+`totalpaths')
            *local delta = `catK'/(( (`catK'-1)*`gridS')+`totalpaths')
            *local delta = `catK'/`totalpaths'
        }
    }

//  #11 AXES

    * set color of grid lines
    if "`gridC'"=="" {
        local gridC "black"
    }
    * hold locations for gridlines
    local gridX ""
    local gridY ""
    * place vertical lines at locations 1 2 3 ...
    forvalue i = 1(1)`itemK' {
        local gridX "`gridX' `i'"
    }

//  #11a - equal grid spacing

    if "`equal'"=="equal" {

        * place horizontal lines at values of categories
        forvalue i = `catMIN'(1)`catMAX' {
            local gridY "`gridY' `i'"
        }
        *forvalue i = `catMIN'(1)`catMAX' {
        *    local gridY "`gridY' `i'"
        *}

        * add grid line at top with added white space between paths and line
        local gridYMAX = `catMAX' + 1 + (`gridS'*`delta')
        local gridY "`gridY' `gridYMAX'"

        * y scale matches minimum category and maxlocation
        local yscale "yscale(range(`catMIN' `gridYMAX'))"

        * mins and maxs for using with -pci-
        local gridYMIN = `catMIN'
        local gridXMIN = 1
        local gridXMAX = `itemK'
if "`defug'"=="debug" {
    tab1 catSTy catENy
}
        * OFFSETS - translate catSTyoff and catENyoff into delta units
        gen _pv_catSTyoff = catSTy + (catSTyoff*`delta') + (`gridS'*`delta')
        gen _pv_catENyoff = catENy + (catENyoff*`delta') + (`gridS'*`delta')
    }

//  #11b - CONDENSED SPACING OF Y GRID

    if "`equal'"=="" { // condensed spacing
*set trace on

        mat def Npathnum = J(1,`catK',.) // # paths in category
        mat def Npathsum = Npathnum      // cum # of paths in category
        mat def Dpathnum = Npathnum      // delta # paths in category
        mat def Dpathsum = Npathnum      // delta cum # of paths in category
        mat def Dgap = Npathnum         // delta gap for that category
        mat def Ngap = Npathnum         // paths with spacing for category
        mat def ygrid = J(1,`catK'+1,.) // location of y grids
        mat def ylabel = Npathnum        // location of y labels

        local space = `gridS'
        local Dspace = `gridS'*`delta'
        local space2 = `space'*2
        local Dspace2 = `Dspace'*2

        mat ygrid[1,1] = `catMIN' // start at minimum

        forvalues k = 1(1)`catK' { // loop through categories
            local k1 = `k' + 1
            * paths
            mat Npathnum[1,`k'] = catMAXN[1,`k']
            mat Dpathnum[1,`k'] = `delta' * Npathnum[1,`k']
            * gaps
            mat Ngap[1,`k'] = Npathnum[1,`k'] + `space2'
            mat Dgap[1,`k'] = Ngap[1,`k']*`delta'
            * cumulative paths
            mat Npathsum[1,`k'] = 0
            forvalue v = 1(1)`k' {
                mat Npathsum[1,`k'] = Npathsum[1,`k'] + Npathnum[1,`v']
            }
            mat Dpathsum[1,`k'] = `delta' * Npathsum[1,`k']
            * ygrids
            mat ygrid[1,`k1'] = `catMIN'
            forvalue v = 1(1)`k' {
                mat ygrid[1,`k1'] = ygrid[1,`k1'] + Dgap[1,`v']
            }
            mat Dpathsum[1,`k'] = `delta' * Npathsum[1,`k']
        }
        forvalues k = 1(1)`catK' { // loop through categories
            local k1 = `k' + 1
            mat ylabel[1,`k'] = (ygrid[1,`k'] + ygrid[1,`k1'])/2
        }

        * offsets to delta units
        gen _pv_catSTyoff = (catSTyoff*`delta') + `Dspace'
        gen _pv_catENyoff = (catENyoff*`delta') + `Dspace'
        *forvalues k = 1(1)`catK' {
        local k = 0
        forvalues kval = `catMIN'(1)`catMAX' {
            local ++k
            qui replace _pv_catSTyoff = _pv_catSTyoff + ygrid[1,`k'] ///
                if catSTy==`kval'
            qui replace _pv_catENyoff = _pv_catENyoff + ygrid[1,`k'] ///
                if catENy==`kval'
        }
        * mins and maxs for using with graphs
        local catK1 = `catK' + 1
        local gridYMIN = `catMIN'
        local gridXMIN = 1
        local gridXMAX = `itemK'
        local gridYMAX = ygrid[1,`catK1']
        local yscale "yscale(range(`catMIN' `gridYMAX'))"
        local gridY ""
        forvalues i = 1(1)`catK1' {
            local g = ygrid[1,`i']
            local gridY "`gridY' `g'"
        }
        if "`debug'"=="debug" {
            mat list Npathnum
            mat list Ngap
            mat list Dpathnum
            mat list Dgap
            mat list ygrid
            mat list ylabel
            di "gridY: `gridY'"
            sum _pv_catSTyoff _pv_catENyoff
        }
*set trace off

    } // condensed

//  #12 LOCALS WITH OPTIONS PASSED TO GRAPH

    * variables to plot by -pcspike-
    local plotVARS "_pv_catSTyoff itemSTx _pv_catENyoff itemENx"
    * NOTE: reordering plotVARS not change which line is on top
    * local plotVARS "_pv_catENyoff itemENx _pv_catSTyoff itemSTx"

    * parameters for x-grid and y-grid lines
    local Pxyline "xline(`gridX', lwidth(`gridXW') lcolor(`gridC'))"
    local Pxyline "`Pxyline' yline(`gridY', lwidth(`gridYW') lcolor(`gridC'))"

    * y-axis labels for categories
    local ylabeltext ""
    local itemlabels : value label catSTy

    * loop through values and find names of variables associated with values

    * equal mode
    if "`equal'"=="equal" {
        forvalues itemnum = `catMIN'(1)`catMAX' {
            local itemlabel : label `itemlabels' `itemnum'
            local textyloc = `itemnum' + .5
            local textxloc = 1 - `ylaboffset'
            local tmptxt `"text(`textyloc' `textxloc' "`itemlabel'",place(w) size(`labelsize'))"'
            local ylabeltext `" `ylabeltext' `tmptxt' "'
        }
    }

    * condensed mode
    else {
        local i = 0
        forvalues itemnum = `catMIN'(1)`catMAX' {
            local ++i
            local ip1 = `i' + 1
            local itemlabel : label `itemlabels' `itemnum'
            local textyloc = ylabel[1,`i']
            local textxloc = 1 - `ylaboffset'
            local tmptxt `"text(`textyloc' `textxloc' "`itemlabel'",place(w) size(`labelsize'))"'
            local ylabeltext `" `ylabeltext' `tmptxt' "'
        }
    }

    * range of x labels
    local lblrng "1(1)`itemK'"
    * angle for labels
    local lblang ""
    if "`angle'"=="angle" {
        local lblang "angle(forty_five)"
    }

    * x-axis and y-axis commands
    * DELETE local Pxaxis "xtitle("") xlabel(,valuelabel nogrid noticks labsize(`labelsize')) legend(off)"
    local Pxaxis "xtitle("") xlabel(`lblrng', `lblang' valuelabel nogrid noticks labsize(`labelsize')) legend(off)"
    local Pyaxis "ytitle("") ylabel(,nolabel nogrid tstyle(none))"
    local Paxis "yscale(off) xscale(noline)"

    * aspect ratio and path width
    local Pratio "aspectratio(`aspectratio') lwidth(`pathwidth')"

    * set other graph defaults
    local Pborder "color(white)" // i.e., no shading
    if "`border'"!="" {
        local Pborder "color(`border')"
    }
    local Pregion "graphregion(lstyle(none) `Pborder')"

    * general plot characateristics
    local Pdefaults `"`Pregion' `Paxis' `Pxaxis' `Pyaxis' `ylabeltext' "'
    * DELETE local Pdefaults `"`Pdefaults' `Pratio' caption(`caption') title(`title') "'
    local Pdefaults `"`Pdefaults' `Pratio' `caption' `title' "'
    local Pdefaults `"`Pdefaults' `subtitle' `note' `options'"'

    * plot of hidden lines
    local Phide "(pcspike `plotVARS' if `activeno', "
    local Phide "`Phide' lcolor(`hideC'*`hideI') lwidth(`pathwidth')"
    local Phide `"`Phide' `Pdefaults' `grid' `yscale')"'
    * DELETE local PLOT  `"twoway `Phide'"'
    * local to hold full plot command
    local PLOT ""

//  #13 - loop through intensity & color vars to create plot sets

    local icolor = `clrK' + 1 // start with 1 more than # of colors, then decrement
    forvalues cat = `clrMAX'(-1)`clrMIN' {

* label can't be -1 so make it _1
local Lcat "`cat'" // if not negative
if `cat'<0 {
    local abscat = `cat'*-1
    local Lcat "_`abscat'"
}
* 2010-02-12 10.10 am cat to Lcat

        local icolor = `icolor' - 1
        * get current color and intensity
        local clr : word `icolor' of `clrVSET'
        local clrinten : word `icolor' of `clrISET'
        * is there an intensity variable
        if `intON' {
            local iint = `intK' + 1
            forvalues icat = `intMAX'(-1)`intMIN' {
                local iint = `iint' - 1
                local inten: word `iint' of `intSET'
                local P`Lcat'`icat' "(pcspike `plotVARS' if `clrNM'==`cat' & `intNM'==`icat' "
                local P`Lcat'`icat' "`P`Lcat'`icat'' `activeyes', "
                * combined the intensities
                local intis = `clrinten'*`inten'
                local P`Lcat'`icat' "`P`Lcat'`icat'' lcolor(`clr'*`intis') lwidth(`pathwidth') )"
                local PLOT "`PLOT' `P`Lcat'`icat''"
            }
        } // intON
        * no intensity variable
        else {
            local P`Lcat' "(pcspike `plotVARS' if `clrNM'==`cat' "
            local P`Lcat' "`P`Lcat'' `activeyes', "
            local P`Lcat' "`P`Lcat'' lcolor(`clr'*`clrinten') lwidth(`pathwidth') )"
            * stack with rest of plots
            local PLOT "`PLOT' `P`Lcat''"
        }
    } // loop through categories

//  #14 - AXES PLOTTED ON TOP OF OTHER LINES

    local i = 0
    local Pgrid ""
    foreach y in `gridY' {
        local yis "`y' `gridXMIN' `y' `gridXMAX', lwidth(`gridYW') lcolor(`gridC')"
        local Pgrid "`Pgrid' (pci `yis')"
    }
    foreach x in `gridX' {
        local xis "`gridYMIN' `x' `gridYMAX' `x', lwidth(`gridXW') lcolor(`gridC')"
        local Pgrid "`Pgrid' (pci `xis')"
    }
    * tack this on to end of plot commands (last so lines are on top)
    local PLOT "`PLOT' `Pgrid'"

//  #15 - DEBUG OUTPUT

    if "`debug'"=="debug" {

        di "TOTAL PATHS       : `totalpaths'"
        di "max N in any cell : `maxcatn'"
        di "delta             : `delta'"

        di "clriset     : `clrISET'"
        di "clrvset     : `clrVSET'"

        di "showif      : `showif'"
        di "hideif      : `hideif'"
        di "hideC       : `hideC'"
        di "hideI       : `hideI'"

        di "itemNM      : `itemNM'"
        di "itemK       : `itemK'"
        di "itemC       : `itemC'"

        di "catK        : `catK'"
        di "catMAX      : `catMAX'"
        di "catMIN      : `catMIN'"

        di "intNM       : `intNM'"
        di "intV        : `intV'"
        di "intON       : `intON'"
        di "intMAX      : `intMAX'"
        di "intMIN      : `intMIN'"
        di "intK        : `intK'"
        di "intSET      : `intSET'"

        di "clrNM       : `clrNM'"
        di "clrI        : `clrI'"
        di "clrISET     : `clrISET'"
        di "clrV        : `clrV'"
        di "clrVSET     : `clrVSET'"
        di "clrK        : `clrK'"
        di "clrMIN      : `clrMIN'"
        di "clrMAX      : `clrMAX'"

        di "gridC       : `gridC'"
        di "gridXW       : `gridXW'"
        di "gridYW       : `gridYW'"
        di "gridS       : `gridS'"
        di "gridX       : `gridX'"
        di "gridY       : `gridY'"
        di "gridYMAX    : `gridYMAX'"
        di "gridXMAX    : `gridXMAX'"
        di "gridYMIN    : `gridYMIN'"
        di "gridXMIN    : `gridXMIN'"

        mat list catMAXN
        mat list catitemN

    }

//  #16 - RUN THE PLOT

    * summarize how the data was ordered
    local pvdata      : char _dta[pvdata]
    local pvsortorder : char _dta[pvsortorder]
    local pvsortvars  : char _dta[pvsortvars]
    local pvmethod    : char _dta[pvmethod]
    *DELETE char define _dta[pvitemncats] "`itemNCATS'" // number of categories
    *DELETE char define _dta[pvitemmincats] "`itemMINCATS'" // minimum category value
    *DELETE char define _dta[pvitemmaxcats] "`itemMAXCATS'" // maximum category value

    di
    di "Data contructed by `pvdata'.ado:"
    di
    di "   Sorted `pvsortorder' by: `pvsortvars'"
    di "   Paths arranged with `pvmethod' method."
    di "   Delta = `delta'"
    di

    * echo the command and run the plot
    if "`quietly'"== "" {
        di _newline ". twoway " `"`Phide'"' " `PLOT'"
        local PLOT `"twoway `Phide' `PLOT'"'
        `PLOT'
        if "`export'"!="" {
            di ". graph export `export'"
            graph export `export'
        }
    } // quietly

    else {
        di "Note: no graph created due to quietly option being used."
    }

//  #17 CLEAN UP

matrix dir

    * order _pv_catSTyoff itemSTx _pv_catENyoff itemENx tempcatSTy tempcatENy
    * sum _pv_catSTyoff itemSTx _pv_catENyoff itemENx
    capture drop _pv_catSTyoff _pv_catENyoff
    capture drop tempcatSTy tempcatENy
* 2010-10-24 02.00 pm catMAXN catitemN is needed
*    foreach m in drop catMAXN catitemN offsetEN offsetST
    foreach m in drop offsetEN offsetST ///
        ylabel ygrid Ngap Dgap Dpathsum ///
        Dpathnum Npathsum Npathnum {
        capture matrix drop `m'
    }
matrix dir

    * move things to globals for use in interactive mode
    global pvhideC          "`hideC'"
    global pvhideC          "`hideC'"
    global pvcolors         "`colors'"
    global pvcolvar         "`colvar'"
    global pvcolintensity   "`colintensity'"
    global pvintensity      "`intensity'"
    global pvintvar         "`intvar'"
    global pvshowif         "`showif'"
    global pvhideif         "`hideif'"
    global pvhidecolor      "`hidecolor'"
    global pvhideintensity  "`hideintensity'"
    global pvcaption        "`caption'"
    global pvtitle          "`title'"
    global pvsubtitle       "`subtitle'"
    global pvnote           "`note'"
    global pvgridcolor      "`gridcolor'"
    global pvgridxwidth =    `gridxwidth'
    global pvgridywidth =   `gridywidth'
    global pvgridspace =    `gridspace'
    global pvborder         "`border'"
    global pvylaboffset =   `ylaboffset'
    global pvlabelsize      "`labelsize'"
    global pvpathwidth =    `pathwidth'
    global pvexport         "`export'"
    global pvoptions        "`options'"
    global pvaspectratio =  `aspectratio'
    global pvdelta =        `delta'
    global pvsample =       `sample'
    global pvdebug           "`debug'"
    global pvangle          "`angle'"
    global pvintrange       "`intrange'"
    global pvcolrange       "`colrange'"

end
exit

** DELETE

* get color for 1st category
local color1 : word 1 of `clrVSET'
local inten1 : word 1 of `clrIset'
local P1 "(pcspike `plotVARS' if `clrNM'==1 `activeyes',"
local P1 "`P1' lcolor(`color1'*`inten1') "
local P1 "`P1' `pathwidth')"

//  loop through colorvar categories to create plot

    local icolor = `clrK' + 1
    * loop through categories to create plot commands
    forvalues cat = `clrMAX'(-1)`clrMIN' {
        local icolor = `icolor' - 1
        local clr : word `icolor' of `clrVSET'
        local inten : word `icolor' of `clrIset'
        local plot`cat' "(pcspike `plotVARS' if `clrNM'==`cat' "
        local plot`cat' "`plot`cat'' `activeyes' "
        local plot`cat' "lcolor(`clr'*`inten') `pathwidth' )"
        * stack with rest of plots
        local PLOT "`PLOT' `plot`cat''"
    }

//  LINE TYPES: DROPPED SINCE LINES WERE UNCLEAR
    [LINEVar(varname)]   /// line type varies by this variable
    [lines(string)]      /// lines used by linevar
    * if blank, use these as defaults
    if "`lines'"=="" {
        local lines "solid"
    }
    if "`linevar'"!="" {
        * number of categories in linevar
        `qui' tab `linevar'
        local nlinecats = r(r)
        * make sure there are enough lines
        local lineset `lines'
        local nlines : word count `lineset'
        while `nlines'<`nlinecats' {
            local lineset "`lineset' `lines'"
            local nlines : word count `lineset'
        }
    } // if linevar

//  TITLES: DROP SINCE NOT NEEDED

    if "`title'"!="" {
        local title "title(`title')"
    }
    if "`subtitle'"!="" {
        local subtitle "subtitle(`subtitle')"
    }
    if "`note'"!="" {
        local note "note(`note')"
    }
    if "`caption'"!="" {
        local caption "caption(`caption')"
    }

//  DROP NO PATTERN

local P1 "`P1' lpat(`pattern') lcolor(`color1'*`inten1') "
local plot`cat' "`plot`cat'' `activeyes', lpat(`pattern') "
local P`cat'`icat' "`P`cat'`icat'' `activeyes', lpat(`pattern') "
local P`cat' "`P`cat'' `activeyes', lpat(`pattern') "
global pvpattern        "`pattern'"
            [PATTERN(string)]           /// experimental: lines pattern
        if "`pattern'" == "" {
            local pattern "$pvpattern"
        }
                if "`pattern'" == "drop" {
            local pattern "$pvpattern"
        }

        * rename master globals
        local gridY "`gridY'"
        local gridYMAX "`gridYMAX'"
        local yscale "`yscale'"
        local gridYMIN "`gridYMIN'"
        local gridXMIN "`gridXMIN'"
        local gridXMAX "`gridXMAX'"

HISTORY

* version 0.0.1 - 2007-12-21 pvplot3
* version 0.0.2 - 2008-01-24 try passthrough
* version 0.0.3 jsl 2008-01-27
* version 0.0.4 jsl 2008-01-29 - add some options, fix some bugs
* version 0.0.5 jsl 2008-01-30 - labels with more items...
* version 0.0.6 jsl 2008-01-30 - range for colors and intensity
* version 0.0.7 jsl 2008-01-30 - cleanup
* version 0.0.8 jsl 2009-10-12 - clarify code
* version 0.1.0 jsl 2010-02-09 - document code
* version 0.1.1 jsl 2010-02-09
*   - equal / condensed
* version 0.1.2 jsl 2010-02-10
*   - minor fixes
* version 0.1.3 jsl 2010-02-11
*   - bug in condensed; add -99 resets; ;remove pattern
* version 0.1.4 jsl 2010-02-11
*   - rewrite condensed and fine tune white spacing around paths