Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

""" 

Contains the Orbit class which hold onformation about equivalent clusters. 

""" 

 

import numpy as np 

import tarfile 

 

from .orientation_family import OrientationFamily 

from ..io.read_write_files import (add_items_to_tarfile_hdf5, 

add_items_to_tarfile_pickle, 

add_list_to_tarfile_custom, 

read_items_hdf5, 

read_items_pickle, 

read_list_custom) 

 

 

class Orbit: 

""" 

This class serves as a container for storing data pertaining to an orbit. 

 

Attributes 

---------- 

orientation_families : list of OrientationFamily objs 

The orientation families of the orbit 

eigensymmetries : list of tuples 

Each eigensymmetry correspond to a pair where the first index is the 

symmetry and the second is the permutation 

eigentensors : list of NumPy arrays 

The decomposition of the force constant into symmetry elements 

""" 

 

# TODO: Make properties of the parameters 

def __init__(self): 

self.orientation_families = [] 

self.eigensymmetries = [] 

self.eigentensors = [] 

 

@property 

def prototype_index(self): 

"""int : index of cluster that serves as prototype for this orbit 

 

In the code the first symmetry is always the identity so the first 

orientation family should always correspond to the prototype""" 

return self.orientation_families[0].cluster_indices[0] 

 

def write(self, f): 

"""Write a Orbit instance to a file. 

 

Parameters 

---------- 

f : str or file object 

name of input file (str) or stream to write to (file object) 

""" 

tar_file = tarfile.open(mode='w', fileobj=f) 

 

# add eigentensors as NumPy array 

items_hdf5 = dict(eigentensors=np.array(self.eigentensors), 

) 

add_items_to_tarfile_hdf5(tar_file, items_hdf5, 'eigentensors') 

 

# add eigensymmetries as list 

items_pickle = dict(eigensymmetries=self.eigensymmetries, 

order=self.order, radius=self.radius, 

maximum_distance=self.maximum_distance) 

add_items_to_tarfile_pickle(tar_file, items_pickle, 'attributes') 

 

# add orientation families 

add_list_to_tarfile_custom(tar_file, self.orientation_families, 

'orientation_families') 

tar_file.close() 

 

@staticmethod 

def read(f): 

"""Load a ClusterSpace from file 

 

Parameters 

---------- 

f : string or file object 

name of input file (string) or stream to load from (file object) 

""" 

 

orb = Orbit() 

tar_file = tarfile.open(mode='r', fileobj=f) 

 

# read eigentensors hdf5 

items_hdf5 = read_items_hdf5(tar_file, 'eigentensors') 

orb.eigentensors = [et for et in items_hdf5['eigentensors']] 

 

# read attributes pickle 

attributes = read_items_pickle(tar_file, 'attributes') 

for name, value in attributes.items(): 

orb.__setattr__(name, value) 

 

# read orientation families 

ofs = read_list_custom(tar_file, 'orientation_families', 

OrientationFamily.read) 

orb.orientation_families = ofs 

return orb 

 

 

def get_geometrical_radius(positions): 

"""Compute the geometrical size of a 3-dimensional point cloud. The 

geometrical size is defined as the average distance to the geometric 

center. 

 

Parameters 

---------- 

positions : list of 3-dimensional vectors 

positions of points in cloud 

 

Returns 

------- 

float 

geometric size of point cloud 

""" 

geometric_center = np.mean(positions, axis=0) 

return np.mean(np.sqrt(np.sum((positions - geometric_center)**2, axis=1))) 

 

 

def get_maximum_distance(positions): 

"""Compute the maximum distance between any two points in a 3-dimensional 

point cloud. This is equivalent to the "size" criterion used when imposing 

a certain (pair) cutoff criterion during construction of a set of clusters. 

 

Parameters 

---------- 

positions : list of 3-dimensional vectors 

positions of points in cloud 

 

Returns 

------- 

float 

maximum distance betwee any two points 

""" 

135 ↛ 136line 135 didn't jump to line 136, because the condition on line 135 was never true if len(positions) == 0: 

return 0.0 

max_distance = 0.0 

for pt1 in positions[:-1]: 

for pt2 in positions[1:]: 

max_distance = max(max_distance, np.linalg.norm(pt1 - pt2)) 

return max_distance