*! version 1.0	1.6.2026
*! Matthew Burnell


/*
DESCRIPTION
mixedpower ia a power calculator for linear mixed models.

*/
**# PROGRAM

program define mixedpower , rclass
	version 17.0

	local version 1.0
	local date 01June2026
	if _caller() >= 12 {
		local hidden hidden
	}
	return `hidden' local mixedpower_version "`version'"
	return `hidden' local mixedpower_date "`date'"
	if "`0'"=="which" exit

	syntax, SCHEDule(numlist ascending >=0 min=2 max=100)	/// schedule list of time incl. baseline
			TRTSPEC(string)							/// how treatment effect specified (slope, intercept, slope and intercept or piecewise (factor and factor0))
			[   									///
			LCTest(numlist)  						///  lincom test of trt paremeters
			JTTest(numlist integer >=0 <=1)			/// joint test of trt paremeters
			CONTSlope(string) 						/// the overall mean slope of the 'control' group
			EFFectiveness(string)  					/// proportionate effect on slope (not for other trtspec types)
			DIFFerence(numlist  min=1 max=100)   					/// the alternative hypothesis difference (numberlist for factor, intercept and slint choices in trtspec())
			ALTCont(string)							/// if you want the cont (control) slope to be piecewise/time-factorised/ or specify no intercept or no slope (factor, noint, noslope - default is slope and intercept)
			ACTUALTRT(string)						/// calculate power for an incorrect treatment specification, by specifying the true treatment specification
			ACTUALCont(string)						/// if you also want to indicate that the control specification is incorrect, hence give correct specification
			CBETA(numlist min=1)					/// control beta values if using actualcont()
			Alpha(real 0.05) 						/// alpha level of test
			TWOSided								/// request properly two-sided test
			POWer(string) 							/// required power
			n(string) 								/// provided sample size
			ARAtio(numlist integer >0 min=2 max=2)	///  allocation ratio of controls:treatment adjustment version
			ALLORatio(numlist integer >0 <=10 min=2 max=2) /// HIDDEN	allocation ratio version of controls:treatment MULTIMATRIX VERSION
 			DROPouts(numlist >=0 <=1)	  			///	numlist values of p(making visit to k and no further) due to dropout (possibly for Control group only)
			DROP2(numlist >=0 <=1)	  				///	numlist values of p(making visit to k and no further) for Treatment Group if different to Control
			STRECruitment(numlist >=0 <=1) 			///	numlist values of p(making visit to k and no further) due to staggered recruitment
			COVariance(string) 						///	covariance matrix of random effect parameters
			ERRORvar(string) 						/// error term (or matrix for multivariate)
			AUTO 									/// speedy variance input using mixed model in memory
			MARGinal								/// specify marginal model - XT variance modelled by error structure patterns only - no random effects included
		    ERRHET(string)  						///  different error terms for treatment group
			ERRXT(string) 							/// matrix input for general or specific non-independent error types across repeated measures - usually for use with 'marginal'
			COVHET(string) 							///	covariance matrix of random effect parameters for treatment group if different
			SCAle(real 1)  							/// to specify schedule numlist in different scale to variance input
			NOSYNtax								/// prevent display of model syntax
			XMAT(numlist integer >=1 max=1)			/// return specific X matrix
			RMAT(numlist integer >=1 max=1)			/// return specific R matrix
			ZMAT(numlist integer >=1 max=1)			/// return specific Z matrix
			GMAT(numlist integer >=1 max=1)			/// return specific G matrix
			BVARN(numlist integer >=1 max=1)		/// return specific Beta covariance matrix
			NOHEADer								/// turn off header
			NOTABle									/// turn of table of counts
			FRAMES(string)							/// HIDDEN OTPION keep frames of generated X, R, Z and G matrices
			FRDROP									/// HIDDEN OTPION use to drop _mp frames from previous run of mixedpower when frames(keep) option used - might not (depending on _mp name) run otherwise unless manually dropped first.
			  /// /* following options for integrating uncertainty */ to be part of separate program?
			IVW										/// HIDDEN OTPION to use IVW instead of inverse-covariance weighting for calculating cohort-combined Betas with X-misspecification
			]



**# PROLOGUE
	local cframe=c(frame)
	if strmatch("`cframe'","_mp_2level*" )==1 | strmatch("`cframe'","_mp_multi*" ) ==1 | strmatch("`cframe'","_mp_direct*" )==1 | strmatch("`cframe'","_mp_3level*" )==1 {
		di as error "You are running mixedpower whilst currently active with a mixedpower derived frame. You need to first change (back) to a different frame, likely 'default'. See {help frames}, including {help frame dir} and {help frame change}"
		exit 198
	}
	else return local fr_current `cframe'


		*** see if previous command was trialcounts and return that cmdline
	local commandline `=r(cmdline)'
	gettoken command  : commandline
	if strmatch("`command'","trialcounts")==1 {
		return local trialcounts_cmd `commandline'
	}

**# required options

** Schedule list - inbuilt Stata syntax check is sufficient for parsing SCHEDule

	* Length of schedule list:
		local sched_length = 0
		foreach i of numlist `schedule' {
			local sched_length = `sched_length' + 1
			}

	* Decant the schedule numlist into locals
		tempname schedmat
		mat `schedmat'=J(1,`sched_length',0)
		local j = 1 // counter - position number
		foreach i of numlist `schedule' {
			local sched`j' = `i'
			mat `schedmat'[1,`j']=`sched`j''
			local j=`j'+1
		}

		* for inserting into prior code as model label
	local model 2level

**# TRTSPEC
				** And treatment specification type is chosen and correct - if not chosen then assume
if strmatch("`trtspec'", "user(*)") local tusertext `trtspec' // to pass to 3level to parse again
if strmatch("`altcont'", "user(*)") local cusertext `trtspec'

			/* define trtspec type */


				foreach trtsp in slope intercept factor factor0 slint {
					if "`trtspec'"=="`trtsp'" {
						local tscheck yes
					}
				}
				if 	"`tscheck'"=="yes" local trtspec "`trtspec'"
				else if strmatch("`trtspec'", "lateslope *") { // lateslope with time value at separation
					local lslt =subinstr("`trtspec'", "lateslope ", "", 1)
					xslopecheck, xnum(`lslt') option(trtspec) spec(lateslope #)
					local trtspec "lateslope"
				}
				else if strmatch("`trtspec'", "2slope *") { // 2slope with time value at changepoint
					local tslt =subinstr("`trtspec'", "2slope ", "", 1)
					xslopecheck, xnum(`tslt') option(trtspec) spec(2slope #)
					local trtspec "2slope"
				}
				else if strmatch("`trtspec'", "user(*)") { // user provided function
					local tuser =subinstr("`trtspec'", "user", "", 1)
					usercheck, func(`tuser') option(trtspec) xvalues(`schedule')
					local trtspec "user"
					local tuserf_n =`s(nfun)'
					local txfun_1 `s(xfun1)'
					local tfunc_1 `s(funct1)'
					if `tuserf_n'==2 {
						local txfun_2 `s(xfun2)'
						local trtspec "user2"
						local tfunc_2 `s(funct2)'
					}
				}
				else {
					display as error "trtspec() type must be one of 'slope', 'intercept', 'factor', 'factor0' (factorised including term at baseline), 'lateslope #' '2slope #', 'slint' (slope and intercept terms) or 'user(f1[; f2]"
					exit 198
				}

**# ALTCONT
					/* define altcont type */
		if "`altcont'"==""	local altcont slint

		foreach contsp in noslope noint factor slint  {
			if "`altcont'"=="`contsp'" {
				local cscheck yes
			}
		}
		if 	"`cscheck'"=="yes" local altcont "`altcont'"
				else if strmatch("`altcont'", "2slope *") { // 2slope with time value at changepoint
					local Ctslt =subinstr("`altcont'", "2slope ", "", 1)
					xslopecheck, xnum(`Ctslt') option(altcont) spec(2slope #)
					local altcont "2slope"
				}
				else if strmatch("`altcont'", "user(*)") { // user provided function
					local cuser =subinstr("`altcont'", "user", "", 1)
					usercheck, func(`cuser') option(altcont) xvalues(`schedule')
					local altcont "user"
					local cuserf_n =`s(nfun)'
					local cxfun_1 `s(xfun1)'
					local cfunc_1 `s(funct1)'
					if `cuserf_n'==2 {
						local cxfun_2 `s(xfun2)'
						local altcont "user2"
						local cfunc_2 `s(funct2)'
					}

				}
				else {
					display as error "Alternative cont model - altcont() - types are one of 'noslope' (no slope i.e intercept only), 'noint' (no intercept i.e slope only), '2slope #', 'factor' or 'user(f1[; f2]. The default, not actively selected, is both slope and intercept terms"
					exit 198
				}

		** checking that if 2slope selected for both control and treatment - that changepoint is at same value of taken
		if "`trtspec'"=="2slope" & "`altcont'"=="2slope" {
				if `tslt'!=`Ctslt' {
					di as error "if '2slope' selected for both altcont() and trtpsec() then changepoint selected for both options must be the same"
					exit 198
			}
		}




					** Equivalent treatment and control checks for when actualtrt() and actualcont() specified


**# ACTUALTRT
			/* define actualtrt type */

				foreach atrtsp in slope intercept factor factor0 slint {
					if "`actualtrt'"=="`atrtsp'" {
						local atscheck yes
					}
				}
				if 	"`atscheck'"=="yes" local actualtrt "`actualtrt'"
				else if strmatch("`actualtrt'", "lateslope *") { // lateslope with time value at separation
					local alslt =subinstr("`actualtrt'", "lateslope ", "", 1)
					xslopecheck, xnum(`alslt') option(actualtrt) spec(lateslope #)
					local actualtrt "lateslope"
				}
				else if strmatch("`actualtrt'", "2slope *") { // 2slope with time value at changepoint
					local atslt =subinstr("`actualtrt'", "2slope ", "", 1)

					xslopecheck, xnum(`atslt') option(actualtrt) spec(2slope #)
					local actualtrt "2slope"
				}
				else if strmatch("`actualtrt'", "user(*)") { // user provided function
					local atuser =subinstr("`actualtrt'", "user", "", 1)
					usercheck, func(`atuser') option(actualtrt) xvalues(`schedule')
					local actualtrt "user"
					local atuserf_n =`s(nfun)'
					local atxfun_1 `s(xfun1)'
					local atfunc_1 `s(funct1)'
					if `atuserf_n'==2 {
						local atxfun_2 `s(xfun2)'
						local actualtrt "user2"
						local atfunc_2 `s(funct2)'
					}
				}
				else if "`actualtrt'"=="" {
				}
				else {
					display as error "actualtrt() type must be one of 'slope', 'intercept', 'factor', 'factor0' (factorised including term at baseline), 'lateslope #' '2slope #', 'slint' (slope and intercept terms) or 'user(f1[; f2]"
					exit 198
				}

**# ACTUALCont
					/* define actualcont type */


		foreach acontsp in noslope noint factor slint  {
			if "`actualcont'"=="`acontsp'" {
				local acscheck yes
			}
		}
		if 	"`acscheck'"=="yes" local actualcont "`actualcont'"
				else if strmatch("`actualcont'", "2slope *") { // 2slope with time value at changepoint
					local aCtslt =subinstr("`actualcont'", "2slope ", "", 1)
					xslopecheck, xnum(`aCtslt') option(actualcont) spec(2slope #)
					local actualcont "2slope"
				}
					else if strmatch("`actualcont'", "user(*)") { // user provided function

					local acuser =subinstr("`actualcont'", "user", "", 1)
					usercheck, func(`acuser') option(actualcont) xvalues(`schedule')
					local actualcont "user"
					local acuserf_n =`s(nfun)'

					local acxfun_1 `s(xfun1)'
					local acfunc_1 `s(funct1)'
					if `acuserf_n'==2 {
						local acxfun_2 `s(xfun2)'
						local actualcont "user2"
						local acfunc_2 `s(funct2)'
					}
				}
				else if "`actualcont'"=="" {
				}
				else {
					display as error "Actual control model - actualcont - types are one of 'slint' (slope and intercept) 'noslope' (no slope i.e intercept only), 'noint' (no intercept i.e slope only), '2slope #', 'factor' or 'user(f1[; f2]. "
					exit 198
				}




**# TEST Check
			** Checking Test Options
	if "`jttest'"!="" & "`lctest'"!="" {
		dis as error  "cannot specify both jttest() and lctest"
					exit 198
	}

			* first change lctest or jttest
	if 	"`jttest'"!="" local test "joint(`jttest')"
	if 	"`lctest'"!="" local test "`lctest'"


	if "`trtspec'"=="slope" |  "`trtspec'"=="intercept" |  "`trtspec'"=="lateslope" | "`trtspec'"=="user"   {
		if "`test'"=="paired" {	// secret paired z-test
		}
		else if "`test'"!="" {
			dis as error  "test() is not specified when trtspec() is 'slope', 'intercept', 'lateslope' or 'user'"
					exit 198
		}
	}

	else if "`test'"!="ivw" & "`test'"!="factorslope" & "`test'"!="factorint" & strmatch("`test'","joint(*)")==0 {
				testcheck,  tsp(`trtspec') schl(`sched_length') test(`test')
				qui numlist "`test'"
				local test=r(numlist)
			}

	if strmatch("`test'","joint(*)")==1 {
		local joint=subinstr("`test'", "joint(", "", 1)
		local joint=subinstr("`joint'", ")", "", 1)

		testcheck,  tsp(`trtspec') schl(`sched_length') test(`joint') xtra(joint())
		local jointlength : word count `joint'

			local df_jt=0
			forvalues jt=1/`jointlength' {
				local joint`jt' : word `jt' of `joint'
				 if `joint`jt''!=0 local df_jt=`df_jt'+1
			}
	}


**# COVARIANCE/ERROR specification
	  ** Making sure either errorvar or errxt is specified (when auto not used)
	  	if "`errorvar'"!="" & "`errxt'"!="" {
	  	dis as error "You must specify only one of errorvar() or errxt()"
					exit 198
	  }
	  if "`auto'"=="" {
		  if "`errorvar'"=="" & "`errxt'"=="" {
			dis as error "You must specify either errorvar() or errxt() if not using auto option"
						exit 198
		  }
	  }
	  if "`errorvar'"=="" & "`errxt'"!="" {
		local errmethod errmethod
	  }
	  if "`errorvar'"!="" & "`errxt'"=="" {
		local errmethod errmethod
	  }

				** Check either auto or (ERRorvar & COVariance) used
	if  "`marginal'"=="" {
	if "`covariance'"!="" & "`auto'"!="" {
					dis as error "You cannot specify both covariance() (together with errorvar()/errxt()) and auto"
					exit 198
				}
	if "`covariance'"=="" & "`auto'"=="" {
					dis as error "No covariance parameter specification: please specify either covariance() and errorvar()/errxt() OR auto OR marginal if intend no random effects"
					exit 198
				}

				* check errorvar and auto not both specified
	if "`errorvar'"!="" & "`auto'"!="" {
					dis as error "You cannot specify both errorvar() (together with covariance()) and auto"
					exit 198
				}
				* Check  error variance included if covariance used
	if "`covariance'"!="" & "`errmethod'"=="" {
					dis as error "You must specify either errorvar()/errxt() with covariance()"
					exit 198
				}
				* Check covariance included if errorvar used
	if "`covariance'"=="" & "`errorvar'"!="" {
					dis as error "You must specify covariance() with errorvar()"
					exit 198
				}
	}
	if "`auto'"!=""  & "`e(cmd)'"!="mixed" {
		di as error "there is no mixed model fitted by {helpb mixed} in memory"
		exit 198
	}

			* Check covariance/error commands not used with marginal option
	if  "`marginal'"!="" {
		if "`errorvar'"!=""  {
					dis as error "You cannot specify both errorvar() and marginal - for a marginal model the error terms (even 'identity' structure) are specified through errxt()"
					exit 198
				}
		if "`covariance'"!=""  {
					dis as error "You cannot specify both covariance() and marginal"
					exit 198
				}
		if "`auto'"!=""  {
					dis as error "You cannot specify both auto and marginal"
					exit 198
				}
	}

				** Check Covariance values
	if  "`marginal'"=="" {
				* Check COVariance is correctly specified in matrix format
		if "`covariance'"!=""  {
					tempname cm
					capture mat `cm'=  `covariance' // first checking matrix supplied in correct format
						if  _rc!=0 {
									dis as error "entry for covariance() not in matrix format"
						exit 198
								}
					capture confirm matrix `cm'  // first checking matrix supplied in correct format
					if  _rc!=0 {
									dis as error "matrix entry for covariance() not correct format"
						exit 198
								}
					}


		else if "`auto'"!="" & "`=e(redim)'"=="0" { // RE CHECK
			di as error "mixed model in memory has no random effects and marginal has not been specified"
			exit 198
		}
		else if "`auto'"!="" & `=e(k_r)'==1 {  // RE CHECK
			di as error "mixed model in memory has no random effects and marginal has not been specified"
			exit 198
		}


		if "`covhet'"!=""  {
			local covhet=strtrim("`covhet'")
			if strmatch("`covhet'", "auto") local chtype chauto
			else if strmatch("`covhet'", "input(*)") {  // checking the auto suboptions
				local chtype chinput
				local chmat=subinstr(`"`covhet'"', "input(", "", 1)
				local chmat=strtrim(subinstr("`chmat'", ")", "", 1))
				tempname chm
				capture mat `chm'=  `chmat' // first checking matrix supplied in correct format
					if  _rc!=0 {
								dis as error "entry for covhet() not in matrix format"
					exit 198
							}
				capture confirm matrix `chm'  // first checking matrix supplied in correct format
				if  _rc!=0 {
								dis as error "entry for covhet() not in matrix format"
					exit 198
							}
				}
			else {
				di as error "covhet() must be specified as 2x2 symmetric matrix using input() suboption or use auto-input of variance parameters with auto suboption"
			}
		}

	}

**# ERRXT PARSING
			** Check ERRXT and ERRHET auto-options

	if  "`marginal'"!="" {
		if "`errxt'"=="" {
			dis as error "if option marginal specified then must provide an xt error structure in errxt()"
					exit 198
		}
	}

	if 	"`errxt'"!=""  {
		local errxt=strtrim("`errxt'")
		if strmatch("`errxt'", "auto") {
			local restype resauto
			errxtmixcheck, residt(`=e(rstructlab)') hetcheck(`=e(resopt)') hety(no)
			local resid `s(residt)'
			local rsh `s(rshort)'
			local rnumber=`s(rnum)'
			local `rsh'n=`rnumber'
			if "`resid'"=="unstructured" & e(k_rs)/e(nrgroups)<`sched_length' {
				di as error "not enough error terms in auto model in memory for schedule length"
				exit 198
			}
		}

		else if strmatch("`errxt'", "input(*)") {  // checking the input suboptions
			local restype resinput
			local resid=subinstr(`"`errxt'"', "input(", "", 1)
			local resid=strtrim(subinstr("`resid'", ")", "", 1))

			local resabbrev: word 1 of `resid'
			capture extabcheck, `resabbrev'
			local resfull `s(exttype)'

			if "`s(exttype)'"=="" err198 You have not correctly specified the residual error structure name
			local resid: subinstr local resid "`resabbrev'" "`resfull'"

			if strmatch("`resid'", "ar *") { // if AR residuals
				local arn2=subinstr("`resid'", "ar ", "", 1)
				local arn2length : word count `arn2'
				if `arn2length'<2 | `arn2length'>3  { // WAS: if `arn2length'<2 | `arn2length'>`sched_length'
					dis as error  " list of AR parameters with 'input' suboption must be at least two and currently at most 3 (for AR 2)"
					exit 198
				}
				forvalues d=1/`arn2length' {
					local contents`d' : word `d' of `arn2'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "list of AR parameters must all be number values"
							exit 198
					}
				}
					if  `arn2length'==2 & (`contents2'>=1 | `contents2' <=-1) {
						dis as error "AR autocorrelation parameter must be inside range {-1, 1}" // CHANGE!!!
							exit 198
					}

			}

			else if strmatch("`resid'", "ma *") { // if MA residuals
				local man2=subinstr("`resid'", "ma ", "", 1)
				local man2length : word count `man2'
				if `man2length'<2 | `man2length'>3  { // currently max=2 if `man2length'<2 | `man2length'>`sched_length'
					dis as error  " list of MA parameters must be at least two and and currently at most 3 (for MA 2)"
					exit 198
				}
				forvalues d=1/`man2length' {
					local contents`d' : word `d' of `man2'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "list of MA parameters must all be number values"
							exit 198
					}
				}
			}
						// no input version of Banded residuals - use unstructured

			else if strmatch("`resid'", "toeplitz *") { // if Toeplitz residuals
				local ton2=subinstr("`resid'", "toeplitz ", "", 1)
				local ton2length : word count `ton2'
				if `ton2length'==0 | `ton2length'>`sched_length'  {
					dis as error  " list of Toeplitz parameters must be at least one and equal or less than schedule length"
					exit 198
				}
				forvalues d=1/`ton2length' {
					local contents`d' : word `d' of `ton2'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "list of Toeplitz parameters must all be number values"
							exit 198
					}
				}
			}
			else if strmatch("`resid'", "exponential *") { // if Exponential residuals i.e generalised AR 1
				local exn2 =subinstr("`resid'", "exponential ", "", 1)
				local exn2length : word count `exn2'
				if `exn2length'!=2  {
					dis as error  " list of exponential parameters must be 2"
					exit 198
				}
				forvalues d=1/`exn2length' {
					local contents`d' : word `d' of `exn2'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "list of exponential parameters must all be number values"
							exit 198
					}
				}
				if `contents2' <=-1 | `contents2'>=1 {
					dis as error "Exponential autocorrelation parameter must be inside range {-1, 1}"
					exit 198
				}
			}
			else if strmatch("`resid'", "unstructured *") { // if unstructured

				local rm =subinstr("`resid'", "unstructured ", "", 1)
				local rm2length : word count `rm'
				if `rm2length'>1  {
					dis as error "suboption input(unstructured {it: matname}) must be supplied with single name of matrix"
					exit 198
				}
				tempname resid_mat
				capture mat `resid_mat'=  `rm' // first checking matrix supplied in correct format
					if  _rc!=0 {
								dis as error "matrix entry for input(unstructured {it: matname}) not correct format"
					exit 198
							}
				capture confirm matrix `resid_mat'  // first checking matrix supplied in correct format
				if  _rc!=0 {
								dis as error "matrix entry for input(unstructured {it: matname}) not correct format"
					exit 198
							}
				local col=colsof(`resid_mat')
				local sym= issymmetric(`resid_mat')
				if `sym' ==0 {
					mat li `resid_mat'
					dis as error "matrix entry for input(unstructured {it: matname}) must be symmetric"
					exit 198
				}

				if `col'!=`sched_length' {
								dis as error "matrix entry for input(unstructured {it: matname}) must be symmetric nxn, where n=number of measures supplied in schedule()"
					exit 198
				}

			}
			else if strmatch("`resid'", "exchangeable *") { // if exchangeable
				local ecn2 =subinstr("`resid'", "exchangeable ", "", 1)
				local ecn2length : word count `ecn2'
				if `ecn2length'!=2   {
					dis as error  " list of suboption input(exchangeable # #) parameters in errxt() must be of length 2"
					exit 198
				}
				forvalues d=1/`ecn2length' {
					local contents`d' : word `d' of `ecn2'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "list of suboption input(exchangeable # #) parameters in errxt() must both be number values"
							exit 198
					}
				}
			}
			else if strmatch("`resid'", "independent *") { // if independent
				local inn2 =subinstr("`resid'", "independent ", "", 1)
				local inn2length : word count `inn2'
				if `inn2length'!=1 & `inn2length'!=`sched_length'    {
					dis as error  " list of suboption input(independent # [#..]) parameters in errxt() must be of length 1 or length of schedule list"
					exit 198
				}
				forvalues d=1/`inn2length' {
					local contents`d' : word `d' of `inn2'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "list of suboption input(independent # [#..]) parameters in errxt() must all be number values"
							exit 198
					}
				}
			}
			else {
				dis as error "error structure supplied with 'input' suboption in errxt() is not recognised. Must be one of independent, exchangeable, ar # [#..], ma # [#..], unstructured {it: matname}, toeplitz # [#..], or exponential # - for banded use unstructured"
				exit 198
			}
		}
		else  {
				dis as error "error structure in errxt() must use either auto or input() suboptions "
				exit 198
		}
	}
   if "`restype'"=="resinput" local resfull `resid'

	gettoken resid : resid

**# ERRHET PARSING

	if 	"`errhet'"!=""  {
		local errhet=strtrim("`errhet'")
		if strmatch("`errhet'", "auto") {
			local hrestype resauto
			errxtmixcheck, residt(`=e(rstructlab)') hetcheck(`=e(resopt)') hety(yes)
			local hresid `s(residt)'
			local hrsh `s(rshort)'
			local hrnumber=`s(rnum)'
			local ehet `s(het)'
			local `ehet'`hrsh'n=`hrnumber'

			if "`resid'"=="unstructured" & e(k_rs)/e(nrgroups)<`sched_length' {
				di as error "not enough error terms in mixed model in memory for schedule length"
				exit 198
			}
		}

		else if strmatch("`errhet'", "input(*)") {  // checking the input suboptions
			local hrestype resinput
			local hresid=subinstr(`"`errhet'"', "input(", "", 1)
			local hresid=strtrim(subinstr("`hresid'", ")", "", 1))

			local hresabbrev: word 1 of `hresid'
			capture extabcheck, `hresabbrev'
			local hresfull `s(exttype)'

			if "`s(exttype)'"=="" err198 You have not correctly specified the heteroschedastic residual error structure name
			local hresid: subinstr local hresid "`hresabbrev'" "`hresfull'"

		/*
		else if strmatch("`errhet'", "input(*)") {  // checking the input suboptions
			local hrestype resinput
			local hresid=subinstr(`"`errhet'"', "input(", "", 1)
			local hresid=strtrim(subinstr("`hresid'", ")", "", 1)) */

			if strmatch("`hresid'", "ar *") { // if AR residuals
				local harn2=subinstr("`hresid'", "ar ", "", 1)
				local harn2length : word count `harn2'
				if `harn2length'<2 | `harn2length'>3 { // 	if `harn2length'<2 | `harn2length'>`sched_length'
					dis as error  " list of input AR parameters for errhet() option with 'input' suboption must be at least two and at most 3 (for AR 2)"
					exit 198
				} // change to max of 2 AR terms i.e 3 values??
				forvalues d=1/`harn2length' {
					local hcontents`d' : word `d' of `harn2'
					capture confirm number `hcontents`d''
						if _rc!=0 {
							dis as error "list of AR parameters must all be number values"
							exit 198
					}
				}
					if  `harn2length'==2 & (`hcontents2'>=1 | `hcontents2' <=-1) {
						dis as error "AR autocorrelation parameter must be inside range {-1, 1}" // CHANGE!!!
							exit 198
					}

			}

			else if strmatch("`hresid'", "ma *") { // if MA residuals
				local hman2=subinstr("`hresid'", "ma ", "", 1)
				local hman2length : word count `hman2'
				if `hman2length'<2 | `hman2length'>3  { // currently max=2 if `hman2length'<2 | `hman2length'>`sched_length'
					dis as error  "list of input MA parameters must be at least two and and at most 3 (for MA 2)"
					exit 198
				}
				forvalues d=1/`hman2length' {
					local hcontents`d' : word `d' of `hman2'
					capture confirm number `hcontents`d''
						if _rc!=0 {
							dis as error "list of MA parameters must all be number values"
							exit 198
					}
				}
			}
						// no input version of Banded residuals - use unstructured

			else if strmatch("`hresid'", "toeplitz *") { // if Toeplitz residuals
				local hton2=subinstr("`hresid'", "toeplitz ", "", 1)
				local hton2length : word count `hton2'
				if `hton2length'==0 | `hton2length'>`sched_length'  {
					dis as error  "list of Toeplitz parameters must be at least one and equal or less than schedule length"
					exit 198
				}
				forvalues d=1/`hton2length' {
					local hcontents`d' : word `d' of `hton2'
					capture confirm number `hcontents`d''
						if _rc!=0 {
							dis as error "list of Toeplitz parameters must all be number values"
							exit 198
					}
				}
			}
			else if strmatch("`hresid'", "exponential *") { // if Exponential residuals i.e generalised AR 1
				local hexn2 =subinstr("`hresid'", "exponential ", "", 1)
				local hexn2length : word count `hexn2'
				if `hexn2length'!=2  {
					dis as error  " list of exponential parameters must be 2"
					exit 198
				}
				forvalues d=1/`hexn2length' {
					local hcontents`d' : word `d' of `hexn2'
					capture confirm number `hcontents`d''
						if _rc!=0 {
							dis as error "list of exponential parameters must all be number values"
							exit 198
					}
				}
				if `hcontents2' <=-1 | `hcontents2'>=1 {
					dis as error "exponential autocorrelation parameter must be inside range {-1, 1}"
					exit 198
				}
			}
			else if strmatch("`hresid'", "unstructured *") { // if unstructured

				local hrm =subinstr("`hresid'", "unstructured ", "", 1)
				local hrm2length : word count `hrm'
				if `hrm2length'>1  {
					dis as error "suboption input(unstructured {it: matname}) must be supplied with single name of matrix"
					exit 198
				}
				tempname hresid_mat
				capture mat `hresid_mat'=  `hrm' // first checking matrix supplied in correct format
					if  _rc!=0 {
								dis as error "matrix entry for input(unstructured {it: matname}) not correct format"
					exit 198
							}
				capture confirm matrix `hresid_mat'  // first checking matrix supplied in correct format
				if  _rc!=0 {
								dis as error "matrix entry for input(unstructured {it: matname}) not correct format"
					exit 198
							}
				local col=colsof(`hresid_mat')
				local sym= issymmetric(`hresid_mat')
				if `sym' ==0 {
					dis as error "matrix entry for input(unstructured {it: matname}) must be symmetric"
				}

				if `col'!=`sched_length' {
								dis as error "matrix entry for input(unstructured {it: matname}) must be symmetric nxn, where n=number of measures supplied in schedule()"
					exit 198
				}

			}
			else if strmatch("`hresid'", "exchangeable *") { // if exchangeable
				local hecn2 =subinstr("`hresid'", "exchangeable ", "", 1)
				local hecn2length : word count `hecn2'
				if `hecn2length'!=2   {
					dis as error  " list of suboption input(exchangeable # #) parameters in errxt() must be of length 2"
					exit 198
				}
				forvalues d=1/`hecn2length' {
					local hcontents`d' : word `d' of `hecn2'
					capture confirm number `hcontents`d''
						if _rc!=0 {
							dis as error "list of suboption input(exchangeable # #) parameters in errxt() must both be number values"
							exit 198
					}
				}
			}
			else if strmatch("`hresid'", "independent *") { // if independent
				local hinn2 =subinstr("`hresid'", "independent ", "", 1)
				local hinn2length : word count `hinn2'
				if `hinn2length'!=1 & `hinn2length'!=`sched_length'    {
					dis as error  " list of suboption input(independent # [#..]) parameters in errxt() must be of length 1 or length of schedule list"
					exit 198
				}
				forvalues d=1/`hinn2length' {
					local hcontents`d' : word `d' of `hinn2'
					capture confirm number `hcontents`d''
						if _rc!=0 {
							dis as error "list of suboption input(independent # [#..]) parameters in errxt() must all be number values"
							exit 198
					}
				}

			}
			else {
				dis as error "error structure supplied with 'input' suboption in errhet() is not recognised. Must be one of independent, exchangeable, ar # [#..], ma # [#..], unstructured {it: matname}, toeplitz # [#..], or exponential # - for banded use unstructured"
				exit 198
			}
		}
		else  {
				dis as error "error structure in errhet() must use (currently) only input() suboptions "
				exit 198
		}
	}

	gettoken hresid : hresid


