digichem-core 6.10.1__py3-none-any.whl → 7.0.0__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.
Files changed (45) hide show
  1. digichem/__init__.py +2 -2
  2. digichem/config/base.py +11 -2
  3. digichem/config/util.py +3 -2
  4. digichem/file/prattle.py +9 -7
  5. digichem/image/render.py +6 -4
  6. digichem/image/spectroscopy.py +17 -4
  7. digichem/input/__init__.py +1 -1
  8. digichem/input/digichem_input.py +39 -34
  9. digichem/misc/io.py +11 -0
  10. digichem/parse/base.py +8 -6
  11. digichem/parse/cclib.py +57 -17
  12. digichem/parse/dump.py +31 -35
  13. digichem/parse/gaussian.py +2 -2
  14. digichem/parse/pyscf.py +13 -3
  15. digichem/parse/turbomole.py +2 -3
  16. digichem/parse/util.py +6 -5
  17. digichem/result/alignment/base.py +2 -2
  18. digichem/result/atom.py +4 -4
  19. digichem/result/base.py +53 -5
  20. digichem/result/dipole_moment.py +1 -1
  21. digichem/result/emission.py +5 -5
  22. digichem/result/energy.py +8 -8
  23. digichem/result/excited_state.py +20 -13
  24. digichem/result/ground_state.py +2 -2
  25. digichem/result/metadata.py +51 -25
  26. digichem/result/nmr.py +37 -28
  27. digichem/result/orbital.py +3 -3
  28. digichem/result/result.py +14 -14
  29. digichem/result/soc.py +3 -3
  30. digichem/result/spectroscopy.py +5 -4
  31. digichem/result/tdm.py +5 -5
  32. digichem/result/vibration.py +15 -6
  33. digichem/test/conftest.py +5 -0
  34. digichem/test/mock/cubegen +87172 -0
  35. digichem/test/mock/formchk +9456 -0
  36. digichem/test/test_image.py +54 -42
  37. digichem/test/test_input.py +17 -3
  38. digichem/test/test_parsing.py +9 -0
  39. digichem/test/test_prattle.py +31 -2
  40. digichem/test/util.py +2 -0
  41. {digichem_core-6.10.1.dist-info → digichem_core-7.0.0.dist-info}/METADATA +1 -1
  42. {digichem_core-6.10.1.dist-info → digichem_core-7.0.0.dist-info}/RECORD +45 -43
  43. {digichem_core-6.10.1.dist-info → digichem_core-7.0.0.dist-info}/WHEEL +0 -0
  44. {digichem_core-6.10.1.dist-info → digichem_core-7.0.0.dist-info}/licenses/COPYING.md +0 -0
  45. {digichem_core-6.10.1.dist-info → digichem_core-7.0.0.dist-info}/licenses/LICENSE +0 -0
digichem/parse/dump.py CHANGED
@@ -25,19 +25,19 @@ class Dump_multi_parser_abc(File_parser_abc):
25
25
  ABC for classes that can read multiple result sets from dumped data.
26
26
  """
27
27
 
28
- def __init__(self, input_file, *other_log_files, raw_data = None, **auxiliary_files):
28
+ def __init__(self, input_file, *other_log_files, raw_data = None, options , **auxiliary_files):
29
29
  """
30
30
  Top level constructor for calculation parsers.
31
31
 
32
32
  :param input_file: The path to read from.
33
33
  """
34
34
  # Neither other_log_files nor auxiliary_files are currently used...
35
- super().__init__(input_file, raw_data = raw_data)
35
+ super().__init__(input_file, raw_data = raw_data, options = options)
36
36
  self.all_results = []
37
37
 
38
38
  @classmethod
39
- def from_data(self, input_file, data):
40
- return self(input_file, raw_data = data)
39
+ def from_data(self, input_file, data, options):
40
+ return self(input_file, raw_data = data, options = options)
41
41
 
42
42
  @property
43
43
  def results(self):
@@ -63,26 +63,24 @@ class Dump_multi_parser_abc(File_parser_abc):
63
63
  def get_sub_parser(self):
64
64
  raise NotImplementedError("Implement in subclass")
65
65
 
66
- def process_all(self, options):
66
+ def process_all(self):
67
67
  """
