*!	Version 1.24 Feb. 1, 2022 by Mead Over
*!	Based on -reganat- Version 1.2. September 12th, 2012 by Valerio Filoso
* Based on version 1.2 of -reganat- by Valerio Filoso dated September 12th, 2012
* which is available as:
* package st0285 from http://www.stata-journal.com/software/sj13-1

*	Additional options added 4/22/2013
*		xoffset(xoffset_specification)		Specifies a constant to be added to x_tilde before graphing
*											Possible values are:
*												mean, min, max, p50, or any other r(.) macro from sum, detail
*												A scalar value specified by the user
*
*		centroid							Plots horizontal and vertical lines through the data centroid
*											When combined with option -xoffset(mean)-, the various
*											regression lines will pass visibly through the point of means.
*
*		saving(stub [,replace])				Specifies the stub of filenames for saved graphs

*	Additional options added 8/2/2013
*		name(string [,replace])				Specifies a name for the combined memory graph
*		*									Passes through all other options to the individual scatter plots

*	Additional option added 2/1/2022
*		store                               Store the estimated regression results using the names
*                                               reganat2_mv   The multivariate regression
*                                               reganat2_x    The regression of variable -x- on all the other rhs variables

program define reganat2
		version 10.1
		syntax varlist [if] [in] [aw fw pw iw/]  ///
			[, Dis(varlist) Label(varname) BIScat BILine Reg NOLegend NOCovlist Scheme(string) Fwl SEMip ///
			XOFFset(string) Centroid saving(string) name(passthru) store * ]	//	Additional options added by Mead Over

		preserve
		tokenize `varlist'
		local dependent `1'
			sum `dependent' `if' `in' , meanonly
			local dep_mean = r(mean)
		mac shift
		local independent `*'
		set graphics off

		* --------------------------------------------------------------------------------------
		* Variables to plot
		* --------------------------------------------------------------------------------------
		if "`dis'" == "" {
			local tobep = "`independent'"
		}
		else {
			local tobep = "`dis'"
		}

		* --------------------------------------------------------------------------------------
		* Header: General information to be displayed
		* --------------------------------------------------------------------------------------
		display " "
		display as text "Regression Anatomy"
		display as text "{hline 78}"
		display as text "Dependent variable ...... : " as result "`dependent'"
		display as text "Independent variables ... : " as result "`independent'"
		display as text "Plotting ................ : " as result "`tobep'"
		if "`label'" != "" {
			display as text"Label variable: `label'"
		}

		* --------------------------------------------------------------------------------------
		* Displaying the multivariate model, if requested
		* --------------------------------------------------------------------------------------
		if `"`reg'"'!="" {
			regress `varlist' `if' `in'
		}
		tempname mvreg
		est store `mvreg'
		if "`store'"~="" {
			est store reganat2_mv
		}

		* --------------------------------------------------------------------------------------
		* Calculating semipartial correlation coefficient, if required
		* --------------------------------------------------------------------------------------
		if "`semip'" != "" {
			pcorr `varlist' `if' `in'
			matrix spc = r(sp_corr)
			local spc_sum = 0
			local dimension = rowsof(spc)
			forvalues y = 1 (1) `dimension' {
				local spc_sum = `spc_sum' + spc[`y',1]^2
			}
			display as text " "
			display as text "Model's variance decomposition                            Value          Perc."
			display as text "{hline 78}"
			cap: reg `varlist' `if' `in'
			local common_v = e(r2) - `spc_sum'
			local idiosy_p = `spc_sum' / e(r2)
			local common_p = `common_v' / e(r2)
			display as text "Variance explained by the X's individually              " as result %7.4f `spc_sum' "        " as result %7.4f `idiosy_p'
			display as text "Variance common to X's                                  " as result %7.4f `common_v' "        " as result %7.4f `common_p'
			display as text "{hline 78}"
			display as text "Variance explained by the model (R-squared)             " as result %7.4f e(r2)
		}


		* --------------------------------------------------------------------------------------
		* Size of marker in scatterplot
		* --------------------------------------------------------------------------------------
		cap: count `if' `in'
		if r(N) > 500 {
			local size = "tiny"
		}
		else {
			local size = "small"
		}

		* --------------------------------------------------------------------------------------
		* Extraction of variables' labels
		* --------------------------------------------------------------------------------------
		local lbldepvar : variable label `dependent'
		if "`lbldepvar'" == "" {
			local lbldepvar = "`dependent'"
		}

		* --------------------------------------------------------------------------------------
		* A string with the list of controls
		* --------------------------------------------------------------------------------------
		cap: local stringa = ""
		foreach x of local independent {
			local etichetta : variable label `x'
			if "`etichetta'" == "" {
				local etichetta = "`x'"
			}
			local stringa = "`stringa', `etichetta'"
			}
		local stringa = substr("`stringa'",2,.)

		* --------------------------------------------------------------------------------------
		* Markers for observations in the scatterplot, if selected
		* --------------------------------------------------------------------------------------
		if "`label'" == "" {
			local etich = ""
		}
		else {
			local etich = "mlabel(`label') mlabsize(tiny) mlabposition(9) msize(`size')"
		}

		cap: macro drop totvar
		local totvar = 0

		* --------------------------------------------------------------------------------------
		* Forming the names of saved graph files (added by Mead Over)
		* --------------------------------------------------------------------------------------
		if "`saving'" ~= "" {
			if strpos("`saving'", ",") > 0 {
				local replace , replace
				local stub = substr("`saving'",1,strpos("`saving'", ",")-1)
			}
			else {
				local stub "`saving'"
			}
		}

		* --------------------------------------------------------------------------------------
		* Preparing the graphs for each variable to be printed
		* --------------------------------------------------------------------------------------
		foreach x of local tobep {

			local totvar = `totvar' + 1
			local lblx : variable label `x'

			if "`lblx'" == "" {
				local lblx = "`x'"
			}

			local covariates = subinword("`independent'","`x'","",1)

			* Preparing x-tilde, according to Regression anatomy theorem
			cap: regress `x' `covariates' `if' `in'
			cap: predict resid_`x' `if' `in', residuals
			label variable resid_`x' "`x'"

			if "`store'"~="" {
				est store reganat2_`x'
			}

*			* Displaying regression results, if required
*			if `"`reg'"'!="" {
*				regress `varlist' `if' `in'
*			}

			* Dropping all the missing obs  (MO: This is draconian.  Why not use -marksample- ? )
			cap: keep if e(sample)

			* Subtracting the relevant mean
			cap: summarize `x', detail
			if "`xoffset'" ~= "" & real("`xoffset'")==. {
				local `x'_`xoffset' = r(`xoffset')
				if ``x'_`xoffset''>=.  {
					di as err _n "The -xoffset()- option must be specified as either a real number"  ///
							_n "or as one of the results stored by the {help summarize##results:summarize, detail} command."  ///
							_n "Here the -xoffset()- option is: " as res "`xoffset'"
					exit 198
				}
			}
			cap: gen `x'_std = `x'-r(mean)

			*	Add a constant "offset" to resid_x and enable plotting of "centroid" (by Mead Over)
			local abscissa resid_`x'
			if "`xoffset'" ~= "" {
				if real("`xoffset'")~=. {
					qui gen `x'_offset = resid_`x' + `xoffset'
					qui replace `x'_std = `x'_std + `xoffset'
					di _n as res "`xoffset'" as txt " added to the residuals of the independent variable "  ///
						as res "`x'"
				}
				else {
					qui gen `x'_offset = resid_`x' + ``x'_`xoffset''
					qui replace `x'_std = `x'_std + ``x'_`xoffset''
					di _n as res "`xoffset'" as txt " of the independent variable "  ///
						as res "`x'" as txt " added to its residuals"
				}
				lab var `x'_offset `"`x'_resid + `xoffset'"'

				local abscissa `x'_offset
			}
			if "`centroid'"~="" {
				if "`xoffset'" == "" {
					di as err "Warning: Adding the centroid option without using the -xooffset- option might distort the graph."
				}
				sum `dependent' , meanonly
				local centroidopts yline(`r(mean)',lpattern(".##") lwidth(medthick))
				sum `x' , meanonly
				local centroidopts `centroidopts' xline(`r(mean)',lpattern(".##") lwidth(medthick))
				local legcent "Dotted crosshairs locate the centroid of the original data"
			}


			* Generate regression parameters estimates
			cap: regress `dependent' `independent' `if' `in'
			local beta = string(_b[`x'],"%9.3f")
			local sebeta = string(_se[`x'],"%9.3f")

			cap: regress `dependent' `x' `if' `in'
			local betab = string(_b[`x'],"%9.3f")
			local sebetab = string(_se[`x'],"%9.3f")

			cap: regress `dependent' resid_`x' `if' `in'
			local spc = string(e(r2),"%9.3f")

			* In case the user requires the FWL version
			if `"`fwl'"'!="" {
				cap: regress `dependent' `covariates' `if' `in'
				cap: drop r_`dependent'_`x'
				cap: drop y_buffer
				cap: predict r_`dependent'_`x', residuals
				cap: generate y_buffer =  `dependent'
				cap: replace `dependent'= r_`dependent'_`x'
				local addition " (FWL version)"
			}


			* Scatterplots

		* --------------------------------------------------------------------------------------
		* Adding the bivariate scatterplot
		* --------------------------------------------------------------------------------------
			if `"`biscat'"'!="" {
				local biscat "(scatter `dependent' `x'_std `if' `in', `etich' msymbol(triangle))"
				local legscat "Scatterplot: Dots = Transformed data, Triangles = Original data."
			}

		* --------------------------------------------------------------------------------------
		* Adding the bivariate regression line
		* --------------------------------------------------------------------------------------
			if `"`biline'"'!="" {
				local capt "caption(`"Bivariate slope: `betab' (`sebetab')"', bexpand justification(left) size(small))"
				local biline "(lfit `dependent' `x'_std `if' `in', lwidth(medium) lpattern(dash) caption(`"Bivariate slope: `betab' (`sebetab')"', size(small) justification(left)) note("Multivariate slope: `beta' (`sebeta'). Semipartial rho2: `spc'", justification(left) size(small)))"

				* --------------------------------------------------------------------------------------
				* Adding or removing the legend
				* --------------------------------------------------------------------------------------
				if `"`nolegend'"'=="" {
					local note `"caption(`"Regression lines: Solid = Multivariate, Dashed = Bivariate."' "`legscat'" "`legcent'", size(small) alignment(middle) position(6) justification(center) box bexpand bmargin(medlarge) span)"'
				}
				else {
					local note ""
				}
			}

		* --------------------------------------------------------------------------------------
		* Preparing the single graphs, with several options
		* --------------------------------------------------------------------------------------
			if "`saving'"~="" {  //	Added by MO
				local svng saving(`stub'_`x'.gph `replace')
			}

			scatter `dependent' `abscissa' `if' `in', xtitle("`lblx'") ytitle("") `etich' xsca(titlegap(2)) ylabel(minmax) xlabel(minmax, nogextend) ymtick(##5) xmtick(##5) ///
				name(`x', replace) legend(off) /* title("`lblx'", span) */ `centroidopts' `svng' `options' || ///
				lfit `dependent' `abscissa' `if' `in', lpattern(solid) lwidth(medium)  xlabel(, labsize(vsmall)) ylabel(, labsize(vsmall)) ///
				note("Multivariate slope: `beta' (`sebeta'). Semipartial rho2: `spc'", bexpand justification(left) size(small)) || ///
				`biline' || ///
				`biscat'


		* In case the user required the FWL option, restore the original values of y
			if `"`fwl'"'!="" {
				cap: replace `dependent' = y_buffer
				cap: drop y_buffer
			}

		* This closes the loop over independent variables
		}

		* --------------------------------------------------------------------------------------
		* Adding or removing the list of covariates
		* --------------------------------------------------------------------------------------
			if `"`nocovlist'"'=="" {
				local covlist "note("Covariates: `stringa'.", bexpand size(medsmall) justification(center) alignment(middle))"
			}
			else {
				local covlist ""
			}

		* --------------------------------------------------------------------------------------
		* Defining the composite graph's style
		* --------------------------------------------------------------------------------------
			if `"`scheme'"'!="" {
				local schema "`scheme'"
			}
			else {
				local schema "sj"
			}

		* --------------------------------------------------------------------------------------
		* Building up the composite graph
		* --------------------------------------------------------------------------------------
		if "`saving'"~="" {  //	Added by MO
			local svng saving(`stub'_combined.gph `replace')
		}
		set graphics on
		graph combine `tobep', ///
		title("Regression Anatomy`addition'", span) subtitle("Dependent variable: `lbldepvar'", span) ///
		`covlist' ///
		`note' ///
		`nota' ///
		scheme(`schema') commonscheme  `svng' `name'

		restore
		est restore `mvreg'
end
*	Version 1.21 April 22, 2013: modified by Mead Over to incorporate the options xoffset, centroid and saving.
*	Version 1.22 August 2, 2013: modified by Mead Over to incorporate the options name and "*".
*	Version 1.23 July 19, 2016: To insert error trap if -xoffset()- option is not something returned by sum, detail
*	Version 1.24 Feb. 1, 2022: Add file extension -.gph- to saved graph files.  Move variable label from -title()- to -xtitle()-
*		Add the option store such that all the estimation results are stored.  Also restore the multivariate regression results.