orochi.phase 4.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 (69) hide show
  1. orochi/__init__.py +22 -0
  2. orochi/phase/__init__.py +4 -0
  3. orochi/phase/database/__init__.py +0 -0
  4. orochi/phase/database/atoms.py +198 -0
  5. orochi/phase/database/compton_cromer_mann_ana.py +34 -0
  6. orochi/phase/database/f0_waasmaier_kirfel.py +46 -0
  7. orochi/phase/database/f1f2_brennan_cowan.py +35 -0
  8. orochi/phase/database/info/compton.py +884 -0
  9. orochi/phase/database/info/element_data.db +0 -0
  10. orochi/phase/database/info/f0.py +2776 -0
  11. orochi/phase/database/info/f1f2.py +96828 -0
  12. orochi/phase/database/info/group_correlations.db +0 -0
  13. orochi/phase/database/info/symmetry_groups.db +0 -0
  14. orochi/phase/database/info/wyckoff.db +0 -0
  15. orochi/phase/database/symmetries.py +573 -0
  16. orochi/phase/io/files.py +41 -0
  17. orochi/phase/io/formats/cif.py +748 -0
  18. orochi/phase/io/formats/cube.py +330 -0
  19. orochi/phase/io/formats/xyz.py +25 -0
  20. orochi/phase/macro/analysis/coordination.py +49 -0
  21. orochi/phase/macro/analysis/find_best_xyz.py +63 -0
  22. orochi/phase/macro/analysis/indices_to_be_adjusted.py +170 -0
  23. orochi/phase/macro/analysis/score.py +72 -0
  24. orochi/phase/macro/analysis/site_relation.py +157 -0
  25. orochi/phase/macro/analyze_cif.py +19 -0
  26. orochi/phase/macro/constraint/adp.py +30 -0
  27. orochi/phase/macro/constraint/lattice.py +43 -0
  28. orochi/phase/macro/constraint/occ.py +31 -0
  29. orochi/phase/macro/constraint/particle_shape.py +7 -0
  30. orochi/phase/macro/constraint/symmetry.py +0 -0
  31. orochi/phase/macro/modify/atom_move.py +36 -0
  32. orochi/phase/macro/modify/stack.py +42 -0
  33. orochi/phase/macro/modify/supercell.py +26 -0
  34. orochi/phase/macro/modify/xyz.py +688 -0
  35. orochi/phase/macro/param_space/lattice.py +275 -0
  36. orochi/phase/macro/param_space/xyz.py +133 -0
  37. orochi/phase/macro/restraint/adp.py +23 -0
  38. orochi/phase/macro/restraint/lattice.py +137 -0
  39. orochi/phase/macro/restraint/occ.py +39 -0
  40. orochi/phase/macro/restraint/xyz.py +95 -0
  41. orochi/phase/macro/topology/bond_analysis.py +782 -0
  42. orochi/phase/macro/topology/topology_analysis.py +125 -0
  43. orochi/phase/params/default.py +337 -0
  44. orochi/phase/phase.py +1664 -0
  45. orochi/phase/submodules/atom_info.py +66 -0
  46. orochi/phase/submodules/composition.py +120 -0
  47. orochi/phase/submodules/constraint.py +272 -0
  48. orochi/phase/submodules/evaluation.py +246 -0
  49. orochi/phase/submodules/explain.py +106 -0
  50. orochi/phase/submodules/lattice.py +96 -0
  51. orochi/phase/submodules/modify.py +251 -0
  52. orochi/phase/submodules/modulation.py +132 -0
  53. orochi/phase/submodules/properties.py +646 -0
  54. orochi/phase/submodules/shape/base/cylinder.py +237 -0
  55. orochi/phase/submodules/shape/base/function/expansion.py +56 -0
  56. orochi/phase/submodules/shape/base/function/surface.py +122 -0
  57. orochi/phase/submodules/shape/base/polygon.py +361 -0
  58. orochi/phase/submodules/shape/base/spheroid.py +151 -0
  59. orochi/phase/submodules/shape/explicit.py +79 -0
  60. orochi/phase/submodules/shape/stack.py +28 -0
  61. orochi/phase/submodules/shape/standard.py +30 -0
  62. orochi/phase/submodules/symmetry.py +979 -0
  63. orochi/phase/utils/viewer.py +36 -0
  64. orochi/phase/version.py +23 -0
  65. orochi_phase-4.0.0.dist-info/METADATA +236 -0
  66. orochi_phase-4.0.0.dist-info/RECORD +69 -0
  67. orochi_phase-4.0.0.dist-info/WHEEL +5 -0
  68. orochi_phase-4.0.0.dist-info/licenses/LICENSE.rst +682 -0
  69. orochi_phase-4.0.0.dist-info/top_level.txt +1 -0