68
68
  Get all the Result set objects produced by this parser.
69
69
 
70
- :param options: A Digichem options nested dictionary containing options to control parsing.
71
70
  :return: A list of the populated result sets.
72
71
  """
73
72
  # Unlike most other parsers, our data can actually contain lots of results.
74
- self.all_results = [self.get_sub_parser()(self.log_file_path, raw_data = data).process(options) for data in self.data]
73
+ self.all_results = [self.get_sub_parser()(self.log_file_path, raw_data = data, options = self.options).process() for data in self.data]
75
74
 
76
75
  return self.all_results
77
76
 
78
- def process(self, options):
77
+ def process(self):
79
78
  """
80
79
  Get a Result set object from this parser.
81
80
 
82
- :param options: A Digichem options nested dictionary containing options to control parsing.
83
81
  :return: The populated result set.
84
82
  """
85
- self.process_all(options)
83
+ self.process_all()
86
84
  return self.results
87
85
 
88
86
 
@@ -127,65 +125,63 @@ class Dump_parser_abc(File_parser_abc):
127
125
  ABC for parsers that read dumped data.
128
126
  """
129
127
 
130
- def __init__(self, input_file, *other_log_files, raw_data = None, **auxiliary_files):
128
+ def __init__(self, input_file, *other_log_files, raw_data = None, options, **auxiliary_files):
131
129
  """
132
130
  Top level constructor for calculation parsers.
133
131
 
134
132
  :param input_file: The path to the input file to read.
135
133
  """
136
134
  # Neither other_log_files nor auxiliary_files are currently used...
137
- super().__init__(input_file, raw_data = raw_data)
135
+ super().__init__(input_file, raw_data = raw_data, options = options)
138
136
 
139
137
  @classmethod
140
- def from_data(self, input_file, data):
141
- return self(input_file, raw_data = data)
138
+ def from_data(self, input_file, data, options):
139
+ return self(input_file, raw_data = data, options = options)
142
140
 
143
- def process_all(self, options):
141
+ def process_all(self):
144
142
  """
145
143
  Get all the Result set objects produced by this parser.
146
144
 
147
- :param options: A Digichem options nested dictionary containing options to control parsing.
148
145
  :return: A list of the populated result sets.
149
146
  """
150
- self.process(options)
147
+ self.process()
151
148
  return [self.results]
152
149
 
153
- def process(self, options):
150
+ def process(self):
154
151
  """
155
152
  Get a Result set object from this parser.
156
153
 
157
- :param options: A Digichem options nested dictionary containing options to control parsing.
158
154
  :return: The populated result set.
159
155
  """
160
156
 
161
157
  # Get our result set.
162
158
  self.results = Result_set(
163
159
  _id = self.data.get("_id"),
164
- metadata = Metadata.from_dump(self.data['metadata'], self.results, options)
160
+ metadata = Metadata.from_dump(self.data['metadata'], self.results, self.options)
165
161
  )
166
162
 
167
163
  # First get our list of MOs (because we need them for excited states too.)
168
- self.results.orbitals = Molecular_orbital_list.from_dump(self.data['orbitals'], self.results, options)
169
- self.results.beta_orbitals = Molecular_orbital_list.from_dump(self.data['beta_orbitals'], self.results, options)
164
+ self.results.orbitals = Molecular_orbital_list.from_dump(self.data['orbitals'], self.results, self.options)
165
+ self.results.beta_orbitals = Molecular_orbital_list.from_dump(self.data['beta_orbitals'], self.results, self.options)
170
166
 
171
- alignment_class = Alignment.from_class_handle(options['alignment']) if options['alignment'] is not None else Minimal
167
+ alignment_class = Alignment.from_class_handle(self.options['alignment']) if self.options['alignment'] is not None else Minimal
172
168
 
173
169
  # Our alignment orientation data.
174
170
  # The constructor for each alignment class automatically performs realignment.
