*! -spmap_point-: Auxiliary program for -spmap- *! Version 1.2.0 - 14 March 2008 *! Version 1.1.0 - 7 May 2007 *! Version 1.0.0 - 7 December 2006 *! Author: Maurizio Pisati *! Department of Sociology and Social Research *! University of Milano Bicocca (Italy) *! maurizio.pisati@unimib.it * ---------------------------------------------------------------------------- * 1. Define program * ---------------------------------------------------------------------------- program spmap_point, rclass version 9.2 * ---------------------------------------------------------------------------- * 2. Define syntax * ---------------------------------------------------------------------------- syntax, [Data(string)] /// [Select(string asis)] /// [BY(string)] /// /// [Xcoord(string)] /// [Ycoord(string)] /// /// [PROPortional(string)] /// [PRange(string)] /// [PSize(string)] /// /// [DEViation(string)] /// [DMax(string)] /// [REFVal(string)] /// [REFWeight(string)] /// /// [SIze(string)] /// [SHape(string)] /// [FColor(string asis)] /// [OColor(string asis)] /// [OSize(string)] /// /// [LEGENDA(string)] /// [LEGTitle(string asis)] /// [LEGLabel(string)] /// [LEGShow(string)] /// [LEGCount] * ---------------------------------------------------------------------------- * 3. Check syntax * ---------------------------------------------------------------------------- /* Preserve data */ preserve /* Check and open dataset */ if ("`data'" != "") { if (substr(reverse("`data'"),1,4) != "atd.") { local data "`data'.dta" } capture confirm file "`data'" if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: file " /// "{bf:`data'} specified in suboption {bf:{ul:d}ata()} " /// "not found{p_end}" exit 601 } use "`data'", clear } /* Select relevant records */ if (`"`select'"' != "") { cap `select' if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: suboption " /// "{bf:{ul:s}elect()} specified incorrectly{p_end}" exit 198 } } /* Check option by() */ if ("`by'" != "") { cap unab by : `by' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "variable {bf:`by'} specified in suboption " /// "{bf:{ul:by}()} not found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "string {bf:`by'} specified in suboption " /// "{bf:{ul:by}()} is not a valid variable " /// "name{p_end}" exit 198 } local NW : word count `by' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:by}()} accepts only one " /// "variable{p_end}" exit 198 } } /* Check option xcoord() */ if ("`xcoord'" == "") { di as err "{p}Problem with option {bf:{ul:poi}nt()}: suboption " /// "{bf:{ul:x}coord()} is required{p_end}" exit 198 } cap unab xcoord : `xcoord' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "variable {bf:`xcoord'} specified in suboption " /// "{bf:{ul:x}coord()} not found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "string {bf:`xcoord'} specified in suboption " /// "{bf:{ul:x}coord()} is not a valid variable " /// "name{p_end}" exit 198 } local NW : word count `xcoord' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:x}coord()} accepts only one " /// "variable{p_end}" exit 198 } cap confirm numeric variable `xcoord', exact if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:x}coord()} accepts only " /// "numeric variables{p_end}" exit 7 } /* Check option ycoord() */ if ("`ycoord'" == "") { di as err "{p}Problem with option {bf:{ul:poi}nt()}: suboption " /// "{bf:{ul:y}coord()} is required{p_end}" exit 198 } cap unab ycoord : `ycoord' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "variable {bf:`ycoord'} specified in suboption " /// "{bf:{ul:y}coord()} not found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "string {bf:`ycoord'} specified in suboption " /// "{bf:{ul:y}coord()} is not a valid variable " /// "name{p_end}" exit 198 } local NW : word count `ycoord' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:y}coord()} accepts only one " /// "variable{p_end}" exit 198 } cap confirm numeric variable `ycoord', exact if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:y}coord()} accepts only " /// "numeric variables{p_end}" exit 7 } /* Check option proportional() */ if ("`proportional'" != "") { cap unab proportional : `proportional' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "variable {bf:`proportional'} specified in " /// "suboption {bf:{ul:prop}ortional()} not " /// "found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "string {bf:`proportional'} specified in " /// "suboption {bf:{ul:prop}ortional()} is not " /// "a valid variable name{p_end}" exit 198 } local NW : word count `proportional' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:prop}ortional()} accepts " /// "only one variable{p_end}" exit 198 } cap confirm numeric variable `proportional', exact if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:prop}ortional()} accepts " /// "only numeric variables{p_end}" exit 7 } } /* Check option prange() */ if ("`prange'" != "") & ("`proportional'" != "") { local NW : word count `prange' if (`NW' != 2) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:pr}ange()} requires exactly " /// "2 arguments{p_end}" exit 198 } foreach W in `prange' { cap confirm number `W' if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:pr}ange()} accepts only " /// "numbers{p_end}" exit 7 } } local N1 : word 1 of `prange' local N2 : word 2 of `prange' if (`N1' == `N2') { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "the two numbers specified in suboption " /// "{bf:{ul:pr}ange()} must be different{p_end}" exit 198 } local MIN = min(`N1', `N2') local MAX = max(`N1', `N2') local prange "`MIN' `MAX'" } /* Check option psize() */ if ("`psize'" != "") & ("`proportional'" != "") { local LIST "absolute relative" local EXIST : list posof "`psize'" in LIST if !`EXIST' { di as err "{p}Problem with option {bf:{ul:poi}nt()}: suboption " /// "{bf:{ul:ps}ize()} accepts only one of the following " /// "keywords: {bf:`LIST'}{p_end}" exit 198 } } /* Check option deviation() */ if ("`deviation'" != "") { if ("`proportional'" != "") { di as err "{p}Problem with option {bf:{ul:poi}nt()}: suboptions " /// "{bf:{ul:prop}ortional()} and {bf:{ul:dev}iation()} " /// "cannot be specified together{p_end}" exit 198 } cap unab deviation : `deviation' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "variable {bf:`deviation'} specified in " /// "suboption {bf:{ul:dev}iation()} not " /// "found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "string {bf:`deviation'} specified in " /// "suboption {bf:{ul:dev}iation()} is not " /// "a valid variable name{p_end}" exit 198 } local NW : word count `deviation' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:dev}iation()} accepts " /// "only one variable{p_end}" exit 198 } cap confirm numeric variable `deviation', exact if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:dev}iation()} accepts " /// "only numeric variables{p_end}" exit 7 } } /* Check option dmax() */ if ("`deviation'" != "") & ("`dmax'" != "") { local NW : word count `dmax' if (`NW' != 1) { di as err "{p}Problem with option {bf:{ul:dia}gram()}: " /// "suboption {bf:{ul:dm}ax()} accepts only 1 " /// "argument{p_end}" exit 198 } cap confirm number `dmax' if _rc { di as err "{p}Problem with option {bf:{ul:dia}gram()}: " /// "suboption {bf:{ul:dm}ax()} accepts only " /// "numbers{p_end}" exit 7 } if (`dmax' <= 0) { di as err "{p}Problem with option {bf:{ul:dia}gram()}: " /// "the argument of suboption {bf:{ul:dm}ax()} " /// "must be >0{p_end}" exit 198 } } /* Check option refval() */ if ("`deviation'" != "") & ("`refval'" != "") { cap confirm number `refval' if _rc { local LIST "mean median" local EXIST : list posof "`refval'" in LIST if !`EXIST' { di as err "{p}Problem with option {bf:{ul:poi}nt()}: suboption " /// "{bf:{ul:refv}al()} accepts only numbers or one of " /// "the following keywords: {bf:`LIST'}{p_end}" exit 198 } } else local RVTYPE "NUM" } /* Check option refweight() */ if ("`refweight'" != "") & ("`deviation'" != "") { cap unab refweight : `refweight' if (_rc == 111) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "variable {bf:`refweight'} specified in " /// "suboption {bf:{ul:refw}eight()} not " /// "found{p_end}" exit 111 } if (_rc == 198) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "string {bf:`refweight'} specified in " /// "suboption {bf:{ul:refw}eight()} is not " /// "a valid variable name{p_end}" exit 198 } local NW : word count `refweight' if (`NW' > 1) { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:refw}eight()} accepts only " /// "one variable{p_end}" exit 198 } cap confirm numeric variable `refweight', exact if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:refw}eight()} accepts " /// "only numeric variables{p_end}" exit 7 } } /* Check option shape() */ if ("`shape'" != "") & ("`deviation'" != "") { local LIST "O D T S o d t s" local NL : word count `shape' forval i = 1/`NL' { local SHP : word `i' of `shape' if (!inlist("`SHP'",".","=","..","...")) { local EXIST : list posof "`SHP'" in LIST if !`EXIST' { di as err "{p}Problem with option {bf:{ul:poi}nt()}: when " /// "suboption {bf:{ul:dev}iation()} is specified, " /// "suboption {bf:{ul:sh}ape()} accepts only solid " /// "symbol styles written in short form: " /// "{bf:`LIST'}{p_end}" exit 198 } } } } /* Check option legenda() */ if ("`legenda'" != "") { local LIST "on off" local EXIST : list posof "`legenda'" in LIST if !`EXIST' { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "suboption {bf:{ul:legenda}()} accepts only one " /// "of the following keywords: {bf:`LIST'}{p_end}" exit 198 } } /* Check options relevant only when legenda(on) */ if ("`legenda'" == "on") { /* Check option leglabel() */ if (`"`leglabel'"' == "") & ("`by'" == "") { di as err "{p}Problem with option {bf:{ul:poi}nt()}: since " /// "you have specified suboption {bf:{ul:legenda}(on)} " /// "but you have not specified any group variable in " /// "suboption {bf:{ul:by}()}, you are requested to " /// "specify suboption {bf:{ul:legl}abel()}{p_end}" exit 198 } /* Check option legshow() */ if ("`legshow'" != "") { cap numlist "`legshow'" if _rc { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "invalid numlist in suboption " /// "{bf:{ul:legs}how()}{p_end}" exit 121 } } /* End */ } /* Marksample */ marksample TOUSE markout `TOUSE' `xcoord' `ycoord' if ("`by'" != "") markout `TOUSE' `by' if ("`proportional'" != "") markout `TOUSE' `proportional' if ("`deviation'" != "") markout `TOUSE' `deviation' if ("`refweight'" != "" & "`deviation'" != "") markout `TOUSE' `refweight' qui count if `TOUSE' if (r(N) == 0) error 2000 * ---------------------------------------------------------------------------- * 4. Define basic objects * ---------------------------------------------------------------------------- /* Select relevant observations */ qui keep if `TOUSE' /* Set defaults relevant only when proportional != "" */ if ("`proportional'" != "") { /* Set default range for weighting variable normalization */ if ("`prange'" == "") { qui su `proportional', meanonly local prange "0 `r(max)'" } /* Set min-max values for weighting variable normalization */ local PMIN : word 1 of `prange' local PMAX : word 2 of `prange' /* Set default reference system for weighting */ if ("`psize'" == "") local psize "relative" /* End */ } /* Set defaults relevant only when deviation != "" */ if ("`deviation'" != "") { /* Set default reference value */ if ("`refval'" == "") local refval "mean" /* Set STAT corresponding to specified reference value */ if ("`refval'" == "mean") local STAT "mean" if ("`refval'" == "median") local STAT "p50" /* Set reference weight */ if ("`refweight'" != "") local REFWEIGHT "[aweight = `refweight']" /* End */ } /* Set default symbol size */ local size_d "*1" if ("`size'" == "") local size "`size_d'" /* Set default symbol shape */ local shape_d "o" if ("`shape'" == "") local shape "`shape_d' ..." /* Set default symbol fill color */ local fcolor_d "black" if (`"`fcolor'"' == "") local fcolor "`fcolor_d' ..." /* Set default outline color */ local ocolor_d "none" if (`"`ocolor'"' == "") local ocolor "`ocolor_d' ..." /* Set default outline thickness */ local osize_d "thin" if ("`osize'" == "") local osize "`osize_d' ..." /* Set default legend */ if ("`legenda'" == "") local legenda "off" /* Set legend title when legtitle(varlab) */ if ("`legenda'" == "on") & ("`by'" != "") & (`"`legtitle'"' == "varlab") { local legtitle : variable label `by' if (`"`legtitle'"' == "") local legtitle "`by'" } * ---------------------------------------------------------------------------- * 5. Create working dataset * ---------------------------------------------------------------------------- /* Housekeeping */ cap drop __POI* /* Generate weighting variable */ if ("`proportional'" == "") qui gen __POI_W = 1 if ("`proportional'" != "") { qui gen __POI_W = (`proportional' - `PMIN') / (`PMAX' - `PMIN') gsort -__POI_W } /* Generate sign and weighting variables if deviation != "" */ if ("`deviation'" != "") { if ("`RVTYPE'" == "NUM") local RV = `refval' else { qui su `deviation' `REFWEIGHT', detail local RV = r(`STAT') } qui gen __POI_S = sign(`deviation' - `RV') qui recode __POI_S (0=1) qui replace __POI_W = abs(`deviation' - `RV') gsort -__POI_S -__POI_W } /* Generate group variable */ if ("`by'" == "") qui gen __POI_G = 1 if ("`by'" != "") qui egen __POI_G = group(`by'), lname(__POI_G) qui tab __POI_G local NG = r(r) /* Generate dummy cases */ qui count local NOBS = r(N) if ("`proportional'" != "") { local NOBS2 = `NOBS' + `NG' * 2 qui set obs `NOBS2' if ("`psize'" == "absolute") { local WMIN = 0 local WMAX = 1 } else { qui su __POI_W local WMIN = r(min) local WMAX = r(max) } local ROW = `NOBS' + 1 forval i = 1/`NG' { qui replace __POI_G = `i' in `ROW' qui replace __POI_W = `WMIN' in `ROW' local ROW = `ROW' + 1 qui replace __POI_G = `i' in `ROW' qui replace __POI_W = `WMAX' in `ROW' local ROW = `ROW' + 1 } gsort __POI_G -__POI_W } if ("`deviation'" != "") { local NOBS2 = `NOBS' + `NG' * 2 * 2 qui set obs `NOBS2' if ("`dmax'" != "") local WMAX = `dmax' else { qui su __POI_W local WMAX = r(max) } local ROW = `NOBS' + 1 forval i = 1/`NG' { qui replace __POI_G = `i' in `ROW' qui replace __POI_S = -1 in `ROW' qui replace __POI_W = 0 in `ROW' local ROW = `ROW' + 1 qui replace __POI_G = `i' in `ROW' qui replace __POI_S = -1 in `ROW' qui replace __POI_W = `WMAX' in `ROW' local ROW = `ROW' + 1 qui replace __POI_G = `i' in `ROW' qui replace __POI_S = 1 in `ROW' qui replace __POI_W = 0 in `ROW' local ROW = `ROW' + 1 qui replace __POI_G = `i' in `ROW' qui replace __POI_S = 1 in `ROW' qui replace __POI_W = `WMAX' in `ROW' local ROW = `ROW' + 1 } gsort -__POI_S __POI_G -__POI_W } /* Generate coordinate variables */ qui gen __POI_X = `xcoord' qui gen __POI_Y = `ycoord' /* Set number of keys */ if ("`deviation'" == "") local NK = `NG' else local NK = `NG' * 2 /* Count points */ if ("`legenda'" == "on") & ("`legcount'" != "") { if ("`deviation'" == "") { forval i = 1/`NG' { qui count if __POI_G == `i' & __POI_X != . if (r(N) > 0) local COUNT "`COUNT'`r(N)' " } } else { forval j = 1(-2)-1 { forval i = 1/`NG' { qui count if __POI_S == `j' & __POI_G == `i' & __POI_X != . if (r(N) > 0) local COUNT "`COUNT'`r(N)' " } } } } /* Save dataset */ keep __POI* qui save "__POI.dta", replace * ---------------------------------------------------------------------------- * 6. Parse style lists * ---------------------------------------------------------------------------- /* Set list of available color palettes */ local PALETTE "`PALETTE' Accent Blues BrBG BuGn BuPu Dark2 GnBu Greens Greys" local PALETTE "`PALETTE' OrRd Oranges PRGn Paired Pastel1 Pastel2 PiYG PuBu" local PALETTE "`PALETTE' PuBuGn PuOr PuRd Purples RdBu RdGy RdPu RdYlBu" local PALETTE "`PALETTE' RdYlGn Reds Set1 Set2 Set3 Spectral YlGn YlGnBu" local PALETTE "`PALETTE' YlOrBr YlOrRd" local PALETTE "`PALETTE' BuRd BuYlRd Heat Terrain Topological" local PALETTE "`PALETTE' Blues2 Greens2 Greys2 Reds2 Rainbow" /* Parse option size() */ local size : word 1 of `size' /* Parse option shape() */ spmap_psl, l(`shape') m(`NG') o({bf:{ul:sh}ape()}) d(`shape_d') local shape `"`s(pl)'"' /* Parse option fcolor() */ local EXIST : list posof `"`fcolor'"' in PALETTE if `EXIST' { if (`NG' > 1) { spmap_color "`fcolor'" `NG' local fcolor `"`s(colors)'"' } else { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "when no group variable is specified in suboption " /// "{bf:{ul:by}()}, suboption {bf:{ul:fc}olor()} " /// "does not accept palette names{p_end}" exit 198 } } else { spmap_psl, l(`fcolor') m(`NG') o({bf:{ul:fc}olor()}) d(`fcolor_d') local fcolor `"`s(pl)'"' } /* Parse option ocolor() */ local EXIST : list posof `"`ocolor'"' in PALETTE if `EXIST' { if (`NG' > 1) { spmap_color "`ocolor'" `NG' local ocolor `"`s(colors)'"' } else { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "when no group variable is specified in suboption " /// "{bf:{ul:by}()}, suboption {bf:{ul:oc}olor()} " /// "does not accept palette names{p_end}" exit 198 } } else { spmap_psl, l(`ocolor') m(`NG') o({bf:{ul:oc}olor()}) d(`ocolor_d') local ocolor `"`s(pl)'"' } /* Parse option osize() */ spmap_psl, l(`osize') m(`NG') o({bf:{ul:os}ize()}) d(`osize_d') local osize `"`s(pl)'"' * ---------------------------------------------------------------------------- * 7. Compose command * ---------------------------------------------------------------------------- /* Compose command */ if ("`deviation'" == "") { forval i = 1/`NG' { local SH : word `i' of `shape' local FC : word `i' of `fcolor' local OC : word `i' of `ocolor' if ("`OC'" == "none") local OC "`FC'" local OS : word `i' of `osize' local GRAPH `"`GRAPH'(scatter __POI_Y __POI_X [aw = __POI_W]"' local GRAPH `"`GRAPH' if __POI_G == `i', ms("`SH'") mc("`FC'")"' local GRAPH `"`GRAPH' msize("`size'") mlw("`OS'") mlc("`OC'") ) "' } } if ("`deviation'" != "") { forval i = 1/`NG' { local SH : word `i' of `shape' local FC : word `i' of `fcolor' local OC : word `i' of `ocolor' if ("`OC'" == "none") local OC "`FC'" local OS : word `i' of `osize' local GRAPH `"`GRAPH'(scatter __POI_Y __POI_X [aw = __POI_W]"' local GRAPH `"`GRAPH' if __POI_G == `i' & __POI_S == 1,"' local GRAPH `"`GRAPH' ms("`SH'") mc("`FC'") msize("`size'")"' local GRAPH `"`GRAPH' mlw("`OS'") mlc("`OC'") ) "' } forval i = 1/`NG' { local SH : word `i' of `shape' local FC "none" local OC : word `i' of `fcolor' local OS : word `i' of `osize' local GRAPH `"`GRAPH'(scatter __POI_Y __POI_X [aw = __POI_W]"' local GRAPH `"`GRAPH' if __POI_G == `i' & __POI_S == -1,"' local GRAPH `"`GRAPH' ms("`SH'h") mc("`FC'") msize("`size'")"' local GRAPH `"`GRAPH' mlw("`OS'") mlc("`OC'") ) "' } } * ---------------------------------------------------------------------------- * 8. Set legend order and labels * ---------------------------------------------------------------------------- /* legenda(off) */ if ("`legenda'" == "off") { local TITLE "" local KEY "" local LABEL "" } /* legenda(on) & by == "" & deviation == "" */ if ("`legenda'" == "on") & ("`by'" == "") & ("`deviation'" == "") { /* Title */ if (`"`legtitle'"' != "") { local Q = strpos(`"`legtitle'"',`"""') /* " */ if (`Q' == 0) local TITLE `"- "`legtitle'""' else local TITLE `"- `legtitle'"' } else { local TITLE "" } /* Keys */ local KEY "1 " /* Labels */ if ("`legcount'" == "") { local LABEL `"`"`leglabel'"' "' } else { local OBS : word 1 of `COUNT' local LABEL `"`"`leglabel' (`OBS')"' "' } /* End */ } /* legenda(on) & by != "" & deviation == "" */ if ("`legenda'" == "on") & ("`by'" != "") & ("`deviation'" == "") { /* Title */ if (`"`legtitle'"' != "") { local Q = strpos(`"`legtitle'"',`"""') /* " */ if (`Q' == 0) local TITLE `"- "`legtitle'""' else local TITLE `"- `legtitle'"' } else { local TITLE "" } /* Keys */ numlist "1/`NK'" local KEY "`r(numlist)'" if ("`legshow'" != "") { local CHECK : list legshow in KEY if !`CHECK' { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "one or more keys specified in suboption " /// "{bf:{ul:legs}how()} do not exist. Valid keys " /// " are: `KEY'{p_end}" exit 198 } else local KEY "`legshow'" } /* Labels */ foreach K in `KEY' { local LBL : label (__POI_G) `K' if ("`legcount'" == "") { local LABEL `"`LABEL'`"`LBL'"' "' } else { local OBS : word `K' of `COUNT' local LABEL `"`LABEL'`"`LBL' (`OBS')"' "' } } /* End */ } /* legenda(on) & deviation != "" */ if ("`legenda'" == "on") & ("`deviation'" != "") { /* Title */ if (`"`legtitle'"' != "") { local Q = strpos(`"`legtitle'"',`"""') /* " */ if (`Q' == 0) local TITLE `"- "`legtitle'""' else local TITLE `"- `legtitle'"' } else { local TITLE "" } /* Keys */ local K = 1 forval j = 1(-2)-1 { forval i = 1/`NG' { qui count if __POI_S == `j' & __POI_G == `i' & __POI_X != . if (r(N) > 0) { local KEY "`KEY'`K' " local VAL "`VAL'`i' " local SGN "`SGN'`j' " } local K = `K' + 1 } } if ("`legshow'" != "") { local CHECK : list legshow in KEY if !`CHECK' { di as err "{p}Problem with option {bf:{ul:poi}nt()}: " /// "one or more keys specified in suboption " /// "{bf:{ul:legs}how()} do not exist. Valid keys " /// " are: `KEY'{p_end}" exit 198 } else local KEY "`legshow'" } /* Labels */ local NW : word count `KEY' forval i = 1/`NW' { local V : word `i' of `VAL' local S : word `i' of `SGN' if ("`S'" == "1") local S "[+]" if ("`S'" == "-1") local S "[-]" if ("`by'" != "") local LBL : label (__POI_G) `V' else local LBL `"`leglabel'"' if ("`legcount'" == "") { local LABEL `"`LABEL'`"`LBL'`S'"' "' } else { local OBS : word `i' of `COUNT' local LABEL `"`LABEL'`"`LBL'`S' (`OBS')"' "' } } /* End */ } * ---------------------------------------------------------------------------- * 9. Return info of interest * ---------------------------------------------------------------------------- /* Return command */ return local command `"`GRAPH'"' /* Return min/max coordinates */ qui summ __POI_X return local xmin = r(min) return local xmax = r(max) qui summ __POI_Y return local ymin = r(min) return local ymax = r(max) /* Return legend info */ return local title `"`TITLE'"' return local key `"`KEY'"' return local label `"`LABEL'"' return local nk = `NK' * ---------------------------------------------------------------------------- * 10. End program * ---------------------------------------------------------------------------- restore end