* Adds Syntax and Excution to stata2mplus * * mar 28 2005 added integration miterations * may 10 2006 fixed parameterization spelling error * Jun 25 2006 added standard Mplus command sections, * making keeping up with Mplus versions * a non-issue so long as new Mplus commands * aren't added. * some Mplus version 2 shortcut command/options * are retained. * Jul 12 2007 Turned off a feature that suppressed appending to variable command * This might mess up montecarlo runs.... * Sep 4 2007 fixed miterations option * Jul 22 2008 Revererted to July 17 2008 version * Oct 28 2008 added define option * DEC 11 2008 KNOWN BUG - when reading parameter estimates, if an IRT model is estimated * (Mplus returns IRT parameter estimates) the matrix of returned parameter * includes duplicate entries, i.e. does distinguish regular parameter * estimates from IRT-scaled parameter estimates. * Jul 27 2009 Adam Carle provided wtscale option * It’s not well known (i.e., not documented in the actual manual), but, * when including weights in multilevel models or complex data, Mplus * automatically scales the weights. For numerous reasons, one may wish * to scale their weights on their own outside the program (e.g., different * scaling methods, same scaling method but using a zero weighting * technique to subpop, etc.). One can tell Mplus not to scale the * weights. But, like I said, the manual doesn’t show it. * I added a bit of code to runmplus to allow this. * Apr 28 2010 Added code for post-processing of models using Bayesian estimation * for Mplus version 6 * Oct 03 2010 Added output processing for Monte Carlo * Feb 15 2011 Added demo4, version5 options * Oct 02 2011 Made it so you don't HAVE to put cluster var in varlist. * Thanks to Tor Neilands * Dec 03 2011 Added some return of fit statistics after EFA * Jun 05 2012 Fixed parsing of priors in model statement * Jun 17 2012 Added extraction of Tech 11 and Tech 14 results * Jul 30 2013 Fixed version call bug * Aug 19 2013 Addressed classname in r(estimate) under LCA/Bayes * Aug 20 2013 Added model missing for montecarlo runs * Aug 21 2013 Fixed how bayesian estimation is determined for post-processing * Oct 14 2013 Added extract of wald test of parameter constraints * Nov 16 2013 Added po(string) option, to process output only * Nov 16 2013 Fixed issue in read_convergence. Mplus apparently no longer automatically * reports when the model estimation terminates normally, in all model types * Nov 22 2013 Added Data Missing command * Jan 01 2015 Added aux shortcut * Mar 01 2015 Added read_parameterestimates_indirect which reads and returns MODEL INDIRECT output * Jun 13 2019 Update contributed to SSC. Minor bug fixes. capture program drop runmplus program define runmplus , rclass version 10 #d ; syntax [varlist] [if] [in] , [ debug po(string) TScores(string) TItle(string) DATa(string) DATAMissing(string) VARiable(string) DEFine(string) ANalysis(string) MOdel(string) OUTput(string) SAVEdata(string) PLOT(string) MONTECARLO(string) DATAIMPUTATION(string) MC(string) SAVEINPutfile(string) SAVELOGfile(string) SAVEINPUTDATAfile(string) log(string) SUBPOPulation(string) STRATification(string) wgt(string) wtscale(string) CLUSter(string) variance(string) iterations(string) sditerations(string) h1iterations(string) miterations(string) mciterations(string) muiterations(string) convergence(string) h1convergence(string) coverage(string) logcriterion(string) mconvergence(string) mcconvergence(string) muconvergence(string) mixc(string) mixu(string) loghigh(string) loglow(string) ucellsize(string) algorithm(string) integration(string) missing(int -9999) NGroups(string) CATegorical(string) tech(string) GROUPing(string) IDvariable(string) within(string) between(string) centering(string) type(string) ESTimator(string) MATrix(string) PARAMeterization(string) MODindices(string) population(string) AUXiliary(string) CLASSes(string) modelmissing(string) * ] ; #d cr if "`aux'" ~= "" & "`auxiliary'" == "" { local auxiliary "`aux'" } #d ; if "`debug'"=="debug" { ; noisily di in green "debugging mode: review of submitted options" _n ; foreach x in algorithm analysis auxiliary aux between categorical centering classes cluster convergence coverage data dataimputation datamissing debug define estimator grouping h1convergence h1iterations idvariable if in integration iterations log logcriterion loghigh loglow matrix mc mcconvergence mciterations mconvergence missing miterations mixc mixu model modelmissing modindices montecarlo muconvergence muiterations ngroups output parameterization plot po population savedata saveinputdatafile saveinputfile savelogfile sditerations stratification subpopulation tech title tscores type ucellsize variable variance varlist wgt within wtscale options { ; if "`x'"~="" { ; di _col(5) in green "`x'" _col(23) "->" _col(27) in yellow "``x''" ; } ; /* close if */ } ; /* close foreach x */ } ; /* close if debug */ #d cr local omatsize=`c(matsize)' if "`po'"=="" { // only do the model setup and running mplus steps if po option not specified * po option will skip right to the output processing of the file specified in the (string) * part of po * RNJ 2013 Nov 16 preserve local varlist "`varlist' `cluster' `auxiliary' `aux' `idvariable' " local varlist : list uniq varlist local numvars = wordcount("`varlist'") local novarlist=0 if `numvars'==0 { local novarlist=1 } * 18-May-2010 * too many options, had to move to anything foreach x in /// SAMPStat samps /// STANDardized stand /// RESidual res /// FSDETerminacy fsdet /// FSCOEFficeint fscoef /// CINTerval cint /// NOCHIsquare nochi /// H1TEch3 h1te /// PATterns pat /// h1se varnocheck /// demo7 demo6 demo4 /// version5 version6 /// debug /// extractmatrices { local foo=lower("`x'") if regexm(lower("`options'"),lower("`x'"))==1 { local `foo' = "`x'" } } if "`debug'"=="debug" { di in green "demo5" _col(20) " -> " in yellow "`demo5'" di in green "demo6" _col(20) " -> " in yellow "`demo6'" di in green "demo7" _col(20) " -> " in yellow "`demo7'" di in green "version3" _col(20) " -> " in yellow "`version3'" di in green "version4" _col(20) " -> " in yellow "`version4'" di in green "version5" _col(20) " -> " in yellow "`version5'" di in green "version6" _col(20) " -> " in yellow "`version6'" } local agrp "samps stand res fsdet fscoef cint noch h1te pat" local bgrp "sampstat standardized residual fsdeterminacy fscoefficeint cinterval nochisquare h1tech3 patterns" local n : word count `agrp' forvalues i = 1/`n' { local a : word `i' of `agrp' local b : word `i' of `bgrp' if "``a''"=="`a'" { local `b' = "`b'" } } * check for summary data, monte carlo #d ; if "`mc'"~="" | "`montecarlo'"~="" | strpos("`data'","imputation")>0 | strpos("`data'","montecarlo")>0 | strpos("`data'","covar")>0 | strpos("`data'","corr")>0 | strpos("`data'","fullc")>0 | strpos("`data'","means")>0 | strpos("`data'","std")>0 { ; *local novarlist=1 ; *local varlist="" ; } ; #d cr *flag for data type imputation lstrfun isdatatypeimputation, strpos(`"`data'"', "imputation") if `isdatatypeimputation'~=0 { local isdatatypeimputation = 1 } * if a montecarlo run is requested, strike the varlist * or if type=imputation if ("`mc'"~="" | "`montecarlo'"~="") { local varlist = "" } if "`isdatatypeimputation'"=="1" { local varlist = "" local novarlist=1 } if "`varlist'"~="" | "`novarlist'"~="1" { qui marksample touse, novarlist qui keep if `touse' order `varlist' keep `varlist' * convert char to numeric foreach var of local varlist { local vartype : type `var' if (substr("`vartype'",1,3)=="str") { display "encoding `var'" tempvar tempenc encode `var', generate(`tempenc') drop `var' rename `tempenc' `var' } * added 6-27-2008 if (substr("`vartype'",1,3)~="str") { qui recast float `var' } } foreach var of local varlist { quietly replace `var' = `missing' if `var' >= . } tempname using *capture erase `using'.dat qui outsheet `varlist' using `using'.dat , comma nonames nolabel replace } * added 5/31/2011 if "`using'"=="" { tempname using } tempvar out qui { capture file close `out' capture erase `using'.inp file open `out' using "`using'.inp", write text } * * ------------------- TITLE ------------------- * file write `out' "TITLE: " _newline if "`title'"~="" { lw , out(`out') line(`"`title'"') } if "`varlist'"~=""|"`novarlist'"=="1" { file write `out' " Variable List - " _newline file write `out' _newline quietly count local ncases = `r(N)' foreach var of local varlist { makelab `var' `out' `ncases' } file write `out' " " _newline * * ------------------- DATA * file write `out' "DATA: " _newline * added 10-5-2006 if "`varnocheck'"=="varnocheck" { file write `out' " VARIANCES = nocheck ; " _newline } if "`varlist'"~="" | "`novarlist'"~="1" { file write `out' " FILE = `pwd'""`using'.dat ;" _newline local wrotedata=1 } if "`data'"~="" { if strpos("`data'","file")==0 { if "`wrotedata'"~="1" { file write `out' " FILE = `pwd'""`using'.dat ;" _newline } } } if "`data'"~="" { tokenize `data' , parse(";") while "`1'"~="" { if "`1'"~=";" { *file write `out' " `1' ; " _n lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * ------------------- VARIABLE * * added July 26 2007 * Checkpoint - if variable is not blank but does not include the * names option, then we presume what is in variable is to be appended * to what is automatically generated by runmplus. Otherwise, we parse out * what is in the variable command and ignore automatically generated stuff local test278=0 if "`montecarlo'"~="" { // added 12-15-2011 local test278=1 } if "`varlist'"=="" { local test278=1 } *if regexm(lower("`varlist'"),"name")==0 { * local test278=1 *} if "`isdatatypeimputation'"=="1" { local test278=1 } *noisily { * foreach x in montecarlo varlist isdatatypeimputation test278 { * di "`x'" _col(30) "-> ``x''" * } *} *if ("`variable'"=="" | regexm(lower("`variable'"),"name")==0) /// * | "`isdatatypeimputation'"=="1" { if "`test278'"~="1" { *noisily di in red "got here" file write `out' "VARIABLE:" _newline if "`varlist'"~="" { file write `out' " NAMES = " _newline " " local len = 0 lw , out(`out') line(`"`varlist'"') } file write `out' " MISSING ARE ALL (`missing') ; " _newline if regexm(lower("`variable'"),"usevar")==0 { ** 03/15/2011 ** Added option to put in usevariables if aux is specified if "`auxiliary'" ~= "" { local avars "`varlist'" local avars : list avars - auxiliary local avars : list avars - idvariable file write `out' " USEVARIABLES =" _newline " " local len = 0 lw , out(`out') line(`"`avars'"') } } if "`categorical'"~="" { file write `out' " CATEGORICAL = " _newline tokenize `categorical' while "`1'"~="" { file write `out' " `1'" _newline mac shift 1 } file write `out' " ;" _n } if "`grouping'"~="" { file write `out' " GROUPING = " lw , out(`out') line(`"`grouping'"') } if "`idvariable'" ~= "" { file write `out' " IDVARIABLE = `idvariable' ;" _newline } if "`wgt'" ~= "" { file write `out' " weight = `wgt' ;" _newline } if "`wtscale'" ~= "" { file write `out' " wtscale = `wtscale' ;" _newline } if "`cluster'" ~= "" { file write `out' " CLUSTER = `cluster' ;" _newline } if "`subpopulation'" ~= "" { file write `out' " SUBPOPULATION = `subpopulation' ;" _newline } if "`stratification'" ~= "" { file write `out' " STRATIFICATION = `stratification' ;" _newline } if "`within'" ~= "" { file write `out' " WITHIN = " _n lw , out(`out') line(`"`within'"') } if "`between'" ~= "" { *file write `out' " BETWEEN = `between' ;" _newline file write `out' " BETWEEN = " _n lw , out(`out') line(`"`between'"') } if "`tscores'" ~= "" { *file write `out' " TSCORES = `tscores' ;" _newline file write `out' " TSCORES = " _n lw , out(`out') line(`"`tscores'"') } * added 6-10-2008 if "`auxiliary'" ~= "" { *** 2-24-2011 file write `out' " AUXILIARY = `auxiliary' ;" _newline file write `out' " AUXILIARY = " _newline lw , out(`out') line(`"`auxiliary'"') } * end edited 6-10-2008 if "`centering'" ~= "" { file write `out' " CENTERING = `centering' ;" _newline } if "`patternvariable'" ~= "" { file write `out' " PATTERNVARIABLE = `patternvariable' ;" _newline } if "`cohort'" ~= "" { file write `out' " COHORT = `cohort' ;" _newline } if "`copattern'" ~= "" { file write `out' " COPATTERN = `copattern' ;" _newline } if "`cohrecode'" ~= "" { file write `out' " COHRECODE = `cohrecode' ;" _newline } if "`timemeasures'" ~= "" { file write `out' " TIMEMEASURES = `timemeasures' ;" _newline } if "`tnames'" ~= "" { file write `out' " TNAMES = `tnames' ;" _newline } if "`classes'" ~= "" { file write `out' " CLASSES = `classes' ;" _newline } if "`training'" ~= "" { file write `out' " TRAINING = `training' ;" _newline } if "`ttype'" ~= "" { file write `out' " TTYPE = `ttype' ;" _newline } } if "`variable'"~="" { * VARIABLE: only gets written if variable is not blank AND DOES * include the keyword name if regexm(lower("`variable'"),"name")==1 { file write `out' "VARIABLE:" _newline } tokenize `variable' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * * ------------------- DEFINE * if "`define'"~="" { file write `out' "DEFINE: " _newline tokenize `define' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } } // closes the condition on a varlist being specified * * ------------------- ANALYSIS * file write `out' "ANALYSIS: " _newline foreach field in /// type estimator matrix parameterization /// variance iterations sditerations h1iterations /// miterations mciterations muiterations /// convergence h1convergence coverage logcriterion /// mconvergence mcconvergence muconvergence mixc /// mixu loghigh loghigh loglow /// ucellsize algorithm integration { if "``field''"~="" { local __x1 = upper("`field'") file write `out' " `__x1' = ``field'' ;" _newline } } if "`analysis'"~="" { tokenize `analysis' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * * ------------------- OUTPUT * file write `out' "OUTPUT: " _newline if "`modindices'"~="" { file write `out' " MODINDICES(`modindices'); " _n } foreach field in /// sampstat standardized residual cinterval nochisquare /// h1se h1tech3 patterns fscoefficeint fsdeterminacy { if "``field''"~="" { local __x1 = upper("`field'") file write `out' " `__x1' ;" _newline } } if "`tech'"~="" { tokenize `tech' while "`1'"~="" { file write `out' " TECH`1' " _newline mac shift 1 } } if "`output'"~="" { tokenize `output' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * * ------------------- PLOT * if "`plot'"~="" { file write `out' "PLOT: " _newline tokenize `plot' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * * ------------------- SAVEDATA * if "`savedata'"~="" { file write `out' "SAVEDATA: " _newline tokenize `savedata' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * * ------------------- MONTECARLO * if "`montecarlo'"~="" & "`mc'"~="" { di in red "please use the montecarlo command or the mc command, not both" exit } if "`montecarlo'"~="" { file write `out' "MONTECARLO: " _newline tokenize `montecarlo' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } if "`mc'"~="" { file write `out' "MONTECARLO: " _newline tokenize `mc' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * ADDED 7-27-2006 * * ------------------- MODEL POPULATION * ***** file write `out' "MODEL: " _newline ***** tokenize "`model'" , parse(";") ***** while "`1'"~="" { ***** if "`1'"~=";" { ***** lw , out(`out') line(`"`1'"') ***** } ***** mac shift 1 ***** } ***** file write `out' " " _newline ***** file close `out' ***** ***** if "`population'"~="" { file write `out' "MODEL POPULATION: " _newline tokenize "`population'" , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * ADDED 11-22-2013 * * ------------------- Data MISSING * if "`datamissing'"~="" { file write `out' "DATA MISSING: " _newline tokenize `datamissing' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * ADDED 8-20-2013 * * ------------------- MODEL MISSING * if "`modelmissing'"~="" { file write `out' "MODEL MISSING: " _newline tokenize `modelmissing' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * ADDED 8-30-2011 * * ------------------- DATA IMPUTATION * if "`dataimputation'"~="" { file write `out' "DATA IMPUTATION: " _newline tokenize `dataimputation' , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline } * * ------------------- MODEL * file write `out' "MODEL: " _newline tokenize "`model'" , parse(";") while "`1'"~="" { if "`1'"~=";" { lw , out(`out') line(`"`1'"') } mac shift 1 } file write `out' " " _newline file close `out' * 7-23-2008 * edit the inp file to accomodate % **** qui { tempname newusing capture erase `newusing'.inp **** filefilter `using'.inp `newusing'.inp , from("% ;") to("%") replace local nchanges = r(occurrences) if `nchanges'>0 { erase `using'.inp while `nchanges'~=0 { filefilter `newusing'.inp `using'.inp , from("% ;") to("%") replace filefilter `using'.inp `newusing'.inp , from("% ;") to("%") replace local nchanges = r(occurrences) } } erase `using'.inp qui copy `newusing'.inp `using'.inp erase `newusing'.inp **** filefilter `using'.inp `newusing'.inp , from("%;") to("%") replace local nchanges = r(occurrences) if `nchanges'>0 { erase `using'.inp while `nchanges'~=0 { filefilter `newusing'.inp `using'.inp , from("%;") to("%") replace filefilter `using'.inp `newusing'.inp , from("%;") to("%") replace local nchanges = r(occurrences) } } erase `using'.inp qui copy `newusing'.inp `using'.inp erase `newusing'.inp **** filefilter `using'.inp `newusing'.inp , from(\037d) to("#$#") replace filefilter `newusing'.inp `using'.inp , from("#$# ") to(\037d\W) replace filefilter `using'.inp `newusing'.inp , from("#$#") to(\037d) replace erase `using'.inp qui copy `newusing'.inp `using'.inp erase `newusing'.inp **** filefilter `using'.inp `newusing'.inp , from(\W\W\W) to(\W\W) replace local nchanges = r(occurrences) if `nchanges'>0 { erase `using'.inp while `nchanges'~=0 { filefilter `newusing'.inp `using'.inp , from(\W\W\W) to(\W\W) replace filefilter `using'.inp `newusing'.inp , from(\W\W\W) to(\W\W) replace local nchanges = r(occurrences) } } erase `using'.inp qui copy `newusing'.inp `using'.inp erase `newusing'.inp } if "`saveinputfile'"~="" { if "`saveinputdatafile'"~="" { saveinp , using(`using') saveinputfile(`saveinputfile') saveinputdatafile(`saveinputdatafile') } else { saveinp , using(`using') saveinputfile(`saveinputfile') } } * end of new stuff 7-23-2008 ** ===================================================== SEND TO MPLUS (Line 616) * ------------------- RUN mplus * demo6 option added 5-17-2010 * demo4 option added 2-14-2011 * version5 option added 2-15-2011 * version6 option added 10-3-2012 * if demo6 is not specified, we'll run a little check anyways /* Retired this section 5-1-2013 if "`demo7'"~="demo7" |"`demo6'"~="demo6" | "`demo4'"~="demo4" { capture confirm file C:\PROGRA~1\MPLUS\Mplus.exe if _rc~=0 { capture confirm file C:\PROGRA~2\MPLUS\Mplus.exe if _rc~=0 { capture confirm file C:\PROGRA~1\MPLUSD~1\Mpdemo6.exe if _rc~=0 { capture confirm file C:\PROGRA~2\MPLUSD~1\Mpdemo6.exe if _rc==0 { local demo6 = "demo6" } capture confirm file C:\PROGRA~1\MPLUSD~1\Mpdemo7.exe if _rc~=0 { capture confirm file C:\PROGRA~2\MPLUSD~1\Mpdemo7.exe if _rc==0 { local demo7 = "demo7" } if _rc~=0 { di in red "Can't find mplus.exe or mpdemo#.exe" } } } } } } if "`demo7'"~="demo7" /// & "`demo6'"~="demo6" /// & "`demo4'"~="demo4" /// & "`demo5'"~="demo5" /// & "`version5'" ~= "version5" /// & "`version6'" ~= "version6" { !mplus `using'.inp } if "`version5'"=="version5" { !mplus5 `using'.inp } if "`version6'"=="version6" { !mplus6 `using'.inp } if "`demo6'"~="" & "`demo4'"~="" & "`version5'"~="" | { di in red "only one demo and/or version can be run at a time" exit } if "`demo7'"=="demo7" | "`demo6'"=="demo6" | "`demo4'"=="demo4" { local ver=substr(reverse(itrim("`demo7'`demo6'`demo4'")),1,1) capture confirm file C:\PROGRA~1\MPLUSD~1\Mpdemo`ver'.exe if _rc==0 { !C:\PROGRA~1\MPLUSD~1\Mpdemo`ver' `using'.inp } if _rc~=0 { di in red "can't find the Mpdemo`ver'.exe file, which I thought would" _n /// "be in c:\program files\mplus demo\. You might consider" _n /// "making sure that file exists in this location. If it exists" _n /// "in another location, determine what that is and make the" _n /// "appropriate edit to the runmplus.ado file, line #590." } } */ * find Mplus executable * Windows only if "`c(os)'"~="Windows" { if "$mplus_path"=="" { global mplus_path "/applications/mplus/mplus" local mplusexe "/applications/mplus/mplus" } else { local mplusexe "$mplus_path" } } if "$mplus_path"=="" { // if the mplus_path has not be set, for example in profile.do cap confirm file c:\progra~1\mplus\mplus.exe if _rc==0 { global mplus_path "c:\progra~1\mplus\mplus.exe" } if _rc~=0 { cap confirm file c:\progra~2\mplus\mplus.exe if _rc==0 { global global mplus_path "c:\progra~2\mplus\mplus.exe" } } } * demo version forvalues i=4/7 { if ("$mplus_path"=="" | "$mplusdemo`i'_path"=="")|"`demo`i''"~="" { foreach j in 1 2 { cap confirm file c:\progra~`j'\mplusd~1\mpdemo`i'.exe if _rc==0 { if "$mplus_path"=="" { global mplus_path "c:\progra~`j'\mplusd~1\mpdemo`i'.exe" } global mplusdemo`i'_path "c:\progra~`j'\mplusd~1\mpdemo`i'.exe" if "`demo`i''"=="demo`i'" { // if demo version specifically requested if `i'==4 { local mplusexe "$mplusdemo4_path" } if `i'==5 { local mplusexe "$mplusdemo5_path" } if `i'==6 { local mplusexe "$mplusdemo6_path" } if `i'==7 { local mplusexe "$mplusdemo7_path" } } } } } } * legacy version if "`version1'"=="version1" { // if old version specifically requested if "$mplus1_path"=="" { // only if path to old version not already set, for e.g., in profile.do foreach j in 2 1 { cap confirm file c:\progra~`j'\mplus1\mplus.exe if _rc==0 { global mplus1_path "c:\progra~`j'\mplus1\mplus.exe" } } } local mplusexe "$mplus1_path" } if "`version2'"=="version2" { // if old version specifically requested if "$mplus2_path"=="" { // only if path to old version not already set, for e.g., in profile.do foreach j in 2 1 { cap confirm file c:\progra~`j'\mplus2\mplus.exe if _rc==0 { global mplus2_path "c:\progra~`j'\mplus2\mplus.exe" } } } local mplusexe "$mplus2_path" } if "`version3'"=="version3" { // if old version specifically requested if "$mplus3_path"=="" { // only if path to old version not already set, for e.g., in profile.do foreach j in 2 1 { cap confirm file c:\progra~`j'\mplus3\mplus.exe if _rc==0 { global mplus3_path "c:\progra~`j'\mplus3\mplus.exe" } } } local mplusexe "$mplus3_path" } if "`version4'"=="version4" { // if old version specifically requested if "$mplus4_path"=="" { // only if path to old version not already set, for e.g., in profile.do foreach j in 2 1 { cap confirm file c:\progra~`j'\mplus4\mplus.exe if _rc==0 { global mplus4_path "c:\progra~`j'\mplus4\mplus.exe" } } } local mplusexe "$mplus4_path" } if "`version5'"=="version5" { // if old version specifically requested if "$mplus5_path"=="" { // only if path to old version not already set, for e.g., in profile.do foreach j in 2 1 { cap confirm file c:\progra~`j'\mplus5\mplus.exe if _rc==0 { global mplus5_path "c:\progra~`j'\mplus5\mplus.exe" } } } local mplusexe "$mplus5_path" } if "`version6'"=="version6" { // if old version specifically requested if "$mplus6_path"=="" { // only if path to old version not already set, for e.g., in profile.do foreach j in 2 1 { cap confirm file c:\progra~`j'\mplus6\mplus.exe if _rc==0 { global mplus6_path "c:\progra~`j'\mplus6\mplus.exe" ** this was here } } } local mplusexe "$mplus6_path" // now it is here 20130730 if "`debug'"=="debug" { noisily di "version6 was called" noisily di "$mplus6_path <- Mplus version 6 path" noisily di "`mplusexe' <- local mplusexe" } } * Note: * if both a specific version is requested AND a specific demo version requested, * the version trumps the demo call. Here we produce an error notice if * this conflict exists local check813=0 forvalues i=1/12 { // robust to version 12 foreach x in version demo { if "``x'`i''"~="" { local check813=`check813'+1 } } } if `check813'>1 { qui { noisily di in red _n /// " please specify only one legacy version or one demo version" _n } exit } if "`mplusexe'"=="" { local mplusexe "$mplus_path" } if "`mplusexe'"=="" { qui { noisily di in red _n /// " runmplus.ado can't find the right mplus executable" _n /// " after looking in some likely places. You can avoid this" _n /// " error by setting a global called mplus_path in your " _n /// " profile.do See example at " noisily di as txt `" {browse "https://sites.google.com/site/ifarwf/home/your-profiledo"}"' } exit } * final check to make sure Mplus executable found * windows only if "`c(os)'"=="Windows" { cap confirm file `mplusexe' if _rc~=0 { qui { noisily di in red _n /// " runmplus.ado can't find the right mplus executable" _n /// " after looking in some likely places. You can avoid this" _n /// " error by setting a global called mplus_path in your " _n /// " profile.do See example at " noisily di as txt `" {browse "https://sites.google.com/site/ifarwf/home/your-profiledo"}"' } exit } } * end of looking for Mplus executable * run Mplus !`mplusexe' `using'.inp * Not sure if I need this bracket x}x } // this closes the if po!="" condition * new 20131116 if "`po'"~="" { preserve * if po is specified, take that file specified in string and and use it as the output tempname using qui copy `po' `using'.out , replace public if "`debug'"=="debug" { noisily di in red "GOt here" noisily di "local po -> `po'" noisily di "local using -> `using'.out" noisily cap confirm file `using'.out } * isdatatypeimputation if "`isdatatypeimputation'"=="" { local isdatatypeimputation=0 * tempname fh local linenum = 0 file open `fh' using `"`using'.out"', read file read `fh' line while r(eof)==0 & "`isdatatypeimputation'"~="1" { local linenum = `linenum' + 1 if regexm(lower(`"`macval(line)'"'),"data imputation")==1 | /// regexm(lower(`"`macval(line)'"'),"multiple data files from")==1 { local isdatatypeimputation=1 local foo=1 return local fooisdatatypeimputation `foo' } file read `fh' line } file close `fh' } } * 5/15/2011 added read_errors * di `"read_errors `using'.out"' read_errors `using'.out if "`r(error)'"=="1" { exit } * ------------------- SAVE OUTPUT FILE IF REQUESTED TO DO SO if "`savelogfile'"~="" { qui copy `using'.out "`savelogfile'.out" , replace // thanks to Elan Cohen MS } ************************************************************************************ ************************************************************************************ ************************************************************************************ ************************** *************************** ************************** START OF OUTPUT PROCESSING *************************** ************************** *************************** ************************************************************************************ ************************************************************************************ ************************************************************************************ ************************************************************************************ **** Added 20101003 montecarlo condition ** need seperate processing of multiple imputation output if `isdatatypeimputation'==1 { qui infix str line 1-85 using `using'.out , clear *qui infix str line 1-85 using trash.out , clear format line %85s gen linenum=_n * fit statistics gen numberofsuccessfulcomputations=linenum if substr(line,1,33)=="Number of successful computations" qui levelsof numberofsuccessfulcomputations , clean if "`debug'"=="debug" { di in red "inside multiple imputation output processing" di in red "`r(levels)'" } foreach x in `r(levels)' { local w=`x'-4 local fitstat=lower(word(line[`w'],1)) if "`debug'"=="debug" { noisily di "`fitstat'<-fitstat" } if "`fitstat'"~="" { if substr("`fitstat'",1,7)=="degrees" { local fitstat="chisquare" local chisquaredf=substr("`fitstatline'",42,10) } local w=`w'+2 local fitstatmean=reverse(word(reverse(line[`w']),1)) local w=`w'+1 local fitstatsd=reverse(word(reverse(line[`w']),1)) local w=`w'+1 local fitstatnsc=reverse(word(reverse(line[`w']),1)) return local `fitstat' = `fitstatmean' return local `fitstat'sd = `fitstatsd' return local `fitstat'nsc = `fitstatnsc' } } * new 10-16-2013 * wald test local i=0 while `i'<`c(N)' { if substr(trim(line[`++i']),1,34)=="Wald Test of Parameter Constraints" { local j=`i'+2 local k=`i'+3 local l=`i'+4 return local WaldTest = reverse(word(reverse(line[`j']),1)) return local WaldTest_df = reverse(word(reverse(line[`k']),1)) return local WaldTest_P = reverse(word(reverse(line[`l']),1)) local i=`c(N)' } } local i=0 while `i'<`c(N)' { if substr(trim(line[`++i']),1,25)=="Number of Free Parameters" { return local free_parameters = reverse(word(reverse(line[`i']),1)) local i=`c(N)' } } **** local MS=_N **** if `ms'>800 { **** capture set matsize `MS' **** } if "`debug'"=="debug" { noisily di in yellow _n "This is line 1252 of runmplus.ado and" /// _n "you are about to call " in green "read_parameterestimates_general" _n _n } read_parameterestimates_general , out(`using'.out) `debug' `extractmatrices' if "`r(outmatrices)'"~="" { foreach x in `r(outmatrices)' { matrix `x' = r(`x') cap return mat `x' = `x' } } cap matrix StdEstimates = r(StdEstimates) cap return matrix StdEstimates = StdEstimates matrix estimate = r(estimate) matrix se = r(se) cap matrix z = r(z) if _rc==0 { matrix z = z return matrix z = z } capture matrix CI = r(CI) capture return matrix CI = CI return matrix estimate = estimate return matrix se = se read_residual_variance , out(`using'.out) `debug' cap matrix residual_variance = r(residual_variance) cap return matrix residual_variance = residual_variance local note "output processing for multiple imputation" return local note "`note'" * Added 20150301 if "`debug'"=="debug" { noisily di in yellow _n "This is line 1285 of runmplus.ado and" /// _n "you are about to call " in green "read_parameterestimates_indirect" _n _n } read_parameterestimates_indirect , out(`using'.out) if "`r(outmatrices)'"~="" { foreach x in `r(outmatrices)' { matrix `x' = r(`x') cap return mat `x' = `x' } } * End added 20150301 } // close output processing for multiple imputation if "`mc'"=="" & "`montecarlo'"=="" & `isdatatypeimputation'==0 { * 28APR2010 * NEW MATERIAL FOR VERSION 6 * SPECIAL OUTPUT PROCESSING FOR BAYESIAN ESTIMATION * Step 1 read output and determine if estimator was bayes qui infix str line 1-85 using `using'.out , clear format line %85s * edit 8/21/2013 gen keep=trim(line)=="Specifications for Bayesian Estimation" // regexm(line,"BAYES") & regexm(line,"Estimator") qui su keep local BAYES = 0 if r(max)==1 { local BAYES=1 } drop keep ************************************************************************************ ************************** *************************** ********************* BAYES ESTIMATION OF OUTPUT PROCESSING ********************* ************************** *************************** ************************************************************************************ if `BAYES'==1 { qui { * post-processing for Bayesian estimation * first model and fits info * chi-square confidence interval not reported, should be added local z=0 local keeper`++z' = "Number of groups" local keeper`++z' = "Number of observations" local keeper`++z' = "Number of dependent variables" local keeper`++z' = "Number of independent variables" local keeper`++z' = "Number of continuous latent variables" local keeper`++z' = "Estimator" local keeper`++z' = "Point estimate" local keeper`++z' = "Number of MCMC chains" local keeper`++z' = "Random seed for the first chain" local keeper`++z' = "Starting value information" local keeper`++z' = "Treatment of categorical mediator" local keeper`++z' = "Algorithm used for Markov chain Monte Carlo" local keeper`++z' = "Convergence criterion" local keeper`++z' = "Maximum number of iterations" local keeper`++z' = "Kth iteration used for thinning" local keeper`++z' = "Minimum covariance coverage value" local keeper`++z' = "Number of Free Parameters" local keeper`++z' = "Posterior Predictive PValue" replace line = regexr(line,"Markov chain Monte Carlo (MCMC)","MCMC") replace line = regexr(line,"K-","K") replace line = regexr(line,"P-","P") gen keep=. forvalues y=1/`z' { replace keep=regexm(line,"`keeper`y''") if keep~=1 } keep if keep==1 gen value=reverse(word(reverse(line),1)) *di "`z'" *list line value while _N>1 { forvalues y=1/`z' { local value=value local line=line ** di "`line'" ** di "`value'" ** list line local vl=length("`value'")+1 ** di "`vl'" local line = reverse(substr(reverse("`line'"),`vl',.)) ** di "`line'" local line=itrim("`line'") ** di "`line'" local line=trim("`line'") ** di "`line'" local line=subinstr("`line'"," ","_",.) ** di "`line'" local line = substr("`line'",1,30) return local `line' = "`value'" drop if _n == 1 } } * now parameter estimates * hack of read_parameterestimates_general.ado * Read in Mplus output file and load parameter estimtes drop _all qui infix str line 1-85 /// str name 1-19 /// str value 20-85 /// using `using'.out format line %85s * IDENTIFY START AND END OF Parameter estimates gen linenum=_n gen x1=_n if /// trim(line)=="MODEL RESULTS" gen x2=_n if /// (substr(trim(line),1,15)=="Beginning Time:") | /// ( /// substr( trim(line), 1,9)=="TECHNICAL" & /// substr(reverse(trim(line)),1,6)==reverse("OUTPUT") /// ) | /// (substr(trim(line),1,28)=="RESULTS IN PROBABILITY SCALE") qui su x2 replace x1=x2 if x1==. & x2==`r(min)' summarize x1 keep if inrange(linenum,r(min)+1,r(max)-1) drop if trim(line)=="" drop x1 drop linenum gen linenum = _n * cleanup drop if substr(trim(line),1,9)=="Posterior" drop if substr(trim(line),1,8)=="Estimate" * suffix line 1152 gen suffix= lower(word(trim(line),3)) if wordcount(line)==3 & (substr(trim(line),1,5)=="Group"|substr(trim(line),1,12)=="Latent Class") replace suffix=suffix[_n-1] if _n>1 & suffix=="" *prefix gen prefix=line if (wordcount(line)==2|wordcount(line)==1) & (wordcount(line)==2 & (substr(trim(line),1,5)=="Group"|substr(trim(line),1,12)=="Class"))~=1 replace prefix=lower(prefix) replace prefix=prefix[_n-1] if _n>1 & prefix=="" * Second prefix gen eset ="" replace eset = line if substr(trim(line),1,21)=="STDYX Standardization" replace eset = line if substr(trim(line),1,20)=="STDY Standardization" replace eset = line if substr(trim(line),1,19)=="STD Standardization" replace eset = "r-square" if substr(trim(line),1,8)=="R-SQUARE" replace eset = lower(eset) replace eset = subinstr(eset,"standardization","",.) replace eset = eset[_n-1] if _n>1 & eset=="" * parameter * different if parameter is latent class proportion gen parameter = lower(word(trim(line),1)) if /// (wordcount(line)<4)~=1 | /// (substr(trim(line),1,5)=="Group")~=1 | /// (substr(trim(line),1,5)=="Class")~=1 replace parameter = lower(word(trim(line),1)) + lower(word(trim(line),2)) if /// (wordcount(line)>4) & /// (substr(trim(line),1,5)=="Class")==1 * estimate gen estimate=word(trim(line),2) if (substr(trim(line),1,5)=="Class")~=1 gen sd=word(trim(line),3) if (substr(trim(line),1,5)=="Class")~=1 gen pv=word(trim(line),4) if (substr(trim(line),1,5)=="Class")~=1 gen lci=word(trim(line),5) if (substr(trim(line),1,5)=="Class")~=1 gen uci=word(trim(line),6) if (substr(trim(line),1,5)=="Class")~=1 replace estimate=word(trim(line),3) if (substr(trim(line),1,5)=="Class")==1 replace sd=word(trim(line),4) if (substr(trim(line),1,5)=="Class")==1 replace pv=word(trim(line),5) if (substr(trim(line),1,5)=="Class")==1 replace lci=word(trim(line),6) if (substr(trim(line),1,5)=="Class")==1 replace uci=word(trim(line),7) if (substr(trim(line),1,5)=="Class")==1 foreach foo in estimate sd pv lci uci { replace `foo'=" " if estimate=="Undefined" } foreach foo in estimate sd pv lci uci { destring `foo', force replace } drop if estimate==. drop if sd==. & eset~="r-square" drop if eset=="r-square" & real(word(line),2)==. *gen x = eset + " " + prefix + " " + parameter + " " + suffix gen x = eset + " " + prefix + " " + parameter + " " + suffix if lower(prefix)~="class proportions" replace x = eset + " " + prefix + " " + parameter if lower(prefix)=="class proportions" replace x= eset + " " + word(line,1) + suffix if eset=="r-square" replace x=lower(x) replace x=trim(x) replace x=itrim(x) replace x = subinstr(x,"observed two-tailed","",.) replace x=itrim(x) replace x = subinstr(x,"new/additional parameters","new",.) * added 1/2/2009 by Frances Yang drop if regexm(x,"category")==1 destring estimate , replace destring sd , replace keep x estimate sd pv lci uci foreach foo in estimate sd pv lci uci { capture matrix drop `foo' } **** local MS=_N **** if `MS'>800 { **** capture set matsize `MS' **** if _rc==0 { **** set matsize `MS' **** } **** } foreach foo in estimate sd pv lci uci { mkmat `foo' , rownames(x) } mat se = sd mat ci = lci, uci foreach foo in estimate sd se pv ci { return matrix `foo' = `foo' } } } ************************************************************************************ ************************** *************************** *************************** NON-BAYES OUTPUT PROCESSING ************************* ************************** *************************** ************************************************************************************ if `BAYES'~=1 { * stuff in this section is prior to 28APR2010 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * BEGIN MODEL TERMINATION DISPLAY COMMAND SECTION * Read in MPLUS log file and * display line if model estimation terminated normally * Read in stata log file and * display fit statistics * create dictionary file * NOTE: not relevant for EFA, at least local out = "`using'"+".out" * new 12/3/2011 * fit statistics for EFA if substr(lower("`type'"),1,3)=="efa" { qui infix str line 1-85 using `out' , clear format line %85s gen linenum=_n *mata: out = cat("`out'") * identify number of efa solutions local m=0 local mlist "" local slist "" *set trace on local efais "efa" local mlist0 : list type - efais local mlist01 : word 1 of `mlist0' local mlist02 : word 2 of `mlist0' keep if substr(trim(lower(line)),1,32)=="exploratory factor analysis with" foreach q of numlist `mlist01'/`mlist02' { forvalues l=1/`c(N)' { if trim(lower(line[`l']))=="exploratory factor analysis with `q' factor(s):" { local m=`m'+1 local mlist "`mlist' `q'" local sis = linenum[`l'] local slist "`slist' `sis'" } } } qui infix str line 1-85 using `out' , clear format line %85s if `m'>0 { * matrix fitstatistics will hold...fit statistics mat fitstatistics=J(13,`m',.) mat rownames fitstatistics = CFI RMSEA AIC BIC aBIC Num_Para LoglikH0 LoglikH1 ChiSquareBasln DFBasln ChiSquare DF SRMR mat colnames fitstatistics = `mlist' * pull out fit statistics solution by solution local c=0 foreach x in `slist' { local c=`c'+1 local span=`x'+50 foreach l of numlist `x'(1)`span' { * cfi if substr(trim(lower(line[`l'])),1,3)=="cfi" { if substr(trim(lower(line[`l'])),1,4)~="cfi/" { local foo = line[`l'] local cfi=real(word("`foo'",2)) mat fitstatistics[1,`c']=`cfi' } } macro drop _foo * rmsea if substr(trim(lower(line[`l'])),1,8)=="estimate" { local foo = line[`l'] local rmsea = real(word("`foo'",2)) mat fitstatistics[2,`c']=`rmsea' } macro drop _foo * aic Akaike if substr(trim(lower(line[`l'])),1,6)=="akaike" { local foo = line[`l'] local aic= real(reverse(word(reverse("`foo'"),1))) mat fitstatistics[3,`c']=`aic' } macro drop _foo * bic bayesian if substr(trim(lower(line[`l'])),1,8)=="bayesian" { local foo = line[`l'] local bic = real(reverse(word(reverse("`foo'"),1))) mat fitstatistics[4,`c']=`bic' } macro drop _foo * abic sample-size if substr(trim(lower(line[`l'])),1,11)=="sample-size" { local foo = line[`l'] local abic = real(reverse(word(reverse("`foo'"),1))) mat fitstatistics[5,`c']=`abic' } macro drop _foo * Number of free parameters if substr(trim(lower(line[`l'])),1,6)=="number" { local foo = line[`l'] local number = real(reverse(word(reverse("`foo'"),1))) mat fitstatistics[6,`c']=`number' } macro drop _foo * loglikelihood H0 if substr(trim(lower(line[`l'])),1,8)=="h0 value" { local foo = line[`l'] local h0ll = real(reverse(word(reverse("`foo'"),1))) mat fitstatistics[7,`c']=`h0ll' } macro drop _foo * Loglikelihood H1 if substr(trim(lower(line[`l'])),1,8)=="h1 value" { local foo = line[`l'] local h1ll = real(reverse(word(reverse("`foo'"),1))) mat fitstatistics[8,`c']=`h1ll' } macro drop _foo * Chi-square Test of Model Fit (Value, Degrees, P-Value, First is Model Second is Baseline) * third value is srmr if substr(trim(lower(line[`l'])),1,5)=="value" { local foo = line[`l'] local value = real(reverse(word(reverse("`foo'"),1))) local test=fitstatistics[9,`c'] if `test'==. { mat fitstatistics[9,`c']=`value' } if `test'~=. { local test2=fitstatistics[11,`c'] if `test2'==. { mat fitstatistics[11,`c']=`value' } if `test2'~=. { mat fitstatistics[13,`c']=`value' } } } macro drop _foo if substr(trim(lower(line[`l'])),1,7)=="degrees" { local foo = line[`l'] local value = real(reverse(word(reverse("`foo'"),1))) local test=fitstatistics[10,`c'] if `test'==. { mat fitstatistics[10,`c']=`value' } if `test'~=. { mat fitstatistics[12,`c']=`value' } } macro drop _foo } } mat worsefit=J(3,`m',.) mat rownames worsefit = WorsefitLRT WorsefitDF WorsefitP local foo=`m'-1 local goo=`m' while `foo'>0 { mat worsefit[1,`foo']=abs(-2*(fitstatistics[7,`goo']-fitstatistics[7,`foo'])) mat worsefit[2,`foo']=(fitstatistics[6,`goo']-fitstatistics[6,`foo']) mat worsefit[3,`foo']=chi2tail((fitstatistics[6,`goo']-fitstatistics[6,`foo']),abs(-2*(fitstatistics[7,`goo']-fitstatistics[7,`foo']))) local foo=`foo'-1 local goo=`goo'-1 } mat fitstatistics = fitstatistics \ worsefit return matrix fitstatistics = fitstatistics return matrix worsefit = worsefit } } // end output processing for efa * end new 12/3/2011 if substr(lower("`type'"),1,3)~="efa" { // & "`mc'"~="" & "`montecarlo'"~="" { * new on 8/17/2012 * for Kate Xu * always read the sample size * (only works for single group models) * "Number of observations" tempname fh local linenum = 0 file open `fh' using `"`out'"', read file read `fh' line while r(eof)==0 & "`bump'"=="" { local linenum = `linenum' + 1 if substr(`"`macval(line)'"',1,22)=="Number of observations" { return scalar Number_of_observations = real(substr(`"`macval(line)'"',23,.)) local bump=1 } file read `fh' line } file close `fh' * another from Kate Xu 9/18/2012 * display warnings * THE STANDARD ERRORS OF THE MODEL PARAMETER ESTIMATES MAY NOT BE local linenum = 0 macro drop _bump file open `fh' using `"`out'"', read file read `fh' line while r(eof)==0 & "`bump'"=="" { local linenum = `linenum' + 1 if (substr(trim(`"`macval(line)'"'),1,63)=="THE STANDARD ERRORS OF THE MODEL PARAMETER ESTIMATES MAY NOT BE") | /// (substr(trim(`"`macval(line)'"'),1,65)=="THE STANDARD ERRORS OF THE MODEL PARAMETER ESTIMATES COULD NOT BE") { if (substr(trim(`"`macval(line)'"'),1,63)=="THE STANDARD ERRORS OF THE MODEL PARAMETER ESTIMATES MAY NOT BE") { return local warning "Standard errors not trustworthy" } if (substr(trim(`"`macval(line)'"'),1,65)=="THE STANDARD ERRORS OF THE MODEL PARAMETER ESTIMATES COULD NOT BE") { return local warning "Standard errors not estimated" } local bump=1 * but read and write the current line and the next four lines di in red `"`macval(line)'"' file read `fh' line di in red `"`macval(line)'"' file read `fh' line di in red `"`macval(line)'"' file read `fh' line di in red `"`macval(line)'"' file read `fh' line di in red `"`macval(line)'"' di in green _n } file read `fh' line } file close `fh' * end new on 8/17/2012 read_convergence , out(`out') local termination = "`r(termination)'" local stop = "`r(stop)'" return local termination = "`r(termination)'" return local stop = "`r(stop)'" } ** Get parameter estimates ** new 6-23-2008 if substr(lower("`type'"),1,3)~="efa" & substr(lower(trim("`termination'")),1,6)=="normal" { if "`debug'"=="debug" { noisily di in yellow _n "This is line 1706 of runmplus.ado and" /// _n "you are about to call " in green "x_general" _n _n } read_parameterestimates_general , out(`out') `debug' `extractmatrices' *** new 6/29/2011 if "`r(outmatrices)'"~="" { foreach x in `r(outmatrices)' { matrix `x' = r(`x') cap return mat `x' = `x' } } *** end new 6/29/2011 matrix estimate = r(estimate) matrix se = r(se) capture matrix CI = r(CI) capture matrix z=r(z) capture return matrix CI = CI capture return matrix z = z capture matrix rsquare = r(rsquare) capture return matrix rsquare = rsquare return matrix estimate = estimate return matrix se = se * Added 20150301 if "`debug'"=="debug" { noisily di in yellow _n "This is line 1285 of runmplus.ado and" /// _n "you are about to call " in green "read_parameterestimates_indirect" _n _n } read_parameterestimates_indirect , out(`using'.out) if "`r(outmatrices)'"~="" { foreach x in `r(outmatrices)' { matrix `x' = r(`x') cap return mat `x' = `x' } } * End added 20150301 if "`debug'"=="debug" { di in yellow _n "This is line 1733 of runmplus.ado and you are about" _n /// " to call " in green "read_residual_variance.ado" _n _n } read_residual_variance , out(`out') `debug' if "`debug'"=="debug" { di in yellow _n "Good news. " in green "read_residual_variance seems to have gone through OK" _n _n } cap matrix residual_variance = r(residual_variance) cap return matrix residual_variance = residual_variance } ** end new 6-23-2008 ** new 10-9-2008 ** This part of the code is ported from read_modelinfo.ado qui { qui infix str line 1-85 using `out' , clear format line %85s * IDENTIFY START AND END OF MODEL INFO gen linenum=_n gen x1=_n if (trim(line)=="SUMMARY OF ANALYSIS")|(trim(line)=="MODEL RESULTS")|(substr(trim(line),1,18)=="TESTS OF MODEL FIT") summarize x1 keep if inrange(linenum,r(min)+1,r(max)-1) drop if trim(line)=="" *** PATCH ON 6-25-2009 *** *** STILL NOT GETING MODEL CHI-SQURE *** *** STUFF ABOVE PROBABLY ONLY WORKS WITH CATEGORICAL DEPENDENT VARIABLES BUT I DON't REALLY KNOW *** local dim = _N-5 *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { local k = `j'+1 local l = `j'+2 local m = `j'+3 local n = `j'+4 if substr(trim(line[`j']),1,28)=="Chi-Square Test of Model Fit" & /// substr(trim(line[`k']),1,5)=="Value" & /// substr(trim(line[`l']),1,18)=="Degrees of Freedom" & /// substr(trim(line[`m']),1,7)=="P-Value" & /// substr(trim(line[`n']),1,25)=="Scaling Correction Factor" { return local chi_square = substr(trim(line[`k']),29,12) return local df = substr(trim(line[`l']),29,12) return local PValue = substr(trim(line[`m']),29,12) return local SCF = substr(trim(line[`n']),29,12) } } *** END OF 6-25-2009 PATCH drop if substr(line,1,10) == "* The ch" drop if substr(line,1,10) == " for ch" drop if substr(line,1,10) == " testin" drop if substr(line,1,10) == " See ch" drop if substr(line,1,10) == "** The de" drop if substr(line,1,10) == " a form" drop if substr(line,1,10) == " See de" drop if substr(trim(line),1,20) == "Loglikelihood change" drop if substr(trim(line),1,7) == "CFI/TLI" drop x1 drop linenum gen linenum = _n gen x1=. local info1 = "Number of observations" local info2 = "Estimator" local info3 = "Parameterization" local info4 = "Chi-Square Test" local info5 = "Value" local info6 = "Degrees of Freedom" local info7 = "P-Value" local info8 = "Chi-Square Test of Model Fit for the Baseline Model" local info9 = "CFI" local info10 = "TLI" local info11 = "RMSEA" local info12 = "Estimate" local info13 = "WRMR" local info14 = "Loglikelihood" local info15 = "H0 Value" local info16 = "H0 Scaling Correction Factor" local info17 = "Number of Free Parameters" local info18 = "Akaike (AIC)" local info19 = "Bayesian (BIC)" local info20 = "Sample-Size Adjusted BIC" local info21 = "Pearson Chi-Square" local info22 = "Likelihood Ratio Chi-Square" local info23 = "Chi-Square Test for Difference Testing" local info24 = "Entropy" local info25 = "Wald Test of Parameter Constraints" local info26 = "SRMR (Standardized Root Mean Square Residual)" * easy ones 1 2 3 9 10 11 13 18 19 20 24 local lab1 = "obs" local lab2 = "estimator" local lab3 = "Parameterization" local lab9 = "CFI" local lab10 = "TLI" local lab11 = "RMSEA" local lab13 = "WRMR" local lab18 = "AIC" local lab19 = "BIC" local lab20 = "aBIC" local lab17 = "free_parameters" local lab24 = "Entropy" local lab25 = "WaldTest" local lab26 = "SRMR" * loglikelihood local lab101 "LL_H0" local lab102 "LL_H1" local info101 = "H0 Value" local info102 = "H1 Value" foreach i of numlist 1/25 101 102 26 { local l = length("`info`i''") replace x1=linenum if substr(trim(line),1,`l') == "`info`i''" } keep if x1~=. keep line gen linenum = _n local dim = _N gen id=1 su linenum if r(N)>0 { reshape wide line, i(id) j(linenum) drop id * first the easy ones foreach i in 101 102 { *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { local l = length("`info`i''") if substr(trim(line`j'),1,`l')=="`info`i''" { return local `lab`i'' = trim(substr(line`j',`l'+1,.)) } } } * added SRMR 3 Mar 2015 forvalues j = 1/`dim' { if substr(trim(line`j'),1,4)=="SRMR" { local k = `j'+1 return local SRMR= trim(substr(trim(line`k'),6,.)) } } // closes SRMR foreach i of numlist 1 2 3 9 10 11 13 17 18 19 20 24 { *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { local l = length("`info`i''") if substr(trim(line`j'),1,`l')=="`info`i''" { return local `lab`i'' = trim(substr(line`j',`l'+1,.)) if `i'==2 { local estimator = trim(substr(line`j',`l'+1,.)) } if `i'==11|`i'==13 { local k = `j'+1 capture confirm variable line`k' if _rc==0 { return local `lab`i'' = trim(substr(line`k',`l'+5,.)) } } } } } * now the hard ones * start added 2013.10.15 forvalues j = 1/`dim' { if substr(trim(line`j'),1,34)=="Wald Test of Parameter Constraints" { local k = `j'+1 local l = `j'+2 local m = `j'+3 local WaldTest = trim(substr(trim(line`k'),6,.)) local WaldTest_df = trim(substr(trim(line`l'),21,.)) return local WaldTest = subinstr("`WaldTest'",char(42),"",.) return local WaldTest_df = subinstr("`WaldTest_df'",char(42),"",.) return local WaldTest_P = trim(substr(trim(line`m'),8,.)) } } if "`estimator'"~="MLR" { *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line`j'),1,28)=="Chi-Square Test of Model Fit" & /// substr(trim(line`j'),1,51)!="Chi-Square Test of Model Fit for the Baseline Model" { local k = `j'+1 local l = `j'+2 local m = `j'+3 local chisquare = trim(substr(trim(line`k'),6,.)) local chisquare_df = trim(substr(trim(line`l'),21,.)) return local chisquare = subinstr("`chisquare'",char(42),"",.) return local chisquare_df = subinstr("`chisquare_df'",char(42),"",.) return local chisquare_P = trim(substr(trim(line`m'),8,.)) } } * chi-square test of model fit for the baseline model *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line`j'),1,51)=="Chi-Square Test of Model Fit for the Baseline Model" { local k = `j'+1 local l = `j'+2 local m = `j'+3 local baseline_chisquare = trim(substr(trim(line`k'),6,.)) local baseline_chisquare_df = trim(substr(trim(line`l'),21,.)) return local BL_chisquare = subinstr("`baseline_chisquare'",char(42),"",.) return local BL_chisquare_df = subinstr("`baseline_chisquare_df'",char(42),"",.) return local BL_chisquare_P = trim(substr(trim(line`m'),8,.)) } } // closes condition for chi-square with estimator not MLR * Chi-Square Test for Difference Testing *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line`j'),1,38)=="Chi-Square Test for Difference Testing" { local k = `j'+1 local l = `j'+2 local m = `j'+3 return local difftest_chisquare = trim(substr(trim(line`k'),6,.)) return local difftest_chisquare_df = trim(substr(trim(line`l'),21,.)) } } // closes condition for chi-square with estimator not MLR } if "`estimator'"=="MLR" { * Loglikelihood *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line`j'),1,13)=="Loglikelihood" { local k = `j'+1 local l = `j'+2 return local Loglikelihood = trim(substr(trim(line`k'),9,.)) return local Loglikelihood_cf = trim(substr(trim(line`l'),31,.)) } } // closes loglikelihood * Pearson Chi-square *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line`j'),1,18)=="Pearson Chi-Square" { local k = `j'+1 local l = `j'+2 local m = `j'+3 return local Pearson_chi2 = trim(substr(trim(line`k'),6,.)) return local Pearson_chi2_df = trim(substr(trim(line`l'),21,.)) return local Pearson_chi2_P = trim(substr(trim(line`m'),8,.)) } } // closes Pearson * Likelihood Ratio Chi-Square *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line`j'),1,27)=="Likelihood Ratio Chi-Square" { local k = `j'+1 local l = `j'+2 local m = `j'+3 capture confirm variable line`k' if _rc==0 { return local LR_chi2 = trim(substr(trim(line`k'),6,.)) } capture confirm variable line`l' if _rc==0 { return local LR_chi2_df = trim(substr(trim(line`l'),21,.)) } capture confirm variable line`m' if _rc==0 { return local LR_chi2_P = trim(substr(trim(line`m'),8,.)) } } } // closes Likelihood Ratio Chi-Square } // closes condition if estimator is MLR } // closes qui on model info section } // closes condition on linenum } // closes condition if BAYES ~=1 } // closes condition if not montecarlo if ("`mc'"~="" | "`montecarlo'"~="" ) & `isdatatypeimputation'==0 { ********************************************* ********************************************* *** output processsing for montecarlo ********************************************* ********************************************* qui { // note not indented drop _all qui infix str line 1-85 /// str name 1-19 /// str value 20-85 /// using `using'.out format line %85s gen linenum=_n *list line capture drop keep gen keep=. replace keep=linenum if substr(trim(line),1,13)=="MODEL RESULTS" replace keep=linenum if substr(trim(lower(line)),1,28)=="quality of numerical results" su keep drop if linenum<=r(min) su keep drop if linenum>=r(max) drop if trim(line)=="" drop linenum gen linenum = _n * cleanup drop if substr(trim(lower(line)),1,9)=="estimates" * suffix line 1725 gen suffix= lower(word(trim(line),2)) if wordcount(line)==2 & (substr(trim(line),1,5)=="Group"|substr(trim(line),1,5)=="Class") replace suffix=suffix[_n-1] if _n>1 & suffix=="" *prefix gen prefix=line if (wordcount(line)==2|wordcount(line)==1) & (wordcount(line)==2 & (substr(trim(line),1,5)=="Group"|substr(trim(line),1,12)=="Class"))~=1 replace prefix=lower(prefix) replace prefix=prefix[_n-1] if _n>1 & prefix=="" * parameter gen parameter = lower(word(trim(line),1)) if (wordcount(line)==2 & substr(trim(line),1,5)=="Group")~=1 * estimate gen population=word(trim(line),2) gen average=word(trim(line),3) gen sd=word(trim(line),4) gen se_average=word(trim(line),5) gen mse=word(trim(line),6) gen coverage95=word(trim(line),7) gen sig_coef_pct=word(trim(line),8) local resultsset "population average sd se_average mse coverage95 sig_coef_pct " foreach foo in `resultsset' { replace `foo'=" " if population=="Undefined" } foreach foo in `resultsset' { destring `foo', force replace } gen x = prefix + " " + parameter + " " + suffix replace x=lower(x) replace x=trim(x) replace x=itrim(x) drop if population==. replace x=subinstr(x," ","_",.) replace x=subinstr(x,"$","_",.) drop if regexm(x,"category")==1 **** local MS=_N*10 **** if `MS'>800 { **** capture set matsize `MS' **** } keep x `resultsset' mkmat `resultsset' , rownames(x) matrix(model_results) return matrix model_results = model_results ************************* ************************* ***** now get fits ************************* *** first drop north of "TESTS OF MODEL FIT" *** then drop south of "MODEL RESULTS" *** THEN FROM within remainder find individual fits as noted local mcfit1="Chi-Square Test of Model Fit" local mcfit2="RMSEA (Root Mean Square Error Of Approximation)" local mcfit3="WRMR (Weighted Root Mean Square Residual)" local mcfit4="Loglikelihood" local mcfit5="H1 Value" local mcfit6="Akaike (AIC)" local mcfit7="Sample-Size Adjusted BIC (n* = (n + 2) / 24)" local mcfit8="SRMR (Standardized Root Mean Square Residual)" *----- * short names local smcfit1="Chi-Square" local smcfit2="RMSEA" local smcfit3="WRMR" local smcfit4="Loglikelihood" local smcfit5="H1 Value" local smcfit6="AIC" local smcfit7="BIC" local smcfit8="SRMR" **** loop over fits forvalues i=1/8 { // 3 is the number of fits, 3 as of 10-3-2010 *di in red "now pulling `smcfit`i'' results" drop _all qui infix str line 1-85 /// str name 1-19 /// str value 20-85 /// using `using'.out format line %85s gen linenum=_n *list line capture drop keep gen keep=. replace keep=linenum if substr(trim(line),1,18)=="TESTS OF MODEL FIT" replace keep=linenum if substr(trim(line),1,13)=="MODEL RESULTS" su keep drop if linenum<=r(min) su keep drop if linenum>=r(max) drop if trim(line)=="" drop linenum gen linenum = _n replace keep=linenum if regexm(line,"`smcfit`i''")==1 su keep drop if linenum<=r(min) replace keep=linenum+14 if regexm(line,"Percentiles")==1 su keep drop if linenum>r(min) gen mean=word(trim(line),2) if regexm(line,"Mean")==1 gen sd=word(trim(line),3) if regexm(line,"Std Dev")==1 gen nsc=word(trim(line),5) if regexm(line,"Number of successful computations")==1 destring mean, force replace destring sd, force replace destring nsc , force replace if "`smcfit`i''"=="Chi-Square" { local smcfit`i'="ChiSquare" } if "`smcfit`i''"=="H1 Value" { local smcfit`i'="H1Value" } if "`smcfit`i''"=="BIC" { local smcfit`i'="aBIC" } mat `smcfit`i'' = J(1,3,.) mat colnames `smcfit`i'' = Mean StdDev NSC su mean if r(N)==1 { mat `smcfit`i''[1,1]=r(mean) return local `smcfit`i''_mean=r(mean) su sd mat `smcfit`i''[1,2]=r(mean) return local `smcfit`i''_sd=r(mean) su nsc mat `smcfit`i''[1,3]=r(mean) return local `smcfit`i''_number_successful = r(mean) } return matrix `smcfit`i'' = `smcfit`i'' } } // close qui } * start added 6-17-2012 tech 11 and 14 output if /// regexm(lower("`output'"),"tech11")==1 | regexm(lower("`tech'"),"11")==1 | /// regexm(lower("`output'"),"tech14")==1 | regexm(lower("`tech'"),"14")==1 { di in green "Now processing TECH11 and/or TECH14 output" * Tech 11 output qui { if regexm(lower("`output'"),"tech11")==1 | regexm(lower("`tech'"),"11")==1 { qui infix str line 1-85 using `out' , clear format line %85s drop if trim(line)=="" local dim=`c(N)' *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line[`j']),1,19)=="TECHNICAL 11 OUTPUT" { local k = `j'+1 local l = `j'+2 local m = `j'+3 local n = `j'+4 return local tech11_randomstarts = trim(substr(trim(line[`l']),38,.)) return local tech11_finalstageopz = trim(substr(trim(line[`m']),36,.)) } } *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line[`j']),1,44)=="VUONG-LO-MENDELL-RUBIN LIKELIHOOD RATIO TEST" { local k = `j'+1 local l = `j'+2 local m = `j'+3 local n = `j'+4 local o = `j'+5 local p = `j'+6 return local tech11_vlmr_h0ll = trim(substr(trim(line[`k']),23,.)) return local tech11_vlmr_2lld = trim(substr(trim(line[`l']),37,.)) return local tech11_vlmr_dnp = trim(substr(trim(line[`m']),41,.)) return local tech11_vlmr_mean = trim(substr(trim(line[`n']),5,.)) return local tech11_vlmr_sd = trim(substr(trim(line[`o']),19,.)) return local tech11_vlmr_pvalue = trim(substr(trim(line[`p']),8,.)) } } *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line[`j']),1,34)=="LO-MENDELL-RUBIN ADJUSTED LRT TEST" { local k = `j'+1 local l = `j'+2 return local tech11_lmr_value = trim(substr(trim(line[`k']),23,.)) return local tech11_lmr_pvalue = trim(substr(trim(line[`p']),8,.)) } } * end tech 11 output } * start tech 14 output if regexm(lower("`output'"),"tech14")==1 | regexm(lower("`tech'"),"14")==1 { *foreach j of numlist 1/`dim' { forvalues j = 1/`dim' { if substr(trim(line[`j']),1,49)=="PARAMETRIC BOOTSTRAPPED LIKELIHOOD RATIO TEST FOR" { local k = `j'+1 local l = `j'+2 local m = `j'+3 local n = `j'+4 local o = `j'+5 return local tech14_h0ll = trim(substr(trim(line[`k']),23,.)) return local tech14_2lld = trim(substr(trim(line[`l']),37,.)) return local tech14_dnp = trim(substr(trim(line[`m']),39,.)) return local tech14_pvalue = trim(substr(trim(line[`n']),20,.)) return local tech14_success = trim(substr(trim(line[`o']),27,.)) } } * end tech 14 output } } // close qui } // end if * end added 6-17-2012 ** * ------------------- SAVE INPUT and DATA FILE IF REQUESTED TO DO SO * if "`saveinputfile'"~="" { cap confirm file `using'.inp if _rc==0 { * new on 7-20-2009 if "`saveinputdatafile'"~="" { tempname foo foo2 capture erase `foo'.inp local `foo2' : subinstr local saveinputdatafile "\" "\BS" , all local `foo2' = "``foo2''"+".dat" qui filefilter `using'.inp `foo'.inp /// , from("`using'.dat") /// to(`"``foo2''"') replace capture erase `saveinputfile'.inp capture erase `using'.inp qui copy `foo'.inp `using'.inp , replace } capture erase "`saveinputfile'.inp" qui copy `using'.inp "`saveinputfile'.inp" , replace } if "`saveinputdatafile'"~="" { cap confirm file `using'.dat if _rc==0 { qui copy `using'.dat "`saveinputdatafile'.dat" , replace } } } capture restore if "`log'"=="off" { di in green "log suppressed" } else { type `using'.out } capture erase `using'.inp capture erase `using'.out capture erase `using'.dat capture erase `r1'.dat * reset matsize qui cap set matsize `omatsize' end ** EMBEDDED PROGRAMS=========================================================== * line write program ========================================================== capture program drop lw program define lw syntax , out(string) line(string) local 1 `"`line'"' * test length of command local linelength : length local 1 if `linelength' < 70 { file write `out' "`1' ; " _n } else { local piece : piece 1 65 of `"`1'"' , nobreak file write `out' "`piece'" _n local k=2 local piece : piece 2 65 of `"`1'"' , nobreak while `"`piece'"' != "" { file write `out' "`piece'" local k = `k' + 1 local piece : piece `k' 65 of `"`1'"' , nobreak if trim(`"`piece'"') ~= "" { file write `out' " " _n } } file write `out' " ; " _n } end * =========================================================================== * ----- PROGRAM MAKELAB capture program drop makelab program define makelab version 7 * variable name, variable number, n of cases, file handle args var myout n * display "args `var' `myout' `n'" local varl : var label `var' file write `myout' " `var' : `varl'" _newline local vl : value label `var' if "`vl'" == "" { exit 0 } tempvar lvar tempvar first decode `var', gen(`lvar') sort `var' by `var' : gen `first' = (_n == 1) & `lvar' != "" local casenum = 1 while (`casenum' <= `n') { if `first'[`casenum'] { local v1 = `var'[`casenum'] local v2 = `lvar'[`casenum'] file write `myout' " `v1': `v2'" _newline } local casenum = `casenum' + 1 } end ** ======================================================================== **-- program saveinp capture program drop saveinp program def saveinp syntax , using(string) [saveinputfile(string) saveinputdatafile(string)] if "`saveinputfile'"~="" { cap confirm file `using'.inp if _rc==0 { * new on 7-20-2009 if "`saveinputdatafile'"~="" { * new on 6-13-2019 cap confirm file `using'.dat if _rc==0 { qui copy `using'.dat `"`saveinputdatafile'.dat"' , replace } tempname foo foo2 capture erase `foo'.inp local `foo2' : subinstr local saveinputdatafile "\" "\BS" , all local `foo2' = "``foo2''"+".dat" filefilter `using'.inp `foo'.inp /// , from("`using'.dat") /// to(`"``foo2''"') qui capture erase `saveinputfile'.inp qui capture erase `using'.inp qui copy `foo'.inp `using'.inp , replace * new on 6-13-a cap confirm file `using'.dat if _rc==0 { qui copy `using'.dat `"`foo2'"' , replace } } qui capture erase `saveinputfile'.inp qui copy `using'.inp `saveinputfile'.inp , replace } } end *** ========================================================== ** READ_ERRORS *** USAGE: read_errors foo.out capture program drop read_errors program define read_errors , rclass version 9 local 0 `"using `0'"' syntax using/ local error=0 tempname fh local linenum = 0 file open `fh' using `"`using'"', read file read `fh' line while r(eof)==0 { local linenum = `linenum' + 1 if substr(`"`macval(line)'"',1,9)=="*** ERROR" { local error = 1 return local error = 1 return local stop = 1 return local termination = "not normal" } if `error'==1 { if trim(`"`macval(line)'"')=="" { exit } noisily display in red `" `macval(line)'"' } file read `fh' line } file close `fh' end *** ============================================================ * have a nice day