**# CHECKING CORRECT INPUTS FOR TRTSPEC CHOICE

* IF: trtspec=="slope" Check either used: Effectiveness + CONTSlope OR Difference
	*if "`model'"!="multi" {
		if "`trtspec'"=="slope" {
				* check effectiveness and difference not both specified
					if "`effectiveness'"!="" & "`difference'"!="" {
					dis as error "You cannot specify both effectiveness() (together with contslope()) and difference()"
					exit 198
				}
				* check one of effectiveness and difference  specified
				if "`effectiveness'"=="" & "`difference'"=="" {
					dis as error "No target slope effect specification: please specify either effectiveness() and contslope() OR difference()"
					exit 198
				}

				* check contslope and difference not both specified
				if "`contslope'"!="" & "`difference'"!="" {
					dis as error "You cannot specify both contslope() (together with effectiveness()) and difference()"
					exit 198
				}
				* check contslope and effectiveness both specified
				if "`effectiveness'"!="" & "`contslope'"=="" {
					dis as error "You must specify both effectiveness() and contslope()"
					exit 198
				}
				* check contslope and both specified
				if "`effectiveness'"=="" & "`contslope'"!="" {
					dis as error "You must specify both effectiveness() and contslope()"
					exit 198
				}
				if 	"`effectiveness'"!="" & "`actualtrt'"!="" {
					dis as error "You cannot specify effectiveness() when also specifying actualtrt()"
					exit 198

				}
			}


		if "`trtspec'"=="intercept" | "`trtspec'"=="factor" | "`trtspec'"=="factor0" | "`trtspec'"=="slint" | "`trtspec'"=="lateslope" | "`trtspec'"=="2slope" | "`trtspec'"=="user" | "`trtspec'"=="user2" {
			if  "`difference'"=="" {
					dis as error "You must specify difference() when trtspec() is 'intercept', 'factor', 'factor0', 'slint', 'lateslope', '2slope' or 'user'"
					exit 198
			}
			if  "`contslope'"!="" {
					dis as error "You must specify difference() ONLY when trtspec() is 'intercept', 'factor', 'factor0', 'slint', 'lateslope', '2slope' or 'user'"
					exit 198
			}
			if  "`effectiveness'"!="" {
					dis as error "You must specify difference() ONLY when trtspec() is 'intercept', 'factor', 'factor0', 'slint', 'lateslope', '2slope' or 'user'"
					exit 198
			}

		}



		* Now check effectiveness is a number >0 and <= 1  if model!=multi, then check contslope

		if "`effectiveness'"!="" { // Effectiveness is specified
				capture confirm number `effectiveness'
				if _rc!=0 {
					dis as error "Effectiveness() must be a number greater than 0 and less than or equal to 1"
					exit 198
				}
				* So eff is specified and it's a number
				if `effectiveness' > 1 {
					dis as error "Effectiveness() must be less than or equal 1"
					exit 198
				}
				if `effectiveness' <=0 {
					dis as error "Effectiveness() must be strictly greater than 0"
					exit 198
				}  // if Model!=multi



		* Now check contslope is a number - or instead variable name for slope term in mixed model in memory
			if "`contslope'"!="" { // contslope is specified
					capture confirm number `contslope'
					if _rc==0 {
						local ns_num=1
							}
					if _rc!=0 {
						local ns_num=0
						 local b_name "`contslope'"
						 tempname beta
						capture scalar `beta'=_b[`b_name'] // using the slope from mixed - doesn't always work if the variable isn't in the dataset! though can just create a fake variable  with that name...

						if "`contslope'"!="" & _rc==111 {
							dis as error "the overall (no treatment) contslope() must be a number or the name of the slope in a mixed model in memory"
							exit 198
						}

					}
				local difflength=1  // for presenting treatment effect in output

			}

		} // If statement "eff is specified"