175
- self.results.atoms = alignment_class.from_dump(self.data['atoms'], self.results, options)
176
- self.results.raw_atoms = Atom_list.from_dump(self.data['raw_atoms'], self.results, options)
171
+ self.results.atoms = alignment_class.from_dump(self.data['atoms'], self.results, self.options)
172
+ self.results.raw_atoms = Atom_list.from_dump(self.data['raw_atoms'], self.results, self.options)
177
173
 
178
174
  # TEDM and TMDM.
179
- self.results.transition_dipole_moments = Transition_dipole_moment.list_from_dump(self.data['excited_states']['values'], self.results, options)
175
+ self.results.transition_dipole_moments = Transition_dipole_moment.list_from_dump(self.data['excited_states']['values'], self.results, self.options)
180
176
 
181
177
  # Excited states.
182
- self.results.excited_states = Excited_state_list.from_dump(self.data['excited_states'], self.results, options)
178
+ self.results.excited_states = Excited_state_list.from_dump(self.data['excited_states'], self.results, self.options)
183
179
 
184
180
  # Energies.
185
- self.results.energies = Energies.from_dump(self.data['energies'], self.results, options)
181
+ self.results.energies = Energies.from_dump(self.data['energies'], self.results, self.options)
186
182
 
187
183
  # Our ground state.
188
- self.results.ground_state = Ground_state.from_dump(self.data['ground_state'], self.results, options)
184
+ self.results.ground_state = Ground_state.from_dump(self.data['ground_state'], self.results, self.options)
189
185
 
190
186
  # And a similar list but also including the ground.
191
187
  self.results.energy_states = Excited_state_list()
@@ -193,24 +189,24 @@ class Dump_parser_abc(File_parser_abc):
193
189
  self.results.energy_states.extend(self.results.excited_states)
194
190
 
195
191
  # SOC.
196
- self.results.soc = SOC_list.from_dump(self.data['soc'], self.results, options)
192
+ self.results.soc = SOC_list.from_dump(self.data['soc'], self.results, self.options)
197
193
 
198
194
  # PDM
199
- self.results.pdm = Dipole_moment.from_dump(self.data['pdm'], self.results, options)
195
+ self.results.pdm = Dipole_moment.from_dump(self.data['pdm'], self.results, self.options)
200
196
 
201
197
  # Frequencies.
202
- self.results.vibrations = Vibrations_list.from_dump(self.data['vibrations'], self.results, options)
198
+ self.results.vibrations = Vibrations_list.from_dump(self.data['vibrations'], self.results, self.options)
203
199
 
204
200
  # NMR.
205
201
  if "nmr" in self.data:
206
- self.results.nmr = NMR_list.from_dump(self.data['nmr'], self.results, options)
202
+ self.results.nmr = NMR_list.from_dump(self.data['nmr'], self.results, self.options)
207
203
 
208
204
  else:
209
- self.results.nmr = NMR_list(atoms = self.results.atoms, options = options)
205
+ self.results.nmr = NMR_list(atoms = self.results.atoms, options = self.options)
210
206
 
211
207
  # Finally, try and set emission.
212
208
  try:
213
- self.results.emission = self.results.emission.from_dump(self.data['emission'], self.results, options)
209
+ self.results.emission = self.results.emission.from_dump(self.data['emission'], self.results, self.options)
214
210
 
215
211
  except Exception:
216
212
  digichem.log.get_logger().warning("Failed to parse emission data", exc_info = True)
@@ -29,9 +29,9 @@ class Gaussian_parser(Cclib_parser):
29
29
  CPU_TIME_HEADER = "Job cpu time:"
30
30
  CPU_HEADER = "Will use up to"
31
31
 
32
- def __init__(self, *log_files, rwfdump = "rwfdump", **auxiliary_files):
32
+ def __init__(self, *log_files, rwfdump = "rwfdump", options, **auxiliary_files):
33
33
  self.rwfdump = rwfdump
34
- super().__init__(*log_files, **auxiliary_files)
34
+ super().__init__(*log_files, options = options, **auxiliary_files)
35
35
 
