servalcat 0.4.131__cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.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.
- servalcat/__init__.py +10 -0
- servalcat/__main__.py +120 -0
- servalcat/ext.cpython-314t-x86_64-linux-gnu.so +0 -0
- servalcat/refine/__init__.py +0 -0
- servalcat/refine/cgsolve.py +100 -0
- servalcat/refine/refine.py +1162 -0
- servalcat/refine/refine_geom.py +245 -0
- servalcat/refine/refine_spa.py +400 -0
- servalcat/refine/refine_xtal.py +339 -0
- servalcat/refine/spa.py +151 -0
- servalcat/refine/xtal.py +312 -0
- servalcat/refmac/__init__.py +0 -0
- servalcat/refmac/exte.py +191 -0
- servalcat/refmac/refmac_keywords.py +660 -0
- servalcat/refmac/refmac_wrapper.py +423 -0
- servalcat/spa/__init__.py +0 -0
- servalcat/spa/fofc.py +488 -0
- servalcat/spa/fsc.py +391 -0
- servalcat/spa/localcc.py +197 -0
- servalcat/spa/realspcc_from_var.py +128 -0
- servalcat/spa/run_refmac.py +979 -0
- servalcat/spa/shift_maps.py +293 -0
- servalcat/spa/shiftback.py +137 -0
- servalcat/spa/translate.py +129 -0
- servalcat/utils/__init__.py +35 -0
- servalcat/utils/commands.py +1629 -0
- servalcat/utils/fileio.py +836 -0
- servalcat/utils/generate_operators.py +296 -0
- servalcat/utils/hkl.py +811 -0
- servalcat/utils/logger.py +140 -0
- servalcat/utils/maps.py +345 -0
- servalcat/utils/model.py +933 -0
- servalcat/utils/refmac.py +759 -0
- servalcat/utils/restraints.py +888 -0
- servalcat/utils/symmetry.py +298 -0
- servalcat/xtal/__init__.py +0 -0
- servalcat/xtal/french_wilson.py +262 -0
- servalcat/xtal/run_refmac_small.py +240 -0
- servalcat/xtal/sigmaa.py +1954 -0
- servalcat/xtal/twin.py +316 -0
- servalcat-0.4.131.dist-info/METADATA +60 -0
- servalcat-0.4.131.dist-info/RECORD +45 -0
- servalcat-0.4.131.dist-info/WHEEL +6 -0
- servalcat-0.4.131.dist-info/entry_points.txt +4 -0
- servalcat-0.4.131.dist-info/licenses/LICENSE +373 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Author: "Keitaro Yamashita, Garib N. Murshudov"
|
|
3
|
+
MRC Laboratory of Molecular Biology
|
|
4
|
+
|
|
5
|
+
This software is released under the
|
|
6
|
+
Mozilla Public License, version 2.0; see LICENSE.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import absolute_import, division, print_function, generators
|
|
9
|
+
import numpy
|
|
10
|
+
import copy
|
|
11
|
+
eps_l = 1.0e-5
|
|
12
|
+
|
|
13
|
+
def generate_all_elements(axis1, order1, axis2=None, order2=0, toler=1.0e-6, toler2=1.e-3):
|
|
14
|
+
#
|
|
15
|
+
# Generate all group elements. Output will be as a list of cyclic groups.
|
|
16
|
+
#
|
|
17
|
+
if axis2 is None: axis2 = numpy.array([0.0,0.0,1.0])
|
|
18
|
+
grp_out = []
|
|
19
|
+
order_out = []
|
|
20
|
+
axes_out = []
|
|
21
|
+
if order2 == 0:
|
|
22
|
+
grp_out = generate_cyclic(axis1, order1)
|
|
23
|
+
order_out.append(order1)
|
|
24
|
+
axes_out.append(axis1)
|
|
25
|
+
return order_out, axes_out, grp_out
|
|
26
|
+
|
|
27
|
+
grp_out = generate_cyclic(axis1,order1)
|
|
28
|
+
order_out.append(order1)
|
|
29
|
+
axes_out.append(axis1)
|
|
30
|
+
grp1 = generate_cyclic(axis2,order2)
|
|
31
|
+
grp_out = add_groups_together(grp_out,grp1,toler2)
|
|
32
|
+
order_out.append(order2)
|
|
33
|
+
axes_out.append(axis2)
|
|
34
|
+
|
|
35
|
+
grp_out_new = copy.copy(grp_out)
|
|
36
|
+
things_to_do = True
|
|
37
|
+
while things_to_do:
|
|
38
|
+
things_to_do = False
|
|
39
|
+
for i, ri in enumerate(grp_out):
|
|
40
|
+
for j, rj in enumerate(grp_out):
|
|
41
|
+
if i !=0 and j!=0 and i != j:
|
|
42
|
+
r3 = numpy.dot(ri,rj)
|
|
43
|
+
if not is_in_the_list_rotation(r3, grp_out, toler2):
|
|
44
|
+
things_to_do = True
|
|
45
|
+
order3, axis3 = find_order(r3, toler2)
|
|
46
|
+
grp3 = generate_cyclic(axis3, order3)
|
|
47
|
+
grp_out_new = add_groups_together(grp_out_new, grp3,toler2)
|
|
48
|
+
order_out.append(order3)
|
|
49
|
+
axes_out.append(axis3)
|
|
50
|
+
r3 = numpy.dot(rj, ri)
|
|
51
|
+
if not is_in_the_list_rotation(r3, grp_out, toler2):
|
|
52
|
+
things_to_do = True
|
|
53
|
+
order3, axis3 = find_order(r3, toler2)
|
|
54
|
+
grp3 = generate_cyclic(axis3,order3)
|
|
55
|
+
grp_out_new = add_groups_together(grp_out_new, grp3,toler2)
|
|
56
|
+
order_out.append(order3)
|
|
57
|
+
axes_out.append(axis3)
|
|
58
|
+
grp_out = copy.copy(grp_out_new)
|
|
59
|
+
#
|
|
60
|
+
# Filter out axes (if they are parallel to each other then select one, for the order we should take
|
|
61
|
+
# the highest order). In our case it should happen only for the group O. We may have 2 and four fold symmetries
|
|
62
|
+
# with the same axis
|
|
63
|
+
axes_out_new = []
|
|
64
|
+
order_out_new = []
|
|
65
|
+
for i, axisi in enumerate(axes_out):
|
|
66
|
+
order_cp = order_out[i]
|
|
67
|
+
for j, axisj in enumerate(axes_out):
|
|
68
|
+
if i < j:
|
|
69
|
+
cangle = numpy.dot(axisi,axisj)/(numpy.linalg.norm(axisi)*numpy.linalg.norm(axisj))
|
|
70
|
+
if numpy.abs(cangle-1.0) < toler or numpy.abs(cangle+1) < toler:
|
|
71
|
+
# same axis
|
|
72
|
+
if order_cp <= order_out[j]:
|
|
73
|
+
order_cp= 0
|
|
74
|
+
break
|
|
75
|
+
if order_cp > 0:
|
|
76
|
+
axes_out_new.append(axisi)
|
|
77
|
+
order_out_new.append(order_cp)
|
|
78
|
+
|
|
79
|
+
return order_out_new, axes_out_new, grp_out
|
|
80
|
+
# generate_all_elements()
|
|
81
|
+
|
|
82
|
+
def find_order(r, toler=1.0e-3):
|
|
83
|
+
order = 1
|
|
84
|
+
r_id = numpy.identity(3)
|
|
85
|
+
r3 = numpy.copy(r_id)
|
|
86
|
+
things_to_do = True
|
|
87
|
+
A = r_id
|
|
88
|
+
while things_to_do and order < 100:
|
|
89
|
+
things_to_do = False
|
|
90
|
+
r3 = numpy.dot(r3, r)
|
|
91
|
+
if numpy.sum(numpy.abs(r3-r_id)) > toler:
|
|
92
|
+
A = A + r3
|
|
93
|
+
things_to_do = True
|
|
94
|
+
order += 1
|
|
95
|
+
|
|
96
|
+
if order >= 100:
|
|
97
|
+
raise RuntimeError("The order of the group is too high: order > 100")
|
|
98
|
+
A = A/order
|
|
99
|
+
axis_l = find_axis(A)
|
|
100
|
+
|
|
101
|
+
return order, axis_l
|
|
102
|
+
# find_order()
|
|
103
|
+
|
|
104
|
+
def add_groups_together(grp_in, grp_add, toler=1.e-3):
|
|
105
|
+
grp_out = copy.copy(grp_in)
|
|
106
|
+
grp_out.extend(filter(lambda r: not is_in_the_list_rotation(r, grp_out, toler), grp_add))
|
|
107
|
+
#for r in grp_add:
|
|
108
|
+
# if not is_in_the_list_rotation(r, grp_out):
|
|
109
|
+
# grp_out.append(r)
|
|
110
|
+
return grp_out
|
|
111
|
+
# add_groups_together()
|
|
112
|
+
|
|
113
|
+
def generate_cyclic(axis, order):
|
|
114
|
+
#
|
|
115
|
+
# This function generates all cyclic group elements using axis and order of the group
|
|
116
|
+
if order <=0 or numpy.sum(numpy.abs(axis)) < eps_l:
|
|
117
|
+
raise RuntimeError("Either order or axis is zero. order= {} axis= {}".format(order, axis))
|
|
118
|
+
gout = []
|
|
119
|
+
id_matr = numpy.identity(3)
|
|
120
|
+
gout.append(id_matr)
|
|
121
|
+
angle = 2.0*numpy.pi/order
|
|
122
|
+
axis = axis/numpy.linalg.norm(axis)
|
|
123
|
+
exp_matr = numpy.array([[0, -axis[2], axis[1]],
|
|
124
|
+
[axis[2], 0, -axis[0]],
|
|
125
|
+
[-axis[1], axis[0], 0]])
|
|
126
|
+
axis_outer = numpy.outer(axis, axis)
|
|
127
|
+
m_int = id_matr - axis_outer
|
|
128
|
+
for i in range(order-1):
|
|
129
|
+
angle_l = angle*(i+1)
|
|
130
|
+
stheta = numpy.sin(angle_l)
|
|
131
|
+
ctheta = numpy.cos(angle_l)
|
|
132
|
+
m_l = exp_matr*stheta + m_int*ctheta +axis_outer
|
|
133
|
+
m_l = numpy.where(numpy.abs(m_l) < 1e-9, 0, m_l)
|
|
134
|
+
gout.append(m_l)
|
|
135
|
+
|
|
136
|
+
return gout
|
|
137
|
+
# generate_cyclic()
|
|
138
|
+
|
|
139
|
+
def AngleAxis2rotatin(axis, angle):
|
|
140
|
+
#
|
|
141
|
+
# Convert axis and ange to a rotation matrix. Here we use a mtrix form of the relatiionship
|
|
142
|
+
# IT may not be the moost efficient algorithm, but it should work (it is more elegant)
|
|
143
|
+
if numpy.sum(numpy.abs(axis)) < eps_l:
|
|
144
|
+
raise RuntimeError("Axis is zero. axis= {} angle= {}".format(axis, angle))
|
|
145
|
+
id_matr = numpy.identity(3)
|
|
146
|
+
axis = axis/numpy.sqrt(numpy.dot(axis,axis))
|
|
147
|
+
exp_matr = numpy.array([[0, -axis[2], axis[1]],
|
|
148
|
+
[axis[2], 0, -axis[0]],
|
|
149
|
+
[-axis[1], axis[0], 0]])
|
|
150
|
+
axis_outer = numpy.outer(axis, axis)
|
|
151
|
+
m_int = id_matr - axis_outer
|
|
152
|
+
stheta = numpy.sin(angle)
|
|
153
|
+
ctheta = numpy.cos(angle)
|
|
154
|
+
m_l = exp_matr*stheta + m_int*ctheta +axis_outer
|
|
155
|
+
m_l = numpy.where(numpy.abs(m_l) < 1e-9, 0, m_l)
|
|
156
|
+
return m_l
|
|
157
|
+
# AngleAxis2rotatin()
|
|
158
|
+
|
|
159
|
+
def Rotation2AxisAngle_cyclic(m_in, eps_l=1.0e-5):
|
|
160
|
+
#
|
|
161
|
+
# Here we assume that rotation matrix is an element of a cyclic group
|
|
162
|
+
# This routine gives the smallest angle for this cyclic group.
|
|
163
|
+
# To find axis of the rotation we use the fact that if we define
|
|
164
|
+
# A = 1/n sum_i-0^(n-1) (R^i) then this operator is a projector to the axis of rotation
|
|
165
|
+
# i.e. for Ax will be on the axis for any x. IT could be equal 0, in this case we select another x
|
|
166
|
+
A = m_in
|
|
167
|
+
m1 = m_in
|
|
168
|
+
id_matr = numpy.identity(3)
|
|
169
|
+
cycle_number = 1
|
|
170
|
+
ended = False
|
|
171
|
+
while not ended and cycle_number < 200:
|
|
172
|
+
if numpy.sum(numpy.abs(m1-id_matr)) < eps_l:
|
|
173
|
+
ended = True
|
|
174
|
+
break
|
|
175
|
+
m1 = numpy.dot(m1,m_in)
|
|
176
|
+
A = A + m1
|
|
177
|
+
cycle_number = cycle_number + 1
|
|
178
|
+
# take a ranom vector
|
|
179
|
+
if cycle_number >= 150 :
|
|
180
|
+
print("matrix ",m_in)
|
|
181
|
+
print("Try to change the tolerance: eps_l = XXX")
|
|
182
|
+
raise RuntimeError("The matrix does not seem to be producing a finite cyclic group")
|
|
183
|
+
A = A/cycle_number
|
|
184
|
+
axis = numpy.zeros(3)
|
|
185
|
+
for xin in ((0,0,1.), (0,1.,0), (1.,0,0,)):
|
|
186
|
+
axis = numpy.dot(A,xin)
|
|
187
|
+
if numpy.dot(axis,axis) > eps_l:
|
|
188
|
+
axis = axis/numpy.sqrt(numpy.dot(axis,axis))
|
|
189
|
+
if numpy.dot(axis,axis) >= eps_l:
|
|
190
|
+
break
|
|
191
|
+
|
|
192
|
+
if axis[2] < 0.0:
|
|
193
|
+
axis = -axis
|
|
194
|
+
elif axis[2] == 0.0 and axis[1] < 0.0:
|
|
195
|
+
axis = -axis
|
|
196
|
+
angle = 2.0*numpy.pi/cycle_number
|
|
197
|
+
axis[axis==0.]=0.
|
|
198
|
+
return axis,angle,cycle_number
|
|
199
|
+
# Rotation2AxisAngle_cyclic()
|
|
200
|
+
|
|
201
|
+
def Rotation2AxisAngle_general(m_in, eps_l=1.0e-5):
|
|
202
|
+
#
|
|
203
|
+
# This routine should work for any rotation matrix
|
|
204
|
+
axis = numpy.array([1, 0.0, 0.0])
|
|
205
|
+
angle = numpy.arccos(max(-1.0, numpy.min((numpy.trace(m_in)-1)/2.0)))
|
|
206
|
+
if numpy.sum(numpy.abs(m_in-numpy.transpose(m_in))) < eps_l:
|
|
207
|
+
#
|
|
208
|
+
# It is a symmetric matrix. so I and m_in form a cyclic group
|
|
209
|
+
A = (numpy.identity(3) + m_in)/2.0
|
|
210
|
+
axis = numpy.zeros(3)
|
|
211
|
+
for a in ((0,0,1.), (0,1.,0), (1.,0,0,)):
|
|
212
|
+
axis = numpy.dot(A, a)
|
|
213
|
+
if numpy.linalg.norm(axis) >= eps_l: break
|
|
214
|
+
else:
|
|
215
|
+
axis[0] = m_in[1,2] - m_in[2,1]
|
|
216
|
+
axis[1] = m_in[0,2] - m_in[2,0]
|
|
217
|
+
axis[2] = m_in[0,1] - m_in[1,0]
|
|
218
|
+
if axis[2] < 0.0:
|
|
219
|
+
axis = -axis
|
|
220
|
+
angle = 2.0*numpy.pi - angle
|
|
221
|
+
elif axis[2] < eps_l and axis[1] < 0.0:
|
|
222
|
+
axis = -axis
|
|
223
|
+
angle = 2.0*numpy.pi - angle
|
|
224
|
+
axis = axis/numpy.linalg.norm(axis)
|
|
225
|
+
axis[axis==0.]=0.
|
|
226
|
+
return axis, angle
|
|
227
|
+
# Rotation2AxisAngle_general()
|
|
228
|
+
|
|
229
|
+
def is_in_the_list_rotation(m_in, m_list, toler = 1.0e-3):
|
|
230
|
+
id_matr = numpy.identity(3)
|
|
231
|
+
return numpy.any(numpy.abs(numpy.trace(numpy.dot(numpy.transpose(m_in), m_list)-id_matr[:,None], axis1=0,axis2=2)) < toler)
|
|
232
|
+
# is_in_the_list_rotation()
|
|
233
|
+
|
|
234
|
+
def closest_rotation(m_in, m_list):
|
|
235
|
+
id_matr = numpy.identity(3)
|
|
236
|
+
return min(numpy.abs(numpy.trace(numpy.dot(numpy.transpose(m_in), m_list)-id_matr[:,None], axis1=0,axis2=2)))
|
|
237
|
+
# closest_rotation()
|
|
238
|
+
|
|
239
|
+
def find_axis(amatr):
|
|
240
|
+
#
|
|
241
|
+
# We assume that amatr is a projector. I.e. y = amatr x is on the the symmetry axis.
|
|
242
|
+
# To avoid problem of 0 vector we try several times to make sure that 0 vector is not generated
|
|
243
|
+
axis1 = numpy.zeros(3)
|
|
244
|
+
for a in ((0,0,1.), (0,1.,0), (1.,0,0,)):
|
|
245
|
+
axis1 = numpy.dot(amatr, a)
|
|
246
|
+
if numpy.linalg.norm(axis1) >= 0.001:
|
|
247
|
+
break
|
|
248
|
+
|
|
249
|
+
axis1 /= numpy.linalg.norm(axis1)
|
|
250
|
+
axis1 = numpy.around(axis1, 10)
|
|
251
|
+
axis1 /= numpy.linalg.norm(axis1)
|
|
252
|
+
# Remove annoying negative signs
|
|
253
|
+
axis1[axis1==0.]=0.
|
|
254
|
+
|
|
255
|
+
if axis1[2] < 0.0:
|
|
256
|
+
axis1 *= -1
|
|
257
|
+
elif axis1[2] == 0.0 and axis1[1] < 0.0:
|
|
258
|
+
axis1 *= -1
|
|
259
|
+
|
|
260
|
+
return axis1
|
|
261
|
+
# find_axis()
|
|
262
|
+
|
|
263
|
+
def rotate_group_elements(Rg, matrices):
|
|
264
|
+
#
|
|
265
|
+
# assume an input list and return a list of matrices
|
|
266
|
+
#
|
|
267
|
+
mm_out = []
|
|
268
|
+
Rg_t = numpy.transpose(Rg)
|
|
269
|
+
for i, mm in enumerate(matrices):
|
|
270
|
+
m1 = numpy.dot(numpy.dot(Rg_t, mm), Rg)
|
|
271
|
+
mm_out.append(m1)
|
|
272
|
+
return(mm_out)
|
|
273
|
+
# rotate_group_elements()
|
|
274
|
+
|
|
275
|
+
if __name__ == "__main__":
|
|
276
|
+
import sys
|
|
277
|
+
from servalcat.utils import symmetry
|
|
278
|
+
symbol = sys.argv[1]
|
|
279
|
+
order, axes, grp = symmetry.operators_from_symbol(symbol)
|
|
280
|
+
#print(order)
|
|
281
|
+
#print(axes)
|
|
282
|
+
#print(grp)
|
|
283
|
+
#quit()
|
|
284
|
+
rgs = symmetry.get_matrices_using_relion(symbol)
|
|
285
|
+
all_ok = True
|
|
286
|
+
max_diff = 0
|
|
287
|
+
for i, m in enumerate(grp):
|
|
288
|
+
#print("Op", i)
|
|
289
|
+
#print(m)
|
|
290
|
+
#ok = is_in_the_list_rotation(m, rgs, toler=1e-4)
|
|
291
|
+
diff = closest_rotation(m, rgs)
|
|
292
|
+
ok = diff < 1e-4
|
|
293
|
+
#print("match? {} {:.1e}".format(ok, diff))
|
|
294
|
+
if not ok: all_ok = False
|
|
295
|
+
if diff > max_diff: max_diff = diff
|
|
296
|
+
print("Final=", all_ok, max_diff)
|