**# DIFF check
		**Checking Difference is correctly specified for various trtspec choices or for actualtrt instead is specified

		*  check if using difference that it is a number if trtspec is slope, intercept or lateslope

		local treatsp `trtspec'
		if "`actualtrt'"!="" local treatsp `actualtrt'

		if "`treatsp'"=="slope" | "`treatsp'"=="intercept" | "`treatsp'"=="lateslope" | "`treatsp'"=="user"   {
			if "`difference'"!="" { // difference is specified
				local difflength : word count `difference'
				if `difflength'!=1     {
					dis as error  "length of supplied values in difference() option when using 'slope', 'intercept', 'lateslope' or 1 'user' function must be one - check if actualtrt() specified"
					exit 198
				}
				forvalues d=1/`difflength' {
					local diff`d' : word `d' of `difference'
					capture confirm number `diff`d''
						if _rc!=0 {
							dis as error "list of supplied values in difference() option must all be numbers"
							exit 198
					}

				}
			}
			local altvarX=1
		}



			* check difference  is 2 numbers if trtspec is slint (slope and intercept), user2  or 2slope
		if "`treatsp'"=="slint" | "`treatsp'"=="2slope" | "`treatsp'"=="user2"  {
			if "`difference'"!="" { // difference is specified
				local difflength : word count `difference'
				if `difflength' != 2 {
					dis as error  " list of difference() effects for 'slint', '2slope' or 2 'user' functions must be length 2 - check if actualtrt() specified"
					exit 198
				}
				forvalues d=1/`difflength' {
					local diff`d' : word `d' of `difference'
					capture confirm number `diff`d''
						if _rc!=0 {
							dis as error "all difference() elements must be specified as a number value"
							exit 198
					}

				}

			}
			local altvarX=2  // for later in picking out elements of 'test'
		}

				* check difference  is a number if trtspec is factor
		if "`treatsp'"=="factor" {
			if "`difference'"!="" { // difference is specified
				local difflength : word count `difference'
				if `difflength' != `sched_length'-1 {
					dis as error  "piecewise list of difference() for factor effects must be of length one less than schedule() - check if actualtrt() specified"
					exit 198
				}
				forvalues d=1/`difflength' {
					local diff`d' : word `d' of `difference'
					capture confirm number `diff`d''
						if _rc!=0 {
							dis as error "all difference() elements must be specified as a number value"
							exit 198
					}

				}
			}
			local altvarX=`sched_length'-1  // for later in picking out elements of 'tes
		}

				* check difference  is a number if trtspec is factor0
		if "`treatsp'"=="factor0" {
			if "`difference'"!="" { // difference is specified
				local difflength : word count  `difference'
				if `difflength' != `sched_length' {
					dis as error  "piecewise list of difference() effects in factor0 must be same length as schedule() - check if actualtrt() specified"
					exit 198
				}
				forvalues d=1/`difflength' {
					local diff`d' : word `d' of `difference'
					capture confirm number `diff`d''
						if _rc!=0 {
							dis as error "all difference() elements must be specified as a number value"
							exit 198
					}

				}

			}
			local altvarX=`sched_length'  // for later in picking out elements of 'test'
		}


**# CBETA
		**cbeta - Control beta if actualcont() specified
		if "`cbeta'"!="" & "`actualcont'"=="" {
			di as error "cbeta() cannot be specified without actualcont()"
			exit 198
		}
		if "`actualcont'"!="" {
			if "`cbeta'"=="" {
				di as error "actualcont() cannot be specified without cbeta()"
				exit 198
			}
			local actcontlength : word count  `cbeta'
				if "`actualcont'"=="slint" {
					if `actcontlength'!=2 {
						di as error "cbeta() must be of length 2 if actualcont() is 'slint'"
						exit 198
					}
				}
				if "`actualcont'"=="noslope" {
					if `actcontlength'!=1 {
						di as error "cbeta() must be of length 1 if actualcont() is 'noslope'"
						exit 198
					}
				}
				if "`actualcont'"=="noint" {
					if `actcontlength'!=1 {
						di as error "cbeta() must be of length 1 if actualcont() is 'noint'"
						exit 198
					}
				}
				if "`actualcont'"=="factor" {
					if `actcontlength'!=`sched_length' {
						di as error "cbeta() must be equal to schedule() length if actualcont() is 'factor'"
						exit 198
					}
				}
				if "`actualcont'"=="2slope" {
					if `actcontlength'!=3 {
						di as error "cbeta() must be of length 3 if actualcont() is '2slope #'"
						exit 198
					}
				}
				if "`actualcont'"=="user" {
					if `actcontlength'!=2 {
						di as error "cbeta() must be of length 2 if actualcont() is 'user' with one function"
						exit 198
					}
				}
				if "`actualcont'"=="user2" {
					if `actcontlength'!=3 {
						di as error "cbeta() must be of length 3 if actualcont() is 'user' with two functions"
						exit 198
					}
				}
		}



**# ALPHA and ARATIO

* ALPHA: Should be between 0 and 1

	if `alpha'<=0 | `alpha'>1 {
					dis as error "Alpha() must be a number greater than 0 and less than 1"
					exit 198
				}

		* ALLORAtio - allocation ratio weightings MULTIMATRIX VERSION - inbuilt Stata syntax check is sufficient for parsing ALLORatio

		if "`alloratio'"!="" {
			local allratio `alloratio'
		}
		else {
			local allratio 1 1
		}
		local ar1: word 1 of `allratio' // for use in matrix creation
		local ar2: word 2 of `allratio'
		local arsum=`ar1'+`ar2' // for use later in power/SS calculations to reweight for 'number' in trial

		/*
	* ARAtio - allocation ratio weightings FORMULA VERSION - inbuilt Stata syntax check is sufficient for parsing ARAtio

		if "`alloratio'"!="" & "`aratio'"!="" {
			dis as error "You are using both the ALLORatio() option and the secret ARatio() option - don't!"
							exit 198
		}

		if "`aratio'"!="" {

			local ar1: word 1 of `aratio'
			local ar2: word 2 of `aratio'
			local arsum=`ar1'+`ar2' // for use later in power/SS calculations to reweight for 'number' in trial
			local k=(`ar1'/`ar2')
			local arfactor=(1+(`k'-1)^2/(4*`k')) // for use later in power/SS calculations to reweight for 'number' in trial
		}
		*/

			* ARAtio - allocation ratio Sigma adjust VERSION - inbuilt Stata syntax check is sufficient for parsing ARAtio

		if "`alloratio'"!="" & "`aratio'"!="" {
			dis as error "You are using both the ALLORatio() option and the secret ARatio() option - don't!"
							exit 198
		}

		if "`aratio'"!="" {

			local ar1: word 1 of `aratio'
			local ar2: word 2 of `aratio'
			local arsum=`ar1'+`ar2' // for use later in power/SS calculations to reweight for 'number' in trial

		}


**# POWER and SAMPLE SIZE

	* Must specify one of power or N: 4 possible cases...
* 1. 1. Both power an n specified - error

	if "`power'"!="" & "`n'"!="" {
							display as error "Only one of power() and n() may be specified, not both"
							exit 198
							}

* 2. Power is specified, n is missing - okay - we'll calculate SAMPLE SIZE (N)

	if "`power'"!="" & "`n'"=="" {
							local given_power=real("`power'")
							if missing(`given_power') { // ...but power isn't a number
								dis as error "Power() must be a number greater than 0 and less than 1"
								exit 198
							}
							local power_or_n power
						}

* 3. Power is absent, n is specified - okay - we'll calculate POWER

	if "`power'"=="" & "`n'"!="" { //
							local given_n=floor(real("`n'"))
							if missing(`given_n') { // ...but n isn't a number
								dis as error "n() must be a numerical value"
								exit 198
							}
	if `given_n' != `n' { // The floor of n must be the same as n... ie n cannot be fractional
								dis as error "n() must be a whole number greater than or equal to 2"
								exit 198
							}
	if `given_n' < 2 { // N must be at least 2
								dis as error "n() must be at least 2"
								exit 198
							}
							local n = ceil(`given_n')
							local power_or_n n
						}

* 4. Both power and n absent: okay, use default value for power - we'll calculate SAMPLE SIZE (N)
	if "`power'"=="" & "`n'"=="" {
							local given_power = 0.8 // Default power is 80%
							local power_or_n power
						}
				* Check values
	if "`power_or_n'"=="power" { // Power is specified - we already know it's a number.
						if `given_power'>=1 {
							dis as error "Power() must be a value strictly less than 1"
							exit 198
						}
						if `given_power'<=0 {
							dis as error "Power() must be a value greater than 0"
							exit 198
						}
					}
					if "`power_or_n'" == "n" { // N is specified - we already know it's a number
						* Make sure it's even, or round down
						local actual_n = `arsum'* floor(`given_n' / `arsum')
						if "`model'"=="3level" & "`crt'"=="" local actual_n = `given_n'
						if `given_n'<`arsum' & "`model'"!="3level" & "`crt'"!="" {
							dis as error "n must be a number greater or equal to `arsum' - the allocation ratio sum"
							exit 198
						}
					}
	/*
* NPCLUSTER
	if "`model'"=="3level" {
				if "`npcluster'"=="" {
			di as error "option npcluster() required if model(3level)"
			exit 198
		}
	}
	else {
		if "`cov3l'"!="" {
			di as error "option cov3l() only required for model(3level)"
			exit 198
		}
		if "`npcluster'"!="" {
			di as error "option npcluster() only required for model(3level)"
			exit 198
		}
		if "`wpcluster'"!="" {
			di as error "option wpcluster() only required for model(3level)"
			exit 198
		}
	}
	*/

**# SCALE and FRAMES
* SCALE

	if `scale' <= 0 {
						dis as error "Scale() must be a positive number"
						exit 198
					}

* FRAMES

	* to keep or not
		if "`frames'"=="" {
			local frames "drop"
		}
		else if "`frames'"=="keep" {
			local frames "keep"
		}
		else  {
				display as error "only acceptable entry for frames() is 'keep'"
					exit 198
		}

* DROPPING _MP FRAMES
		if "`frdrop'"!="" {
			qui capture frame drop _mp*
		}

**# DROPUTS
* DROPOUTS
	* Is there a dropout list specified?
		local drop_yes = 0
		if "`dropouts'"!="" local drop_yes = 1

	* Drop matrix must be same length as Schedule matrix
			* Length of dropout list
		if `drop_yes'==1 {
			local drop_length = 0
			foreach i of numlist `dropouts' {
				local drop_length = `drop_length ' + 1
			}
			* Is this equal to schedule matrix?
			if `sched_length' != `drop_length' {
				dis as error  "Dropouts() list must correspond in length (`drop_length') with visit schedule (`sched_length')"
				exit 198
			}
		}

	* Decant dropout numlist into locals and calculate people who attend all visits
		local dfrac_left = 1 // The proportion attending all visits - one unless dropouts specified

		if `drop_yes'==1 {
			local j = 1 // counter - position number
			foreach fr of numlist `dropouts' {
				local dfrac`j' = `fr'
				local j = `j' + 1
				local dfrac_left = `dfrac_left' - `fr'

					}
		* Check the drop matrix adds up = 1 (100%) (with tolerance allowed)
			if `dfrac_left' < -0.000001 | `dfrac_left' > 0.000001 {
				display as error  "Dropout probabilities must sum to 1: list sums to `=1-`dfrac_left''"
				exit 198
				}
			}


		tempname drops
		mat `drops'=J(1,`sched_length',0)
		if "`dropouts'"!="" {
			forvalues dr=1/`sched_length' {
				local drpo: word `dr' of `dropouts'
				mat `drops'[1,`dr']=`drpo'
			}
		}

		if "`dropouts'"=="" {
			mat `drops'[1,`sched_length']=1
		}
		 return mat dropouts=`drops'

		* DROP2 - Different Treatment dropout rate
	* Is there a 2nd dropout list specified?
		local drop2_yes = 0

		if "`drop2'"!="" local drop2_yes = 1

		if `drop2_yes'==1 & `drop_yes'==0 {
			di as error "Cannot specify drop2() if dropouts() not also selected"
			exit
		}

	* Drop2 matrix must be same length as Schedule matrix
			* Length of drop2 list
		if `drop2_yes'==1 {
			local drop2_length = 0
			foreach i of numlist `drop2' {
				local drop2_length = `drop2_length ' + 1
			}
			* Is this equal to schedule matrix?
			if `sched_length' != `drop2_length' {
				dis as error  "Drop2() list must correspond in length (`drop2_length') with visit schedule (`sched_length')"
				exit 198
			}
		}

	* Decant dropout numlist into locals and calculate people who attend all visits
		local dfrac2_left = 1 // The proportion attending all visits - one unless dropouts specified

		if `drop2_yes'==1 {
			local j = 1 // counter - position number
			foreach fr of numlist `drop2' {
				local d2frac`j' = `fr'
				local j = `j' + 1
				local dfrac2_left = `dfrac2_left' - `fr'

					}
		* Check the drop matrix adds up = 1 (100%) (with tolerance allowed)
			if `dfrac2_left' < -0.00001 | `dfrac_left' > 0.00001 {
				display as error  "Dropout probabilities must sum to 1: list sums to `=1-`dfrac2_left''"
				exit 198
				}
			}


		tempname drops drops2
		mat `drops'=J(1,`sched_length',0)
		if "`drop2'"!="" mat `drops2'=J(1,`sched_length',0)
		if "`dropouts'"!="" {
			forvalues dr=1/`sched_length' {
				local drpo: word `dr' of `dropouts'
				mat `drops'[1,`dr']=`drpo'
			}
		}
		if "`drop2'"!="" {
			forvalues dr2=1/`sched_length' {
				local drpo2: word `dr2' of `drop2'
				mat `drops2'[1,`dr2']=`drpo2'
			}
		}

		if "`dropouts'"=="" {
			mat `drops'[1,`sched_length']=1
		}
		if "`drop2'"!="" return mat dropouts2=`drops2'
		 return mat dropouts=`drops'

**# STREC
* STAGGERED RECRUITMENT

	* Is there a strec list specified?
		local strec_yes = 0
		if "`strecruitment'"!="" local strec_yes = 1

	* Strec numlist must same length as  Schedule numlist
		* Length of strec list
			if `strec_yes'==1 {
				local strec_length = 0
				foreach i of numlist `strecruitment' {
					local strec_length = `strec_length' + 1
				}
				* Is this equal to schedule numlist+1?
				if `sched_length' != `strec_length' {
					dis as error  "Staggered recruitment - strecruitment() - list must correspond in length (`strec_length') with visit schedule (`sched_length')"
					exit 198
				}
			}
	* Decant strec numlist into locals and calculate people who attend all visits
		local rfrac_left = 1 // The proportion attending all visits - one unless strec specified
			if `strec_yes'==1 {
				local j = 1 // counter - position number
				foreach rfr of numlist `strecruitment' {
					local rfrac`j' = `rfr'
					local j = `j' + 1
					local rfrac_left = `rfrac_left' - `rfr'
				}
		* Check the strec matrix adds up to less than 100%
			if `rfrac_left' < -0.00001 {
				display as error  "Staggered recruitment - strecruitment() - list of probabilities cannot exceed 1: list sums to `=1-`rfrac_left''"
				exit 198
			}

		}

		tempname strcs
		mat `strcs'=J(1,`sched_length',0)
       if "`strecruitment'"!="" {
			forvalues sr=1/`sched_length' {
				local strc: word `sr' of `strecruitment'
				mat `strcs'[1,`sr']=`strc'
			}
	   }
		if "`strecruitment'"=="" {
			mat `strcs'[1,`sched_length']=1
		}
		 return mat st_rec=`strcs'

** Now calculate weights integrating dropout and staggered recruitment
	if "`strecruitment'"!="" &  "`dropouts'"!="" {

		local count: word count `strecruitment'

		local finalwgts
		forval i = 1/`count' {
			local weight_`i'
			local w_inv = 1
			local w1: word `i' of `strecruitment'

			forval j = 1/`i' {
				local w2: word `j' of `dropouts'

				if `i' == `j' {
					local weight_`j' = `weight_`j'' + `w1'*`w_inv'
				}
				else {
					local weight_`j' = `weight_`j'' + `w1'*`w2'
				}

				local w_inv = `w_inv' - `w2'
			}
		}

		forvalues i=1/`count' {
			local  finalwgts "`finalwgts' `weight_`i''"
		}

	}

** Same, if drop2 used

	if "`strecruitment'"!="" &  "`drop2'"!="" {

		local count: word count `strecruitment'

		local finalwgts2
		forval i = 1/`count' {
			local weight_`i'
			local w_inv = 1
			local w1: word `i' of `strecruitment'

			forval j = 1/`i' {
				local w2: word `j' of `drop2'

				if `i' == `j' {
					local weight_`j' = `weight_`j'' + `w1'*`w_inv'
				}
				else {
					local weight_`j' = `weight_`j'' + `w1'*`w2'
				}

				local w_inv = `w_inv' - `w2'
			}
		}

		forvalues i=1/`count' {
			local  finalwgts2 "`finalwgts2' `weight_`i''"
		}

	}

**# SUMMARISING DROPOUTS and STREC
** Choose which weights to use  - dropout only, strec only... or the integration of both version (above)

			local cohorts=0 // won't need separate cohorts i.e frames
	if "`strecruitment'"!="" &  "`dropouts'"!="" {
			local	pwgts "`finalwgts'"
			local cohorts=1 // will need etc.
		}
	if "`strecruitment'"=="" &  "`dropouts'"!="" {
			local	pwgts "`dropouts'"
			local cohorts=1
		}
	if "`strecruitment'"!="" &  "`dropouts'"=="" {
			local	pwgts "`strecruitment'"
			local cohorts=1
		}
	if "`strecruitment'"!="" &  "`drop2'"!="" {
			local	pwgts2 "`finalwgts2'"
		}
	if "`strecruitment'"=="" &  "`drop2'"!="" {
			local	pwgts2 "`drop2'"
		}


**# FIRST RETURNS

		tempname prwt prwt2
		local fwlist2
		local fw2list2
		local sumpwgts=0
		local sumpwgts2=0

		mat `prwt'=J(1,`sched_length',0)
		if `drop2_yes'==1 mat `prwt2'=J(1,`sched_length',0)
		if "`strecruitment'"=="" &  "`dropouts'"=="" {
			mat `prwt'[1,`sched_length']=1
			forvalues i=1/`sched_length' {
				local fw`i'=0
				if `i'==`sched_length' local fw`i'=1
				local fwlist2="`fwlist2' `fw`i''"
			}
			local pwgts "`fwlist2'"
			local sumpwgts=1
			local sumpwgts2=1
		}
		else {
			forvalues i=1/`sched_length' {
				local fw`i': word `i' of `pwgts'
				local sumpwgts=`sumpwgts'+`fw`i''
				local sumpwgts_`i'=`sumpwgts'
				if `drop2_yes'==1 {
					local fwT`i': word `i' of `pwgts2'
					local sumpwgts2=`sumpwgts2'+`fwT`i''
					local sumpwgts2_`i'=`sumpwgts2'
				}
			}
			forvalues pw=1/`sched_length' {
				local pwt: word `pw' of `pwgts'
				mat `prwt'[1,`pw']=`pwt'
				local fw`pw': word `pw' of `pwgts'
				local fw2`pw'=`fw`pw''*1/`sumpwgts'
				local fwlist2="`fwlist2' `fw2`pw''"
				if `drop2_yes'==1 {
					local pwt2: word `pw' of `pwgts2'
					mat `prwt2'[1,`pw']=`pwt2'
					local fwT`pw': word `pw' of `pwgts2'
					local fwT2`pw'=`fwT`pw''*1/`sumpwgts2'
					local fw2list2="`fw2list2' `fwT2`pw''"
				}

			}
		}

		if `drop2_yes'==0 local pwgts2 `pwgts' // will use for actual sigma rewighting, even though same as pwgts

		** `combined' weights - just to use to select non-zero cohorts

		local cwgts
		forvalues cw=1/`sched_length' {
			if  `drop2_yes'==1 local cwgt=(`fw`cw''+`fwT`cw'')/2
			else local cwgt=(`fw`cw'')
			local cwgts "`cwgts' `cwgt'"
		}



		** RETURN SOME STUFF incl. STREC and DROPOUTS, DROP" etc
		if "`twosided'"!="" local tsided ts_yes
		else local tsided ts_no
		if "`jttest'"!="" local tsided ts_yes
		tempname crita scl dim
		scalar `crita'=`alpha'
		scalar `scl'=`scale'
		return scalar alpha=`crita'
		return scalar scale=`scl'
		return local aratio `allratio'
		return local twosided `tsided'

		if "`actualtrt'"=="user2" return local acttrt_userfunc2 `atfunc_2'
		if "`actualtrt'"=="user" | "`actualtrt'"=="user2" return local acttrt_userfunc `atfunc_1'
		if "`actualcont'"=="user2" return local actcont_userfunc2 `acfunc_2'
		if "`actualcont'"=="user" | "`actualcont'"=="user2" return local actcont_userfunc `acfunc_1'
		return local trt_true `actualtrt'
		return local cont_true `actualcont'
		if "`trtspec'"=="user2" return local trt_userfunc2 `tfunc_2'
		if "`trtspec'"=="user" | "`trtspec'"=="user2" return local trt_userfunc `tfunc_1'
		if "`altcont'"=="user2" return local cont_userfunc2 `cfunc_2'
		if "`altcont'"=="user" | "`altcont'"=="user2" return local cont_userfunc `cfunc_1'

		return local trt_spec `trtspec'
		if "`altcont'"!="" return local cont_spec `altcont'
		else return local cont_spec slint
		if `drop2_yes'==1 return mat cohort_wgts2=`prwt2'
		return mat cohort_wgts=`prwt'

		if `drop2_yes'==1 return local fw_rescale2 `"`fw2list2'"'
		return local fw_rescale `"`fwlist2'"'
		if `drop2_yes'==1 return local final_wgts2 `"`pwgts2'"'
		return local final_wgts `"`pwgts'"'