36
36
  def parse_metadata(self):
37
37
  """
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
- # TODO: We need some way of generating a checksum
21
- self.data._id = hashlib.sha1(json.dumps(dir(self.data), sort_keys = True).encode('utf-8')).hexdigest()
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
 
@@ -98,14 +98,13 @@ class Turbomole_parser(Cclib_parser):
98
98
  if len(self.data.metadata['cpu_time']) == 0:
99
99
  del(self.data.metadata['cpu_time'])
100
100
 
101
- def process(self, options):
101
+ def process(self):
102
102
  """
103
103
  Get a Result set object from this parser.
104
104
 
105
- :param options: A Digichem options nested dictionary containing options to control parsing.
106
105
  :return: The populated result set.
107
106
  """
108
- super().process(options)
107
+ super().process()
109
108
 
110
109
  # After processing is complete, have a look for excited state density files.
111
110
  # These have the general file name:
digichem/parse/util.py CHANGED
@@ -60,7 +60,7 @@ def find_log_files_from_hint(hint):
60
60
  # Remove any 'digichem.log' files as we know these are not calc log files.
61
61
  # We don't actually write 'digichem.log' files anymore either (we use digichem.out instead),
62
62
  # but older versions did...
63
- log_files = [log_file for log_file in log_files if log_file.name not in ["digichem.log", "digichem.out", "silico.log", "silico.out"]]
63
+ log_files = [log_file for log_file in log_files if log_file.name not in ["digichem.log", "digichem.out", "silico.log", "silico.out", ".digichem.yaml"]]
64
64
  else:
65
65
  parent = hint.parent
66
66
  log_files = [hint]
@@ -227,10 +227,10 @@ def parse_calculation(*log_files, options, parse_all = False, format_hint = "aut
227
227
  open_log_files, open_aux_files = archive.open()
228
228
 
229
229
  if parse_all:
230
- results = from_log_files(*open_log_files, format_hint = format_hint, parser_options = parser_options, **open_aux_files).process_all(options)
230
+ results = from_log_files(*open_log_files, format_hint = format_hint, parser_options = parser_options, options = options, **open_aux_files).process_all()
231
231
 
232
232
  else:
233
- results = from_log_files(*open_log_files, format_hint = format_hint, parser_options = parser_options, **open_aux_files).process(options)
233
+ results = from_log_files(*open_log_files, format_hint = format_hint, parser_options = parser_options, options = options, **open_aux_files).process()
234
234
 
235
235
  finally:
236
236
  if not keep_archive:
@@ -379,7 +379,6 @@ def parse_and_merge_multiple_calculations(*multiple_results, options, parser_opt
379
379
  :param multiple_results: A list of two dimensions, where the first dimension is a list of separate results to process, and the second dimension is a list of results that should be merged together.
380
380
  :param options: A Digichem options nested dictionary containing options to control parsing.
381
381
  :param format_hint: A hint as to the format of the given log files. Either 'auto' (to guess), 'log' (calc log file), 'sir' (digichem result file) or 'sid' (digichem database file).
382
- :param pool: An optional subprocessing.pool object to use for parallel parsing.
383
382
  :param init_func: An optional function to call to init each newly created process.
384
383
  :param processes: The max number of processes to create the new pool object with.
385
384
  :param auxiliary_files: An optional list of lists of dicts of auxiliary files. Each item in auxiliary_files should match the corresponding log file in multiple_results.
@@ -388,6 +387,7 @@ def parse_and_merge_multiple_calculations(*multiple_results, options, parser_opt
388
387
  if auxiliary_files is None:
389
388
  auxiliary_files = [None] * len(multiple_results)
390
389
 
390
+ pool = None
391
391
  # Do some parsing.
392
392
  # TODO: This parallelization isn't ideal, currently we process each group of to-be merged calcs separately, meaning processes can be wasted.
393
393
  try:
@@ -402,7 +402,8 @@ def parse_and_merge_multiple_calculations(*multiple_results, options, parser_opt
402
402
  return result_lists
403
403
 
404
404
  finally:
405
- pool.__exit__(None, None, None)
405
+ if pool:
406
+ pool.__exit__(None, None, None)
406
407
 
407
408
 
408
409
  class open_for_parsing():
@@ -240,11 +240,11 @@ class Alignment(Atom_list, Dynamic_parent):
240
240
  for atom in self:
241
241
  print("{}, {}, {}, {}".format(atom.element, atom.coords[0], atom.coords[1], atom.coords[2]))
242
242
 
243
- def dump(self, digichem_options):
243
+ def _dump_(self, digichem_options, all):
244
244
  """
