digichem-core 6.10.1__py3-none-any.whl → 6.10.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- digichem/__init__.py +2 -2
- digichem/config/base.py +1 -1
- digichem/image/render.py +6 -4
- digichem/misc/io.py +11 -0
- digichem/parse/cclib.py +47 -11
- digichem/parse/pyscf.py +13 -3
- digichem/result/metadata.py +45 -10
- digichem/test/conftest.py +5 -0
- digichem/test/mock/cubegen +87172 -0
- digichem/test/mock/formchk +9456 -0
- digichem/test/test_image.py +54 -42
- digichem/test/util.py +2 -0
- {digichem_core-6.10.1.dist-info → digichem_core-6.10.3.dist-info}/METADATA +1 -1
- {digichem_core-6.10.1.dist-info → digichem_core-6.10.3.dist-info}/RECORD +17 -15
- {digichem_core-6.10.1.dist-info → digichem_core-6.10.3.dist-info}/WHEEL +0 -0
- {digichem_core-6.10.1.dist-info → digichem_core-6.10.3.dist-info}/licenses/COPYING.md +0 -0
- {digichem_core-6.10.1.dist-info → digichem_core-6.10.3.dist-info}/licenses/LICENSE +0 -0
digichem/__init__.py
CHANGED
|
@@ -20,7 +20,7 @@ from digichem.datas import get_resource
|
|
|
20
20
|
# development = prerelease is not None
|
|
21
21
|
# # The full version number of this package.
|
|
22
22
|
# __version__ = "{}.{}.{}{}".format(major_version, minor_version, revision, "-pre.{}".format(prerelease) if development else "")
|
|
23
|
-
__version__ = "6.10.
|
|
23
|
+
__version__ = "6.10.3"
|
|
24
24
|
_v_parts = __version__.split("-")[0].split(".")
|
|
25
25
|
major_version = int(_v_parts[0])
|
|
26
26
|
minor_version = int(_v_parts[1])
|
|
@@ -39,7 +39,7 @@ __author__ = [
|
|
|
39
39
|
]
|
|
40
40
|
|
|
41
41
|
# Program date (when we were last updated). This is changed automatically.
|
|
42
|
-
_last_updated_string = "
|
|
42
|
+
_last_updated_string = "09/06/2025"
|
|
43
43
|
last_updated = datetime.strptime(_last_updated_string, "%d/%m/%Y")
|
|
44
44
|
|
|
45
45
|
# The sys attribute 'frozen' is our flag, '_MEIPASS' is the dir location.
|
digichem/config/base.py
CHANGED
|
@@ -72,7 +72,7 @@ Possible options are:
|
|
|
72
72
|
),
|
|
73
73
|
batoms = Options(help = "Beautiful Atoms/Blender specific options (only applies if engine == 'batoms'",
|
|
74
74
|
blender = Option(help = "Path to the blender executable, in which beautiful atoms should be installed", default = "batoms-blender"),
|
|
75
|
-
cpus = Option(help = "The number of CPUs/threads to use. This option is overridden if running in a calculation
|
|
75
|
+
cpus = Option(help = "The number of CPUs/threads to use. This option is overridden if running in a calculation environment (where it uses the same number of CPUs as the calculation did)", type = int, default = 1),
|
|
76
76
|
render_samples = Option(help = "The number of render samples (or passes) to use. Higher values result in higher image quality and greater render times", type = int, default = 32),
|
|
77
77
|
perspective = Option(help = "The perspective mode", choices = ["orthographic", "perspective"], default = "perspective"),
|
|
78
78
|
stacking = Option(help = "The number of image copies to composite together to avoid transparency artifacts", type = int, default = 10)
|
digichem/image/render.py
CHANGED
|
@@ -247,7 +247,6 @@ class Batoms_renderer(Render_maker):
|
|
|
247
247
|
# "--render-samples", f"{samples}",
|
|
248
248
|
"--perspective", f"{self.perspective}",
|
|
249
249
|
"--padding", f"{padding}",
|
|
250
|
-
"--rotations",
|
|
251
250
|
]
|
|
252
251
|
for orientation, resolution, samples, mini_file_name in targets:
|
|
253
252
|
args.extend([
|
|
@@ -258,9 +257,12 @@ class Batoms_renderer(Render_maker):
|
|
|
258
257
|
mini_file_name
|
|
259
258
|
])
|
|
260
259
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
260
|
+
if len(self.rotations) > 0:
|
|
261
|
+
args.append("--rotations")
|
|
262
|
+
|
|
263
|
+
# Add rotations.
|
|
264
|
+
for rotation in self.rotations:
|
|
265
|
+
args.append(json.dumps(rotation))
|
|
264
266
|
|
|
265
267
|
return args
|
|
266
268
|
|
digichem/misc/io.py
CHANGED
|
@@ -6,6 +6,7 @@ import os
|
|
|
6
6
|
import shutil
|
|
7
7
|
import sys
|
|
8
8
|
import warnings
|
|
9
|
+
import itertools
|
|
9
10
|
from uuid import uuid4
|
|
10
11
|
import hashlib
|
|
11
12
|
|
|
@@ -320,3 +321,13 @@ class Safe_path():
|
|
|
320
321
|
"""
|
|
321
322
|
# Close our file.
|
|
322
323
|
self.close()
|
|
324
|
+
|
|
325
|
+
def dir_size(target):
|
|
326
|
+
"""
|
|
327
|
+
Calculate the total used file space of a directory and all contents.
|
|
328
|
+
"""
|
|
329
|
+
bytes = 0
|
|
330
|
+
for path in itertools.chain(Path(target).rglob("*"), [Path(target)]):
|
|
331
|
+
bytes += path.stat().st_size
|
|
332
|
+
|
|
333
|
+
return bytes
|
digichem/parse/cclib.py
CHANGED
|
@@ -156,15 +156,49 @@ class Cclib_parser(File_parser_abc):
|
|
|
156
156
|
headers = next(reader)
|
|
157
157
|
|
|
158
158
|
# Check headers match.
|
|
159
|
-
if (headers[0]
|
|
160
|
-
headers[1]
|
|
161
|
-
headers[2]
|
|
162
|
-
headers[3]
|
|
163
|
-
headers[4]
|
|
164
|
-
headers[9]
|
|
165
|
-
headers[15]
|
|
166
|
-
headers[17]
|
|
159
|
+
if (headers[0] == "Duration / s" and
|
|
160
|
+
headers[1] == "Memory Used (Real) / bytes" and
|
|
161
|
+
headers[2] == "Memory Used (Real) / %" and
|
|
162
|
+
headers[3] == "Memory Available (Real) / bytes" and
|
|
163
|
+
headers[4] == "Memory Available (Real) / %" and
|
|
164
|
+
headers[9] == "CPU Usage / %" and
|
|
165
|
+
headers[15] == "Output Directory Available / bytes" and
|
|
166
|
+
headers[17] == "Scratch Directory Used / bytes" and
|
|
167
|
+
headers[18] == "Scratch Directory Available / bytes"
|
|
167
168
|
):
|
|
169
|
+
column_map = {
|
|
170
|
+
"duration": 0,
|
|
171
|
+
"memory_used": 1,
|
|
172
|
+
"memory_used_percent": 2,
|
|
173
|
+
"memory_available": 3,
|
|
174
|
+
"memory_available_percent": 4,
|
|
175
|
+
"cpu_used": 9,
|
|
176
|
+
"output_available": 15,
|
|
177
|
+
"scratch_used": 17,
|
|
178
|
+
"scratch_available": 18
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
elif (headers[0] == "Duration / s" and
|
|
182
|
+
headers[1] == "Memory Used (Real) / bytes" and
|
|
183
|
+
headers[2] == "Memory Used (Real) / %" and
|
|
184
|
+
headers[3] == "Memory Available (Real) / bytes" and
|
|
185
|
+
headers[4] == "Memory Available (Real) / %" and
|
|
186
|
+
headers[9] == "CPU Usage / %" and
|
|
187
|
+
headers[15] == "Output Directory Available / bytes" and
|
|
188
|
+
headers[17] == "Scratch Directory Available / bytes"
|
|
189
|
+
):
|
|
190
|
+
column_map = {
|
|
191
|
+
"duration": 0,
|
|
192
|
+
"memory_used": 1,
|
|
193
|
+
"memory_used_percent": 2,
|
|
194
|
+
"memory_available": 3,
|
|
195
|
+
"memory_available_percent": 4,
|
|
196
|
+
"cpu_used": 9,
|
|
197
|
+
"output_available": 15,
|
|
198
|
+
"scratch_available": 17
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
else:
|
|
168
202
|
raise Digichem_exception("wrong headers found in profile.csv file")
|
|
169
203
|
|
|
170
204
|
# Then the body.
|
|
@@ -185,17 +219,19 @@ class Cclib_parser(File_parser_abc):
|
|
|
185
219
|
# - cpu used
|
|
186
220
|
# - output space
|
|
187
221
|
# - scratch space
|
|
188
|
-
new_data = numpy.zeros((math.ceil(lines / factor),
|
|
222
|
+
new_data = numpy.zeros((math.ceil(lines / factor), len(column_map)))
|
|
189
223
|
|
|
190
224
|
# Now decimate.
|
|
191
|
-
for i, k in enumerate(
|
|
225
|
+
for i, k in enumerate(column_map.values()):
|
|
192
226
|
if factor > 1:
|
|
193
227
|
new_data[:, i] = signal.decimate(data[:, k], factor)
|
|
194
228
|
else:
|
|
195
229
|
new_data[:, i] = data[:, k]
|
|
196
230
|
|
|
197
231
|
|
|
198
|
-
self.data.metadata['performance'] =
|
|
232
|
+
self.data.metadata['performance'] = {
|
|
233
|
+
key: new_data[:, index] for index, key in enumerate(column_map)
|
|
234
|
+
}
|
|
199
235
|
|
|
200
236
|
|
|
201
237
|
def parse_output_line(self, log_file, line):
|
digichem/parse/pyscf.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import hashlib
|
|
2
2
|
import json
|
|
3
|
+
from uuid import uuid4
|
|
3
4
|
|
|
4
5
|
from cclib.bridge.cclib2pyscf import cclibfrommethods
|
|
5
6
|
|
|
6
7
|
from digichem.parse.base import Parser_abc
|
|
8
|
+
import digichem.log
|
|
7
9
|
|
|
8
10
|
class Pyscf_parser(Parser_abc):
|
|
9
11
|
"""
|
|
@@ -17,9 +19,17 @@ class Pyscf_parser(Parser_abc):
|
|
|
17
19
|
|
|
18
20
|
def _parse(self):
|
|
19
21
|
self.data = cclibfrommethods(**self.methods)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
# Try to generate a checksum from metadata.
|
|
25
|
+
self.data._id = hashlib.sha1(json.dumps(self.data.metadata, sort_keys = True).encode('utf-8')).hexdigest()
|
|
26
|
+
|
|
27
|
+
except Exception:
|
|
28
|
+
# No luck, something in metadata must be unhashable.
|
|
29
|
+
digichem.log.get_logger().error("Unable to generate hash ID from calculation metadata, using random ID instead", exc_info = True)
|
|
30
|
+
# TODO: Think of a better way to do this.
|
|
31
|
+
self.data._id = hashlib.sha1(uuid4().hex.encode('utf-8')).hexdigest()
|
|
32
|
+
|
|
22
33
|
self.data.metadata['name'] = self.mol_name
|
|
23
34
|
self.data._aux = {'methods': self.methods}
|
|
24
|
-
|
|
25
35
|
|
digichem/result/metadata.py
CHANGED
|
@@ -679,8 +679,9 @@ class Performance(Result_object):
|
|
|
679
679
|
memory_available = [],
|
|
680
680
|
memory_available_percent = [],
|
|
681
681
|
cpu_used = [],
|
|
682
|
-
|
|
683
|
-
|
|
682
|
+
output_available = [],
|
|
683
|
+
scratch_used = [],
|
|
684
|
+
scratch_available = [],
|
|
684
685
|
memory_allocated = None,
|
|
685
686
|
cpu_allocated = None,
|
|
686
687
|
):
|
|
@@ -690,11 +691,22 @@ class Performance(Result_object):
|
|
|
690
691
|
self.memory_available = memory_available
|
|
691
692
|
self.memory_available_percent = memory_available_percent
|
|
692
693
|
self.cpu_used = cpu_used
|
|
693
|
-
self.
|
|
694
|
-
self.
|
|
694
|
+
self.output_available = output_available
|
|
695
|
+
self.scratch_used = scratch_used
|
|
696
|
+
self.scratch_available = scratch_available
|
|
695
697
|
|
|
696
698
|
self.memory_allocated = memory_allocated if memory_allocated is not None else self.max_mem
|
|
697
699
|
self.cpu_allocated = cpu_allocated if cpu_allocated is not None else math.ceil(max(cpu_used) / 100)
|
|
700
|
+
|
|
701
|
+
@property
|
|
702
|
+
def output_space(self):
|
|
703
|
+
warnings.warn("output_space is deprecated, use output_available instead", DeprecationWarning)
|
|
704
|
+
return self.output_available
|
|
705
|
+
|
|
706
|
+
@property
|
|
707
|
+
def scratch_space(self):
|
|
708
|
+
warnings.warn("scratch_space is deprecated, use scratch_available instead", DeprecationWarning)
|
|
709
|
+
return self.scratch_available
|
|
698
710
|
|
|
699
711
|
|
|
700
712
|
@classmethod
|
|
@@ -705,6 +717,21 @@ class Performance(Result_object):
|
|
|
705
717
|
:param parser: Output data parser.
|
|
706
718
|
:return: A populated Performance object.
|
|
707
719
|
"""
|
|
720
|
+
return self(
|
|
721
|
+
duration = parser.data.metadata['performance']['duration'].tolist(),
|
|
722
|
+
memory_used = parser.data.metadata['performance']['memory_used'].tolist(),
|
|
723
|
+
memory_allocated = Memory(parser.data.metadata['memory_available']) if "memory_available" in parser.data.metadata else None,
|
|
724
|
+
memory_used_percent = parser.data.metadata['performance']['memory_used_percent'].tolist(),
|
|
725
|
+
memory_available = parser.data.metadata['performance']['memory_available'].tolist(),
|
|
726
|
+
memory_available_percent = parser.data.metadata['performance']['memory_available_percent'].tolist(),
|
|
727
|
+
cpu_used = parser.data.metadata['performance']['cpu_used'].tolist(),
|
|
728
|
+
cpu_allocated = parser.data.metadata.get('num_cpu', None),
|
|
729
|
+
output_available = parser.data.metadata['performance']['output_available'].tolist(),
|
|
730
|
+
scratch_used = parser.data.metadata['performance']['scratch_used'].tolist() if 'scratch_used' in parser.data.metadata['performance'] else [0] * len(parser.data.metadata['performance']['duration']),
|
|
731
|
+
scratch_available = parser.data.metadata['performance']['scratch_available'].tolist()
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
|
|
708
735
|
return self(
|
|
709
736
|
duration = parser.data.metadata['performance'][:, 0].tolist(),
|
|
710
737
|
memory_used = parser.data.metadata['performance'][:, 1].tolist(),
|
|
@@ -788,8 +815,9 @@ class Performance(Result_object):
|
|
|
788
815
|
memory_available_percent = [0.0] * len(data['values'])
|
|
789
816
|
cpu_used = [0.0] * len(data['values'])
|
|
790
817
|
cpu_allocated = data['cpu_allocated']
|
|
791
|
-
|
|
792
|
-
|
|
818
|
+
output_available = [0.0] * len(data['values'])
|
|
819
|
+
scratch_used = [0.0] * len(data['values'])
|
|
820
|
+
scratch_available = [0.0] * len(data['values'])
|
|
793
821
|
|
|
794
822
|
for i, value in enumerate(data['values']):
|
|
795
823
|
duration[i] = value['duration']['value']
|
|
@@ -798,8 +826,10 @@ class Performance(Result_object):
|
|
|
798
826
|
memory_available[i] = value['memory_available']['value']
|
|
799
827
|
memory_available_percent[i] = value['memory_available_percent']['value']
|
|
800
828
|
cpu_used[i] = value['cpu_used']['value']
|
|
801
|
-
|
|
802
|
-
|
|
829
|
+
output_available[i] = value['output_space']['value']
|
|
830
|
+
if 'scratch_used' in value:
|
|
831
|
+
scratch_used[i] = value['scratch_used']['value']
|
|
832
|
+
scratch_available[i] = value['scratch_space']['value']
|
|
803
833
|
|
|
804
834
|
return self(
|
|
805
835
|
duration = duration,
|
|
@@ -810,8 +840,9 @@ class Performance(Result_object):
|
|
|
810
840
|
memory_available_percent = memory_available_percent,
|
|
811
841
|
cpu_used = cpu_used,
|
|
812
842
|
cpu_allocated = cpu_allocated,
|
|
813
|
-
|
|
814
|
-
|
|
843
|
+
output_available = output_available,
|
|
844
|
+
scratch_used = scratch_used,
|
|
845
|
+
scratch_available = scratch_available
|
|
815
846
|
)
|
|
816
847
|
|
|
817
848
|
|
|
@@ -871,6 +902,10 @@ class Performance(Result_object):
|
|
|
871
902
|
"units": "bytes",
|
|
872
903
|
"value": self.output_space[i]
|
|
873
904
|
},
|
|
905
|
+
'scratch_used': {
|
|
906
|
+
"units": "bytes",
|
|
907
|
+
"value": self.scratch_used[i]
|
|
908
|
+
},
|
|
874
909
|
'scratch_space': {
|
|
875
910
|
"units": "bytes",
|
|
876
911
|
"value": self.scratch_space[i]
|
digichem/test/conftest.py
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import numpy
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
2
4
|
|
|
3
5
|
# Set numpy errors (not sure why this isn't the default...)
|
|
4
6
|
numpy.seterr(invalid = 'raise', divide = 'raise')
|
|
7
|
+
|
|
8
|
+
# Expand path to include mocks.
|
|
9
|
+
os.environ["PATH"] = str(Path(__file__).parent / "mock") + os.pathsep + os.environ["PATH"]
|