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
@@ -46,10 +46,10 @@ class Solvent(Result_object):
46
46
  @classmethod
47
47
  def from_parser(self, parser):
48
48
  """
49
- Construct a Metadata object from an output file parser.
49
+ Construct a Solvent object from an output file parser.
50
50
 
51
51
  :param parser: Output data parser.
52
- :return: A populated Metadata object.
52
+ :return: A populated Solvent object.
53
53
  """
54
54
  return self(
55
55
  name = parser.data.metadata.get('solvent_name', None),
@@ -78,7 +78,7 @@ class Solvent(Result_object):
78
78
  else:
79
79
  return "Unknown"
80
80
 
81
- def dump(self, digichem_options):
81
+ def _dump_(self, digichem_options, all):
82
82
  return {
83
83
  "model": self.model,
84
84
  "name": self.name,
@@ -142,6 +142,7 @@ class Metadata(Result_object):
142
142
 
143
143
  def __init__(
144
144
  self,
145
+ jobId = None,
145
146
  name = None,
146
147
  user = None,
147
148
  log_files = None,
@@ -177,6 +178,7 @@ class Metadata(Result_object):
177
178
  """
178
179
  Constructor for result Metadata objects.
179
180
 
181
+ :param jobId: If this result was generated from a digichem calculation, the relevant jobID.
180
182
  :param name: Optional name of this calculation result.
181
183
  :param user: The username of the user who parsed this result.
182
184
  :param log_files: An optional list of text-based calculation log files from which this result was parsed.
@@ -203,6 +205,7 @@ class Metadata(Result_object):
203
205
  :param memory_available: The maximum amount of memory available to this calculation (the amount requested by the user).
204
206
  :param memory_used: The maximum amount of memory used by the calculation (the amount requested by the user).
205
207
  """
208
+ self.jobId = jobId
206
209
  self.num_calculations = 1
207
210
  self.name = name
208
211
  self.user = user
@@ -453,6 +456,7 @@ class Metadata(Result_object):
453
456
 
454
457
  # TODO: This doesn't seem to make sense; the parser already contains a metadata object...
455
458
  return self(
459
+ jobId = parser.data.metadata.get('jobId', None),
456
460
  name = parser.data.metadata.get('name', None),
457
461
  user = parser.data.metadata.get('user', None),
458
462
  log_files = parser.data.metadata.get('log_files', None),
@@ -485,7 +489,7 @@ class Metadata(Result_object):
485
489
  # There is no metadata available, give up.
486
490
  raise Result_unavailable_error("Metadata", "no metadata is available")
487
491
 
488
- def dump(self, digichem_options):
492
+ def _dump_(self, digichem_options, all):
489
493
  """
490
494
  Get a representation of this result object in primitive format.
491
495
  """
@@ -497,6 +501,7 @@ class Metadata(Result_object):
497
501
  }
498
502
 
499
503
  attrs = [
504
+ "jobId",
500
505
  "history",
501
506
  "charge",
502
507
  "multiplicity",
@@ -538,7 +543,7 @@ class Metadata(Result_object):
538
543
  "value": self.pressure,
539
544
  "units": "atm"
540
545
  }
541
- attr_dict["solvent"] = self.solvent.dump(digichem_options)
546
+ attr_dict["solvent"] = self.solvent.dump(digichem_options, all)
542
547
 
543
548
  attr_dict['num_cpu'] = self.num_cpu
544
549
  for attr_name in ("memory_used", "memory_available"):
@@ -554,7 +559,7 @@ class Metadata(Result_object):
554
559
  "units": None
555
560
  }
556
561
 
557
- attr_dict['performance'] = self.performance.dump(digichem_options) if self.performance else None
562
+ attr_dict['performance'] = self.performance.dump(digichem_options, all) if self.performance else None
558
563
 
559
564
  return attr_dict
560
565
 
@@ -679,8 +684,9 @@ class Performance(Result_object):
679
684
  memory_available = [],
680
685
  memory_available_percent = [],
681
686
  cpu_used = [],
682
- output_space = [],
683
- scratch_space = [],
687
+ output_available = [],
688
+ scratch_used = [],
689
+ scratch_available = [],
684
690
  memory_allocated = None,
685
691
  cpu_allocated = None,
686
692
  ):
@@ -690,11 +696,22 @@ class Performance(Result_object):
690
696
  self.memory_available = memory_available
691
697
  self.memory_available_percent = memory_available_percent
692
698
  self.cpu_used = cpu_used
693
- self.output_space = output_space
694
- self.scratch_space = scratch_space
699
+ self.output_available = output_available
700
+ self.scratch_used = scratch_used
701
+ self.scratch_available = scratch_available
695
702
 
696
703
  self.memory_allocated = memory_allocated if memory_allocated is not None else self.max_mem
697
704
  self.cpu_allocated = cpu_allocated if cpu_allocated is not None else math.ceil(max(cpu_used) / 100)
705
+
706
+ @property
707
+ def output_space(self):
708
+ warnings.warn("output_space is deprecated, use output_available instead", DeprecationWarning)
709
+ return self.output_available
710
+
711
+ @property
712
+ def scratch_space(self):
713
+ warnings.warn("scratch_space is deprecated, use scratch_available instead", DeprecationWarning)
714
+ return self.scratch_available
698
715
 
699
716
 
700
717
  @classmethod
@@ -706,16 +723,17 @@ class Performance(Result_object):
706
723
  :return: A populated Performance object.
707
724
  """
708
725
  return self(
709
- duration = parser.data.metadata['performance'][:, 0].tolist(),
710
- memory_used = parser.data.metadata['performance'][:, 1].tolist(),
726
+ duration = parser.data.metadata['performance']['duration'].tolist(),
727
+ memory_used = parser.data.metadata['performance']['memory_used'].tolist(),
711
728
  memory_allocated = Memory(parser.data.metadata['memory_available']) if "memory_available" in parser.data.metadata else None,
712
- memory_used_percent = parser.data.metadata['performance'][:, 2].tolist(),
713
- memory_available = parser.data.metadata['performance'][:, 3].tolist(),
714
- memory_available_percent = parser.data.metadata['performance'][:, 4].tolist(),
715
- cpu_used = parser.data.metadata['performance'][:, 5].tolist(),
729
+ memory_used_percent = parser.data.metadata['performance']['memory_used_percent'].tolist(),
730
+ memory_available = parser.data.metadata['performance']['memory_available'].tolist(),
731
+ memory_available_percent = parser.data.metadata['performance']['memory_available_percent'].tolist(),
732
+ cpu_used = parser.data.metadata['performance']['cpu_used'].tolist(),
716
733
  cpu_allocated = parser.data.metadata.get('num_cpu', None),
717
- output_space = parser.data.metadata['performance'][:, 6].tolist(),
718
- scratch_space = parser.data.metadata['performance'][:, 7].tolist()
734
+ output_available = parser.data.metadata['performance']['output_available'].tolist(),
735
+ 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']),
736
+ scratch_available = parser.data.metadata['performance']['scratch_available'].tolist()
719
737
  )
720
738
 
721
739
  @property
@@ -788,8 +806,9 @@ class Performance(Result_object):
788
806
  memory_available_percent = [0.0] * len(data['values'])
789
807
  cpu_used = [0.0] * len(data['values'])
790
808
  cpu_allocated = data['cpu_allocated']
791
- output_space = [0.0] * len(data['values'])
792
- scratch_space = [0.0] * len(data['values'])
809
+ output_available = [0.0] * len(data['values'])
810
+ scratch_used = [0.0] * len(data['values'])
811
+ scratch_available = [0.0] * len(data['values'])
793
812
 
794
813
  for i, value in enumerate(data['values']):
795
814
  duration[i] = value['duration']['value']
@@ -798,8 +817,10 @@ class Performance(Result_object):
798
817
  memory_available[i] = value['memory_available']['value']
799
818
  memory_available_percent[i] = value['memory_available_percent']['value']
800
819
  cpu_used[i] = value['cpu_used']['value']
801
- output_space[i] = value['output_space']['value']
802
- scratch_space[i] = value['scratch_space']['value']
820
+ output_available[i] = value['output_space']['value']
821
+ if 'scratch_used' in value:
822
+ scratch_used[i] = value['scratch_used']['value']
823
+ scratch_available[i] = value['scratch_space']['value']
803
824
 
804
825
  return self(
805
826
  duration = duration,
@@ -810,12 +831,13 @@ class Performance(Result_object):
810
831
  memory_available_percent = memory_available_percent,
811
832
  cpu_used = cpu_used,
812
833
  cpu_allocated = cpu_allocated,
813
- output_space = output_space,
814
- scratch_space = scratch_space
834
+ output_available = output_available,
835
+ scratch_used = scratch_used,
836
+ scratch_available = scratch_available
815
837
  )
816
838
 
817
839
 
818
- def dump(self, digichem_options):
840
+ def _dump_(self, digichem_options, all):
819
841
  """
820
842
  Get a representation of this result object in primitive format.
821
843
  """
@@ -871,6 +893,10 @@ class Performance(Result_object):
871
893
  "units": "bytes",
872
894
  "value": self.output_space[i]
873
895
  },
896
+ 'scratch_used': {
897
+ "units": "bytes",
898
+ "value": self.scratch_used[i]
899
+ },
874
900
  'scratch_space': {
875
901
  "units": "bytes",
876
902
  "value": self.scratch_space[i]
digichem/result/nmr.py CHANGED
@@ -22,7 +22,7 @@ class NMR_spectrometer(Result_object):
22
22
  A class for generating NMR spectra on-demand.
23
23
  """
24
24
 
25
- def __init__(self, nmr_results, frequency = 300, fwhm = 0.001, resolution = 0.001, cutoff = 0.01, coupling_filter = 0.1, pre_merge = 0.01, post_merge = None, isotope_options = None):
25
+ def __init__(self, nmr_results, frequency = 300, fwhm = 0.001, resolution = 0.001, cutoff = 0.01, y_filter = 1e-6, coupling_filter = 0.1, pre_merge = 0.01, post_merge = None, isotope_options = None):
26
26
  """
27
27
  Constructor for NMR_spectrometer.
28
28
 
@@ -39,6 +39,7 @@ class NMR_spectrometer(Result_object):
39
39
  self.fwhm = fwhm
40
40
  self.gaussian_resolution = resolution
41
41
  self.gaussian_cutoff = cutoff
42
+ self.y_filter = y_filter
42
43
  self.coupling_filter = coupling_filter
43
44
  self._isotope_options = isotope_options if isotope_options is not None else {}
44
45
 
@@ -48,6 +49,7 @@ class NMR_spectrometer(Result_object):
48
49
  "pre_merge": self.pre_merge,
49
50
  "post_merge": self.post_merge,
50
51
  "fwhm": self.fwhm,
52
+ "y_filter": self.y_filter,
51
53
  "gaussian_resolution": self.gaussian_resolution,
52
54
  "coupling_filter": self.coupling_filter,
53
55
  "gaussian_cutoff": self.gaussian_cutoff,
@@ -66,6 +68,7 @@ class NMR_spectrometer(Result_object):
66
68
  fwhm = options['nmr']['fwhm'],
67
69
  resolution = options['nmr']['gaussian_resolution'],
68
70
  cutoff = options['nmr']['gaussian_cutoff'],
71
+ y_filter = options['nmr']['y_filter'],
69
72
  coupling_filter = options['nmr']['coupling_filter'],
70
73
  pre_merge = options['nmr']['pre_merge'],
71
74
  post_merge = options['nmr']['post_merge'],
@@ -160,6 +163,9 @@ class NMR_spectrometer(Result_object):
160
163
 
161
164
  return False
162
165
 
166
+ def __iter__(self):
167
+ return iter(self.available.keys())
168
+
163
169
  def __getitem__(self, item):
164
170
  """
165
171
  Generate a spectrum for a given shortcode.
@@ -170,7 +176,7 @@ class NMR_spectrometer(Result_object):
170
176
  # match the interface.
171
177
  return lambda digichem_options: self.spectrum(*self.parse_shortcode(item))
172
178
 
173
- def generate_for_dump(self):
179
+ def _get_dump_(self):
174
180
  """
175
181
  Method used to get a dictionary used to generate on-demand values for dumping.
176
182
 
@@ -180,7 +186,7 @@ class NMR_spectrometer(Result_object):
180
186
  """
181
187
  return self
182
188
 
183
- def dump(self, digichem_options):
189
+ def _dump_(self, digichem_options, all):
184
190
  # Return a list of possible spectra we can generate.
185
191
  return {
186
192
  "codes": list(self.available.keys()),
@@ -208,7 +214,7 @@ class NMR_spectrometer(Result_object):
208
214
 
209
215
  # The total spectrum takes all simulated peaks.
210
216
  # These are grouped by atom_group, flatten this list before passing to spectroscopy.
211
- graph = Combined_graph.from_nmr(grouped_peaks, isotope_options['fwhm'], isotope_options['gaussian_resolution'], isotope_options['gaussian_cutoff'])
217
+ graph = Combined_graph.from_nmr(grouped_peaks, isotope_options['fwhm'], isotope_options['gaussian_resolution'], isotope_options['gaussian_cutoff'], filter = isotope_options['y_filter'])
212
218
 
213
219
  return graph
214
220
 
@@ -489,6 +495,8 @@ class NMR_list(Result_container):
489
495
  self.options = options
490
496
  self.groups = self.group()
491
497
  self.spectrometer = NMR_spectrometer.from_options(self.groups, options = options)
498
+ # This is used as part of the dump mechanic.
499
+ self.spectrum = self.spectrometer
492
500
 
493
501
  @classmethod
494
502
  def from_parser(self, parser):
@@ -599,14 +607,15 @@ class NMR_list(Result_container):
599
607
 
600
608
  return nmr_object_groups
601
609
 
602
- def dump(self, digichem_options):
610
+ def _dump_(self, digichem_options, all):
603
611
  """
604
612
  Dump this list of NMR results to a list of primitive types.
605
613
  """
606
614
  grouping = self.groups
607
615
  dump_dict = {
608
- "values": super().dump(digichem_options),
609
- "groups": {group_id.label: group.dump(digichem_options) for group_id, group in grouping.items()},
616
+ "values": super()._dump_(digichem_options, all),
617
+ "groups": {group_id.label: group.dump(digichem_options, all) for group_id, group in grouping.items()},
618
+ "spectrum": self.spectrometer.dump(digichem_options, all)
610
619
  }
611
620
  return dump_dict
612
621
 
@@ -620,17 +629,17 @@ class NMR_list(Result_container):
620
629
  """
621
630
  return self(NMR.list_from_dump(data['values'], result_set, options), atoms = result_set.atoms, options = options)
622
631
 
623
- def generate_for_dump(self):
624
- """
625
- Method used to get a dictionary used to generate on-demand values for dumping.
632
+ # def _get_dump_(self):
633
+ # """
634
+ # Method used to get a dictionary used to generate on-demand values for dumping.
626
635
 
627
- This functionality is useful for hiding expense properties from the normal dump process, while still exposing them when specifically requested.
636
+ # This functionality is useful for hiding expense properties from the normal dump process, while still exposing them when specifically requested.
628
637
 
629
- 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.
630
- """
631
- return {
632
- "spectrum": lambda digichem_options: self.spectrometer
633
- }
638
+ # 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.
639
+ # """
640
+ # return {
641
+ # "spectrum": lambda digichem_options: self.spectrometer
642
+ # }
634
643
 
635
644
 
636
645
  class NMR_group(Result_object, Floatable_mixin):
@@ -649,7 +658,7 @@ class NMR_group(Result_object, Floatable_mixin):
649
658
  def __float__(self):
650
659
  return float(self.shielding)
651
660
 
652
- def dump(self, digichem_options):
661
+ def _dump_(self, digichem_options, all):
653
662
  """
654
663
  Get a representation of this result object in primitive format.
655
664
  """
@@ -661,7 +670,7 @@ class NMR_group(Result_object, Floatable_mixin):
661
670
  "value": self.shielding
662
671
  },
663
672
  #"couplings": [{"groups": [group.label for group in coupling['groups']], "isotopes": list(coupling["isotopes"]), "total": coupling["total"]} for coupling in self.couplings],
664
- "couplings": [coupling.dump(digichem_options) for coupling in self.couplings]
673
+ "couplings": [coupling.dump(digichem_options, all) for coupling in self.couplings]
665
674
  }