245
245
  Get a representation of this result object in primitive format.
246
246
  """
247
- dump_dict = super().dump(digichem_options)
247
+ dump_dict = super()._dump_(digichem_options, all)
248
248
  dump_dict['alignment_method'] = self.human_method_type
249
249
  return dump_dict
250
250
 
digichem/result/atom.py CHANGED
@@ -453,7 +453,7 @@ class Atom_list(Result_container, Unmergeable_container_mixin, Molecule_mixin):
453
453
  """
454
454
  return self(Atom.list_from_coords(coords), charge = coords.charge)
455
455
 
456
- def dump(self, Digichem_options):
456
+ def _dump_(self, digichem_options, all):
457
457
  """
458
458
  Get a representation of this result object in primitive format.
459
459
  """
@@ -490,7 +490,7 @@ class Atom_list(Result_container, Unmergeable_container_mixin, Molecule_mixin):
490
490
  },
491
491
  "linearity_ratio": float(self.get_linear_ratio()),
492
492
  "planarity_ratio": float(self.get_planar_ratio()),
493
- "values": super().dump(Digichem_options),
493
+ "values": super()._dump_(digichem_options, all),
494
494
  }
495
495
  return dump_dict
496
496
 
@@ -522,7 +522,7 @@ class Atom_list(Result_container, Unmergeable_container_mixin, Molecule_mixin):
522
522
  """
523
523
  Convert this list of atoms to mol format (useful for reading with rdkit).
524
524
  """
525
- return Openprattle_converter.get_cls("xyz")(input_file = self.to_xyz(), input_file_path = "internal atoms object", input_file_type = "xyz").convert("mol", charge = self.charge)
525
+ return Openprattle_converter(input_file_buffer = self.to_xyz(), input_file_path = "internal atoms object", input_file_type = "xyz").convert("mol", charge = self.charge)
526
526
 
527
527
  def to_rdkit_molecule(self):
528
528
  """
@@ -673,7 +673,7 @@ class Atom(Atom_ABC):
673
673
  """
674
674
  return math.sqrt( (self.coords[0] - foreign_atom.coords[0])**2 + (self.coords[1] - foreign_atom.coords[1])**2 + (self.coords[2] - foreign_atom.coords[2])**2)
675
675
 
676
- def dump(self, Digichem_options):
676
+ def _dump_(self, digichem_options, all):
677
677
  """
678
678
  Get a representation of this result object in primitive format.
679
679
  """
digichem/result/base.py CHANGED
@@ -93,17 +93,55 @@ class Result_object():
93
93
 
94
94
  return multiple_objects[0]
95
95
 
96
+ def calculate(self, item, digichem_options):
97
+ """
98
+ Retrieve/calculate an on-demand value, caching the value if it has not already been retrieved.
99
+
100
+ This function is a wrapper around _get_dump_(), caching the calculation result to avoid
101
+ expensive recalculation.
102
+
103
+ :param item: The key corresponding to an item in this object's _get_dump_() dict.
104
+ :param digichem_options: Digichem options that will be passed to _get_dump_() (unused on a cache hit).
105
+ """
106
+ if not hasattr(self, "_dump_cache"):
107
+ self._dump_cache = {}
108
+
109
+ if item in self._dump_cache:
110
+ # Cache hit.
111
+ return self._dump_cache[item]
112
+
113
+ else:
114
+ # Cache miss.
115
+ # Generate (and cache) the data.
116
+ self._dump_cache[item] = self.generate_for_dump()[item](digichem_options)
117
+
118
+ # And return of course.
119
+ return self._dump_cache[item]
120
+
96
121
  def generate_for_dump(self):
