*! Version 1.0, Dirk Enzmann (20-Aug-2026) *! *! Helper for loevh2_meta_save: (re)writes the small, self-contained *! companion .do file that goes alongside a meta()-produced .dta file. program define loevh2_meta_writedo version 16.0 args dta do origframe origchanged // bt/cq/dq: literal backtick / closing-single-quote / double-quote // characters. ALWAYS referenced directly as bare `bt'/`cq' // macro references (for backtick/quote pairs) or wrapped in their // OWN compound double quotes `"`dq'"' (for literal double quotes) // inside a -file write- argument list -- NEVER pre-assembled into // any OTHER intermediate local macro first. local bt = char(96) local cq = char(39) local dq = char(34) // Determine local _have_svy and variables for list -- via a // temporary helper frame `_mfh', so the caller's own current frame // (whatever it may be at this point in the call chain) is never // disturbed by the "use ... , clear" below. // // NOTE: `origframe'/`origchanged' describe the USER's true original // frame/changed-status (as of before loevh2/loevh2_boot/loevh2_svy // was ever called) -- NOT necessarily the frame that is CURRENT // right now, at this point inside loevh2_meta_writedo. Only the // "not changed" message text uses `origchanged'; the actual // frame-drop-safety fix below never assumes `origframe' equals // c(frame) at this moment, and works correctly regardless. tempname _mfh frame create `_mfh' local _setvars = "" local _have_svy = 0 if `origchanged' == 0 local changed = "NOT " // `_runlist' collects the numeric codes (run==1, run==2, ...) of // every run that has AT LEAST 2 rows (studies/sub-samples) -- i.e. // every run for which an independent, meta-native fixed/random // pooled summary is actually meaningful (a single-row run has // nothing to pool; its H/SE/N are already fully visible in the // "list run_id source study label H SE N ..." line above, so no // separate meta summarize block is generated for it -- see the // task discussion this feature was designed from). `_runlab`_r'' // holds each such run's own human-readable %tc label text (read // back from the `run' value label already built by // loevh2_meta_save), for use as an on-screen header in the // generated .do's per-run blocks. local _runlist = "" local _ntotalruns = 0 frame `_mfh' { quietly use "`dta'", clear capture confirm variable svy_wtype svy_wexp svy_cluster svy_strata svy_fpc if _rc == 0 { local svysetvars = "svy_wtype svy_wexp svy_cluster svy_strata svy_fpc" foreach v of local svysetvars { qui tab1 `v' if r(N) > 0 { local _setvars = "`_setvars' `v'" local _have_svy = 1 } } } capture confirm variable run if _rc == 0 { quietly levelsof run, local(_allruns) local _ntotalruns : word count `_allruns' foreach _r of local _allruns { quietly count if run == `_r' if r(N) >= 2 { local _runlist = "`_runlist' `_r'" local _rundisp : label (run) `_r' local _runlab`_r' = `"`_rundisp'"' } } } } // Drop the temporary helper frame FIRST, then switch back to the // user's true original frame -- NEVER the reverse order. This // guarantees "frame drop `_mfh'" is never issued while `_mfh' is // the CURRENT frame (which is exactly what triggered "may not drop // current frame" in the version 1.0 code -- see the header note // above), regardless of what `origframe' resolves to. frame drop `_mfh' capture confirm frame `origframe' if _rc == 0 & "`origframe'" != "" { frame change `origframe' } local linesize = c(linesize) tempname fh file open `fh' using "`do'", write text replace file write `fh' "// Auto-generated by loevh2_meta_save -- do not edit by hand" _n file write `fh' "// Re-created on `c(current_date)' `c(current_time)'" _n file write `fh' "//" _n file write `fh' "// Loads `dta'" _n file write `fh' "// and re-runs inverse-variance (meta-analytic) pooling of the already computed" _n file write `fh' "// H/SE/N rows saved by loevh2/loevh2_boot/loevh2_svy's compare + meta() options." _n file write `fh' "//" _n if `_have_svy' { file write `fh' "// NOTE: the svy_* columns below document the survey design (weight/cluster/" _n file write `fh' "// strata/fpc) used to COMPUTE each loevh2_svy-sourced row's H/SE (for reference" _n file write `fh' "// only). This script uses ONLY the already-computed H/SE/N values below -- it" _n file write `fh' "// does NOT require, and cannot reconstruct, the original raw dataset(s) any row" _n file write `fh' "// was originally computed from." _n } else { file write `fh' "// This script uses ONLY the already-computed H/SE/N values below -- it does NOT" _n file write `fh' "// require, and cannot reconstruct, the original raw dataset(s) any row was" _n file write `fh' "// originally computed from." _n } file write `fh' "" _n file write `fh' "use " `"`dq'"' "`dta'" `"`dq'"' ", clear" _n file write `fh' "" _n file write `fh' "di as txt _n " `"`dq'"' "Sub-samples pooled from `dta':" `"`dq'"' _n file write `fh' "set linesize 255" _n file write `fh' "format H SE %6.5f" _n file write `fh' "list run_id source study H SE N se_type `_setvars', sepby(run_id) ab(12) noobs" _n file write `fh' "set linesize `linesize'" _n file write `fh' "" _n file write `fh' "// (a) Set the data up for Stata's -meta- suite reproducing the results from" _n file write `fh' "// loevh2/loevh2_boot/loevh2_svy's --compare-- output (fixed-effects model," _n file write `fh' "// assuming all k studies/sub-samples share exactly ONE true underlying" _n file write `fh' "// effect H); further meta-analysis (set summarize, subgroup analysis, meta" _n file write `fh' "// forestplot, etc.) can be run." _n file write `fh' "" _n file write `fh' "capture meta set H SE, studylab(label) eslab(Loevinger's H) fixed" _n file write `fh' "meta summarize, cformat(%9.4f)" _n file write `fh' "" _n file write `fh' "// (b) Set the data up for random-effects model meta analysis (assuming each" _n file write `fh' "// study/sub-sample has its OWN true effect, drawn from a distribution of" _n file write `fh' "// true effects -- i.e., there is genuine between-study heterogeneity," _n file write `fh' "// tau^2 > 0); more commonly recommended if Q is (strongly) significant." _n file write `fh' "// Further analyses (meta summarize, subgroup analyses, meta forestplot," _n file write `fh' "// etc.) can be run." _n file write `fh' "" _n file write `fh' "capture meta set H SE, studylab(label) eslab(Loevinger's H) random" _n file write `fh' "meta summarize, cformat(%9.4f)" _n file write `fh' "" _n // (c) Per-run breakdown: written whenever (i) at least one run has 2 // or more rows/sub-samples of its own (i.e. there is at least one // qualifying run for which an independent, meta-native fixed/random // pooled summary is actually meaningful -- see `_runlist' above), AND // (ii) the FILE AS A WHOLE contains 2 or more distinct runs in total // (`_ntotalruns', collected above alongside `_runlist' -- counting // EVERY run, including single-row ones, not just qualifying ones). local _nruns : word count `_runlist' if `_nruns' >= 1 & `_ntotalruns' >= 2 { file write `fh' "// (c) Per-run breakdown: separately pool the sub-samples contributed by EACH" _n file write `fh' "// run (i.e. each separate loevh2/loevh2_boot/loevh2_svy ..., compare meta()" _n file write `fh' "// call that added rows to this .dta) that has 2 or more rows of its own --" _n file write `fh' "// letting you directly compare the pooled H across runs." _n file write `fh' "" _n file write `fh' "tab run" _n file write `fh' "" _n foreach _r of local _runlist { file write `fh' "di as txt _n " `"`dq'"' "---- `_runlab`_r'' ----" `"`dq'"' _n file write `fh' "capture meta set H SE if run==`_r', studylab(label) eslab(Loevinger's H) fixed" _n file write `fh' "meta summarize, cformat(%9.4f)" _n file write `fh' "" _n file write `fh' "capture meta set H SE if run==`_r', studylab(label) eslab(Loevinger's H) random" _n file write `fh' "meta summarize, cformat(%9.4f)" _n file write `fh' "" _n } } file close `fh' di as txt "meta(): companion pooling script written to " as res "`do'" _n _n /// "NOTE: " as txt "running " as res `"`do'"' as txt _n /// " will replace the `changed'CHANGED dataset currently in memory with the pooled" _n /// " results -- reload your own data afterward if continuing further analysis" _n /// " in this Stata session." end