digichem-core 6.0.0rc1__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 (111) hide show
  1. digichem/__init__.py +75 -0
  2. digichem/basis.py +116 -0
  3. digichem/config/README +3 -0
  4. digichem/config/__init__.py +5 -0
  5. digichem/config/base.py +321 -0
  6. digichem/config/locations.py +14 -0
  7. digichem/config/parse.py +90 -0
  8. digichem/config/util.py +117 -0
  9. digichem/data/README +4 -0
  10. digichem/data/batoms/COPYING +18 -0
  11. digichem/data/batoms/LICENSE +674 -0
  12. digichem/data/batoms/README +2 -0
  13. digichem/data/batoms/__init__.py +0 -0
  14. digichem/data/batoms/batoms-renderer.py +351 -0
  15. digichem/data/config/digichem.yaml +714 -0
  16. digichem/data/functionals.csv +15 -0
  17. digichem/data/solvents.csv +185 -0
  18. digichem/data/tachyon/COPYING.md +5 -0
  19. digichem/data/tachyon/LICENSE +30 -0
  20. digichem/data/tachyon/tachyon_LINUXAMD64 +0 -0
  21. digichem/data/vmd/common.tcl +468 -0
  22. digichem/data/vmd/generate_combined_orbital_images.tcl +70 -0
  23. digichem/data/vmd/generate_density_images.tcl +45 -0
  24. digichem/data/vmd/generate_dipole_images.tcl +68 -0
  25. digichem/data/vmd/generate_orbital_images.tcl +57 -0
  26. digichem/data/vmd/generate_spin_images.tcl +66 -0
  27. digichem/data/vmd/generate_structure_images.tcl +40 -0
  28. digichem/datas.py +14 -0
  29. digichem/exception/__init__.py +7 -0
  30. digichem/exception/base.py +133 -0
  31. digichem/exception/uncatchable.py +63 -0
  32. digichem/file/__init__.py +1 -0
  33. digichem/file/base.py +364 -0
  34. digichem/file/cube.py +284 -0
  35. digichem/file/fchk.py +94 -0
  36. digichem/file/prattle.py +277 -0
  37. digichem/file/types.py +97 -0
  38. digichem/image/__init__.py +6 -0
  39. digichem/image/base.py +113 -0
  40. digichem/image/excited_states.py +335 -0
  41. digichem/image/graph.py +293 -0
  42. digichem/image/orbitals.py +239 -0
  43. digichem/image/render.py +617 -0
  44. digichem/image/spectroscopy.py +797 -0
  45. digichem/image/structure.py +115 -0
  46. digichem/image/vmd.py +826 -0
  47. digichem/input/__init__.py +3 -0
  48. digichem/input/base.py +78 -0
  49. digichem/input/digichem_input.py +500 -0
  50. digichem/input/gaussian.py +140 -0
  51. digichem/log.py +179 -0
  52. digichem/memory.py +166 -0
  53. digichem/misc/__init__.py +4 -0
  54. digichem/misc/argparse.py +44 -0
  55. digichem/misc/base.py +61 -0
  56. digichem/misc/io.py +239 -0
  57. digichem/misc/layered_dict.py +285 -0
  58. digichem/misc/text.py +139 -0
  59. digichem/misc/time.py +73 -0
  60. digichem/parse/__init__.py +13 -0
  61. digichem/parse/base.py +220 -0
  62. digichem/parse/cclib.py +138 -0
  63. digichem/parse/dump.py +253 -0
  64. digichem/parse/gaussian.py +130 -0
  65. digichem/parse/orca.py +96 -0
  66. digichem/parse/turbomole.py +201 -0
  67. digichem/parse/util.py +523 -0
  68. digichem/result/__init__.py +6 -0
  69. digichem/result/alignment/AA.py +114 -0
  70. digichem/result/alignment/AAA.py +61 -0
  71. digichem/result/alignment/FAP.py +148 -0
  72. digichem/result/alignment/__init__.py +3 -0
  73. digichem/result/alignment/base.py +310 -0
  74. digichem/result/angle.py +153 -0
  75. digichem/result/atom.py +742 -0
  76. digichem/result/base.py +258 -0
  77. digichem/result/dipole_moment.py +332 -0
  78. digichem/result/emission.py +402 -0
  79. digichem/result/energy.py +323 -0
  80. digichem/result/excited_state.py +821 -0
  81. digichem/result/ground_state.py +94 -0
  82. digichem/result/metadata.py +644 -0
  83. digichem/result/multi.py +98 -0
  84. digichem/result/nmr.py +1086 -0
  85. digichem/result/orbital.py +647 -0
  86. digichem/result/result.py +244 -0
  87. digichem/result/soc.py +272 -0
  88. digichem/result/spectroscopy.py +514 -0
  89. digichem/result/tdm.py +267 -0
  90. digichem/result/vibration.py +167 -0
  91. digichem/test/__init__.py +6 -0
  92. digichem/test/conftest.py +4 -0
  93. digichem/test/test_basis.py +71 -0
  94. digichem/test/test_calculate.py +30 -0
  95. digichem/test/test_config.py +78 -0
  96. digichem/test/test_cube.py +369 -0
  97. digichem/test/test_exception.py +16 -0
  98. digichem/test/test_file.py +104 -0
  99. digichem/test/test_image.py +337 -0
  100. digichem/test/test_input.py +64 -0
  101. digichem/test/test_parsing.py +79 -0
  102. digichem/test/test_prattle.py +36 -0
  103. digichem/test/test_result.py +489 -0
  104. digichem/test/test_translate.py +112 -0
  105. digichem/test/util.py +207 -0
  106. digichem/translate.py +591 -0
  107. digichem_core-6.0.0rc1.dist-info/METADATA +96 -0
  108. digichem_core-6.0.0rc1.dist-info/RECORD +111 -0
  109. digichem_core-6.0.0rc1.dist-info/WHEEL +4 -0
  110. digichem_core-6.0.0rc1.dist-info/licenses/COPYING.md +10 -0
  111. digichem_core-6.0.0rc1.dist-info/licenses/LICENSE +11 -0