**# XMAT, RMAT etc parsing

* RETURNED MATRICES
		*XMAT

	if "`xmat'"!="" & `cohorts'==0 {
		if `xmat'!=`sched_length' {
				dis as error "with no dropout() or strec(), xmat() must contain a number equal to the schedule() length"
					exit 198
			}
	}
	if "`xmat'"!="" & `cohorts'==1 {
			if `xmat'>`sched_length' {
				dis as error "xmat() must contain a number not larger than the schedule() length"
					exit 198
			}
			forvalues xm=1/`sched_length' {
				local pw`xm': word `xm' of `pwgts'
				if `pw`xm''==0 & `xm'==`xmat' {
					dis as error "xmat() must contain a number that represents a present cohort i.e. a non-zero probability in strec() or dropout() list"
					exit 198
							}
			}
	}
			*RMAT
	if "`rmat'"!="" & `cohorts'==0 {
		if `rmat'!=`sched_length' {
				dis as error "with no dropout() or strec(), rmat() must contain a number equal to the schedule() length"
					exit 198
			}
	}
	if "`rmat'"!="" & `cohorts'==1 {
			if `rmat'>`sched_length' {
				dis as error "rmat() must contain a number not larger than the schedule() length"
					exit 198
			}
			forvalues rm=1/`sched_length' {
				local pw`rm': word `rm' of `pwgts'
				if `pw`rm''==0 & `rm'==`rmat'  {
					dis as error "rmat() must contain a number that represents a present cohort i.e. a non-zero probability in strec() or dropout() list"
					exit 198
							}
			}
	}

			*ZMAT
	if "`zmat'"!="" & "`marginal'"!=""	{
		dis as error "cannot request zmat() if model is marginal"
					exit 198
	}
	if "`zmat'"!="" & `cohorts'==0 {
		if `zmat'!=`sched_length' {
				dis as error "with no dropout() or strec(), zmat() must contain a number equal to the schedule() length"
					exit 198
			}
	}
	if "`zmat'"!="" & `cohorts'==1 {
			if `zmat'>`sched_length' {
				dis as error "zmat() must contain a number not larger than the schedule() length"
					exit 198
			}
			forvalues zm=1/`sched_length' {
				local pw`zm': word `zm' of `pwgts'
				if `pw`zm''==0  & `zm'==`zmat' {
					dis as error "zmat() must contain a number that represents a present cohort i.e. a non-zero probability in strec() or dropout() list"
					exit 198
							}
			}
	}

			*GMAT
	if "`gmat'"!="" & "`marginal'"!=""	{
		dis as error "cannot request gmat() if model is marginal"
					exit 198
	}
	if "`gmat'"!="" & `cohorts'==0 {
		if `gmat'!=`sched_length' {
				dis as error "with no dropout() or strec(), gmat() must contain a number equal to the schedule() length"
					exit 198
			}
	}
	if "`gmat'"!="" & `cohorts'==1 {
			if `gmat'>`sched_length' {
				dis as error "gmat() must contain a number not larger than the schedule() length"
					exit 198
			}
			forvalues gm=1/`sched_length' {
				local pw`gm': word `gm' of `pwgts'
				if `pw`gm''==0 & `gm'==`gmat'  {
					dis as error "gmat() must contain a number that represents a present cohort i.e. a non-zero probability in strec() or dropout() list"
					exit 198
							}
			}
	}

				*BVARN

	if "`bvarn'"!="" & `cohorts'==0   {
		if `bvarn'<`sched_length' {
				dis as error "with no dropout() or strec(), bvarn() must be the number equal to the schedule() length"
					exit 198
		}
	}
	if "`bvarn'"!="" & `cohorts'==1 {
			if `bvarn'>`sched_length' {
				dis as error "bvarn() must contain a number not larger than the schedule() length"
					exit 198
			}
			forvalues bv=1/`sched_length' {
				local pw`bv': word `bv' of `pwgts'
				if `pw`bv''==0 & `bv'==`bvarn'  {
					dis as error "bvarn() must contain a number that represents a present cohort i.e. a non-zero probability in strec() or dropout() list"
					exit 198
							}
			}
	}



********************************************************************************
**# 2-LEVEL MODEL CALCULATIONS
********************************************************************************

*if "`model'" =="2level" {
		//qui tempname  covmat

** Check Covariance values

**# BASIC COVARIANCE INPUTS

* Check user-inputted COVariance is a 2x2 symmetric matrix assuming user/matrix input
	if "`covariance'"!=""  {
		tempname cov_mat
		mat `cov_mat'=`covariance'
		local col=colsof(`cov_mat')
		local sym= issymmetric(`cov_mat')

		if `sym' ==0 | `col'!=2 {
						dis as error "covariance() matrix must be symmetric 2x2"
			exit 198
					}
		}

*Check user-inputted random effect variances >=0

	if "`covariance'"!="" { // version for if numbers entered directly as matrix
			local intvar= el(`cov_mat', 1, 1)
								if `intvar' < 0 {
				dis as error "random intercept variance must be a positive number, unless intentially zero (random slope model only or standard linear regression if slope variance also =0)"
				exit 198
			}

			local slvar= el(`cov_mat', 2, 2)
								if `slvar' <0 {
				dis as error "random slope variance must be a positive number, unless intentially zero (random intercept model only or standard linear regression if intercept variance also =0)"
				exit 198
			}

	}


*Check user-inputted COVariance has implied correlation <=1 and >=-1
	 if "`covariance'"!=""  {
	 	tempname corr_mat
		local cov12=el(`cov_mat', 1,2)
		if `cov12'!=0 {
			mat `corr_mat'=corr(`cov_mat')
			local corr_slopeint= el(`corr_mat', 1, 2)
			if `corr_slopeint' >1 {
				dis as error "correlation of random effects is greater than 1 - check values"
				exit 198
			}
			if `corr_slopeint' <-1 {
				dis as error "correlation of random effects is less than -1 - check values"
				exit 198
			}
		}
		else local corr_slopeint=0
	 }



* 'auto' auto-version
	if "`auto'"!="" {
		local rewc: word count `=e(redim)'
		local vtwc: word count `=e(vartypes)'

		forvalues re=1/`rewc' {
			local re`re' : word `re' of `=e(redim)'
			local vt`re' : word `re' of `e(vartypes)'
		}

		if `re1'==2 { // version for if using mixed model in memory

				capture local slvar=(exp(_b[lns1_1_1:_cons]))^2
					if _rc!=0 {
						local slvar=0
					}
				capture local intvar=(exp(_b[lns1_1_2:_cons]))^2
					if _rc!=0 {
						local intvar=0
					}
				capture local corr_slopeint=tanh(_b[atr1_1_1_2:_cons]) // correlation of random effects
					if _rc!=0 {
						local corr_slopeint=0
					}
				capture local cov12=`corr_slopeint'*sqrt(`intvar')*sqrt(`slvar')
				if _rc!=0 {
						local cov12=0
					}
		}
				if "`vt1'"=="Identity" & `re1'==1 & `rewc'==1 {
					if e(revars)=="_cons" {
						local slvar=0
						local intvar=(exp(_b[lns1_1_1:_cons]))^2
					}
					if e(revars)!="_cons" {
						local intvar=0
						local slvar=(exp(_b[lns1_1_1:_cons]))^2
					}
					local  cov12=0
				}
				if "`vt1'"=="Identity" & `re1'==1 & `rewc'==2 {
					if strmatch("`=e(revars)'", "*0.*#*") {
						local intvar=0
						local slvar=(exp(_b[lns1_1_1:_cons]))^2
					}
					else {
						local intvar=(exp(_b[lns1_1_1:_cons]))^2
						local slvar=0
					}
					local  cov12=0
				}

	}

**# HET COVARIANCE INPUT

	** Check Covhet values - covariance matrix for treatment grp if covhet() specified

* Check user-inputted covhet is a 2x2 symmetric matrix assuming user/matrix input
	if "`chtype'"=="chinput"  {

		local col=colsof(`chm')
		local sym= issymmetric(`chm')

		if `sym' ==0 | `col'!=2 {
						dis as error "covhet() matrix must be symmetric 2x2"
			exit 198
					}
		}

*Check user-inputted random effect variances >0

	if "`chtype'"=="chinput" { // version for if numbers entered directly as matrix

			local hintvar= el(`chm', 1, 1)
								if `hintvar' < 0 {
				dis as error "random intercept variance for covhet() must be a positive number, unless intentially zero (random slope model only or standard linear regression if slope variance also =0)"
				exit 198
			}

			local hslvar= el(`chm', 2, 2)
								if `hslvar' <0 {
				dis as error "random slope variance for covhet() must be a positive number, unless intentially zero (random intercept model only or standard linear regression if intercept variance also =0)"
				exit 198
			}

	}


*Check user-inputted covhet has implied correlation <=1 and >=-1
	 if "`chtype'"=="chinput"  {
	  tempname hcorr_mat
		local hcov12=el(`chm', 1,2)
		if `hcov12'!=0 {
			mat `hcorr_mat'=corr(`chm')
			local hcorr_slopeint= el(`hcorr_mat', 1, 2)
			if `hcorr_slopeint' >1 {
				dis as error "correlation of treatment group-specific random effects is greater than 1 - check values"
				exit 198
			}
			if `hcorr_slopeint' <-1 {
				dis as error "correlation of treatment group-specific random effects is less than -1 - check values"
				exit 198
			}
		}
		else local hcorr_slopeint=0
	 }




		if  "`chtype'"=="chauto"  { // version for if using mixed model in memory
				local rewc: word count `=e(redim)'
				local vtwc: word count `=e(vartypes)'

				forvalues re=1/`rewc' {
					local re`re' : word `re' of `=e(redim)'
					local vt`re' : word `re' of `e(vartypes)'
				}
			if `rewc'!=2 {
				di as error "heteroschedastic covariance model fitted incorrectly, see {help mixedpower}"
				exit 198
			}
			if `re2'==2  {
			capture local hslvar=(exp(_b[lns1_2_1:_cons]))^2
				if _rc!=0 {
					local hslvar=0
				}
			capture local hintvar=(exp(_b[lns1_2_2:_cons]))^2
				if _rc!=0 {
					local hintvar=0
				}
			capture local hcorr_slopeint=tanh(_b[atr1_2_1_2:_cons]) // correlation of random effects
				if _rc!=0 {
					local hcorr_slopeint=0
				}
			capture local hcov12=`hcorr_slopeint'*sqrt(`hintvar')*sqrt(`hslvar')
				if _rc!=0 {
					local hcov12=0
				}
			}
			if "`vt2'"=="Identity" & `re2'==1 {
					if strmatch("`=e(revars)'", "* 1.*#*") {
						local hintvar=0
						local hslvar=(exp(_b[lns1_2_1:_cons]))^2
					}
					else {
						local hintvar=(exp(_b[lns1_2_1:_cons]))^2
						local hslvar=0
					}
					local  hcov12=0
				}

	}


	if "`marginal'"==""	{
	** Rescale the (CONTROL or ALL) variance terms that need rescaling (random intercept variance doesn't) - scale==1 if unspecified i.e no rescaling

			if `slvar'!=0 local var_slope=(`scale'*(sqrt(`slvar')))^2 // var. random slopes - rescaled if necessary
			else local var_slope=`slvar'
			local  var_int=`intvar' // Variance of random intercepts - no rescaling required
			if `var_int'!=0 & `var_slope'!=0 local cov_slopeint=`corr_slopeint'*sqrt(`var_int')*sqrt(`var_slope')  //
			else local cov_slopeint=0

			** and put together...

			local covmat `var_int' `cov_slopeint' `cov_slopeint' `var_slope' // rescaled (if required) covariance matrix in numlist form

		** Rescale the (TREATMENT) variance terms that need rescaling (random intercept variance doesn't) - scale==1 if unspecified i.e no rescaling
		if "`covhet'"!="" {
			if `hslvar'!=0 local hvar_slope=(`scale'*(sqrt(`hslvar')))^2 // var. random slopes - rescaled if necessary
			else local hvar_slope=`hslvar'
			local  hvar_int=`hintvar' // Variance of random intercepts - no rescaling required
			if `hvar_int'!=0 & `hvar_slope'!=0 local hcov_slopeint=`hcorr_slopeint'*sqrt(`hvar_int')*sqrt(`hvar_slope')  //
			else local hcov_slopeint=0
			** and put together...

			local hcovmat `hvar_int' `hcov_slopeint' `hcov_slopeint' `hvar_slope' // rescaled (if required) covariance matrix in numlist form
		}
		if "`covhet'"=="" {
			local hcovmat `covmat'
		}
	}

**# SIMPLE ERROR MATRIX INPUT

	***** Error matrix *****

	tempname rescov
	mat `rescov'=J(`sched_length',`sched_length',0)


** Error variances check - independent errors, no marginal modelling

* user-inputted version
	if "`errorvar'"!="" { // version for if numbers entered directly
		capture confirm number `errorvar'
				if _rc!=0 {
					dis as error "error variance must be a number greater than 0"
					exit 198
				}
		if `errorvar' <-1 {
			dis as error "error variance must be a number greater than 0"
			exit 198
		}
		local var_res=`errorvar'
		if "`errxt'"=="" local resid independent
	}

	* 'auto' auto-version
	if "`auto'"!="" & "`errxt'"=="" { // version for if using mixed model in memory
		local var_res=(exp(_b[lnsig_e:_cons]))^2
		local resid independent
	}

	* fill 'rescov' with IID errors
	if ("`auto'"!="" & "`errxt'"=="") | "`errorvar'"!="" {
		forvalues i=1/`sched_length' {
		mat `rescov'[`i',`i'] =`var_res'
		}
	}

**# XT ERROR MATRIX INPUT