666
675
 
667
676
  class NMR_group_spin_coupling(Result_object):
@@ -686,7 +695,7 @@ class NMR_group_spin_coupling(Result_object):
686
695
  """
687
696
  return sum([coupling.isotropic('total') for coupling in self.couplings]) / len(self.couplings)
688
697
 
689
- def dump(self, digichem_options):
698
+ def _dump_(self, digichem_options, all):
690
699
  """
691
700
  Get a representation of this result object in primitive format.
692
701
  """
@@ -697,7 +706,7 @@ class NMR_group_spin_coupling(Result_object):
697
706
  "units": "Hz",
698
707
  "value": float(self.total),
699
708
  }
700
- #"couplings": [coupling.dump(digichem_options) for coupling in self.couplings]
709
+ #"couplings": [coupling.dump(digichem_options, all) for coupling in self.couplings]
701
710
  }
702
711
 
703
712
  def other(self, atom_group):
@@ -819,14 +828,14 @@ class NMR(Result_object, Floatable_mixin):
819
828
  ]
820
829
 
821
830
 
822
- def dump(self, digichem_options):
831
+ def _dump_(self, digichem_options, all):
823
832
  """
824
833
  Get a representation of this result object in primitive format.
825
834
  """
826
835
  return {
827
836
  "atom": self.atom.label,
828
- "shielding": self.shielding.dump(digichem_options),
829
- "couplings": self.couplings.dump(digichem_options)
837
+ "shielding": self.shielding.dump(digichem_options, all),
838
+ "couplings": self.couplings.dump(digichem_options, all)
830
839
  }
831
840
 
832
841
 
@@ -867,7 +876,7 @@ class NMR_tensor_ABC(Result_object):
867
876
  eigenvalues = self.eigenvalues(tensor)
868
877
  return sum(eigenvalues) / len(eigenvalues)
869
878
 
870
- def dump(self, digichem_options):
879
+ def _dump_(self, digichem_options, all):
871
880
  """
