servalcat 0.4.88__cp312-cp312-macosx_11_0_arm64.whl → 0.4.100__cp312-cp312-macosx_11_0_arm64.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.
Potentially problematic release.
This version of servalcat might be problematic. Click here for more details.
- servalcat/__init__.py +2 -2
- servalcat/ext.cpython-312-darwin.so +0 -0
- servalcat/refine/refine.py +125 -42
- servalcat/refine/refine_geom.py +24 -11
- servalcat/refine/refine_spa.py +55 -31
- servalcat/refine/refine_xtal.py +31 -22
- servalcat/refine/spa.py +12 -4
- servalcat/refine/xtal.py +15 -12
- servalcat/refmac/refmac_wrapper.py +3 -11
- servalcat/spa/fofc.py +9 -3
- servalcat/spa/fsc.py +8 -10
- servalcat/spa/run_refmac.py +16 -11
- servalcat/spa/translate.py +2 -2
- servalcat/utils/commands.py +154 -4
- servalcat/utils/fileio.py +15 -8
- servalcat/utils/hkl.py +63 -26
- servalcat/utils/logger.py +25 -1
- servalcat/utils/maps.py +2 -2
- servalcat/utils/model.py +22 -15
- servalcat/utils/refmac.py +1 -1
- servalcat/utils/restraints.py +27 -28
- servalcat/utils/symmetry.py +5 -5
- servalcat/xtal/french_wilson.py +7 -5
- servalcat/xtal/sigmaa.py +69 -45
- servalcat/xtal/twin.py +73 -44
- {servalcat-0.4.88.dist-info → servalcat-0.4.100.dist-info}/METADATA +4 -4
- servalcat-0.4.100.dist-info/RECORD +45 -0
- {servalcat-0.4.88.dist-info → servalcat-0.4.100.dist-info}/WHEEL +1 -1
- servalcat-0.4.88.dist-info/RECORD +0 -45
- {servalcat-0.4.88.dist-info → servalcat-0.4.100.dist-info}/entry_points.txt +0 -0
- {servalcat-0.4.88.dist-info → servalcat-0.4.100.dist-info}/licenses/LICENSE +0 -0
servalcat/refine/spa.py
CHANGED
|
@@ -38,8 +38,14 @@ class LL_SPA:
|
|
|
38
38
|
self.lab_obs = lab_obs
|
|
39
39
|
self.st = st
|
|
40
40
|
self.monlib = monlib
|
|
41
|
-
self.
|
|
41
|
+
self.d_min_max = hkldata.d_min_max()
|
|
42
42
|
self.ll = None
|
|
43
|
+
self.b_aniso = None
|
|
44
|
+
|
|
45
|
+
def refine_id(self):
|
|
46
|
+
if self.source == "electron":
|
|
47
|
+
return "ELECTRON MICROSCOPY"
|
|
48
|
+
return "NON-EM SPA" # does not happen, I guess
|
|
43
49
|
|
|
44
50
|
def update_ml_params(self):
|
|
45
51
|
# FIXME make sure D > 0
|
|
@@ -52,7 +58,7 @@ class LL_SPA:
|
|
|
52
58
|
else:
|
|
53
59
|
st = self.st
|
|
54
60
|
|
|
55
|
-
self.hkldata.df["FC"] = utils.model.calc_fc_fft(st, self.
|
|
61
|
+
self.hkldata.df["FC"] = utils.model.calc_fc_fft(st, self.d_min_max[0] - 1e-6,
|
|
56
62
|
monlib=self.monlib,
|
|
57
63
|
source=self.source,
|
|
58
64
|
mott_bethe=self.mott_bethe,
|
|
@@ -92,15 +98,17 @@ class LL_SPA:
|
|
|
92
98
|
stats = fsc.calc_fsc_all(self.hkldata, labs_fc=["FC"], lab_f=self.lab_obs)
|
|
93
99
|
fsca = fsc.fsc_average(stats.ncoeffs, stats.fsc_FC_full)
|
|
94
100
|
logger.writeln("FSCaverage = {:.4f}".format(fsca))
|
|
101
|
+
ret = {"summary": {"FSCaverage": fsca, "-LL": self.calc_target()}}
|
|
95
102
|
# XXX in fsc object, _full is misleading - it's not full in cross validation mode
|
|
96
103
|
if "D" in self.hkldata.binned_df and "S" in self.hkldata.binned_df:
|
|
97
104
|
stats[["D", "S"]] = self.hkldata.binned_df[["D", "S"]]
|
|
98
|
-
|
|
105
|
+
ret["bin_stats"] = stats
|
|
106
|
+
return ret
|
|
99
107
|
|
|
100
108
|
def calc_grad(self, atom_pos, refine_xyz, adp_mode, refine_occ, refine_h, specs):
|
|
101
109
|
dll_dab = numpy.empty_like(self.hkldata.df[self.lab_obs])
|
|
102
110
|
d2ll_dab2 = numpy.zeros(len(self.hkldata.df.index))
|
|
103
|
-
blur = utils.model.determine_blur_for_dencalc(self.st, self.
|
|
111
|
+
blur = utils.model.determine_blur_for_dencalc(self.st, self.d_min_max[0] / 3) # TODO need more work
|
|
104
112
|
logger.writeln("blur for deriv= {:.2f}".format(blur))
|
|
105
113
|
for i_bin, idxes in self.hkldata.binned():
|
|
106
114
|
D = self.hkldata.binned_df.D[i_bin]
|
servalcat/refine/xtal.py
CHANGED
|
@@ -30,7 +30,7 @@ class LL_Xtal:
|
|
|
30
30
|
self.free = free
|
|
31
31
|
self.st = st
|
|
32
32
|
self.monlib = monlib
|
|
33
|
-
self.
|
|
33
|
+
self.d_min_max = hkldata.d_min_max()
|
|
34
34
|
self.fc_labs = ["FC0"]
|
|
35
35
|
self.use_solvent = use_solvent
|
|
36
36
|
if use_solvent:
|
|
@@ -45,7 +45,7 @@ class LL_Xtal:
|
|
|
45
45
|
self.ll = None
|
|
46
46
|
self.scaling = sigmaa.LsqScale()
|
|
47
47
|
if twin:
|
|
48
|
-
self.twin_data = find_twin_domains_from_data(self.hkldata)
|
|
48
|
+
self.twin_data, _ = find_twin_domains_from_data(self.hkldata)
|
|
49
49
|
else:
|
|
50
50
|
self.twin_data = None
|
|
51
51
|
if self.twin_data:
|
|
@@ -54,6 +54,9 @@ class LL_Xtal:
|
|
|
54
54
|
logger.writeln("will use {} reflections for parameter estimation".format(self.use_in_est))
|
|
55
55
|
logger.writeln("will use {} reflections for refinement".format(self.use_in_target))
|
|
56
56
|
|
|
57
|
+
def refine_id(self):
|
|
58
|
+
return {"xray": "X-RAY", "electron": "ELECTRON", "neutron": "NEUTRON"}.get(self.source, "") + " DIFFRACTION"
|
|
59
|
+
|
|
57
60
|
def update_ml_params(self):
|
|
58
61
|
self.b_aniso = sigmaa.determine_ml_params(self.hkldata, self.is_int, self.fc_labs, self.D_labs, self.b_aniso,
|
|
59
62
|
self.centric_and_selections, use=self.use_in_est,
|
|
@@ -63,7 +66,7 @@ class LL_Xtal:
|
|
|
63
66
|
# self.centric_and_selections)
|
|
64
67
|
def update_fc(self):
|
|
65
68
|
sigmaa.update_fc(st_list=[self.st], fc_labs=self.fc_labs,
|
|
66
|
-
d_min=self.
|
|
69
|
+
d_min=self.d_min_max[0], monlib=self.monlib,
|
|
67
70
|
source=self.source, mott_bethe=self.mott_bethe,
|
|
68
71
|
hkldata=self.hkldata, twin_data=self.twin_data)
|
|
69
72
|
|
|
@@ -78,20 +81,20 @@ class LL_Xtal:
|
|
|
78
81
|
for sel in self.centric_and_selections[i_bin]])
|
|
79
82
|
mask = numpy.empty(len(self.hkldata.df.index)) * numpy.nan
|
|
80
83
|
mask[idxes] = 1 / self.hkldata.debye_waller_factors(b_cart=self.b_aniso)[idxes]**2
|
|
81
|
-
self.twin_data.est_f_true(self.hkldata.df.I * mask,
|
|
82
|
-
self.hkldata.df.SIGI * mask)
|
|
84
|
+
self.twin_data.est_f_true(self.hkldata.df.I.to_numpy() * mask,
|
|
85
|
+
self.hkldata.df.SIGI.to_numpy() * mask)
|
|
83
86
|
|
|
84
87
|
def overall_scale(self, min_b=0.1):
|
|
85
88
|
miller_array = self.twin_data.asu if self.twin_data else self.hkldata.miller_array()
|
|
86
89
|
if self.use_solvent:
|
|
87
|
-
Fmask = sigmaa.calc_Fmask(self.st, self.
|
|
90
|
+
Fmask = sigmaa.calc_Fmask(self.st, self.d_min_max[0], miller_array)
|
|
88
91
|
if self.twin_data:
|
|
89
92
|
fc_sum = self.twin_data.f_calc[:,:-1].sum(axis=1)
|
|
90
93
|
else:
|
|
91
94
|
fc_sum = self.hkldata.df[self.fc_labs[:-1]].sum(axis=1).to_numpy()
|
|
92
95
|
fc_list = [fc_sum, Fmask]
|
|
93
96
|
else:
|
|
94
|
-
if twin_data:
|
|
97
|
+
if self.twin_data:
|
|
95
98
|
fc_list = [self.twin_data.f_calc.sum(axis=1)]
|
|
96
99
|
else:
|
|
97
100
|
fc_list = [self.hkldata.df[self.fc_labs].sum(axis=1).to_numpy()]
|
|
@@ -177,7 +180,7 @@ class LL_Xtal:
|
|
|
177
180
|
return ret
|
|
178
181
|
|
|
179
182
|
def calc_grad(self, atom_pos, refine_xyz, adp_mode, refine_occ, refine_h, specs=None):
|
|
180
|
-
blur = utils.model.determine_blur_for_dencalc(self.st, self.
|
|
183
|
+
blur = utils.model.determine_blur_for_dencalc(self.st, self.d_min_max[0] / 3) # TODO need more work
|
|
181
184
|
logger.writeln("blur for deriv= {:.2f}".format(blur))
|
|
182
185
|
if self.twin_data:
|
|
183
186
|
dll_dab, d2ll_dab2 = self.twin_data.ll_der_fc0()
|
|
@@ -206,8 +209,8 @@ class LL_Xtal:
|
|
|
206
209
|
to = Io[cidxes] / sigIo[cidxes] - sigIo[cidxes] / (c+1) / k_ani[cidxes]**2 / S / epsilon
|
|
207
210
|
tf = k_ani[cidxes] * Fc_abs / numpy.sqrt(sigIo[cidxes])
|
|
208
211
|
sig1 = k_ani[cidxes]**2 * epsilon * S / sigIo[cidxes]
|
|
209
|
-
k_num = 0.5 if c == 0 else 0. # acentric:0.5, centric: 0.
|
|
210
|
-
r = ext.integ_J_ratio(k_num, k_num - 0.5, True, to, tf, sig1, c+1,
|
|
212
|
+
k_num = numpy.repeat(0.5 if c == 0 else 0., to.size) # acentric:0.5, centric: 0.
|
|
213
|
+
r = ext.integ_J_ratio(k_num, k_num - 0.5, True, to, tf, sig1, numpy.repeat(c+1, to.size),
|
|
211
214
|
integr.exp2_threshold, integr.h, integr.N, integr.ewmax)
|
|
212
215
|
r *= numpy.sqrt(sigIo[cidxes]) / k_ani[cidxes]
|
|
213
216
|
g = (2-c) * (Fc_abs - r) / epsilon / S * Ds[:,0]
|
|
@@ -232,11 +235,11 @@ class LL_Xtal:
|
|
|
232
235
|
m = numpy.tanh(X)
|
|
233
236
|
g = (Fc_abs - m * Fo) / Sigma * Ds[:,0]
|
|
234
237
|
dll_dab[cidxes] = g * expip
|
|
235
|
-
d2ll_dab2[cidxes] = (1. / Sigma - (Fo /
|
|
238
|
+
d2ll_dab2[cidxes] = (1. / Sigma - (Fo / Sigma)**2 * (1. - m**2)) * Ds[:,0]**2
|
|
236
239
|
dll_dab *= self.hkldata.debye_waller_factors(b_iso=-blur)
|
|
237
240
|
|
|
238
241
|
if self.mott_bethe:
|
|
239
|
-
d2 =
|
|
242
|
+
d2 = numpy.reciprocal(self.twin_data.s2_array) if self.twin_data else self.hkldata.d_spacings()**2
|
|
240
243
|
dll_dab *= d2 * gemmi.mott_bethe_const()
|
|
241
244
|
d2ll_dab2 *= gemmi.mott_bethe_const()**2
|
|
242
245
|
|
|
@@ -11,7 +11,6 @@ import numpy
|
|
|
11
11
|
import json
|
|
12
12
|
import os
|
|
13
13
|
import sys
|
|
14
|
-
import io
|
|
15
14
|
import tempfile
|
|
16
15
|
import subprocess
|
|
17
16
|
import argparse
|
|
@@ -126,8 +125,7 @@ def prepare_crd(st, crdout, ligand, make, monlib_path=None, h_pos="elec",
|
|
|
126
125
|
max_seq_num = max([max(res.seqid.num for res in chain) for model in st for chain in model])
|
|
127
126
|
if max_seq_num > 9999:
|
|
128
127
|
logger.writeln("Max residue number ({}) exceeds 9999. Needs workaround.".format(max_seq_num))
|
|
129
|
-
|
|
130
|
-
topo = gemmi.prepare_topology(st, monlib, warnings=sio, ignore_unknown_links=True)
|
|
128
|
+
topo = gemmi.prepare_topology(st, monlib, warnings=logger.silent(), ignore_unknown_links=True)
|
|
131
129
|
refmac_fixes.fix_before_topology(st, topo,
|
|
132
130
|
fix_microheterogeneity=False,
|
|
133
131
|
fix_resimax=True,
|
|
@@ -135,8 +133,7 @@ def prepare_crd(st, crdout, ligand, make, monlib_path=None, h_pos="elec",
|
|
|
135
133
|
|
|
136
134
|
if unre:
|
|
137
135
|
# Refmac5 does not seem to do anything to hydrogen when unre regardless of "make hydr"
|
|
138
|
-
|
|
139
|
-
topo = gemmi.prepare_topology(st, monlib, warnings=sio, ignore_unknown_links=True)
|
|
136
|
+
topo = gemmi.prepare_topology(st, monlib, warnings=logger.silent(), ignore_unknown_links=True)
|
|
140
137
|
metal_kws = []
|
|
141
138
|
else:
|
|
142
139
|
if make.get("hydr") == "a": logger.writeln("(re)generating hydrogen atoms")
|
|
@@ -194,7 +191,7 @@ def prepare_crd(st, crdout, ligand, make, monlib_path=None, h_pos="elec",
|
|
|
194
191
|
if st.name.lower() in block_names:
|
|
195
192
|
st.name = st.name + str(i)
|
|
196
193
|
doc = gemmi.prepare_refmac_crd(st, topo, monlib, h_change)
|
|
197
|
-
doc.write_file(crdout,
|
|
194
|
+
doc.write_file(crdout, options=gemmi.cif.Style.NoBlankLines)
|
|
198
195
|
logger.writeln("crd file written: {}".format(crdout))
|
|
199
196
|
return refmac_fixes, [x+"\n" for x in metal_kws]
|
|
200
197
|
# prepare_crd()
|
|
@@ -276,11 +273,6 @@ def modify_output(pdbout, cifout, fixes, hout, cispeps, keep_original_output=Fal
|
|
|
276
273
|
logger.writeln("This structure cannot be saved as an official PDB format. Using hybrid-36. Header part may be inaccurate.")
|
|
277
274
|
if not hout:
|
|
278
275
|
st.remove_hydrogens() # remove hydrogen from pdb, while kept in mmcif
|
|
279
|
-
# Use short name in pdb
|
|
280
|
-
st.shorten_ccd_codes()
|
|
281
|
-
if st.shortened_ccd_codes:
|
|
282
|
-
msg = " ".join("{}->{}".format(o,n) for o,n in st.shortened_ccd_codes)
|
|
283
|
-
logger.writeln("Using shortened residue names in the output pdb file: " + msg)
|
|
284
276
|
os.rename(pdbout, pdbout + suffix)
|
|
285
277
|
utils.fileio.write_pdb(st, pdbout)
|
|
286
278
|
if not keep_original_output:
|
servalcat/spa/fofc.py
CHANGED
|
@@ -44,9 +44,11 @@ def add_arguments(parser):
|
|
|
44
44
|
parser.add_argument("--monlib",
|
|
45
45
|
help="Monomer library path. Default: $CLIBD_MON")
|
|
46
46
|
parser.add_argument("--omit_proton", action='store_true',
|
|
47
|
-
help="Omit proton from model in map calculation")
|
|
47
|
+
#help="Omit hydrogen proton (leaving electrons) from model in map calculation")
|
|
48
|
+
help=argparse.SUPPRESS)
|
|
48
49
|
parser.add_argument("--omit_h_electron", action='store_true',
|
|
49
|
-
help="Omit hydrogen electrons from model in map calculation")
|
|
50
|
+
#help="Omit hydrogen electrons (leaving protons) from model in map calculation")
|
|
51
|
+
help=argparse.SUPPRESS)
|
|
50
52
|
parser.add_argument("--source", choices=["electron", "xray", "neutron"], default="electron")
|
|
51
53
|
parser.add_argument('-o','--output_prefix', default="diffmap",
|
|
52
54
|
help='output file name prefix (default: %(default)s)')
|
|
@@ -464,7 +466,11 @@ def main(args):
|
|
|
464
466
|
logger.writeln("coot --script " + py_out)
|
|
465
467
|
if mask is not None:
|
|
466
468
|
logger.writeln("\nWant to list Fo-Fc map peaks? Try:")
|
|
467
|
-
|
|
469
|
+
if omit_h_electron:
|
|
470
|
+
logger.writeln("servalcat util map_peaks --map {}_normalized_fofc_flipsign.mrc --model {} --abs_level 4.0".format(args.output_prefix, args.model))
|
|
471
|
+
else:
|
|
472
|
+
logger.writeln("servalcat util map_peaks --map {}_normalized_fofc.mrc --model {} --abs_level 4.0".format(args.output_prefix, args.model))
|
|
473
|
+
|
|
468
474
|
# main()
|
|
469
475
|
|
|
470
476
|
if __name__ == "__main__":
|
servalcat/spa/fsc.py
CHANGED
|
@@ -20,13 +20,14 @@ def add_arguments(parser):
|
|
|
20
20
|
|
|
21
21
|
parser.add_argument('--model',
|
|
22
22
|
help="")
|
|
23
|
-
parser.
|
|
23
|
+
group = parser.add_mutually_exclusive_group(required=True)
|
|
24
|
+
group.add_argument('--map',
|
|
24
25
|
help='Input map file(s)')
|
|
25
|
-
|
|
26
|
+
group.add_argument("--halfmaps", nargs=2)
|
|
27
|
+
group.add_argument('--mtz',
|
|
26
28
|
help='Input mtz file.')
|
|
27
29
|
parser.add_argument('--labin', nargs=2,
|
|
28
30
|
help='label (F and PHI) for mtz')
|
|
29
|
-
parser.add_argument("--halfmaps", nargs=2)
|
|
30
31
|
parser.add_argument('--pixel_size', type=float,
|
|
31
32
|
help='Override pixel size (A)')
|
|
32
33
|
parser.add_argument('--mask', help='Mask file')
|
|
@@ -68,13 +69,10 @@ def write_loggraph(stats, labs_fc, log_out):
|
|
|
68
69
|
model_labs1 = [l for l in stats if any(l.startswith("fsc_"+fc) for fc in labs_fc)]
|
|
69
70
|
model_labs2 = [l for l in stats if any(l.startswith(("cc_"+fc, "mcos_"+fc)) for fc in labs_fc)]
|
|
70
71
|
power_labs = [l for l in stats if l.startswith("power_")]
|
|
71
|
-
half_labs1 = ["fsc_half_unmasked", "fsc_half_masked", "fsc_half_masked_rand", "fsc_half_masked_corrected"]
|
|
72
|
-
half_labs2 = ["cc_half", "mcos_half"]
|
|
73
|
-
if not
|
|
74
|
-
|
|
75
|
-
half_labs1 = ["fsc_half"]
|
|
76
|
-
else:
|
|
77
|
-
half_labs1 = []
|
|
72
|
+
half_labs1 = [l for l in ("fsc_half_unmasked", "fsc_half_masked", "fsc_half_masked_rand", "fsc_half_masked_corrected") if l in stats]
|
|
73
|
+
half_labs2 = [l for l in ("cc_half", "mcos_half") if l in stats]
|
|
74
|
+
if not half_labs1 and "fsc_half" in stats:
|
|
75
|
+
half_labs1 = ["fsc_half"]
|
|
78
76
|
|
|
79
77
|
stats2 = stats.copy()
|
|
80
78
|
stats2.insert(0, "bin", stats.index)
|
servalcat/spa/run_refmac.py
CHANGED
|
@@ -10,7 +10,6 @@ import gemmi
|
|
|
10
10
|
import numpy
|
|
11
11
|
import json
|
|
12
12
|
import os
|
|
13
|
-
import io
|
|
14
13
|
import shutil
|
|
15
14
|
import argparse
|
|
16
15
|
from servalcat.utils import logger
|
|
@@ -58,7 +57,7 @@ def add_arguments(parser):
|
|
|
58
57
|
help='Sharpening or blurring B')
|
|
59
58
|
utils.symmetry.add_symmetry_args(parser) # add --pg etc
|
|
60
59
|
parser.add_argument('--contacting_only', action="store_true", help="Filter out non-contacting NCS")
|
|
61
|
-
parser.add_argument('--ignore_symmetry',
|
|
60
|
+
parser.add_argument('--ignore_symmetry', action='store_true',
|
|
62
61
|
help='Ignore symmetry information (MTRIX/_struct_ncs_oper) in the model file')
|
|
63
62
|
parser.add_argument('--find_links', action='store_true',
|
|
64
63
|
help='Automatically add links')
|
|
@@ -150,6 +149,7 @@ def calc_fsc(st, output_prefix, maps, d_min, mask, mask_radius, soft_edge, b_bef
|
|
|
150
149
|
assert st_sr is None
|
|
151
150
|
|
|
152
151
|
logger.writeln("Calculating map-model FSC..")
|
|
152
|
+
ret = {"summary": {}}
|
|
153
153
|
|
|
154
154
|
if d_min_fsc is None:
|
|
155
155
|
d_min_fsc = utils.maps.nyquist_resolution(maps[0][0])
|
|
@@ -220,12 +220,17 @@ def calc_fsc(st, output_prefix, maps, d_min, mask, mask_radius, soft_edge, b_bef
|
|
|
220
220
|
s.drop(columns=[x for x in s if x.startswith("fsc_FC") and x.endswith(("half1","half2"))], inplace=True)
|
|
221
221
|
|
|
222
222
|
# FSCaverages
|
|
223
|
+
ret["summary"]["d_min"] = d_min
|
|
224
|
+
ret["summary"]["FSCaverage"] = spa.fsc.fsc_average(stats2.ncoeffs, stats2.fsc_model)
|
|
225
|
+
if cross_validation:
|
|
226
|
+
ret["summary"]["FSCaverage_half1"] = spa.fsc.fsc_average(stats2.ncoeffs, stats2.fsc_model_half1)
|
|
227
|
+
ret["summary"]["FSCaverage_half2"] = spa.fsc.fsc_average(stats2.ncoeffs, stats2.fsc_model_half2)
|
|
223
228
|
fscavg_text = "Map-model FSCaverages (at {:.2f} A):\n".format(d_min)
|
|
224
|
-
fscavg_text += " FSCaverage(full) = {: .4f}\n".format(
|
|
229
|
+
fscavg_text += " FSCaverage(full) = {: .4f}\n".format(ret["summary"]["FSCaverage"])
|
|
225
230
|
if cross_validation:
|
|
226
231
|
fscavg_text += "Cross-validated map-model FSCaverages:\n"
|
|
227
|
-
fscavg_text += " FSCaverage(half1)= {: .4f}\n".format(
|
|
228
|
-
fscavg_text += " FSCaverage(half2)= {: .4f}\n".format(
|
|
232
|
+
fscavg_text += " FSCaverage(half1)= {: .4f}\n".format(ret["summary"]["FSCaverage_half1"])
|
|
233
|
+
fscavg_text += " FSCaverage(half2)= {: .4f}\n".format(ret["summary"]["FSCaverage_half2"])
|
|
229
234
|
|
|
230
235
|
# for loggraph
|
|
231
236
|
fsc_logfile = "{}_fsc.log".format(output_prefix)
|
|
@@ -269,8 +274,8 @@ def calc_fsc(st, output_prefix, maps, d_min, mask, mask_radius, soft_edge, b_bef
|
|
|
269
274
|
json.dump(stats.to_dict("records"),
|
|
270
275
|
open("{}_fsc.json".format(output_prefix), "w"),
|
|
271
276
|
indent=True)
|
|
272
|
-
|
|
273
|
-
return fscavg_text
|
|
277
|
+
ret["binned"] = stats2.to_dict(orient="records")
|
|
278
|
+
return fscavg_text, ret
|
|
274
279
|
# calc_fsc()
|
|
275
280
|
|
|
276
281
|
def calc_fofc(st, st_expanded, maps, monlib, model_format, args, diffmap_prefix="diffmap"):
|
|
@@ -462,7 +467,7 @@ def process_input(st, maps, resolution, monlib, mask_in, args,
|
|
|
462
467
|
unit_cell = maps[0][0].unit_cell
|
|
463
468
|
spacegroup = gemmi.SpaceGroup(1)
|
|
464
469
|
start_xyz = numpy.array(maps[0][0].get_position(*grid_start).tolist())
|
|
465
|
-
A =
|
|
470
|
+
A = unit_cell.orth.mat.array
|
|
466
471
|
center = numpy.sum(A, axis=1) / 2 #+ start_xyz
|
|
467
472
|
|
|
468
473
|
# Create mask
|
|
@@ -593,7 +598,7 @@ def process_input(st, maps, resolution, monlib, mask_in, args,
|
|
|
593
598
|
topo, metal_kws = utils.restraints.prepare_topology(st, monlib, h_change=h_change, raise_error=False)
|
|
594
599
|
args.keywords = metal_kws + args.keywords
|
|
595
600
|
elif not no_refmac_fix:
|
|
596
|
-
topo = gemmi.prepare_topology(st, monlib, warnings=
|
|
601
|
+
topo = gemmi.prepare_topology(st, monlib, warnings=logger.silent(), ignore_unknown_links=True)
|
|
597
602
|
else:
|
|
598
603
|
topo = None # not used
|
|
599
604
|
if not no_refmac_fix:
|
|
@@ -618,7 +623,7 @@ def process_input(st, maps, resolution, monlib, mask_in, args,
|
|
|
618
623
|
args.keywords.append("make cr prepared")
|
|
619
624
|
gemmi.setup_for_crd(st)
|
|
620
625
|
doc = gemmi.prepare_refmac_crd(st, topo, monlib, h_change)
|
|
621
|
-
doc.write_file(crdout,
|
|
626
|
+
doc.write_file(crdout, options=gemmi.cif.Style.NoBlankLines)
|
|
622
627
|
logger.writeln("crd file written: {}".format(crdout))
|
|
623
628
|
|
|
624
629
|
hkldata = utils.maps.mask_and_fft_maps(maps, resolution, None, with_000=False)
|
|
@@ -955,7 +960,7 @@ def main(args):
|
|
|
955
960
|
monlib=monlib, cross_validation=args.cross_validation,
|
|
956
961
|
blur=args.blur,
|
|
957
962
|
d_min_fsc=args.fsc_resolution,
|
|
958
|
-
cross_validation_method=args.cross_validation_method, st_sr=st_sr_expanded)
|
|
963
|
+
cross_validation_method=args.cross_validation_method, st_sr=st_sr_expanded)[0]
|
|
959
964
|
|
|
960
965
|
# Calc Fo-Fc (and updated) maps
|
|
961
966
|
calc_fofc(st, st_expanded, maps, monlib, model_format, args)
|
servalcat/spa/translate.py
CHANGED
|
@@ -60,9 +60,9 @@ def find_peak(tf_map, ini_pos):
|
|
|
60
60
|
|
|
61
61
|
x = tf_map.unit_cell.fractionalize(ini_pos)
|
|
62
62
|
logger.writeln(" x0: [{}, {}, {}]".format(*x.tolist()))
|
|
63
|
-
logger.writeln(" f0: {}".format(-tf_map.
|
|
63
|
+
logger.writeln(" f0: {}".format(-tf_map.interpolate_value(x, order=3)))
|
|
64
64
|
|
|
65
|
-
res = scipy.optimize.minimize(fun=lambda x:-tf_map.
|
|
65
|
+
res = scipy.optimize.minimize(fun=lambda x:-tf_map.interpolate_value(gemmi.Fractional(*x), order=3),
|
|
66
66
|
x0=x.tolist(),
|
|
67
67
|
jac=lambda x:-numpy.array(tf_map.tricubic_interpolation_der(gemmi.Fractional(*x))[1:]))
|
|
68
68
|
logger.writeln(str(res))
|
servalcat/utils/commands.py
CHANGED
|
@@ -185,6 +185,17 @@ def add_arguments(p):
|
|
|
185
185
|
parser.add_argument('-o', '--output_prefix',
|
|
186
186
|
help="default: taken from input file")
|
|
187
187
|
|
|
188
|
+
# conf
|
|
189
|
+
parser = subparsers.add_parser("conf", description = 'Compare conformations')
|
|
190
|
+
parser.add_argument('models', nargs="+")
|
|
191
|
+
parser.add_argument("--min_diff", type=float, default=60.)
|
|
192
|
+
parser.add_argument('--ligand', nargs="*", action="append")
|
|
193
|
+
parser.add_argument("--monlib",
|
|
194
|
+
help="Monomer library path. Default: $CLIBD_MON")
|
|
195
|
+
parser.add_argument("--same_chain", action='store_true', help="Only between same chains (more than one file)")
|
|
196
|
+
parser.add_argument('-o', '--output_prefix', default="conf",
|
|
197
|
+
help="")
|
|
198
|
+
|
|
188
199
|
# adp
|
|
189
200
|
parser = subparsers.add_parser("adp", description = 'ADP analysis')
|
|
190
201
|
parser.add_argument('model')
|
|
@@ -281,6 +292,9 @@ def add_arguments(p):
|
|
|
281
292
|
parser = subparsers.add_parser("seq", description = 'Print/align model sequence')
|
|
282
293
|
parser.add_argument("--model", required=True)
|
|
283
294
|
parser.add_argument('--seq', nargs="*", action="append", help="Sequence file(s)")
|
|
295
|
+
parser.add_argument('--scoring', nargs=6, type=int, default=(1, 0, -1, -1, 0, -1),
|
|
296
|
+
metavar=("match", "mismatch", "gapo", "gape", "good_gapo", "bad_gapo"),
|
|
297
|
+
help="scoring function. default: %(default)s")
|
|
284
298
|
|
|
285
299
|
# dnarna
|
|
286
300
|
parser = subparsers.add_parser("dnarna", description = 'DNA to RNA or RNA to DNA model conversion')
|
|
@@ -919,6 +933,135 @@ def geometry(args):
|
|
|
919
933
|
fileio.write_model(st, file_name="{}_per_atom_score{}".format(args.output_prefix, model_format))
|
|
920
934
|
# geometry()
|
|
921
935
|
|
|
936
|
+
def compare_conf(args):
|
|
937
|
+
def angle_abs_diff(a, b, full=360.):
|
|
938
|
+
# from gemmi/math.hpp
|
|
939
|
+
d = abs(a - b)
|
|
940
|
+
if d > full:
|
|
941
|
+
d -= numpy.floor(d / full) * full
|
|
942
|
+
return min(d, full - d)
|
|
943
|
+
# angle_abs_diff()
|
|
944
|
+
|
|
945
|
+
if args.ligand: args.ligand = sum(args.ligand, [])
|
|
946
|
+
st = None
|
|
947
|
+
for i, f in enumerate(args.models):
|
|
948
|
+
tmp = fileio.read_structure(f)
|
|
949
|
+
if len(args.models) > 1:
|
|
950
|
+
for chain in tmp[0]:
|
|
951
|
+
chain.name = f"{i+1}_{chain.name}"
|
|
952
|
+
if i == 0:
|
|
953
|
+
st = tmp
|
|
954
|
+
else:
|
|
955
|
+
for chain in tmp[0]:
|
|
956
|
+
st[0].add_chain(chain)
|
|
957
|
+
try:
|
|
958
|
+
monlib = restraints.load_monomer_library(st, monomer_dir=args.monlib, cif_files=args.ligand,
|
|
959
|
+
stop_for_unknowns=True)
|
|
960
|
+
except RuntimeError as e:
|
|
961
|
+
raise SystemExit(f"Error: {e}")
|
|
962
|
+
|
|
963
|
+
model.setup_entities(st, clear=True, force_subchain_names=True, overwrite_entity_type=True)
|
|
964
|
+
try:
|
|
965
|
+
topo, _ = restraints.prepare_topology(st, monlib, h_change=gemmi.HydrogenChange.NoChange,
|
|
966
|
+
check_hydrogen=False)
|
|
967
|
+
except RuntimeError as e:
|
|
968
|
+
raise SystemExit(f"Error: {e}")
|
|
969
|
+
ncslist = restraints.prepare_ncs_restraints(st)
|
|
970
|
+
lookup = {x.atom: x for x in st[0].all()}
|
|
971
|
+
ptypes = {x.name: x.polymer_type for x in st.entities}
|
|
972
|
+
resn_lookup = {(chain.name, res.seqid): res.name for chain in st[0] for res in chain}
|
|
973
|
+
confs = {}
|
|
974
|
+
for t in topo.torsions:
|
|
975
|
+
cra = lookup[t.atoms[0]]
|
|
976
|
+
ptype = ptypes[cra.residue.entity_id]
|
|
977
|
+
is_peptide = ptype in (gemmi.PolymerType.PeptideL, gemmi.PolymerType.PeptideD)
|
|
978
|
+
is_peptide_tors = t.restr.label.startswith("chi") or t.restr.label in ("omega", "phi", "psi")
|
|
979
|
+
is_na = ptype in (gemmi.PolymerType.Dna, gemmi.PolymerType.Rna, gemmi.PolymerType.DnaRnaHybrid)
|
|
980
|
+
is_na_tors = t.restr.label in ("C2e-chi", "alpha", "beta", "gamma", "C2e-nyu0", "epsilon", "zeta")
|
|
981
|
+
if (is_peptide and is_peptide_tors) or (is_na and is_na_tors):
|
|
982
|
+
confs.setdefault(cra.chain.name, {}).setdefault(cra.residue.seqid, {})[t.restr.label] = numpy.rad2deg(t.calculate())
|
|
983
|
+
fulls = {("ARG", "chi5"): 180., ("TYR", "chi2"): 180., ("PHE", "chi2"): 180., ("ASP", "chi2"): 180., ("GLU", "chi3"): 180.}
|
|
984
|
+
ret = []
|
|
985
|
+
for_coot = []
|
|
986
|
+
for ncs in ncslist.ncss:
|
|
987
|
+
c1, c2 = ncs.chains
|
|
988
|
+
if args.same_chain and len(args.models) > 1 and c1[c1.index("_"):] != c2[c2.index("_"):]:
|
|
989
|
+
continue
|
|
990
|
+
for s1, s2 in ncs.seqids:
|
|
991
|
+
if c1 in confs and s1 in confs[c1] and c2 in confs and s2 in confs[c2]:
|
|
992
|
+
conf1, conf2 = confs[c1][s1], confs[c2][s2]
|
|
993
|
+
resn = resn_lookup[(c1, s1)]
|
|
994
|
+
for t in conf1:
|
|
995
|
+
if t in conf2:
|
|
996
|
+
d = angle_abs_diff(conf1[t], conf2[t], fulls.get((resn, t), 360.))
|
|
997
|
+
ret.append((c1, s1, c2, s2, resn, t, conf1[t], conf2[t], d))
|
|
998
|
+
if d > args.min_diff:
|
|
999
|
+
for_coot.append((c1, s1.num, c2, s2.num, resn, t, d))
|
|
1000
|
+
df = pandas.DataFrame(ret, columns=["chain_1", "seq_1", "chain_2", "seq_2", "resn", "label", "conf_1", "conf_2", "diff"])
|
|
1001
|
+
df.sort_values("diff", ascending=False, inplace=True)
|
|
1002
|
+
logger.writeln(f"\nList of torsion angle differences (>{args.min_diff})")
|
|
1003
|
+
logger.writeln(df[df["diff"] > args.min_diff].to_string(index=False))
|
|
1004
|
+
|
|
1005
|
+
for_coot.sort(key=lambda x:-x[-1])
|
|
1006
|
+
coot_out = args.output_prefix + "_coot.py"
|
|
1007
|
+
with open(coot_out, "w") as ofs:
|
|
1008
|
+
# https://python-gtk-3-tutorial.readthedocs.io/en/latest/treeview.html
|
|
1009
|
+
ofs.write("""\
|
|
1010
|
+
from __future__ import absolute_import, division, print_function
|
|
1011
|
+
import re
|
|
1012
|
+
import gtk
|
|
1013
|
+
class coot_serval_conf_list:
|
|
1014
|
+
def __init__(self):
|
|
1015
|
+
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
|
1016
|
+
window.set_title("Different conformations (Servalcat)")
|
|
1017
|
+
window.set_default_size(600, 600)
|
|
1018
|
+
scrolled_win = gtk.ScrolledWindow()
|
|
1019
|
+
scrolled_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
|
|
1020
|
+
vbox = gtk.VBox(False, 2)
|
|
1021
|
+
self.liststore = gtk.ListStore(str, int, str, int, str, str, float)
|
|
1022
|
+
self.filter = self.liststore.filter_new()
|
|
1023
|
+
self.treeview = gtk.TreeView(model=self.filter)
|
|
1024
|
+
for i, column_title in enumerate(["chain_1", "seq_1", "chain_2", "seq_2", "resn", "label", "diff"]):
|
|
1025
|
+
renderer = gtk.CellRendererText()
|
|
1026
|
+
column = gtk.TreeViewColumn(column_title, renderer, text=i)
|
|
1027
|
+
self.treeview.append_column(column)
|
|
1028
|
+
self.data = {}
|
|
1029
|
+
self.add_data()
|
|
1030
|
+
scrolled_win.add_with_viewport(self.treeview) # add?
|
|
1031
|
+
vbox.pack_start(scrolled_win, True, True, 0)
|
|
1032
|
+
window.add(vbox)
|
|
1033
|
+
window.show_all()
|
|
1034
|
+
self.treeview.connect("row-activated", self.on_row_activated)
|
|
1035
|
+
|
|
1036
|
+
def on_row_activated(self, treeview, path, column):
|
|
1037
|
+
assert len(path) == 1
|
|
1038
|
+
col_idx = [i for i, c in enumerate(treeview.get_columns()) if column == c][0]
|
|
1039
|
+
row = self.liststore[path[0]]
|
|
1040
|
+
if col_idx < 2:
|
|
1041
|
+
chain, resi = row[0], row[1]
|
|
1042
|
+
elif col_idx < 4:
|
|
1043
|
+
chain, resi = row[2], row[3]
|
|
1044
|
+
else:
|
|
1045
|
+
return
|
|
1046
|
+
if re.search("^[0-9]+_[0-9A-Za-z]", chain):
|
|
1047
|
+
chain = chain[chain.index("_")+1:]
|
|
1048
|
+
imol = active_atom_spec()[1][0]
|
|
1049
|
+
for name in (" CA ", " C1'"):
|
|
1050
|
+
a = get_atom(imol, chain, resi, "", name)
|
|
1051
|
+
if a:
|
|
1052
|
+
set_rotation_center(*a[2])
|
|
1053
|
+
break
|
|
1054
|
+
|
|
1055
|
+
def add_data(self):
|
|
1056
|
+
for i, d in enumerate(self.data):
|
|
1057
|
+
self.liststore.append(d)
|
|
1058
|
+
|
|
1059
|
+
gui = coot_serval_conf_list()
|
|
1060
|
+
""".format(for_coot))
|
|
1061
|
+
logger.writeln("\nRun:")
|
|
1062
|
+
logger.writeln(f"coot --script {coot_out}")
|
|
1063
|
+
# compare_conf()
|
|
1064
|
+
|
|
922
1065
|
def adp_stats(args):
|
|
923
1066
|
if not args.output_prefix: args.output_prefix = fileio.splitext(os.path.basename(args.model))[0] + "_adp"
|
|
924
1067
|
st = fileio.read_structure(args.model)
|
|
@@ -1242,6 +1385,9 @@ def seq(args):
|
|
|
1242
1385
|
for sf in args.seq:
|
|
1243
1386
|
seqs.extend(fileio.read_sequence_file(sf))
|
|
1244
1387
|
|
|
1388
|
+
sc = gemmi.AlignmentScoring()
|
|
1389
|
+
sc.match, sc.mismatch, sc.gapo, sc.gape, sc.good_gapo, sc.bad_gapo = args.scoring
|
|
1390
|
+
|
|
1245
1391
|
st = fileio.read_structure(args.model) # TODO option to (or not to) expand NCS
|
|
1246
1392
|
model.setup_entities(st, clear=True, force_subchain_names=True, overwrite_entity_type=True)
|
|
1247
1393
|
for chain in st[0]:
|
|
@@ -1257,17 +1403,20 @@ def seq(args):
|
|
|
1257
1403
|
gemmi.PolymerType.Rna: gemmi.ResidueKind.RNA}.get(p_type, gemmi.ResidueKind.AA)
|
|
1258
1404
|
s = [gemmi.expand_one_letter(x, kind) for x in seq]
|
|
1259
1405
|
if None in s: continue
|
|
1260
|
-
|
|
1406
|
+
#als = [gemmi.align_sequence_to_polymer(s, p, p_type, gemmi.AlignmentScoring(x)) for x in ("s", "p")]
|
|
1407
|
+
#results.append([name, max(als, key=lambda x: x.match_count), seq])
|
|
1408
|
+
results.append([name, gemmi.align_sequence_to_polymer(s, p, p_type, sc), seq])
|
|
1261
1409
|
|
|
1262
1410
|
if results:
|
|
1263
1411
|
logger.writeln("Chain: {}".format(chain.name))
|
|
1264
1412
|
logger.writeln(" polymer type: {}".format(str(p_type).replace("PolymerType.", "")))
|
|
1265
|
-
name, al, s1 = max(results, key=lambda x: x[1].score)
|
|
1413
|
+
name, al, s1 = max(results, key=lambda x: (x[1].match_count, x[1].score))
|
|
1266
1414
|
logger.writeln(" match: {}".format(name))
|
|
1415
|
+
logger.writeln(" aligned: {}".format(al.match_count))
|
|
1267
1416
|
logger.writeln(" score: {}".format(al.score))
|
|
1268
1417
|
p1, p2 = al.add_gaps(s1, 1), al.add_gaps(p_seq, 2)
|
|
1269
|
-
unkseq = [x.start() for x in re.finditer("\-", p1)]
|
|
1270
|
-
mismatches = [x.start() for x in re.finditer("\.", al.match_string)]
|
|
1418
|
+
unkseq = [x.start() for x in re.finditer(r"\-", p1)]
|
|
1419
|
+
mismatches = [x.start() for x in re.finditer(r"\.", al.match_string)]
|
|
1271
1420
|
if mismatches or unkseq:
|
|
1272
1421
|
idxes = {x.start(): i for i, x in enumerate(re.finditer("[^-]", p2))}
|
|
1273
1422
|
seqnums = [str(x.seqid) for x in p]
|
|
@@ -1371,6 +1520,7 @@ def main(args):
|
|
|
1371
1520
|
merge_models=merge_models,
|
|
1372
1521
|
merge_dicts=merge_dicts,
|
|
1373
1522
|
geom=geometry,
|
|
1523
|
+
conf=compare_conf,
|
|
1374
1524
|
adp=adp_stats,
|
|
1375
1525
|
power=show_power,
|
|
1376
1526
|
fcalc=fcalc,
|
servalcat/utils/fileio.py
CHANGED
|
@@ -17,7 +17,6 @@ import re
|
|
|
17
17
|
import subprocess
|
|
18
18
|
import gemmi
|
|
19
19
|
import numpy
|
|
20
|
-
import numpy.lib.recfunctions
|
|
21
20
|
import gzip
|
|
22
21
|
|
|
23
22
|
def splitext(path):
|
|
@@ -83,10 +82,12 @@ def write_mmcif(st, cif_out, cif_ref=None):
|
|
|
83
82
|
groups.scale = True
|
|
84
83
|
groups.assembly = True
|
|
85
84
|
groups.entity = True
|
|
85
|
+
groups.entity_poly = True
|
|
86
86
|
groups.entity_poly_seq = True
|
|
87
87
|
groups.cis = True
|
|
88
88
|
groups.conn = True
|
|
89
89
|
groups.software = True
|
|
90
|
+
groups.auth_all = True
|
|
90
91
|
# FIXME is this all?
|
|
91
92
|
try:
|
|
92
93
|
doc = read_cif_safe(cif_ref)
|
|
@@ -107,23 +108,27 @@ def write_mmcif(st, cif_out, cif_ref=None):
|
|
|
107
108
|
block.find_mmcif_category("_atom_sites.").erase()
|
|
108
109
|
st_new.update_mmcif_block(block, groups)
|
|
109
110
|
if "_entry.id" in st_new.info: st_new.info["_entry.id"] = st_new.info["_entry.id"][:78]
|
|
110
|
-
doc.write_file(cif_out,
|
|
111
|
+
doc.write_file(cif_out, options=gemmi.cif.Style.Aligned)
|
|
111
112
|
else:
|
|
112
113
|
st_new.name = st_new.name[:78] # this will become _entry.id
|
|
113
114
|
if "_entry.id" in st_new.info: st_new.info["_entry.id"] = st_new.info["_entry.id"][:78]
|
|
114
|
-
groups = gemmi.MmcifOutputGroups(True)
|
|
115
|
+
groups = gemmi.MmcifOutputGroups(True, auth_all=True)
|
|
115
116
|
doc = gemmi.cif.Document()
|
|
116
117
|
block = doc.add_new_block("new")
|
|
117
118
|
st_new.update_mmcif_block(block, groups)
|
|
118
|
-
doc.write_file(cif_out,
|
|
119
|
+
doc.write_file(cif_out, options=gemmi.cif.Style.Aligned)
|
|
119
120
|
# write_mmcif()
|
|
120
121
|
|
|
121
122
|
def write_pdb(st, pdb_out):
|
|
122
123
|
logger.writeln("Writing PDB file: {}".format(pdb_out))
|
|
124
|
+
st = st.clone()
|
|
123
125
|
chain_id_lens = [len(x) for x in model.all_chain_ids(st)]
|
|
124
126
|
if chain_id_lens and max(chain_id_lens) > 2:
|
|
125
|
-
st = st.clone()
|
|
126
127
|
st.shorten_chain_names()
|
|
128
|
+
st.shorten_ccd_codes()
|
|
129
|
+
if st.shortened_ccd_codes:
|
|
130
|
+
msg = " ".join("{}->{}".format(o,n) for o,n in st.shortened_ccd_codes)
|
|
131
|
+
logger.writeln(" Using shortened residue names in the output pdb file: " + msg)
|
|
127
132
|
st.write_pdb(pdb_out, use_linkr=True)
|
|
128
133
|
# write_pdb()
|
|
129
134
|
|
|
@@ -339,6 +344,8 @@ def read_structure(xyz_in, assign_het_flags=True, merge_chain_parts=True):
|
|
|
339
344
|
if st is None:
|
|
340
345
|
logger.writeln("Reading chemical component file: {}".format(xyz_in))
|
|
341
346
|
st = gemmi.make_structure_from_chemcomp_block(block)
|
|
347
|
+
for i in range(len(st)-1):
|
|
348
|
+
del st[1]
|
|
342
349
|
elif spext[1].lower() in (".ins", ".res"):
|
|
343
350
|
logger.writeln("Reading SHELX ins/res file: {}".format(xyz_in))
|
|
344
351
|
st = model.cx_to_mx(read_shelx_ins(ins_in=xyz_in)[0])
|
|
@@ -456,7 +463,7 @@ def merge_ligand_cif(cifs_in, cif_out):
|
|
|
456
463
|
if b.name not in list_names:
|
|
457
464
|
doc.add_copied_block(b)
|
|
458
465
|
|
|
459
|
-
doc.write_file(cif_out,
|
|
466
|
+
doc.write_file(cif_out, options=gemmi.cif.Style.Aligned)
|
|
460
467
|
# merge_ligand_cif()
|
|
461
468
|
|
|
462
469
|
def read_shelx_ins(ins_in=None, lines_in=None, ignore_q_peaks=True): # TODO support gz?
|
|
@@ -571,7 +578,7 @@ def read_shelx_ins(ins_in=None, lines_in=None, ignore_q_peaks=True): # TODO supp
|
|
|
571
578
|
symms.extend([x*gemmi.Op("-x,-y,-z") for x in symms])
|
|
572
579
|
|
|
573
580
|
ss.symops = [op.triplet() for op in set(symms)]
|
|
574
|
-
ss.
|
|
581
|
+
ss.determine_and_set_spacegroup("s")
|
|
575
582
|
# in case of non-regular setting, gemmi.SpaceGroup cannot be constructed anyway.
|
|
576
583
|
if ss.spacegroup is None:
|
|
577
584
|
raise RuntimeError("Cannot construct space group from symbols: {}".format(ss.symops))
|
|
@@ -598,7 +605,7 @@ def read_shelx_hkl(cell, sg, hklf, file_in=None, lines_in=None):
|
|
|
598
605
|
# wavelength = l[32:40]
|
|
599
606
|
|
|
600
607
|
ints = gemmi.Intensities()
|
|
601
|
-
ints.set_data(cell, sg, hkls, vals, sigs)
|
|
608
|
+
ints.set_data(cell, sg, numpy.asarray(hkls), numpy.asarray(vals), numpy.asarray(sigs))
|
|
602
609
|
ints.merge_in_place(gemmi.DataType.Anomalous)
|
|
603
610
|
if not (ints.isign_array < 0).any(): ints.type = gemmi.DataType.Mean
|
|
604
611
|
logger.writeln(" Multiplicity: max= {} mean= {:.1f} min= {}".format(numpy.max(ints.nobs_array),
|