** XT errors inputting - replace  `rescov' error matrix with xt errors from errxt() option - lots of code to follow...
	if "`errxt'"!="" {
		mat `rescov'=J(`sched_length',`sched_length',0) // override any IID error matrix from errorvar()

			if "`resid'"=="ar" {  // autoregressive
				if "`restype'"=="resinput" {
					local arn=`arn2length'-1
					forvalues d=1/`arn2length' {
						local param`d' : word `d' of `arn2'
					}

				}
				if `arn'==1 { //AR(1)
					if "`restype'"=="resauto" local rho1=tanh(_b[r_atr1:_cons])
					if "`restype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons])^2
					if "`restype'"=="resinput" local rho1=`param2'
					if "`restype'"=="resinput" local sige=`param1'
					forvalues i=1/`sched_length' {
						forvalues j=1/`sched_length' {
							local rc`i'`j'=`sige'*`rho1'^`=abs(`i'-`j')'
							mat `rescov'[`i',`j'] =`rc`i'`j''
						}
					}
				}
				if `arn'==2  { // AR(2)
					if "`restype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons])^2
					if "`restype'"== "resauto" local phi1=_b[r_phi1_1:_cons]
					if "`restype'"== "resauto" local phi2=_b[r_phi1_2:_cons]
					if "`restype'"=="resinput" local phi1=`param2'
					if "`restype'"=="resinput" local phi2=`param3'
					if "`restype'"=="resinput" local sige=`param1'
					*local psi=(1+`phi2')((1-`phi2')^2-`phi1'^2)
					forvalues i=1/`sched_length' {
						local d=`i'-1
						if `d'==0 local rc`d'=`sige'
						if `d'==1 local rc`d'=`phi1'/(1-`phi2')*`sige'
						if `d'>=2 local rc`d'=`phi1'*`rc`=`d'-1''+`phi2'*`rc`=`d'-2''
					}
					forvalues i=1/`sched_length' {
						forvalues j=1/`sched_length' {
							local diff=abs(`i'-`j')
							forvalues dd=0/`=`sched_length'-1' {
								if `diff'==`dd' {
									local rc`i'`j'=`rc`dd''
								}
							}
							mat `rescov'[`i',`j'] =`rc`i'`j''
						}
					}
				}
		}




			if "`resid'"=="ma" { // moving average
				if "`restype'"=="resinput" {
					local man=`man2length'-1
					forvalues d=1/`man2length' {
						local param`d' : word `d' of `man2'
					}
				}
				if `man'==1 { // MA(1)
					if "`restype'"=="resauto" local theta1=tanh(_b[r_att1:_cons])
					if "`restype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons])^2
					if "`restype'"=="resinput" local theta1=`param2'
					if "`restype'"=="resinput" local sige=`param1'
					forvalues i=1/`sched_length' {
						forvalues j=1/`sched_length' {
							if `i'==`j' {
								local rc`i'`j'=`sige'
								mat `rescov'[`i',`j'] =`rc`i'`j''
							}
							if abs(`i'-`j')==1  {
								local rc`i'`j'=`sige'*`theta1'/(1+`theta1'^2)
								mat `rescov'[`i',`j'] =`rc`i'`j''
							}
						}
					}
				}
				if `man'==2  { // MA(2)
					if "`restype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons])^2
					if "`restype'"=="resauto" local theta1=_b[r_theta1_1:_cons]
					if "`restype'"=="resauto" local theta2=_b[r_theta1_2:_cons]
					if "`restype'"=="resinput" local theta1=`param2'
					if "`restype'"=="resinput" local theta2=`param3'
					if "`restype'"=="resinput" local sige=`param1'
					local sigv=(`sige')/(1+`theta1'^2+`theta2'^2)
					forvalues i=1/`sched_length' {
						forvalues j=1/`sched_length' {
							if `i'==`j' {
								local rc`i'`j'=`sige'
								mat `rescov'[`i',`j'] =`rc`i'`j''
							}
							if abs(`i'-`j')==1  {
								local rc`i'`j'=(`theta1'+`theta1'*`theta2')*`sigv'
								mat `rescov'[`i',`j'] =`rc`i'`j''
							}
							if abs(`i'-`j')==2  {
								local rc`i'`j'=(`theta2')*`sigv'
								mat `rescov'[`i',`j'] =`rc`i'`j''
							}
						}
					}
				}
			}




			if "`resid'"=="banded" { //banded - no input version, use unstructured
				forvalues i=1/`sched_length' {
					if `i'==1 {
						if "`restype'"=="resauto" local sige1=exp(_b[lnsig_e:_cons])^2
					}
					else {
						if "`restype'"=="resauto" local sige`i'= exp(_b[lnsig_e:_cons]+_b[r_lns1_`i'ose:_cons])^2
					}
					local rc`i'`i'=`sige`i''
					mat `rescov'[`i',`i'] =`rc`i'`i''
				}
				forvalues i=1/`sched_length' {
						forvalues j=`=`i'+1'/`sched_length' {
							if abs(`i'-`j')<=`ban' & `i'!=`j' {
								if "`restype'"=="resauto" local rc`i'`j'=tanh(_b[r_atr1_`i'_`j':_cons])*`sige`i''^0.5*`sige`j''^0.5
								mat `rescov'[`i',`j'] =`rc`i'`j''
								mat `rescov'[`j',`i'] =`rc`i'`j''
							}
						}
				}
			}




			if "`resid'"=="toeplitz" {  // toeplitz
				if "`restype'"=="resinput" {
					local ton=`ton2length'-1
					forvalues d=1/`ton2length' {
						local param`d' : word `d' of `ton2'
					}
				}
				if "`restype'"=="resauto" local sige1=exp(_b[lnsig_e:_cons])^2
				if "`restype'"=="resinput" local sige1=`param1'
				forvalues i=1/`sched_length' {
					local rc`i'`i'=`sige1'
					mat `rescov'[`i',`i'] =`rc`i'`i''
				}
				forvalues i=1/`sched_length' {
						forvalues j=`=`i'+1'/`sched_length' {
							local diff= abs(`i'-`j')
							if `diff'<=`ton' {
								if "`restype'"=="resauto" local rc`i'`j'=tanh(_b[r_atr1_`diff':_cons])*`sige1'^0.5*`sige1'^0.5
								if "`restype'"=="resinput" local rc`i'`j'=`param`=`diff'+1''*`sige1'^0.5*`sige1'^0.5
								mat `rescov'[`i',`j'] =`rc`i'`j''
								mat `rescov'[`j',`i'] =`rc`i'`j''
							}
						}
				}
			}




			if "`resid'"=="unstructured" { // unstructured
				if "`restype'"=="resinput"  {
					mat `rescov'=`resid_mat'
							}
				if "`restype'"=="resauto"  {
					forvalues i=1/`sched_length' {
						if `i'==1 {
							 local sige1=exp(_b[lnsig_e:_cons])^2
						}
						else {
							 local sige`i'= exp(_b[lnsig_e:_cons]+_b[r_lns1_`i'ose:_cons])^2
						}
						local rc`i'`i'=`sige`i''
						mat `rescov'[`i',`i'] =`rc`i'`i''
					}
					forvalues i=1/`sched_length' {
							forvalues j=`=`i'+1'/`sched_length' {
								local rc`i'`j'=tanh(_b[r_atr1_`i'_`j':_cons])*`sige`i''^0.5*`sige`j''^0.5
								mat `rescov'[`i',`j'] =`rc`i'`j''
								mat `rescov'[`j',`i'] =`rc`i'`j''

							}
					}
				}
			}




			if "`resid'"=="exponential" { // exponential
				if "`restype'"=="resinput" {
					forvalues d=1/`exn2length' {
						local param`d' : word `d' of `exn2'
					}
				}
				if "`restype'"=="resauto" local rho1=invlogit(_b[r_logitr1:_cons])
				if "`restype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons])^2
				if "`restype'"=="resinput" local rho1=`param2'
				if "`restype'"=="resinput" local sige=`param1'
				forvalues i=1/`sched_length' {
					local it: word `i' of `schedule'
					forvalues j=1/`sched_length' {
						local jt: word `j' of `schedule'
						local rc`i'`j'=`sige'*`rho1'^`=abs(`it'-`jt')'
						mat `rescov'[`i',`j'] =`rc`i'`j''
					}
				}
			}


			if "`resid'"=="exchangeable" { // exchangeable
				if "`restype'"=="resinput" {
					forvalues d=1/`ecn2length' {
						local param`d' : word `d' of `ecn2'
					}
				}
				if "`restype'"=="resauto" local sige1=exp(_b[lnsig_e:_cons])^2
				if "`restype'"=="resinput" local sige1=`param1'
				forvalues i=1/`sched_length' {
					local rc`i'`i'=`sige1'
					mat `rescov'[`i',`i'] =`rc`i'`i''
				}
				forvalues i=1/`sched_length' {
						forvalues j=`=`i'+1'/`sched_length' {
								if "`restype'"=="resauto" local rc`i'`j'=tanh(_b[r_atr1:_cons])*`sige1'^0.5*`sige1'^0.5
								if "`restype'"=="resinput" local rc`i'`j'=`param2'*`sige1'^0.5*`sige1'^0.5
								mat `rescov'[`i',`j'] =`rc`i'`j''
								mat `rescov'[`j',`i'] =`rc`i'`j''
						}
				}
			}



			if "`resid'"=="independent" {  // independent - IID as well as heterogeneous ID for input version
				if "`restype'"=="resinput" {
					forvalues d=1/`sched_length' {
						if `inn2length'==1 local param`d' : word 1 of `inn2'
						if `inn2length'>1 local param`d' : word `d' of `inn2'
						mat `rescov'[`d',`d'] =`param`d''
					}
				}
				if "`restype'"=="resauto"  {
					forvalues i=1/`sched_length' {
						if `inn'==1 {
							 local rc`i'`i'=exp(_b[lnsig_e:_cons])^2
						}
						if `inn'==`sched_length' {
							 if `i'==1 local rc`i'`i'=exp(_b[lnsig_e:_cons])^2

							else {
								local rc`i'`i'= exp(_b[lnsig_e:_cons]+_b[r_lns`i'ose:_cons])^2
							}
						}
						mat `rescov'[`i',`i'] =`rc`i'`i''
					}
					local inn2length=`inn'  // for use in syntax code output
				}
			}
	}
	*mat errxtcov=`rescov'
	*mat li errxtcov


**# HET ERROR MATRIX INPUT


	tempname reshcov
	mat `reshcov'=`rescov'

	if "`errhet'"!="" {

		mat `reshcov'=J(`sched_length',`sched_length',0)

		if "`hresid'"=="ar" {  // autoregressive
			if "`hrestype'"=="resinput" {
				local harn=`harn2length'-1
				forvalues d=1/`harn2length' {
					local param`d' : word `d' of `harn2'
				}
			}
			if `harn'==1 { //AR(1)
				if "`hrestype'"=="resauto" local rho1=tanh(_b[r_atr2:_cons])
				if "`hrestype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons]+ _b[r_lns2ose:_cons])^2
				if "`hrestype'"=="resinput" local rho1=`param2'
				if "`hrestype'"=="resinput" local sige=`param1'
				forvalues i=1/`sched_length' {
					forvalues j=1/`sched_length' {
						local rc`i'`j'=`sige'*`rho1'^`=abs(`i'-`j')'
						mat `reshcov'[`i',`j'] =`rc`i'`j''
					}
				}
			}

			if `harn'==2  { // AR(2)
					if "`hrestype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
					if "`hrestype'"== "resauto" local phi1=_b[r_phi2_1:_cons]
					if "`hrestype'"== "resauto" local phi2=_b[r_phi2_2:_cons]
					if "`hrestype'"=="resinput" local phi1=`param2'
					if "`hrestype'"=="resinput" local phi2=`param3'
					if "`hrestype'"=="resinput" local sige=`param1'
				*local psi=(1+`phi2')((1-`phi2')^2-`phi1'^2)
				forvalues i=1/`sched_length' {
					local d=`i'-1
					if `d'==0 local rc`d'=`sige'
					if `d'==1 local rc`d'=`phi1'/(1-`phi2')*`sige'
					if `d'>=2 local rc`d'=`phi1'*`rc`=`d'-1''+`phi2'*`rc`=`d'-2''
				}
				forvalues i=1/`sched_length' {
					forvalues j=1/`sched_length' {
						local diff=abs(`i'-`j')
						forvalues dd=0/`=`sched_length'-1' {
							if `diff'==`dd' {
								local rc`i'`j'=`rc`dd''
							}
						}
						mat `reshcov'[`i',`j'] =`rc`i'`j''
					}
				}
			}
	}




		if "`hresid'"=="ma" { // moving average
			if "`hrestype'"=="resinput" {
				local hman=`hman2length'-1
				forvalues d=1/`hman2length' {
					local param`d' : word `d' of `hman2'
				}
			}
			if `hman'==1 { // MA(1)
				if "`hrestype'"=="resauto" local theta1=tanh(_b[r_att2:_cons])
				if "`hrestype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
				if "`hrestype'"=="resinput" local theta1=`param2'
				if "`hrestype'"=="resinput" local sige=`param1'
				forvalues i=1/`sched_length' {
					forvalues j=1/`sched_length' {
						if `i'==`j' {
							local rc`i'`j'=`sige'
							mat `reshcov'[`i',`j'] =`rc`i'`j''
						}
						if abs(`i'-`j')==1  {
							local rc`i'`j'=`sige'*`theta1'/(1+`theta1'^2)
							mat `reshcov'[`i',`j'] =`rc`i'`j''
						}
					}
				}
			}
			if `hman'==2  { // MA(2)
					if "`hrestype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
					if "`hrestype'"=="resauto" local theta1=_b[r_theta2_1:_cons]
					if "`hrestype'"=="resauto" local theta2=_b[r_theta2_2:_cons]
					if "`hrestype'"=="resinput" local theta1=`param2'
					if "`hrestype'"=="resinput" local theta2=`param3'
					if "`hrestype'"=="resinput" local sige=`param1'
				local sigv=(`sige')/(1+`theta1'^2+`theta2'^2)
				forvalues i=1/`sched_length' {
					forvalues j=1/`sched_length' {
						if `i'==`j' {
							local rc`i'`j'=`sige'
							mat `reshcov'[`i',`j'] =`rc`i'`j''
						}
						if abs(`i'-`j')==1  {
							local rc`i'`j'=(`theta1'+`theta1'*`theta2')*`sigv'
							mat `reshcov'[`i',`j'] =`rc`i'`j''
						}
						if abs(`i'-`j')==2  {
							local rc`i'`j'=(`theta2')*`sigv'
							mat `reshcov'[`i',`j'] =`rc`i'`j''
						}
					}
				}
			}
		}

		if "`hresid'"=="banded" { //banded - no input version, use unstructured
				forvalues i=1/`sched_length' {
					if `i'==1 {
						if "`hrestype'"=="resauto" local sige1=exp(_b[lnsig_e:_cons]+_b[r_lns2_1ose:_cons])^2
					}
					else {
						if "`hrestype'"=="resauto" local sige`i'= exp(_b[lnsig_e:_cons]+_b[r_lns2_`i'ose:_cons])^2
					}
					local rc`i'`i'=`sige`i''
					mat `reshcov'[`i',`i'] =`rc`i'`i''
				}
				forvalues i=1/`sched_length' {
						forvalues j=`=`i'+1'/`sched_length' {
							if abs(`i'-`j')<=`hban' & `i'!=`j' {
								if "`hrestype'"=="resauto" local rc`i'`j'=tanh(_b[r_atr2_`i'_`j':_cons])*`sige`i''^0.5*`sige`j''^0.5
								mat `reshcov'[`i',`j'] =`rc`i'`j''
								mat `reshcov'[`j',`i'] =`rc`i'`j''
							}
						}
				}
			}

		if "`hresid'"=="toeplitz" {  // toeplitz
			if "`hrestype'"=="resinput" {
				local hton=`hton2length'-1
				forvalues d=1/`hton2length' {
					local param`d' : word `d' of `hton2'
				}
			}
			if "`hrestype'"=="resauto" local sige1=exp(_b[lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
			if "`hrestype'"=="resinput" local sige1=`param1'
			forvalues i=1/`sched_length' {
				local rc`i'`i'=`sige1'
				mat `reshcov'[`i',`i'] =`rc`i'`i''
			}
			forvalues i=1/`sched_length' {
					forvalues j=`=`i'+1'/`sched_length' {
						local diff= abs(`i'-`j')
						if `diff'<=`hton' {
							if "`hrestype'"=="resauto" local rc`i'`j'=tanh(_b[r_atr2_`diff':_cons])*`sige1'^0.5*`sige1'^0.5
							if "`hrestype'"=="resinput" local rc`i'`j'=`param`=`diff'+1''*`sige1'^0.5*`sige1'^0.5
							mat `reshcov'[`i',`j'] =`rc`i'`j''
							mat `reshcov'[`j',`i'] =`rc`i'`j''
						}
					}
			}
		}


		if "`hresid'"=="unstructured" { // unstructured
					if "`hrestype'"=="resinput"  {
					mat `reshcov'=`hresid_mat'
							}
				if "`hrestype'"=="resauto"  {
					forvalues i=1/`sched_length' {
						if `i'==1 {
							 local sige1=exp(_b[lnsig_e:_cons]+_b[r_lns2_1ose:_cons])^2
						}
						else {
							 local sige`i'= exp(_b[lnsig_e:_cons]+_b[r_lns2_`i'ose:_cons])^2
						}
						local rc`i'`i'=`sige`i''
						mat `reshcov'[`i',`i'] =`rc`i'`i''
					}
					forvalues i=1/`sched_length' {
							forvalues j=`=`i'+1'/`sched_length' {
								local rc`i'`j'=tanh(_b[r_atr2_`i'_`j':_cons])*`sige`i''^0.5*`sige`j''^0.5
								mat `reshcov'[`i',`j'] =`rc`i'`j''
								mat `reshcov'[`j',`i'] =`rc`i'`j''

							}
					}
				}
		}

		if "`hresid'"=="exponential" { // exponential
			if "`hrestype'"=="resinput" {
				forvalues d=1/`hexn2length' {
					local param`d' : word `d' of `hexn2'
				}
			}
			if "`hrestype'"=="resauto" local rho1=invlogit(_b[r_logitr2:_cons])
			if "`hrestype'"=="resauto" local sige=exp(_b[ lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
			if "`hrestype'"=="resinput" local rho1=`param2'
			if "`hrestype'"=="resinput" local sige=`param1'
			forvalues i=1/`sched_length' {
				local it: word `i' of `schedule'
				forvalues j=1/`sched_length' {
					local jt: word `j' of `schedule'
					local rc`i'`j'=`sige'*`rho1'^`=abs(`it'-`jt')'
					mat `reshcov'[`i',`j'] =`rc`i'`j''
				}
			}
		}

		if "`hresid'"=="exchangeable" { // exchangeable
			if "`hrestype'"=="resinput" {
				forvalues d=1/`hecn2length' {
					local param`d' : word `d' of `hecn2'
				}
			}
			if "`hrestype'"=="resauto" local sige1=exp(_b[lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
			if "`hrestype'"=="resinput" local sige1=`param1'
			forvalues i=1/`sched_length' {
				local rc`i'`i'=`sige1'
				mat `reshcov'[`i',`i'] =`rc`i'`i''
			}
			forvalues i=1/`sched_length' {
					forvalues j=`=`i'+1'/`sched_length' {
							if "`hrestype'"=="resauto" local rc`i'`j'=tanh(_b[r_atr2:_cons])*`sige1'^0.5*`sige1'^0.5
							if "`hrestype'"=="resinput" local rc`i'`j'=`param2'*`sige1'^0.5*`sige1'^0.5
							mat `reshcov'[`i',`j'] =`rc`i'`j''
							mat `reshcov'[`j',`i'] =`rc`i'`j''
					}
			}
		}


		if "`hresid'"=="independent" {  // independent - IID as well as heterogeneous ID for input version
			if "`hrestype'"=="resinput" {
				forvalues d=1/`sched_length' {

					if `hinn2length'==1 local param`d' : word 1 of `hinn2'
					if `hinn2length'>1 local param`d' : word `d' of `hinn2'
					mat `reshcov'[`d',`d'] =`param`d''
				}
			}
				if "`hrestype'"=="resauto"  {
					forvalues i=1/`sched_length' {
						if `hinn'==1 {
							 local rc`i'`i'=exp(_b[lnsig_e:_cons]+_b[r_lns2ose:_cons])^2
						}
						if `hinn'==`sched_length' {
							 if `i'==1 local rc`i'`i'=exp(_b[lnsig_e:_cons]+_b[r_lns2ose:_cons])^2

							else {
								local rc`i'`i'= exp(_b[lnsig_e:_cons]+_b[r_lns`i'ose:_cons])^2
							}
						}
						mat `reshcov'[`i',`i'] =`rc`i'`i''
					}
					local hinn2length=`hinn'  // for use in syntax code output
				}
		}

	}

	if "`errhet'"=="" local hresid `resid'

 *mat li `reshcov'

**# RESCALING
local scale1=1

** Rescale contslope - changes with scale, so an x% effect means something different (i.e rescale TTE)

	if "`contslope'"!="" {
		if `ns_num'==1 { // version if slope specified as number
			local diff1=`contslope'*`effectiveness'
		}
		if `ns_num'==0 { // version if slope value taken from mixed model slope (`beta')
			local diff1=`beta'*`effectiveness'
		}
		local difference=-1*(`diff1')
	}



** Rescale Slope Difference parameter - only matters if trtspec=slope because it's an interaction parameter
	local trdiff `trtspec'
	if "`actualtrt'"!="" local trdiff `actualtrt'  // change to actualtrt spec.

	tempname tte cvalues
	mat `tte'=J(1,`altvarX',0)
	if "`cbeta'"!="" {
		mat `cvalues'=J(1,`actcontlength',0)
		forvalues cb=1/`actcontlength' {
			local cbeta`cb': word `cb' of `cbeta'
			mat `cvalues'[1,`cb']=`cbeta`cb''
		}
		*mat li `cvalues'
	}

	if "`trdiff'"=="slope" mat `tte'[1,1]=`diff1'*`scale1' // note scale1 is kept=1, not using scaling here now

	if "`trdiff'"=="intercept" mat `tte'[1,1]=`diff1'

	if "`trdiff'"=="lateslope" mat `tte'[1,1]=`diff1'*`scale1'

	if "`trdiff'"=="user" mat `tte'[1,1]=`diff1'*`scale1'

	if "`trdiff'"=="slint" {
		mat `tte'[1,1]=`diff1'
		mat `tte'[1,2]=`diff2'*`scale1'
	}

	if "`trdiff'"=="2slope" {
		mat `tte'[1,1]=`diff1'*`scale1'
		mat `tte'[1,2]=`diff2'*`scale1'
	}

	if "`trdiff'"=="user2" {
		mat `tte'[1,1]=`diff1'*`scale1'
		mat `tte'[1,2]=`diff2'*`scale1'
	}

	if  "`trdiff'"=="factor0" | "`trdiff'"=="factor"   {
		forvalues tst=1/`altvarX' {
			mat `tte'[1,`tst']=`diff`tst''
		}
	}