97
122
  """
98
123
  Method used to get a dictionary used to generate on-demand values for dumping.
99
124
 
100
125
  This functionality is useful for hiding expense properties from the normal dump process, while still exposing them when specifically requested.
101
126
 
102
- Each key in the returned dicrt is the name of a dumpable item, each value is a function to call with digichem_options as its only param.
127
+ Each key in the returned dict is the name of a dumpable item, each value is a function to call with digichem_options as its only param.
103
128
  """
104
- return {}
129
+ warnings.warn("generate_for_dump() is deprecated, use calculate() or _get_dump_() instead", DeprecationWarning)
130
+ return self._get_dump_()
105
131
 
106
- def dump(self, digichem_options):
132
+ def dump(self, digichem_options, all = False):
133
+ # First, get simple key:value pairs.
134
+ base_dict = self._dump_(digichem_options, all)
135
+
136
+ # Then extend with generator ones if we have any.
137
+ if all:
138
+ generators = self._get_dump_()
139
+ for key in generators:
140
+ base_dict[key] = generators[key](digichem_options)
141
+
142
+ return base_dict
143
+
144
+ def _dump_(self, digichem_options, all):
107
145
  """
108
146
  Abstract function that is called to dump the value of the result object to a primitive type, suitable for serializing with yaml.
109
147
 
@@ -112,6 +150,16 @@ class Result_object():
112
150
  - 'units': The units of the result (for example, k m^-s).
113
151
  """
114
152
  raise NotImplementedError("Implement in subclass")
153
+
154
+ def _get_dump_(self):
155
+ """
156
+ Method used to get a dictionary used to generate on-demand values for dumping.
157
+
158
+ This functionality is useful for hiding expense properties from the normal dump process, while still exposing them when specifically requested.
159
+
160
+ Each key in the returned dict is the name of a dumpable item, each value is a function to call with digichem_options as its only param.
161
+ """
162
+ return {}
115
163
 
116
164
 
117
165
  class Floatable_mixin():
@@ -253,6 +301,6 @@ class Result_container(list, Result_object):
253
301
  else:
254
302
  return self.merge_default(*multiple_lists, **kwargs)
255
303
 
256
- def dump(self, digichem_options):
257
- return [item.dump(digichem_options) for item in self]
304
+ def _dump_(self, digichem_options, all):
305
+ return [item.dump(digichem_options, all) for item in self]
258
306
 
@@ -182,7 +182,7 @@ class Dipole_moment_ABC(Result_object):
182
182
  except (FloatingPointError, ZeroDivisionError):
183
183
  return 0
184
184
 
185
- def dump(self, digichem_options):
185
+ def _dump_(self, digichem_options, all):
186
186
  """
187
187
  Get a representation of this result object in primitive format.
188
188
  """
@@ -27,11 +27,11 @@ class Emissions(Result_object):
27
27
  self.adiabatic = adiabatic if adiabatic is not None else {}
28
28
  self.vertical = vertical if vertical is not None else {}
29
29
 
30
- def dump(self, digichem_options):
30
+ def _dump_(self, digichem_options, all):
31
31
  # Several dumpers (JSON, DB backends based on JSON etc) don't support non-string keys...
32
32
  return {
33
- "adiabatic": {str(key):value.dump(digichem_options) for key,value in self.adiabatic.items()},
34
- "vertical": {str(key):value.dump(digichem_options) for key,value in self.vertical.items()}
33
+ "adiabatic": {str(key):value.dump(digichem_options, all) for key,value in self.adiabatic.items()},
34
+ "vertical": {str(key):value.dump(digichem_options, all) for key,value in self.vertical.items()}
35
35
  }
36
36
 
37
37
  @classmethod
@@ -343,12 +343,12 @@ class Relaxed_excited_state(Excited_state):
343
343
  else:
344
344
  raise
