-
Notifications
You must be signed in to change notification settings - Fork 0
/
sweep.functions.au3
360 lines (300 loc) · 14.7 KB
/
sweep.functions.au3
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
#cs ----------------------------------------------------------------------------
Script: sweep
AutoIt Version: 3.3.14.2
Author: Matt Easton
Created: 2018.01.15
Modified: 2018.01.15
Version: 0.0.1.0
Script Function:
Create a batch of input files from a batch definition file and a template
Based on runLORASR.Sweep v0.4.4.0
#ce ----------------------------------------------------------------------------
#include-once
#include <Array.au3>
#include <Excel.au3>
#include <File.au3>
#include <FileConstants.au3>
#include "sweep.common.au3"
;~ #include "sweep.results.au3"
#include "sweep.progress.au3"
; Code version
$g_sSweepVersion = "0.0.1.0"
; Main function
Func SweepInput($sWorkingDirectory = @WorkingDir, $sSweepFile = "Sweep.xlsx", $sTemplateFile = "Template.txt", $sResultsFile = "Batch results.csv", $sInputFolder = "Input")
LogMessage("Called `SweepInput($sWorkingDirectory = " & $sWorkingDirectory & ", $sSweepFile = " & $sSweepFile & ", $sTemplateFile = " & $sTemplateFile & ", $sResultsFile = " & $sResultsFile & ", $sInputFolder = " & $sInputFolder & ")`", 5)
; Declarations
Local $iResult = 0, $iParameter = 0, $iParameters = 0
Local $asParameters, $asValues
; Find sweep definition files
LogMessage("Finding sweep definition files...", 3, "SweepInput")
UpdateProgress($g_sProgressType, 1, "Finding sweep definition files")
$iResult = FindSweepFiles($sWorkingDirectory, $sSweepFile, $sTemplateFile, $sInputFolder)
If (Not $iResult) Or @error Then
LogMessage("Sweep definition files not found.", 3, "SweepInput")
SetError(1)
Return 0
EndIf
; Load parameter details
LogMessage("Loading parameters from sweep definition...", 3, "SweepInput")
UpdateProgress($g_sProgressType, 2, "Loading parameters from sweep definition")
$iResult = LoadSweepParameters($asParameters, $asValues, $sWorkingDirectory, $sSweepFile)
If (Not $iResult) Or @error Then
ThrowError("Error loading sweep parameters. Cannot build parameter sweep.", 3, "SweepInput", @error)
SetError(2)
Return 0
EndIf
; Clear up existing input files in working directory
LogMessage("Clearing up existing input files...", 3, "SweepInput")
UpdateProgress($g_sProgressType, 3, "Clearing up existing input files")
$iResult = DeleteInputFiles($sWorkingDirectory, $sTemplateFile)
If (Not $iResult) Or @error Then
ThrowError("Error while clearing up input files", 4, "SweepInput", @error)
; Try to continue
SetError(0)
EndIf
; Build input files for each set of parameter values
LogMessage("Building input files for parameter sweep...", 3, "SweepInput")
$iParameters = UBound($asParameters,1) - 1
For $iParameter = 0 To $iParameters
LogMessage("Parameter " & String($iParameter + 1) & " (" & $asParameters[$iParameter][0] & ")", 4, "SweepInput")
UpdateProgress($g_sProgressType, Round($iParameter/($iParameters + 2) * 100), "Parameter " & String($iParameter + 1) & " of " & $iParameters & " (" & $asParameters[$iParameter][0] & ")")
$iResult = SweepParameter($asParameters, $asValues, $iParameter, $sWorkingDirectory, $sTemplateFile)
If (Not $iResult) Or @error Then
ThrowError("Error building input files. Cannot build parameter sweep.", 3, "SweepInput", @error)
SetError(3)
Return 0
EndIf
Next
; Move input files to separate folders per run
LogMessage("Moving input files to subfolders...", 3, "SweepInput")
$iResult = MoveToSubfolders($sWorkingDirectory, $sTemplateFile)
If (Not $iResult) Or @error Then
ThrowError("Error while moving input files to subfolders", 3, "SweepInput", @error)
SetError(4)
EndIf
; Create results file and write headers
;~ LogMessage("Creating batch results output file...", 3, "SweepInput")
;~ UpdateProgress($g_sProgressType, Round(($iParameters + 1)/($iParameters + 2) * 100), "Creating batch results output file")
;~ $iResult = CreateResultsFile($asParameters, $sWorkingDirectory, $sResultsFile)
;~ If (Not $iResult) Or @error Then
;~ ThrowError("Error building batch results output file.", 4, "SweepInput", @error)
;~ SetError(4)
;~ EndIf
; Exit
LogMessage("End of parameter sweep preparations.", 3, "SweepInput")
UpdateProgress($g_sProgressType, 100, "End of parameter sweep preparations")
Return (Not @error)
EndFunc
; Function to clear up existing input files in the working directory
Func DeleteInputFiles($sWorkingDirectory = @WorkingDir, $sTemplateFile = "Template.txt")
LogMessage("Called `DeleteInputFiles($sWorkingDirectory = " & $sWorkingDirectory & ", $sTemplateFile = " & $sTemplateFile & ")`", 5)
; Declarations
Local $bMoveTemplate = False
; Check that the template file doesn't have the extension "in"
If StringCompare(StringRight($sTemplateFile, 3), "*.in") = 0 Then
$bMoveTemplate = True
FileMove($sWorkingDirectory & "\" & $sTemplateFile, $sWorkingDirectory & "\" & StringTrimRight($sTemplateFile,3) & ".bak", $FC_OVERWRITE)
EndIf
If @error Then
ThrowError("Error with template file " & $sTemplateFile, 3, "DeleteInputFiles", @error)
SetError(1)
Return 0
EndIf
; Delete all *.in files
;~ DeleteFiles("*.in", $sWorkingDirectory)
;~ If @error Then
;~ ThrowError("Error deleting input files", 3, "DeleteInputFiles", @error)
;~ SetError(2)
;~ EndIf
; Put back the template file if required
If $bMoveTemplate Then FileMove($sWorkingDirectory & "\" & StringTrimRight($sTemplateFile,3) & ".bak", $sWorkingDirectory & "\" & $sTemplateFile, $FC_OVERWRITE)
; Exit
Return (Not @error)
EndFunc
; Function to find sweep files and copy them to the working directory
Func FindSweepFiles($sWorkingDirectory = @WorkingDir, $sSweepFile = "Sweep.xlsx", $sTemplateFile = "Template.txt", $sInputFolder = "Input")
LogMessage("Called `FindSweepFiles($sWorkingDirectory = " & $sWorkingDirectory & ", $sSweepFile = " & $sSweepFile & ", $sTemplateFile = " & $sTemplateFile & ", $sInputFolder = " & $sInputFolder & ")`", 5)
; Find sweep definition file
If FindFile($sSweepFile, $sWorkingDirectory, $sWorkingDirectory & "\" & $sInputFolder, True) Then
LogMessage("Found sweep parameters spreadsheet `" & $sSweepFile & "`", 4, "FindSweepFiles")
Else
ThrowError("Sweep parameters spreadsheet `" & $sSweepFile & "` not found.", 3, "FindSweepFiles", @error)
SetError(1)
Return 0
EndIf
; Find template file
If FindFile($sSweepFile, $sWorkingDirectory, $sWorkingDirectory & "\" & $sInputFolder, True) Then
LogMessage("Found template file `" & $sTemplateFile & "`", 4, "FindSweepFiles")
Else
ThrowError("Template file `" & $sTemplateFile & "` not found.", 3, "FindSweepFiles", @error)
SetError(2)
Return 0
EndIf
; Exit
Return (Not @error)
EndFunc
; Function to load sweep parameters from spreadsheet
Func LoadSweepParameters(ByRef $asParameters, ByRef $asValues, $sWorkingDirectory = @WorkingDir, $sSweepFile = "Sweep.xlsx")
LogMessage("Called `LoadSweepParameters(ByRef $asParameters, ByRef $asValues, $sWorkingDirectory = " & $sWorkingDirectory & ", $sSweepFile = " & $sSweepFile & ")`", 5)
; Declarations
Local $oExcel, $oWorkbook
; Open Excel
$oExcel = _Excel_Open(False)
If @error Then
ThrowError("Error creating the Excel application object.", 3, "LoadSweepParameters", @error)
SetError(1)
Return 0
EndIf
; Open the spreadsheet
LogMessage("Opening workbook `" & $sWorkingDirectory & "\" & $sSweepFile & "`", 3, "LoadSweepParameters")
$oWorkbook = _Excel_BookOpen($oExcel, $sWorkingDirectory & "\" & $sSweepFile)
If @error Then
ThrowError("Error opening workbook `" & $sSweepFile & "`", 3, "LoadSweepParameters", @error)
SetError(2)
Return 0
EndIf
; Read in parameter details from Excel file
$nParameters = _Excel_RangeRead($oWorkbook, 1, "B1")
$asParameters = _Excel_RangeRead($oWorkbook, 1, "A4:D" & $nParameters + 3)
If @error Then
ThrowError("Error reading parameters from workbook.", 3, "LoadSweepParameters", @error)
SetError(3)
Return 0
EndIf
LogMessage("Loaded " & $nParameters & " parameter definitions", 3, "LoadSweepParameters")
; Read in parameter values from Excel file
$nValues = _ArrayMax($asParameters,1,-1,-1,1)
If $nParameters = 1 Then
; Workaround to force $values to be a 2D array to avoid errors when only one parameter is swept
$asValues = _Excel_RangeRead($oWorkbook, 2, "A2:" & Chr(Asc("A") + $nParameters) & $nvalues + 1)
Else
$asValues = _Excel_RangeRead($oWorkbook, 2, "A2:" & Chr(Asc("A") + $nParameters - 1) & $nvalues + 1)
EndIf
If @error Then
ThrowError("Error reading parameter values from workbook.", 3, "LoadSweepParameters", @error)
SetError(34)
Return 0
EndIf
LogMessage("Loaded parameter values for all defined parameters", 3, "LoadSweepParameters")
; Close Excel
_Excel_Close($oExcel)
If @error Then
ThrowError("Error closing Excel.", 3, "LoadSweepParameters", @error)
SetError(5)
EndIf
; Exit
Return (Not @error)
EndFunc
; Function to sweep through a parameter and create input files for each value of that parameter
Func SweepParameter($asParameters, $asValues, $iParameter = 0, $sWorkingDirectory = @WorkingDir, $sTemplateFile = "Template.txt")
LogMessage("Called `SweepParameter($asParameters, $asValues, $iParameter = " & $iParameter & ", $sWorkingDirectory = " & $sWorkingDirectory & ", $sTemplateFile = " & $sTemplateFile & ")`", 5)
; Declarations
Local $iValue = 0
Local $asBaseFiles
Local $sBaseFile = "", $sCurrentFile
; Build list of base files from which to build the next level of the parameter sweep
If $iParameter = 0 Then
; For the first parameter, create the set of input files from the template
$sBaseFile = $sTemplateFile
Dim $asBaseFiles[1] = [$sBaseFile]
Else
; For subsequent parameters, copy the existing input files and expand the parameter sweep.
$asBaseFiles = _FileListToArray($sWorkingDirectory, "*.in.tmp")
; The first entry is a count of files, not required
_ArrayDelete($asBaseFiles, 0)
EndIf
If @error Then
ThrowError("Error getting list of existing input files.", 3, "SweepParameter", @error)
SetError(1)
Return 0
EndIf
; Loop through all values for this parameter
For $iValue = 0 To $asParameters[$iParameter][1] - 1
; Loop through all existing base files
For $sBaseFile In $asBaseFiles
; Build filenames
If $iParameter = 0 Then
; For first parameter, the filename is just the value of the first parameter
$sCurrentFile = $asValues[$iValue][$iParameter] & ".in.tmp"
Else
; For subsequent parameters, we need to skip the original template and modify the existing sweep files
If $sBaseFile = $sTemplateFile Then ContinueLoop
; Add the value of the current parameter to name of the files that have already been swept
$sCurrentFile = StringTrimRight($sBaseFile, 7) & "-" & $asValues[$iValue][$iParameter] & ".in.tmp"
EndIf
If @error Then
ThrowError("Error building input file name for value #" & $iValue & " of parameter #" & $iParameter & " (" & $asParameters[$iParameter][0] & " = " & $asValues[$iValue][$iParameter] & ")", 3, "SweepParameter", @error)
; Move to next file
SetError(0)
ContinueLoop
EndIf
; Copy files
FileCopy($sWorkingDirectory & "\" & $sBaseFile, $sWorkingDirectory & "\" & $sCurrentFile, $FC_OVERWRITE)
If @error Then
ThrowError("Error creating input file `" & $sCurrentFile & "` from base file `" & $sBaseFile & "`", 3, "SweepParameter", @error)
; Move to next file
SetError(0)
ContinueLoop
EndIf
; Replace the dummy code for this current parameter with the value of the parameter
_ReplaceStringInFile($sWorkingDirectory & "\" & $sCurrentFile, $asParameters[$iParameter][3], $asValues[$iValue][$iParameter], $STR_CASESENSE)
If @error Then
ThrowError("Error modifying input file `" & $sCurrentFile & "`", 3, "SweepParameter", @error)
; Move to next file
SetError(0)
ContinueLoop
EndIf
; Report success
LogMessage("Created input file `" & $sCurrentFile & "`", 3, "SweepParameter")
Next ; $asBaseFiles
Next ; $iValue
; At the end of the value loop, delete the base files for previous parameters
If $iParameter > 0 Then
For $sBaseFile In $asBaseFiles
FileDelete($sWorkingDirectory & "\" & $sBaseFile)
If @error Then
ThrowError("Error deleting base file `" & $sBaseFile & "`", 3, "SweepParameter", @error)
; Move to next file
SetError(0)
ContinueLoop
EndIf
LogMessage("Deleted base file `" & $sBaseFile & "`", 3, "SweepParameter")
Next ; $sBaseFile
EndIf
; Exit
Return (Not @error)
EndFunc
; Function to copy input files to source folders
Func MoveToSubfolders($sWorkingDirectory = @WorkingDir, $sTemplateFile = "Template.txt")
LogMessage("Called `MoveToSubfolders($sWorkingDirectory = " & $sWorkingDirectory & ", $sTemplateFile = " & $sTemplateFile & ")`", 5)
; Declarations
Local $iValue = 0
Local $asInputFiles
Local $sCurrentFile, $sCurrentSubfolder
; Get list of temporary input files
$asInputFiles = _FileListToArray($sWorkingDirectory, "*.in.tmp")
If @error Then
ThrowError("Error getting list of existing input files.", 3, "MoveToSubfolders", @error)
SetError(1)
Return 0
EndIf
; Loop through input files
For $sCurrentFile In $asInputFiles
; Get folder name
$sCurrentSubfolder = StringTrimRight($sCurrentFile, 7)
; Move and rename temporary input file
FileMove($sWorkingDirectory & "\" & $sCurrentFile, $sWorkingDirectory & "\" & $sCurrentSubfolder & "\" & $sTemplateFile, $FC_OVERWRITE + $FC_CREATEPATH)
If @error Then
ThrowError("Error moving input files.", 3, "MoveToSubfolders", @error)
SetError(2)
Return 0
EndIf
; Copy other input files
CopyFiles("*.in", $sWorkingDirectory, $sWorkingDirectory & "\" & $sCurrentSubfolder, False)
If @error Then
ThrowError("Error copying input files.", 3, "MoveToSubfolders", @error)
SetError(2)
Return 0
EndIf
Next ; $sCurrentFile
EndFunc