872
881
  Get a representation of this result object in primitive format.
873
882
  """
@@ -931,7 +940,7 @@ class NMR_shielding(NMR_tensor_ABC):
931
940
 
932
941
  return shieldings
933
942
 
934
- def dump(self, digichem_options):
943
+ def _dump_(self, digichem_options, all):
935
944
  """
936
945
  Get a representation of this result object in primitive format.
937
946
  """
@@ -939,7 +948,7 @@ class NMR_shielding(NMR_tensor_ABC):
939
948
  "reference": self.reference,
940
949
  }
941
950
 
942
- dump_dic.update(super().dump(digichem_options))
951
+ dump_dic.update(super()._dump_(digichem_options, all))
943
952
  return dump_dic
944
953
 
945
954
  @classmethod
@@ -1073,7 +1082,7 @@ class NMR_spin_coupling(NMR_tensor_ABC):
1073
1082
  in data
1074
1083
  ]
1075
1084
 
1076
- def dump(self, digichem_options):
1085
+ def _dump_(self, digichem_options, all):
1077
1086
  """
1078
1087
  Get a representation of this result object in primitive format.
1079
1088
  """
@@ -1082,5 +1091,5 @@ class NMR_spin_coupling(NMR_tensor_ABC):
1082
1091
  "isotopes": (self.isotopes[0], self.isotopes[1]),
1083
1092
  }
1084
1093
 
1085
- dump_dic.update(super().dump(digichem_options))
1094
+ dump_dic.update(super()._dump_(digichem_options, all))
1086
1095
  return dump_dic
@@ -238,7 +238,7 @@ class Molecular_orbital_list(Result_container):
238
238
 
239
239
  return self(cls.list_from_dump(data['values'], result_set, options))
240
240
 
241
- def dump(self, digichem_options):
241
+ def _dump_(self, digichem_options, all):
242
242
  """
