-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboltzmann
executable file
·169 lines (123 loc) · 3.91 KB
/
boltzmann
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
#!/home/vport/projects/scripts/.scripts_environment/bin/python
import os
import argparse
import glob
from pathlib import Path
from math import exp
from rich.console import Console
from rich.table import Table
K = 0.001987204259
XTBHESSEXT = ".sph"
class GibbsEnergyNotFound(Exception):
pass
def parse_arguments():
parser = argparse.ArgumentParser(
description="Calculate the boltzmann distribution of a set of ORCA logfiles."
)
# Add temperature argument with a default value of 293 Kelvin
parser.add_argument(
"-t",
"--temperature",
type=float,
default=293,
help="Temperature in Kelvin (default: 293)",
)
# Add temperature argument with a default value of 293 Kelvin
parser.add_argument(
"-x",
"--xtbhess",
action="store_true",
help="Use the single point hessian from xtb",
)
parser.add_argument(
"-r",
"--remove",
type=float,
default=0,
help="Remove all files above a certain threshhold",
)
parser.add_argument(
"files", nargs="+", help="List of files (at least two are required)"
)
# Parse arguments
args = parser.parse_args()
# Check if at least two files are provided
if len(args.files) < 2:
parser.error("At least two files are required.")
return args
def parse_gibbs_orca(file: str):
energy = 0
with open(file, "r") as f:
lines = f.readlines()
for line in lines:
if "Final Gibbs free energy" in line:
energy = float(line.split()[-2])
# else:
if energy == 0:
return GibbsEnergyNotFound
return energy
def parse_gibbs_orca_xtb(file: str):
hessfile = Path(file).stem + XTBHESSEXT
electronic_energy = 0
grrho = 0
with open(file, "r") as f:
lines = f.readlines()
for line in lines:
if "FINAL SINGLE POINT ENERGY" in line:
electronic_energy = float(line.split()[-1])
with open(hessfile, "r") as f:
hesslines = f.readlines()
for line in hesslines:
if "G(RRHO) contrib" in line:
grrho = float(line.replace(":", "").rstrip().split(" ")[-2])
return electronic_energy + grrho
def clean_files(energy_dict: dict[str, float], threshold):
remove = [k for k, v in energy_dict.items() if v > threshold]
remove = [Path(file).stem for file in remove]
for rootname in remove:
for filename in glob.glob(f"./{rootname}*"):
os.remove(filename)
def gibbs_factor(energy, temperature):
return exp(-energy / (K * temperature))
def main():
args = parse_arguments()
if args.xtbhess:
energy_dict = {
file: parse_gibbs_orca_xtb(file) * 627.503 for file in args.files
}
else:
energy_dict = {file: parse_gibbs_orca(file) * 627.503 for file in args.files}
energy_dict = {
file: (energy - min(energy_dict.values()))
for file, energy in energy_dict.items()
}
exponentials = {}
for k, v in energy_dict.items():
exponentials[k] = gibbs_factor(v, args.temperature)
normalization_factor = sum(exponentials.values())
populations = {k: (v / normalization_factor) for k, v in exponentials.items()}
populations = {
k: v
for k, v in sorted(populations.items(), key=lambda item: item[1], reverse=True)
}
console = Console()
table = Table()
table.add_column("Filename")
table.add_column("Pop (%)")
table.add_column("deltaG")
table.add_column("Rank")
count = 1
for k, v in populations.items():
table.add_row(
f"{Path(k).stem}",
"{:.2f}%".format(v * 100),
"{:.3f} kcal/mol".format(energy_dict[k]),
"{}".format(count),
)
count += 1
console.print(table)
if args.remove != 0:
clean_files(energy_dict, args.remove)
# Example usage
if __name__ == "__main__":
main()