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.
- orochi/__init__.py +22 -0
- orochi/phase/__init__.py +4 -0
- orochi/phase/database/__init__.py +0 -0
- orochi/phase/database/atoms.py +198 -0
- orochi/phase/database/compton_cromer_mann_ana.py +34 -0
- orochi/phase/database/f0_waasmaier_kirfel.py +46 -0
- orochi/phase/database/f1f2_brennan_cowan.py +35 -0
- orochi/phase/database/info/compton.py +884 -0
- orochi/phase/database/info/element_data.db +0 -0
- orochi/phase/database/info/f0.py +2776 -0
- orochi/phase/database/info/f1f2.py +96828 -0
- orochi/phase/database/info/group_correlations.db +0 -0
- orochi/phase/database/info/symmetry_groups.db +0 -0
- orochi/phase/database/info/wyckoff.db +0 -0
- orochi/phase/database/symmetries.py +573 -0
- orochi/phase/io/files.py +41 -0
- orochi/phase/io/formats/cif.py +748 -0
- orochi/phase/io/formats/cube.py +330 -0
- orochi/phase/io/formats/xyz.py +25 -0
- orochi/phase/macro/analysis/coordination.py +49 -0
- orochi/phase/macro/analysis/find_best_xyz.py +63 -0
- orochi/phase/macro/analysis/indices_to_be_adjusted.py +170 -0
- orochi/phase/macro/analysis/score.py +72 -0
- orochi/phase/macro/analysis/site_relation.py +157 -0
- orochi/phase/macro/analyze_cif.py +19 -0
- orochi/phase/macro/constraint/adp.py +30 -0
- orochi/phase/macro/constraint/lattice.py +43 -0
- orochi/phase/macro/constraint/occ.py +31 -0
- orochi/phase/macro/constraint/particle_shape.py +7 -0
- orochi/phase/macro/constraint/symmetry.py +0 -0
- orochi/phase/macro/modify/atom_move.py +36 -0
- orochi/phase/macro/modify/stack.py +42 -0
- orochi/phase/macro/modify/supercell.py +26 -0
- orochi/phase/macro/modify/xyz.py +688 -0
- orochi/phase/macro/param_space/lattice.py +275 -0
- orochi/phase/macro/param_space/xyz.py +133 -0
- orochi/phase/macro/restraint/adp.py +23 -0
- orochi/phase/macro/restraint/lattice.py +137 -0
- orochi/phase/macro/restraint/occ.py +39 -0
- orochi/phase/macro/restraint/xyz.py +95 -0
- orochi/phase/macro/topology/bond_analysis.py +782 -0
- orochi/phase/macro/topology/topology_analysis.py +125 -0
- orochi/phase/params/default.py +337 -0
- orochi/phase/phase.py +1664 -0
- orochi/phase/submodules/atom_info.py +66 -0
- orochi/phase/submodules/composition.py +120 -0
- orochi/phase/submodules/constraint.py +272 -0
- orochi/phase/submodules/evaluation.py +246 -0
- orochi/phase/submodules/explain.py +106 -0
- orochi/phase/submodules/lattice.py +96 -0
- orochi/phase/submodules/modify.py +251 -0
- orochi/phase/submodules/modulation.py +132 -0
- orochi/phase/submodules/properties.py +646 -0
- orochi/phase/submodules/shape/base/cylinder.py +237 -0
- orochi/phase/submodules/shape/base/function/expansion.py +56 -0
- orochi/phase/submodules/shape/base/function/surface.py +122 -0
- orochi/phase/submodules/shape/base/polygon.py +361 -0
- orochi/phase/submodules/shape/base/spheroid.py +151 -0
- orochi/phase/submodules/shape/explicit.py +79 -0
- orochi/phase/submodules/shape/stack.py +28 -0
- orochi/phase/submodules/shape/standard.py +30 -0
- orochi/phase/submodules/symmetry.py +979 -0
- orochi/phase/utils/viewer.py +36 -0
- orochi/phase/version.py +23 -0
- orochi_phase-4.0.0.dist-info/METADATA +236 -0
- orochi_phase-4.0.0.dist-info/RECORD +69 -0
- orochi_phase-4.0.0.dist-info/WHEEL +5 -0
- orochi_phase-4.0.0.dist-info/licenses/LICENSE.rst +682 -0
- 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
|
orochi/phase/__init__.py
ADDED
|
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
|