243
243
  Get a representation of this result object in primitive format.
244
244
  """
@@ -249,7 +249,7 @@ class Molecular_orbital_list(Result_container):
249
249
  },
250
250
  "num_occupied": len(self.occupied),
251
251
  "num_virtual": len(self.virtual),
252
- "values": super().dump(digichem_options),
252
+ "values": super()._dump_(digichem_options, all),
253
253
  "spin_type": self.safe_get("spin_type")
254
254
  }
255
255
  # # Add HOMO and LUMO
@@ -498,7 +498,7 @@ class Molecular_orbital(Result_object, Floatable_mixin):
498
498
  # The index used to access data from cclib (which always has two lists, one for alpha one for beta).
499
499
  ccdata_index = 0
500
500
 
501
- def dump(self, digichem_options):
501
+ def _dump_(self, digichem_options, all):
502
502
  """
503
503
  Get a representation of this result object in primitive format.
504
504
  """
digichem/result/result.py CHANGED
@@ -221,7 +221,7 @@ class Result_set(Result_object):
221
221
  # No S1 available.
222
222
  return None
223
223
 
224
- def dump(self, digichem_options):
224
+ def _dump_(self, digichem_options, all):
225
225
  "Dump the data contained in this result set, serialising it to a hierarchy of dicts that can be saved in various formats."
226
226
  # Start with our DB ID if we have one.
227
227
  dump_dic = {}
@@ -229,19 +229,19 @@ class Result_set(Result_object):
229
229
  dump_dic['_id'] = self._id
230
230
 
231
231
  dump_dic.update({
232
- "metadata": self.metadata.dump(digichem_options),
233
- "ground_state": self.ground_state.dump(digichem_options) if self.ground_state is not None else None,
234
- "energies": self.energies.dump(digichem_options),
235
- "atoms": self.atoms.dump(digichem_options),
236
- "raw_atoms": self.raw_atoms.dump(digichem_options),
237
- "orbitals": self.orbitals.dump(digichem_options),
238
- "beta_orbitals": self.beta_orbitals.dump(digichem_options),
239
- "pdm": self.pdm.dump(digichem_options) if self.pdm is not None else None,
240
- "excited_states": self.excited_states.dump(digichem_options),
241
- "soc": self.soc.dump(digichem_options),
242
- "vibrations": self.vibrations.dump(digichem_options),
243
- "nmr": self.nmr.dump(digichem_options),
244
- "emission": self.emission.dump(digichem_options)
232
+ "metadata": self.metadata.dump(digichem_options, all),
233
+ "ground_state": self.ground_state.dump(digichem_options, all) if self.ground_state is not None else None,
234
+ "energies": self.energies.dump(digichem_options, all),
235
+ "atoms": self.atoms.dump(digichem_options, all),
236
+ "raw_atoms": self.raw_atoms.dump(digichem_options, all),
237
+ "orbitals": self.orbitals.dump(digichem_options, all),
238
+ "beta_orbitals": self.beta_orbitals.dump(digichem_options, all),
239
+ "pdm": self.pdm.dump(digichem_options, all) if self.pdm is not None else None,
240
+ "excited_states": self.excited_states.dump(digichem_options, all),
241
+ "soc": self.soc.dump(digichem_options, all),
242
+ "vibrations": self.vibrations.dump(digichem_options, all),
243
+ "nmr": self.nmr.dump(digichem_options, all),
244
+ "emission": self.emission.dump(digichem_options, all)
245
245
  })
246
246
 
247
247
  return dump_dic
digichem/result/soc.py CHANGED
@@ -104,7 +104,7 @@ class Spin_orbit_coupling(Result_object, Floatable_mixin):
104
104
  self.zero = zero
105
105
  self.negative_one = negative_one
106
106
 
107
- def dump(self, digichem_options):
107
+ def _dump_(self, digichem_options, all):
108
108
  """
