servalcat 0.4.72__cp312-cp312-macosx_11_0_arm64.whl → 0.4.99__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.

@@ -15,6 +15,7 @@ import tempfile
15
15
  import subprocess
16
16
  import argparse
17
17
  from collections import OrderedDict
18
+ import servalcat # for version
18
19
  from servalcat.utils import logger
19
20
  from servalcat.refmac import refmac_keywords
20
21
  from servalcat import utils
@@ -64,7 +65,7 @@ def read_stdin(stdin):
64
65
 
65
66
  def prepare_crd(st, crdout, ligand, make, monlib_path=None, h_pos="elec",
66
67
  no_adjust_hydrogen_distances=False, fix_long_resnames=True,
67
- keep_entities=False):
68
+ keep_entities=False, unre=False):
68
69
  assert h_pos in ("elec", "nucl")
69
70
  h_change = dict(a=gemmi.HydrogenChange.ReAddButWater,
70
71
  y=gemmi.HydrogenChange.NoChange,
@@ -80,67 +81,85 @@ def prepare_crd(st, crdout, ligand, make, monlib_path=None, h_pos="elec",
80
81
  if at.occ > 1: # XXX should I check special positions?
81
82
  at.occ = 1.
82
83
 
83
- if not keep_entities:
84
+ refmac_fixes = utils.refmac.FixForRefmac()
85
+ if keep_entities:
86
+ refmac_fixes.store_res_labels(st)
87
+ else:
84
88
  utils.model.setup_entities(st, clear=True, force_subchain_names=True, overwrite_entity_type=True)
85
- # TODO read dictionary from xyzin (priority: user cif -> monlib -> xyzin
86
- try:
87
- monlib = utils.restraints.load_monomer_library(st,
88
- monomer_dir=monlib_path,
89
- cif_files=ligand,
90
- stop_for_unknowns=not make.get("newligand"))
91
- except RuntimeError as e:
92
- raise SystemExit("Error: {}".format(e))
93
89
 
94
- use_cispeps = make.get("cispept", "y") != "y"
95
- make_link = make.get("link", "n")
96
- make_ss = make.get("ss", "y")
97
- only_from = set()
98
- if make_link == "y":
99
- # add all links
100
- add_found = True
101
- elif make_ss == "y":
102
- add_found = True
103
- only_from.add("disulf")
90
+ if unre:
91
+ logger.writeln("Monomer library will not be loaded due to unrestrained refinement request")
92
+ monlib = gemmi.MonLib()
104
93
  else:
105
- add_found = False
106
-
107
- utils.restraints.fix_elements_in_model(monlib, st)
108
- utils.restraints.find_and_fix_links(st, monlib, add_found=add_found, find_symmetry_related=False, add_only_from=only_from)
109
- for con in st.connections:
110
- if con.link_id not in ("?", "", "gap") and con.link_id not in monlib.links:
111
- logger.writeln(" removing unknown link id ({}). Ad-hoc link will be generated.".format(con.link_id))
112
- con.link_id = ""
94
+ # TODO read dictionary from xyzin (priority: user cif -> monlib -> xyzin
95
+ try:
96
+ monlib = utils.restraints.load_monomer_library(st,
97
+ monomer_dir=monlib_path,
98
+ cif_files=ligand,
99
+ stop_for_unknowns=not make.get("newligand"))
100
+ except RuntimeError as e:
101
+ raise SystemExit("Error: {}".format(e))
102
+
103
+ use_cispeps = make.get("cispept", "y") != "y"
104
+ make_link = make.get("link", "n")
105
+ make_ss = make.get("ss", "y")
106
+ only_from = set()
107
+ if make_link == "y":
108
+ # add all links
109
+ add_found = True
110
+ elif make_ss == "y":
111
+ add_found = True
112
+ only_from.add("disulf")
113
+ else:
114
+ add_found = False
115
+
116
+ utils.restraints.fix_elements_in_model(monlib, st)
117
+ utils.restraints.find_and_fix_links(st, monlib, add_found=add_found,
118
+ find_metal_links=(make_link == "y"),
119
+ find_symmetry_related=False, add_only_from=only_from)
120
+ for con in st.connections:
121
+ if con.link_id not in ("?", "", "gap") and con.link_id not in monlib.links:
122
+ logger.writeln(" removing unknown link id ({}). Ad-hoc link will be generated.".format(con.link_id))
123
+ con.link_id = ""
113
124
 
114
- refmac_fixes = utils.refmac.FixForRefmac()
115
125
  max_seq_num = max([max(res.seqid.num for res in chain) for model in st for chain in model])
116
126
  if max_seq_num > 9999:
117
127
  logger.writeln("Max residue number ({}) exceeds 9999. Needs workaround.".format(max_seq_num))
118
- topo = gemmi.prepare_topology(st, monlib, ignore_unknown_links=True)
128
+ topo = gemmi.prepare_topology(st, monlib, warnings=logger.silent(), ignore_unknown_links=True)
119
129
  refmac_fixes.fix_before_topology(st, topo,
120
130
  fix_microheterogeneity=False,
121
131
  fix_resimax=True,
122
132
  fix_nonpolymer=False)
123
133
 
124
- if make.get("hydr") == "a": logger.writeln("(re)generating hydrogen atoms")
125
- try:
126
- topo, metal_kws = utils.restraints.prepare_topology(st, monlib, h_change=h_change, ignore_unknown_links=False,
127
- check_hydrogen=(h_change==gemmi.HydrogenChange.NoChange),
128
- use_cispeps=use_cispeps)
129
- except RuntimeError as e:
130
- raise SystemExit("Error: {}".format(e))
134
+ if unre:
135
+ # Refmac5 does not seem to do anything to hydrogen when unre regardless of "make hydr"
136
+ topo = gemmi.prepare_topology(st, monlib, warnings=logger.silent(), ignore_unknown_links=True)
137
+ metal_kws = []
138
+ else:
139
+ if make.get("hydr") == "a": logger.writeln("(re)generating hydrogen atoms")
140
+ try:
141
+ topo, metal_kws = utils.restraints.prepare_topology(st, monlib, h_change=h_change, ignore_unknown_links=False,
142
+ check_hydrogen=(h_change==gemmi.HydrogenChange.NoChange),
143
+ use_cispeps=use_cispeps)
144
+ except RuntimeError as e:
145
+ raise SystemExit("Error: {}".format(e))
131
146
 
132
- if make.get("hydr") != "n" and st[0].has_hydrogen():
133
- if h_pos == "nucl" and (make.get("hydr") == "a" or not no_adjust_hydrogen_distances):
134
- resnames = st[0].get_all_residue_names()
135
- utils.restraints.check_monlib_support_nucleus_distances(monlib, resnames)
136
- logger.writeln("adjusting hydrogen position to nucleus")
137
- topo.adjust_hydrogen_distances(gemmi.Restraints.DistanceOf.Nucleus, default_scale=1.1)
138
- elif h_pos == "elec" and make.get("hydr") == "y" and not no_adjust_hydrogen_distances:
139
- logger.writeln("adjusting hydrogen position to electron cloud")
140
- topo.adjust_hydrogen_distances(gemmi.Restraints.DistanceOf.ElectronCloud)
147
+ if make.get("hydr") != "n" and st[0].has_hydrogen():
148
+ if h_pos == "nucl" and (make.get("hydr") == "a" or not no_adjust_hydrogen_distances):
149
+ resnames = st[0].get_all_residue_names()
150
+ utils.restraints.check_monlib_support_nucleus_distances(monlib, resnames)
151
+ logger.writeln("adjusting hydrogen position to nucleus")
152
+ topo.adjust_hydrogen_distances(gemmi.Restraints.DistanceOf.Nucleus, default_scale=1.1)
153
+ elif h_pos == "elec" and make.get("hydr") == "y" and not no_adjust_hydrogen_distances:
154
+ logger.writeln("adjusting hydrogen position to electron cloud")
155
+ topo.adjust_hydrogen_distances(gemmi.Restraints.DistanceOf.ElectronCloud)
141
156
 
142
157
  if fix_long_resnames: refmac_fixes.fix_long_resnames(st)
143
158
 
159
+ # remove "given" ncs matrices
160
+ # TODO write them back to the output files
161
+ st.ncs = gemmi.NcsOpList(x for x in st.ncs if not x.given)
162
+
144
163
  # for safety
145
164
  if "_entry.id" in st.info:
146
165
  st.info["_entry.id"] = st.info["_entry.id"].replace(" ", "")
@@ -172,7 +191,7 @@ def prepare_crd(st, crdout, ligand, make, monlib_path=None, h_pos="elec",
172
191
  if st.name.lower() in block_names:
173
192
  st.name = st.name + str(i)
174
193
  doc = gemmi.prepare_refmac_crd(st, topo, monlib, h_change)
175
- doc.write_file(crdout, style=gemmi.cif.Style.NoBlankLines)
194
+ doc.write_file(crdout, options=gemmi.cif.Style.NoBlankLines)
176
195
  logger.writeln("crd file written: {}".format(crdout))
177
196
  return refmac_fixes, [x+"\n" for x in metal_kws]
178
197
  # prepare_crd()
@@ -221,11 +240,22 @@ def modify_output(pdbout, cifout, fixes, hout, cispeps, keep_original_output=Fal
221
240
  # should we check metals and put MetalC?
222
241
 
223
242
  # fix entity (Refmac seems to make DNA non-polymer; as seen in 1fix)
224
- utils.model.setup_entities(st, clear=True, overwrite_entity_type=True, force_subchain_names=True)
225
- for e in st.entities:
226
- if not e.full_sequence and e.entity_type == gemmi.EntityType.Polymer and e.subchains:
227
- rspan = st[0].get_subchain(e.subchains[0])
228
- e.full_sequence = [r.name for r in rspan]
243
+ if not fixes or not fixes.res_labels:
244
+ utils.model.setup_entities(st, clear=True, overwrite_entity_type=True, force_subchain_names=True)
245
+ for e in st.entities:
246
+ if not e.full_sequence and e.entity_type == gemmi.EntityType.Polymer and e.subchains:
247
+ rspan = st[0].get_subchain(e.subchains[0])
248
+ e.full_sequence = [r.name for r in rspan]
249
+
250
+ # fix label_seq_id
251
+ for chain in st[0]:
252
+ for res in chain:
253
+ res.label_seq = None
254
+ st.assign_label_seq_id()
255
+
256
+ # add servalcat version
257
+ if len(st.meta.software) > 0 and st.meta.software[-1].name == "refmac":
258
+ st.meta.software[-1].version += f" (refmacat {servalcat.__version__})"
229
259
 
230
260
  suffix = ".org"
231
261
  os.rename(cifout, cifout + suffix)
@@ -243,11 +273,6 @@ def modify_output(pdbout, cifout, fixes, hout, cispeps, keep_original_output=Fal
243
273
  logger.writeln("This structure cannot be saved as an official PDB format. Using hybrid-36. Header part may be inaccurate.")
244
274
  if not hout:
245
275
  st.remove_hydrogens() # remove hydrogen from pdb, while kept in mmcif
246
- # Use short name in pdb
247
- st.shorten_ccd_codes()
248
- if st.shortened_ccd_codes:
249
- msg = " ".join("{}->{}".format(o,n) for o,n in st.shortened_ccd_codes)
250
- logger.writeln("Using shortened residue names in the output pdb file: " + msg)
251
276
  os.rename(pdbout, pdbout + suffix)
252
277
  utils.fileio.write_pdb(st, pdbout)
253
278
  if not keep_original_output:
@@ -292,11 +317,12 @@ def main(args):
292
317
  crdout = None
293
318
  refmac_fixes = None
294
319
  cispeps = []
295
- if xyzin is not None and keywords["refi"].get("type") != "unre":
320
+ unre = keywords["refi"].get("type") == "unre"
321
+ if xyzin is not None:
296
322
  #tmpfd, crdout = tempfile.mkstemp(prefix="gemmi_", suffix=".crd") # TODO use dir=CCP4_SCR
297
323
  #os.close(tmpfd)
298
324
  st = utils.fileio.read_structure(xyzin)
299
- if not st.cell.is_crystal():
325
+ if not st.cell.is_crystal() and not unre:
300
326
  if args.auto_box_with_padding is not None:
301
327
  st.cell = utils.model.box_from_model(st[0], args.auto_box_with_padding)
302
328
  st.spacegroup_hm = "P 1"
@@ -309,7 +335,8 @@ def main(args):
309
335
  refmac_fixes, metal_kws = prepare_crd(st, crdout, args.ligand, make=keywords["make"], monlib_path=args.monlib,
310
336
  h_pos="nucl" if keywords.get("source")=="ne" else "elec",
311
337
  no_adjust_hydrogen_distances=args.no_adjust_hydrogen_distances,
312
- keep_entities=args.keep_entities)
338
+ keep_entities=args.keep_entities,
339
+ unre=unre)
313
340
  inputs = metal_kws + inputs # add metal exte first; otherwise it may be affected by user-defined inputs
314
341
  opts["xyzin"] = crdout
315
342
  cispeps = st.cispeps
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)')
@@ -377,6 +379,17 @@ def write_coot_script(py_out, model_file, mtz_file, contour_fo=1.2, contour_fofc
377
379
  ofs.write("add_molecular_symmetry(imol, {})\n".format(",".join(str(x) for x in v)))
378
380
  # write_coot_script()
379
381
 
382
+ def write_chimerax_script(cxc_out, model_file, fo_mrc_file, fofc_mrc_file):
383
+ with open(cxc_out, "w") as ofs:
384
+ ofs.write('open {}\n'.format(model_file))
385
+ ofs.write('open {}\n'.format(fo_mrc_file))
386
+ ofs.write('open {}\n'.format(fofc_mrc_file))
387
+ ofs.write('volume #3 level 4 level -4 color #00FF00 color #FF0000 squaremesh false cap false style mesh meshlighting false\n')
388
+ ofs.write('isolde start\n')
389
+ ofs.write('clipper associate #2 toModel #1\n')
390
+ ofs.write('clipper associate #3 toModel #1\n')
391
+ # write_chimerax_script()
392
+
380
393
  def main(args):
381
394
  if not args.halfmaps and not args.map:
382
395
  raise SystemExit("Error: give --halfmaps or --map")
@@ -453,7 +466,11 @@ def main(args):
453
466
  logger.writeln("coot --script " + py_out)
454
467
  if mask is not None:
455
468
  logger.writeln("\nWant to list Fo-Fc map peaks? Try:")
456
- logger.writeln("servalcat util map_peaks --map {}_normalized_fofc.mrc --model {} --abs_level 4.0".format(args.output_prefix, args.model))
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
+
457
474
  # main()
458
475
 
459
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.add_argument('--map',
23
+ group = parser.add_mutually_exclusive_group(required=True)
24
+ group.add_argument('--map',
24
25
  help='Input map file(s)')
25
- parser.add_argument('--mtz',
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')
@@ -36,6 +37,8 @@ def add_arguments(parser):
36
37
  parser.add_argument('--mask_soft_edge',
37
38
  type=float, default=0,
38
39
  help='Add soft edge to model mask.')
40
+ parser.add_argument('--mask_model', action='store_true',
41
+ help='Apply mask to model density')
39
42
  parser.add_argument("--b_before_mask", type=float,
40
43
  help="when model-based mask is used: sharpening B value for sharpen-mask-unsharpen procedure. By default it is determined automatically.")
41
44
  parser.add_argument('--no_sharpen_before_mask', action='store_true',
@@ -66,13 +69,10 @@ def write_loggraph(stats, labs_fc, log_out):
66
69
  model_labs1 = [l for l in stats if any(l.startswith("fsc_"+fc) for fc in labs_fc)]
67
70
  model_labs2 = [l for l in stats if any(l.startswith(("cc_"+fc, "mcos_"+fc)) for fc in labs_fc)]
68
71
  power_labs = [l for l in stats if l.startswith("power_")]
69
- half_labs1 = ["fsc_half_unmasked", "fsc_half_masked", "fsc_half_masked_rand", "fsc_half_masked_corrected"]
70
- half_labs2 = ["cc_half", "mcos_half"]
71
- if not all(l in stats for l in half_labs1):
72
- if "fsc_half" in stats:
73
- half_labs1 = ["fsc_half"]
74
- else:
75
- 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"]
76
76
 
77
77
  stats2 = stats.copy()
78
78
  stats2.insert(0, "bin", stats.index)
@@ -340,7 +340,7 @@ def main(args):
340
340
  labs_fc.append("FC")
341
341
  hkldata.df[labs_fc[-1]] = utils.model.calc_fc_fft(st_expanded, args.resolution - 1e-6, source="electron",
342
342
  miller_array=hkldata.miller_array())
343
- if mask is not None:
343
+ if args.mask_model and mask is not None:
344
344
  if args.b_before_mask is None:
345
345
  normalizer = 1.
346
346
  else:
@@ -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(spa.fsc.fsc_average(stats2.ncoeffs, stats2.fsc_model))
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(spa.fsc.fsc_average(stats2.ncoeffs, stats2.fsc_model_half1))
228
- fscavg_text += " FSCaverage(half2)= {: .4f}\n".format(spa.fsc.fsc_average(stats2.ncoeffs, stats2.fsc_model_half2))
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"):
@@ -311,6 +316,12 @@ def calc_fofc(st, st_expanded, maps, monlib, model_format, args, diffmap_prefix=
311
316
  contour_fo=None if mask is None else 1.2,
312
317
  contour_fofc=None if mask is None else 3.0,
313
318
  ncs_ops=st.ncs)
319
+
320
+ # Create ChimeraX script
321
+ spa.fofc.write_chimerax_script(cxc_out="{}_chimerax.cxc".format(args.output_prefix),
322
+ model_file="{}.mmcif".format(args.output_prefix), # ChimeraX handles mmcif just fine
323
+ fo_mrc_file="{}_normalized_fo.mrc".format(diffmap_prefix),
324
+ fofc_mrc_file="{}_normalized_fofc.mrc".format(diffmap_prefix))
314
325
  # calc_fofc()
315
326
 
316
327
  def write_final_summary(st, refmac_summary, fscavg_text, output_prefix, is_mask_given):
@@ -356,6 +367,9 @@ Weight used: {final_weight}
356
367
  Open refined model and diffmap.mtz with COOT:
357
368
  coot --script {prefix}_coot.py
358
369
 
370
+ Open refined model, map and difference map with ChimeraX/ISOLDE:
371
+ chimerax {prefix}_chimerax.cxc
372
+
359
373
  {map_peaks_msg}
360
374
  =============================================================================
361
375
  """.format(rmsbond=refmac_summary["cycles"][-1].get("rms_bond", "???"),
@@ -453,7 +467,7 @@ def process_input(st, maps, resolution, monlib, mask_in, args,
453
467
  unit_cell = maps[0][0].unit_cell
454
468
  spacegroup = gemmi.SpaceGroup(1)
455
469
  start_xyz = numpy.array(maps[0][0].get_position(*grid_start).tolist())
456
- A = numpy.array(unit_cell.orthogonalization_matrix.tolist())
470
+ A = unit_cell.orth.mat.array
457
471
  center = numpy.sum(A, axis=1) / 2 #+ start_xyz
458
472
 
459
473
  # Create mask
@@ -584,7 +598,7 @@ def process_input(st, maps, resolution, monlib, mask_in, args,
584
598
  topo, metal_kws = utils.restraints.prepare_topology(st, monlib, h_change=h_change, raise_error=False)
585
599
  args.keywords = metal_kws + args.keywords
586
600
  elif not no_refmac_fix:
587
- topo = gemmi.prepare_topology(st, monlib, warnings=io.StringIO(), ignore_unknown_links=True)
601
+ topo = gemmi.prepare_topology(st, monlib, warnings=logger.silent(), ignore_unknown_links=True)
588
602
  else:
589
603
  topo = None # not used
590
604
  if not no_refmac_fix:
@@ -609,7 +623,7 @@ def process_input(st, maps, resolution, monlib, mask_in, args,
609
623
  args.keywords.append("make cr prepared")
610
624
  gemmi.setup_for_crd(st)
611
625
  doc = gemmi.prepare_refmac_crd(st, topo, monlib, h_change)
612
- doc.write_file(crdout, style=gemmi.cif.Style.NoBlankLines)
626
+ doc.write_file(crdout, options=gemmi.cif.Style.NoBlankLines)
613
627
  logger.writeln("crd file written: {}".format(crdout))
614
628
 
615
629
  hkldata = utils.maps.mask_and_fft_maps(maps, resolution, None, with_000=False)
@@ -681,8 +695,9 @@ def check_args(args):
681
695
  if args.keyword_file:
682
696
  args.keyword_file = sum(args.keyword_file, [])
683
697
  for f in args.keyword_file:
698
+ if not os.path.exists(f):
699
+ raise SystemExit(f"Error: keyword file was not found: {f}")
684
700
  logger.writeln("Keyword file: {}".format(f))
685
- assert os.path.exists(f)
686
701
  else:
687
702
  args.keyword_file = []
688
703
 
@@ -945,7 +960,7 @@ def main(args):
945
960
  monlib=monlib, cross_validation=args.cross_validation,
946
961
  blur=args.blur,
947
962
  d_min_fsc=args.fsc_resolution,
948
- 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]
949
964
 
950
965
  # Calc Fo-Fc (and updated) maps
951
966
  calc_fofc(st, st_expanded, maps, monlib, model_format, args)
@@ -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.tricubic_interpolation(x)))
63
+ logger.writeln(" f0: {}".format(-tf_map.interpolate_value(x, order=3)))
64
64
 
65
- res = scipy.optimize.minimize(fun=lambda x:-tf_map.tricubic_interpolation(gemmi.Fractional(*x)),
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))