*! version 1.1 Sep2003 *Now has a size (weight) option on funnel plot program define funnel,rclass version 7.0 syntax [varlist(default=none)] [if] [in] [aweight] [ , SAmple noINVert YSQrt YLAbel(string) /* */ OVerall(string) YLOg XLOg SAving(string) YTICK(string) * ] if "`weight'"!="" {local weight "[ `weight' `exp']" } if "`varlist'"=="" { *No variables specified: use _ES with _seES (_selogES) or _SS as saved previously from metan *Name of effect size should be held in r(measure) local es= r(measure) if ("`es'"=="." | "`es'"=="") { di in re "funnel must either:" _n " 1. be run immediately after metan, or" di in re " 2. declare also the effect size and its standard error" exit } if ("`es'"=="OR" |"`es'"=="RR" ) { local xlog "xlog" local log "log" } if "`es'"=="" { local es "Effect size" } if "`sample'"=="" { *Plot se or 1/se vs effect size if "`invert'"=="" { local oneover "1/" } local 2 "_se`log'ES" local varlab2 : var label `2' if "`varlab2'"=="" { local varlab2 "SE(`log'`es')" } local varlab2 "`oneover'`varlab2'" } *Plot sample size vs effect size else { local 2 "_SS" local varlab2 "Sample size" } local 1 "_ES" local varlab1 : var label _ES if "`varlab1'"=="" { local varlab1 "`es'" } if "`log'"!="" { local varlab1 "`varlab1' (log scale)" } } else { * plot variables as specified parse "`varlist'", parse(" ") confirm var `1' `2' cap assert ("`3'"=="" & "`2'"!="") if _rc!=0 { di in re "incorrect variable list" exit _rc } if "`sample'"=="" & "`invert'"=="" { local oneover "1/" } local varlab1 : var label `1' if "`varlab1'"=="" { local varlab1 `1'} local varlab2 : var label `2' if "`varlab2'"=="" { local varlab2 `2' } local varlab2 "`oneover'`varlab2'" } qui { tempvar stat Y gen `Y' =`oneover'`2' `if' `in' gen `stat' =`1' `if' `in' label var `Y' "`varlab2'" label var `stat' "`varlab1'" if "`ylabel'"=="" { sum `Y',meanonly local rmin= r(min) local rmax= r(max) local ylabel "`rmin',`rmax'" } if "`ysqrt'"!="" { tempvar temp gen `temp'=`Y' drop `Y' tempvar Y if "`ytick'"!="" { local trylabel="`ytick',`ylabel'" } else { local trylabel="`ylabel'" } axiscale `Y'=`temp' `if' `in', label(`trylabel') function(sqrt[@]) local ylabel $S_15 if "`ytick'"!="" { *now to separate contents of fylabel into ylabel and ytick! Rather than do that though, *change _LAB so that yticks are given a null label. tokenize "`ytick'", parse(,) local nyticks=0 while "`1'"!="" { *Find out how many ticks are to be removed local nyticks=`nyticks'+1 mac shift 2 } tokenize "`ylabel'", parse(,) local i=1 while `i'<=`nyticks' { label define _LAB `1' " " , modify mac shift 2 local i=`i'+1 } local ytick } label var `Y' "`varlab2', square root scale" } } /* end of qui section*/ if "`ytick'"!="" { local ytick "ytick(`ytick')" } graph `Y' `stat' `weight', ylabel(`ylabel') `xlog' `ylog' `ytick' `options' if "`saving'"!="" { local saving "saving(`saving')" } gph open, `saving' graph gph font 300 200 local Gymin=r(ymin) local Gymax=r(ymax) local r5 =r(ay) local r6 =r(by) local r7 =r(ax) local r8 =r(bx) local flag1=0 if "`overall'"!="" { * add dashed line qui sum `stat' local minstat=r(min) local maxstat=r(max) parse "`overall'", parse(" ") cap { assert "`2'"=="" assert `1'>=`minstat' assert `1'<=`maxstat' } if _rc!=0 {local flag1=1} else { gph pen 9 local Gxov=`1' if "`xlog'"!="" {local xlog "log"} if "`ylog'"!="" {local ylog "log"} local Axco=`r7'*`xlog'(`Gxov')+`r8' local j =`r5'*`ylog'(`Gymin')+`r6' local Adashl=`r5'*(`ylog'(`Gymax')-`ylog'(`Gymin'))/100 local Ayhi=`r5'*`ylog'(`Gymax')+`r6' while `j'>`Ayhi' { local Aycol=`j' local Aycoh=`j'+`Adashl' gph line `Aycol' `Axco' `Aycoh' `Axco' local j=`j'+2*`Adashl' } } } gph close if `flag1'>0 { di in blue "Error in overall() option. Dashed line not displayed"} return local measure `es' end *! version 1.2.1 PR 19Nov96. /* Written by Patrick Royston as part of tgraph (STB34). Modified (scaled down) to have new axis label stored in redundant global macro S_15, instead of $S_1 as used by metan.ado */ program define axiscale version 4.0 local varlist "req new max(1)" local exp "req noprefix" local if "opt" local in "opt" #delimit ; local options "Labels(string) Function(string) MIN(string) MAX(string) Valuelab(string)" ; #delimit cr tempvar x labs newlabs new parse "`*'" if "`labels'"=="" | "`functio'"=="" { di in red "labels() and function() must be supplied" exit 198 } if "`min'"!="" { conf num `min' } else local min . if "`max'"!="" { conf num `max' } else local max . if "`valuela'"=="" { local valuela _LAB } * Find min and max of oldvar quietly { gen `x'=`exp' `if' `in' sum `x' if `min'==. { local min=_result(5) } else if `min'>_result(5) { noi di in red "invalid min(), `min'> min(`exp')" exit 198 } if `max'==. { local max=_result(6) } else if `max'<_result(6) { noi di in red "invalid max(), `max' < max(`exp')" exit 198 } * Convert labels to a var, including min and max gen `labs'=. parse "`labels',`min',`max'", parse(",") local nlab 0 while "`1'"!="" { if "`1'"!="," { conf num `1' local nlab=`nlab'+1 local lab`nlab' `1' /* store label as string */ replace `labs'=`1' in `nlab' } mac shift } * Update min and max for consistency with labels sum `labs' if `min'>_result(5) { local nlab1=`nlab'-1 local min=_result(5) replace `labs'=`min' in `nlab1' } if `max'<_result(6) { local max=_result(6) replace `labs'=`max' in `nlab' } * Transform labels parse "`functio'", parse("@[]") local f while "`1'"!="" { if "`1'"=="@" { local 1 `labs' } else if "`1'"=="[" { local 1 "(" } else if "`1'"=="]" { local 1 ")" } local f "`f'`1'" mac shift } cap replace `labs'=`f' local rc=_rc if `rc' { noisily error `rc' } local tmin=`labs'[`nlab'-1] local tmax=`labs'[`nlab'] if `tmin'>`tmax' { local temp `tmin' local tmin `tmax' local tmax `temp' } * Transform oldvar parse "`functio'", parse("@[]") local f while "`1'"!="" { if "`1'"=="@" { local 1 `x' } else if "`1'"=="[" { local 1 "(" } else if "`1'"=="]" { local 1 ")" } local f "`f'`1'" mac shift } cap replace `x'=`f' local rc=_rc if `rc' { noisily error `rc' } * Transform transformed oldvar to integer scale gen int `new'=. rescale `new' `x' `tmin' `tmax' /* tmin->0, tmax->1000 */ * Do same to labels gen int `newlabs'=. rescale `newlabs' `labs' `tmin' `tmax' * Convert newlabs to string local xxl /* string of new labels */ cap lab drop `valuela' local i 0 while `i'<`nlab'-2 { local i=`i'+1 local xx=`newlabs'[`i'] if "`xxl'"=="" { local xxl `xx' } else local xxl "`xxl',`xx'" lab def `valuela' `xx' "`lab`i''",add } replace `varlist'=`new' lab values `varlist' `valuela' lab var `varlist' "`exp', transformed scale" } describe `varlist' global S_15 `xxl' *global S_NJC `xxl' end program define rescale /* newintvar oldtsfvar tsfmin tsfmax */ replace `1'=int(1000*(`2'-`3')/(`4'-`3')+.5) end