program diff_plot

	version 11.2


syntax varlist(max=1 numeric)    	///
       [if]                      	///
	   [in],                    	///
	   Time(varname)				///
	   Group(varname)				///
	   [DRop_trend]					///
	   [TItle(string)]       		///
	   [DEcimals(integer 2)] 		///
	   [SCale] 						///
	   [GRaphopts(string)]			///
	   [L1_opts(string)]			///
	   [L2_opts(string)]			///
	   [L3_opts(string)]			///
	   [M1_opts(string)]			///
	   [M2_opts(string)]			///
	   [M3_opts(string)]

********************************************************************************

* Basic checks prior to running the program

********************************************************************************

	* Check if elabel is installed

	cap which elabel
	if _rc == 111{

	display as err "	This module requires the 'elabel' package to search through labels of the time and treatment variables."
	display as err "	You need to run:"
	display as err "	ssc install elabel, replace"
	exit 198
}

qui {

********************************************************************************

* Setup

********************************************************************************

	* Use preserve rather than temp files (as recommended by Kit Baum)

	preserve

	* Sample indicator for mapping the [IF] condition

	marksample touse

	* Keep if X == x

	qui keep if `touse' == 1

	* Check if time and group variables take only two unique values

	levelsof `time', local(time_levels)
	local num_time_levels: word count `time_levels'

	if `num_time_levels' != 2 {
		display as err "	The time variable must contain only two unique values."
		exit 198
	}

	levelsof `group', local(group_levels)
	local num_group_levels: word count `group_levels'

	if `num_group_levels' != 2 {
		display as err "	The group variable must contain only two unique values."
		exit 198
	}

********************************************************************************

* Save locals for later use

********************************************************************************

	local varlabel : variable label `varlist'

	* If missing, assign actual values as value labels to time and group variables

	local val_lab: value label `time'

	if "`val_lab'" == "" {

	levelsof `time', local(time_levels)

	foreach val of local time_levels {
	label define time_lbl `val' "`val'", add
	}

	label values `time' time_lbl
	}


	local val_lab: value label `group'

	if "`val_lab'" == "" {

	levelsof `group', local(group_levels)

	foreach val of local group_levels {
	label define group_lbl `val' "`val'", add
	}

	label values `group' group_lbl
	}


* Save data points to add to graphs

	levelsof `time', local(time_levels)
	local time1: word 1 of `time_levels'
	local time2: word 2 of `time_levels'

	elabel list (`time') iff (# == `time1')
	local time_lab1 = `r(labels)'

	elabel list (`time') iff (# == `time2')
	local time_lab2 = `r(labels)'

	levelsof `group', local(group_levels)
	local group1: word 1 of `group_levels'
	local group2: word 2 of `group_levels'

	elabel list (`group') iff (# == `group1')
	local group_lab1 = `r(labels)'

	elabel list (`group') iff (# == `group2')
	local group_lab2 = `r(labels)'

	if "`title'" != "" {
	local graph_title "`title'"
}

	if "`title'" == "" {
	local graph_title "Change from `time_lab1' to `time_lab2' for `varlabel'"
}

	local ylab

	if "`scale'" !="" {
	local ylab ylabel(0(20)100)
}

	* Store locals for control group

	summarize `varlist' if `time' == `time1' & `group' == `group1'
	local control_p1 = r(mean)

	summarize `varlist' if `time' == `time2' & `group' == `group1'
	local control_p2 = r(mean)

	* Store locals for treatment group

	summarize `varlist' if `time' == `time1' & `group' == `group2'
	local treatment_p1 = r(mean)

	summarize `varlist' if `time' == `time2' & `group' == `group2'
	local treatment_p2 = r(mean)

	* Calculate the difference between the baseline values

	local baseline_diff = `treatment_p1' - `control_p1'

	* Calculate the endline value for the parallel trend line

	local parallel_trend_p2 = `control_p2' + `baseline_diff'

	* Calculate the intervention effect

	local int_eff 		= (`treatment_p2' - `treatment_p1') - (`control_p2' - `control_p1')
	local int_eff_fmt 	= strltrim("`: display %9.`decimals'f `int_eff''")

********************************************************************************

* Create a new dataset

********************************************************************************

	clear
	set obs 6
	gen str30 group = ""
	gen str10 time = ""
	gen float value = .

	replace group = "Control" in 1
	replace time = "Period 1" in 1
	replace value = `control_p1' in 1

	replace group = "Control" in 2
	replace time = "Period 2" in 2
	replace value = `control_p2' in 2

	replace group = "Treatment" in 3
	replace time = "Period 1" in 3
	replace value = `treatment_p1' in 3

	replace group = "Treatment" in 4
	replace time = "Period 2" in 4
	replace value = `treatment_p2' in 4

	replace group = "Parallel Trend" in 5
	replace time = "Period 1" in 5
	replace value = `treatment_p1' in 5

	replace group = "Parallel Trend" in 6
	replace time = "Period 2" in 6
	replace value = `parallel_trend_p2' in 6

	* Encode the time variable

	encode time, gen(time_num)

	* Format labels for the scatter plot values

	gen lab_val = string(value, "%8.`decimals'f")

	* Dynamically pad the y-axis (by 5%)

	sum value
	local min_value = `r(min)'
	local max_value = `r(max)'
	local range = abs(`max_value' - `min_value')

	local y1 = `min_value' - 0.05*`range'
	local y2 = `max_value' + 0.05*`range'

********************************************************************************

* Make the graph

********************************************************************************

	if "`drop_trend'" == "" {

	twoway ///
	(line 		value time_num 	if group == "Control", 			lcolor(blue) 	lpattern(solid) lwidth(medium) 					 `l1_opts') ///
	(scatter 	value time_num 	if group == "Control", 			mcolor(blue) 	mlabel(lab_val) mlabposition(12) mlabcolor(blue)	`m1_opts') ///
	(line 		value time_num 	if group == "Treatment", 		lcolor(green) 	lpattern(solid) lwidth(medium) 					 `l2_opts') ///
	(scatter 	value time_num 	if group == "Treatment", 		mcolor(green) 	mlabel(lab_val) mlabposition(12) mlabcolor(green) `m2_opts') ///
	(line 		value time_num 	if group == "Parallel Trend",	lcolor(green) 	lpattern(dash) lwidth(medium) 					 `l3_opts') ///
	(scatter 	value time_num 	if group == "Parallel Trend",	mcolor(green) 	mlabel(lab_val) mlabposition(12) mlabcolor(green) `m3_opts'), ///
	legend(order(1 "`group_lab1'" 3 "`group_lab2'" 5 "Parallel Trend")) legend(pos(6) row(1)) ///
	title("`graph_title'", size(small) span) subtitle("Intervention Effect: `int_eff_fmt'", size(vsmall) span) xtitle("Time") ytitle("") ///
	xlabel(1 "`time_lab1'" 2 "`time_lab2'") xscale(range(0.95 2.05)) yscale(range(`y1' `y2')) `ylab' `graphopts'

}

	if "`drop_trend'" != "" {

		twoway ///
	(line 		value time_num 	if group == "Control", 			lcolor(blue) 	lpattern(solid) lwidth(medium) 					 `l1_opts') ///
	(scatter 	value time_num 	if group == "Control", 			mcolor(blue) 	mlabel(lab_val) mlabposition(12) mlabcolor(blue)	 `m1_opts') ///
	(line 		value time_num 	if group == "Treatment", 		lcolor(green) 	lpattern(solid) lwidth(medium) 					 `l2_opts') ///
	(scatter 	value time_num 	if group == "Treatment", 		mcolor(green) 	mlabel(lab_val) mlabposition(12) mlabcolor(green) `m2_opts'), ///
	legend(order(1 "`group_lab1'" 3 "`group_lab2'")) legend(pos(6) row(1)) ///
	title("`graph_title'", size(small) span) xtitle("Time") ytitle("") ///
	xlabel(1 "`time_lab1'" 2 "`time_lab2'") xscale(range(0.95 2.05)) yscale(range(`y1' `y2')) `ylab' `graphopts'

}

	* Go back to the user's dataset

	restore

}

end