modelcraft 4.0.1__py3-none-any.whl → 5.0.0__py3-none-any.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.
modelcraft/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "4.0.1"
1
+ __version__ = "5.0.0"
2
2
 
3
3
  from .cell import max_distortion as max_cell_distortion
4
4
  from .cell import remove_scale
modelcraft/arguments.py CHANGED
@@ -241,25 +241,27 @@ _GROUP.add_argument(
241
241
 
242
242
  _EM = _SUB_PARSERS.add_parser("em", parents=[_PARENT], formatter_class=_FORMATTER)
243
243
  _GROUP = _EM.add_argument_group("required arguments (em)")
244
- _GROUP.add_argument(
245
- "--map",
246
- required=True,
247
- nargs="+",
244
+ _MAP = _GROUP.add_mutually_exclusive_group(required=True)
245
+ _MAP.add_argument(
246
+ "--half-maps",
247
+ nargs=2,
248
248
  metavar="X",
249
249
  help=(
250
- "Either two half-maps or a single map in MRC format. "
251
- "Input maps will be trimmed using Servalcat. "
252
- "If two half-maps are provided then Servalcat will be used to calculate "
250
+ "Unsharpened, unweighted half-maps in MRC format for use in refinement. "
251
+ "This option is preferred over providing a single map. "
252
+ "If the --build-map argument is not provided "
253
+ "then Servalcat will be used to calculate "
253
254
  "a normalised expected (NE) map for model building."
254
255
  ),
255
256
  )
256
- _GROUP.add_argument(
257
- "--mask",
257
+ _MAP.add_argument(
258
+ "--single-map",
258
259
  metavar="X",
259
260
  help=(
260
- "Mask with the same grid size and dimensions as the input map(s). "
261
- "Servalcat will use this mask when trimming the maps. "
262
- "If a mask is not provided then EMDA mapmask will be used to create one."
261
+ "A single unsharpened, unweighted map in MRC format for use in refinement. "
262
+ "Only use this option if you do not have two half-maps available. "
263
+ "If the --build-map argument is not provided "
264
+ "then this map will also be used for model building. "
263
265
  ),
264
266
  )
265
267
  _GROUP.add_argument(
@@ -267,19 +269,33 @@ _GROUP.add_argument(
267
269
  type=float,
268
270
  required=True,
269
271
  metavar="X",
270
- help="High resolution limit in Angstroms",
272
+ help=(
273
+ "Best resolution (high resolution limit) in Angstroms. "
274
+ "Using a higher resolution (a smaller number) reduces the grid spacing, "
275
+ "which may give better results at the cost of slower calculations."
276
+ ),
271
277
  )
278
+ _GROUP = _EM.add_argument_group("optional arguments (em)")
272
279
  _GROUP.add_argument(
273
- "--blur",
274
- default=0.0,
275
- type=float,
280
+ "--build-map",
281
+ metavar="X",
282
+ help=(
283
+ "Optimally-sharpened map (e.g. from LocScale) for use in model building. "
284
+ "If this is not provided then a normalised expected (NE) map "
285
+ "will be calculated from the two half-maps. "
286
+ "If half-maps were not provided then the single map will be used."
287
+ ),
288
+ )
289
+ _GROUP.add_argument(
290
+ "--mask",
276
291
  metavar="X",
277
292
  help=(
278
- "B-factor for global blurring or sharpening of the input map "
279
- "(positive values for blurring and negative values for sharpening). "
280
- "This value is only used if a single input map is provided. "
281
- "If two half-maps are provided then local blurring and sharpening "
282
- "is performed in the calculation of the normalised expected (NE) map."
293
+ "Mask for trimming the input maps in MRC format, "
294
+ "with the same grid size and dimensions as the input maps. "
295
+ "Having a box size that is too large will lead to worse building results, "
296
+ "slow down the programs, and make the FSC calculation less accurate. "
297
+ "If this argument is set to 'auto' "
298
+ "then EMDA mapmask will be used to create a mask."
283
299
  ),
284
300
  )
285
301
 
@@ -303,25 +319,30 @@ def _basic_check(args: argparse.Namespace):
303
319
  _PARSER.error(f"--threads must be between 1 and {(os.cpu_count() or 1)}")
304
320
  if args.mode == "em" and args.resolution <= 0:
305
321
  _PARSER.error("--resolution must be greater than 0")
306
- if args.mode == "em" and len(args.map) > 2:
307
- _PARSER.error("--map only takes two half-maps or a single map")
308
- if args.mode == "em" and len(args.map) == 2 and args.blur != 0.0:
309
- _PARSER.error("--blur can only be used with a single map and not two half-maps")
310
322
 
311
323
 
312
324
  def _check_paths(args: argparse.Namespace):
313
- for arg in ("contents", "data", "map", "mask", "model", "restraints"):
325
+ for arg in (
326
+ "build_map",
327
+ "contents",
328
+ "data",
329
+ "half_maps",
330
+ "mask",
331
+ "model",
332
+ "restraints",
333
+ "single_map",
334
+ ):
314
335
  if hasattr(args, arg):
315
336
  attr = getattr(args, arg)
316
- if isinstance(attr, str):
337
+ if isinstance(attr, str) and attr != "auto":
317
338
  if not os.path.exists(attr):
318
- _PARSER.error("File not found: %s" % attr)
339
+ _PARSER.error(f"File not found: {attr}")
319
340
  attr = os.path.abspath(attr)
320
341
  setattr(args, arg, attr)
321
342
  if isinstance(attr, list):
322
343
  for i, path in enumerate(attr):
323
344
  if not os.path.exists(path):
324
- _PARSER.error("File not found: %s" % path)
345
+ _PARSER.error(f"File not found: {path}")
325
346
  attr[i] = os.path.abspath(path)
326
347
 
327
348
 
@@ -49,12 +49,12 @@ class ServalcatNemap(Job):
49
49
  @dataclasses.dataclass
50
50
  class ServalcatTrimResult:
51
51
  mask: gemmi.Ccp4Map
52
- maps: list
52
+ maps: dict
53
53
  seconds: float
54
54
 
55
55
 
56
56
  class ServalcatTrim(Job):
57
- def __init__(self, mask: gemmi.Ccp4Map, maps: list):
57
+ def __init__(self, mask: gemmi.Ccp4Map, maps: dict):
58
58
  super().__init__("servalcat")
59
59
  self.mask = mask
60
60
  self.maps = maps
@@ -64,21 +64,20 @@ class ServalcatTrim(Job):
64
64
  self.mask.write_ccp4_map(self._path("mask.ccp4"))
65
65
  self._args += ["--mask", "mask.ccp4"]
66
66
  self._args.append("--maps")
67
- for i, map_ in enumerate(self.maps):
68
- map_.write_ccp4_map(self._path(f"map{i}.ccp4"))
69
- self._args.append(f"map{i}.ccp4")
67
+ for name, ccp4_map in self.maps.items():
68
+ ccp4_map.write_ccp4_map(self._path(f"{name}.ccp4"))
69
+ self._args.append(f"{name}.ccp4")
70
70
  self._args.append("--noncubic")
71
71
  self._args.append("--noncentered")
72
72
  self._args.append("--no_shift")
73
73
 
74
74
  def _result(self) -> ServalcatTrimResult:
75
- self._check_files_exist("mask_trimmed.mrc", "map0_trimmed.mrc")
75
+ self._check_files_exist("mask_trimmed.mrc")
76
76
  return ServalcatTrimResult(
77
77
  mask=read_map(self._path("mask_trimmed.mrc")),
78
- maps=[
79
- read_map(self._path(f"map{i}_trimmed.mrc"))
80
- for i in range(len(self.maps))
81
- ],
78
+ maps={
79
+ name: read_map(self._path(f"{name}_trimmed.mrc")) for name in self.maps
80
+ },
82
81
  seconds=self._seconds,
83
82
  )
84
83
 
@@ -25,12 +25,17 @@ class ModelCraftEm(Pipeline):
25
25
  self.report["version"] = __version__
26
26
  self.report["args"] = raw_args
27
27
  self.report["cycles"] = []
28
+ self.maps = {}
29
+ self.fmean = None
30
+ self.phases = None
28
31
 
29
32
  def run(self):
30
33
  print(f"# ModelCraft {__version__}", flush=True)
31
34
  os.makedirs(self.args.directory, exist_ok=self.args.overwrite_directory)
32
35
  self.start_time = time.time()
33
- self._process_input_maps()
36
+ self._read_input_maps()
37
+ self._trim_input_maps()
38
+ self._calculate_fmean_and_phases()
34
39
  structure = self.args.model
35
40
  best_fsc = None
36
41
  cycles_without_improvement = 0
@@ -58,36 +63,52 @@ class ModelCraftEm(Pipeline):
58
63
  break
59
64
  self.terminate("Normal")
60
65
 
61
- def _process_input_maps(self):
62
- maps = [read_map(path) for path in self.args.map]
63
- if self.args.mask is not None:
64
- mask = read_map(self.args.mask)
66
+ def _read_input_maps(self):
67
+ if self.args.half_maps:
68
+ self.maps["half_map1"] = read_map(self.args.half_maps[0])
69
+ self.maps["half_map2"] = read_map(self.args.half_maps[1])
65
70
  else:
66
- mask = EmdaMapMask(maps[0]).run(self).mask
67
- trimmed = ServalcatTrim(mask, maps).run(self)
68
- self.args.map = trimmed.maps
69
- if len(maps) == 2:
71
+ self.maps["single_map"] = read_map(self.args.single_map)
72
+ if self.args.build_map:
73
+ self.maps["build_map"] = read_map(self.args.build_map)
74
+
75
+ def _trim_input_maps(self):
76
+ if self.args.mask:
77
+ if self.args.mask == "auto":
78
+ map_for_mask = self.maps.get("half_map1", self.maps.get("single_map"))
79
+ mask = EmdaMapMask(map_for_mask).run(self).mask
80
+ else:
81
+ mask = read_map(self.args.mask)
82
+ trimmed = ServalcatTrim(mask, self.maps).run(self)
83
+ self.maps.update(trimmed.maps)
84
+
85
+ def _calculate_fmean_and_phases(self):
86
+ if self.args.build_map:
87
+ refmac = RefmacMapToMtz(
88
+ density=self.maps["build_map"],
89
+ resolution=self.args.resolution,
90
+ ).run(self)
91
+ fphi = refmac.fphi
92
+ elif self.args.half_maps:
70
93
  nemap = ServalcatNemap(
71
- halfmap1=trimmed.maps[0],
72
- halfmap2=trimmed.maps[1],
94
+ halfmap1=self.maps["half_map1"],
95
+ halfmap2=self.maps["half_map2"],
73
96
  resolution=self.args.resolution,
74
- mask=trimmed.mask,
75
97
  ).run(self)
76
- self.args.fphi = nemap.fphi
98
+ fphi = nemap.fphi
77
99
  else:
78
100
  refmac = RefmacMapToMtz(
79
- density=trimmed.maps[0],
101
+ density=self.maps["single_map"],
80
102
  resolution=self.args.resolution,
81
- blur=self.args.blur,
82
103
  ).run(self)
83
- self.args.fphi = refmac.fphi
84
- self.args.fmean, self.args.phases = convert_to_fsigf_and_phifom(self.args.fphi)
104
+ fphi = refmac.fphi
105
+ self.fmean, self.phases = convert_to_fsigf_and_phifom(fphi)
85
106
 
86
107
  def buccaneer(self, structure: gemmi.Structure) -> gemmi.Structure:
87
108
  result = Buccaneer(
88
109
  contents=self.args.contents,
89
- fsigf=self.args.fmean,
90
- phases=self.args.phases,
110
+ fsigf=self.fmean,
111
+ phases=self.phases,
91
112
  input_structure=structure,
92
113
  mr_structure=self.args.model,
93
114
  cycles=5,
@@ -99,8 +120,8 @@ class ModelCraftEm(Pipeline):
99
120
  def nautilus(self, structure: gemmi.Structure) -> gemmi.Structure:
100
121
  result = Nautilus(
101
122
  contents=self.args.contents,
102
- fsigf=self.args.fmean,
103
- phases=self.args.phases,
123
+ fsigf=self.fmean,
124
+ phases=self.phases,
104
125
  structure=structure,
105
126
  ).run(self)
106
127
  return result.structure
@@ -111,9 +132,9 @@ class ModelCraftEm(Pipeline):
111
132
  result = ServalcatRefine(
112
133
  structure=structure,
113
134
  resolution=self.args.resolution,
114
- halfmap1=self.args.map[0] if len(self.args.map) == 2 else None,
115
- halfmap2=self.args.map[1] if len(self.args.map) == 2 else None,
116
- density=self.args.map[0] if len(self.args.map) == 1 else None,
135
+ halfmap1=self.maps.get("half_map1"),
136
+ halfmap2=self.maps.get("half_map2"),
137
+ density=self.maps.get("single_map"),
117
138
  ligand=self.args.restraints,
118
139
  ).run(self)
119
140
  return result.structure
@@ -122,8 +143,8 @@ class ModelCraftEm(Pipeline):
122
143
  result = ServalcatFsc(
123
144
  structure=structure,
124
145
  resolution=self.args.resolution,
125
- halfmap1=self.args.map[0] if len(self.args.map) == 2 else None,
126
- halfmap2=self.args.map[1] if len(self.args.map) == 2 else None,
127
- density=self.args.map[0] if len(self.args.map) == 1 else None,
146
+ halfmap1=self.maps.get("half_map1"),
147
+ halfmap2=self.maps.get("half_map2"),
148
+ density=self.maps.get("single_map"),
128
149
  ).run(self)
129
150
  return result.fsc
@@ -123,6 +123,8 @@ class ModelCraftXray(Pipeline):
123
123
  def run_buccaneer_and_nautilus(self):
124
124
  buccaneer = self.buccaneer()
125
125
  nautilus = self.nautilus()
126
+ if buccaneer is None and nautilus is None:
127
+ self.terminate(reason="No residues built")
126
128
  if buccaneer is None or nautilus is None:
127
129
  self.update_current_from_refmac_result(buccaneer or nautilus)
128
130
  else:
@@ -132,7 +134,7 @@ class ModelCraftXray(Pipeline):
132
134
 
133
135
  def buccaneer(self):
134
136
  if not self.args.contents.proteins:
135
- return
137
+ return None
136
138
  result = Buccaneer(
137
139
  contents=self.args.contents,
138
140
  fsigf=self.args.fmean,
@@ -147,12 +149,14 @@ class ModelCraftXray(Pipeline):
147
149
  cycles=3 if self.cycle == 1 else 2,
148
150
  threads=self.args.threads,
149
151
  ).run(self)
152
+ if result.structure is None or ModelStats(result.structure).residues == 0:
153
+ return None
150
154
  write_mmcif(self.path("current.cif"), result.structure)
151
155
  return self.run_refmac(result.structure, cycles=10)
152
156
 
153
157
  def nautilus(self):
154
158
  if not (self.args.contents.rnas or self.args.contents.dnas):
155
- return
159
+ return None
156
160
  result = Nautilus(
157
161
  contents=self.args.contents,
158
162
  fsigf=self.args.fmean,
@@ -161,6 +165,8 @@ class ModelCraftXray(Pipeline):
161
165
  freer=self.args.freer,
162
166
  structure=self.current_structure,
163
167
  ).run(self)
168
+ if result.structure is None or ModelStats(result.structure).residues == 0:
169
+ return None
164
170
  write_mmcif(self.path("current.cif"), result.structure)
165
171
  return self.run_refmac(result.structure, cycles=10)
166
172
 
@@ -14,17 +14,18 @@ from . import (
14
14
 
15
15
 
16
16
  @in_temp_directory
17
- def test_3488_model():
17
+ def test_3488_single_map():
18
18
  args = ["em"]
19
19
  args += ["--contents", sequence_path()]
20
- args += ["--map", density_path()]
20
+ args += ["--single-map", density_path()]
21
21
  args += ["--resolution", "3.2"]
22
- args += ["--blur", "10"]
23
22
  args += ["--cycles", "1"]
24
23
  args += ["--model", structure_path()]
24
+ args += ["--mask", "auto"]
25
25
  with pytest.raises(SystemExit):
26
26
  main(args)
27
- with open(os.path.join("modelcraft", "modelcraft.json")) as report_file:
27
+ report_path = os.path.join("modelcraft", "modelcraft.json")
28
+ with open(report_path, encoding="utf-8") as report_file:
28
29
  report = json.load(report_file)
29
30
  assert report["seconds"]["total"] > 0
30
31
  assert report["final"]["fsc"] > 0.6
@@ -32,16 +33,18 @@ def test_3488_model():
32
33
 
33
34
 
34
35
  @in_temp_directory
35
- def test_3488_halfmaps():
36
+ def test_3488_half_maps():
36
37
  args = ["em"]
37
38
  args += ["--contents", sequence_path()]
38
- args += ["--map", halfmap1_path(), halfmap2_path()]
39
+ args += ["--half-maps", halfmap1_path(), halfmap2_path()]
40
+ args += ["--build-map", density_path()]
39
41
  args += ["--mask", mask_path()]
40
42
  args += ["--resolution", "3.2"]
41
43
  args += ["--cycles", "1"]
42
44
  with pytest.raises(SystemExit):
43
45
  main(args)
44
- with open(os.path.join("modelcraft", "modelcraft.json")) as report_file:
46
+ report_path = os.path.join("modelcraft", "modelcraft.json")
47
+ with open(report_path, encoding="utf-8") as report_file:
45
48
  report = json.load(report_file)
46
49
  assert report["seconds"]["total"] > 0
47
50
  assert report["termination_reason"] == "Normal"
@@ -17,11 +17,13 @@ def test_servalcat_nemap():
17
17
 
18
18
 
19
19
  def test_servalcat_trim():
20
- halfmap1 = read_map(halfmap1_path())
21
- halfmap2 = read_map(halfmap2_path())
22
- density = read_map(density_path())
20
+ maps = {
21
+ "halfmap1": read_map(halfmap1_path()),
22
+ "halfmap2": read_map(halfmap2_path()),
23
+ "density": read_map(density_path()),
24
+ }
23
25
  mask = read_map(mask_path())
24
- trimmed = ServalcatTrim(mask, [density, halfmap1, halfmap2]).run()
26
+ trimmed = ServalcatTrim(mask, maps).run()
25
27
  assert len(trimmed.maps) == 3
26
28
 
27
29
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: modelcraft
3
- Version: 4.0.1
3
+ Version: 5.0.0
4
4
  Summary: Automated model building pipeline for X-ray crystallography
5
5
  Home-page: https://github.com/paulsbond/modelcraft
6
6
  Author: Paul Bond
@@ -16,7 +16,7 @@ Classifier: Programming Language :: Python :: 3.9
16
16
  Requires-Python: ~=3.7
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
- Requires-Dist: gemmi >=0.5.4
19
+ Requires-Dist: gemmi>=0.5.4
20
20
  Requires-Dist: numpy
21
21
  Requires-Dist: pandas
22
22
  Requires-Dist: requests
@@ -1,6 +1,6 @@
1
- modelcraft/__init__.py,sha256=EShQrPLQTgeHMytTnuJwRw8JFkGsBYMVe-iHAMoy66w,2185
1
+ modelcraft/__init__.py,sha256=gfYpLpVeYaQdezn2628PhHSn1zD3bQSH1EcotBve5PU,2185
2
2
  modelcraft/__main__.py,sha256=0D-TbVRrb0ipPCS-NnUvifaG2kAsBn6mXtWLjyExOXM,77
3
- modelcraft/arguments.py,sha256=DChFhzk09Fwpsb4ycZ4OBfXxsFJLNiQiao4ZoErB5wA,14606
3
+ modelcraft/arguments.py,sha256=fqsnzJhJKOg7MRgjqb50WFp_lQowG4J9O6ITyqr-q4g,15203
4
4
  modelcraft/cell.py,sha256=mqoQfODyXd43MhLYnGwXxTag42Fx9l2wMH3s-ouXpr0,2057
5
5
  modelcraft/combine.py,sha256=ibxg6dhvKBQ2r7AZlGE-ebEpO7dPNDVP5ChYppil9To,5020
6
6
  modelcraft/contents.py,sha256=VEdFt1u6PDMUGjYbHa6eORr-9voi2zfzuc1CV1c5nuI,9860
@@ -8,8 +8,8 @@ modelcraft/environ.py,sha256=T8oMcx2rqc2FjNy-roKWl4CoVUnNJ1UOCecM0xbPC3E,553
8
8
  modelcraft/geometry.py,sha256=ofgIgZ4G2W56vofldJVrkTjuxAbDhzOtsJckv-kCP_A,1218
9
9
  modelcraft/job.py,sha256=RpM8UfIPH0uNf_yuwBTq4GLp2aY-4_yvJEQd7r3aL4o,4104
10
10
  modelcraft/maps.py,sha256=Lyv3YjKNdUgi6vaLmQ8CcZFKq39EPL4NDC5qO_kCd0A,354
11
- modelcraft/modelcraftem.py,sha256=x2o2b_uD91mr-gJHK9CrODVAdp9FCJF9kIC1GrofMLI,5133
12
- modelcraft/modelcraftxray.py,sha256=l73CSdLkEjgf1MdEZgp6tJnTwtkTvp5lvkxSA-mCSWU,12791
11
+ modelcraft/modelcraftem.py,sha256=AEZYS4zN_-O1cxv78K9Mf2dj_AMVEcAYmuThV-0S7Pw,5757
12
+ modelcraft/modelcraftxray.py,sha256=tRzxvhcC5opUiy24GeQaMLG2ZT_qvlcdq6ObFpA9nnM,13121
13
13
  modelcraft/monlib.py,sha256=cEiYHKGEKpBlv-fJbKYJ91aZyMu9iAtmwdyuWeZj2F0,1482
14
14
  modelcraft/pipeline.py,sha256=2fUmFcCyUG6EmAOxSHtcG91zRHHZmwjRkmJy5Y7Raus,2030
15
15
  modelcraft/reflections.py,sha256=w8iV5NBcghUlufXWvxXLtbW8oNHR5Jx9ELKhgKThvkw,6274
@@ -34,7 +34,7 @@ modelcraft/jobs/nautilus.py,sha256=eOpCynvFcGdlCwF9fE4oKlWnUPSP3sAnE5KLS0UfZGE,2
34
34
  modelcraft/jobs/parrot.py,sha256=G1ZYpnsu8_T_fUaO5VExMvzJjacsY8Avw4i_HBtSgi8,2190
35
35
  modelcraft/jobs/phasematch.py,sha256=clUoRs4fptJa2Wy2sLYhRrfsutPtjqaIBwFwpOGdkuY,1841
36
36
  modelcraft/jobs/refmac.py,sha256=sOVbLOq3t_SUH7zpUlLUrtHwzG_y_wkjIbIE9ec3iJE,5379
37
- modelcraft/jobs/servalcat.py,sha256=QBZEWalbJt6QQUI4LT9m_0cqZ21I46q1cHzAl9TS6G8,6619
37
+ modelcraft/jobs/servalcat.py,sha256=dysjZGtNdjuJNZWNDAw5NqaCO0OzNk2jomENbNSpp2U,6588
38
38
  modelcraft/jobs/sheetbend.py,sha256=Dmky59U0P2FeU_Ggy7502NQBErFiJ0xcShOkysZeDrc,1569
39
39
  modelcraft/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
40
  modelcraft/scripts/contents.py,sha256=LTu_v8YUYRgo_s7sK4Q1ikP95da49x-arsXAgtbsTyI,7694
@@ -67,16 +67,16 @@ modelcraft/tests/ccp4/test_solvent.py,sha256=DN42jpiqIXO5ogqvcsH2DX_-YGQRXJ-h3AK
67
67
  modelcraft/tests/ccp4/test_structure.py,sha256=zXEDHankyyIuMDF4wWVKowLKYvHbA0EpWM0bxZwo-Vg,336
68
68
  modelcraft/tests/ccp4/test_xray.py,sha256=YExs_3_l8HEDJ3hjNCnvoF5rTd3mWrAdotywV_jK1Vk,2995
69
69
  modelcraft/tests/ccpem/__init__.py,sha256=fY53G_EEc9LG4FmZ-IfQEhmEsNg5FZfxFwOCUQj019c,656
70
- modelcraft/tests/ccpem/test_em.py,sha256=PkROOKE-mdcFo709E8ifd39PUshpgV63pzsYja3mVzw,1368
70
+ modelcraft/tests/ccpem/test_em.py,sha256=6fM4z1Zh27oTdo_4IY5p9jB0qQWdLri-TQUV3ea2TVE,1529
71
71
  modelcraft/tests/ccpem/test_emda.py,sha256=Bd9Cv4EoDckLYLqsZg7XNTYnGogqELzWokiHs5bU1W4,399
72
72
  modelcraft/tests/ccpem/test_refmac.py,sha256=AYpTftXpvKBUMi7VQw0cMOJVJ883z2RVAlCRAvLUBto,325
73
- modelcraft/tests/ccpem/test_servalcat.py,sha256=3FQVpo-Vf9MStV-dZD-ZVzGin7YefgTGaEfn9PNGcW4,1423
73
+ modelcraft/tests/ccpem/test_servalcat.py,sha256=X6d0z5yE-sxNa-6_WySn12QhvbJelYNnpOqfQju7PvM,1435
74
74
  modelcraft/tests/unittests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
75
  modelcraft/tests/unittests/test_contents.py,sha256=aAHha4pQYMyKes7OiOZ11_-9z-BVqh4OSmAL8gRUX_Y,3153
76
76
  modelcraft/tests/unittests/test_reflections.py,sha256=xshb_2QcAko2l98-Pd1LuEjMZAVv-O7LkhtzGRnrbM4,3674
77
- modelcraft-4.0.1.dist-info/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
78
- modelcraft-4.0.1.dist-info/METADATA,sha256=j5FQa_9CFRpNtBwStccDGNGzfuruNJgw2lgxTzmAHtc,1893
79
- modelcraft-4.0.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
80
- modelcraft-4.0.1.dist-info/entry_points.txt,sha256=bWef3WSAihTv1fI39wScTAmrKtn5mOYZ3SEeBpM4RrU,172
81
- modelcraft-4.0.1.dist-info/top_level.txt,sha256=My5973x4fvPrlRfQOuuFxqultnVzrg_aamczcSijdlQ,11
82
- modelcraft-4.0.1.dist-info/RECORD,,
77
+ modelcraft-5.0.0.dist-info/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
78
+ modelcraft-5.0.0.dist-info/METADATA,sha256=yUpLJkzkoxlWPf-3It_RcaxO4MKtarTQnccCH7LGs60,1892
79
+ modelcraft-5.0.0.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
80
+ modelcraft-5.0.0.dist-info/entry_points.txt,sha256=bWef3WSAihTv1fI39wScTAmrKtn5mOYZ3SEeBpM4RrU,172
81
+ modelcraft-5.0.0.dist-info/top_level.txt,sha256=My5973x4fvPrlRfQOuuFxqultnVzrg_aamczcSijdlQ,11
82
+ modelcraft-5.0.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (75.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5