109
109
  Get a representation of this result object in primitive format.
110
110
  """
@@ -235,11 +235,11 @@ class Total_spin_orbit_coupling(Spin_orbit_coupling):
235
235
  """
236
236
  return "<{}|Hso|{}> (cm-1): {:10.5f}".format(self.singlet_state.state_symbol, self.triplet_state.state_symbol, self.root_sum_square)
237
237
 
238
- def dump(self, digichem_options):
238
+ def _dump_(self, digichem_options, all):
239
239
  """
240
240
  Get a representation of this result object in primitive format.
241
241
  """
242
- dump_dic = super().dump(digichem_options)
242
+ dump_dic = super()._dump_(digichem_options, all)
243
243
  # Remove elements.
244
244
  del(dump_dic['soc'])
245
245
  return dump_dic
@@ -112,7 +112,7 @@ class Spectroscopy_graph(Spectroscopy_graph_abc):
112
112
  For generating pictures of these graphs, see digichem.image.spectroscopy
113
113
  """
114
114
 
115
- def __init__(self, coordinates, fwhm, resolution = 1, cutoff = 0.01, adjust_zero = False):
115
+ def __init__(self, coordinates, fwhm, resolution = 1, cutoff = 0.01, filter = 1e-6, adjust_zero = False):
116
116
  """