**# HEADER


	if "`noheader'"=="" {

		di _n "{it:mixedpower}" as text " - power and sample size calculator for linear mixed models (version 1.0): author M.Burnell"
		di as text "MRC Centre of Research Excellence in Clinical Trial Innovation, UCL, London WC1V 6LJ, UK" _n
	}


********** MODEL SYNTAX OUTPUT SECTION *****************************************
**# SYNTAX
	if "`nosyntax'"=="" {
		 di  "{hline}"
		* ctype
		 if "`altcont'"=="factor" local ct1 i.
		 if "`altcont'"=="noint" | "`altcont'"=="slint" | "`altcont'"=="2slope" local ct1 c.
		if "`altcont'"=="factor" | "`altcont'"=="noint" | "`altcont'"=="slint" | "`altcont'"=="2slope" {
			local ct2 time
		}
		if "`altcont'"=="user" local cus1 f(t)_c1({it:time})
		if "`altcont'"=="user2" local cus2 f(t)_c1({it:time}) f(t)_c2({it:time})

		* ttype
		 if "`trtspec'"=="factor" | "`trtspec'"=="factor0" {
			local tt1 i.
			local tt2 time
			local tt3 #1.
			local tt4 trt
		 }
		 if "`trtspec'"=="slope" | "`trtspec'"=="slint" | "`trtspec'"=="lateslope" | "`trtspec'"=="2slope" {
			local tt1 c.
			local tt2 time
			local tt3 #1.
			local tt4 trt
		 }
		 * tint
		 if "`trtspec'"=="slint" | "`trtspec'"=="intercept" local tint i.trt
		 * ls
		 if "`trtspec'"=="lateslope"  local ls _LS
		  * 2s
		  if "`altcont'"=="2slope"  local cts1 _2S_1
		 if "`altcont'"=="2slope"  local cts2a c.
		 if "`altcont'"=="2slope"  local cts2b time_2S_2

		 if "`trtspec'"=="2slope"  local ts1 _2S_1
		 if "`trtspec'"=="2slope"  local ts2a c.
		 if "`trtspec'"=="2slope"  local ts2b time_2S_2
		 if "`trtspec'"=="2slope"  local ts2c #1.
		 if "`trtspec'"=="2slope"  local ts2d trt
		 if "`trtspec'"=="user" local tus1 f_1({it:time})#1.trt
		 if "`trtspec'"=="user2" local tus2 f_1({it:time})#1.trt f_2({it:time})#1.trt
		 * nocons
		 if "`altcont'"=="noint" local nocons , nocons
		 * factortr
		 if "`trtspec'"=="factor" & "`altcont'"=="noint" local factortr  constraints(1)
		 if "`trtspec'"=="factor" & "`altcont'"!="noint" local factortr , constraints(1)
		 if "`marginal'"=="" {
			 * retime
			 if `var_slope'>0 local retime " {it:time}"
			 * cov
			 if `cov_slopeint'!=0 local cov " cov(unstr)"
			 if `cov_slopeint'==0 local cov " cov(independent)"
			 if `var_slope'==0 & `cov_slopeint'==0 local cov ""
			 * marg
			 if `var_int'==0 local marg nocons
			 local comma ","
		 }

		 * marg
		 if "`marginal'"!="" local marg nocons
		 if "`marginal'"!="" local comma ","
		 * restype/resnum/torby
		 local restype independent
		 local torby t
		  if "`errxt'"!="" {
			local restype `resid'
			if "`resid'"=="ar" local resnum `arn'
			if "`resid'"=="ma" local resnum `man'
			if "`resid'"=="banded" local resnum `ban'
			if "`resid'"=="toeplitz" local resnum `ton'
			if "`resid'"=="independent" {
				if `inn2length'==1 local torby t
				if `inn2length'>1 local torby by
			}
			else local torby t
		  }
		 * errxt
		 if "`errhet'"!="" local ext " by({it:trt})"
		 * covhet
		 if "`covhet'"!="" {
			if `intvar'!=0 local ch0int "0.{it:trt}"
			if `slvar'!=0 local ch0sl " c.{it:time}#0.{it:trt}"
			if `cov12'!=0 local ch0cov " cov(unstr)"
			if `slvar'!=0 & `cov12'==0 local ch0cov " cov(ind)"
			local retime " `ch0sl' `ch0int',`ch0cov' nocons"
			local cov
			if `hintvar'!=0 local ch1int "1.{it:trt}"
			if `hslvar'!=0 local ch1sl " c.{it:time}#1.{it:trt}"
			if `hcov12'!=0 local ch1cov "cov(unstr)"
			if `hslvar'!=0 & `hcov12'==0 local ch1cov " cov(ind)"
			local hretime "|| {it:id_level2}: `ch1sl' `ch1int', `ch1cov' nocons"
			local comma
		 }

		di as text "Mixed model syntax:"
		if "`trtspec'"=="factor" {
			di as result "constraint 1 _b[0.{it:time}#1.{it:trt}]=0 "
		}
		di  as res "mixed{it: depvar} `ct1'{it:`ct2'}{it:`cts1'} `cts2a'{it:`cts2b'}`cus1'`cus2' {it:`tint'} `tt1'{it:`tt2'}{it:`ls'}{it:`ts1'}`tt3'{it:`tt4'} `ts2a'{it:`ts2b'}`ts2c'{it:`ts2d'}`tus1'`tus2' `nocons' `factortr' || {it:id_level2}:`retime' `hretime'`comma'`cov' `marg' resid(`restype' `resnum', `torby'({it:time})`ext') "
		if "`resid'"!="`hresid'" & "`hresid'"!="" {
			di as error "note that error structure {it:type} for treatment group - errhet() - is different to {it:type} for control group - errxt() - which is not possible to specify with the mixed command"
		}
	}




***** MATRIX SECTIONS **********************************************************
**# MATRIX/FRAME SETTING UP

* do we need to consider weighting of different schedule cohorts i.e. create multiple frames?

	if "`strecruitment'"=="" & "`dropouts'"=="" {
		local mframes=1  // either going to make just one frame - no pwgt cohorts
	}
	else {
		local mframes=`sched_length'  // ... or multiple frames (not necessarily sched_length amount, if any cwgts==0)
	}


* create new frame(s) with matrix contents and calculate variance of treatment effects



	local frlist // for creating numlist of frames to include when cohort==1 in following loop

	foreach n of numlist 1/`mframes' { // create a frame for each schedule cohort if necessary. Not going to use tempnames if frames(keep), otherwise frames will be dropped by program

		local pwgts_`n': word `n' of `cwgts' // not needed anymore?...
		local pwgt0_`n': word `n' of `pwgts'
		local pwgt1_`n': word `n' of `pwgts2'
		if `cohorts'==0 {
			local pwgts_1=1 // not needed anymore?...
			local pwgt0_`n'=1
			local pwgt1_`n'=1
		}


		if `pwgts_`n''>0  {
			if `cohorts'==1 & `n'>0  {
				local frlist "`frlist' `n'"
			}
**# 2-LEVEL - X matrix and identifier variables plus intitial frame(s) set up
		 	if "`frames'"=="keep"	{
				tempname _mp_`model'_`trtspec'_coh`cohorts'_`n'
				frame create `_mp_`model'_`trtspec'_coh`cohorts'_`n''
				frame change `_mp_`model'_`trtspec'_coh`cohorts'_`n''
				notes: mixedpower dataframe
				notes: model type: `model'
				notes: treatment specification: `trtspec'
				notes: cohort (0=represents full sample; 1=represents partial sample) : `cohorts'
				if `cohorts'==1 {
					notes: cohort schedule: up to visit `n'
				}
				if `cohorts'==0 {
					notes: cohort schedule: up to visit `sched_length' only
				}
				notes: probability weight of cohort: `pwgts_`n''
			}
			if "`frames'"=="drop" & "`fr_created'"!="yes" {
				tempname _mp_`model'_`trtspec'
				frame create `_mp_`model'_`trtspec''
				frame change `_mp_`model'_`trtspec''
				local fr_created yes
			}
		qui {
				**# 2level X matrix

			local k=`n' // number of visits from schedule to use for this (nth) frame
			if `cohorts'==0 {
				local k=`sched_length' // no dropout/strec then will use all visits
			}
			local trwt1: word 1 of `allratio'
			local trwt2: word 2 of `allratio'
			local obsn=`sched_length'*(`trwt1'+`trwt2')

			set obs `=`obsn'+100'

			gen trt_cohort=.
			gen obs=.
			gen double time=.
			gen treat=.
			if "`actualtrt'"!="" & "`actualcont'"=="" local copyC yes
			if "`actualtrt'"=="" & "`actualcont'"!="" local copyT yes

			if "`altcont'"=="factor" local contvar=`sched_length'  // changed from `k', so creating X variables for all timepoints even if not reached by cohort (column of zeros), for purpose of matrix calculation of overall B_variance
			if "`actualcont'"=="factor"	local Acontvar=`sched_length'

			if "`altcont'"=="noint" 	local contvar=1
			if "`actualcont'"=="noint" 	local Acontvar=1

			if "`altcont'"=="noslope" 	local contvar=1
			if "`actualcont'"=="noslope" 	local Acontvar=1

			if "`altcont'"=="slint" 	local contvar=2
			if "`actualcont'"=="slint" 	local Acontvar=2

			if "`altcont'"=="2slope" 	local contvar=3
			if "`actualcont'"=="2slope" 	local Acontvar=3

			if "`altcont'"=="user" local contvar=2
			if "`actualcont'"=="user" local Acontvar=2

			if "`altcont'"=="user2" local contvar=3
			if "`actualcont'"=="user2" local Acontvar=3

			if "`trtspec'"=="factor0" local altvar=`sched_length'
			if "`actualtrt'"=="factor0"  local Aaltvar=`sched_length'


			if "`trtspec'"=="factor" local altvar=`sched_length'-1
			if "`actualtrt'"=="factor" local Aaltvar=`sched_length'-1


			if "`trtspec'"=="slope" local altvar=1
			if "`actualtrt'"=="slope" local Aaltvar=1


			if "`trtspec'"=="intercept" local altvar=1
			if "`actualtrt'"=="intercept" local Aaltvar=1


			if "`trtspec'"=="slint" local altvar=2
			if "`actualtrt'"=="slint" local Aaltvar=2


			if "`trtspec'"=="lateslope" local altvar=1
			if "`actualtrt'"=="lateslope" local Aaltvar=1


	 		if "`trtspec'"=="2slope" local altvar=2
			if "`actualtrt'"=="2slope" local Aaltvar=2

			if "`trtspec'"=="user" local altvar=1
			if "`actualtrt'"=="user" local Aaltvar=1

			if "`trtspec'"=="user2" local altvar=2
			if "`actualtrt'"=="user2" local Aaltvar=2

			if "`copyC'"=="yes" local Acontvar=`contvar' // copy the C X vars into AX if required
			if "`copyT'"=="yes" local Aaltvar=`altvar' // copy the T X vars into AX

			local vlim=`contvar'+`altvar'
			forvalues v=1/`vlim' {
					gen double X`v'=0
				}

			if "`actualtrt'"!="" | "`actualcont'"!="" {
				local avlim=`Acontvar'+`Aaltvar'
				forvalues av=1/`avlim' {
						gen double AX`av'=0

					}
			}

		}

			local in=0 // local counter for inputting matrix values in appropriate row
			local trt_coh=0	// dataset marker identifying unique trt#cohorts based on ARAtio arguments
			local trt=-1 // identify trt and control groups (will be 0/1 values when inputted)

			local arat=0 // for picking which ARatio weight to use

			forvalues g=0/1 {  // loop over treatment
				local trt=`trt'+1
				local arat=`arat'+1
				local trwt: word `arat' of `allratio'
				forvalues ab=1/`trwt' { // loop over trt#cohort weights
					local trt_coh=`trt_coh'+1
					forvalues j=1/`k'	{ // loop over visits upto `n' for that cohort for X values (for Xi+1 to Xsched_length will be left as zeros)

						local t : word `j' of `schedule'
						if "`trtspec'"=="user" | "`trtspec'"=="user2" local tu1 : word `j' of `txfun_1'
						if "`trtspec'"=="user2" local tu2 : word `j' of `txfun_2'
						if "`actualtrt'"=="user" | "`actualtrt'"=="user2" local atu1 : word `j' of `atxfun_1'
						if "`actualtrt'"=="user2" local atu2 : word `j' of `atxfun_2'
						if "`altcont'"=="user" | "`altcont'"=="user2" local cu1 : word `j' of `cxfun_1'
						if "`altcont'"=="user2" local cu2 : word `j' of `cxfun_2'
						if "`actualcont'"=="user" | "`actualcont'"=="user2" local acu1 : word `j' of `acxfun_1'
						if "`actualcont'"=="user2"  local acu2 : word `j' of `acxfun_2'

						local in=`in'+1

						if "`altcont'"=="factor" {
							qui replace X`j'=1 in `in'
						}
						if "`altcont'"=="noint" {
							qui replace X1=`t' in `in'
						}
						if "`altcont'"=="noslope" {
							qui replace X1=1 in `in'
						}
						if "`altcont'"=="slint" {
							qui replace X1=1 in `in'
							qui replace X2=`t' in `in'
						}
						if "`altcont'"=="2slope" {
							qui replace X1=1 in `in'
							qui replace X2=cond((`t'-`Ctslt')<0,`t',`Ctslt') in `in'
							qui replace X3=`t' in `in'
						}
						if "`altcont'"=="user" {
							qui replace X1=1 in `in'
							qui replace X2=`cu1' in `in'
						}
						if "`altcont'"=="user2" {
							qui replace X1=1 in `in'
							qui replace X2=`cu1' in `in'
							qui replace X3=`cu2' in `in'
						}
						if "`trtspec'"=="factor0" {
							local x=`contvar'+`j'
								*local xin=(`trt_coh'-1)*`k'+ `j'
							qui replace X`x'=1*`g' in `in'
						}
						if "`trtspec'"=="factor" {
							local x=`contvar'+`j'-1
								*local xin=(`trt_coh'-1)*`k'+ `j'
							if `j'>1 {
							qui replace X`x'=1*`g' in `in'
							}
						}
						if "`trtspec'"=="slope" {
							local x=`contvar'+1
							qui replace X`x'=`t'*`g' in `in'
						}
						if "`trtspec'"=="intercept" {
							local x=`contvar'+1
							qui replace X`x'=1*`g' in `in'
						}
						if "`trtspec'"=="slint" {
							local x=`contvar'+1
							local xx=`contvar'+2
							qui replace X`x'=1*`g' in `in'
							qui replace X`xx'=`t'*`g' in `in'

						}
						if "`trtspec'"=="lateslope" {
							local x=`contvar'+1
							qui replace X`x'=cond((`t'-`lslt')>0,(`t'-`lslt'),0)*`g' in `in'
						}
						if "`trtspec'"=="2slope" {
							local x=`contvar'+1
							local xx=`contvar'+2
							qui replace X`x'=cond((`t'-`tslt')<0,`t',`tslt')*`g' in `in'
							qui replace X`xx'=`t'*`g' in `in'
						}
						if "`trtspec'"=="user" {
							*noi di "`contvar' `tu1'"
							local x=`contvar'+1
							qui replace X`x'=`tu1'*`g' in `in'
						}
						if "`trtspec'"=="user2" {
							local x=`contvar'+1
							local xx=`contvar'+2
							qui replace X`x'=`tu1'*`g' in `in'
							qui replace X`xx'=`tu2'*`g' in `in'
						}