345
345
 
346
- def dump(self, digichem_options):
346
+ def _dump_(self, digichem_options, all):
347
347
  """
348
348
  Get a representation of this result object in primitive format.
349
349
  """
350
350
 
351
- dump_dict = super().dump(digichem_options)
351
+ dump_dict = super()._dump_(digichem_options, all)
352
352
  dump_dict['emission_type'] = self.emission_type
353
353
  dump_dict['ground_multiplicity'] = self.ground_multiplicity
354
354
  dump_dict['excited_energy'] = {
digichem/result/energy.py CHANGED
@@ -65,7 +65,7 @@ class Energies(Result_object):
65
65
  scf = SCF_energy_list.from_parser(parser)
66
66
  )
67
67
 
68
- def dump(self, digichem_options):
68
+ def _dump_(self, digichem_options, all):
69
69
  """
70
70
  Get a representation of this result object in primitive format.
71
71
  """
@@ -74,11 +74,11 @@ class Energies(Result_object):
74
74
  "value": float(self.final),
75
75
  "units": "eV"
76
76
  },
77
- "scf": self.scf.dump(digichem_options),
78
- "mp": self.mp.dump(digichem_options),
79
- "cc": self.cc.dump(digichem_options)
77
+ "scf": self.scf.dump(digichem_options, all),
78
+ "mp": self.mp.dump(digichem_options, all),
79
+ "cc": self.cc.dump(digichem_options, all)
80
80
  }
81
- dump.update({"mp{}".format(index+2): energy.dump(digichem_options) for index, energy in enumerate(self.mp_energies)})
81
+ dump.update({"mp{}".format(index+2): energy.dump(digichem_options, all) for index, energy in enumerate(self.mp_energies)})
82
82
  return dump
83
83
 
84
84
  @classmethod
@@ -210,7 +210,7 @@ class Energy_list(Result_container, Unmergeable_container_mixin):
210
210
  except AttributeError:
211
211
  return self()
212
212
 
213
- def dump(self, digichem_options):
213
+ def _dump_(self, digichem_options, all):
214
214
  """
215
215
  Get a representation of this result object in primitive format.
216
216
  """
@@ -270,11 +270,11 @@ class MP_energy_list(Energy_list):
270
270
  super().__init__(items)
271
271
  self.order = order
272
272
 
273
- def dump(self, digichem_options):
273
+ def _dump_(self, digichem_options, all):
274
274
  """
275
275
  Get a representation of this result object in primitive format.
276
276
  """
277
- dump = super().dump(digichem_options)
277
+ dump = super()._dump_(digichem_options, all)
278
278
  dump['order'] = self.order
279
279
  return dump
280
280
 
@@ -230,7 +230,7 @@ class Excited_state_list(Result_container):
230
230
  merged.assign_levels()
231
231
  return merged
232
232
 
