-
Notifications
You must be signed in to change notification settings - Fork 0
/
psimulate2.ado
756 lines (666 loc) · 22.5 KB
/
psimulate2.ado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
*! parallelise simulate2
*! Version 1.09 - 31.10.2023
*! by Jan Ditzen - www.jan.ditzen.net
/* changelog
To version 1.01
- 21.10.2019: - bug fixes in program to get exe name
- no batch file written anymore; support for MacOS
- added options nocls and processors to set max processors for Stata MP
- version 15 and simulate support
- 17.01.2020 - added seedstream option
- 21.01.2020 - fix if used in loops; added global to save seed ($psim2Seed)
To version 1.02
- 30.01.2020 - added mata matrices copied over
To version 1.03
- 27.02.2020 - improved behaviour for long lines in do files or programs
- warning message if no seed set
To version 1.04
- 07.10.2020 - added "/" to temppath locals
- 03.02.2021 - bug fixed if data appended to frame but frame does not exists
To version 1.05
- 02.08.2021 - bug fix in exepath
To version 1.06
- 21.01.2022 - bug fix in temppath
To version 1.07
- 24.01.2022 - bug fix if program has more than 250 characters
To version 1.08
- 18.07.2023 - added option onlydots: display only dots for parallel simulate. better for servers
- 31.07.2023 - added options docmd() and globalid()
To version 1.08
- 31.10.2023 - support for Stata BE
*/
program psimulate2 , rclass
version 15
_on_colon_parse `0'
local after `"`s(after)'"'
local 0 `"`s(before)'"'
** parse only part before : , rest doesnt matter
syntax [anything(name=exp_list equalok)] ///
[fw iw pw aw] [if] [in] [, ///
Reps(integer -1) ///
SAving(string) ///
DOUBle /// not documented
noLegend ///
Verbose ///
SEED(string) /// not documented
TRace /// "prefix" options
/// simulate2 options
SEEDSave(string) ///
Parallel(string) /// parallel options
NOCls /// do not refresh windows
simulate /// use simulate rather than simulate2
seedstream(integer 0) /// first seedstream
ONLYDOTS /// show only dots
docmd(string) /// alternative command line to call do files
globalid(string) /// set id if psimulate run in parallel; default is empty
]
local 0 `parallel'
syntax [anything(name = instance)] , [ ///
exe(string) ///
temppath(string) ///
PROCessors(integer 1) ///
]
if "`instance'" == "" {
local instance = 1
}
if `seedstream' > 0 {
local seedstream = `seedstream' - 1
}
if "`temppath'" == "" {
local temppath `"`c(tmpdir)'"'
}
if "`nocls'`onlydots'" == "" {
local cls cls
}
if "`c(mode)'" == "batch" {
** If run in batch mode, do not use cls
local cls ""
}
if "`docmd'" == "" local docmd "do"
*** which simulate is used
if "`simulate'" == "" {
** make sure even if simulate not used but version < 16, use simulate
if `c(stata_version)' < 16 {
local simulate simulate
local whichsim "simulate"
}
else {
local whichsim "simulate2"
*** re-set to version 16
version 16
}
}
else {
local whichsim "simulate"
}
global psim2_id `globalid'
local psim2_id $psim2_id
*** remove p2sim files from folder
local files: dir `"`temppath'"' files "psim2`psim2_id'_*"
foreach file in `files' {
erase "`temppath'/`file'"
}
cap erase "`temppath'/lpsim2`psim2_id'_matafunc.mlib"
*** Get exe path
if "`exe'" == "" {
psim2_getExePath
local exepath `"`r(exepath)'"'
}
else {
local exepath "`exe'"
}
*** Copy mata matrices
local matamatsave = 0
cap erase "`temppath'/psim2`psim2_id'_matamat.mmat"
*** Process seed options
*** 1. neither frame nor dta used, then seed(seed rng seedstream)
*** 2. frame used -> save as dta; if rng and stream empty, use mt64s and instance
*** 3. dta used -> load as dta; if rng and stream empty, use mt64s and instance
*** 4. no seed set; set seed to Stata default seed, rng to mt64s and stream instance
local seednote = 0
local resetseed = 0
if "`whichsim'" == "simulate2" {
local instseed = `inst' + `seedstream'
if "`seed'" == "" {
*** case 4.
local seednote = 1
local seed `". mt64s \`instseed'"'
}
else {
local 0 `seed'
syntax anything , [frame dta start(integer 1)]
tokenize `anything'
if "`1'" == "." | "`1'" == "_current" {
if "`1'" == "_current" {
local resetseed = 1
}
if "$psim2Seed" != "" {
local 1 "$psim2Seed"
}
else {
local 1 `c(rngstate)'
local 2 `c(rng_current)'
}
*local 3 `c(rngstream)'
}
if wordcount("`frame' `dta'") == 2 {
di as err "options frame and dta cannot be combined"
exit 184
}
local startseednum = `start'
if "`frame'`dta'" == "" {
if "`2'" == "" {
local 2 "mt64s"
}
if "`3'" == "" {
local 3 `"\`instseed'"'
}
local seed `"`1' `2' \`3'"'
}
else {
tokenize `anything'
if "`frame'" != "" {
frame `1': save "`temppath'/psim2`psim2_id'_seed", replace
local seed `"`temppath'/psim2`psim2_id'_seed `2' `3' `4' , dta"'
local seedstartop `"start(\`=\`repscum'+\`startseednum'-1')"'
}
else if "`dta'" != "" {
local seed `"`1' `2' `3' `4' , dta"'
local seedstartop `"start(\`=\`repscum'+\`startseednum'-1')"'
}
}
}
if "`seedsave'" != "" {
local 0 `seedsave'
syntax anything , [frame seednumber(integer 1) append]
local sseeddest `"`anything'"'
local sseedframe "`frame'"
local sseedappend "`append'"
local seedsave `"`temppath'/psim2`psim2_id'_seedsave_\`inst' , seednumber(\`repscum')"'
}
}
else {
local seedsave ""
local seed seed(`seed')
}
*** remove last saved seed from global
if "$psim2Seed" != "" {
macro drop psim2Seed
}
*** save dta
save "`temppath'/psim2`psim2_id'_start", replace emptyok
*** Number of replications for each
local repsavg = floor(`reps'/`instance')
local repscum = 1
*** check if repsavg > 0
if `repsavg' == 0 {
while `repsavg' == 0 {
local instance = `instance'-1
local repsavg = floor(`reps'/`instance')
}
}
*** correct here commandline
forvalues inst = 1(1)`instance' {
local repsi = `repsavg' + (`inst'==1) * (`reps' - `repsavg'*`instance')
local instseed = `inst' + `seedstream'
if "`whichsim'" == "simulate2" {
psim2_WriteDofile `exp_list' , ///
/// sim2 options
saving("`temppath'/psim2`psim2_id'_results_`inst'", replace) reps(`repsi') ///
perindicator(100, perindicpath(`"`temppath'"') performid(`inst')) ///
seed("`seed'" "`seedstartop'") seedsave("`seedsave'") seedstream(`seedstream') ///
/// writeBatch options
id(`inst') processors(`processors') ///
startdta(psim2`psim2_id'_start) temppath(`temppath') ///
: `after'
}
else {
psim2_WriteDofile `exp_list' , ///
/// sim options
saving("`temppath'/psim2`psim2_id'_results_`inst'", replace) reps(`repsi') ///
`seed' ///
/// writeBatch options
id(`inst') processors(`processors') simulate ///
startdta(psim2`psim2_id'_start) temppath(`temppath') ///
: `after'
}
local repscum = `repscum'+`repsi'
}
if "`c(os)'" == "Windows" {
local winexec_e "/e"
}
else if "`c(os)'" == "MacOSX" {
local winexec_e "-e"
}
else if "`c(os)'" == "Unix" {
local winexec_e ""
}
local starttime = clock(c(current_time),"hms")
if "`c(console)'" == "" {
forvalues inst = 1(1)`instance' {
* noi disp `"command line to execute: winexec `exepath' `winexec_e' do "`temppath'psim2_DoFile_`inst'.do" "'
* local lastcmd `"winexec `exepath' `winexec_e' do "`temppath'psim2_DoFile_`inst'.do" "'
winexec `exepath' `winexec_e' `docmd' "`temppath'/psim2`psim2_id'_DoFile_`inst'.do"
}
}
else {
forvalues inst = 1(1)`instance' {
local line "`line' (`exepath' `docmd' "`temppath'/psim2`psim2_id'_DoFile_`inst'.do" &)"
if `inst' != `instance' {
local line "`line' ; "
}
}
noi disp "Starting `instance' Instances. No output available, please wait."
qui shell `line'
}
**** Output
local sleeptime = 1000
noi disp "Initalising...."
local reps_done = 0
while `reps' > `reps_done' {
** Reset reps done
local reps_done = 0
sleep `sleeptime'
forvalues inst = 1(1)`instance' {
if fileexists("`temppath'/psim2`psim2_id'_performance_`inst'.mmat") == 1 {
cap qui mata mata matuse "`temppath'/psim2`psim2_id'_performance_`inst'", replace
if _rc != 0 {
** build in artifical sleep
noi disp "error in saving psim2`psim2_id'_performance_`inst'"
sleep 1000
cap qui mata mata matuse "`temppath'/psim2`psim2_id'_performance_`inst'", replace
}
qui mata st_local("done_`inst'",strofreal(p2sim_performance[1,1]))
qui mata st_local("reps_`inst'",strofreal(p2sim_performance[1,2]))
** if simulate is used -999 is returned when done
if `reps_`inst'' == -999 {
local reps_`inst' = `reps' / `instance'
local done_`inst' = `reps_`inst''
}
}
else {
local reps_`inst' = `reps'
local done_`inst' = 0
}
local reps_done = `reps_done' + `done_`inst''
}
*** all times in ms sec.
local nowtime = clock(c(current_time),"hms")
local avg_run = (`nowtime' - `starttime') /`reps_done'
if `avg_run' == . {
local avg_run = 0
}
** time in minutes
local time_elapsed = (`nowtime' - `starttime')
*local exp_time_left = (`reps'-`reps_done')*`avg_run'/`instance'
local exp_time_left = `time_elapsed' / `reps_done' * `reps'
*** in hour format
local exp_finish_time = `nowtime'+`exp_time_left'
`cls'
if "`onlydots'" == "" {
noi disp as text ""
noi disp "psimulate2 - parallelise `whichsim'"
noi disp as text ""
local aftertt = strtrim(`"`after'"'')
noi disp as text `"command: `aftertt' "'
noi disp as text ""
noi disp as text "Timings (hour, minute, sec):" _col(40) "Estimated:"
noi disp as text " Average Run: " _col(24) %tcHH:MM:SS.sss `avg_run' _col(40) " Time left (min):" _col(60) %tcHH:MM:SS `exp_time_left'
noi disp as text " Time Elapsed:" _col(24) %tcHH:MM:SS `time_elapsed' _col(40) " finishing time:" _col(60) %tcHH:MM:SS `exp_finish_time'
noi disp ""
if "`whichsim'" == "simulate2" {
forvalues inst = 1(1)`instance' {
noi disp as text "Instance `inst':"
noi disp as text " Done " %9.2f `=`done_`inst''/`reps_`inst''*100' "%" _col(20) "(`done_`inst''/`reps_`inst'')"
}
noi disp as text "Total"
noi disp as text " Done " %9.2f `=`reps_done'/`reps'*100' "%" _col(20) "(`reps_done'/`reps')"
}
else {
noi disp as text " simulate does not allow for process indication. Please wait."
}
local sleeptime = `avg_run' * `reps' / 100
}
else {
noi disp "." , _c
}
*** wait at least 0.25 sec
if `sleeptime' < 250 {
local sleeptime = 250
}
else if `sleeptime' > 60000 {
local sleeptime = 59999
}
if "`onlydots'" == "" {
noi disp ""
noi disp as text "Current Time: `c(current_time)' - next refresh in " %tcSS.ss `sleeptime' " sec."
if `seednote' == 1 {
noi disp as text "No seed set. If psimulate is used in a loop, "
noi disp as text "all iterations of the loop will have the Stata default seed."
}
}
sleep `sleeptime'
}
noi disp ""
noi disp "Click on link to open log file: "
di as text "Log files "
forvalues inst = 1(1)`instance' {
if fileexists("psim2`psim2_id'_DoFile_`inst'.log") == 1 {
disp as smcl _col(5) "Instance `inst':" _col(20) `"{view psim2_DoFile_`inst'.log: Log File}"'
}
}
*** Save seeds
qui {
if "`sseeddest'" != "" {
clear
use "`temppath'/psim2`psim2_id'_seedsave_1"
forvalues inst = 2(1)`instance' {
append using "`temppath'/psim2`psim2_id'_seedsave_`inst'", force
}
if "`sseedframe'" == "" {
if "`sseedappend'" != "" {
append using "`sseeddest'", force
}
save "`sseeddest'" , replace
}
else {
if "`sseedappend'" != "" {
frame `sseeddest': save "`temppath'/psim2`psim2_id'_oldseed", replace
append using "`temppath'/psim2`psim2_id'_oldseed"
}
cap frame drop `sseeddest'
frame copy `c(frame)' `sseeddest'
}
}
*** Collect data
clear
use "`temppath'/psim2`psim2_id'_results_1"
forvalues inst = 2(1)`instance' {
qui append using "`temppath'/psim2`psim2_id'_results_`inst'", force
}
if "`saving'" != "" {
local 0 `"`saving'"'
syntax anything [, frame replace append]
if "`frame'" != "" {
if "`append'" != "" {
*** check if frame exists
frame dir
if regexm("`r(frames)'","`anything'") == 0 {
frame create `anything'
}
frame `anything': save "`temppath'/psim2`psim2_id'_oldframe", replace emptyok
append using "`temppath'/psim2`psim2_id'_oldframe"
}
cap frame drop `anything'
frame copy `c(frame)' `anything'
}
else {
if "`append'" != "" {
append using `"`anything'"'
}
save `"`anything'"', replace
}
}
mata st_local("last_seed1",p2sim_lastseed[1])
return local rngstate "`last_seed1'"
mata st_local("last_seed",p2sim_lastseed[2])
return local rngseed_mt64s "`last_seed'"
mata st_local("p2sim_lastrng",p2sim_lastrng)
return local rng_current "`p2sim_lastrng'"
if `resetseed' == 1 {
global psim2Seed = "`last_seed1'"
}
}
end
cap program drop psim2_WriteDofile
program define psim2_WriteDofile
_on_colon_parse `0'
local after `"`s(after)'"'
local 0 `"`s(before)'"'
local psim2_id $psim2_id
syntax [anything(name=explist equalok)], id(string) startdta(string) temppath(string) processors(integer) seedstream(integer) [simulate] *
local sim2_options `options'
local path `"`temppath'"'
local doFileName "psim2`psim2_id'_DoFile_`id'.do"
tempname dofile
**** Create do file with programs
psim2_programlist , temppath("`temppath'")
local pnames "`r(pnames)'"
noi disp "pnames: `pnames'"
**** Write do file
file open `dofile' using `"`path'/`doFileName'"' , w replace
*** Add Time Stamp
file write `dofile' `"disp "This is psmulate2""' _n
file write `dofile' `"disp "File was written `c(current_time)'""' _n
if "`pnames'" != "" {
file write `dofile' `"include `"`temppath'/psim2`psim2_id'_programs.do"'"' _n
}
**** If Stata MP, use only one core:
if `c(MP)' == 1 {
file write `dofile' `"set processors `processors'"' _n
}
**** Add ados and globals
**** ado
tokenize `"$S_ADO"' , p(";")
while "`1'" != "" {
if "`1'" != "BASE" & "`1'" != "SITE" & "`1'" != "." & "`1'" != "BASE" & "`1'" != "PERSONAL" & "`1'" != "PLUS" & "`1'" != "OLDPLACE" & "`1'" != ";" {
file write `dofile' `"adopath + "`1'""' _n
}
macro shift
}
**** globals
local allGlobals : all globals
tokenize `"`allGlobals'"'
while "`1'" != "" {
if "`1'" != "S_ADO" & "`1'" != "S_level" & "`1'" != "F1" & "`1'" != "F2" & "`1'" != "F7" & "`1'" != "F8" & "`1'" != "S_StataSE" & "`1'" != "S_FLAVOR" & "`1'" != "S_OS" & "`1'" != "S_OSDTL" & "`1'" != "S_MACH" {
if strtoname("`1'") == "`1'" {
file write `dofile' `"global `1' ="$`1'""' _n
}
}
macro shift
}
**** Mata programs; easy way, check if mata programs exist, if so, add then to libary and
**** set new ado path to library in do file
mata mata memory
if `r(Nf_def)' > 0 {
cap lmbuild lpsim2`psim2_id'_matafunc , dir(`temppath') replace
if _rc != 0 {
sleep 200
cap lmbuild lpsim2`psim2_id'_matafunc , dir(`temppath') replace
}
file write `dofile' `"adopath + "`temppath'""' _n
file write `dofile' `"mata mata mlib index"' _n
}
**** Mata programs
mata mata memory
if `r(Nm)' > 0 {
mata mata matsave "`temppath'/psim2`psim2_id'_matamat.mmat" *, replace
file write `dofile' `"mata mata matuse "`temppath'/psim2`psim2_id'_matamat.mmat", replace"' _n
}
/*
**** do same for matrices
local allMatrices: all matrices
tokenize `"`allMatrices'"'
while "`1'" != "" {
file write `dofile' `"matrix `1' =``'1'"' _n
macro shift
}
**** all scalars
local allScalar: all scalars
tokenize `"`allScalar'"'
while "`1'" != "" {
file write `dofile' `"scalar `1' ="`1'""' _n
macro shift
}
*/
**** Open Dataset
file write `dofile' `"use "`temppath'/`startdta'""' _n
**** Do cmd
if "`simulate'" == "" {
file write `dofile' `"simulate2 `explist' , inpsim2 psim2_id(`psim2_id') `options' : `after'"' _n
}
else {
file write `dofile' `"set rng mt64s"' _n
file write `dofile' `"set rngstream `=`id'+`seedstream''"' _n
file write `dofile' `"simulate `explist' , `options' : `after'"' _n
file write `dofile' `"mata p2sim_performance = -999, -999 "' _n
file write `dofile' `"mata p2sim_lastrng = "\`c(rng_current)'""' _n
file write `dofile' `"mata p2sim_lastseed = "\`c(rngstate)'" , "\`c(rngseed_mt64s)'""' _n
file write `dofile' `"cap mata mata matsave "`temppath'/psim2`psim2_id'_performance_`id'" p2sim_performance p2sim_lastseed p2sim_lastrng , replace "' _n
}
**** Close do file
file close `dofile'
end
cap program drop psim2_getExePath
program define psim2_getExePath, rclass
local datafiles: dir "`c(sysdir_stata)'" files "*.exe"
if wordcount(`"`datafiles'"') == 1 {
local datafiles = subinstr(`"`datafiles'"',`"""',"",.)
local exepath `c(sysdir_stata)'`datafiles'
local exename `"`datafiles)'"'
}
else {
if "`c(os)'" == "Windows" {
if `c(SE)' == 1 & `c(MP)' == 0 {
local type SE
}
else if `c(MP)' == 1 {
local type MP
}
else {
if "`c(edition_real)'" == "BE" local type BE
else type IC
}
local exepath "`c(sysdir_stata)'Stata`type'-`c(bit)'.exe"
local exename "Stata`type'-`c(bit)'.exe"
}
else if "`c(os)'" == "MacOSX" {
if `c(SE)' == 1 & `c(MP)' == 0 {
local type "SE"
local exepath /usr/local/bin/stata-se
}
else if `c(MP)' == 1 {
local type "MP"
loc exepath /usr/local/bin/stata-mp
}
else {
local type "IC"
loc exepath /usr/local/bin/stata
}
}
else if "`c(os)'" == "Unix" {
local w = c(sysdir_stata)
if `c(SE)' == 1 & `c(MP)' == 0 {
local type "SE"
loc exepath `w'stata-se
}
else if `c(MP)' == 1 {
local type "MP"
loc exepath `w'stata-mp
}
}
if fileexists("`exepath'") == 0 {
display as smcl "No Stata exe found. Please set a path using {help psimulate2##options:exepath()}."
exit
}
}
return local exepath `"`exepath'"'
return local exename "`exename'"
end
program define psim2_programlist, rclass
syntax [anything] , temppath(string)
local psim2_id $psim2_id
log
local logname "`r(filename)'"
cap log close
local linesize `c(linesize)'
set linesize 250
log using "`temppath'/psim2`psim2_id'_plog", replace text nomsg
program dir
log close
set linesize `linesize'
tempname file nextline
file open `file' using `"`temppath'/psim2`psim2_id'_plog.log"' , read
file read `file' line
while r(eof)==0 {
local line `" `macval(line)'"'
local count = wordcount("`line'")
tokenize `line'
capture confirm number `2'
if `count' == 2 & _rc != 0 {
local pnames "`pnames' `2'"
}
file read `file' line
}
file close `file'
**** write a new do file with contents of each program
if "`pnames'" != "" {
*local appendreplace "replace"
tempname dofilenew
file open `dofilenew' using "`temppath'/psim2`psim2_id'_programs.do" , write text replace
foreach prog in `pnames' {
local linesize `c(linesize)'
set linesize 250
log using "`temppath'/psim2`psim2_id'_tmp_program.log" , text nomsg replace
cap noi program list `prog'
log close
set linesize `linesize'
if _rc == 0 {
file open `file' using `"`temppath'/psim2`psim2_id'_tmp_program.log"' , read
file read `file' line
/// Open it the second time and shift one line down to check if line was cut off
file open `nextline' using `"`temppath'/psim2`psim2_id'_tmp_program.log"' , read
file read `nextline' next
file read `nextline' next
local inprog = -1
while r(eof)==0 {
gettoken 1 2 : line
if "`1'" != "." & "`1'" != "" & "`1'" != "=" & "`1'" != "-" {
local first = subinstr("`1'",".","",.)
capture confirm number `first'
*** line starts with a number, contains code
if _rc != 0 & `inprog' == -1 {
local line = subinstr("`line'",":","",.)
file write `dofilenew' `"program define `line'"' _n
local inprog = 1
}
else if `inprog' == 1 {
local rest = subinstr(`"`macval(line)'"',"`1'","",.)
//// check if next line start with ">", then this needs to be added to current line
gettoken n1 n2: next
if regexm(`"`n1'"',">") == 1 {
local rest = strtrim(`"`rest'"')
*local n2 = strtrim(`"`n2'"')
*local n2 = subinstr(`"`n2'"'," ","",1)
local n2 = strltrim(`"`n2'"')
file write `dofilenew' `"`macval(rest)'`macval(n2)'"' _n
/// now shift both files one line down
file read `file' line
file read `nextline' next
}
else {
file write `dofilenew' `"`macval(rest)'"' _n
}
}
else {
local inprog = 0
}
}
file read `nextline' next
file read `file' line
}
file close `file'
file close `nextline'
** add end
file write `dofilenew' `"end"' _n
file write `dofilenew' `""' _n
}
}
file close `dofilenew'
}
if "`logname'" != "" {
log using "`logname'", append
}
return clear
return local pnames "`pnames'"
end