117
117
  Constructor for Spectroscopy_graph objects
118
118
 
@@ -137,6 +137,7 @@ class Spectroscopy_graph(Spectroscopy_graph_abc):
137
137
  self.fwhm = fwhm
138
138
  self.resolution = resolution
139
139
  self.cutoff = cutoff
140
+ self.filter = filter
140
141
 
141
142
  # Caches
142
143
  self._gaussians = []
@@ -187,7 +188,7 @@ class Spectroscopy_graph(Spectroscopy_graph_abc):
187
188
  # Next, determine the limits in which we'll plot.
188
189
  limits = self.gaussian_limits()
189
190
 
190
- # Apply rounding to nearest resolution step cover up floating-point errors.
191
+ # Apply rounding to nearest resolution step to cover up floating-point errors.
191
192
  points = [self.resolution *round(point / self.resolution) for point in numpy.linspace(*limits)]
192
193
 
193
194
  # Plot and return.
@@ -202,7 +203,7 @@ class Spectroscopy_graph(Spectroscopy_graph_abc):
202
203
  )
203
204
  )
204
205
  gaussians = [
205
- [(x, self.gaussian(a, b, c, x)) for x in points]
206
+ [(x, y) for x in points if (y := self.gaussian(a, b, c, x)) >= self.filter]
206
207
  for b, a in self.base_coordinates
207
208
  ]