digichem/test/util.py ADDED
@@ -0,0 +1,207 @@
1
+ """Common testing utilities and convenience functions."""
2
+
3
+ import pytest
4
+ from pathlib import Path
5
+
6
+ import digichem.config
7
+ from digichem.datas import get_resource
8
+
9
+
10
+ def data_directory():
11
+ """
12
+ Get a path to the test data directory.
13
+ """
14
+ return get_resource('test/data')
15
+
16
+
17
+ # Input files.
18
+ benzene_cdx = Path(data_directory(), "Input", "Benzene.cdx")
19
+ pyridine_cml = Path(data_directory(), "Input", "Pyridine.cml")
20
+ cyclopentane_com = Path(data_directory(), "Input", "Cyclopentane.com")
21
+ water_xyz = Path(data_directory(), "Input", "Water.xyz")
22
+ ethane_xyz = Path(data_directory(), "Input", "Ethane.xyz")
23
+ pyridine_si_v2 = Path(data_directory(), "Input/Pyridine.v2.si")
24
+ pyridine_si_v1 = Path(data_directory(), "Input/Pyridine.v1.si")
25
+
26
+
27
+ # Result files for testing parsing.
28
+ result_files = {
29
+ "gaussian": [Path(data_directory(), datum) for datum in [
30
+ 'Naphthalene/Gaussian 16 Optimisation Frequencies PBE1PBE (GD3BJ) Toluene 6-31G(d,p)',
31
+ 'Naphthalene/Gaussian 16 Excited States TDA 10 Singlets 10 Triplets PBE1PBE (GD3BJ) Toluene 6-31G(d,p).tar.gz',
32
+ 'Naphthalene/Gaussian 16 Excited States TDA Optimised S(1) PBE1PBE (GD3BJ) Toluene 6-31G(d,p).tar.gz',
33
+ ]],
34
+ "turbomole": [Path(data_directory(), datum) for datum in [
35
+ 'Naphthalene/Turbomole Optimisation ADC(2) cc-pVDZ.tar.gz',
36
+ 'Naphthalene/Turbomole Excited States ADC(2) S(1) and S(2) cc-pVDZ.tar.gz',
37
+ 'Naphthalene/Turbomole Excited States ADC(2) T(1) and T(2) cc-pVDZ.tar.gz',
38
+ ]],
39
+ "orca": [Path(data_directory(), datum) for datum in [
40
+ 'Pyridine/Orca Single Point PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz',
41
+ 'Pyridine/Orca Gradient PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz',
42
+ 'Pyridine/Orca Optimisation PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz',
43
+ 'Pyridine/Orca Optimisation Frequencies PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz',
44
+ 'Pyridine/Orca Frequencies PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz',
45
+ 'Pyridine/Orca NMR PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz',
46
+ 'Pyridine/Orca Excited States TDA 10 Singlets 10 Triplets PBE0 (GD3BJ) Gas Phase Pople Basis Sets STO-3G.tar.gz'
47
+ ]]
48
+ }
49
+
50
+ @pytest.fixture(scope="package")
51
+ def digichem_options(tmpdir_factory):
52
+ config = digichem.config.get_config()
53
+
54
+ # Change the default DB locations to prevent SPAM.
55
+ config['databases'] = [
56
+ "{{name: test1, path: {}}}".format(
57
+ Path(tmpdir_factory.mktemp("silico_database1"), "tmp.db")
58
+ ),
59
+ "{{name: test2, path: {}}}".format(
60
+ Path(tmpdir_factory.mktemp("silico_database2"), "tmp.db")
61
+ ),
62
+ "{{name: test3, auto_fill: False, path: {}}}".format(
63
+ Path(tmpdir_factory.mktemp("silico_database3"), "tmp.db")
64
+ ),
65
+ ]
66
+ config.logging['render_logging'] = True
67
+ config.validate()
68
+ return config
69
+
70
+
71
+ def check_float_list(test_list, expected_list, abs = 1e-4):
72
+ """
73
+ Helper function to compare to lists of floats.
74
+ """
75
+ # Pytest bug #9921 prevents this comparison from working for now...
76
+ #assert test_list == pytest.approx(expected_list, abs=abs)
77
+ for list_index in range(0,len(expected_list)):
78
+ assert test_list[list_index] == pytest.approx(expected_list[list_index], abs=abs)
79
+
80
+
81
+ def check_dipole(dipole_moment, coords, abs = 1e-4):
82
+ """
83
+ Helper function to check a dipole moment (PDM, TEDM or TMDM) matches some expected values.
84
+ """
85
+ check_float_list(dipole_moment.vector_coords, coords, abs)
86
+
87
+ # Check total
88
+ assert dipole_moment.total == pytest.approx((coords[0] **2 + coords[1] **2 + coords[2] **2) **0.5, abs = abs)
89
+
90
+
91
+ def check_orbitals(orbitals, num_occ, num_unocc, homo, lumo):
92
+ """Helper function for checking orbital energies"""
93
+ # Check numbers.
94
+ assert len(orbitals) == num_occ + num_unocc
95
+ assert len(orbitals.occupied) == num_occ
96
+ assert len(orbitals.virtual) == num_unocc
97
+
98
+ # Check energies.
99
+ assert orbitals.HOMO_energy == pytest.approx(homo)
100
+ assert orbitals.LUMO_energy == pytest.approx(lumo)
101
+ assert orbitals.HOMO_LUMO_energy == pytest.approx(lumo - homo)
102
+
103
+ # Check ordering.
104
+ assert [orbital.level for orbital in orbitals] == list(range(1, num_occ + num_unocc +1))
105
+
106
+
107
+ def check_rendered_image(base_name):
108
+ """Check whether the eight separate images of a given rendered image have been created."""
109
+ for extension in ["jpg", "png"]:
110
+ for orientation in ["x0y0z0", "x0y90z0", "x45y45z45", "x90y0z0"]:
111
+ assert Path(base_name.parent, f"{base_name.name}.{orientation}.{extension}").exists()
112
+
113
+
114
+ def check_report(report_folder, base_name, *,
115
+ unrestricted = False,
116
+ optimisation = False,
117
+ dipole = True,
118
+ vibrations = False,
119
+ excited_states = False,
120
+ absorption = False,
121
+ nmr = False,
122
+ s1_tdm = False,
123
+ s1_diff = False,
124
+ t1_diff = False,
125
+ s1_nto = False,
126
+ t1_nto = False,
127
+ vertical_emission = False,
128
+ adiabatic_emission = False):
129
+ """
130
+ Check that certain report and image files have been correctly rendered.
131
+ """
132
+ # First, check the report file itself is there
133
+ assert (Path(report_folder, f"{base_name}.journal.pdf").exists() and Path(report_folder, f"{base_name}.traditional.pdf").exists()) or Path(report_folder, f"{base_name}.pdf").exists()
134
+
135
+ # Now check for images.
136
+ image_folder = Path(report_folder, "image")
137
+ # HOMO and LUMO
138
+ for image in (["HOMO", "LUMO"] if not unrestricted else ["HOMO (alpha)", "HOMO (beta)", "LUMO (alpha)", "LUMO (beta)"]):
139
+ check_rendered_image(Path(image_folder, f"{image}", f"{base_name}.{image}"))
140
+
141
+ # HOMO-LUMO overlap
142
+ if not unrestricted:
143
+ check_rendered_image(Path(image_folder, "HOMO LUMO", f"{base_name}.HOMO_LUMO"))
144
+
145
+ else:
146
+ check_rendered_image(Path(image_folder, "HOMO LUMO", f"{base_name}.alpha_HOMO_LUMO"))
147
+ check_rendered_image(Path(image_folder, "HOMO LUMO", f"{base_name}.beta_HOMO_LUMO"))
148
+
149
+ # Structure and density.
150
+ check_rendered_image(Path(image_folder, "Structure", f"{base_name}.structure"))
151
+ check_rendered_image(Path(image_folder, "Density", f"{base_name}.SCF"))
152
+
153
+ # Dipole.
154
+ if dipole:
155
+ check_rendered_image(Path(image_folder, "Dipole Moment", f"{base_name}.dipole"))
156
+
157
+ if optimisation:
158
+ assert Path(image_folder, f"{base_name}.SCF_graph.png").exists()
159
+
160
+ # HOMO-LUMO diagrams.
161
+ if not unrestricted:
162
+ assert Path(image_folder, "Orbital Diagram", f"{base_name}.HOMO_LUMO.png").exists()
163
+ assert Path(image_folder, "Orbital Diagram", f"{base_name}.orbitals.png").exists()
164
+
165
+ else:
166
+ assert Path(image_folder, "Orbital Diagram", f"{base_name}.alpha_HOMO_LUMO.png").exists()
167
+ assert Path(image_folder, "Orbital Diagram", f"{base_name}.beta_HOMO_LUMO.png").exists()
168
+ assert Path(image_folder, "Orbital Diagram", f"{base_name}.alpha_orbitals.png").exists()
169
+ assert Path(image_folder, "Orbital Diagram", f"{base_name}.beta_orbitals.png").exists()
170
+
171
+ # NMR.
172
+ if nmr:
173
+ assert len(Path(image_folder, "NMR").iterdir()) != 0
174
+
175
+ # Excited state stuff.
176
+ if s1_tdm:
177
+ check_rendered_image(Path(image_folder, "S(1) Transition Dipole Moment", f"{base_name}.S(1)_dipole"))
178
+
179
+ if s1_diff:
180
+ check_rendered_image(Path(image_folder, "S(1)", f"{base_name}.S(1)_difference_density"))
181
+
182
+ if t1_diff:
183
+ check_rendered_image(Path(image_folder, "T(1)", f"{base_name}.T(1)_difference_density"))
184
+
185
+ if s1_nto:
186
+ check_rendered_image(Path(image_folder, "S(1)", f"{base_name}.S(1)_NTO"))
187
+
188
+ if t1_nto:
189
+ check_rendered_image(Path(image_folder, "T(1)", f"{base_name}.T(1)_NTO"))
190
+
191
+ if excited_states:
192
+ assert Path(image_folder, f"{base_name}.excited_states.png").exists()
193
+
194
+ if absorption:
195
+ assert Path(image_folder, f"{base_name}.simulated_absorption_spectrum.png").exists()
196
+
197
+ if vertical_emission:
198
+ assert Path(image_folder, f"{base_name}.vertical_S(1)_emission_states.png").exists()
199
+ assert Path(image_folder, f"{base_name}.simulated_vertical_S(1)_emission_spectrum.png").exists()
200
+
201
+ if adiabatic_emission:
202
+ assert Path(image_folder, f"{base_name}.adiabatic_S(1)_emission_states.png").exists()
203
+ assert Path(image_folder, f"{base_name}.simulated_adiabatic_S(1)_emission_spectrum.png").exists()
204
+
205
+ # Vibrations.
206
+ if vibrations:
207
+ assert Path(image_folder, f"{base_name}.simulated_frequencies.png").exists()