*! ae_volcano ver 1.0 10/02/2020 *start with row per event cap prog drop aevolcano cap postclose ae_volc program define aevolcano, rclass version 15.0 tempfile original tempfile ae_volcano_1 /* DESCRIPTION: Creating a volcano plot for AE data in clinical trials ver 1.0: original */ *Current syntax syntax varlist , treat(varname) id(varname) n1(integer) n2(integer) /// [ ODDSratio(integer 0) RISKratio(integer 0) PVALue(integer 0) /// PADJ(integer 0) fdrlower(varname) fdrhigher(varname) FDRval(real 0.1) /// labelyn(integer 0) label(real 1) labelnum(integer 0) /// labcol(string) labang(integer 90) labpos(integer 12) labgap(integer 5) /// labcol1(string) labang1(integer 90) labpos1(integer 12) labgap1(integer 5) /// labcol2(string) labang2(integer 90) labpos2(integer 12) labgap2(integer 5) /// xaxismin(real 0) xaxismax(real 0) xaxisdp(real 0.1) xaxisticks(real 4) /// yaxismin(real 0) yaxismax(real 0) yaxisdp(real 0.1) yaxisticks(real 4) /// xaxistitle(string) yaxistitle(string) title(string) subtitle(string) /// ylineyn(integer 0) yline(numlist) ylinepat(string) ylinecol(string) ylinewidth(real 0.5) /// mfcolor(string) mlcolor(string) /// mfcolor1(string) mlcolor1(string) /// mfcolor2(string) mlcolor2(string) /// grphcol(string) plotcol(string) /// legendyn(integer 0) legend1(string) legend2(string) legendpos(integer 6) legendcol(integer 1) legendrow(integer 2) /// SAVing(string) graphsave(string) clear ] preserve /* Syntax explanation varlist - can contain string or numeric and indicates variable that contains the AE name/identifier treat - variable containing treat allocation - recommend code treatment as 1 and placebo as 2 id - individual patient ID - patients can have more than one entry (row) n1 - number in treatment group (participants may not have all had an AE so n may be higher than n in AE dataset) n2 - number in control group (participants may not have all had an AE so n may be higher than n in AE dataset) */ /* Optional commands (1) oddsratio is optional and if not specified default is 0 which indicates output risk difference, if oddsratio is 1 then output odds ratio (2) riskratio is optional and if not specified default is 0 which indicates output risk difference, if riskratio is 1 then output risk ratio (3) pvalue is optional and if not specified default is 0 which indicates the p-value from the Fisher's exact test is used, if pvalue is 1 then p-value from Pearson's chi-squared is used ******************************************* (4) padj is optional and if not specified default is 0 which indicates no p-value adjustement if padj is 1 then the FDR p-value adjustment is invoked (5-7) these commands are available if call on aefdr command if padj is 1 then user needs to specify: (5) fdrhigher - to indicate variable with bodysystem event/higher term (6) fdrlower - to indicate variable with preferred term/lower level event term if these are not specified then error should be returned (7) fdrval is optional and indicates the value that adjustment carried out on (flags events with adjusted event/lowerterm and bodysystem/higher term p-value below it) - default is 0.1 ******************************************* (8) labelyn is optional and if not specified default is 0 which indicates bubble labels turned off, if labelyn is 1 then bubble/circle labels turned on and the option `label' can be used to indicate threshold for labels based on p-values (9) label(real 1) is optional and if not specified default value is 1 which means any variables with log10 P-value greater than 1 will be labeled, this equates to a p-value <0.1. (10) labelnum is optional and if not specified default is 0 which indicates number labels not required, if labelnum is 1 then bubble labels assigned numeric values - only applies when varlist numeric if labelnum is 2 then bubble labels assigned label values - only applies when varlist numeric (11) labcol is optional - gives overall label color. If labcol not specified then: labcol1 and labcol2 are optional and if not specified default to black - allows bubble label colour to be changed - can differ between treatment groups labcol1 and labcol2 take strings and acceptable entries include Stata colorstyle. See help colorstyle. Error message issued if entered incorrectly (12) labang is optional - gives overall label angel. If not specified then: labang1 and labang2 are optional and if not specified default is 90 giving vertical bubble labels - can differ between treatment groups (13) labpos is optional - gives overall label position. If not specified then: labpos1 and labpos2 are optional and if not specified default is 12 giving bubble labels above the point - can differ between treatment groups (14) labgap is optional - gives overall label gap. If not specified then: labgap1 and labgap2 are optional and if not specified default is 5 giving a gap of 5 points between point and bubble label - can differ between treatment groups (15) xaxismin, xaxismax, yaxismin and yaxismax(real 0) are optional commands with default 0 - they allow user to add a value to min and max x and y axis values to extend the plot area - the default 0 results in the actual min and max values being using for axis limits e.g. a value of 2 adds 2 units to the maximum. (16) xaxisticks and yaxisticks are optional with default 4 - they allow the user to specify how the xaxis and yaxis are divided/how the ticks are spaced. This divides the range (max-min) of xaxis and yaxis values and will incorporate and additions made to this range through xaxismin, xaxismax, yaxismin and yaxismax (17) xaxisdp and yaxisdp are optional with default 0.1 - they allow the user to specify the units the xaxis and yaxis values are rounded to (18) ylineyn is optional and if not specified then default is 0 which indicates that yline is "off" which means line colour is white and therefore does not appear on the plot i.e. sets default to yline off if ylineyn is 1 then defaults below apply (19) yline is optional and if not specified default is to give a line at value of 1 which equates to a p-value of 0.1 Unless the aefdr adjustment used in which case the yline is plotted at the min adjusted p-value to indicate significance and if no events were flagged as significant after adjustment the line is set at 0 yline can take a list of numbers to produce multiple horizontal lines (20) ylinepat is optional and if not specified defaults to dash - giving a dashed yline ylinepat takes strings, acceptable entries include Stata linepatternstyle e.g. solid, dash, dot, dash dot, shortdash, shortdash dot, longdash, longdash dot, blank. See help linepatternstyle. Error message issued if entered incorrectly (21) ylinecol is optional and if not specified defaults to bluishgray - giving a bluishgrey horizontal line ylinecol takes strings and acceptable entries include Stata colorstyle. See help colorstyle Error message issued if entered incorrectly (22) ylinewidth is optional and if not specified defaults to line width of 0.5 (23) mfcolor is optional - gives overall bubble fill color. If mfcolor not specified then: mfcolor1 and mfcolor2 are optional and default to red and blue filled bubbles if not specified mfcolor1 and mfcolor2 take strings and acceptable entries include Stata colorstyle. See help colorstyle Error message issued if entered incorrectly (24) mlcolor - mlcolor1 and mlcolor2 are optional and default to red and blue outlines for bubbles if not specified mlcolor1 and mlcolor2 take strings and acceptable entries include Stata colorstyle. See help colorstyle Error message issued if entered incorrectly (25) mfcolsat, mfcolsat1 and mfcolsat2 default to 80 - gives saturation of bubble fill colour (26) mlcolsat, mlcolsat1 and mlcolsat2 are restricted 80 - gives saturation of bubble outline colour ****mfcolsat1, mfcolsat2, mlcolsat1 and mlcolsat2 are restricting the bubble colour opacity and are set at standard values (27) grphcol and plotcol are optional and default to white background for plot and graph background colour grphcol and plotcol take strings and acceptable entries include colorstyle. See help colorstyle Error message issued if entered incorrectly (28) legendyn is optional and if not specified default value is 0 which indicates legend turned off if legendyn is 1 then legend on and the options `legend1' and `legend2' can be used to add text to the legend If legendyn is 1 and legend1 and legend2 not specified legend will display "Risk in Group 1" and "Risk in Group 2" */ /* *NOTES (1) Allow labels to change position, angle and gap from bubble but sometimes labels still overlap - in this scenario advise users to switch labels off and insert own labels. Alternatively use a numeric variable and label with numbers (2) Number of labels specified by choosing log10 P-value that should be exceeded e.g. 1 which equates to p-value less than 0.1. (3) Incorporates a continuity correction (adds 0.5 an event to each group) when fitting odds or risk and there are 0 events in one of the arms (4) Odds ratio risk ratio plotted on log scale to ensure symmetrical axis */ ********************************************************************************** qui{ /* open the big quietly loop around aevolcano*/ local mlcolsat = 80 local mlcolsat1 = 80 local mlcolsat2 = 80 local mfcolsat = 80 local mfcolsat1 = 80 local mfcolsat2 = 80 ****Error checking********* *Confirm patient id numeric cap confirm numeric variable `id' local id_num = _rc if `id_num' !=0 { display as error "id variable not numeric" exit 7 } *treat needs to contain a number cap confirm numeric variable `treat' local treat_num = _rc if `treat_num' !=0 { display as error "treat variable not numeric" exit 7 } *Only one of oddsratio or riskratio can be specified if `oddsratio'==1 & `riskratio'==1 { display as error "only one of oddsratio or riskratio can be specified at a time" exit 7 } *pvalue can only take values 0 or 1 to indicate if Fisher's exact or Pearson's chi squared p-values should be used if `pvalue' >1 | `pvalue'<0 { display as error "pvalue can only take values 0 or 1" exit 7 } *padj can only take values 0 or 1 to indicate if p-value adjustment should be used if `padj' >1 | `padj'<0 { display as error "padj can only take values 0 or 1" exit 7 } *if padj=1 then calls aefdr command which requires fdrhigher and fdrlower to be specified if (`padj' ==1 & "`fdrhigher'"=="") | (`padj' ==1 & "`fdrlower'"=="") { display as error "if padj specified then fdrhigher and fdrlower required" exit 7 } if (`padj' ==0 & "`fdrhigher'"!="") { display as error "fdrhigher not applicable if no adjustment" exit 7 } if (`padj' ==0 & "`fdrlower'"!="") { display as error "fdrlower not applicable if no adjustment" exit 7 } *labelyn can only take values 0 or 1 to indicate if labels off or on, respectively if `labelyn' >1 | `labelyn'<0 { display as error "labelyn can only take values 0 or 1" exit 7 } *labelnum can only take values 0 or 1 or 2 to indicate if labels should take numeric values or labels - only applicable when varlist is numeric - this is checked further down if `labelnum' >2 | `labelnum'<0 { display as error "labelnum can only take values 0, 1 or 2" exit 7 } if `labelyn'==0 & `labelnum'!=0 { display as error "labelnum only applicable when labels turned on" exit 7 } if "`labcol'"!=""{ local labcol1="`labcol'" local labcol2="`labcol'" } *If labang not equal to default value then individual labang commands can be used if "`labang'"!="90"{ local labang1=`labang' local labang2=`labang' } if "`labpos'"!="12"{ local labpos1=`labpos' local labpos2=`labpos' } if "`labgap'"!="5"{ local labgap1=`labgap' local labgap2=`labgap' } if "`mfcolor'"!=""{ local mfcolor1="`mfcolor'" local mfcolor2="`mfcolor'" } if "`mlcolor'"!=""{ local mlcolor1="`mlcolor'" local mlcolor2="`mlcolor'" } *labpos can only take integer values between 0 and 12 if "`labpos'"!=""{ if `labpos' >12 | `labpos'<0 { display as error "labpos can only take integer values between 0 and 12" exit 7 } } if `labpos1' >12 | `labpos1'<0 { display as error "labpos1 can only take integer values between 0 and 12" exit 7 } if `labpos2' >12 | `labpos2'<0 { display as error "labpos2 can only take integer values between 0 and 12" exit 7 } ******setting linepattern default before error checking*************************** *Linepattern defaults to dash if "`ylinepat'" == "" { local ylinepat= "dash" } *if default y line off then use ylineyn to default colour to white so can't see it if `ylineyn' >1 | `ylineyn'<0 { display as error "ylineyn can only take values 0 or 1" exit 7 } if `ylineyn'==0 { local ylinecol = "white" } *yline colour defaults to bluishgray if `ylineyn'==1 & "`ylinecol'" == "" { local ylinecol = "bluishgray" } *******Error checking - restrict ylinepat to the linepattern available in Stata******** local test = c(sysdir_base) local test2 = "`test'"+"style" local linepatopt : dir "`test2'" files "linepattern-*.style" local linepatopt : list clean linepatopt local linepatopt: subinstr local linepatopt "linepattern-" "", all local linepatopt: subinstr local linepatopt ".style" "", all local linepatopt: subinstr local linepatopt "blank" "", all tempvar lpat1 gen `lpat1'=0 if "`ylinepat'"!="" { foreach lname in `linepatopt' { cap replace `lpat1'=1 if "`lname'"=="`ylinepat'" } } if `lpat1'== 0 { disp as error "`ylinepat' is not a Stata linepattern style. Please see Stata linepatternstyle for acceptable options" exit 198 } *************Setting default colours before error checking************ *Label colours if "`labcol1'" == "" { local labcol1 = "black" } if "`labcol2'" == "" { local labcol2 = "black" } *Default bubble colour fill in group with risk difference >=0 plot to red (if treatment =1 and control = 2 then riskdiff>=0 indicates increased risk in treatment grp) if "`mfcolor1'" == "" { local mfcolor1 ="red" } *Default bubble colour fill in group with risk difference <0 plot to blue (if treatment =1 and control = 2 then riskdiff<0 indicates increased risk in control grp) if "`mfcolor2'" == "" { local mfcolor2 ="blue" } *Default bubble colour outline in risk difference >=0 plot to red if "`mlcolor1'" == "" { local mlcolor1 ="red" } *Default bubble colour outline in risk difference <0 plot to blue if "`mlcolor2'" == "" { local mlcolor2 ="blue" } *Default plot background colour to white if "`plotcol'" =="" { local plotcol = "white" } *Default graph background colour to white if "`grphcol'" =="" { local grphcol = "white" } ***Error checking colours**************** local test = c(sysdir_base) local test2 = "`test'"+"style" local coloropt : dir "`test2'" files "color-*.style" local coloropt : list clean coloropt local coloropt: subinstr local coloropt "color-" "", all local coloropt: subinstr local coloropt ".style" "", all local coloropt: subinstr local coloropt "blank" "", all tempvar col1 gen `col1'=0 if "`mfcolor1'"!="" { foreach lname in `coloropt' { cap replace `col1'=1 if "`lname'"=="`mfcolor1'" } } if `col1'== 0 { disp as error "`mfcolor1' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col2 gen `col2'=0 if "`mfcolor12"!="" { foreach lname in `coloropt' { cap replace `col2'=1 if "`lname'"=="`mfcolor2'" } } if `col2'== 0 { disp as error "`mfcolor2' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col3 gen `col3'=0 if "`labcol1"!="" { foreach lname in `coloropt' { cap replace `col3'=1 if "`lname'"=="`labcol1'" } } if `col3'== 0 { disp as error "`labcol1' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col4 gen `col4'=0 if "`labcol2"!="" { foreach lname in `coloropt' { cap replace `col4'=1 if "`lname'"=="`labcol2'" } } if `col4'== 0 { disp as error "`labcol2' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col5 gen `col5'=0 if "`ylinecol"!="" { foreach lname in `coloropt' { cap replace `col5'=1 if "`lname'"=="`ylinecol'" } } if `col5'== 0 { disp as error "`ylinecol' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col6 gen `col6'=0 if "`mlcolor1"!="" { foreach lname in `coloropt' { cap replace `col6'=1 if "`lname'"=="`mlcolor1'" } } if `col6'== 0 { disp as error "`mlcolor1' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col7 gen `col7'=0 if "`mlcolor2"!="" { foreach lname in `coloropt' { cap replace `col7'=1 if "`lname'"=="`mlcolor2'" } } if `col7'== 0 { disp as error "`mlcolor2' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col8 gen `col8'=0 if "`plotcol"!="" { foreach lname in `coloropt' { cap replace `col8'=1 if "`lname'"=="`plotcol'" } } if `col8'== 0 { disp as error "`plotcol' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } tempvar col9 gen `col9'=0 if "`grphcol"!="" { foreach lname in `coloropt' { cap replace `col9'=1 if "`lname'"=="`grphcol'" } } if `col9'== 0 { disp as error "`grphcol' is not a colour. Please see Stata colorstyle for acceptable options" exit 198 } *legendyn can only take values 0 or 1 if `legendyn' >1 | `legendyn'<0 { display as error "legendyn can only take values 0 or 1" exit 7 } *Legend labels can only be specified when legend on if `legendyn' ==0 & "`legend1'"!="" { display as error "legend1 can only be specified when legend on" exit 7 } if `legendyn' ==0 & "`legend2'"!="" { display as error "legend2 can only be specified when legend on" exit 7 } *legendpos can only take integer values between 0 and 12 if `legendpos' >12 | `legendpos'<0 { display as error "legendpos can only take integer values between 0 and 12 " exit 7 } *Error checking - saving command correctly specified if "`saving'" != "" { tokenize "`saving'", parse(",") local filename `1' local replace `3' if "`replace'" == "" { confirm new file `filename'.dta } if "`replace'" != "" { if "`replace'" != "replace" { display as error "option saving, `replace' not allowed" } } } if "`graphsave'"!="" { tokenize "`graphsave'" , parse(",") local graphname `1' local graphreplace `3' if "`graphreplace'" == "" { confirm new file `graphname'.gph } if "`graphreplace'" != "" { if "`graphreplace'" != "replace" { display as error "option saving, `graphreplace' not allowed" } } } ************************************************************************************************************************* tokenize `varlist' local by "`1'" *local event "`1'" *Error message if specify more than one variable to analyse by if "`2'"!="" { display as error "too many variables specified. Please specify only one variable to examine the adverse events by." exit 198 } *Create numeric/string indicators for higher/loewr fdr for use after post file below to direct ae_fdr cap confirm numeric variable `fdrhigher' local higher_n_rc=_rc di `higher_n_rc' cap confirm numeric variable `fdrlower' local lower_n_rc=_rc di `lower_n_rc' cap confirm string variable `fdrhigher' local higher_s_rc=_rc di `higher_s_rc' *If numerical can keep labels if required cap confirm numeric variable `by' local num_status = _rc if `num_status' ==0 { if `labelnum'==2{ tempvar by_decoded decode `by', gen(`by_decoded') local by "`by_decoded'" local varlist "`by_decoded'" } } /*Code for string variable*/ if substr("`:type `by''" ,1,3) == "str" { levelsof `treat', matrow(uniqlist) mat list uniqlist *matrix with a row for each treatment arm local count_treat=r(r) *local var with number of treatment arms mat define results=J(`count_treat',3,.) *matrix with 3 columns and number of rows as defined by `count_treat' which is number of treatment arms egen ae_id = group(`by') *gen a numeric variable for each AE listed in by (where by is the list of variables in varlist of syntax) tab ae_id local count=r(r) *local var with number of distinct AEs save `original'.dta , replace postfile ae_volc r1 r2 risk_diff odds_ratio log_OR risk_ratio log_RR n_events p_val log_p_val p_val_chi log_p_val_chi str80 event str80 bs_event using `ae_volcano_1'.dta, replace forvalues i=1(1)`count' { *runs through the following for each AE use `original'.dta , clear keep if ae_id==`i' *Keeps all occurrences of the first AE, then on next run through the second AE and so on forvalues t=1(1)`count_treat'{ *runs through it for each treatment group separately local arm_level=uniqlist[`t',1] di `arm_level' inspect `id' if `treat'==`arm_level' *Summarises every variable when treatment group =1 and then 2 and so dependent on how many arms there are but the plot really only applicable when two groups local n_`t' = r(N_unique) *local var with number of AEs *If there are more than 99 unique values then r(N_unique) will be set to missing *to overcome this use the levelsof command instead if `n_`t'' ==. { levelsof `id' if `treat'==`arm_level' local n_`t' = r(r) } local r`t' = `n_`t''/`n`t'' *local var with proportion where n_t comes from previous line and nt comes from syntax line local n`t'_p2 = `n`t''-`n_`t'' *local var with number on treatment arm minus those with event - gives number without event local tot_`t' = `n`t'' } **********RISK DIFFERENCE & P-VALUE***************** *Now using info from each treatment group local risk_diff=(`n_1'/`n1')-(`n_2'/`n2') *local var with proportion in treatment 1 - proportion in treatment 2 tabi `n_1' `n1_p2' \ `n_2' `n2_p2', exact chi *direct test with number with and without event in each treatment group *gives fishers exact p-value and chi-squared p-value local p_val = r(p_exact) *local var containing p-value from Fisher's exact test from the tabi command local log_p = -1*log10(`p_val') *local var containing the log of the above p-value local p_val_chi = r(p) *local var containing p-value from chi squared test issued in tabi command local log_p_chi = -1*log10(`p_val_chi') *local var containing the log of the chi-squared p-value ************************************************ *If 0 events present then the risk ratio and odds ratio are non-calcuable, to avoid this we add 0.5 an event if `n_1'==0 & `n_2'!=0 { local n_1 = 0.5 local n_2 = `n_2'+0.5 local tot_1 = `tot_1'+0.5 local tot_2 = `tot_2'+0.5 local n1_p2 = `tot_1'-`n_1' local n2_p2 = `tot_2'-`n_2' } if `n_2'==0 & `n_1'!=0 { local n_2 = 0.5 local n_1 = `n_1'+0.5 local tot_1 = `tot_1'+0.5 local tot_2 = `tot_2'+0.5 local n1_p2 = `tot_1'-`n_1' local n2_p2 = `tot_2'-`n_2' } *****************ODDS RATIO******************* local odds_ratio=(`n_1'/`n1_p2')/(`n_2'/`n2_p2') local logOR = log((`n_1'/`n1_p2')/(`n_2'/`n2_p2')) ************************************************ *****************RISK RATIO***************** local risk_ratio=(`n_1'/`tot_1')/(`n_2'/`tot_2') local logRR = log((`n_1'/`tot_1')/(`n_2'/`tot_2')) ********************************************** count *count is a local var that will call number of individual AEs local events = r(N) local e_name = "`varlist'" in 1 di `e_name' if "`fdrhigher'" !="" { local bs_name = `fdrhigher' in 1 di "`bs_name'" } else { local bs_name = "" } post ae_volc (`r1') (`r2') (`risk_diff') (`odds_ratio') (`logOR') (`risk_ratio') (`logRR') (`events') (`p_val') (`log_p') (`p_val_chi') (`log_p_chi') (`e_name') ("`bs_name'") use `original'.dta , clear } } else { /* numeric option*/ local by "`1'" macro shift levelsof `treat', matrow(uniqlist) mat list uniqlist local count_treat=r(r) mat define results=J(`count_treat',3,.) egen ae_id = group(`by') tab ae_id local count=r(r) save `original'.dta , replace postfile ae_volc r1 r2 risk_diff odds_ratio log_OR risk_ratio log_RR n_events p_val log_p_val p_val_chi log_p_val_chi eventnum bsnum str80 bs_event using `ae_volcano_1'.dta, replace forvalues i=1(1)`count' { use `original'.dta , clear keep if ae_id==`i' forvalues t=1(1)`count_treat'{ local arm_level=uniqlist[`t',1] di `arm_level' inspect `id' if `treat'==`arm_level' local n_`t' = r(N_unique) *If there are more than 99 unique values then r(N_unique) will be set to missing *to overcome this use the levelsof command instead if `n_`t'' ==. { levelsof `id' if `treat'==`arm_level' local n_`t' = r(r) } local r`t' = `n_`t''/`n`t'' local n`t'_p2 = `n`t''-`n_`t'' local tot_`t' = `n`t'' } ********RISK DIFFERENCE & P-VALUE****************** local risk_diff=(`n_1'/`n1')-(`n_2'/`n2') tabi `n_1' `n1_p2' \ `n_2' `n2_p2', exact chi local p_val = r(p_exact) local log_p = -1*log10(`p_val') local p_val_chi = r(p) local log_p_chi = -1*log10(`p_val_chi') **************************************************** if `n_1'==0 & `n_2'!=0 { local n_1 = 0.5 local n_2 = `n_2'+0.5 local tot_1 = `tot_1'+0.5 local tot_2 = `tot_2'+0.5 local n1_p2 = `tot_1'-`n_1' local n2_p2 = `tot_2'-`n_2' } if `n_2'==0 & `n_1'!=0 { local n_2 = 0.5 local n_1 = `n_1'+0.5 local tot_1 = `tot_1'+0.5 local tot_2 = `tot_2'+0.5 local n1_p2 = `tot_1'-`n_1' local n2_p2 = `tot_2'-`n_2' } *****************ODDS RATIO******************* local odds_ratio=(`n_1'/`n1_p2')/(`n_2'/`n2_p2') local logOR = log((`n_1'/`n1_p2')/(`n_2'/`n2_p2')) *********************************************** *****************RISK RATIO***************** local risk_ratio=(`n_1'/`tot_1')/(`n_2'/`tot_2') local logRR = log((`n_1'/`tot_1')/(`n_2'/`tot_2')) ********************************************** count local events = r(N) *getting the numeric value for the event local e_name_num = "`by'" in 1 di `e_name_num' cap confirm numeric variable `fdrhigher' local bs_num = _rc *if higherterm is also numeric capturing the numeric value if "`fdrhigher'" !="" & `bs_num'==0 { local bs_name_num = "`fdrhigher'" in 1 di `bs_name_num' } if "`fdrhigher'" =="" | `bs_num'!=0 { local bs_name_num = . } *if higherterm is string then if "`fdrhigher'" !="" & `bs_num'!=0 { *getting the string label for the event local bs_name = `fdrhigher' in 1 di "`bs_name'" } if "`fdrhigher'" =="" | `bs_num'==0 { local bs_name = "" } post ae_volc (`r1') (`r2') (`risk_diff') (`odds_ratio') (`logOR') (`risk_ratio') (`logRR') (`events') (`p_val') (`log_p') (`p_val_chi') (`log_p_chi') (`e_name_num') (`bs_name_num') ("`bs_name'") use `original'.dta , clear } } postclose ae_volc use `ae_volcano_1'.dta, clear lab var r1 "Proportion with event in group 1" lab var r2 "Proportion with event in group 2" lab var risk_diff "Risk difference" lab var odds_ratio "Odds ratio" lab var log_OR "log(odds ratio)" lab var risk_ratio "Risk ratio" lab var log_RR "log(risk ratio)" lab var n_events "Total number of events" lab var p_val "Fisher's exact p-value" lab var log_p_val "log(Fisher's exact p-value)" lab var p_val_chi "Chi-squared test p-value" lab var log_p_val_chi "log(Chi-squared test p-value)" cap lab var event "AE name (lower level)" cap lab var bs_event "Bodysystem name (higher level)" cap lab var eventnum "AE number (lower level)" cap lab var bsnum "Bodysystem number (higher level)" sort event save `ae_volcano_1'.dta , replace ****************************************************************************************************** *call on aefdr command - current version aefdr.ado - program included at the end of this code *For string variables (this will include numerics with labels turned into strings - if lablnum=2) cap confirm string variable bs_event local body_string = _rc cap confirm string variable event local event_string = _rc *PATH FOR STRING STRING or STRING NUMERIC (as bs_event always a string within even when body system started numeric) if `body_string'==0 & `event_string'==0 { if `padj' ==1 { *If p-value adjustment on if `pvalue'==0 { *if default p-value calculated (Fisher's exact) use variable "p_val" for aefdr command aefdr , fdrhigher(bs_event) fdrlower(event) pvalueadj(p_val) fdrval(`fdrval') summ p_val if flag==1 local ynumadj= r(max) local log_ynumadj = -1*log10(`ynumadj') sort event merge event using `ae_volcano_1'.dta *aefdr replace the dataset that we need - ae_volcano_1. Merge ae_volcano_1 in so that now includes the adjusted p-values } else { *if p-value chi-squared p-value calculated use variable "p_val_chi" for aefdr command aefdr , fdrhigher(bs_event ) fdrlower(event) pvalueadj(p_val_chi) fdrval(`fdrval') summ p_val_chi if flag==1 local ynumadj= r(max) local log_ynumadj = -1*log10(`ynumadj') sort event merge event using `ae_volcano_1'.dta } } } *For numeric variables (excluding those which have aready been turned to string for labels if labelnum==2) if `labelnum'!=2 { local body_numeric = `higher_n_rc' local event_numeric = `lower_n_rc' } else { local body_numeric = 123 local event_numeric = 123 } *PATH FOR NUMERIC NUMERIC if `body_numeric'==0 & `event_numeric'==0 { if `padj' ==1 { *If p-value adjustment on if `pvalue'==0 { *if default p-value calculated (Fisher's exact) use variable "p_val" for aefdr command aefdr , fdrhigher(bsnum) fdrlower(eventnum) pvalueadj(p_val) fdrval(`fdrval') *egen ynum_adj = max(p_val) if flag==1 summ p_val if flag==1 local ynumadj= r(max) local log_ynumadj = -1*log10(`ynumadj') sort event merge event using `ae_volcano_1'.dta } else { *if p-value chi-squared p-value calculated use variable "p_val_chi" for aefdr command aefdr , fdrhigher(bsnum ) fdrlower(eventnum) pvalueadj(p_val_chi) fdrval(`fdrval') summ p_val_chi if flag==1 local ynumadj= r(max) local log_ynumadj = -1*log10(`ynumadj') sort event merge event using `ae_volcano_1'.dta } } } **PATH FOR NUMERIC STRING: if `labelnum'!=2 { local body_string2 = `higher_s_rc' local event_numeric = `lower_n_rc' } else { local body_string2 = 123 local event_numeric = 123 } if `body_string2'==0 & `event_numeric'==0 { if `padj' ==1 { *If p-value adjustment on if `pvalue'==0 { *if default p-value calculated (Fisher's exact) use variable "p_val" for aefdr command *bsnum will be numeric or empty if body system is a string aefdr , fdrhigher(bs_event) fdrlower(eventnum) pvalueadj(p_val) fdrval(`fdrval') summ p_val if flag==1 local ynumadj= r(max) local log_ynumadj = -1*log10(`ynumadj') sort event merge event using `ae_volcano_1'.dta } *if `pvalue'==1 { else { *if p-value chi-squared p-value calculated use variable "p_val_chi" for aefdr command aefdr , fdrhigher(bs_event ) fdrlower(eventnum) pvalueadj(p_val_chi) fdrval(`fdrval') summ p_val_chi if flag==1 local ynumadj= r(max) local log_ynumadj = -1*log10(`ynumadj') sort event merge event using `ae_volcano_1'.dta } } } cap drop _merge summ p_val, d sort p_val save `ae_volcano_1'.dta , replace ****************Creating labels****************** /*Creates a label (mylabel) for all events that exceed log_p value above a specified value in the syntax The default is 1 which means any variables with log10 p-value greater than 1 will be labeled which equates to a p-value <0.1 */ *If no adjustment and Fisher's exact test used then use log_p_val for labels if `padj' ==0 & `pvalue'==0 { *If labelyn is 1 then labels are switched on *if label not specified then default value for label is 1 *this labels all events with log_p_val>1 if `labelyn' ==1 & (`labelnum'==0 | `labelnum'==2) { gen mylabel = event if log_p_val>`label' } } *If no adjustment and Chi squared test used then use log_p_val for labels if `padj' ==0 & `pvalue'==1 { *If labelyn is 1 then labels are switched on *if label not specified then default value for label is 1 *this labels all events with log_p_val>1 if `labelyn' ==1 & (`labelnum'==0 | `labelnum'==2) { gen mylabel = event if log_p_val_chi>`label' } } *If adjustment used and Fisher's exact then if `padj' ==1 & `pvalue'==0 { *If labelyn is 1 then labels are switched on *and if ynumadj has a value use this as label threshold if `labelyn' ==1 & (`labelnum'==0 |`labelnum'==2 ) & `ynumadj'!=. { gen mylabel = event if log_p_val>`log_ynumadj' } } *If adjustment used and Chi squared used then if `padj' ==1 & `pvalue'==1 { *If labelyn is 1 then labels are switched on *and if ynumadj has a value use this as label threshold if `labelyn' ==1 & (`labelnum'==0 |`labelnum'==2 ) & `ynumadj'!=. { gen mylabel = event if log_p_val_chi>`log_ynumadj' } } if `padj' ==1 & `pvalue'==0 { *If labelyn is 1 then labels are switched on *but if ynumadj is missing then default to value of label if `labelyn' ==1 & (`labelnum'==0 |`labelnum'==2 ) & `ynumadj'==. { gen mylabel = event if log_p_val>`label' } } if `padj' ==1 & `pvalue'==1 { *If labelyn is 1 then labels are switched on *but if ynumadj is missing then default to value of label if `labelyn' ==1 & (`labelnum'==0 |`labelnum'==2 ) & `ynumadj'==. { gen mylabel = event if log_p_val_chi>`label' } } ******************* *Allowing numeric labels when input variables are numeric if `labelnum'!=2 { cap confirm numeric variable eventnum local event_num = _rc if `event_num'!=0 & `labelnum'!=0 { display as error "labelnum=1 only applicable when varlist is a numeric variable" exit 7 } } else { local event_num = 123 } *If no adjustment and Fisher's exact then use log_p_val for labels if `padj' ==0 & `pvalue'==0 { if `labelyn' ==1 & `labelnum'==1 & `event_num'==0 { gen mylabel = eventnum if log_p_val>`label' } } *If no adjustment and Chi squared used then use log_p_val for labels if `padj' ==0 & `pvalue'==1 { if `labelyn' ==1 & `labelnum'==1 & `event_num'==0 { gen mylabel = eventnum if log_p_val_chi>`label' } } *If adjustment and Fisher's exact used then if `padj' ==1 & `pvalue'==0 { if `labelyn' ==1 & `labelnum'==1 & `event_num'==0 & `ynumadj'!=. { gen mylabel = eventnum if log_p_val>`log_ynumadj' } } *If adjustment and Fisher's exact used then if `padj' ==1 & `pvalue'==1 { if `labelyn' ==1 & `labelnum'==1 & `event_num'==0 & `ynumadj'!=. { gen mylabel = eventnum if log_p_val_chi>`log_ynumadj' } } if `padj' ==1 & `pvalue'==0 { *If labelyn is 1 then labels are switched on *but if ynumadj is missing then default to value of label if `labelyn' ==1 & `labelnum'==1 & `event_num'==0 & `ynumadj'==. { gen mylabel = eventnum if log_p_val>`label' } } if `padj' ==1 & `pvalue'==1 { *If labelyn is 1 then labels are switched on *but if ynumadj is missing then default to value of label if `labelyn' ==1 & `labelnum'==1 & `event_num'==0 & `ynumadj'==. { gen mylabel = eventnum if log_p_val_chi>`label' } } cap confirm variable mylabel if _rc==0 { cap confirm string variable mylabel if _rc!=0 { tostring mylabel, gen(mylabel2) drop mylabel rename mylabel2 mylabel replace mylabel="" if mylabel=="." } } *If labelyn is 0 then labels switched off if `labelyn' ==0 { gen mylabel = "" } *************Setting defaults************ *xaxis title and yaxis title if "`xaxistitle'" =="" & `oddsratio'==0 & `riskratio'==0 { local xaxistitle = "Risk difference" } if "`xaxistitle'" =="" & `oddsratio'==1 { local xaxistitle = "log10(Odds ratio)" } if "`xaxistitle'" =="" & `riskratio'==1 { local xaxistitle = "log10(Risk ratio)" } if "`yaxistitle'" =="" & `pvalue'==0 { local yaxistitle = "-log10(Fishers' Exact P-value)" } if "`yaxistitle'" =="" & `pvalue'==1 { local yaxistitle = "-log10(Pearson's Chi-Squared P-value)" } *Add horizontal lines to the plot - default to the same value as default for label i.e. 1 if `padj' ==0 { if "`yline'" == "" { local ynum = 1 } else { local ynum `yline' } } if `padj' ==1 { if "`yline'" == "" & `ynumadj'!=. { local ynum `log_ynumadj' } *if adjustment on and user not specified a point for yline then default colour to white so no line appears if "`yline'" == "" & `ynumadj'==. { local ynum 0 local ylinecol = "white" } if "`yline'" != "" & `ynumadj'==. { local ynum `yline' } if "`yline'" != "" & `ynumadj'!=. { local ynum `yline' `log_ynumadj' } } ************************************************** *Specifying min and max axis values *xaxis if `oddsratio'==0 & `riskratio'==0 { summ risk_diff , det local min = r(min) local max = r(max) local min_whole = (round(`min' , `xaxisdp')+`xaxismin') local max_whole = (round(`max' , `xaxisdp')+`xaxismax') local range = `max_whole' - `min_whole' local ticks = `range' / `xaxisticks' local ticks_xaxis = (round(`ticks' ,`xaxisdp')) } if `oddsratio'==1 { summ log_OR , det local min = r(min) local max = r(max) local min_whole = (round(`min' , `xaxisdp')+`xaxismin') local max_whole = (round(`max' , `xaxisdp')+`xaxismax') local range = `max_whole' - `min_whole' local ticks = `range' / `xaxisticks' local ticks_xaxis = (round(`ticks' ,`xaxisdp')) } if `riskratio'==1 { summ log_RR , det local min = r(min) local max = r(max) local min_whole = (round(`min' , `xaxisdp')+`xaxismin') local max_whole = (round(`max' , `xaxisdp')+`xaxismax') local range = `max_whole' - `min_whole' local ticks = `range' / `xaxisticks' local ticks_xaxis = (round(`ticks' ,`xaxisdp')) } *yaxis if `pvalue'== 0 { summ log_p_val , det local min_lp = r(min) local max_lp = r(max) local min_whole_lp = (round(`min_lp' , `yaxisdp')+`yaxismin') local max_whole_lp = (round(`max_lp' , `yaxisdp')+`yaxismax') local range_yaxis = `max_whole_lp' - `min_whole_lp' local ticksyaxis = `range_yaxis' / `yaxisticks' local ticks_yaxis = (round(`ticksyaxis' ,`yaxisdp')) } if `pvalue'== 1 { summ log_p_val_chi , det local min_lp = r(min) local max_lp = r(max) local min_whole_lp = (round(`min_lp' , `yaxisdp')+`yaxismin') local max_whole_lp = (round(`max_lp' , `yaxisdp')+`yaxismax') local range_yaxis = `max_whole_lp' - `min_whole_lp' local ticksyaxis = `range_yaxis' / `yaxisticks' local ticks_yaxis = (round(`ticksyaxis' ,`yaxisdp')) } ******************************************************************************* *Plot *************RISK DIFFERENCE************************************ *To give risk-diff using Fisher's exact p-value if `oddsratio'==0 & `riskratio'==0 { if `pvalue'==0 { gen pvalue_cat=1 if log_p_val<0.5 replace pvalue_cat=0 if log_p_val>=0.5 replace pvalue_cat=3 if log_p_val<0.5 & log_p_val>=0.25 replace pvalue_cat=2 if log_p_val>=0.75 gen group =1 if risk_diff>=0 & pvalue_cat==1 recode group .=2 if risk_diff>=0 & pvalue_cat==0 recode group .=3 if risk_diff>=0 & pvalue_cat==2 recode group .=4 if risk_diff>=0 & pvalue_cat==3 recode group .=5 if risk_diff<0 & pvalue_cat==1 recode group .=6 if risk_diff<0 & pvalue_cat==0 recode group .=7 if risk_diff<0 & pvalue_cat==2 recode group .=8 if risk_diff<0 & pvalue_cat==3 *Ensuring the weights are accurate and not just based on observations within the if restrictions expand 8 replace risk_diff = . if mod(_n,8) > 0 recode group (1=2) (2=3) (3=4) (4=5) (5=6) (6=7) (7=8) (8=1) if mod(_n,8) == 1 recode group (1=3) (2=4) (3=5) (4=6) (5=7) (6=8) (7=1) (8=2) if mod(_n,8) == 2 recode group (1=4) (2=5) (3=6) (4=7) (5=8) (6=1) (7=2) (8=3) if mod(_n,8) == 3 recode group (1=5) (2=6) (3=7) (4=8) (5=1) (6=2) (7=3) (8=4) if mod(_n,8) == 4 recode group (1=6) (2=7) (3=8) (4=1) (5=2) (6=3) (7=4) (8=5) if mod(_n,8) == 5 recode group (1=7) (2=8) (3=1) (4=2) (5=3) (6=4) (7=5) (8=6) if mod(_n,8) == 6 recode group (1=8) (2=1) (3=2) (4=3) (5=4) (6=5) (7=6) (8=7) if mod(_n,8) == 7 *Check that have individuals in each arm in each p-value category: *& Costruct graph code only including lines that have the combinations in data set *Incorporating legend code so that only two labels displayed (or 1 if events all in one direction) local graphcode "twoway" local segments_counter=0 count if risk_diff>=0 & pvalue_cat==2 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==3 [fw=n_events] , mfcolor(`mfcolor1'%`mfcolsat1') mlcolor(`mlcolor1'%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legend1'"=="" { local legenddef1 = "Risk in Group 1" } else { local legenddef1 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef1 = "`legend1'" } } count if risk_diff>=0 & pvalue_cat==0 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==2 [fw=n_events] , mfcolor(`mfcolor1'*0.75%`mfcolsat1') mlcolor(`mlcolor1'*0.75%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef1'"=="" { local legenddef2 = "Risk in Group 1" } else { local legenddef2 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef2 = "`legend1'" } } count if risk_diff>=0 & pvalue_cat==3 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==4 [fw=n_events] , mfcolor(`mfcolor1'*0.5%`mfcolsat1') mlcolor(`mlcolor1'*0.5%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef2'"=="" { local legenddef3 = "Risk in Group 1" } else { local legenddef3 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef3 = "`legend1'" } } count if risk_diff>=0 & pvalue_cat==1 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==1 [fw=n_events] , mfcolor(`mfcolor1'*0.25%`mfcolsat1') mlcolor(`mlcolor1'*0.25%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef3'"=="" { local legenddef4 = "Risk in Group 1" } else { local legenddef4 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef4 = "`legend1'" } } count if risk_diff<0 & pvalue_cat==2 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==7 [fw=n_events] , mfcolor(`mfcolor2'%`mfcolsat2') mlcolor(`mlcolor2'%`mlcolsat2') )" if `legendyn' ==1 & "`legend5'"=="" { local legenddef5 = "Risk in Group 2" } else { local legenddef5= "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef5 = "`legend2'" } } count if risk_diff<0 & pvalue_cat==0 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==6 [fw=n_events] , mfcolor(`mfcolor2'*0.75%`mfcolsat2') mlcolor(`mlcolor2'*0.75%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef5'"=="" { local legenddef6 = "Risk in Group 2" } else { local legenddef6 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef6 = "`legend2'" } } count if risk_diff<0 & pvalue_cat==3 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==8 [fw=n_events] , mfcolor(`mfcolor2'*0.5%`mfcolsat2') mlcolor(`mlcolor2'*0.5%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef6'"=="" { local legenddef7 = "Risk in Group 2" } else { local legenddef7 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef7 = "`legend2'" } } count if risk_diff<0 & pvalue_cat==1 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val risk_diff if group==5 [fw=n_events] , mfcolor(`mfcolor2'*0.25%`mfcolsat2') mlcolor(`mlcolor2'*0.25%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef7'"=="" { local legenddef8 = "Risk in Group 2" } else { local legenddef8 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef8 = "`legend2'" } } *To account for possibility of 0 events in either RD<0 or RD>=0 count if risk_diff>=0 & risk_diff!=. local rd_pos = r(N) count if risk_diff <0 & risk_diff!=. local rd_neg = r(N) if (`rd_pos'!=0 & `rd_pos'!=.) & (`rd_neg'!=0 & `rd_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val risk_diff if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') )" if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } local graphcode "`graphcode' (scatter log_p_val risk_diff if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if (`rd_pos'!=0 & `rd_pos'!=.) & (`rd_neg'==0 | `rd_neg'==.) { local graphcode "`graphcode' (scatter log_p_val risk_diff if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') " if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } } if (`rd_pos'==0 | `rd_pos'==.) & (`rd_neg'!=0 & `rd_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val risk_diff if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if `rd_pos'==0 { local segments_counter=`segments_counter'+1 } local segments_counter=`segments_counter'+1 *Build legend text if `legendyn' ==1 & "`legenddef1'"!="" { local legendtext1 = "lab(1 `legenddef1')" } if `legendyn' ==1 & "`legenddef1'"=="" & "`legenddef2'"!="" { local legendtext1 = "lab(1 `legenddef2')" } if `legendyn' ==1 & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef3'"!="" { local legendtext1 = "lab(1 `legenddef3')" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"!="" { local legendtext1 = "lab(1 `legenddef4')" } if "`legend1'"!="" { local legenddef9 = "`legend1'" } if "`legend1'"=="" { local legenddef9 = "Risk in Group 2" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"=="" { local legendtext1 = "lab(1 `legenddef9')" } if `legendyn' ==1 & "`legenddef5'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef5')" } if `legendyn' ==1 & "`legenddef5'"=="" & "`legenddef6'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef6')" } if `legendyn' ==1 & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef7'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef7')" } if `legendyn' ==1 & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef8'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef8')" } if "`legend2'"!="" { local legenddef10 = "`legend2'" } if "`legend2'"=="" { local legenddef10 = "Risk in Group 1" } if `legendyn' ==1 & "`legenddef8'"=="" & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" { local legendtext2 = "lab(1 `legenddef10')" } local legendtext = "order(1 `segments_counter') `legendtext1' `legendtext2'" if `rd_pos'==0 { local legendtext = "order(1) `legendtext1'" } if `rd_neg'==0 { local legendtext = "order(1) `legendtext2'" } if `legendyn' ==0 { local legendtext = "off" } *xlab options: if `min_whole'!=0 & `ticks_xaxis'!=0 & `max_whole'!=0 { local xlab = "xlab(`min_whole'(`ticks_xaxis')`max_whole')" } *Add in graph options: local graphcode "`graphcode' title(`title') subtitle(`subtitle') xtitle(`xaxistitle') ytitle(`yaxistitle') yline( `ynum' , lpattern(`ylinepat') lcolor(`ylinecol') lwidth(`ylinewidth') ) ylab(`min_whole_lp'(`ticks_yaxis')`max_whole_lp' , nogrid) `xlab' graphregion(color(`grphcol')) plotregion(color(`plotcol'))), legend(`legendtext' pos(`legendpos') cols(`legendcol') rows(`legendrow'))" *Run the above to get the scatterplot code noi `graphcode' cap drop if risk_diff == . } } ***********To give risk-difference with Pearson's chi-squared************ if `oddsratio'==0 & `riskratio'==0 { if `pvalue'==1 { gen pvalue_cat=1 if log_p_val_chi<0.5 replace pvalue_cat=0 if log_p_val_chi>=0.5 replace pvalue_cat=3 if log_p_val_chi<0.5 & log_p_val_chi>=0.25 replace pvalue_cat=2 if log_p_val_chi>=0.75 gen group =1 if risk_diff>=0 & pvalue_cat==1 recode group .=2 if risk_diff>=0 & pvalue_cat==0 recode group .=3 if risk_diff>=0 & pvalue_cat==2 recode group .=4 if risk_diff>=0 & pvalue_cat==3 recode group .=5 if risk_diff<0 & pvalue_cat==1 recode group .=6 if risk_diff<0 & pvalue_cat==0 recode group .=7 if risk_diff<0 & pvalue_cat==2 recode group .=8 if risk_diff<0 & pvalue_cat==3 expand 8 replace risk_diff = . if mod(_n,8) > 0 recode group (1=2) (2=3) (3=4) (4=5) (5=6) (6=7) (7=8) (8=1) if mod(_n,8) == 1 recode group (1=3) (2=4) (3=5) (4=6) (5=7) (6=8) (7=1) (8=2) if mod(_n,8) == 2 recode group (1=4) (2=5) (3=6) (4=7) (5=8) (6=1) (7=2) (8=3) if mod(_n,8) == 3 recode group (1=5) (2=6) (3=7) (4=8) (5=1) (6=2) (7=3) (8=4) if mod(_n,8) == 4 recode group (1=6) (2=7) (3=8) (4=1) (5=2) (6=3) (7=4) (8=5) if mod(_n,8) == 5 recode group (1=7) (2=8) (3=1) (4=2) (5=3) (6=4) (7=5) (8=6) if mod(_n,8) == 6 recode group (1=8) (2=1) (3=2) (4=3) (5=4) (6=5) (7=6) (8=7) if mod(_n,8) == 7 *Check that have individuals in each different colour category: *& Costruct graph code only including lines that have the combinations in data set local graphcode "twoway" local segments_counter=0 count if risk_diff>=0 & pvalue_cat==2 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==3 [fw=n_events] , mfcolor(`mfcolor1'%`mfcolsat1') mlcolor(`mlcolor1'%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legend1'"=="" { local legenddef1 = "Risk in Group 1" } else { local legenddef1 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef1 = "`legend1'" } } count if risk_diff>=0 & pvalue_cat==0 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==2 [fw=n_events] , mfcolor(`mfcolor1'*0.75%`mfcolsat1') mlcolor(`mlcolor1'*0.75%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef1'"=="" { local legenddef2 = "Risk in Group 1" } else { local legenddef2 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef2 = "`legend1'" } } count if risk_diff>=0 & pvalue_cat==3 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==4 [fw=n_events] , mfcolor(`mfcolor1'*0.5%`mfcolsat1') mlcolor(`mlcolor1'*0.5%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef2'"=="" { local legenddef3 = "Risk in Group 1" } else { local legenddef3 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef3 = "`legend1'" } } count if risk_diff>=0 & pvalue_cat==1 & risk_diff!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==1 [fw=n_events] , mfcolor(`mfcolor1'*0.25%`mfcolsat1') mlcolor(`mlcolor1'*0.25%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef3'"=="" { local legenddef4 = "Risk in Group 1" } else { local legenddef4 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef4 = "`legend1'" } } count if risk_diff<0 & pvalue_cat==2 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==7 [fw=n_events] , mfcolor(`mfcolor2'%`mfcolsat2') mlcolor(`mlcolor2'%`mlcolsat2') )" if `legendyn' ==1 & "`legend5'"=="" { local legenddef5 = "Risk in Group 2" } else { local legenddef5= "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef5 = "`legend2'" } } count if risk_diff<0 & pvalue_cat==0 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==6 [fw=n_events] , mfcolor(`mfcolor2'*0.75%`mfcolsat2') mlcolor(`mlcolor2'*0.75%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef5'"=="" { local legenddef6 = "Risk in Group 2" } else { local legenddef6 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef6 = "`legend2'" } } count if risk_diff<0 & pvalue_cat==3 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==8 [fw=n_events] , mfcolor(`mfcolor2'*0.5%`mfcolsat2') mlcolor(`mlcolor2'*0.5%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef6'"=="" { local legenddef7 = "Risk in Group 2" } else { local legenddef7 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef7 = "`legend2'" } } count if risk_diff<0 & pvalue_cat==1 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group==5 [fw=n_events] , mfcolor(`mfcolor2'*0.25%`mfcolsat2') mlcolor(`mlcolor2'*0.25%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef7'"=="" { local legenddef8 = "Risk in Group 2" } else { local legenddef8 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef8 = "`legend2'" } } *To account for possibility of 0 events in either RD<0 or RD>=0 count if risk_diff>=0 & risk_diff!=. local rd_pos = r(N) count if risk_diff <0 & risk_diff!=. local rd_neg = r(N) if (`rd_pos'!=0 & `rd_pos'!=.) & (`rd_neg'!=0 & `rd_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') )" if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if (`rd_pos'!=0 & `rd_pos'!=.) & (`rd_neg'==0 | `rd_neg'==.) { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') " if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } } if (`rd_pos'==0 | `rd_pos'==.) & (`rd_neg'!=0 & `rd_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val_chi risk_diff if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if `rd_pos'==0 { local segments_counter=`segments_counter'+1 } local segments_counter=`segments_counter'+1 *building legend text if `legendyn' ==1 & "`legenddef1'"!="" { local legendtext1 = "lab(1 `legenddef1')" } if `legendyn' ==1 & "`legenddef1'"=="" & "`legenddef2'"!="" { local legendtext1 = "lab(1 `legenddef2')" } if `legendyn' ==1 & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef3'"!="" { local legendtext1 = "lab(1 `legenddef3')" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"!="" { local legendtext1 = "lab(1 `legenddef4')" } if "`legend1'"!="" { local legenddef9 = "`legend1'" } if "`legend1'"=="" { local legenddef9 = "Risk in Group 2" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"=="" { local legendtext1 = "lab(1 `legenddef9')" } if `legendyn' ==1 & "`legenddef5'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef5')" } if `legendyn' ==1 & "`legenddef5'"=="" & "`legenddef6'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef6')" } if `legendyn' ==1 & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef7'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef7')" } if `legendyn' ==1 & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef8'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef8')" } if "`legend2'"!="" { local legenddef10 = "`legend2'" } if "`legend2'"=="" { local legenddef10 = "Risk in Group 1" } if `legendyn' ==1 & "`legenddef8'"=="" & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" { local legendtext2 = "lab(1 `legenddef10')" } local legendtext = "order(1 `segments_counter') `legendtext1' `legendtext2'" if `rd_pos'==0 { local legendtext = "order(1) `legendtext1'" } if `rd_neg'==0 { local legendtext = "order(1) `legendtext2'" } if `legendyn' ==0 { local legendtext = "off" } *xlab options: if `min_whole'!=0 & `ticks_xaxis'!=0 & `max_whole'!=0 { local xlab = "xlab(`min_whole'(`ticks_xaxis')`max_whole')" } *Add in graph options: local graphcode "`graphcode' title(`title') subtitle(`subtitle') xtitle(`xaxistitle') ytitle(`yaxistitle') yline( `ynum' , lpattern(`ylinepat') lcolor(`ylinecol') lwidth(`ylinewidth') ) ylab(`min_whole_lp'(`ticks_yaxis')`max_whole_lp' , nogrid) `xlab' graphregion(color(`grphcol')) plotregion(color(`plotcol'))), legend(`legendtext' pos(`legendpos') cols(`legendcol') rows(`legendrow'))" *Run graph code: noi `graphcode' cap drop if risk_diff == . } } ****************************ODDS RATIO**************************** **********To give odds ratio with Fisher's exact p-value********* if `oddsratio'==1 { if `pvalue'==0 { gen pvalue_cat=1 if log_p_val<0.5 replace pvalue_cat=0 if log_p_val>=0.5 replace pvalue_cat=3 if log_p_val<0.5 & log_p_val>=0.25 replace pvalue_cat=2 if log_p_val>=0.75 gen group =1 if log_OR>=0 & pvalue_cat==1 recode group .=2 if log_OR>=0 & pvalue_cat==0 recode group .=3 if log_OR>=0 & pvalue_cat==2 recode group .=4 if log_OR>=0 & pvalue_cat==3 recode group .=5 if log_OR<0 & pvalue_cat==1 recode group .=6 if log_OR<0 & pvalue_cat==0 recode group .=7 if log_OR<0 & pvalue_cat==2 recode group .=8 if log_OR<0 & pvalue_cat==3 expand 8 replace log_OR = . if mod(_n,8) > 0 recode group (1=2) (2=3) (3=4) (4=5) (5=6) (6=7) (7=8) (8=1) if mod(_n,8) == 1 recode group (1=3) (2=4) (3=5) (4=6) (5=7) (6=8) (7=1) (8=2) if mod(_n,8) == 2 recode group (1=4) (2=5) (3=6) (4=7) (5=8) (6=1) (7=2) (8=3) if mod(_n,8) == 3 recode group (1=5) (2=6) (3=7) (4=8) (5=1) (6=2) (7=3) (8=4) if mod(_n,8) == 4 recode group (1=6) (2=7) (3=8) (4=1) (5=2) (6=3) (7=4) (8=5) if mod(_n,8) == 5 recode group (1=7) (2=8) (3=1) (4=2) (5=3) (6=4) (7=5) (8=6) if mod(_n,8) == 6 recode group (1=8) (2=1) (3=2) (4=3) (5=4) (6=5) (7=6) (8=7) if mod(_n,8) == 7 *Check that have individuals in each differnt colour category: *& Costruct graph code only including lines that have the combinations in data set local graphcode "twoway" local segments_counter=0 count if log_OR>=0 & pvalue_cat==2 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==3 [fw=n_events] , mfcolor(`mfcolor1'%`mfcolsat1') mlcolor(`mlcolor1'%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legend1'"=="" { local legenddef1 = "Odds higher in Group 1" } else { local legenddef1 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef1 = "`legend1'" } } count if log_OR>=0 & pvalue_cat==0 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==2 [fw=n_events] , mfcolor(`mfcolor1'*0.75%`mfcolsat1') mlcolor(`mlcolor1'*0.75%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef1'"=="" { local legenddef2 = "Odds higher in Group 1" } else { local legenddef2 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef2 = "`legend1'" } } count if log_OR>=0 & pvalue_cat==3 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==4 [fw=n_events] , mfcolor(`mfcolor1'*0.5%`mfcolsat1') mlcolor(`mlcolor1'*0.5%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef2'"=="" { local legenddef3 = "Odds higher in Group 1" } else { local legenddef3 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef3 = "`legend1'" } } count if log_OR>=0 & pvalue_cat==1 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==1 [fw=n_events] , mfcolor(`mfcolor1'*0.25%`mfcolsat1') mlcolor(`mlcolor1'*0.25%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef3'"=="" { local legenddef4 = "Odds higher in Group 1" } else { local legenddef4 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef4 = "`legend1'" } } count if log_OR<0 & pvalue_cat==2 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==7 [fw=n_events] , mfcolor(`mfcolor2'%`mfcolsat2') mlcolor(`mlcolor2'%`mlcolsat2') )" if `legendyn' ==1 & "`legend5'"=="" { local legenddef5 = "Odds higher in Group 2" } else { local legenddef5= "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef5 = "`legend2'" } } count if log_OR<0 & pvalue_cat==0 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==6 [fw=n_events] , mfcolor(`mfcolor2'*0.75%`mfcolsat2') mlcolor(`mlcolor2'*0.75%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef5'"=="" { local legenddef6 = "Odds higher in Group 2" } else { local legenddef6 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef6 = "`legend2'" } } count if log_OR<0 & pvalue_cat==3 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==8 [fw=n_events] , mfcolor(`mfcolor2'*0.5%`mfcolsat2') mlcolor(`mlcolor2'*0.5%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef6'"=="" { local legenddef7 = "Odds higher in Group 2" } else { local legenddef7 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef7 = "`legend2'" } } count if log_OR<0 & pvalue_cat==1 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_OR if group==5 [fw=n_events] , mfcolor(`mfcolor2'*0.25%`mfcolsat2') mlcolor(`mlcolor2'*0.25%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef7'"=="" { local legenddef8 = "Odds higher in Group 2" } else { local legenddef8 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef8 = "`legend2'" } } *To account for possibility of 0 events in either OR<1 or OR>=1 count if log_OR>=0 & log_OR!=. local or_pos = r(N) count if log_OR <0 & log_OR!=. local or_neg = r(N) if (`or_pos'!=0 & `or_pos'!=.) & (`or_neg'!=0 & `or_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val log_OR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') )" if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } local graphcode "`graphcode' (scatter log_p_val log_OR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if (`or_pos'!=0 & `or_pos'!=.) & (`or_neg'==0 | `or_neg'==.) { local graphcode "`graphcode' (scatter log_p_val log_OR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') " if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } } if (`or_pos'==0 | `or_pos'==.) & (`or_neg'!=0 & `or_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val log_OR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if `or_pos'==0 { local segments_counter=`segments_counter'+1 } local segments_counter=`segments_counter'+1 *Building legend text if `legendyn' ==1 & "`legenddef1'"!="" { local legendtext1 = "lab(1 `legenddef1')" } if `legendyn' ==1 & "`legenddef1'"=="" & "`legenddef2'"!="" { local legendtext1 = "lab(1 `legenddef2')" } if `legendyn' ==1 & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef3'"!="" { local legendtext1 = "lab(1 `legenddef3')" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"!="" { local legendtext1 = "lab(1 `legenddef4')" } if "`legend1'"!="" { local legenddef9 = "`legend1'" } if "`legend1'"=="" { local legenddef9 = "Odds higher in Group 2" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"=="" { local legendtext1 = "lab(1 `legenddef9')" } if `legendyn' ==1 & "`legenddef5'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef5')" } if `legendyn' ==1 & "`legenddef5'"=="" & "`legenddef6'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef6')" } if `legendyn' ==1 & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef7'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef7')" } if `legendyn' ==1 & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef8'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef8')" } if "`legend2'"!="" { local legenddef10 = "`legend2'" } if "`legend2'"=="" { local legenddef10 = "Odds higher in Group 1" } if `legendyn' ==1 & "`legenddef8'"=="" & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" { local legendtext2 = "lab(1 `legenddef10')" } local legendtext = "order(1 `segments_counter') `legendtext1' `legendtext2'" if `or_pos'==0 { local legendtext = "order(1) `legendtext1'" } if `or_neg'==0 { local legendtext = "order(1) `legendtext2'" } if `legendyn' ==0 { local legendtext = "off" } *xlab options: if `min_whole'!=0 & `ticks_xaxis'!=0 & `max_whole'!=0 { local xlab = "xlab(`min_whole'(`ticks_xaxis')`max_whole')" } *Add in graph options: local graphcode "`graphcode' title(`title') subtitle(`subtitle') xtitle(`xaxistitle') ytitle(`yaxistitle') yline( `ynum' , lpattern(`ylinepat') lcolor(`ylinecol') lwidth(`ylinewidth') ) ylab(`min_whole_lp'(`ticks_yaxis')`max_whole_lp' , nogrid) `xlab' graphregion(color(`grphcol')) plotregion(color(`plotcol'))), legend(`legendtext' pos(`legendpos') cols(`legendcol') rows(`legendrow'))" *Run graph code: noi `graphcode' cap drop if log_OR == . } } *Using log odds to make sure x-axis symmetrical if `oddsratio'==1 { if `pvalue'==1 { gen pvalue_cat=1 if log_p_val_chi<0.5 replace pvalue_cat=0 if log_p_val_chi>=0.5 replace pvalue_cat=3 if log_p_val_chi<0.5 & log_p_val_chi>=0.25 replace pvalue_cat=2 if log_p_val_chi>=0.75 gen group =1 if log_OR>=0 & pvalue_cat==1 recode group .=2 if log_OR>=0 & pvalue_cat==0 recode group .=3 if log_OR>=0 & pvalue_cat==2 recode group .=4 if log_OR>=0 & pvalue_cat==3 recode group .=5 if log_OR<0 & pvalue_cat==1 recode group .=6 if log_OR<0 & pvalue_cat==0 recode group .=7 if log_OR<0 & pvalue_cat==2 recode group .=8 if log_OR<0 & pvalue_cat==3 expand 8 replace log_OR = . if mod(_n,8) > 0 recode group (1=2) (2=3) (3=4) (4=5) (5=6) (6=7) (7=8) (8=1) if mod(_n,8) == 1 recode group (1=3) (2=4) (3=5) (4=6) (5=7) (6=8) (7=1) (8=2) if mod(_n,8) == 2 recode group (1=4) (2=5) (3=6) (4=7) (5=8) (6=1) (7=2) (8=3) if mod(_n,8) == 3 recode group (1=5) (2=6) (3=7) (4=8) (5=1) (6=2) (7=3) (8=4) if mod(_n,8) == 4 recode group (1=6) (2=7) (3=8) (4=1) (5=2) (6=3) (7=4) (8=5) if mod(_n,8) == 5 recode group (1=7) (2=8) (3=1) (4=2) (5=3) (6=4) (7=5) (8=6) if mod(_n,8) == 6 recode group (1=8) (2=1) (3=2) (4=3) (5=4) (6=5) (7=6) (8=7) if mod(_n,8) == 7 *Check that have individuals in each differnt colour category: *& Costruct graph code only including lines that have the combinations in data set local graphcode "twoway" local segments_counter=0 count if log_OR>=0 & pvalue_cat==2 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==3 [fw=n_events] , mfcolor(`mfcolor1'%`mfcolsat1') mlcolor(`mlcolor1'%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legend1'"=="" { local legenddef1 = "Odds higher in Group 1" } else { local legenddef1 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef1 = "`legend1'" } } count if log_OR>=0 & pvalue_cat==0 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==2 [fw=n_events] , mfcolor(`mfcolor1'*0.75%`mfcolsat1') mlcolor(`mlcolor1'*0.75%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef1'"=="" { local legenddef2 = "Odds higher in Group 1" } else { local legenddef2 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef2 = "`legend1'" } } count if log_OR>=0 & pvalue_cat==3 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==4 [fw=n_events] , mfcolor(`mfcolor1'*0.5%`mfcolsat1') mlcolor(`mlcolor1'*0.5%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef2'"=="" { local legenddef3 = "Odds higher in Group 1" } else { local legenddef3 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef3 = "`legend1'" } } count if log_OR>=0 & pvalue_cat==1 & log_OR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==1 [fw=n_events] , mfcolor(`mfcolor1'*0.25%`mfcolsat1') mlcolor(`mlcolor1'*0.25%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef3'"=="" { local legenddef4 = "Odds higher in Group 1" } else { local legenddef4 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef4 = "`legend1'" } } count if log_OR<0 & pvalue_cat==2 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==7 [fw=n_events] , mfcolor(`mfcolor2'%`mfcolsat2') mlcolor(`mlcolor2'%`mlcolsat2') )" if `legendyn' ==1 & "`legend5'"=="" { local legenddef5 = "Odds higher in Group 2" } else { local legenddef5= "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef5 = "`legend2'" } } count if log_OR<0 & pvalue_cat==0 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==6 [fw=n_events] , mfcolor(`mfcolor2'*0.75%`mfcolsat2') mlcolor(`mlcolor2'*0.75%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef5'"=="" { local legenddef6 = "Odds higher in Group 2" } else { local legenddef6 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef6 = "`legend2'" } } count if log_OR<0 & pvalue_cat==3 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==8 [fw=n_events] , mfcolor(`mfcolor2'*0.5%`mfcolsat2') mlcolor(`mlcolor2'*0.5%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef6'"=="" { local legenddef7 = "Odds higher in Group 2" } else { local legenddef7 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef7 = "`legend2'" } } count if log_OR<0 & pvalue_cat==1 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group==5 [fw=n_events] , mfcolor(`mfcolor2'*0.25%`mfcolsat2') mlcolor(`mlcolor2'*0.25%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef7'"=="" { local legenddef8 = "Odds higher in Group 2" } else { local legenddef8 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef8 = "`legend2'" } } *To account for possibility of 0 events in either OR<1 or OR>=1 count if log_OR>=0 & log_OR!=. local or_pos = r(N) count if log_OR<0 & log_OR!=. local or_neg = r(N) if (`or_pos'!=0 & `or_pos'!=.) & (`or_neg'!=0 & `or_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') )" if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if (`or_pos'!=0 & `or_pos'!=.) & (`or_neg'==0 | `or_neg'==.) { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') " if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } } if (`or_pos'==0 | `or_pos'==.) & (`or_neg'!=0 & `or_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val_chi log_OR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if `or_pos'==0 { local segments_counter=`segments_counter'+1 } local segments_counter=`segments_counter'+1 *Building legend text if `legendyn' ==1 & "`legenddef1'"!="" { local legendtext1 = "lab(1 `legenddef1')" } if `legendyn' ==1 & "`legenddef1'"=="" & "`legenddef2'"!="" { local legendtext1 = "lab(1 `legenddef2')" } if `legendyn' ==1 & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef3'"!="" { local legendtext1 = "lab(1 `legenddef3')" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"!="" { local legendtext1 = "lab(1 `legenddef4')" } if "`legend1'"!="" { local legenddef9 = "`legend1'" } if "`legend1'"=="" { local legenddef9 = "Odds higher in Group 2" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"=="" { local legendtext1 = "lab(1 `legenddef9')" } if `legendyn' ==1 & "`legenddef5'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef5')" } if `legendyn' ==1 & "`legenddef5'"=="" & "`legenddef6'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef6')" } if `legendyn' ==1 & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef7'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef7')" } if `legendyn' ==1 & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef8'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef8')" } if "`legend2'"!="" { local legenddef10 = "`legend2'" } if "`legend2'"=="" { local legenddef10 = "Odds higher in Group 1" } if `legendyn' ==1 & "`legenddef8'"=="" & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" { local legendtext2 = "lab(1 `legenddef10')" } local legendtext = "order(1 `segments_counter') `legendtext1' `legendtext2'" if `or_pos'==0 { local legendtext = "order(1) `legendtext1'" } if `or_neg'==0 { local legendtext = "order(1) `legendtext2'" } if `legendyn' ==0 { local legendtext = "off" } *xlab options: if `min_whole'!=0 & `ticks_xaxis'!=0 & `max_whole'!=0 { local xlab = "xlab(`min_whole'(`ticks_xaxis')`max_whole')" } *Add in graph options: local graphcode "`graphcode' title(`title') subtitle(`subtitle') xtitle(`xaxistitle') ytitle(`yaxistitle') yline( `ynum' , lpattern(`ylinepat') lcolor(`ylinecol') lwidth(`ylinewidth') ) ylab(`min_whole_lp'(`ticks_yaxis')`max_whole_lp' , nogrid) `xlab' graphregion(color(`grphcol')) plotregion(color(`plotcol'))), legend(`legendtext' pos(`legendpos') cols(`legendcol') rows(`legendrow'))" *Run graph code: noi `graphcode' cap drop if log_OR == . } } ************************RISK RATIO**************************************************** *Using log RR to make sure x-axis symmetrical *To give risk-ratio and Fisher's exact p-value if `riskratio'==1 { if `pvalue'==0 { gen pvalue_cat=1 if log_p_val<0.5 replace pvalue_cat=0 if log_p_val>=0.5 replace pvalue_cat=3 if log_p_val<0.5 & log_p_val>=0.25 replace pvalue_cat=2 if log_p_val>=0.75 gen group =1 if log_RR>=0 & pvalue_cat==1 recode group .=2 if log_RR>=0 & pvalue_cat==0 recode group .=3 if log_RR>=0 & pvalue_cat==2 recode group .=4 if log_RR>=0 & pvalue_cat==3 recode group .=5 if log_RR<0 & pvalue_cat==1 recode group .=6 if log_RR<0 & pvalue_cat==0 recode group .=7 if log_RR<0 & pvalue_cat==2 recode group .=8 if log_RR<0 & pvalue_cat==3 expand 8 replace log_RR = . if mod(_n,8) > 0 recode group (1=2) (2=3) (3=4) (4=5) (5=6) (6=7) (7=8) (8=1) if mod(_n,8) == 1 recode group (1=3) (2=4) (3=5) (4=6) (5=7) (6=8) (7=1) (8=2) if mod(_n,8) == 2 recode group (1=4) (2=5) (3=6) (4=7) (5=8) (6=1) (7=2) (8=3) if mod(_n,8) == 3 recode group (1=5) (2=6) (3=7) (4=8) (5=1) (6=2) (7=3) (8=4) if mod(_n,8) == 4 recode group (1=6) (2=7) (3=8) (4=1) (5=2) (6=3) (7=4) (8=5) if mod(_n,8) == 5 recode group (1=7) (2=8) (3=1) (4=2) (5=3) (6=4) (7=5) (8=6) if mod(_n,8) == 6 recode group (1=8) (2=1) (3=2) (4=3) (5=4) (6=5) (7=6) (8=7) if mod(_n,8) == 7 *Check that have individuals in each differnt colour category: *& Costruct graph code only including lines that have the combinations in data set local graphcode "twoway" local segments_counter=0 count if log_RR>=0 & pvalue_cat==2 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==3 [fw=n_events] , mfcolor(`mfcolor1'%`mfcolsat1') mlcolor(`mlcolor1'%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legend1'"=="" { local legenddef1 = "Risk in Group 1" } else { local legenddef1 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef1 = "`legend1'" } } count if log_RR>=0 & pvalue_cat==0 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==2 [fw=n_events] , mfcolor(`mfcolor1'*0.75%`mfcolsat1') mlcolor(`mlcolor1'*0.75%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef1'"=="" { local legenddef2 = "Risk in Group 1" } else { local legenddef2 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef2 = "`legend1'" } } count if log_RR>=0 & pvalue_cat==3 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==4 [fw=n_events] , mfcolor(`mfcolor1'*0.5%`mfcolsat1') mlcolor(`mlcolor1'*0.5%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef2'"=="" { local legenddef3 = "Risk in Group 1" } else { local legenddef3 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef3 = "`legend1'" } } count if log_RR>=0 & pvalue_cat==1 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==1 [fw=n_events] , mfcolor(`mfcolor1'*0.25%`mfcolsat1') mlcolor(`mlcolor1'*0.25%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef3'"=="" { local legenddef4 = "Risk in Group 1" } else { local legenddef4 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef4 = "`legend1'" } } count if log_RR<0 & pvalue_cat==2 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==7 [fw=n_events] , mfcolor(`mfcolor2'%`mfcolsat2') mlcolor(`mlcolor2'%`mlcolsat2') )" if `legendyn' ==1 & "`legend5'"=="" { local legenddef5 = "Risk in Group 2" } else { local legenddef5= "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef5 = "`legend2'" } } count if log_RR<0 & pvalue_cat==0 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==6 [fw=n_events] , mfcolor(`mfcolor2'*0.75%`mfcolsat2') mlcolor(`mlcolor2'*0.75%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef5'"=="" { local legenddef6 = "Risk in Group 2" } else { local legenddef6 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef6 = "`legend2'" } } count if log_RR<0 & pvalue_cat==3 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==8 [fw=n_events] , mfcolor(`mfcolor2'*0.5%`mfcolsat2') mlcolor(`mlcolor2'*0.5%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef6'"=="" { local legenddef7 = "Risk in Group 2" } else { local legenddef7 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef7 = "`legend2'" } } count if log_RR<0 & pvalue_cat==1 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val log_RR if group==5 [fw=n_events] , mfcolor(`mfcolor2'*0.25%`mfcolsat2') mlcolor(`mlcolor2'*0.25%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef7'"=="" { local legenddef8 = "Risk in Group 2" } else { local legenddef8 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef8 = "`legend2'" } } *To account for possibility of 0 events in either RR<1 or RR>=1 count if log_RR>=0 & log_RR!=. local rr_pos = r(N) count if log_RR <0 & log_RR!=. local rr_neg = r(N) if (`rr_pos'!=0 & `rr_pos'!=.) & (`rr_neg'!=0 & `rr_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val log_RR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') )" if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } local graphcode "`graphcode' (scatter log_p_val log_RR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if (`rr_pos'!=0 & `rr_pos'!=.) & (`rr_neg'==0 | `rr_neg'==.) { local graphcode "`graphcode' (scatter log_p_val log_RR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') " if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } } if (`rr_pos'==0 | `rr_pos'==.) & (`rr_neg'!=0 & `rr_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val log_RR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if `rr_pos'==0 { local segments_counter=`segments_counter'+1 } local segments_counter=`segments_counter'+1 *Building legend text if `legendyn' ==1 & "`legenddef1'"!="" { local legendtext1 = "lab(1 `legenddef1')" } if `legendyn' ==1 & "`legenddef1'"=="" & "`legenddef2'"!="" { local legendtext1 = "lab(1 `legenddef2')" } if `legendyn' ==1 & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef3'"!="" { local legendtext1 = "lab(1 `legenddef3')" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"!="" { local legendtext1 = "lab(1 `legenddef4')" } if "`legend1'"!="" { local legenddef9 = "`legend1'" } if "`legend1'"=="" { local legenddef9 = "Risk in Group 2" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"=="" { local legendtext1 = "lab(1 `legenddef9')" } if `legendyn' ==1 & "`legenddef5'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef5')" } if `legendyn' ==1 & "`legenddef5'"=="" & "`legenddef6'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef6')" } if `legendyn' ==1 & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef7'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef7')" } if `legendyn' ==1 & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef8'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef8')" } if "`legend2'"!="" { local legenddef10 = "`legend2'" } if "`legend2'"=="" { local legenddef10 = "Risk in Group 1" } if `legendyn' ==1 & "`legenddef8'"=="" & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" { local legendtext2 = "lab(1 `legenddef10')" } local legendtext = "order(1 `segments_counter') `legendtext1' `legendtext2'" if `rr_pos'==0 { local legendtext = "order(1) `legendtext1'" } if `rr_neg'==0 { local legendtext = "order(1) `legendtext2'" } if `legendyn' ==0 { local legendtext = "off" } *xlab options: if `min_whole'!=0 & `ticks_xaxis'!=0 & `max_whole'!=0 { local xlab = "xlab(`min_whole'(`ticks_xaxis')`max_whole')" } *Add in graph options: local graphcode "`graphcode' title(`title') subtitle(`subtitle') xtitle(`xaxistitle') ytitle(`yaxistitle') yline( `ynum' , lpattern(`ylinepat') lcolor(`ylinecol') lwidth(`ylinewidth') ) ylab(`min_whole_lp'(`ticks_yaxis')`max_whole_lp' , nogrid) `xlab' graphregion(color(`grphcol')) plotregion(color(`plotcol'))), legend(`legendtext' pos(`legendpos') cols(`legendcol') rows(`legendrow'))" *Run graph code: noi `graphcode' cap drop if log_RR == . } } *************To give risk-ratio and Pearson's chi-squared************ *using log RR to make sure x axis symmetrical if `riskratio'==1 { if `pvalue'==1 { gen pvalue_cat=1 if log_p_val_chi<0.5 replace pvalue_cat=0 if log_p_val_chi>=0.5 replace pvalue_cat=3 if log_p_val_chi<0.5 & log_p_val_chi>=0.25 replace pvalue_cat=2 if log_p_val_chi>=0.75 gen group =1 if log_RR>=0 & pvalue_cat==1 recode group .=2 if log_RR>=0 & pvalue_cat==0 recode group .=3 if log_RR>=0 & pvalue_cat==2 recode group .=4 if log_RR>=0 & pvalue_cat==3 recode group .=5 if log_RR<0 & pvalue_cat==1 recode group .=6 if log_RR<0 & pvalue_cat==0 recode group .=7 if log_RR<0 & pvalue_cat==2 recode group .=8 if log_RR<0 & pvalue_cat==3 expand 8 replace log_RR = . if mod(_n,8) > 0 recode group (1=2) (2=3) (3=4) (4=5) (5=6) (6=7) (7=8) (8=1) if mod(_n,8) == 1 recode group (1=3) (2=4) (3=5) (4=6) (5=7) (6=8) (7=1) (8=2) if mod(_n,8) == 2 recode group (1=4) (2=5) (3=6) (4=7) (5=8) (6=1) (7=2) (8=3) if mod(_n,8) == 3 recode group (1=5) (2=6) (3=7) (4=8) (5=1) (6=2) (7=3) (8=4) if mod(_n,8) == 4 recode group (1=6) (2=7) (3=8) (4=1) (5=2) (6=3) (7=4) (8=5) if mod(_n,8) == 5 recode group (1=7) (2=8) (3=1) (4=2) (5=3) (6=4) (7=5) (8=6) if mod(_n,8) == 6 recode group (1=8) (2=1) (3=2) (4=3) (5=4) (6=5) (7=6) (8=7) if mod(_n,8) == 7 *Check that have individuals in each differnt colour category: *& Costruct graph code only including lines that have the combinations in data set local graphcode "twoway" local segments_counter=0 count if log_RR>=0 & pvalue_cat==2 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==3 [fw=n_events] , mfcolor(`mfcolor1'%`mfcolsat1') mlcolor(`mlcolor1'%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legend1'"=="" { local legenddef1 = "Risk in Group 1" } else { local legenddef1 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef1 = "`legend1'" } } count if log_RR>=0 & pvalue_cat==0 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==2 [fw=n_events] , mfcolor(`mfcolor1'*0.75%`mfcolsat1') mlcolor(`mlcolor1'*0.75%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef1'"=="" { local legenddef2 = "Risk in Group 1" } else { local legenddef2 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef2 = "`legend1'" } } count if log_RR>=0 & pvalue_cat==3 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==4 [fw=n_events] , mfcolor(`mfcolor1'*0.5%`mfcolsat1') mlcolor(`mlcolor1'*0.5%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef2'"=="" { local legenddef3 = "Risk in Group 1" } else { local legenddef3 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef3 = "`legend1'" } } count if log_RR>=0 & pvalue_cat==1 & log_RR!=. if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==1 [fw=n_events] , mfcolor(`mfcolor1'*0.25%`mfcolsat1') mlcolor(`mlcolor1'*0.25%`mlcolsat1') )" local segments_counter=`segments_counter'+1 if `legendyn' ==1 & "`legenddef3'"=="" { local legenddef4 = "Risk in Group 1" } else { local legenddef4 = "" } if `legendyn' ==1 & "`legend1'"!="" { local legenddef4 = "`legend1'" } } count if log_RR<0 & pvalue_cat==2 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==7 [fw=n_events] , mfcolor(`mfcolor2'%`mfcolsat2') mlcolor(`mlcolor2'%`mlcolsat2') )" if `legendyn' ==1 & "`legend5'"=="" { local legenddef5 = "Risk in Group 2" } else { local legenddef5= "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef5 = "`legend2'" } } count if log_RR<0 & pvalue_cat==0 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==6 [fw=n_events] , mfcolor(`mfcolor2'*0.75%`mfcolsat2') mlcolor(`mlcolor2'*0.75%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef5'"=="" { local legenddef6 = "Risk in Group 2" } else { local legenddef6 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef6 = "`legend2'" } } count if log_RR<0 & pvalue_cat==3 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==8 [fw=n_events] , mfcolor(`mfcolor2'*0.5%`mfcolsat2') mlcolor(`mlcolor2'*0.5%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef6'"=="" { local legenddef7 = "Risk in Group 2" } else { local legenddef7 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef7 = "`legend2'" } } count if log_RR<0 & pvalue_cat==1 if r(N)>0 & r(N)!=. { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group==5 [fw=n_events] , mfcolor(`mfcolor2'*0.25%`mfcolsat2') mlcolor(`mlcolor2'*0.25%`mlcolsat2') )" if `legendyn' ==1 & "`legenddef7'"=="" { local legenddef8 = "Risk in Group 2" } else { local legenddef8 = "" } if `legendyn' ==1 & "`legend2'"!="" { local legenddef8 = "`legend2'" } } *To account for possibility of 0 events in either RR<1 or RR>=1 count if log_RR>=0 & log_RR!=. local rr_pos = r(N) count if log_RR <0 & log_RR!=. local rr_neg = r(N) if (`rr_pos'!=0 & `rr_pos'!=.) & (`rr_neg'!=0 & `rr_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') )" if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if (`rr_pos'!=0 & `rr_pos'!=.) & (`rr_neg'==0 | `rr_neg'==.) { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group>=1 & group<=4 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol1') mlabangle(`labang1') mlabposition(`labpos1') mlabgap(`labgap1') " if `legendyn' ==1 & "`legend9'"=="" { local legenddef9 = "" } } if (`rr_pos'==0 | `rr_pos'==.) & (`rr_neg'!=0 & `rr_neg'!=.) { local graphcode "`graphcode' (scatter log_p_val_chi log_RR if group>=5 & group<=8 , msymbol(i) mlabel(mylabel) mlabcolor(`labcol2') mlabangle(`labang2') mlabposition(`labpos2') mlabgap(`labgap2') " if `legendyn' ==1 & "`legend10'"=="" { local legenddef10 = "" } } if `rr_pos'==0 { local segments_counter=`segments_counter'+1 } local segments_counter=`segments_counter'+1 *Building legend text if `legendyn' ==1 & "`legenddef1'"!="" { local legendtext1 = "lab(1 `legenddef1')" } if `legendyn' ==1 & "`legenddef1'"=="" & "`legenddef2'"!="" { local legendtext1 = "lab(1 `legenddef2')" } if `legendyn' ==1 & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef3'"!="" { local legendtext1 = "lab(1 `legenddef3')" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"!="" { local legendtext1 = "lab(1 `legenddef4')" } if "`legend1'"!="" { local legenddef9 = "`legend1'" } if "`legend1'"=="" { local legenddef9 = "Risk in Group 2" } if `legendyn' ==1 & "`legenddef3'"=="" & "`legenddef2'"=="" & "`legenddef1'"=="" & "`legenddef4'"=="" { local legendtext1 = "lab(1 `legenddef9')" } if `legendyn' ==1 & "`legenddef5'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef5')" } if `legendyn' ==1 & "`legenddef5'"=="" & "`legenddef6'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef6')" } if `legendyn' ==1 & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef7'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef7')" } if `legendyn' ==1 & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" & "`legenddef8'"!="" { local legendtext2 = "lab(`segments_counter' `legenddef8')" } if "`legend2'"!="" { local legenddef10 = "`legend2'" } if "`legend2'"=="" { local legenddef10 = "Risk in Group 1" } if `legendyn' ==1 & "`legenddef8'"=="" & "`legenddef7'"=="" & "`legenddef6'"=="" & "`legenddef5'"=="" { local legendtext2 = "lab(1 `legenddef10')" } local legendtext = "order(1 `segments_counter') `legendtext1' `legendtext2'" if `rr_pos'==0 { local legendtext = "order(1) `legendtext1'" } if `rr_neg'==0 { local legendtext = "order(1) `legendtext2'" } if `legendyn' ==0 { local legendtext = "off" } *xlab options: if `min_whole'!=0 & `ticks_xaxis'!=0 & `max_whole'!=0 { local xlab = "xlab(`min_whole'(`ticks_xaxis')`max_whole')" } *Add in graph options: local graphcode "`graphcode' title(`title') subtitle(`subtitle') xtitle(`xaxistitle') ytitle(`yaxistitle') yline( `ynum' , lpattern(`ylinepat') lcolor(`ylinecol') lwidth(`ylinewidth') ) ylab(`min_whole_lp'(`ticks_yaxis')`max_whole_lp' , nogrid) `xlab' graphregion(color(`grphcol')) plotregion(color(`plotcol'))), legend(`legendtext' pos(`legendpos') cols(`legendcol') rows(`legendrow'))" *Run graph code: noi `graphcode' cap drop if log_RR == . } } ************************ if "`saving'"!="" { noi save `filename', `replace' } if "`graphsave'"!="" { noi graph save `graphname', `graphreplace' } if "`clear'" == "" { use `original'.dta , clear } else { restore , not use `ae_volcano_1'.dta , clear } } /*close the big quietly loop around aevolcano*/ end ***************************************************************** /*FDR adjustment as per Mehrotra and Adewale V1.0 10/02/2020 */ cap prog drop aefdr program define aefdr , rclass version 15.0 /*Description: Adjusting p-values according to work of Mehrotra and Adewale Start with a row per event - require variable for bodysystem ID, AE ID and unadjsuted p-value v0.1: original */ *Syntax syntax, FDRHIGHER(varname) FDRLOWER(varname) PVALUEADJ(varname) [FDRval(real 0.1)] /* Syntax explanation fdrhigher - can contain numeric or string. indicates the variable that contains the higher level/bodysystem AE name/identifier fdrlower - can contain numeric or string. indicates the variable that contains the lower level AE name/identifier pvalueadj - contains numeric variable containing unadjusted p-values fdrval - optional command that indicates the alpha value to flag events at. Default is 0.1 */ qui{ /* open the big quietly loop for aefdr*/ ****Error checking********* *Confirm pvalue numeric cap confirm numeric variable `pvalueadj' local pval_num = _rc if `pval_num' !=0 { display as error "pvalue variable not numeric" exit 7 } /*closes if pval_num loop*/ ***************************************************************************** tokenize `fdrhigher' local by_bs "`1'" tokenize `fdrlower' local by_ae "`1'" if substr("`:type `by_bs''" ,1,3) == "str" & substr("`:type `by_ae''" ,1,3) == "str" { /*STRING OPTION FOR BODYSYSTEM AND EVENT */ egen bs_id = group(`by_bs') egen ae_id = group(`by_ae') sort bs_id `pvalueadj' ae_id *Ranks events within bodysystems bysort bs_id : gen rank = [_n] *Generates the max rank in each bodysytem to indicate total number of events within each bysort bs_id : egen max =max(rank) *Generate the maximum p-value for each bodysystem gen p1_max = `pvalueadj' if rank==max *Generate an inflated p-value for each event gen p1 = (max/rank)*`pvalueadj' *Create a local macro that indicates total number of bodysystems summ bs_id return list local max = r(max) disp `max' *Generating variable for body-system p-value gen bs_p = . *Generating variable for event p-value gen p2 =. *Looping through each bodysystem in turn foreach num of numlist 1(1)`max' { disp "fdrhigher" `num' *Generating local macro with max number of events in each bodysystem cap summ rank if bs_id==`num' return list local maxevents`num' = r(max) disp "Number of events in higher term" `num' ":" `maxevents`num'' disp `maxevents`num'' local maxevents = `maxevents`num'' *Numbers do not have to be consecutive so if a bodysystem number is not *used then this will allow the code to keep running if `maxevents' == . { gen error`num' = _rc } /*closing if loop*/ else { *Looping through each event in a bodysystem/higher term (from largerst to smallest) foreach num1 of numlist `maxevents'(-1)1 { disp `maxevents' *Bounding adjusted p-values by the maximum unadjusted value in that bodysystem replace p2 = p1 if rank==max & bs_id==`num' *Establishing minimum p-value for each of the N-1 events replace p2 = p1[_n] if p2 ==. & rank==`num1' & p1[_n]< p2[_n+1] & bs_id==`num' replace p2 = p2[_n+1] if p2 ==. & rank==`num1' & p2[_n+1]<= p1[_n] & bs_id==`num' } /*closes foreach num1 loop*/ } /*closes else loop*/ *Creating a bodysystem p-value equal to the minimum adjusted event p-value cap summ p2 if bs_id==`num' replace bs_p = r(min) if bs_id==`num' sort bs_id rank } /*closes foreach num loop */ } /*closes the big if substring loop*/ if substr("`:type `by_bs''" ,1,3) != "str" & substr("`:type `by_ae''" ,1,3) == "str" { /*NUMERIC OPTION FOR BODYSYSTEM AND STRING EVENT*/ cap encode `by_ae', gen(aefdr_int_1) if _rc!=0 { gen aefdr_int_1=real(`by_ae') } sort `fdrhigher' `pvalueadj' `fdrlower' gen bs_id = `fdrhigher' gen ae_id = aefdr_int_1 *Ranks events within bodysystems bysort `fdrhigher' : gen rank = [_n] *Generates the max rank in each bodysytem to indicate total number of events within each bysort `fdrhigher' : egen max =max(rank) *Generate the maximum p-value for each bodysystem/higher term gen p1_max = `pvalueadj' if rank==max *Generate an inflated p-value gen p1 = (max/rank)*`pvalueadj' *Create a local macro that indicates total number of bodysystems summ `fdrhigher' return list local max = r(max) disp `max' *Generating variable for body-system p-value gen bs_p = . *Generating variable for event p-value gen p2 =. *Looping through each bodysystem in turn foreach num of numlist 1(1)`max' { disp "fdrhigher" `num' *Generating local macro with max number of events in each bodysystem cap summ rank if `fdrhigher'==`num' return list local maxevents`num' = r(max) disp "Number of events in higher term" `num' ":" `maxevents`num'' disp `maxevents`num'' local maxevents = `maxevents`num'' *Numbers do not have to be consecutive so if a bodysystem number is not *used then this will allow the code to keep running if `maxevents' == . { gen error`num' = _rc } /* closes the if maxevents loop*/ else { *Looping through each event in a bodysystem (from largerst to smallest) foreach num1 of numlist `maxevents'(-1)1 { disp `maxevents' *Bounding adjusted p-values by the maximum unadjusted value in that higherterm/bodysystem replace p2 = p1 if rank==max & `fdrhigher'==`num' *Establishing minimum p-value for each of the N-1 events replace p2 = p1[_n] if p2 ==. & rank==`num1' & p1[_n]< p2[_n+1] & `fdrhigher'==`num' replace p2 = p2[_n+1] if p2 ==. & rank==`num1' & p2[_n+1]<= p1[_n] & `fdrhigher'==`num' } /*closes the else loop*/ } /*closes the foreach num loop*/ *Creating a bodysystem p-value equal to the minimum adjusted event p-value cap summ p2 if `fdrhigher'==`num' replace bs_p = r(min) if `fdrhigher'==`num' sort `fdrhigher' rank } /*close the else loop*/ } /*close the big else loop*/ if substr("`:type `by_bs''" ,1,3) == "str" & substr("`:type `by_ae''" ,1,3) != "str" { /*STRING OPTION FOR BODYSYSTEM AND NUMERIC EVENT*/ cap encode `by_bs', gen(aefdr_int_2) if _rc!=0 { gen aefdr_int_2=real(`by_bs') } sort `fdrhigher' `pvalueadj' `fdrlower' gen bs_id = aefdr_int_2 gen ae_id = `fdrlower' *Ranks events within bodysystems bysort `fdrhigher' : gen rank = [_n] *Generates the max rank in each bodysytem to indicate total number of events within each bysort `fdrhigher' : egen max =max(rank) *Generate the maximum p-value for each bodysystem gen p1_max = `pvalueadj' if rank==max *Generate an inflated p-value gen p1 = (max/rank)*`pvalueadj' *Create a local macro that indicates total number of bodysystems *summ `fdrhigher' summ bs_id return list local max = r(max) disp `max' *Generating variable for body-system p-value gen bs_p = . *Generating variable for event p-value gen p2 =. *Looping through each bodysystem in turn foreach num of numlist 1(1)`max' { disp "fdrhigher" `num' *Generating local macro with max number of events in each bodysystem *cap summ rank if `fdrhigher'==`num' cap summ rank if bs_id==`num' return list local maxevents`num' = r(max) disp "Number of events in higher term" `num' ":" `maxevents`num'' disp `maxevents`num'' local maxevents = `maxevents`num'' *Numbers do not have to be consecutive so if a bodysystem number is not *used then this will allow the code to keep running if `maxevents' == . { gen error`num' = _rc } /* closes the if maxevents loop*/ else { *Looping through each event in a bodysystem/higher term (from largerst to smallest) foreach num1 of numlist `maxevents'(-1)1 { disp `maxevents' *Bounding adjusted p-values by the maximum unadjusted value in that bodysystem *replace p2 = p1 if rank==max & `fdrhigher'==`num' replace p2 = p1 if rank==max & bs_id==`num' *Establishing minimum p-value for each of the N-1 events replace p2 = p1[_n] if p2 ==. & rank==`num1' & p1[_n]< p2[_n+1] & bs_id==`num' replace p2 = p2[_n+1] if p2 ==. & rank==`num1' & p2[_n+1]<= p1[_n] & bs_id==`num' } /*closes the else loop*/ } /*closes the foreach num loop*/ *Creating a bodysystem p-value equal to the minimum adjusted event p-value cap summ p2 if bs_id==`num' replace bs_p = r(min) if bs_id==`num' sort bs_id rank } /*close the else loop*/ } /*close the big else loop*/ else if substr("`:type `by_bs''" ,1,3) != "str" & substr("`:type `by_ae''" ,1,3) != "str" { /*NUMERIC OPTION FOR BODYSYSTEM AND EVENT*/ sort `fdrhigher' `pvalueadj' `fdrlower' gen bs_id = `fdrhigher' gen ae_id = `fdrlower' *Ranks events within bodysystems bysort `fdrhigher' : gen rank = [_n] *Generates the max rank in each bodysytem to indicate total number of events within each bysort `fdrhigher' : egen max =max(rank) *Generate the maximum p-value for each bodysystem gen p1_max = `pvalueadj' if rank==max *Generate an inflated p-value gen p1 = (max/rank)*`pvalueadj' *Create a local macro that indicates total number of bodysystems summ `fdrhigher' return list local max = r(max) disp `max' *Generating variable for body-system p-value gen bs_p = . *Generating variable for event p-value gen p2 =. *Looping through each bodysystem in turn foreach num of numlist 1(1)`max' { disp "fdrhigher" `num' *Generating local macro with max number of events in each bodysystem cap summ rank if `fdrhigher'==`num' return list local maxevents`num' = r(max) disp "Number of events in bodsystem" `num' ":" `maxevents`num'' disp `maxevents`num'' local maxevents = `maxevents`num'' *Numbers do not have to be consecutive so if a bodysystem/higher term number is not *used then this will allow the code to keep running if `maxevents' == . { gen error`num' = _rc } /* closes the if maxevents loop*/ else { *Looping through each event in a bodysystem/higherterm (from largerst to smallest) foreach num1 of numlist `maxevents'(-1)1 { disp `maxevents' *Bounding adjusted p-values by the maximum unadjusted value in that higherterm replace p2 = p1 if rank==max & `fdrhigher'==`num' *Establishing minimum p-value for each of the N-1 events replace p2 = p1[_n] if p2 ==. & rank==`num1' & p1[_n]< p2[_n+1] & `fdrhigher'==`num' replace p2 = p2[_n+1] if p2 ==. & rank==`num1' & p2[_n+1]<= p1[_n] & `fdrhigher'==`num' } /*closes the else loop*/ } /*closes the foreach num loop*/ *Creating a bodysystem p-value equal to the minimum adjusted event p-value cap summ p2 if `fdrhigher'==`num' replace bs_p = r(min) if `fdrhigher'==`num' sort `fdrhigher' rank } /*close the else loop*/ } /*close the big else loop*/ cap drop error* *Rank bodysystem p-values egen rank_bs = rank(bs_p) if rank==1 , unique // assign unique ties, arbitrary assigning different values for tied ranks **Create a variable to indicate bodysystem rank on each row bysort bs_id : egen rank_bs_grp = max(rank_bs) *Generate the max number of bodysystems egen max_bs_rank =max(rank_bs) gen max_bs_p = bs_p if rank_bs==max_bs_rank *Inflating the body system p-values gen p1_bs = (max_bs_rank/rank_bs)*bs_p sort rank_bs *Bounding maximum adusted bodysystem p-value gen p2_bs = p1_bs if rank_bs==max_bs_rank *Looping through each bodysystem to calculate adjusted p-value foreach num of numlist `max'(1)1 { replace p2_bs = p1_bs[_n] if p2_bs ==. & rank_bs==`num' & p1_bs[_n]< p2_bs[_n+1] replace p2_bs = p2_bs[_n+1] if p2_bs ==. & rank_bs==`num' & p2_bs[_n+1]<= p1_bs[_n] summ p2_bs if rank_bs == `num' replace p2_bs = r(min) if p2_bs==. & rank_bs_grp == `num' } /*close foreach num loop*/ sort bs_id ae_id *Flagging the events that satisfy max threshold p-value to indicate a signal gen flag = 1 if p2<`fdrval' & p2_bs<`fdrval' keep `fdrhigher' `fdrlower' `pvalueadj' p2 p2_bs flag cap lab var p2 "FDR adjusted p-value for AE (lower level)" cap lab var p2_bs "FDR adjusted p-value for bodysystem (higher level)" cap lab var flag "Flag for events that satisfy p-value threshold in fdrval" noi display as text "Dataset with adjusted p-values now saved in working directory" noi save adjusted_pvalues.dta , replace } /*closes the big quietly loop for aefdr*/ end exit