233
- def generate_for_dump(self):
233
+ def _get_dump_(self):
234
234
  """
235
235
  Method used to get a dictionary used to generate on-demand values for dumping.
236
236
 
@@ -257,14 +257,21 @@ class Excited_state_list(Result_container):
257
257
  # TODO: It's weird that these spectra are only available in dumped format, there should be some property/function on the class that also returns them...
258
258
  spectrum_nm = Absorption_emission_graph.from_excited_states(
259
259
  self,
260
- digichem_options['absorption_spectrum']['fwhm'],
261
- digichem_options['absorption_spectrum']['gaussian_resolution'],
262
- digichem_options['absorption_spectrum']['gaussian_cutoff'],
260
+ fwhm = digichem_options['absorption_spectrum']['fwhm'],
261
+ resolution = digichem_options['absorption_spectrum']['gaussian_resolution'],
262
+ cutoff = digichem_options['absorption_spectrum']['gaussian_cutoff'],
263
+ filter = digichem_options['absorption_spectrum']['y_filter'],
263
264
  use_jacobian = digichem_options['absorption_spectrum']['use_jacobian']
264
265
  )
265
266
 
266
267
 
267
- spectrum_ev = Spectroscopy_graph([(excited_state.energy, excited_state.oscillator_strength) for excited_state in self], digichem_options['absorption_spectrum']['fwhm'], digichem_options['absorption_spectrum']['gaussian_resolution'], digichem_options['absorption_spectrum']['gaussian_cutoff'])
268
+ spectrum_ev = Spectroscopy_graph(
269
+ [(excited_state.energy, excited_state.oscillator_strength) for excited_state in self],
270
+ fwhm = digichem_options['absorption_spectrum']['fwhm'],
271
+ resolution = digichem_options['absorption_spectrum']['gaussian_resolution'],
272
+ cutoff = digichem_options['absorption_spectrum']['gaussian_cutoff'],
273
+ filter = digichem_options['absorption_spectrum']['y_filter']
274
+ )
268
275
 
269
276
  try:
270
277
  spectrum_nm_data = spectrum_nm.plot_cumulative_gaussian()
@@ -298,9 +305,9 @@ class Excited_state_list(Result_container):
298
305
  }
299
306
  }
300
307
 
301
- def dump(self, digichem_options):
308
+ def _dump_(self, digichem_options, all):
302
309
  dump_dict = {
303
- "values": super().dump(digichem_options),
310
+ "values": super()._dump_(digichem_options, all),
304
311
  }
305
312
 
306
313
  # Add extra properties.
@@ -358,7 +365,7 @@ class Excited_state_transition(Result_object):
358
365
  """
359
366
  return self.coefficient **2
360
367
 
361
- def dump(self, digichem_options):
368
+ def _dump_(self, digichem_options, all):
362
369
  """
363
370
  Get a representation of this result object in primitive format.
364
371
  """
@@ -558,7 +565,7 @@ class Energy_state(Result_object, Floatable_mixin):
558
565
  """
559
566
  return "{}({})".format(self.multiplicity_symbol, self.multiplicity_level)
560
567
 
561
- def dump(self, digichem_options):
568
+ def _dump_(self, digichem_options, all):
562
569
  """
563
570
  Get a representation of this result object in primitive format.
564
571
  """
@@ -708,11 +715,11 @@ class Excited_state(Energy_state):
708
715
  # Now convert to 0 -> 255 and return.
709
716
  return [int(clr * 255) for clr in rgb]
710
717
 
711
- def dump(self, digichem_options):
718
+ def _dump_(self, digichem_options, all):
712
719
  """
713
720
  Get a representation of this result object in primitive format.
714
721
  """
715
- dump_dict = super().dump(digichem_options)
722
+ dump_dict = super()._dump_(digichem_options, all)
716
723
  dump_dict.update({
717
724
  "wavelength": {
718
725
  "value": float(self.wavelength),
@@ -725,8 +732,8 @@ class Excited_state(Energy_state):
725
732
  },
726
733
  "symmetry": self.symmetry,
727
734
  "oscillator_strength": float(self.oscillator_strength) if self.oscillator_strength is not None else None,
728
- "tdm": self.transition_dipole_moment.dump(digichem_options) if self.transition_dipole_moment is not None else None,
729
- "transitions": [tran.dump(digichem_options) for tran in self.transitions],
735
+ "tdm": self.transition_dipole_moment.dump(digichem_options, all) if self.transition_dipole_moment is not None else None,
736
+ "transitions": [tran.dump(digichem_options, all) for tran in self.transitions],
730
737
  })
731
738
  return dump_dict
732
739
 
@@ -35,11 +35,11 @@ class Ground_state(Energy_state):
35
35
  """
36
36
  return self.charge == other.charge and self.multiplicity == other.multiplicity and self.energy == other.energy
37
37
 
38
- def dump(self, digichem_options):
38
+ def _dump_(self, digichem_options, all):
39
39
  """
40
40
  Get a representation of this result object in primitive format.
41
41
  """
42
- parent_dict = super().dump(digichem_options)
42
+ parent_dict = super()._dump_(digichem_options, all)
43
43
  return {
44
44
  "index": parent_dict['index'],
45
45
  "symbol": parent_dict['symbol'],