orochi/__init__.py ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python
2
+ ##############################################################################
3
+ #
4
+ # (c) 2025 National Institute for Materials Science (NIMS).
5
+ # All rights reserved.
6
+ #
7
+ # File coded by: Tominaka Laboratory members and community contributors.
8
+ #
9
+ # See GitHub contributions for a more detailed list of contributors.
10
+ # https://github.com/Tominaka-Laboratory/orochi.pdf-simulator/graphs/contributors
11
+ #
12
+ # See LICENSE.rst for license information.
13
+ #
14
+ ##############################################################################
15
+ """Blank namespace package for module orochi."""
16
+
17
+
18
+ from pkgutil import extend_path
19
+
20
+ __path__ = extend_path(__path__, __name__)
21
+
22
+ # End of file
@@ -0,0 +1,4 @@
1
+ from .phase import Phase
2
+
3
+ __all__ = ["Phase"]
4
+
File without changes
@@ -0,0 +1,198 @@
1
+ import re
2
+ import os
3
+ import sqlite3
4
+ import pandas as pd
5
+ import json
6
+
7
+ elements = {"atomic_number": int, "symbol": str, "atomic_mass": float, "typical_valences": json.loads}
8
+ ionic_radii = {"atomic_number": int, "charge": int, "coordination_number": int, "radius": float, "is_shannon": bool}
9
+ bond_valence_params = {"atom_a": str, "valence_a": int, "atom_b": str, "valence_b": int, "r0": float, "b": float}
10
+ element_group_mapping = {"atomic_number": int, "group_id": int}
11
+ element_groups = {"group_id": int, "group_name": str}
12
+
13
+
14
+ class AtomInformation:
15
+ def __init__(self):
16
+ dir = os.path.dirname(__file__)
17
+ self.table = os.path.join(dir, "info", "element_data.db")
18
+
19
+ ## General Function
20
+ def get(self, table_name:str, targets:list=None, **kwargs):
21
+
22
+ if table_name == "elements":
23
+ form = elements
24
+ elif table_name == "ion_radii":
25
+ form = ionic_radii
26
+ elif table_name == "bond_valence_params":
27
+ form = bond_valence_params
28
+ elif table_name == "element_group_mapping":
29
+ form = element_group_mapping
30
+ elif table_name == "element_groups":
31
+ form = element_groups
32
+ else:
33
+ return None
34
+
35
+ keys = []
36
+ vals = []
37
+ for key, val in kwargs.items():
38
+ if val is None:
39
+ continue
40
+ keys.append(key)
41
+ vals.append(str(val))
42
+
43
+ conn = sqlite3.connect(self.table)
44
+ target = ",".join(targets) if targets else "*"
45
+ where_query = " AND ".join([f"{key} = ?" for key in keys])
46
+ query = f'SELECT {target} FROM {table_name} WHERE {where_query}'
47
+ df = pd.read_sql_query(query, conn, params=vals)
48
+ conn.close()
49
+
50
+ if df.empty:
51
+ return None
52
+ else:
53
+ for col in df.columns:
54
+ if col in form:
55
+ df[col] = df[col].apply(lambda x: form[col](x) if pd.notna(x) else None)
56
+ return df
57
+
58
+ def parse_symbol(self, symbol):
59
+ symbol_str = str(symbol).strip()
60
+ pattern = r'^([A-Z][a-z]?)(\d*)([\+\-]?)$'
61
+ match = re.match(pattern, symbol_str)
62
+ if match:
63
+ symbol = match.group(1)
64
+ charge_str = match.group(2)
65
+ sign = match.group(3)
66
+ if sign:
67
+ charge_num = int(charge_str) if charge_str else 1
68
+ final_charge = charge_num if sign == "+" else -charge_num
69
+ else:
70
+ final_charge = 0
71
+ else:
72
+ final_charge = 0
73
+
74
+ return symbol, final_charge
75
+
76
+ def get_atomic_number(self, symbol=None):
77
+ atomic_number = self.get("elements",
78
+ targets=["atomic_number"],
79
+ symbol=symbol)
80
+ if atomic_number is None:
81
+ return None
82
+ atomic_number = atomic_number.iloc[0]["atomic_number"]
83
+ return atomic_number
84
+
85
+
86
+ def get_symbol(self, atomic_number=None):
87
+ symbol = self.get("elements",
88
+ targets=["symbol"],
89
+ atomic_number=atomic_number)
90
+ if symbol is None:
91
+ return None
92
+ symbol = symbol.iloc[0]["symbol"]
93
+ return symbol
94
+
95
+ def get_atomic_mass(self, atomic_number=None, symbol=None):
96
+ mass = self.get("elements",
97
+ targets=["atomic_mass"],
98
+ atomic_number=atomic_number,
99
+ symbol=symbol)
100
+ if mass is None:
101
+ return None
102
+ mass = mass.iloc[0]["atomic_mass"]
103
+ return mass
104
+
105
+ def get_typical_valences(self, atomic_number=None, symbol=None):
106
+ valences = self.get("elements",
107
+ targets=["typical_valences"],
108
+ atomic_number=atomic_number,
109
+ symbol=symbol)
110
+ if valences is None:
111
+ return [0]
112
+ valences = valences.iloc[0]["typical_valences"]
113
+ return valences
114
+
115
+ def get_shannon_radius(self, atomic_number=None, symbol=None, charge=None, coordination_number=None):
116
+ radius = self.get("ion_radii",
117
+ targets=["radius"],
118
+ atomic_number=atomic_number,
119
+ symbol=symbol,
120
+ charge=charge,
121
+ is_shannon=1,
122
+ coordination_number=coordination_number)
123
+ if radius is None:
124
+ return None
125
+ radius = radius.iloc[0]["radius"]
126
+ return radius
127
+
128
+ def get_radius(self, atomic_number=None, symbol=None, charge=None):
129
+ if charge is None:
130
+ charge = 0
131
+ charge = int(charge)
132
+ radius = self.get("ion_radii",
133
+ targets=["radius"],
134
+ atomic_number=atomic_number,
135
+ symbol=symbol,
136
+ charge=charge,
137
+ is_shannon=0)
138
+ if radius is None and charge != 0:
139
+ radius = self.get("ion_radii",
140
+ targets=["radius"],
141
+ atomic_number=atomic_number,
142
+ symbol=symbol,
143
+ charge=charge,
144
+ is_shannon=1)
145
+ if radius is None:
146
+ radius = self.get("ion_radii",
147
+ targets=["radius"],
148
+ atomic_number=atomic_number,
149
+ symbol=symbol,
150
+ charge=0,
151
+ is_shannon=0)
152
+ if radius is not None:
153
+ radius = radius.iloc[0]["radius"]
154
+
155
+ return radius
156
+
157
+ def get_element_type(self, atomic_number=None, symbol=None):
158
+ if atomic_number is None:
159
+ atomic_number = self.get_atomic_number(symbol)
160
+
161
+ group_id = self.get("element_group_mapping",
162
+ targets=["group_id"],
163
+ atomic_number=atomic_number)
164
+ if group_id is None:
165
+ return None
166
+ group_id = group_id.iloc[0]["group_id"]
167
+ group_name = self.get("element_groups",
168
+ targets=["group_name"],
169
+ group_id=group_id).iloc[0]["group_name"]
170
+ return group_name
171
+
172
+ def get_typical_coordination_number(self, atomic_number=None, symbol=None, charge=None) -> list:
173
+ if charge is not None and int(charge) != 0:
174
+ df = self.get("ion_radii",
175
+ targets=["coordination_number"],
176
+ atomic_number=atomic_number,
177
+ symbol=symbol,
178
+ charge=int(charge),
179
+ is_shannon=1)
180
+ if df is not None and not df.empty:
181
+ cns = sorted(df["coordination_number"].dropna().astype(int).unique().tolist())
182
+ if cns:
183
+ return cns
184
+ df = self.get("ion_radii",
185
+ targets=["coordination_number"],
186
+ atomic_number=atomic_number,
187
+ symbol=symbol,
188
+ is_shannon=1)
189
+ if df is not None and not df.empty:
190
+ cns = sorted(df["coordination_number"].dropna().astype(int).unique().tolist())
191
+ if cns:
192
+ return cns
193
+ return [0]
194
+
195
+
196
+
197
+
198
+
@@ -0,0 +1,34 @@
1
+ import re
2
+ import numpy as np
3
+ from .info.compton import symbol_data
4
+
5
+ def compton_function(atom):
6
+ """Compton scattering
7
+
8
+ Source: D.T. Cormer and J. B. Mann: J. Chem. Phys., 47 1892 (1967)
9
+ return q-dependent function
10
+
11
+
12
+ Returns
13
+ -------
14
+ function(q)
15
+ Function returning 1d array form of Compoton scattering at eneryg of q
16
+ """
17
+
18
+ atom = re.sub(r"[-+,\d]", "", atom)
19
+ p = symbol_data.get(atom)
20
+
21
+ def compton(q):
22
+ cf = (
23
+ p[0]
24
+ - (
25
+ p[1] * np.exp(-p[2] * (q / 4.0 / np.pi) ** 2.0)
26
+ + p[3] * np.exp(-p[4] * (q / 4.0 / np.pi) ** 2)
27
+ + p[5] * np.exp(-p[6] * (q / 4.0 / np.pi) ** 2.0)
28
+ + p[7]
29
+ )
30
+ ** 2.0
31
+ )
32
+ return cf
33
+
34
+ return compton
@@ -0,0 +1,46 @@
1
+ import re
2
+ import numpy as np
3
+ from .info.f0 import symbol_data
4
+
5
+ def f0_function(atom):
6
+ """Atomic scattering factors.
7
+
8
+ Source: D. Waasmaier & A. Kirfel (Acta Cryst. (1995). A51, 416-413) (f0 for nonionic atoms)
9
+ list [a1 a2 a3 a4 a5 c b1 b2 b3 b4 b5]
10
+ f0[k] = c + [SUM a_i*EXP(-b_i*(k^2)) ]
11
+ return q dependent function
12
+
13
+ Parameters
14
+ ----------
15
+ atom : string
16
+ element type
17
+
18
+ Returns
19
+ -------
20
+ f(q)
21
+ Function returning 1d array form of scattering factor at eneryg of q
22
+ """
23
+
24
+
25
+ list = symbol_data.get(atom)
26
+ if list == None:
27
+ atom = re.sub(r"[-+,\d]", "", atom)
28
+ list = symbol_data[atom]
29
+
30
+ data = np.array(list)
31
+ f0a = data[0:5]
32
+ f0b = data[6:11]
33
+ f0c = data[5]
34
+
35
+ def get_f0(q):
36
+ s = np.square(q / (4.0 * np.pi)) # =(sin(theta)/rambda)^2
37
+ f0 = (
38
+ np.sum(
39
+ f0a * np.exp(-1.0 * f0b[np.newaxis, :] * s[:, np.newaxis]),
40
+ axis=-1,
41
+ )
42
+ + f0c
43
+ )
44
+ return f0
45
+
46
+ return get_f0
@@ -0,0 +1,35 @@
1
+ import re
2
+ import numpy as np
3
+ from .info.f1f2 import symbol_data
4
+
5
+ def f1f2_function(atom):
6
+ """Energy-dependence functions of scattering factors.
7
+ phton energy [ev], f1, f2
8
+
9
+ Source: S. Brennan and P.L. Cowan (1992), Rev. Sci. Instrum. 63, 850.
10
+
11
+ Parameters
12
+ ----------
13
+ atom : string
14
+ Element type
15
+
16
+ Returns
17
+ -------
18
+ list
19
+ list(numpy.ndarray(f1), numpy.ndarray(f2))
20
+ """
21
+
22
+
23
+ atom = re.sub(r"[-+,\d]", "", atom)
24
+ list = symbol_data.get(atom)
25
+ if list == None:
26
+ list = [[0, 0, 0], [200000, 0, 0]]
27
+
28
+ data = np.array(list)
29
+
30
+ def get_f1f2(energy):
31
+ f1 = np.interp(energy, data[:, 0], data[:, 1])
32
+ f2 = np.interp(energy, data[:, 0], data[:, 2])
33
+ return [f1, f2]
34
+
35
+ return get_f1f2