208
209
 
@@ -232,7 +233,7 @@ class Spectroscopy_graph(Spectroscopy_graph_abc):
232
233
  # Plot and return.
233
234
  digichem.log.get_logger().debug("Plotting cumulative gaussian peaks from {:0.2f} to {:0.2f} with a step size of {} ({} total points) for {} peaks ({} total iterations)".format(limits[0], limits[1], self.resolution, limits[2], len(self.base_coordinates), len(self.base_coordinates) * limits[2]))
234
235
  gaussian = [
235
- (x, sum((self.gaussian(a, b, c, x) for b, a in self.base_coordinates))) for x in points
236
+ (x, y) for x in points if ( y := sum((self.gaussian(a, b, c, x) for b, a in self.base_coordinates))) > self.filter
236
237
  ]
237
238
 
238
239
  return gaussian
digichem/result/tdm.py CHANGED
@@ -42,12 +42,12 @@ class Transition_dipole_moment_ABC(Dipole_moment_ABC):
42
42
  atoms = result_set.atoms
43
43
  )
44
44
 
45
- def dump(self, digichem_options):
45
+ def _dump_(self, digichem_options, all):
46
46
  """
47
47
  Get a representation of this result object in primitive format.
48
48
  """
49
49
  data = {'state_level': self.state_level}
