-
Notifications
You must be signed in to change notification settings - Fork 0
/
Identify.py
103 lines (86 loc) · 2.7 KB
/
Identify.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
"""
Identify.py
This file is used to identify the type of structure that is being used.
"""
import numpy as np
def identify(xyz):
"""
identify
This function is used to identify the type of structure that is
being used given the XYZ coordinates of the atoms in the
structure.
:param xyz:
:return: The type of structure that is being used.
"""
movements = get_movements(xyz)
movement_set = []
for move in movements:
move = move.tolist()
if not close_to_any(move, movement_set):
movement_set.append(move)
neg_move = [-move[0], -move[1], -move[2]]
if not close_to_any(neg_move, movement_set):
movement_set.append(neg_move)
distance_counter = {
0.0: 0,
1.0: 0,
1.4: 0,
1.7: 0,
2.0: 0
}
for move in movement_set:
for move2 in movement_set:
move = np.array(move)
move2 = np.array(move2)
distance = np.linalg.norm(move - move2)
if distance < 0.5:
distance_counter[0.0] += 1
elif distance < 1.2:
distance_counter[1.0] += 1
elif distance < 1.55:
distance_counter[1.4] += 1
elif distance < 1.85:
distance_counter[1.7] += 1
else:
distance_counter[2.0] += 1
if distance_counter[1.0] == 0 and distance_counter[1.7] == 0:
if len(movement_set) > 4:
return 6, "CUBIC HONEYCOMB"
else:
return 4, "SQUARE TILING"
else:
if len(movement_set) > 8:
return 12, "TETRAHEDRAL-OCTAHEDRAL HONEYCOMB"
else:
return 8, "TRIANGULAR PRISMATIC HONEYCOMB"
def get_movements(xyz):
"""
get_movements
This function is used to get the movements of the atoms in the
structure.
:param xyz:
:return: A numpy array of the movements of the atoms in the
structure.
"""
movements = np.zeros((xyz.shape[0] - 1, xyz.shape[1]))
for i in range(len(xyz) - 1):
movements[i] = xyz[i + 1] - xyz[i]
return movements
def close_to_any(main_vector, set_of_vectors, threshold=0.15):
"""
close_to_any
This function is used to determine if a vector is close to any
vector in a set of vectors.
:param main_vector:
:param set_of_vectors:
:param threshold:
:return: True if the vector is close to any vector in the set of
vectors, False otherwise.
"""
for vector in set_of_vectors:
vector = np.array(vector)
main_vector = np.array(main_vector)
distance = np.linalg.norm(main_vector - vector)
if distance < threshold:
return True
return False