**# AX MATRIX
						*ACTUAL X creations
						if  "`actualcont'"!=""  {
							if "`actualcont'"=="factor" {
								qui replace AX`j'=1 in `in'
							}
							if "`actualcont'"=="noint" {
								qui replace AX1=`t' in `in'
							}
							if "`actualcont'"=="noslope" {
								qui replace AX1=1 in `in'
							}
							if "`actualcont'"=="slint" {
								qui replace AX1=1 in `in'
								qui replace AX2=`t' in `in'
							}
							if "`actualcont'"=="2slope" {
								qui replace AX1=1 in `in'
								qui replace AX2=cond((`t'-`aCtslt')<0,`t',`aCtslt') in `in'
								qui replace AX3=`t' in `in'
							}
							if "`actualcont'"=="user" {
								qui replace AX1=1 in `in'
								qui replace AX2=`acu1' in `in'
							}
							if "`actualcont'"=="user2" {
								qui replace AX1=1 in `in'
								qui replace AX2=`acu1' in `in'
								qui replace AX3=`acu2' in `in'
							}
						}
						if "`copyC'"=="yes" {
							foreach var of varlist X1-X`=`contvar'' {
								qui replace A`var'=`var'
							}
						}
						if  "`actualtrt'"!="" {
							if "`actualtrt'"=="factor0" {
								local ax=`Acontvar'+`j'
								qui replace AX`ax'=1*`g' in `in'
							}
							if "`actualtrt'"=="factor" {
								local ax=`Acontvar'+`j'-1
								if `j'>1 {
								qui replace AX`ax'=1*`g' in `in'
								}
							}
							if "`actualtrt'"=="slope" {
								local ax=`Acontvar'+1
								qui replace AX`ax'=`t'*`g' in `in'
							}
							if "`actualtrt'"=="intercept" {
								local ax=`Acontvar'+1
								qui replace AX`ax'=1*`g' in `in'
							}
							if "`actualtrt'"=="slint" {
								local ax=`Acontvar'+1
								local axx=`Acontvar'+2
								qui replace AX`ax'=1*`g' in `in'
								qui replace AX`axx'=`t'*`g' in `in'
							}
							if "`actualtrt'"=="lateslope" {
								local ax=`Acontvar'+1
								qui replace AX`ax'=cond((`t'-`alslt')>0,(`t'-`alslt'),0)*`g' in `in'
							}
							if "`actualtrt'"=="2slope" {
								local ax=`Acontvar'+1
								local axx=`Acontvar'+2
								qui replace AX`ax'=cond((`t'-`atslt')<0,`t',`atslt')*`g' in `in'
								qui replace AX`axx'=`t'*`g' in `in'
							}
							if "`actualtrt'"=="user" {
								local ax=`Acontvar'+1
								qui replace AX`ax'=`atu1'*`g' in `in'
							}
							if "`actualtrt'"=="user2" {
								local ax=`Acontvar'+1
								local axx=`Acontvar'+2
								qui replace AX`ax'=`atu1'*`g' in `in'
								qui replace AX`axx'=`atu2'*`g' in `in'
							}
						}

						if "`copyT'"=="yes" {
							local aa=0
							foreach var of varlist X`=`contvar'+1'-X`=`contvar'+`altvar'' {

								local aa=`aa'+1
								local varA X`=`Acontvar'+`aa''
								qui replace A`varA'=`var'
							}
						}
						qui replace trt_cohort=`trt_coh' in `in'
						qui replace obs=`j' in `in'
						qui replace time=`t' in `in'
						qui replace treat=`trt' in `in'
					}
				}
			}


			local in=`in'+1
			foreach var of varlist trt_cohort obs time treat  X1-X`vlim'    {
					qui replace `var'=. in `in'/l
				}
			if "`actualtrt'"!="" |  "`actualcont'"!="" {
				foreach avar of varlist trt_cohort obs time treat  AX1-AX`avlim'    {
						qui replace `avar'=. in `in'/l
					}
			}
			qui tostring treat, gen(trt_str)
			qui tostring trt_cohort, gen(ar_str)
			qui tostring obs, gen(vis_str)
			qui gen str15 rownames="t"+trt_str+"_"+"v"+vis_str
			qui replace rownames="" if treat==.
			qui replace trt_str="" if treat==.
			qui replace ar_str="" if treat==.
			qui replace vis_str="" if treat==.

			tempname X	Xm AX AXm Xmod
			mkmat X1-X`vlim', matrix(`X') nomissing rownames(rownames)
			if "`actualtrt'"!="" |  "`actualcont'"!="" mkmat AX1-AX`avlim', matrix(`AX') nomissing rownames(rownames)

			if "`xmat'"!="" {
				if `xmat'==`n' & `cohorts'==1 {
					mat `Xmod'=`X'
					mat `Xm'=`X'
					return matrix xmat=`Xm'
					if "`actualtrt'"!="" |  "`actualcont'"!="" {
						mat `AXm'=`AX'
						return matrix actual_xmat=`AXm'
					}
				}
				if `cohorts'==0 {
					mat `Xmod'=`X'
					mat `Xm'=`X'
					return matrix xmat=`Xm'
					if "`actualtrt'"!="" |  "`actualcont'"!="" {
						mat `AXm'=`AX'
						return matrix actual_xmat=`AXm'
					}
				}
			}



		**# 2level R matrix
			local arat=0
			local in=0
			local inxt=0

			forvalues g=0/1 { // loop over treatment
				local arat=`arat'+1
				local trwt: word `arat' of `allratio'
				forvalues ab=1/`trwt' { // loop over treatment#cohort weights
					forvalues r=1/`k'	{	// loop over visits upto `n'

						local in=`in'+1
						qui gen double R`in'=0
						if `r'==1 {
							local inxt=`in'
						}
						forvalues c=1/`k' {
							local inr=`inxt'+`r'-1
							local inc=`inxt'+`c'-1
							if `g'==0 {
								qui replace R`inr'=`rescov'[`r',`c'] in `inc'
							}
							if `g'==1 {
								qui replace R`inr'=`reshcov'[`r',`c'] in `inc'
							}

						}

					}
				}
			}

			local inl=`in'+1
			foreach var of varlist R1-R`in' {
				qui replace `var'=. in `inl'/l
			}

			tempname R Rm
			mkmat R1-R`in', matrix(`R') nomissing rownames(rownames)

			if "`rmat'"!="" {
				if `rmat'==`n' & `cohorts'==1 {
					mat `Rm'=`R'
					return matrix rmat=`Rm'
				}
				if `cohorts'==0 {
					mat `Rm'=`R'
					return matrix rmat=`Rm'
				}
			}


	if "`marginal'"=="" {
		**# 2level Z matrix

			local in=0
			local nct=0
			local arat=0

			forvalues g=0/1 {

				local arat=`arat'+1
				local trwt: word `arat' of `allratio'
				forvalues ab=1/`trwt' {

					local nct=`nct'+1
					local z1=(`nct'-1)*2+1
					local z2=(`nct'-1)*2+2

					gen double Z`z1'=0
					gen double Z`z2'=0

					forvalues j=1/`k'{
						local t : word `j' of `schedule'
						local in=`in'+1

						qui replace Z`z1'=1 in `in'  // creating Z design matrix in pairs - this one for random intercept
						qui replace Z`z2'=`t' in `in' // this one for random slope


					}
				}
			}

			local inl=`in'+1
			foreach var of varlist Z1-Z`z2' {
				qui replace `var'=. in `inl'/l
			}
			tempname Z Zm
			mkmat Z1-Z`z2', matrix(`Z') nomissing rownames(rownames)

			if "`zmat'"!="" {
				if `zmat'==`n' & `cohorts'==1 {
					mat `Zm'=`Z'
					return matrix zmat=`Zm'
				}
				if `cohorts'==0 {
					mat `Zm'=`Z'
					return matrix zmat=`Zm'
				}
			}

		**# 2level G matrix

			local arat=0
			local in=0
			forvalues g=0/1 {

				local arat=`arat'+1
				local trwt: word `arat' of `allratio'
				forvalues ab=1/`trwt' {

					local in=`in'+1
					local g1=1+(`in'-1)*2  // for entering the cov parameters in pairs per row
					local g2=2+(`in'-1)*2

					qui gen double G`g1'=0
					qui gen double G`g2'=0

					local cell=0
					local rmax=2 // cov matrix is 2x2 - will be larger for multivariate version
					local cmax=2

					forvalues r=1/`rmax' {
						forvalues c=1/`cmax' {
							local cell=`cell'+1
							local value: word `cell' of `covmat'
							local hvalue: word `cell' of `hcovmat'
							local in`r'`c'=(`g1')+(`r'-1)
							local gc=`g1'+(`c'-1)
							if `g'==0 qui replace G`gc'=`value' in `in`r'`c''
							if `g'==1 qui replace G`gc'=`hvalue' in `in`r'`c''
						}
					}

				}
			}


			local inl=`g2'+1
			foreach var of varlist G1-G`g2' {
				qui replace `var'=. in `inl'/l
			}
			tempname G Gm
			mkmat G1-G`g2', matrix(`G') nomissing

			if "`gmat'"!="" {
				if `gmat'==`n' & `cohorts'==1 {
					mat `Gm'=`G'
					return matrix gmat=`Gm'
				}
				if `cohorts'==0 {
					mat `Gm'=`G'
					return matrix gmat=`Gm'
				}
			}


	}


**# MATRIX ALGEBRA

			tempname sigma sigma0 B_var invsigma Abeta AY AYM EYM Mbeta MbetaT tteM sigma sigmaC sigmaT
			if "`marginal'"!="" {
				mat `sigma'=`R'
				mat `sigma0'=`sigma'
			}
			else {
				mat `sigma'=`R'+`Z'*`G'*`Z''  // note transpose ' - not an excess quote symbol!
				mat `sigma0'=`sigma'
			}

**# REWEIGHTING
			*** ARATIO plus pweights section ***
			if "`alloratio'"=="" {

				if `pwgt0_`n''>0 mat `sigmaC'=(1/`ar1')*(1/`pwgt0_`n'')*`sigma'[1..rowsof(`sigma'),1..`k']
				if `pwgt0_`n''==0 mat `sigmaC'=(1/`ar1')*(0)*`sigma'[1..rowsof(`sigma'),1..`k']

				if `pwgt1_`n''>0 mat `sigmaT'=(1/`ar2')*(1/`pwgt1_`n'')*`sigma'[1..rowsof(`sigma'),`=1+`k''..`=2*`k'']
				if `pwgt1_`n''==0 mat `sigmaT'=(1/`ar2')*(0)*`sigma'[1..rowsof(`sigma'),`=1+`k''..`=2*`k'']
				mat coljoin `sigma'=`sigmaC' `sigmaT'

			}

			*mat li `sigma'

			**********************
**# ACTUAL Matrix stuff
			** Calculate var(B) and if actualtrt/cont used, calculate model betas
			mat `invsigma'=invsym(`sigma')
			mat `B_var'=invsym(`X''*invsym(`sigma')*`X') // note transpose ' - not an excess quote symbol!
			if  "`actualtrt'"!="" | "`actualcont'"!="" {

				mat `Abeta'=J(1,`=`Acontvar'+`Aaltvar'',0) // actual beta vector
				if "`cbeta'"!="" {    // zeros for C unless cbeta and actualcont used
					forvalues ab=1/`Acontvar'{
						mat `Abeta'[1,`ab']=`cvalues'[1,`ab']
					}
				}
				if "`actualtrt'"!="" {  // add actual T betas
					forvalues ab=1/`Aaltvar'{
						mat `Abeta'[1,`=`Acontvar'+`ab'']=`tte'[1,`ab']
					}
				}
				if "`actualtrt'"=="" { // actual T betas will be same as model if only actualcont used
					forvalues ab=1/`Aaltvar'{
						mat `Abeta'[1,`=`Acontvar'+`ab'']=`tte'[1,`ab']
					}
				}
				*mat abs= `Abeta'
				*mat axi= `AX'
				mat `AY'=`AX'*`Abeta''  // actual Ys given actual B and actual X design
				mat `Mbeta'=`B_var'*`X''*`invsigma'*`AY' // model betas (for both C and T)
				mat `MbetaT'=`Mbeta''
				mat `tteM'= `MbetaT'[1,`=`contvar'+1'..`=`contvar'+`altvar''] // vector of just the T betas
				*mat AYs= `AY'
				*mat mbs= `Mbeta'
				*mat li `tteM'
				*mat li axi
				*mat li AYs
				*mat li mbs
			}


			if `cohorts'==1 { // name Var(B) invsigma model betas and a diagonal version of Var(B) for each cohort
					tempname B_var`n' sigma`n' invsigma`n'    MbetaT`n' bvarD`n'
					mat `B_var`n''=`B_var'
					mat `sigma`n''=`sigma0'
					if  "`actualtrt'"!="" | "`actualcont'"!="" {
						mat `bvarD`n''=diag(vecdiag(`B_var`n''))
						mat `MbetaT`n''=`Mbeta''

					}
			}

			tempname bvarin sigmain corrin iccn sigvec zgzvec  // return Var(B) for specified cohort
**# MATRIX RETURNS

			if "`marginal'"=="" & "`resid'"=="independent" & "`hresid'"=="independent" local icc yes  // if ICC to be reported
			if "`bvarn'"!=""  {
					if `cohorts'==1 & `bvarn'==`n' {
						mat `sigmain'=`sigma`n''
						mat `corrin'=corr(`sigma`n'')
						mat `bvarin'=`B_var`n''
						if "`icc'"=="yes" {
							mat `sigvec'=vecdiag(`sigma`n'')
							mat `zgzvec'=vecdiag(`sigma`n'')-vecdiag(`R')
							mata: st_matrix("`iccn'", st_matrix("`zgzvec'") :/ st_matrix("`sigvec'"))
							return matrix cond_icc_n=`iccn'
						}
						return matrix bvar_n=`bvarin'
						return matrix sigma_n=`sigmain'
						return matrix wcorr_n=`corrin'
					}
					if `cohorts'==0 & `bvarn'==`sched_length' {
						mat `corrin'=corr(`sigma0')
						mat `sigmain'=`sigma0'
						mat `bvarin'=`B_var'
						if "`icc'"=="yes" {
							mat `sigvec'=vecdiag(`sigma0')
							mat `zgzvec'=vecdiag(`sigma0')-vecdiag(`R')
							mata: st_matrix("`iccn'", st_matrix("`zgzvec'") :/ st_matrix("`sigvec'"))
							return matrix cond_icc_n=`iccn'
						}
						return matrix bvar_n=`bvarin'
						return matrix sigma_n=`sigmain'
						return matrix wcorr_n=`corrin'
					}
				}


			tempname nmcount
			qui egen `nmcount' = rownonmiss(_all), strok
			qui drop if `nmcount' == 0
			qui drop `nmcount'



			if "`frames'"=="drop"  {
				drop _all
			}
			if "`frames'"=="keep"  {
			frame rename `_mp_`model'_`trtspec'_coh`cohorts'_`n'' _mp_`model'_`trtspec'_coh`cohorts'_`n'
			}
		}
		else  // for the schedule points who don't have associated unique cohorts

	}	// end of mframes loop


**# OVERALL BVAR CALCULATIONS
			***** Perform  overall-calculation of X-covariance if needed *****
	if `cohorts'==1 {
		tempname B_var  // the overall X-covariance matrix
		tempname wgtsum Mbetawgt bvarD
		mat `wgtsum'=J(`vlim',`vlim',0)
		foreach n of numlist `frlist' {

			*mat `wgtsum'=`wgtsum'+`pwgts_`n''*invsym(`B_var`n'')
			mat `wgtsum'=`wgtsum'+invsym(`B_var`n'')

		}

		mat `B_var'=invsym(`wgtsum')


		if "`actualtrt'"!="" | "`actualcont'"!="" {  // calc model betas for each cohort and combine weighted by ICW or IVW
			mat `Mbetawgt'=J(1,`vlim',0)
			mat `bvarD'=diag(vecdiag(`B_var'))
			foreach n of numlist `frlist' {

				if "`ivw'"!="" mat `Mbetawgt'=`Mbetawgt'+`MbetaT`n''*invsym(`bvarD`n'')*`bvarD'
				if "`ivw'"=="" mat `Mbetawgt'=`Mbetawgt'+`MbetaT`n''*invsym(`B_var`n'')*`B_var'

			}

			mat `tteM'= `Mbetawgt'[1,`=`contvar'+1'..`=`contvar'+`altvar'']

		}


	}

**# EFFECT SIZE RETURNS
	tempname bvar effsz tb tba mbw ab
	mat `bvar'=`B_var'
	return mat beta_var=`bvar'

	mat `effsz'=J(1,1,0)
	if "`actualtrt'"=="" & "`actualcont'"=="" mat `tteM'=`tte'
	if "`actualtrt'"=="" & "`actualcont'"=="" {
		if "`xmat'"!="" {
			mat `Abeta'=J(1,`=`contvar'+`altvar'',0)
			forvalues ab=1/`altvar'{
						mat `Abeta'[1,`=`contvar'+`ab'']=`tte'[1,`ab']
					}
			mat `AYM'=`Xmod'*`Abeta''
			return mat exp_y_true=`AYM'
		}
	}

	mat `tb'=`tte'
	mat `tba'=`tteM'

	if  "`actualtrt'"!="" | "`actualcont'"!="" {
		mat `AYM'=`AY'

		mat `ab'=`Abeta'
		return mat betas_true=`ab'
		if `cohorts'==1 {
			mat `mbw'=`Mbetawgt'
			return mat betas_model=`mbw'
			return mat exp_y_true=`AYM'
			if "`xmat'"!="" {
				mat `EYM'=`Xmod'*`Mbetawgt''
				return mat exp_y_model=`EYM'
			}

		}
		else {
			mat `mbw'=`MbetaT'
			return mat betas_model=`mbw'
			return mat exp_y_true=`AYM'
			if "`xmat'"!="" {
				mat `EYM'=`Xmod'*`MbetaT''
				return mat exp_y_model=`EYM'
			}

		}
	}

	return mat trtbeta_true=`tb'
	return mat trtbeta_model=`tba'


		if "`trtspec'"=="slope" | "`trtspec'"=="intercept" | "`trtspec'"=="lateslope" | "`trtspec'"=="user" {
			if "`test'"=="paired"  { // secret power option ("paired") for doing a paired z-test - just using the cont intercept variance
				local trtpos=`contvar'
				local b_var=`B_var'[`trtpos',`trtpos']
				mat `effsz'=`tteM'/sqrt(`b_var')
			}
			else {
				local trtpos=`contvar'+1
				local b_var=`B_var'[`trtpos',`trtpos']
				if `b_var'!=0 mat `effsz'=`tteM'/sqrt(`b_var')
				mat `effsz'=`tteM'/sqrt(`b_var')
			}
			local trteff=`tteM'[1,1]
		}


**# LC TEST
		if "`trtspec'"=="slint" | "`trtspec'"=="2slope" | "`trtspec'"=="factor" | "`trtspec'"=="factor0" | "`trtspec'"=="user2" {


			 if strmatch("`test'","joint(*)")==0 {

				tempname testlc lincom  bvartr varlc
				mat `testlc'=J(1,`altvar',0)
				forvalues tst=1/`altvar' {
					local testlc`tst': word `tst' of `test'
					mat `testlc'[1,`tst']=`testlc`tst''
				}

				mat `lincom'=J(1,1,0)
				mat `lincom'=`testlc'*`tteM''

				mat `bvartr'=`B_var'[`=`contvar'+1'..`=`contvar'+`altvar'',`=`contvar'+1'..`=`contvar'+`altvar'']
				mat `varlc'=`testlc'*`bvartr'*`testlc''
				mat `effsz'=`lincom'*invsym(cholesky(`varlc'))
				local b_var=`varlc'[1,1]
				local trteff=`lincom'[1,1]
				return mat test_lc=`testlc'
			}


			local effsize=`effsz'[1,1]

**# JOINT TEST
		 if strmatch("`test'","joint(*)")==1 { // joint test chi2  statistic calculation
				tempname b_jt R_jt Rtrt W_jt	testjt wchi2 dfjt
				mat `b_jt'=J(`=`contvar'+`altvar'',1, 0) // create bx1 matrix of joint test difference values - included the control variables but have them always zero, so don't have to recreate variance matrix

				mat `R_jt'=J(`=`contvar'+`altvar'',`=`contvar'+`altvar'',0)
				forvalues jt=1/`altvar' {
					local testjt`jt': word `jt' of `joint'
					mat `b_jt'[`=`contvar'+`jt'',1]=`tteM'[1,`jt']
					mat `R_jt'[`=`contvar'+`jt'',`=`contvar'+`jt'']=`testjt`jt''

				}
			mat `W_jt'=(`R_jt'*`b_jt')'*invsym(`R_jt'*`B_var'*`R_jt'')*(`R_jt'*`b_jt')
			mat `Rtrt'=vecdiag(`R_jt'[`=`contvar'+1'..`=`contvar'+`altvar'',`=`contvar'+1'..`=`contvar'+`altvar''])
			return mat test_jt=`Rtrt'
			scalar `wchi2'=`W_jt'[1,1]
			return scalar w_chi2=`wchi2'
			scalar `dfjt'=`df_jt'
			return scalar df_jt=`dfjt'
			}

		} // end factor, factor0, slint, 2lsope loop

	 * just for non-test versions

			local effsize=`effsz'[1,1]

		*mat bmodel=(r(beta_var))*r(xmat)'*(invsym(r(rmat)+r(zmat)*r(gmat)*r(zmat)'))*r(actual_y)	// if want to check model beta

	****************************************************************************