50
- data.update(super().dump(digichem_options))
50
+ data.update(super()._dump_(digichem_options, all))
51
51
  return data
52
52
 
53
53
  @property
@@ -221,13 +221,13 @@ class Transition_dipole_moment(Result_object):
221
221
 
222
222
  return self(electric = electric, magnetic = magnetic)
223
223
 
224
- def dump(self, digichem_options):
224
+ def _dump_(self, digichem_options, all):
225
225
  """
226
226
  Get a representation of this result object in primitive format.
227
227
  """
228
228
  return {
229
- "electric": self.electric.dump(digichem_options) if self.electric is not None else None,
230
- "magnetic": self.magnetic.dump(digichem_options) if self.magnetic is not None else None,
229
+ "electric": self.electric.dump(digichem_options, all) if self.electric is not None else None,
230
+ "magnetic": self.magnetic.dump(digichem_options, all) if self.magnetic is not None else None,
231
231
  "angle": {
232
232
  "value": float(self.angle().angle) if self.electric is not None and self.magnetic is not None else None,
233
233
  "units": self.angle().units if self.electric is not None and self.magnetic is not None else None,
@@ -43,7 +43,7 @@ class Vibrations_list(Result_container, Unmergeable_container_mixin):
43
43
  """
44
44
  return self(Vibration.list_from_parser(parser))
45
45
 
46
- def generate_for_dump(self):
46
+ def _get_dump_(self):
47
47
  """
48
48
  Method used to get a dictionary used to generate on-demand values for dumping.
49
49
 
@@ -51,7 +51,9 @@ class Vibrations_list(Result_container, Unmergeable_container_mixin):
51
51
 
52
52
  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.
53
53
  """
54
- return {"spectrum": self.generate_spectrum}
54
+ return {
55
+ "spectrum": self.generate_spectrum,
56
+ }
55
57
 
56
58
  def generate_spectrum(self, digichem_options):
57
59
  """
@@ -65,7 +67,14 @@ class Vibrations_list(Result_container, Unmergeable_container_mixin):
65
67
  from digichem.result.spectroscopy import Spectroscopy_graph
66
68
 
67
69
 
68
- spectrum = Spectroscopy_graph.from_vibrations(self, digichem_options['IR_spectrum']['fwhm'], digichem_options['IR_spectrum']['gaussian_resolution'], digichem_options['IR_spectrum']['gaussian_cutoff'])
70
+ spectrum = Spectroscopy_graph.from_vibrations(
71
+ self,
72
+ fwhm = digichem_options['IR_spectrum']['fwhm'],
73
+ resolution = digichem_options['IR_spectrum']['gaussian_resolution'],
74
+ cutoff = digichem_options['IR_spectrum']['gaussian_cutoff'],
75
+ filter = digichem_options['IR_spectrum']['y_filter'],
76
+ )
77
+
69
78
 
70
79
  try:
71
80
  spectrum_data = spectrum.plot_cumulative_gaussian()
@@ -82,11 +91,11 @@ class Vibrations_list(Result_container, Unmergeable_container_mixin):
82
91
  "peaks": spectrum_peaks
83
92
  }
84
93
 
85
- def dump(self, digichem_options):
94
+ def _dump_(self, digichem_options, all):
86
95
  dump_dict = {
87
96
  "num_vibrations": len(self),
88
97
  "num_negative": len(self.negative),
89
- "values": super().dump(digichem_options),
98
+ "values": super()._dump_(digichem_options, all),
90
99
  }
91
100
  return dump_dict
92
101
 
@@ -126,7 +135,7 @@ class Vibration(Result_object, Floatable_mixin):
126
135
  """
127
136
  return float(self.frequency)
128
137
 
129
- def dump(self, digichem_options):
138
+ def _dump_(self, digichem_options, all):
130
139
  """
131
140
  Get a representation of this result object in primitive format.
132
141
  """
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"]