Reputation: 5
I wrote a script which edits a .txt file of a simulation program (LTspice) and then runs the simulation using the modified .txt file.
There are eight values (with three possible states) which I want to change independently for each iteration. Therefore I used eight for loops to iterate through all the combinations by searching and replacing the strings in the .txt file. This looks like this:
Txt_original = 'SIM_COM_Automated_Copy.txt' #LTSpice output file has to be copied manually first
rawDataFile = 'SIM_COM_Automated_Copy.raw'
list1 =[]
list2 = []
with open(Txt_original, 'rb') as file:
Data_backup = file.read()
resistorValues = [['Res1=1980', 'Res1=2000', 'Res1=2020'],['Res2=1980', 'Res2=2000', 'Res2=2020'], ['Res3=1980', 'Res3=2000', 'Res3=2020'], ['Res4=1980', 'Res4=2000', 'Res4=2020'], ['Res7=19800', 'Res7=20000', 'Res7=20200'], ['Res8=9900', 'Res8=10000', 'Res8=10100'], ['Res16=19800', 'Res16=20000', 'Res16=20200'], ['Res17=9900', 'Res17=10000', 'Res17=10100']]
count = 0
for a in range(1,3):
editSimParameters(Txt_original, resistorValues[0][0], resistorValues[0][a] ) #Res1
for b in range(1,3):
editSimParameters(Txt_original, resistorValues[1][0], resistorValues[1][b] ) #Res2
for c in range(1,3):
editSimParameters(Txt_original, resistorValues[2][0], resistorValues[2][c] ) #Res3
for d in range(1,3):
editSimParameters(Txt_original, resistorValues[3][0], resistorValues[3][d] ) #Res4
for e in range(1,2):
editSimParameters(Txt_original, resistorValues[4][0], resistorValues[4][e] ) #Res7
for f in range(1,2):
editSimParameters(Txt_original, resistorValues[5][0], resistorValues[5][f] ) #Res8
for g in range(1,2):
editSimParameters(Txt_original, resistorValues[6][0], resistorValues[6][g] ) #Res16
for h in range(1,2):
editSimParameters(Txt_original, resistorValues[7][0], resistorValues[7][h] ) #Res17
runSimulation(Txt_original)
#time.sleep(10)
result = evaluateResults(rawDataFile)
valueSet = [a, b, c, d, e, f, g, h]
if valueSet == [2,2,2,2,1,1,1,1]:
print('Res1= '+resistorValues[0][a])
print('Res2= '+resistorValues[1][b])
print('Res3= '+resistorValues[2][c])
print('Res4= '+resistorValues[3][d])
print('Res7= '+resistorValues[4][e])
print('Res8= '+resistorValues[5][f])
print('Res16= '+resistorValues[6][g])
print('Res17= '+resistorValues[7][h])
print('The result of the combination ' + str(valueSet) + ' is ' + str(result))
list1.append(result)
list2.append(valueSet)
with open(Txt_original, 'wb') as file: #Reset the working file
file.write(Data_backup)
#Progress Tracking
count = count +1
if count%25 == 0:
print(count)
The editSimParameters() function looks like this:
def editSimParameters(workingFile, oldParam, newParam):
with open(workingFile, 'rb') as file:
Data_original = file.read()
Data_temp = Data_original.replace(oldParam.encode('utf-8'), newParam.encode('utf-8'))
with open(workingFile, 'wb') as file:
file.write(Data_temp)
I have reduced the number of loop iteration in this example, so that the code terminates faster. Nonetheless when running this code the result for the combination [2,2,2,2,1,1,1,1] is different to the result of the same combination which I obtained by altering the for loops, so that only this combination is executed:
Result after the iteration (16 simulations in total): The result of the combination [2, 2, 2, 2, 1, 1, 1, 1] is 16.347881
Result with altered for loops (1 simulation): The result of the combination [2, 2, 2, 2, 1, 1, 1, 1] is 16.327114
The result with just one simulation is correct which I verified by doing the simulation manually.
Am I overseeing a problem when iterating over and changing the .txt file or is there anything else?
Upvotes: 0
Views: 71
Reputation: 169398
Here's a much simplified (and more powerful) version of what you seem to be trying to do, using itertools.product
and a regular expression to replace the resistor values.
The idea is that we
zip
magic to massage that dictionary into a form itertools.product
acceptsitertools.product
to generate the cartesian product of the values, then zip
them back with the keys to get a combo
dictre.sub
to substitute those values into (a copy of) the template.print()
ing the data
like we do here, you'd write that out to the file you feed to the simulator, and do what you must there. I would recommend not overwriting the original template file.You can add as many keys and values to the resistor_combos
dict as you like, and they'll all be exhaustively checked.
import itertools
import re
# Would be read from the original SIM_COM_Automated_Copy file
template = """
Res1=100
Res2=100
Res8=1000
""".strip()
resistor_combos = {
"Res1": [123, 456],
"Res2": [789, 126],
}
resistor_keys, resistor_values = zip(*resistor_combos.items())
for value_combo in itertools.product(*resistor_values):
combo = dict(zip(resistor_keys, value_combo))
data = template # "Copy" the template for modification
for key, value in combo.items():
data = re.sub(f"^{key}=(\d+)", f"{key}={value}", data, flags=re.MULTILINE)
print(combo)
print(data)
print("====")
This prints out
{'Res1': 123, 'Res2': 789}
Res1=123
Res2=789
Res8=1000
====
{'Res1': 123, 'Res2': 126}
Res1=123
Res2=126
Res8=1000
====
{'Res1': 456, 'Res2': 789}
Res1=456
Res2=789
Res8=1000
====
{'Res1': 456, 'Res2': 126}
Res1=456
Res2=126
Res8=1000
====
Upvotes: 4