**# MAIN RESULTS
	*** CALCULATE THE MAIN RESULT: Either sample size or power
	* first for z tests with effect size then if chi2 joint test, no effsize
	qui tempname  sampfactor alpha_tail sampsize sampsize_C sampsize_T power z_power frac_ss frac_power


	if strmatch("`test'","joint(*)")==0 {


		if "`power_or_n'"=="power" { // Calc SAMPLE SIZE
			scalar `alpha_tail' = 1 - (0.5 * `alpha')
			scalar `sampfactor' = ( invnormal(`alpha_tail') + invnormal(`given_power'))^2
			scalar `sampsize' = 2*ceil( `sampfactor' / (`effsize')^2)*(`arsum'/2)
			scalar `frac_ss' = 2*(`sampfactor' / (`effsize')^2)*(`arsum'/2)
			/*
			if  "`aratio'"!="" {
				scalar `sampsize' = `arsum'*ceil( (`arfactor'*2)*(`sampfactor' / ((`effsize')^2)/`arsum'))
				scalar `frac_ss' = 2*( (`arfactor')*(`sampfactor' / (`effsize')^2))
			}*/
			scalar `sampsize_C' =  ceil(`sampsize'*(`ar1'/`arsum'))
			scalar `sampsize_T' =  ceil(`sampsize'*(`ar2'/`arsum'))
			scalar `frac_power' = `given_power' // Transferring the local into the scalar...
			scalar `power' =normal(( abs(`effsize')*sqrt(`sampsize'/`arsum') ) - invnormal(1-`alpha'/2))
		}

		else { // Calc POWER
			// Calc the power here
			scalar `sampsize' = `actual_n' // As specified by the user; transferring to output scalar
			scalar `frac_ss' = `given_n'
			scalar `sampsize_C' = `actual_n'*(`ar1'/`arsum')
			scalar `sampsize_T' = `actual_n'*(`ar2'/`arsum')
			scalar `z_power' = ( abs(`effsize')*sqrt(`actual_n'/`arsum') ) - invnormal(1-`alpha'/2)
			scalar `frac_power' = normal(( abs(`effsize')*sqrt(`given_n'/`arsum') ) - invnormal(1-`alpha'/2))
			/*if  "`aratio'"!="" {
				scalar `z_power' = ( abs(`effsize')*sqrt(`actual_n'/(`arfactor'*2)) ) - invnormal(1-`alpha'/2)
				scalar `frac_power' = normal((abs(`effsize')*sqrt(`given_n'/(`arfactor'*2)) ) - invnormal(1-`alpha'/2))
			}*/
			scalar `power' = normal(`z_power')
		} // (((delta[`i']*`slope')*sqrt(`size')/`B_var1')-invnormal(1-`alpha'))
	}

	if strmatch("`test'","joint(*)")==1 | "`twosided'"!="" {
		if "`twosided'"!="" & "`jttest'"=="" {
			tempname W_jt
			mat `W_jt'=J(1,1,0)
			local df_jt=1
			local w11=`effsz'[1,1]*`effsz'[1,1]
			mat `W_jt'[1,1]=`w11'
			local star *
		}
		local alpha_jt= invchi2tail(`df_jt', `alpha')
		if "`power_or_n'"=="power" {
			scalar `sampsize'=`arsum'*ceil(npnchi2(`df_jt',`alpha_jt',`=1-`given_power'')/`W_jt'[1,1]-.000001) // might need a bit of tolerance adjustment!
			scalar `frac_ss' = `arsum'*(npnchi2(`df_jt',`alpha_jt',`=1-`given_power'')/`W_jt'[1,1]-.000001)
			scalar `sampsize_C' =  ceil(`sampsize'*(`ar1'/`arsum'))
			scalar `sampsize_T' =  ceil(`sampsize'*(`ar2'/`arsum'))
			scalar `power' = 1-nchi2(`df_jt',`W_jt'[1,1]*`sampsize'/`arsum',`alpha_jt')
			scalar `frac_power' = `given_power'
		}
		else {
			scalar `power'=1-nchi2(`df_jt',`W_jt'[1,1]*`actual_n'/`arsum',`alpha_jt')
			if `power'==. scalar `power'=1
			scalar `frac_power'=1-nchi2(`df_jt',`W_jt'[1,1]*`given_n'/`arsum',`alpha_jt')
			if `frac_power'==. scalar `frac_power'=1
			scalar `sampsize' = `actual_n'
			scalar `frac_ss' = `given_n'
			scalar `sampsize_C' = `actual_n'*(`ar1'/`arsum')
			scalar `sampsize_T' = `actual_n'*(`ar2'/`arsum')
		}
	}

**# DISPLAY
***** DISPLAY OUTPUT SECTION ****************

			local schedrd
			forvalues t=1/`sched_length' {
				local schrd_`t': word `t' of `schedule'
				if mod(`schrd_`t'',0.1)!=0 local schrd_`t': di %3.2f `schrd_`t''
				else if mod(`schrd_`t'',1)!=0 local schrd_`t': di %2.1f `schrd_`t''
				local schedrd "`schedrd' `schrd_`t''"
			}
			local diffrd
			forvalues d=1/`difflength' {
				local diffrd_`d': word `d' of `difference'
				if mod(`diffrd_`d'',0.1)!=0 local diffrd_`d': di %3.2f `diffrd_`d''
				else if mod(`diffrd_`d'',1)!=0 local diffrd_`d': di %2.1f `diffrd_`d''
				local diffrd "`diffrd' `diffrd_`d''"
			}

			if "`actualtrt'"!="" local attext " {it:but with actual} {hi:`actualtrt'} {it:treatment effect}"
			local offset 25
			di  "{hline}"
			if "`power_or_n'"=="n" local calc_PorN power
			if "`power_or_n'"=="power" local calc_PorN sample size
			di _n as text "Calculating {hi:`calc_PorN'} for a {hi:2-level} mixed model with {hi:`trtspec'} treatment effect parameterisation`attext':"
			di _s(2) as text "visit schedule" _col(`=`offset'-2') "="  _col(`=`offset'-1') as res "`schedrd'"
			di _s(2) as text "treatment effect(s)" _col(`=`offset'-2') "="  _col(`=`offset'-1') as res "`diffrd'"
			di _s(2) as text "alpha`star'" _col(`=`offset'-2') "="  _col(`offset') as res %4.3f `alpha'
			di _s(2) as text "total sample size"  _col(`=`offset'-2') "="  _col(`offset') as res `sampsize'
			di _s(2) as text "n in control arm"  _col(`=`offset'-2') "="  _col(`offset') as res `sampsize_C'
			di _s(2) as text "n in treatment arm"  _col(`=`offset'-2') "="  _col(`offset') as res `sampsize_T'
			di _s(2) as text "power"  _col(`=`offset'-2') "="  _col(`offset') as res %5.4f  `power'


			if "`strecruitment'"!="" local table yes
			if "`dropouts'"!="" local table yes


**# TABLE DISPLAY
			*if "`table'"=="yes" { // run through it anyway to get matrices

					local Clist
					local Tlist
					local headlist1
					local headlist2
					local cwidth=9
					if `sched_length'>12	local cwidth=6
					tempname CmatN TmatN CmatrdN TmatrdN
					foreach mat in `CmatN' `TmatN' `CmatrdN' `TmatrdN' {
						mat `mat'=J(1,`sched_length',0)
					}
					forvalues i=1/`sched_length' {
						local start=15
						if `i'==1 local sumCN_`i'=`sumpwgts'*`sampsize_C'
						local pwgts_`i': word `i' of `pwgts'

						if `i'>1 local sumCN_`i'=`sumCN_`=`i'-1'' -`pwgts_`=`i'-1''*`sampsize_C'
						local sumCNrd_`i': di %-5.0f abs(`sumCN_`i'')
						local pwgts2_`i': word `i' of `pwgts2'
						if `i'==1 & "`drop2'"!="" local sumTN_`i'=`sumpwgts2'*`sampsize_T'

						if `i'==1 & "`drop2'"=="" local sumTN_`i'=`sumpwgts'*`sampsize_T'

						if `i'>1 local sumTN_`i'=`sumTN_`=`i'-1'' -`pwgts2_`=`i'-1''*`sampsize_T'
						local sumTNrd_`i': di %-5.0f abs(`sumTN_`i'')
						local hdi`i' "visit `i'"
						if `sched_length'>12 local hdi`i' "v_`i'"
						local headlist1 "`headlist1' " _col(`=`start'+`cwidth'*(`i'-1)') "`hdi`i''"

						local h`i': word `i' of `schedule'
						if mod(`h`i'',1)!=0 local hrd`i': di %-2.1f `h`i''
						if mod(`h`i'',1)==0 local hrd`i': di %-1.0f `h`i''
						local hd2i`i' "time=`hrd`i''"
						if `sched_length'>12 local hd2i`i' "t=`hrd`i''"
						local headlist2 "`headlist2' " 	_col(`=`start'+`cwidth'*(`i'-1)') "`hd2i`i''"
						local Clist "`Clist' "  _col(`=`start'+`cwidth'*(`i'-1)') "`sumCNrd_`i''"
						local Tlist "`Tlist' " _col(`=`start'+`cwidth'*(`i'-1)') "`sumTNrd_`i''"
						mat `CmatN'[1,`i']=`sumCN_`i''
						mat `TmatN'[1,`i']=`sumTN_`i''
						mat `CmatrdN'[1,`i']=`sumCNrd_`i''
						mat `TmatrdN'[1,`i']=`sumCNrd_`i''

					}
				*}


	if "`notable'"=="" {
		if "`strecruitment'"!="" local table yes
		if "`dropouts'"!="" local table yes

		if `sched_length'<=20 {
			if "`table'"=="yes" {
				local line =12
				di _n as text "Table of control and treatment group numbers (rounded) reaching each visit:"
					di  _col(`line') "{c |}"	"`headlist1'"
					di  _col(`line') "{c |}"	"`headlist2'"
					di  _dup(`=`line'-1') "{c -}" _col(`line') "{c +}"	_dup(`=`cwidth'*`=`sched_length'+1'-5') "{c -}"
					di  "control " _col(`line') "{c |}" "`Clist'"
					di  "treatment " _col(`line') "{c |}" "`Tlist'"
				}
			}
	}

**# FINAL RETURNS
	** back to RETURNS

	return matrix trtrd_num=`TmatrdN'
	return matrix contrd_num=`CmatrdN'
	return matrix trt_num=`TmatN'
	return matrix cont_num=`CmatN'
	return matrix sched_list=`schedmat'


	tempname  var_eff eff teff setrial


	if strmatch("`test'","joint(*)")==0 {
		scalar `setrial'=sqrt(`b_var'/(`sampsize'/`arsum'))
		return scalar se_trial=`setrial'
		scalar `var_eff'=`b_var'
		return scalar var_trteff=`var_eff'
		scalar `teff'=`trteff'
		return scalar trt_eff=`teff'
		scalar `eff'=`effsize'
		return scalar effectsize=`eff'
	}

	return local final_wgts `"`pwgts'"'
	return scalar power=`power'
	return scalar fractional_power=`frac_power'
	return scalar samplesize=`sampsize'
	return scalar fractional_ss=`frac_ss'
	return local schedule "`schedule'"
	return local cmd mixedpower
	return local cmdline `"mixedpower `0'"'


	frame change `cframe'



end


**# OTHER PROGRAMS

capture program drop err198
	prog def err198
	di as error `"`0'"'
	exit 198
	end

capture program drop extabcheck
	program extabcheck, sclass
		version 17.0

		syntax, [INDependent EXChangeable ar ma  UNstructured BAnded TOeplitz EXPonential]
		sreturn clear
		foreach ext in independent exchangeable ar ma unstructured banded toeplitz exponential {
			if "``ext''"!="" local newext `ext'
		}
		sreturn local exttype `newext'
	end

capture program drop xslopecheck
program xslopecheck, sclass
	version 17.0

	syntax, xnum(string) option(string) spec(string)

					capture confirm number `xnum'
						if _rc!=0 {
							dis as error "time value supplied with `option'(`spec') option must be a real number"
							exit 198
					}
					capture assert `xnum'>=0
						if _rc!=0 {
							dis as error "time value supplied with `option'(`spec') option must be a real number >=0"
							exit 198
					}

end

capture program drop testcheck
program testcheck, sclass
	version 17.0

	syntax,  tsp(string) schl(numlist integer >=1 min=1 max=1) [test(string) xtra(string)]

	if "`test'"=="" {
			dis as error  "jttest() or lctest() must be specified when trtspec() is '`tsp''"
			exit 198
	}
	numlist "`test'"
	local test=r(numlist)

	local contentslength : word count `test'
			if "`tsp'"=="factor0" {
								if `contentslength' != `schl' {
					dis as error  "content list length for test(`xtra')=`contentslength' when trtspec() is '`tsp'' must be same as visit schedule=`schl'"
					exit 198
				}
			}
			if "`tsp'"=="factor" {
								if `contentslength' != `schl'-1 {
					dis as error  "content list length for test(`xtra')=`contentslength' when trtspec() is '`tsp'' must be one less than for visit schedule=`schl'"
					exit 198
				}
			}
			if "`tsp'"=="slint" | "`trtspec'"=="2slope" | "`trtspec'"=="user2" {
								if `contentslength' != 2 {
					dis as error  "content list length for test(`xtra'=`contentslength') when trtspec() is '`tsp'' must be 2"
					exit 198
				}
			}

				forvalues d=1/`contentslength' {
					local contents`d' : word `d' of `test'
					capture confirm number `contents`d''
						if _rc!=0 {
							dis as error "content list for test() must be specified as number values"
							exit 198
					}
				}
end

capture program drop usercheck
program usercheck, sclass
	version 17.0

	syntax,   func(string) option(string) xvalues(numlist)

		sreturn clear

		gettoken finit : func, parse("(") match(br)
		local numfunc=1
		if strmatch("`finit'", "*;*")	{
			local numfunc=2
			gettoken func1 finit: finit, parse(;)
			gettoken comma1 finit: finit, parse(;)
			if strmatch("`finit'", "*;*") {
				di as error "You have tried to specify (by use of semi-colon separation) too many user-defined functions in `option'"
				exit 198
			}
			else local func2 `finit'
		}
		else local func1 `finit'
		tempname _mp_userfunctionscheck
		frame create `_mp_userfunctionscheck'
		frame change `_mp_userfunctionscheck'

		local y1
		local y2
		local sl: word count `xvalues'
		qui set obs `sl'
		qui gen double x=.
		qui gen double yvar1=.
		if `numfunc'==2 qui gen double yvar2=.
		forvalues sch=1/`sl' {
			local xv1`sch': word `sch' of `xvalues'
			*local fn1=subinstr("`func1'","x","`xv1`sch''",.)

			qui replace x=`xv1`sch'' in `sch'
			capture qui replace yvar1=`func1' in `sch'
			if _rc!=0 {
				di as error "user-function_1 provided cannot be evaluated for `option'"
				exit 198
			}

			local y1`sch'=yvar1[`sch']
			if   `y1`sch''==. local y1`sch'=0
			local y1 "`y1' `y1`sch''"
			if `numfunc'==2 {

				capture qui replace yvar2=`func2' in `sch'
				if _rc!=0 {
					di as error "user-function_2 provided cannot be evaluated for `option'"
					exit 198
				}

				local y2`sch'=yvar2[`sch']
				if   `y2`sch''==. local y2`sch'=0
				local y2 "`y2' `y2`sch''"
			}


		}
		sreturn local nfun=`numfunc'
		sreturn local xfun1 "`y1'"
		sreturn local funct1 "`func1'"
		if `numfunc'==2 sreturn local xfun2 "`y2'"
		if `numfunc'==2 sreturn local funct2 "`func2'"
end

capture program drop errxtmixcheck
program errxtmixcheck, sclass
	version 17.0

	syntax,   residt(string) hety(string) hetcheck(string)
		sreturn clear
	if "`hety'"=="yes" {
		if  strmatch("`hetcheck'","* by(*)*") {
			local ehet h
		}
		else {
			di as error "mixed model in memory not fitted with separate error structure by group"
				exit 198
		}
	}

	if  strmatch("`residt'","AR(*)") {
		local restype ar
		local rshort ar
		local nsub= subinstr("`residt'", "AR(", "", 1)
		local nsub= subinstr("`nsub'", ")", "", 1)
		local num=`nsub'
	}
	else if  strmatch("`residt'","MA(*)") {
		local restype ma
		local rshort ma
		local nsub= subinstr("`residt'", "MA(", "", 1)
		local nsub= subinstr("`nsub'", ")", "", 1)
		local num=`nsub'
	}
	else if  strmatch("`residt'","Banded(*)") {
		local restype banded
		local rshort ba
		local nsub= subinstr("`residt'", "Banded(", "", 1)
		local nsub= subinstr("`nsub'", ")", "", 1)
		local num=`nsub'
	}
	else if  strmatch("`residt'","Toeplitz(*)") {
		local restype toeplitz
		local rshort to
		local nsub= subinstr("`residt'", "Toeplitz(", "", 1)
		local nsub= subinstr("`nsub'", ")", "", 1)
		local num=`nsub'
	}
	else if  strmatch("`residt'","Unstructured") {
		local restype unstructured
		local rshort un
		local num=0
	}
	else if  strmatch("`residt'","Exponential") {
		local restype exponential
		local rshort exp
		local num=0
	}
	else if  strmatch("`residt'","Exchangeable") {
		local restype exchangeable
		local rshort ex
		local num=0
	}
	else if  strmatch("`residt'","Independent") {
		local restype independent
		local rshort in
		local num=1
	}
	else {
		di as error "Residual error type not recognised"
		exit 198
	}
	sreturn local residt `restype'
	sreturn local rshort `rshort'
	sreturn local rnum `num'
	sreturn local het `ehet'


end