program ternary
	version 12.1
	syntax varlist(min=3 max=3) [, LABELS(varname) LABELSIZE(name) STYLE(name) BY(varname numeric) GRID(integer 3) LEGENDPOSition(integer 10) LEGENDSIZE(name) AXISLABELSIZE(name) AXISTITLESIZE(name) MARKERSymbols(namelist min=1 max=6) MARKERColors(namelist min=1 max=6) OUTER]

	quietly {

	/* TO DO: */
	/* 1. Axis titles able to be specified by user */


	/*========================================================================*/
	/* CHECKING OPTIONS ARE CORRECT                                           */
	/*========================================================================*/

	/* STYLE -----------------------------------------------------------------*/
	if "`style'"~="" & "`style'"~="scatter" & "`style'"~="connected" {
		noisily di as error "ERROR: If specified, style must be scatter or connected"
		exit
	}

	/* LABELSIZE, AXISLABELSIZE, AXISTITLESIZE, LEGENDSIZE--------------------*/

	if "`labelsize'"=="" local labelsize "medsmall"
	if "`axislabelsize'"=="" local axislabelsize "medsmall"
	if "`axistitlesize'"=="" local axistitlesize "medsmall"
	if "`legendsize'"=="" local legeendsize "medsmall"

	local ls = 0
	local als = 0
	local ats = 0
	local les = 0

	foreach choice in zero miniscule quarter_tiny third_tiny half_tiny tiny vsmall small medsmall medium medlarge large vlarge huge vhuge {
		if "`labelsize'"=="`choice'" {
			local ls = 1
		}
		if "`axislabelsize'"=="`choice'" {
			local als = 1
		}
		if "`axistitlesize'"=="`choice'" {
			local ats = 1
		}
		if "`legendsize'"=="`choice'" {
			local les = 1
		}
	}

	if `ls'==0 {
		noisily di as error "ERROR: labelsize must be a valid textsizestyle"
		exit
	}
	if `als'==0 {
		noisily di as error "ERROR: axislabelsize must be a valid textsizestyle"
		exit
	}
	if `ats'==0 {
		noisily di as error "ERROR: axistitlesize must be a valid textsizestyle"
		exit
	}
	if `les'==0 {
		noisily di as error "ERROR: legendsize must be a valid textsizestyle"
		exit
	}

	/* MARKER SYMBOLS --------------------------------------------------------*/

	local scount = 1
	tokenize "`markersymbols'"
	while "`1'"~="" {
		local msymbol`scount' = "`1'"
		local scount = `scount'+1
		macro shift
	}

	while `scount'<=6 {
		local msymbol`scount' = "circle"
		local scount = `scount'+1
	}

	local ms = 0

	foreach choice in O D T S + X o d s t x Oh Dh Th Sh oh dh th sh p i circle diamond triangle square plus smcircle smdiamond smsquare smtriangle smplus smx circle_hollow diamond_hollow triangle_hollow square_hollow smcircle_hollow smdiamond_hollow smtriangle_hollow smsquare_hollow {
		if "`msymbol1'"=="`choice'" local ms = `ms'+1
		if "`msymbol2'"=="`choice'" local ms = `ms'+1
		if "`msymbol3'"=="`choice'" local ms = `ms'+1
		if "`msymbol4'"=="`choice'" local ms = `ms'+1
		if "`msymbol5'"=="`choice'" local ms = `ms'+1
		if "`msymbol6'"=="`choice'" local ms = `ms'+1
	}

	if `ms' ~= 6 {
		noisily di as error "ERROR: markersymbol must be a valid symbolstyle"
		exit
	}

	/* LEGENDPOSITION --------------------------------------------------------*/

	if `legendposition'>12 | `legendposition'<1 {
		noisily di as error "ERROR: Legend position must take a value of between 1 and 12"
		exit
	}

	/* GRID VALUES -----------------------------------------------------------*/

	if `grid'>5 | `grid'<1 {
		noisily di as error "ERROR: Grid option must take a value of between 1 and 5"
		exit
	}

	/* MARKER COLOURS --------------------------------------------------------*/

	if "`markercolors'"~="" {
		local ccount = 1
		tokenize "`markercolors'"

		while "`1'"~="" {
			local color`ccount' "`1'"
			local ccount = `ccount'+1
			macro shift
		}
	}

/*	local color1 $DPRUGREEN
	local color2 $DPRUBLUE
	local color3 $DPRUDKGREEN
	local color4 $DPRUDKBLUE
	local color5 $DPRUTURQ
	local color6 $DPRUDKTURQ */


	/*========================================================================*/
	/* OTHER DEFAULT SETTINGS                                                 */
	/*========================================================================*/

	if "`style'"=="" | "`style'"=="scatter" {
		local stylecommand = "scatter"
		forvalues i = 1(1)6 {
			local connectedlinecommand`i' = ""
		} 	/* forvalues i */
	}	/* if "`style'"=="" */

	if "`style'"=="connected" {
		local stylecommand = "connected"
		forvalues i = 1(1)6 {
			if "`color`i'"~="" {
				local connectedlinecommand`i' lcolor("`color`i''")
			}
			else {
				local connectedlinecommand`1' ""
			}
		}	/* forvalues i */
	}	/* if "`style'"=="connected" */

	if "`by'"~="" {
		qui inspect `by'
		if `r(N_unique)'>6 {
			noisily di as error "Too many possible values in by variable"
			exit
		}
	}

	tempvar axispoint a b c A B C test vertex xcoord ycoord pointx pointy labeldots gridremover
	tokenize "`varlist'"
	qui gen `A' = `1'
	local A_name = "`1'"
	macro shift
	qui gen `B' = `1'
	local B_name = "`1'"
	macro shift
	qui gen `C' = `1'
	local C_name = "`1'"

	qui gen `test' = `A' + `B' + `C'
	qui capture assert (`test'<=1.001 & `test'>=0.999)							/* Checking data validity: a+b+c=1 */
	if _rc==9 {
		noisily di "Error: Variables need to sum to one for each observation."
		exit
	}

	/*========================================================================*/
	/* COORDINATES FOR TRIANGLE                                               */
	/*========================================================================*/

	qui count
	local origobs = `r(N)'
	if `origobs'<100 qui set obs 100
	qui gen `axispoint' = _n if _n<=100
	qui gen `a' = .
	qui gen `b' = .
	qui gen `c' = .

	/* For bottom line */
	qui replace `a' = 1 if `axispoint'==1
	qui replace `b' = 0 if `axispoint'==1
	qui replace `a' = 0.8 if `axispoint'==2
	qui replace `b' = 0.2 if `axispoint'==2
	qui replace `a' = 0.75 if `axispoint'==3
	qui replace `b' = 0.25 if `axispoint'==3
	qui replace `a' = 2/3 if `axispoint'==4
	qui replace `b' = 1/3 if `axispoint'==4
	qui replace `a' = 0.6 if `axispoint'==5
	qui replace `b' = 0.4 if `axispoint'==5
	qui replace `a' = 0.5 if `axispoint'==6
	qui replace `b' = 0.5 if `axispoint'==6
	qui replace `a' = 0.4 if `axispoint'==7
	qui replace `b' = 0.6 if `axispoint'==7
	qui replace `a' = 1/3 if `axispoint'==8
	qui replace `b' = 2/3 if `axispoint'==8
	qui replace `a' = 0.25 if `axispoint'==9
	qui replace `b' = 0.75 if `axispoint'==9
	qui replace `a' = 0.2 if `axispoint'==10
	qui replace `b' = 0.8 if `axispoint'==10
	qui replace `a' = 0 if `axispoint'==11
	qui replace `b' = 1 if `axispoint'==11

	/* For right line */
	qui replace `a' = 0 if `axispoint'>=12 & `axispoint'<=22
	qui replace `b' = 1 if `axispoint'==12
	qui replace `b' = 0.8 if `axispoint'==13
	qui replace `b' = 0.75 if `axispoint'==14
	qui replace `b' = 2/3 if `axispoint'==15
	qui replace `b' = 0.6 if `axispoint'==16
	qui replace `b' = 0.5 if `axispoint'==17
	qui replace `b' = 0.4 if `axispoint'==18
	qui replace `b' = 1/3 if `axispoint'==19
	qui replace `b' = 0.25 if `axispoint'==20
	qui replace `b' = 0.2 if `axispoint'==21
	qui replace `b' = 0 if `axispoint'==22

	/* For left line */
	qui replace `b' = 0 if `axispoint'>=23 & `axispoint'<=33
	qui replace `a' = 0 if `axispoint'==23
	qui replace `a' = 0.2 if `axispoint'==24
	qui replace `a' = 0.25 if `axispoint'==25
	qui replace `a' = 1/3 if `axispoint'==26
	qui replace `a' = 0.4 if `axispoint'==27
	qui replace `a' = 0.5 if `axispoint'==28
	qui replace `a' = 0.6 if `axispoint'==29
	qui replace `a' = 2/3 if `axispoint'==30
	qui replace `a' = 0.75 if `axispoint'==31
	qui replace `a' = 0.8 if `axispoint'==32
	qui replace `a' = 1 if `axispoint'==33

	/* This drops out the unnecessary grids */
	qui gen `gridremover' = (round(mod(`a'*`grid',1),0.001)~=0 | round(mod(`b'*`grid',1),0.001)~=0)
	qui replace `a' = . if `gridremover'==1
	qui replace `c' = 1 - `a' - `b'

	preserve
		des, replace clear
		qui su position if name=="`A_name'"
		local varpos = `r(max)'
		local vertexlabel_a = varlab[`varpos']
		qui su position if name=="`B_name'"
		local varpos = `r(max)'
		local vertexlabel_b = varlab[`varpos']
		qui su position if name=="`C_name'"
		local varpos = `r(max)'
		local vertexlabel_c = varlab[`varpos']
	restore

	/* This vertex code is used to create labels for the points on the triangle */
	qui gen `vertex' = ""
	qui replace `vertex' = "1" if `gridremover'~=1 		& (`axispoint'==1 | `axispoint'==12 | `axispoint'==23)
	qui replace `vertex' = "4/5" if `gridremover'~=1	& (`axispoint'==2 | `axispoint'==13 | `axispoint'==24)
	qui replace `vertex' = "3/4" if `gridremover'~=1	& (`axispoint'==3 | `axispoint'==14 | `axispoint'==25)
	qui replace `vertex' = "2/3" if `gridremover'~=1	& (`axispoint'==4 | `axispoint'==15 | `axispoint'==26)
	qui replace `vertex' = "3/5" if `gridremover'~=1	& (`axispoint'==5 | `axispoint'==16 | `axispoint'==27)
	qui replace `vertex' = "1/2" if `gridremover'~=1 	& (`axispoint'==6 | `axispoint'==17 | `axispoint'==28)
	qui replace `vertex' = "2/5" if `gridremover'~=1	& (`axispoint'==7 | `axispoint'==18 | `axispoint'==29)
	qui replace `vertex' = "1/3" if `gridremover'~=1	& (`axispoint'==8 | `axispoint'==19 | `axispoint'==30)
	qui replace `vertex' = "1/4" if `gridremover'~=1	& (`axispoint'==9 | `axispoint'==20 | `axispoint'==31)
	qui replace `vertex' = "1/5" if `gridremover'~=1	& (`axispoint'==10 | `axispoint'==21 | `axispoint'==32)
	qui replace `vertex' = "0" if `gridremover'~=1	& (`axispoint'==11 | `axispoint'==22 | `axispoint'==33)

	qui gen `xcoord' = `b' + `c'/2
	qui gen `ycoord' = `c' * (3^.5)/2
	qui replace `xcoord' = 0.5 if `axispoint'==97
	qui replace `ycoord' = -0.15 if `axispoint'==97
	qui replace `xcoord' = .9 if `axispoint'==98				/* 98 and 99 coordinates need refining */
	qui replace `ycoord' = 0.55 if `axispoint'==98
	qui replace `xcoord' = 0.1 if `axispoint'==99
	qui replace `ycoord' = 0.55 if `axispoint'==99
	capture la drop DOTLABELS
	la def DOTLABELS 97 "`vertexlabel_a'" 98 "`vertexlabel_b'" 99 "`vertexlabel_c'"
	la val `axispoint' DOTLABELS

	qui gen `pointx' = `B' + `C'/2
	qui gen `pointy' = `C' * (3^.5)/2


	/*========================================================================*/
	/* FOR OPTIONAL SHADED OUTER AREA                                         */
	/*========================================================================*/

	if "`outer'"=="outer" {
		qui su `xcoord' if `axispoint'>=24 & `axispoint'<=32
		local xdisp = `r(min)'
		qui su `xcoord' if `axispoint'>=2 & `axispoint'<=10
		local xshift = `r(min)'
		qui su `ycoord' if `axispoint'>=24 & `axispoint'<=32
		local ydisp = `r(min)'
		qui su `ycoord' if `axispoint'>=13 & `axispoint'<=21
		local yshift = `r(min)'

		qui replace `xcoord' = -`xdisp'-`xshift' if `axispoint'==40 | `axispoint'==80
		qui replace `ycoord' = -`ydisp' if `axispoint'==40 | `axispoint'==80

		qui replace `xcoord' = +`xdisp'+`xshift'+1 if `axispoint'==54
		qui replace `ycoord' = -`ydisp' if `axispoint'==54

		qui replace `xcoord' = 0.5 if `axispoint'==67
		qui replace `ycoord' = (3^.5)/2+2*`yshift' if `axispoint'==67

		local outercommand (area `ycoord' `xcoord' if `axispoint'==40 | `axispoint'==54 | `axispoint'==67 | `axispoint'==80, color(gs15) base(-`yshift')) (area `ycoord' `xcoord' if `axispoint'==1 | `axispoint'==12 | `axispoint'==23 | `axispoint'==33, color(white))
	}
	else {
		local outercommand (scatter `ycoord' `xcoord' if `axispoint'==.) (scatter `ycoord' `xcoord' if `axispoint'==.)
	}


	/*========================================================================*/
	/* TO ENSURE THAT THE TERNARY PLOT IS APPROPRIATELY POSITIONED TO MAIN-   */
	/* THE CORRECT ASPECT RATIO                                               */
	/*========================================================================*/
	qui su `pointy'
	local ymin = `r(min)'
	local ymax = `r(max)'
	qui su `pointx'
	local xmin = `r(min)'
	local xmax = `r(max)'
	qui su `ycoord'
	local ymax = max(`r(max)',`ymax')
	local ymin = min(`r(min)',`ymin')
	qui su `xcoord'
	local xmax = max(`r(max)',`xmax')
	local xmin = min(`r(min)',`xmin')

	local yrange = max(`ymax'-`ymin',1.05)
	local xrange = max(`xmax'-`xmin',1.05)

	local aspectratio = (`yrange'/`xrange')*5
	local xscalecommand xscale(off) xlabel(`xmin' `xmax')
	local yscalecommand yscale(off) ylabel(`ymin' `ymax')


	/*------------------------------------------------------------------------*/

	if "`labels'"=="" {
		local labelcommand = ""
	}
	else {
		local labelcommand = " mlabel(`labels') mlabsize(`labelsize') mlabcolor(black) "
	}

	local legendcommand ""

	if "`by'"~="" {
		local legendcommand order(
		local legendorder = 31
		qui levelsof `by', local(byvalues)

		local counter = 1
		foreach group of local byvalues {
			local sLabel: label (`by') `group'
			if "`color`counter'"~="" {
				local groupcommand`counter' (`stylecommand' `pointy' `pointx' if `by'==`group', msize(small) msymbol(`msymbol`counter'') mcolor("`color`counter''") `labelcommand' `connectedlinecommand`counter'')
			}
			else {
				local groupcommand`counter' (`stylecommand' `pointy' `pointx' if `by'==`group', msize(small) msymbol(`msymbol`counter'') `labelcommand' `connectedlinecommand`counter'')
			}
			local legendcommand `legendcommand' `legendorder' "`sLabel'"
			local counter = `counter' + 1
			local legendorder = `legendorder' + 1
		}

		if "`outer'"=="outer" {
			local legendcommand `legendcommand' 1 "Area bounded by -1/`grid'"
		}

		local legendcommand `legendcommand') col(1) size(`legendsize') position(`legendposition') ring(0)

		while `counter'<=6 {
			local groupcommand`counter' ""
			local counter = `counter' + 1
		}
	}
	else {
		if "`outer'"=="outer" {
			local legendcommand `legendcommand' 1 "Area bounded by -1/`grid'" col(1) size(`legendsize') position(`legendposition') ring(0)
		}
		else {
			local legendcommand "off"
		}
		if "`color1'"~="" {
			local groupcommand1 (`stylecommand' `pointy' `pointx', msize(small) msymbol(`msymbol1') mcolor("`color1'") `labelcommand' `connectedlinecommand1')
		}
		else {
			local groupcommand1 (`stylecommand' `pointy' `pointx', msize(small) msymbol(`msymbol1') `labelcommand' `connectedlinecommand1')
		}
		local groupcommand2 ""
		local groupcommand3 ""
		local groupcommand4 ""
		local groupcommand5 ""
		local groupcommand6 ""
	}


	#delimit ;
	twoway 	/*(area `ycoord' `xcoord' if `axispoint'==40 | `axispoint'==54 | `axispoint'==67 | `axispoint'==80, color(gs15) base(-`yshift'))
	(area `ycoord' `xcoord' if `axispoint'==1 | `axispoint'==12 | `axispoint'==23 | `axispoint'==33, color(white))*/
	`outercommand'
	(line `ycoord' `xcoord' if `axispoint'==1 | `axispoint'==11 | `axispoint'==23 | `axispoint'==33, lcolor(black))
	(line `ycoord' `xcoord' if `axispoint'==2 | `axispoint'==21 | `axispoint'==24, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==3 | `axispoint'==20 | `axispoint'==25, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==4 | `axispoint'==19 | `axispoint'==26, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==5 | `axispoint'==18 | `axispoint'==27, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==6 | `axispoint'==17 | `axispoint'==28, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==7 | `axispoint'==16 | `axispoint'==29, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==8 | `axispoint'==15 | `axispoint'==30, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==9 | `axispoint'==14 | `axispoint'==31, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==10 | `axispoint'==13 | `axispoint'==32, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==2 | `axispoint'==32, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==3 | `axispoint'==31, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==4 | `axispoint'==30, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==5 | `axispoint'==29, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==6 | `axispoint'==28, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==7 | `axispoint'==27, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==8 | `axispoint'==26, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==9 | `axispoint'==25, lcolor(black) lstyle(dot))
	(line `ycoord' `xcoord' if `axispoint'==10 | `axispoint'==24, lcolor(black) lstyle(dot))
	(scatter `ycoord' `xcoord' if `axispoint'>=1 & `axispoint'<=11, msymbol(none) mlabel(`vertex') mlabsize(`axislabelsize') mlabposition(6) mlabcolor(black))
	(scatter `ycoord' `xcoord' if `axispoint'>=12 & `axispoint'<=22, msymbol(none) mlabel(`vertex') mlabsize(`axislabelsize') mlabposition(2) mlabcolor(black))
	(scatter `ycoord' `xcoord' if `axispoint'>=23 & `axispoint'<=33, msymbol(none) mlabel(`vertex') mlabsize(`axislabelsize') mlabposition(10) mlabcolor(black))
	(scatter `ycoord' `xcoord' if `axispoint'==97, mlabel(`axispoint') mlabposition(0) mlabsize(`axistitlesize') mlabcolor(black) msymbol(none)) /* inserted*/
	(scatter `ycoord' `xcoord' if `axispoint'==98, mlabel(`axispoint') mlabposition(0) mlabsize(`axistitlesize') mlabcolor(black) msymbol(none) mlabangle(-60)) /* inserted*/
	(scatter `ycoord' `xcoord' if `axispoint'==99, mlabel(`axispoint') mlabposition(0) mlabsize(`axistitlesize') mlabcolor(black) msymbol(none) mlabangle(60)) /* inserted*/
	(scatter `ycoord' `xcoord' if `axispoint'==.) /* Placeholder commands so that groupcommand defaults align with scheme's default colours */
	(scatter `ycoord' `xcoord' if `axispoint'==.) /* Placeholder commands so that groupcommand defaults align with scheme's default colours */
	(scatter `ycoord' `xcoord' if `axispoint'==.) /* Placeholder commands so that groupcommand defaults align with scheme's default colours */
	`groupcommand1'
	`groupcommand2'
	`groupcommand3'
	`groupcommand4'
	`groupcommand5'
	`groupcommand6'
	,
	`xscalecommand'
	xlabel(, nogrid)
	`yscalecommand'
	ylabel(, nogrid)
	legend(`legendcommand') xsize(5) ysize(`aspectratio')
	graphregion(fcolor(white)) plotregion(fcolor(white))
	;
	#delimit cr

	qui drop if _n>`origobs'

	} /* quietly */

end