modelcraft 5.0.3__py3-none-any.whl → 6.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.
Files changed (90) hide show
  1. modelcraft/__init__.py +16 -31
  2. modelcraft/__main__.py +0 -1
  3. modelcraft/arguments.py +35 -7
  4. modelcraft/combine.py +22 -41
  5. modelcraft/contents.py +188 -164
  6. modelcraft/environ.py +0 -7
  7. modelcraft/geometry.py +39 -27
  8. modelcraft/job.py +6 -5
  9. modelcraft/jobs/acedrg.py +2 -0
  10. modelcraft/jobs/buccaneer.py +22 -4
  11. modelcraft/jobs/comit.py +2 -0
  12. modelcraft/jobs/ctruncate.py +3 -1
  13. modelcraft/jobs/emda.py +2 -0
  14. modelcraft/jobs/findwaters.py +2 -0
  15. modelcraft/jobs/freerflag.py +2 -0
  16. modelcraft/jobs/libg.py +2 -0
  17. modelcraft/jobs/molrep.py +2 -0
  18. modelcraft/jobs/nautilus.py +28 -14
  19. modelcraft/jobs/nucleofind.py +88 -0
  20. modelcraft/jobs/parrot.py +13 -2
  21. modelcraft/jobs/phasematch.py +2 -1
  22. modelcraft/jobs/refmac.py +3 -1
  23. modelcraft/jobs/servalcat.py +36 -2
  24. modelcraft/jobs/sheetbend.py +2 -0
  25. modelcraft/modelcraftem.py +49 -6
  26. modelcraft/modelcraftxray.py +90 -42
  27. modelcraft/monlib.py +55 -52
  28. modelcraft/pdbe.py +54 -0
  29. modelcraft/pipeline.py +1 -1
  30. modelcraft/prune.py +69 -0
  31. modelcraft/reflections.py +11 -1
  32. modelcraft/scripts/contents.py +5 -215
  33. modelcraft/scripts/copies.py +26 -17
  34. modelcraft/scripts/modelcraft.py +1 -0
  35. modelcraft/scripts/sidechains.py +141 -0
  36. modelcraft/scripts/validate.py +81 -0
  37. modelcraft/sequence.py +106 -0
  38. modelcraft/solvent.py +42 -113
  39. modelcraft/structure.py +64 -41
  40. modelcraft/tests/ccp4/__init__.py +7 -11
  41. modelcraft/tests/ccp4/test_acedrg.py +2 -0
  42. modelcraft/tests/ccp4/test_arguments.py +3 -0
  43. modelcraft/tests/ccp4/test_buccaneer.py +3 -2
  44. modelcraft/tests/ccp4/test_cell.py +4 -1
  45. modelcraft/tests/ccp4/test_comit.py +2 -0
  46. modelcraft/tests/ccp4/test_contents.py +99 -17
  47. modelcraft/tests/ccp4/test_copies.py +1 -0
  48. modelcraft/tests/ccp4/test_ctruncate.py +2 -0
  49. modelcraft/tests/ccp4/test_findwaters.py +2 -0
  50. modelcraft/tests/ccp4/test_freerflag.py +2 -0
  51. modelcraft/tests/ccp4/test_libg.py +1 -0
  52. modelcraft/tests/ccp4/test_molrep.py +3 -0
  53. modelcraft/tests/ccp4/test_monlib.py +75 -45
  54. modelcraft/tests/ccp4/test_nautilus.py +5 -3
  55. modelcraft/tests/ccp4/test_nucleofind.py +62 -0
  56. modelcraft/tests/ccp4/test_parrot.py +3 -1
  57. modelcraft/tests/ccp4/test_phasematch.py +2 -0
  58. modelcraft/tests/ccp4/test_prune.py +17 -0
  59. modelcraft/tests/ccp4/test_reflections.py +110 -1
  60. modelcraft/tests/ccp4/test_refmac.py +3 -0
  61. modelcraft/tests/{unittests/test_contents.py → ccp4/test_sequence.py} +5 -12
  62. modelcraft/tests/ccp4/test_servalcat.py +52 -0
  63. modelcraft/tests/ccp4/test_sheetbend.py +4 -3
  64. modelcraft/tests/ccp4/test_sidechains.py +25 -0
  65. modelcraft/tests/ccp4/test_solvent.py +12 -26
  66. modelcraft/tests/ccp4/test_structure.py +1 -0
  67. modelcraft/tests/ccp4/test_validation.py +19 -0
  68. modelcraft/tests/ccp4/test_xray.py +12 -6
  69. modelcraft/tests/ccpem/test_em.py +3 -0
  70. modelcraft/tests/ccpem/test_emda.py +2 -0
  71. modelcraft/tests/ccpem/test_refmac.py +1 -0
  72. modelcraft/tests/ccpem/test_servalcat.py +4 -3
  73. modelcraft/utils.py +16 -4
  74. modelcraft/validation.py +101 -0
  75. modelcraft-6.0.0.dist-info/METADATA +76 -0
  76. modelcraft-6.0.0.dist-info/RECORD +85 -0
  77. {modelcraft-5.0.3.dist-info → modelcraft-6.0.0.dist-info}/WHEEL +1 -1
  78. {modelcraft-5.0.3.dist-info → modelcraft-6.0.0.dist-info}/entry_points.txt +2 -0
  79. modelcraft/coot/prune.py +0 -1085
  80. modelcraft/coot/sidechains.py +0 -68
  81. modelcraft/jobs/acorn.py +0 -114
  82. modelcraft/jobs/coot.py +0 -104
  83. modelcraft/tests/ccp4/test_coot.py +0 -29
  84. modelcraft/tests/ccp4/test_geometry.py +0 -20
  85. modelcraft/tests/unittests/__init__.py +0 -0
  86. modelcraft/tests/unittests/test_reflections.py +0 -101
  87. modelcraft-5.0.3.dist-info/METADATA +0 -49
  88. modelcraft-5.0.3.dist-info/RECORD +0 -82
  89. modelcraft-5.0.3.dist-info/licenses/LICENSE +0 -504
  90. {modelcraft-5.0.3.dist-info → modelcraft-6.0.0.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
1
1
  from modelcraft.scripts.copies import main
2
+
2
3
  from . import ccp4_path, in_temp_directory, insulin_contents
3
4
 
4
5
 
@@ -1,6 +1,8 @@
1
1
  import gemmi
2
+
2
3
  from modelcraft.jobs.ctruncate import CTruncate
3
4
  from modelcraft.reflections import DataItem
5
+
4
6
  from . import ccp4_path
5
7
 
6
8
 
@@ -1,6 +1,8 @@
1
1
  import gemmi
2
+
2
3
  from modelcraft.jobs.findwaters import FindWaters
3
4
  from modelcraft.structure import ModelStats
5
+
4
6
  from . import insulin_refmac
5
7
 
6
8
 
@@ -1,5 +1,7 @@
1
1
  import gemmi
2
+
2
3
  from modelcraft.jobs.freerflag import FreeRFlag
4
+
3
5
  from . import ccp4_path
4
6
 
5
7
 
@@ -1,5 +1,6 @@
1
1
  from modelcraft.jobs.libg import Libg
2
2
  from modelcraft.structure import read_structure
3
+
3
4
  from . import ccp4_path
4
5
 
5
6
 
@@ -1,8 +1,11 @@
1
1
  import os
2
+
2
3
  import gemmi
4
+
3
5
  from modelcraft.jobs.molrep import Molrep
4
6
  from modelcraft.reflections import DataItem
5
7
  from modelcraft.structure import read_structure
8
+
6
9
  from . import ccp4_path
7
10
 
8
11
 
@@ -1,61 +1,91 @@
1
+ import math
2
+
1
3
  import gemmi
2
- from modelcraft.contents import PROTEIN_CODES, DNA_CODES, RNA_CODES
3
- from modelcraft.monlib import atom_ids, in_library, group, is_protein, is_nucleic
4
+ import pytest
5
+
6
+ from modelcraft.monlib import MonLib
7
+ from modelcraft.sequence import DNA_CODES, PROTEIN_CODES, RNA_CODES
8
+
9
+
10
+ @pytest.fixture(name="monlib", scope="module")
11
+ def monlib_fixture():
12
+ return MonLib({"COM", "2GP"}, include_standard=True)
4
13
 
5
14
 
6
- def test_hoh_ids():
15
+ def test_hoh_ids(monlib: MonLib):
7
16
  ids = {"O", "H1", "H2"}
8
- assert atom_ids("HOH") == ids
17
+ assert monlib.atom_ids("HOH") == ids
9
18
 
10
19
 
11
- def test_gly_ids():
20
+ def test_gly_ids(monlib: MonLib):
12
21
  ids = {"N", "H", "H2", "H3", "CA", "HA3", "HA2", "C", "O", "OXT"}
13
- assert atom_ids("GLY") == ids
22
+ assert monlib.atom_ids("GLY") == ids
14
23
 
15
24
 
16
- def test_com_ids():
25
+ def test_com_ids(monlib: MonLib):
17
26
  ids = {"C1", "C2", "S1", "S2", "O1S", "O2S", "O3S"}
18
27
  ids |= {"H11", "H12", "H21", "H22", "HS1", "HOS3"}
19
- assert atom_ids("COM") == ids
28
+ assert monlib.atom_ids("COM") == ids
20
29
 
21
30
 
22
- def test_in_library():
31
+ def test_in_library(monlib: MonLib):
23
32
  for code in PROTEIN_CODES.values():
24
- assert in_library(code)
33
+ assert code in monlib
25
34
  for code in DNA_CODES.values():
26
- assert in_library(code)
35
+ assert code in monlib
27
36
  for code in RNA_CODES.values():
28
- assert in_library(code)
29
- assert not in_library("NOT_IN_MONLIB")
30
-
31
-
32
- def test_group():
33
- assert group("GLY") == gemmi.ChemComp.Group.Peptide
34
- assert group("ALA") == gemmi.ChemComp.Group.Peptide
35
- assert group("MSE") == gemmi.ChemComp.Group.Peptide
36
- assert group("PRO") == gemmi.ChemComp.Group.PPeptide
37
- assert group("U") == gemmi.ChemComp.Group.Rna
38
- assert group("DT") == gemmi.ChemComp.Group.Dna
39
- assert group("HOH") == gemmi.ChemComp.Group.NonPolymer
40
- assert group("NOT_IN_MONLIB") is None
41
-
42
-
43
- def test_protein():
44
- assert is_protein("GLY")
45
- assert is_protein("ALA")
46
- assert is_protein("MSE")
47
- assert is_protein("PRO")
48
- assert not is_protein("U")
49
- assert not is_protein("DT")
50
- assert not is_protein("HOH")
51
- assert not is_protein("NOT_IN_MONLIB")
52
-
53
-
54
- def test_nucleic():
55
- assert not is_nucleic("GLY")
56
- assert not is_nucleic("ALA")
57
- assert not is_nucleic("PRO")
58
- assert is_nucleic("U")
59
- assert is_nucleic("DT")
60
- assert not is_nucleic("HOH")
61
- assert not is_nucleic("NOT_IN_MONLIB")
37
+ assert code in monlib
38
+ assert "NOT_IN_MONLIB" not in monlib
39
+
40
+
41
+ def test_group(monlib: MonLib):
42
+ assert monlib.group("GLY") == gemmi.ChemComp.Group.Peptide
43
+ assert monlib.group("ALA") == gemmi.ChemComp.Group.Peptide
44
+ assert monlib.group("MSE") == gemmi.ChemComp.Group.Peptide
45
+ assert monlib.group("PRO") == gemmi.ChemComp.Group.PPeptide
46
+ assert monlib.group("U") == gemmi.ChemComp.Group.Rna
47
+ assert monlib.group("DT") == gemmi.ChemComp.Group.Dna
48
+ assert monlib.group("HOH") == gemmi.ChemComp.Group.NonPolymer
49
+ assert monlib.group("NOT_IN_MONLIB") == gemmi.ChemComp.Group.Null
50
+
51
+
52
+ def test_protein(monlib: MonLib):
53
+ assert monlib.is_protein("GLY")
54
+ assert monlib.is_protein("ALA")
55
+ assert monlib.is_protein("MSE")
56
+ assert monlib.is_protein("PRO")
57
+ assert not monlib.is_protein("U")
58
+ assert not monlib.is_protein("DT")
59
+ assert not monlib.is_protein("HOH")
60
+
61
+
62
+ def test_nucleic(monlib: MonLib):
63
+ assert not monlib.is_nucleic("GLY")
64
+ assert not monlib.is_nucleic("ALA")
65
+ assert not monlib.is_nucleic("PRO")
66
+ assert monlib.is_nucleic("U")
67
+ assert monlib.is_nucleic("DT")
68
+ assert not monlib.is_nucleic("HOH")
69
+
70
+
71
+ @pytest.mark.parametrize("code,expected", [("HOH", 18), ("2GP", 432)])
72
+ def test_volume(monlib: MonLib, code: str, expected: float):
73
+ assert math.isclose(monlib.volume(code), expected, abs_tol=0.01)
74
+
75
+
76
+ def test_not_in_monlib(monlib: MonLib):
77
+ with pytest.raises(KeyError):
78
+ monlib["NOT_IN_MONLIB"]
79
+
80
+
81
+ @pytest.mark.parametrize(
82
+ "code,expected",
83
+ [
84
+ ("ALA", 89.09),
85
+ ("ASP", 132.09),
86
+ ("ASN", 132.12),
87
+ ("UNK", 103.12),
88
+ ],
89
+ )
90
+ def test_weight(monlib: MonLib, code: str, expected: float):
91
+ assert math.isclose(monlib.weight(code), expected, abs_tol=0.01)
@@ -1,16 +1,18 @@
1
1
  import gemmi
2
+
2
3
  from modelcraft.jobs.freerflag import FreeRFlag
3
4
  from modelcraft.jobs.nautilus import Nautilus
4
5
  from modelcraft.jobs.refmac import Refmac
5
6
  from modelcraft.pipeline import Pipeline
6
7
  from modelcraft.reflections import DataItem
7
- from modelcraft.scripts.contents import _entry_contents
8
+ from modelcraft.scripts.contents import AsuContents
8
9
  from modelcraft.structure import (
9
- contains_residue,
10
10
  ModelStats,
11
+ contains_residue,
11
12
  read_structure,
12
13
  remove_residues,
13
14
  )
15
+
14
16
  from . import in_temp_directory, pdbe_download
15
17
 
16
18
 
@@ -27,7 +29,7 @@ def test_102d():
27
29
  fsigf = DataItem(mtz, "FP,SIGFP")
28
30
  freer = FreeRFlag(fsigf).run().freer
29
31
  refmac = Refmac(structure=structure, fsigf=fsigf, freer=freer, cycles=0).run()
30
- contents = _entry_contents("102d")
32
+ contents = AsuContents.from_pdbe("102d")
31
33
  pipeline = Pipeline(keep_jobs=True)
32
34
  # Test without an input structure
33
35
  nautilus = Nautilus(
@@ -0,0 +1,62 @@
1
+ import shutil
2
+
3
+ import gemmi
4
+ import pytest
5
+
6
+ from modelcraft.jobs.freerflag import FreeRFlag
7
+ from modelcraft.jobs.nucleofind import NucleoFindBuild, NucleoFindPredict
8
+ from modelcraft.jobs.refmac import Refmac
9
+ from modelcraft.pipeline import Pipeline
10
+ from modelcraft.reflections import DataItem
11
+ from modelcraft.scripts.contents import AsuContents
12
+ from modelcraft.structure import (
13
+ ModelStats,
14
+ contains_residue,
15
+ read_structure,
16
+ remove_residues,
17
+ )
18
+
19
+ from . import in_temp_directory, pdbe_download
20
+
21
+
22
+ @pytest.mark.skipif(not shutil.which("nucleofind"), reason="NucleoFind not installed")
23
+ @in_temp_directory
24
+ def test_102d():
25
+ # Prepare input data
26
+ pdbe_download("102d.cif")
27
+ structure = read_structure("102d.cif")
28
+ pdbe_download("r102dsf.ent")
29
+ doc = gemmi.cif.read("r102dsf.ent")
30
+ rblocks = gemmi.as_refln_blocks(doc)
31
+ cif2mtz = gemmi.CifToMtz()
32
+ mtz = cif2mtz.convert_block_to_mtz(rblocks[0])
33
+ fsigf = DataItem(mtz, "FP,SIGFP")
34
+ freer = FreeRFlag(fsigf).run().freer
35
+ refmac = Refmac(structure=structure, fsigf=fsigf, freer=freer, cycles=0).run()
36
+ contents = AsuContents.from_pdbe("102d")
37
+ pipeline = Pipeline(keep_jobs=True)
38
+ # Test without an input structure
39
+ prediction = NucleoFindPredict(fphi=refmac.fphi_best).run(pipeline)
40
+ build_result = NucleoFindBuild(
41
+ contents=contents,
42
+ fphi=refmac.fphi_best,
43
+ prediction=prediction,
44
+ ).run(pipeline)
45
+ stats = ModelStats(build_result.structure)
46
+ assert stats.residues > 12
47
+ # Test with an input structure
48
+ remove_residues(structure, ["HOH"])
49
+ build_result = NucleoFindBuild(
50
+ contents=contents,
51
+ fphi=refmac.fphi_best,
52
+ prediction=prediction,
53
+ structure=structure,
54
+ ).run(pipeline)
55
+ stats = ModelStats(build_result.structure)
56
+ assert contains_residue(build_result.structure, "DT")
57
+ assert stats.residues > 22
58
+ assert build_result.fragments_built > 2
59
+ assert build_result.residues_built > 22
60
+ assert build_result.residues_sequenced > 20
61
+ assert build_result.longest_fragment > 11
62
+ # TODO: assert contains_residue(nautilus.structure, "TNT")
@@ -1,7 +1,9 @@
1
1
  import gemmi
2
- from modelcraft.reflections import DataItem
2
+
3
3
  from modelcraft.contents import AsuContents
4
4
  from modelcraft.jobs.parrot import Parrot
5
+ from modelcraft.reflections import DataItem
6
+
5
7
  from . import ccp4_path
6
8
 
7
9
 
@@ -1,8 +1,10 @@
1
1
  import gemmi
2
+
2
3
  from modelcraft.jobs.phasematch import PhaseMatch
3
4
  from modelcraft.jobs.refmac import Refmac
4
5
  from modelcraft.reflections import DataItem
5
6
  from modelcraft.structure import read_structure
7
+
6
8
  from . import ccp4_path
7
9
 
8
10
 
@@ -0,0 +1,17 @@
1
+ from ...prune import prune
2
+ from ...structure import ModelStats
3
+ from . import insulin_refmac
4
+
5
+
6
+ def test_insulin_prune():
7
+ refmac = insulin_refmac()
8
+ pruned = prune(
9
+ structure=refmac.structure,
10
+ fphi_best=refmac.fphi_best,
11
+ fphi_diff=refmac.fphi_diff,
12
+ fphi_calc=refmac.fphi_calc,
13
+ residue_threshold=-2,
14
+ )
15
+ stats_in = ModelStats(refmac.structure)
16
+ stats_out = ModelStats(pruned)
17
+ assert stats_out.residues < stats_in.residues
@@ -1,9 +1,118 @@
1
1
  from typing import List
2
+
2
3
  import gemmi
3
- from modelcraft.reflections import DataItem, convert_to_fsigf_and_phifom
4
+ import pytest
5
+
6
+ from modelcraft.reflections import (
7
+ DataItem,
8
+ column_refs,
9
+ contract_label,
10
+ convert_to_fsigf_and_phifom,
11
+ expand_label,
12
+ )
13
+
4
14
  from . import ccp4_path
5
15
 
6
16
 
17
+ @pytest.mark.parametrize(
18
+ "label,expanded",
19
+ [
20
+ ("HL", "HLA,HLB,HLC,HLD"),
21
+ ("HLanom", "HLanomA,HLanomB,HLanomC,HLanomD"),
22
+ ("HLABCD.F_sigF", "HLABCD.F_sigF.F,HLABCD.F_sigF.sigF"),
23
+ ("parrot.ABCD", "parrot.ABCD.A,parrot.ABCD.B,parrot.ABCD.C,parrot.ABCD.D"),
24
+ ("parrot.F_phi", "parrot.F_phi.F,parrot.F_phi.phi"),
25
+ ("FreeR_flag", "FreeR_flag"),
26
+ ("prefix.HL", "prefix.HLA,prefix.HLB,prefix.HLC,prefix.HLD"),
27
+ ("prefix.label", "prefix.label"),
28
+ ("prefix_ABCD", "prefix_ABCD.A,prefix_ABCD.B,prefix_ABCD.C,prefix_ABCD.D"),
29
+ ("prefix_HL", "prefix_HLA,prefix_HLB,prefix_HLC,prefix_HLD"),
30
+ ("x.y.HL", "x.y.HLA,x.y.HLB,x.y.HLC,x.y.HLD"),
31
+ ("prefix.FreeR_flag", "prefix.FreeR_flag"),
32
+ ("prefix.I_sigI", "prefix.I_sigI.I,prefix.I_sigI.sigI"),
33
+ ("prefix.phi_fom", "prefix.phi_fom.phi,prefix.phi_fom.fom"),
34
+ ],
35
+ )
36
+ def test_expand_label(label: str, expanded: str):
37
+ assert expand_label(label) == expanded
38
+
39
+
40
+ @pytest.mark.parametrize(
41
+ "label,contracted",
42
+ [
43
+ ("FreeR_flag", "FreeR_flag"),
44
+ ("prefix.FreeR_flag", "prefix.FreeR_flag"),
45
+ ("prefix.F_phi.F,prefix.F_phi.phi", "prefix.F_phi"),
46
+ ("prefix.F_sigF.F,prefix.F_sigF.sigF", "prefix.F_sigF"),
47
+ ("prefix.I_sigI.I,prefix.I_sigI.sigI", "prefix.I_sigI"),
48
+ ("prefix.phi_fom.phi,prefix.phi_fom.fom", "prefix.phi_fom"),
49
+ ("prefix.ABCD.A,prefix.ABCD.B,prefix.ABCD.C,prefix.ABCD.D", "prefix.ABCD"),
50
+ ],
51
+ )
52
+ def test_contract_label(label: str, contracted: str):
53
+ assert contract_label(label) == contracted
54
+
55
+
56
+ @pytest.mark.parametrize(
57
+ "columns,project,crystal,dataset,label",
58
+ [
59
+ ("label", "", "", "", "label"),
60
+ ("/label", "", "", "", "label"),
61
+ ("/label/", "", "", "", "label"),
62
+ ("[label]", "", "", "", "label"),
63
+ ("[[label]]", "", "", "", "label"),
64
+ ("/*/*/*/*/*/*/*/*/*/[[label]]//", "", "", "", "label"),
65
+ ("dataset/label", "", "", "dataset", "label"),
66
+ ("crystal/dataset/label", "", "crystal", "dataset", "label"),
67
+ ("project/crystal/dataset/label", "project", "crystal", "dataset", "label"),
68
+ ],
69
+ )
70
+ def test_single_column_ref(
71
+ columns: str, project: str, crystal: str, dataset: str, label: str
72
+ ):
73
+ refs = column_refs(columns)
74
+ assert refs[0].project == project
75
+ assert refs[0].crystal == crystal
76
+ assert refs[0].dataset == dataset
77
+ assert refs[0].label == label
78
+
79
+
80
+ @pytest.mark.parametrize(
81
+ "columns",
82
+ [
83
+ ("label1,label2"),
84
+ ("[label1,label2]"),
85
+ ("/*/*/*/label1,label2"),
86
+ ("/*/*/*/[label1,label2]"),
87
+ ],
88
+ )
89
+ def test_multiple_column_refs(columns: str):
90
+ refs = column_refs(columns)
91
+ for ref in refs:
92
+ assert ref.project == ""
93
+ assert ref.crystal == ""
94
+ assert ref.dataset == ""
95
+ assert refs[0].label == "label1"
96
+ assert refs[1].label == "label2"
97
+
98
+
99
+ def test_column_refs_with_duplicate_labels():
100
+ refs1 = column_refs("/xtal/peak/[F(+),SIGF(+),F(-),SIGF(-)]")
101
+ refs2 = column_refs("/xtal/infl/[F(+),SIGF(+),F(-),SIGF(-)]")
102
+ labels = ["F(+)", "SIGF(+)", "F(-)", "SIGF(-)"]
103
+ assert len(refs1) == len(labels)
104
+ assert len(refs2) == len(labels)
105
+ for i, label in enumerate(labels):
106
+ assert refs1[i].project == ""
107
+ assert refs2[i].project == ""
108
+ assert refs1[i].crystal == "xtal"
109
+ assert refs2[i].crystal == "xtal"
110
+ assert refs1[i].dataset == "peak"
111
+ assert refs2[i].dataset == "infl"
112
+ assert refs1[i].label == label
113
+ assert refs2[i].label == label
114
+
115
+
7
116
  def search_test(
8
117
  mtz: gemmi.Mtz, types: str, expected: List[str], sequential: bool = True
9
118
  ) -> None:
@@ -1,8 +1,11 @@
1
1
  import math
2
+
2
3
  import gemmi
4
+
3
5
  from modelcraft.jobs.refmac import Refmac
4
6
  from modelcraft.reflections import DataItem
5
7
  from modelcraft.structure import read_structure
8
+
6
9
  from . import ccp4_path
7
10
 
8
11
 
@@ -1,10 +1,6 @@
1
1
  import pytest
2
- from modelcraft.contents import (
3
- code1_to_code3,
4
- guess_sequence_type,
5
- PolymerType,
6
- sequences_in_file,
7
- )
2
+
3
+ from modelcraft.sequence import PolymerType, sequences_in_file
8
4
 
9
5
 
10
6
  @pytest.mark.parametrize(
@@ -18,8 +14,8 @@ from modelcraft.contents import (
18
14
  ("GGGG", PolymerType.PROTEIN),
19
15
  ],
20
16
  )
21
- def test_guess_sequence_type(sequence: str, expected: PolymerType):
22
- assert guess_sequence_type(sequence) == expected
17
+ def test_polymer_type(sequence: str, expected: PolymerType):
18
+ assert PolymerType.guess(sequence) == expected
23
19
 
24
20
 
25
21
  @pytest.mark.parametrize(
@@ -27,19 +23,16 @@ def test_guess_sequence_type(sequence: str, expected: PolymerType):
27
23
  [
28
24
  ("A", PolymerType.PROTEIN, "ALA"),
29
25
  ("B", PolymerType.PROTEIN, "ASX"),
30
- ("J", PolymerType.PROTEIN, "UNK"),
31
26
  ("X", PolymerType.PROTEIN, "UNK"),
32
27
  ("Z", PolymerType.PROTEIN, "GLX"),
33
28
  ("A", PolymerType.RNA, "A"),
34
- ("J", PolymerType.RNA, "N"),
35
29
  ("X", PolymerType.RNA, "N"),
36
30
  ("A", PolymerType.DNA, "DA"),
37
- ("J", PolymerType.DNA, "DN"),
38
31
  ("X", PolymerType.DNA, "DN"),
39
32
  ],
40
33
  )
41
34
  def test_code1_to_code3(code1: str, polymer_type: PolymerType, expected: str):
42
- assert code1_to_code3(code1, polymer_type) == expected
35
+ assert polymer_type.codes[code1] == expected
43
36
 
44
37
 
45
38
  @pytest.mark.parametrize(
@@ -0,0 +1,52 @@
1
+ import gemmi
2
+
3
+ from modelcraft.jobs.servalcat import ServalcatFw
4
+ from modelcraft.reflections import DataItem
5
+
6
+ from . import ccp4_path
7
+
8
+
9
+ def ianom_test(path: str, label: str) -> None:
10
+ mtz = gemmi.read_mtz_file(path)
11
+ observations = DataItem(mtz, label)
12
+ servalcat = ServalcatFw(observations=observations).run()
13
+ assert servalcat.fmean.nreflections == observations.nreflections
14
+ assert servalcat.fanom.nreflections == observations.nreflections
15
+ assert servalcat.imean.nreflections == observations.nreflections
16
+
17
+
18
+ def imean_test(path: str, label: str) -> None:
19
+ mtz = gemmi.read_mtz_file(path)
20
+ observations = DataItem(mtz, label)
21
+ servalcat = ServalcatFw(observations=observations).run()
22
+ assert servalcat.fmean.nreflections == observations.nreflections
23
+ assert servalcat.fanom is None
24
+ assert servalcat.imean is None
25
+
26
+
27
+ def test_1rxf():
28
+ path = ccp4_path("examples", "data", "1rxf.mtz")
29
+ imean_test(path, "I,SIGI")
30
+
31
+
32
+ def test_ianom():
33
+ path = ccp4_path("examples", "data", "1vr7_lr_i.mtz")
34
+ imean_test(path, "IMEAN,SIGIMEAN")
35
+ ianom_test(path, "I(+),SIGI(+),I(-),SIGI(-)")
36
+
37
+
38
+ def test_deuterolysin():
39
+ path = ccp4_path("examples", "data", "deuterolysin.mtz")
40
+ imean_test(path, "IMEAN,SIGIMEAN")
41
+ ianom_test(path, "I(+),SIGI(+),I(-),SIGI(-)")
42
+
43
+
44
+ def test_gere():
45
+ path = ccp4_path("examples", "data", "gere.mtz")
46
+ imean_test(path, "IMEAN,SIGIMEAN")
47
+ ianom_test(path, "I(+),SIGI(+),I(-),SIGI(-)")
48
+
49
+
50
+ def test_insulin():
51
+ path = ccp4_path("examples", "data", "insulin.mtz")
52
+ imean_test(path, "IMEAN,SIGIMEAN")
@@ -1,7 +1,9 @@
1
1
  import gemmi
2
+
2
3
  from modelcraft.jobs.sheetbend import Sheetbend
3
4
  from modelcraft.reflections import DataItem
4
- from modelcraft.structure import ModelStats, read_structure
5
+ from modelcraft.structure import read_structure
6
+
5
7
  from . import ccp4_path
6
8
 
7
9
 
@@ -12,5 +14,4 @@ def test_1rxf():
12
14
  freer = DataItem(mtz, "FreeR_flag")
13
15
  pdb_path = ccp4_path("examples", "data", "1rxf_randomise.pdb")
14
16
  structure = read_structure(pdb_path)
15
- sheetbend = Sheetbend(structure=structure, fsigf=fsigf, freer=freer).run()
16
- assert ModelStats(structure) == ModelStats(sheetbend.structure)
17
+ Sheetbend(structure=structure, fsigf=fsigf, freer=freer).run()
@@ -0,0 +1,25 @@
1
+ from pathlib import Path
2
+ from tempfile import TemporaryDirectory
3
+
4
+ import gemmi
5
+
6
+ from modelcraft.reflections import write_mtz
7
+ from modelcraft.scripts.sidechains import any_missing_side_chains
8
+ from modelcraft.scripts.sidechains import main as fix_side_chains
9
+ from modelcraft.structure import write_mmcif
10
+
11
+ from . import insulin_refmac
12
+
13
+
14
+ def test_insulin():
15
+ refmac = insulin_refmac()
16
+ assert any_missing_side_chains(refmac.structure)
17
+ with TemporaryDirectory() as tempdir:
18
+ xyzin = str(Path(tempdir, "input.cif"))
19
+ hklin = str(Path(tempdir, "input.mtz"))
20
+ xyzout = str(Path(tempdir, "output.cif"))
21
+ write_mmcif(xyzin, refmac.structure)
22
+ write_mtz(hklin, [refmac.fphi_best], ["FWT,PHWT"])
23
+ fix_side_chains([xyzin, hklin, xyzout])
24
+ structure = gemmi.read_structure(xyzout)
25
+ assert not any_missing_side_chains(structure)
@@ -1,30 +1,16 @@
1
- import math
1
+ import gemmi
2
2
  import pytest
3
- from modelcraft.contents import Polymer, PolymerType
4
- from modelcraft.solvent import _library_volume, _library_weight, _polymer_weight
5
3
 
4
+ from modelcraft.contents import AsuContents
5
+ from modelcraft.solvent import solvent_fraction
6
6
 
7
- @pytest.mark.parametrize(
8
- "code,expected",
9
- [
10
- ("ALA", 89.09),
11
- ("ASP", 132.09),
12
- ("ASN", 132.12),
13
- ("UNK", 103.12),
14
- ],
15
- )
16
- def test_library_weight(code: str, expected: float):
17
- weight = _library_weight(code)
18
- assert math.isclose(weight, expected, abs_tol=0.01)
19
7
 
20
-
21
- @pytest.mark.parametrize("code,expected", [("HOH", 18), ("2GP", 432)])
22
- def test_library_volume(code: str, expected: float):
23
- volume = _library_volume(code)
24
- assert math.isclose(volume, expected, abs_tol=0.01)
25
-
26
-
27
- def test_polymer_weight():
28
- polymer = Polymer("GG", polymer_type=PolymerType.PROTEIN)
29
- weight = _polymer_weight(polymer)
30
- assert math.isclose(weight, 132.12, abs_tol=0.01)
8
+ def test_1o6a():
9
+ contents = AsuContents.from_pdbe("1o6a")
10
+ cell = gemmi.UnitCell(61.481, 61.481, 113.148, 90, 90, 90)
11
+ spacegroup = gemmi.SpaceGroup("P 41 21 2")
12
+ fraction = solvent_fraction(contents, cell, spacegroup, resolution=1.85)
13
+ assert fraction == pytest.approx(0.5, abs=0.1)
14
+ contents.copies = None
15
+ guessed = solvent_fraction(contents, cell, spacegroup, resolution=1.85)
16
+ assert guessed == fraction
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from ...structure import read_structure
3
4
  from . import ccp4_path
4
5
 
@@ -0,0 +1,19 @@
1
+ import math
2
+
3
+ import numpy as np
4
+
5
+ from ...monlib import MonLib
6
+ from ...validation import validate_refmac
7
+ from . import insulin_refmac
8
+
9
+
10
+ def test_insulin():
11
+ refmac = insulin_refmac()
12
+ monlib = MonLib(refmac.structure[0].get_all_residue_names())
13
+ metrics = validate_refmac(refmac, monlib)
14
+ assert len(metrics) > 0
15
+ assert math.isclose(np.median(metrics["BFac"]), 0)
16
+ assert math.isclose(np.median(metrics["RSCC"]), 0)
17
+ assert math.isclose(np.median(metrics["Diff"]), 0)
18
+ assert math.isclose(np.median(metrics["Geom"]), 0)
19
+ assert math.isclose(np.median(metrics["Score"]), 0)