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.
- modelcraft/__init__.py +16 -31
- modelcraft/__main__.py +0 -1
- modelcraft/arguments.py +35 -7
- modelcraft/combine.py +22 -41
- modelcraft/contents.py +188 -164
- modelcraft/environ.py +0 -7
- modelcraft/geometry.py +39 -27
- modelcraft/job.py +6 -5
- modelcraft/jobs/acedrg.py +2 -0
- modelcraft/jobs/buccaneer.py +22 -4
- modelcraft/jobs/comit.py +2 -0
- modelcraft/jobs/ctruncate.py +3 -1
- modelcraft/jobs/emda.py +2 -0
- modelcraft/jobs/findwaters.py +2 -0
- modelcraft/jobs/freerflag.py +2 -0
- modelcraft/jobs/libg.py +2 -0
- modelcraft/jobs/molrep.py +2 -0
- modelcraft/jobs/nautilus.py +28 -14
- modelcraft/jobs/nucleofind.py +88 -0
- modelcraft/jobs/parrot.py +13 -2
- modelcraft/jobs/phasematch.py +2 -1
- modelcraft/jobs/refmac.py +3 -1
- modelcraft/jobs/servalcat.py +36 -2
- modelcraft/jobs/sheetbend.py +2 -0
- modelcraft/modelcraftem.py +49 -6
- modelcraft/modelcraftxray.py +90 -42
- modelcraft/monlib.py +55 -52
- modelcraft/pdbe.py +54 -0
- modelcraft/pipeline.py +1 -1
- modelcraft/prune.py +69 -0
- modelcraft/reflections.py +11 -1
- modelcraft/scripts/contents.py +5 -215
- modelcraft/scripts/copies.py +26 -17
- modelcraft/scripts/modelcraft.py +1 -0
- modelcraft/scripts/sidechains.py +141 -0
- modelcraft/scripts/validate.py +81 -0
- modelcraft/sequence.py +106 -0
- modelcraft/solvent.py +42 -113
- modelcraft/structure.py +64 -41
- modelcraft/tests/ccp4/__init__.py +7 -11
- modelcraft/tests/ccp4/test_acedrg.py +2 -0
- modelcraft/tests/ccp4/test_arguments.py +3 -0
- modelcraft/tests/ccp4/test_buccaneer.py +3 -2
- modelcraft/tests/ccp4/test_cell.py +4 -1
- modelcraft/tests/ccp4/test_comit.py +2 -0
- modelcraft/tests/ccp4/test_contents.py +99 -17
- modelcraft/tests/ccp4/test_copies.py +1 -0
- modelcraft/tests/ccp4/test_ctruncate.py +2 -0
- modelcraft/tests/ccp4/test_findwaters.py +2 -0
- modelcraft/tests/ccp4/test_freerflag.py +2 -0
- modelcraft/tests/ccp4/test_libg.py +1 -0
- modelcraft/tests/ccp4/test_molrep.py +3 -0
- modelcraft/tests/ccp4/test_monlib.py +75 -45
- modelcraft/tests/ccp4/test_nautilus.py +5 -3
- modelcraft/tests/ccp4/test_nucleofind.py +62 -0
- modelcraft/tests/ccp4/test_parrot.py +3 -1
- modelcraft/tests/ccp4/test_phasematch.py +2 -0
- modelcraft/tests/ccp4/test_prune.py +17 -0
- modelcraft/tests/ccp4/test_reflections.py +110 -1
- modelcraft/tests/ccp4/test_refmac.py +3 -0
- modelcraft/tests/{unittests/test_contents.py → ccp4/test_sequence.py} +5 -12
- modelcraft/tests/ccp4/test_servalcat.py +52 -0
- modelcraft/tests/ccp4/test_sheetbend.py +4 -3
- modelcraft/tests/ccp4/test_sidechains.py +25 -0
- modelcraft/tests/ccp4/test_solvent.py +12 -26
- modelcraft/tests/ccp4/test_structure.py +1 -0
- modelcraft/tests/ccp4/test_validation.py +19 -0
- modelcraft/tests/ccp4/test_xray.py +12 -6
- modelcraft/tests/ccpem/test_em.py +3 -0
- modelcraft/tests/ccpem/test_emda.py +2 -0
- modelcraft/tests/ccpem/test_refmac.py +1 -0
- modelcraft/tests/ccpem/test_servalcat.py +4 -3
- modelcraft/utils.py +16 -4
- modelcraft/validation.py +101 -0
- modelcraft-6.0.0.dist-info/METADATA +76 -0
- modelcraft-6.0.0.dist-info/RECORD +85 -0
- {modelcraft-5.0.3.dist-info → modelcraft-6.0.0.dist-info}/WHEEL +1 -1
- {modelcraft-5.0.3.dist-info → modelcraft-6.0.0.dist-info}/entry_points.txt +2 -0
- modelcraft/coot/prune.py +0 -1085
- modelcraft/coot/sidechains.py +0 -68
- modelcraft/jobs/acorn.py +0 -114
- modelcraft/jobs/coot.py +0 -104
- modelcraft/tests/ccp4/test_coot.py +0 -29
- modelcraft/tests/ccp4/test_geometry.py +0 -20
- modelcraft/tests/unittests/__init__.py +0 -0
- modelcraft/tests/unittests/test_reflections.py +0 -101
- modelcraft-5.0.3.dist-info/METADATA +0 -49
- modelcraft-5.0.3.dist-info/RECORD +0 -82
- modelcraft-5.0.3.dist-info/licenses/LICENSE +0 -504
- {modelcraft-5.0.3.dist-info → modelcraft-6.0.0.dist-info}/top_level.txt +0 -0
modelcraft/coot/sidechains.py
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
RESIDUES_WITH_SIDECHAINS = {
|
|
2
|
-
"ARG",
|
|
3
|
-
"ASN",
|
|
4
|
-
"ASP",
|
|
5
|
-
"CYS",
|
|
6
|
-
"GLN",
|
|
7
|
-
"GLU",
|
|
8
|
-
"HIS",
|
|
9
|
-
"ILE",
|
|
10
|
-
"LEU",
|
|
11
|
-
"LYS",
|
|
12
|
-
"MET",
|
|
13
|
-
"MSE",
|
|
14
|
-
"PHE",
|
|
15
|
-
"PRO",
|
|
16
|
-
"SER",
|
|
17
|
-
"THR",
|
|
18
|
-
"TRP",
|
|
19
|
-
"TYR",
|
|
20
|
-
"VAL",
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def neighbours_specs(residue):
|
|
25
|
-
specs = [residue.spec]
|
|
26
|
-
if residue.prev is not None:
|
|
27
|
-
specs = [residue.prev.spec] + specs
|
|
28
|
-
if residue.next is not None:
|
|
29
|
-
specs = specs + [residue.next.spec]
|
|
30
|
-
return specs
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def refine(imol, specs):
|
|
34
|
-
if COOT1:
|
|
35
|
-
coot_utils.with_auto_accept([refine_residues_py, imol, specs])
|
|
36
|
-
else:
|
|
37
|
-
with AutoAccept():
|
|
38
|
-
refine_residues_py(imol, specs)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def fix_side_chain(imol, imap, residue):
|
|
42
|
-
spec = residue.spec
|
|
43
|
-
delete_residue_sidechain(imol, spec[0], spec[1], spec[2], 0)
|
|
44
|
-
neighbours = neighbours_specs(residue)
|
|
45
|
-
refine(imol, neighbours)
|
|
46
|
-
fill_partial_residue(imol, *spec)
|
|
47
|
-
if COOT1:
|
|
48
|
-
auto_fit_best_rotamer(imol, spec[0], spec[1], spec[2], "", imap, 1, 0.1)
|
|
49
|
-
else:
|
|
50
|
-
auto_fit_best_rotamer(spec[1], "", spec[2], spec[0], imol, imap, 1, 0.1)
|
|
51
|
-
refine(imol, neighbours)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def fix_side_chains(imol, imap, imap_diff):
|
|
55
|
-
model = Model(imol, imap, imap_diff)
|
|
56
|
-
main_median = median([r.main_chain_correctness for r in model.residues])
|
|
57
|
-
side_median = median([r.side_chain_correctness for r in model.residues if r.truncatable])
|
|
58
|
-
if side_median is None:
|
|
59
|
-
return
|
|
60
|
-
main_threshold = main_median * 0.25
|
|
61
|
-
side_threshold = side_median * 0.25
|
|
62
|
-
for residue in model.residues:
|
|
63
|
-
if (
|
|
64
|
-
residue.name in RESIDUES_WITH_SIDECHAINS
|
|
65
|
-
and residue.main_chain_correctness > main_threshold
|
|
66
|
-
and ((not residue.truncatable) or (residue.truncatable and residue.side_chain_correctness < side_threshold))
|
|
67
|
-
):
|
|
68
|
-
fix_side_chain(imol, imap, residue)
|
modelcraft/jobs/acorn.py
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
# from .job import Job
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
# class Acorn(Job):
|
|
5
|
-
# def __init__(self):
|
|
6
|
-
# super().__init__()
|
|
7
|
-
# self.finish()
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# /home/paul/Programs/ccp4-7.0/bin/mtzdump \
|
|
11
|
-
# HKLIN "/home/paul/Desktop/tmp.mtz" \
|
|
12
|
-
# << EOF
|
|
13
|
-
# END
|
|
14
|
-
# EOF
|
|
15
|
-
|
|
16
|
-
# /home/paul/Programs/ccp4-7.0/bin/unique \
|
|
17
|
-
# HKLOUT "/tmp/paul/TEST_2_2_mtz.tmp" \
|
|
18
|
-
# << EOF
|
|
19
|
-
# cell 40.4450 42.6790 56.6510 90.0000 90.0000 90.0000
|
|
20
|
-
# symmetry 'P 21 21 21'
|
|
21
|
-
# resolution 1.0
|
|
22
|
-
# title [No title given]
|
|
23
|
-
# labout F=F_unique SIGF=SIGF_unique
|
|
24
|
-
# end
|
|
25
|
-
# EOF
|
|
26
|
-
|
|
27
|
-
# /home/paul/Programs/ccp4-7.0/bin/cad \
|
|
28
|
-
# HKLIN1 "/home/paul/Desktop/tmp.mtz" \
|
|
29
|
-
# HKLIN2 "/tmp/paul/TEST_2_2_mtz.tmp" \
|
|
30
|
-
# HKLOUT "/tmp/paul/TEST_2_5_mtz.tmp" \
|
|
31
|
-
# << EOF
|
|
32
|
-
# LABIN FILE 1 ALL
|
|
33
|
-
# LABIN FILE 2 ALL
|
|
34
|
-
# END
|
|
35
|
-
# EOF
|
|
36
|
-
|
|
37
|
-
# /home/paul/Programs/ccp4-7.0/bin/mtzutils \
|
|
38
|
-
# HKLIN "/tmp/paul/TEST_2_5_mtz.tmp" \
|
|
39
|
-
# HKLOUT "/tmp/paul/TEST_2_7_mtz.tmp" \
|
|
40
|
-
# << EOF
|
|
41
|
-
# EXCL F_unique SIGF_unique
|
|
42
|
-
# END
|
|
43
|
-
# EOF
|
|
44
|
-
|
|
45
|
-
# /home/paul/Programs/ccp4-7.0/bin/phaser \
|
|
46
|
-
# << EOF
|
|
47
|
-
# MODE MR_ANO
|
|
48
|
-
# HKLIN "/tmp/paul/TEST_2_7_mtz.tmp"
|
|
49
|
-
# LABIN FP=FP SIGFP=SIGFP
|
|
50
|
-
# ROOT "/home/paul/Desktop/TEST_2"
|
|
51
|
-
# EOF
|
|
52
|
-
|
|
53
|
-
# /home/paul/Programs/ccp4-7.0/bin/ecalc \
|
|
54
|
-
# HKLIN "/home/paul/Desktop/TEST_2.mtz" \
|
|
55
|
-
# HKLOUT "/home/paul/Desktop/tmp_ecalc1.mtz" \
|
|
56
|
-
# << EOF
|
|
57
|
-
# title [No title given]
|
|
58
|
-
# labin FP=FP_ISO SIGFP=SIGFP_ISO
|
|
59
|
-
# labout FECALC=F_ECALC E=E_ISO SIGE=SIGE_ISO
|
|
60
|
-
# spacegroup 'P 21 21 21'
|
|
61
|
-
# EOF
|
|
62
|
-
|
|
63
|
-
# /home/paul/Programs/ccp4-7.0/bin/acorn \
|
|
64
|
-
# HKLIN "/home/paul/Desktop/tmp_ecalc1.mtz" \
|
|
65
|
-
# HKLOUT "/home/paul/Desktop/tmp_acorn1.mtz" \
|
|
66
|
-
# << EOF
|
|
67
|
-
# title [No title given]
|
|
68
|
-
# labin FP=FP_ISO SIGFP=SIGFP_ISO E=E_ISO PHIN=hltofom.Phi_fom.phi WTIN=hltofom.Phi_fom.fom
|
|
69
|
-
# labout PHIOUT=PHIOUT WTOUT=WTOUT
|
|
70
|
-
|
|
71
|
-
# #General ACORN keywords
|
|
72
|
-
|
|
73
|
-
# #Select Reflection Data
|
|
74
|
-
# EXTEND
|
|
75
|
-
|
|
76
|
-
# #Select Model Parameters
|
|
77
|
-
|
|
78
|
-
# #ACORN-MR keywords
|
|
79
|
-
|
|
80
|
-
# #ACORN-PHASE keywords
|
|
81
|
-
# NTRY 10
|
|
82
|
-
|
|
83
|
-
# END
|
|
84
|
-
# EOF
|
|
85
|
-
|
|
86
|
-
# /home/paul/Programs/ccp4-7.0/bin/fft \
|
|
87
|
-
# HKLIN "/home/paul/Desktop/tmp_acorn1.mtz" \
|
|
88
|
-
# MAPOUT "/tmp/paul/TEST_2_11_map.tmp" \
|
|
89
|
-
# << EOF
|
|
90
|
-
# title [No title given]
|
|
91
|
-
# labin -
|
|
92
|
-
# F1=E_ISO SIG1=SIGE_ISO PHI=PHIOUT W=WTOUT
|
|
93
|
-
# end
|
|
94
|
-
# EOF
|
|
95
|
-
|
|
96
|
-
# /home/paul/Programs/ccp4-7.0/bin/mapmask \
|
|
97
|
-
# MAPIN "/tmp/paul/TEST_2_11_map.tmp" \
|
|
98
|
-
# MAPOUT "/tmp/paul/TEST_2.map" \
|
|
99
|
-
# << EOF
|
|
100
|
-
# SYMMETRY 'P 21 21 21'
|
|
101
|
-
# XYZLIM ASU
|
|
102
|
-
# EOF
|
|
103
|
-
|
|
104
|
-
# /home/paul/Programs/ccp4-7.0/bin/peakmax \
|
|
105
|
-
# MAPIN "/tmp/paul/TEST_2.map" \
|
|
106
|
-
# XYZOUT "/home/paul/Desktop/TEST_2.pdb" \
|
|
107
|
-
# XYZFRC "/home/paul/Desktop/TEST_2.ha" \
|
|
108
|
-
# << EOF
|
|
109
|
-
# threshhold -
|
|
110
|
-
# rms -
|
|
111
|
-
# 5.0
|
|
112
|
-
# numpeaks 40
|
|
113
|
-
# output brookhaven frac
|
|
114
|
-
# EOF
|
modelcraft/jobs/coot.py
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import dataclasses
|
|
2
|
-
import os
|
|
3
|
-
import gemmi
|
|
4
|
-
from ..job import Job
|
|
5
|
-
from ..reflections import DataItem, write_mtz
|
|
6
|
-
from ..structure import read_structure, write_mmcif
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@dataclasses.dataclass
|
|
10
|
-
class CootResult:
|
|
11
|
-
structure: gemmi.Structure
|
|
12
|
-
seconds: float
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class Coot(Job):
|
|
16
|
-
def __init__(self, script: str, structures: list, fphis: list):
|
|
17
|
-
super().__init__("coot")
|
|
18
|
-
self.script = script
|
|
19
|
-
self.structures = structures
|
|
20
|
-
self.fphis = fphis
|
|
21
|
-
|
|
22
|
-
def _setup(self) -> None:
|
|
23
|
-
script_lines = [
|
|
24
|
-
"try:\n",
|
|
25
|
-
" COOT1 = True\n",
|
|
26
|
-
" try:\n",
|
|
27
|
-
" import coot_utils\n",
|
|
28
|
-
" except NameError:\n",
|
|
29
|
-
" COOT1 = False\n",
|
|
30
|
-
" if COOT1:\n",
|
|
31
|
-
" from coot import *\n",
|
|
32
|
-
" turn_off_backup(0)\n",
|
|
33
|
-
]
|
|
34
|
-
for i, structure in enumerate(self.structures):
|
|
35
|
-
write_mmcif(self._path(f"xyzin{i}.cif"), structure)
|
|
36
|
-
script_lines += [
|
|
37
|
-
f" IMOL{i} = handle_read_draw_molecule('xyzin{i}.cif')\n"
|
|
38
|
-
]
|
|
39
|
-
for i, fphi in enumerate(self.fphis):
|
|
40
|
-
write_mtz(self._path(f"hklin{i}.mtz"), [fphi])
|
|
41
|
-
script_lines += [
|
|
42
|
-
f" IMAP{i} = make_and_draw_map('hklin{i}.mtz', "
|
|
43
|
-
f"'{fphi.label(0)}', '{fphi.label(1)}', '', 0, 0)\n"
|
|
44
|
-
]
|
|
45
|
-
script_lines += [" set_imol_refinement_map(IMAP0)\n"]
|
|
46
|
-
for line in self.script.split("\n"):
|
|
47
|
-
script_lines += [f" {line}\n"]
|
|
48
|
-
script_lines += [
|
|
49
|
-
" write_cif_file(IMOL0, 'xyzout.cif')\n",
|
|
50
|
-
" coot_real_exit(0)\n",
|
|
51
|
-
"except:\n",
|
|
52
|
-
" import traceback\n",
|
|
53
|
-
" traceback.print_exc()\n",
|
|
54
|
-
" coot_real_exit(1)\n",
|
|
55
|
-
]
|
|
56
|
-
with open(self._path("script.py"), "w") as script_file:
|
|
57
|
-
script_file.writelines(script_lines)
|
|
58
|
-
self._args += ["--no-graphics"]
|
|
59
|
-
self._args += ["--no-guano"]
|
|
60
|
-
self._args += ["--no-state-script"]
|
|
61
|
-
self._args += ["--script", "script.py"]
|
|
62
|
-
|
|
63
|
-
def _result(self) -> CootResult:
|
|
64
|
-
self._check_files_exist("xyzout.cif")
|
|
65
|
-
return CootResult(
|
|
66
|
-
structure=read_structure(self._path("xyzout.cif")),
|
|
67
|
-
seconds=self._seconds,
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class Prune(Coot):
|
|
72
|
-
def __init__(
|
|
73
|
-
self,
|
|
74
|
-
structure: gemmi.Structure,
|
|
75
|
-
fphi_best: DataItem,
|
|
76
|
-
fphi_diff: DataItem,
|
|
77
|
-
chains_only: bool = False,
|
|
78
|
-
):
|
|
79
|
-
path = os.path.join(os.path.dirname(__file__), "..", "coot", "prune.py")
|
|
80
|
-
with open(path) as stream:
|
|
81
|
-
script = stream.read()
|
|
82
|
-
if chains_only:
|
|
83
|
-
script += "prune(IMOL0, IMAP0, IMAP1, residues=False, sidechains=False)\n"
|
|
84
|
-
else:
|
|
85
|
-
script += "prune(IMOL0, IMAP0, IMAP1)\n"
|
|
86
|
-
super().__init__(
|
|
87
|
-
script=script, structures=[structure], fphis=[fphi_best, fphi_diff]
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
class FixSideChains(Coot):
|
|
92
|
-
def __init__(
|
|
93
|
-
self, structure: gemmi.Structure, fphi_best: DataItem, fphi_diff: DataItem
|
|
94
|
-
):
|
|
95
|
-
path = os.path.join(os.path.dirname(__file__), "..", "coot", "prune.py")
|
|
96
|
-
with open(path) as stream:
|
|
97
|
-
script = stream.read()
|
|
98
|
-
path = os.path.join(os.path.dirname(__file__), "..", "coot", "sidechains.py")
|
|
99
|
-
with open(path) as stream:
|
|
100
|
-
script += "\n\n%s\n" % stream.read()
|
|
101
|
-
script += "fix_side_chains(IMOL0, IMAP0, IMAP1)\n"
|
|
102
|
-
super().__init__(
|
|
103
|
-
script=script, structures=[structure], fphis=[fphi_best, fphi_diff]
|
|
104
|
-
)
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from modelcraft.jobs.coot import Prune, FixSideChains
|
|
2
|
-
from modelcraft.structure import ModelStats
|
|
3
|
-
from . import insulin_refmac
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def test_insulin_prune():
|
|
7
|
-
refmac = insulin_refmac()
|
|
8
|
-
refmac.structure.remove_alternative_conformations()
|
|
9
|
-
coot = Prune(
|
|
10
|
-
structure=refmac.structure,
|
|
11
|
-
fphi_best=refmac.fphi_best,
|
|
12
|
-
fphi_diff=refmac.fphi_diff,
|
|
13
|
-
).run()
|
|
14
|
-
stats_in = ModelStats(refmac.structure)
|
|
15
|
-
stats_out = ModelStats(coot.structure)
|
|
16
|
-
assert stats_out.residues < stats_in.residues
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def test_insulin_fix_side_chains():
|
|
20
|
-
refmac = insulin_refmac()
|
|
21
|
-
refmac.structure.remove_alternative_conformations()
|
|
22
|
-
coot = FixSideChains(
|
|
23
|
-
structure=refmac.structure,
|
|
24
|
-
fphi_best=refmac.fphi_best,
|
|
25
|
-
fphi_diff=refmac.fphi_diff,
|
|
26
|
-
).run()
|
|
27
|
-
stats_in = ModelStats(refmac.structure)
|
|
28
|
-
stats_out = ModelStats(coot.structure)
|
|
29
|
-
assert stats_out.residues == stats_in.residues
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import gemmi
|
|
2
|
-
from modelcraft.structure import read_structure
|
|
3
|
-
from modelcraft.geometry import rmsz
|
|
4
|
-
from . import ccp4_path
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def test_standard():
|
|
8
|
-
path = ccp4_path("examples", "data", "2eck.pdb")
|
|
9
|
-
structure = read_structure(path)
|
|
10
|
-
assert 0 < rmsz(structure) < 2
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def test_with_unl():
|
|
14
|
-
path = ccp4_path("examples", "data", "2eck.pdb")
|
|
15
|
-
structure = read_structure(path)
|
|
16
|
-
residue = gemmi.Residue()
|
|
17
|
-
residue.name = "UNL"
|
|
18
|
-
residue.seqid = gemmi.SeqId(999, " ")
|
|
19
|
-
structure[0][0].add_residue(residue)
|
|
20
|
-
assert 0 < rmsz(structure) < 2
|
|
File without changes
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from modelcraft.reflections import column_refs, expand_label, contract_label
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
@pytest.mark.parametrize(
|
|
6
|
-
"label,expanded",
|
|
7
|
-
[
|
|
8
|
-
("HL", "HLA,HLB,HLC,HLD"),
|
|
9
|
-
("HLanom", "HLanomA,HLanomB,HLanomC,HLanomD"),
|
|
10
|
-
("HLABCD.F_sigF", "HLABCD.F_sigF.F,HLABCD.F_sigF.sigF"),
|
|
11
|
-
("parrot.ABCD", "parrot.ABCD.A,parrot.ABCD.B,parrot.ABCD.C,parrot.ABCD.D"),
|
|
12
|
-
("parrot.F_phi", "parrot.F_phi.F,parrot.F_phi.phi"),
|
|
13
|
-
("FreeR_flag", "FreeR_flag"),
|
|
14
|
-
("prefix.HL", "prefix.HLA,prefix.HLB,prefix.HLC,prefix.HLD"),
|
|
15
|
-
("prefix.label", "prefix.label"),
|
|
16
|
-
("prefix_ABCD", "prefix_ABCD.A,prefix_ABCD.B,prefix_ABCD.C,prefix_ABCD.D"),
|
|
17
|
-
("prefix_HL", "prefix_HLA,prefix_HLB,prefix_HLC,prefix_HLD"),
|
|
18
|
-
("x.y.HL", "x.y.HLA,x.y.HLB,x.y.HLC,x.y.HLD"),
|
|
19
|
-
("prefix.FreeR_flag", "prefix.FreeR_flag"),
|
|
20
|
-
("prefix.I_sigI", "prefix.I_sigI.I,prefix.I_sigI.sigI"),
|
|
21
|
-
("prefix.phi_fom", "prefix.phi_fom.phi,prefix.phi_fom.fom"),
|
|
22
|
-
],
|
|
23
|
-
)
|
|
24
|
-
def test_expand_label(label: str, expanded: str):
|
|
25
|
-
assert expand_label(label) == expanded
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
@pytest.mark.parametrize(
|
|
29
|
-
"label,contracted",
|
|
30
|
-
[
|
|
31
|
-
("FreeR_flag", "FreeR_flag"),
|
|
32
|
-
("prefix.FreeR_flag", "prefix.FreeR_flag"),
|
|
33
|
-
("prefix.F_phi.F,prefix.F_phi.phi", "prefix.F_phi"),
|
|
34
|
-
("prefix.F_sigF.F,prefix.F_sigF.sigF", "prefix.F_sigF"),
|
|
35
|
-
("prefix.I_sigI.I,prefix.I_sigI.sigI", "prefix.I_sigI"),
|
|
36
|
-
("prefix.phi_fom.phi,prefix.phi_fom.fom", "prefix.phi_fom"),
|
|
37
|
-
("prefix.ABCD.A,prefix.ABCD.B,prefix.ABCD.C,prefix.ABCD.D", "prefix.ABCD"),
|
|
38
|
-
],
|
|
39
|
-
)
|
|
40
|
-
def test_contract_label(label: str, contracted: str):
|
|
41
|
-
assert contract_label(label) == contracted
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@pytest.mark.parametrize(
|
|
45
|
-
"columns,project,crystal,dataset,label",
|
|
46
|
-
[
|
|
47
|
-
("label", "", "", "", "label"),
|
|
48
|
-
("/label", "", "", "", "label"),
|
|
49
|
-
("/label/", "", "", "", "label"),
|
|
50
|
-
("[label]", "", "", "", "label"),
|
|
51
|
-
("[[label]]", "", "", "", "label"),
|
|
52
|
-
("/*/*/*/*/*/*/*/*/*/[[label]]//", "", "", "", "label"),
|
|
53
|
-
("dataset/label", "", "", "dataset", "label"),
|
|
54
|
-
("crystal/dataset/label", "", "crystal", "dataset", "label"),
|
|
55
|
-
("project/crystal/dataset/label", "project", "crystal", "dataset", "label"),
|
|
56
|
-
],
|
|
57
|
-
)
|
|
58
|
-
def test_single_column_ref(
|
|
59
|
-
columns: str, project: str, crystal: str, dataset: str, label: str
|
|
60
|
-
):
|
|
61
|
-
refs = column_refs(columns)
|
|
62
|
-
assert refs[0].project == project
|
|
63
|
-
assert refs[0].crystal == crystal
|
|
64
|
-
assert refs[0].dataset == dataset
|
|
65
|
-
assert refs[0].label == label
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
@pytest.mark.parametrize(
|
|
69
|
-
"columns",
|
|
70
|
-
[
|
|
71
|
-
("label1,label2"),
|
|
72
|
-
("[label1,label2]"),
|
|
73
|
-
("/*/*/*/label1,label2"),
|
|
74
|
-
("/*/*/*/[label1,label2]"),
|
|
75
|
-
],
|
|
76
|
-
)
|
|
77
|
-
def test_multiple_column_refs(columns: str):
|
|
78
|
-
refs = column_refs(columns)
|
|
79
|
-
for ref in refs:
|
|
80
|
-
assert ref.project == ""
|
|
81
|
-
assert ref.crystal == ""
|
|
82
|
-
assert ref.dataset == ""
|
|
83
|
-
assert refs[0].label == "label1"
|
|
84
|
-
assert refs[1].label == "label2"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def test_column_refs_with_duplicate_labels():
|
|
88
|
-
refs1 = column_refs("/xtal/peak/[F(+),SIGF(+),F(-),SIGF(-)]")
|
|
89
|
-
refs2 = column_refs("/xtal/infl/[F(+),SIGF(+),F(-),SIGF(-)]")
|
|
90
|
-
labels = ["F(+)", "SIGF(+)", "F(-)", "SIGF(-)"]
|
|
91
|
-
assert len(refs1) == len(labels)
|
|
92
|
-
assert len(refs2) == len(labels)
|
|
93
|
-
for i in range(len(labels)):
|
|
94
|
-
assert refs1[i].project == ""
|
|
95
|
-
assert refs2[i].project == ""
|
|
96
|
-
assert refs1[i].crystal == "xtal"
|
|
97
|
-
assert refs2[i].crystal == "xtal"
|
|
98
|
-
assert refs1[i].dataset == "peak"
|
|
99
|
-
assert refs2[i].dataset == "infl"
|
|
100
|
-
assert refs1[i].label == labels[i]
|
|
101
|
-
assert refs2[i].label == labels[i]
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: modelcraft
|
|
3
|
-
Version: 5.0.3
|
|
4
|
-
Summary: Automated model building pipeline for X-ray crystallography
|
|
5
|
-
Home-page: https://github.com/paulsbond/modelcraft
|
|
6
|
-
Author: Paul Bond
|
|
7
|
-
Author-email: paul.bond@york.ac.uk
|
|
8
|
-
License: LGPL-2.1
|
|
9
|
-
Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Classifier: Programming Language :: Python
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
16
|
-
Requires-Python: ~=3.7
|
|
17
|
-
Description-Content-Type: text/markdown
|
|
18
|
-
License-File: LICENSE
|
|
19
|
-
Requires-Dist: gemmi>=0.5.5
|
|
20
|
-
Requires-Dist: numpy
|
|
21
|
-
Requires-Dist: pandas
|
|
22
|
-
Requires-Dist: requests
|
|
23
|
-
Requires-Dist: scipy
|
|
24
|
-
Dynamic: author
|
|
25
|
-
Dynamic: author-email
|
|
26
|
-
Dynamic: classifier
|
|
27
|
-
Dynamic: description
|
|
28
|
-
Dynamic: description-content-type
|
|
29
|
-
Dynamic: home-page
|
|
30
|
-
Dynamic: license
|
|
31
|
-
Dynamic: license-file
|
|
32
|
-
Dynamic: requires-dist
|
|
33
|
-
Dynamic: requires-python
|
|
34
|
-
Dynamic: summary
|
|
35
|
-
|
|
36
|
-
# ModelCraft
|
|
37
|
-
|
|
38
|
-
[](https://pypi.org/project/modelcraft/)
|
|
39
|
-
[](https://github.com/paulsbond/modelcraft/blob/master/LICENSE)
|
|
40
|
-
[](https://pypi.org/project/modelcraft/)
|
|
41
|
-
[](https://github.com/paulsbond/modelcraft/actions/workflows/pythontest.yml)
|
|
42
|
-
[](https://github.com/paulsbond/modelcraft/issues)
|
|
43
|
-
[](https://pypistats.org/packages/modelcraft)
|
|
44
|
-
[](https://github.com/paulsbond/modelcraft/releases)
|
|
45
|
-
|
|
46
|
-
Automated model building of proteins and nucleic acids
|
|
47
|
-
in X-ray crystallography and cryo-EM.
|
|
48
|
-
|
|
49
|
-
https://paulsbond.co.uk/modelcraft
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
modelcraft/__init__.py,sha256=Z0WSV4AM5IaCjZ0uPDdV9bhnWuoPKLeyp13BIDU4-GY,2185
|
|
2
|
-
modelcraft/__main__.py,sha256=0D-TbVRrb0ipPCS-NnUvifaG2kAsBn6mXtWLjyExOXM,77
|
|
3
|
-
modelcraft/arguments.py,sha256=fqsnzJhJKOg7MRgjqb50WFp_lQowG4J9O6ITyqr-q4g,15203
|
|
4
|
-
modelcraft/cell.py,sha256=dReWECZKuyZGSfR-MmumoD7qkrBiWM6GlaGpguDgU14,2025
|
|
5
|
-
modelcraft/combine.py,sha256=ibxg6dhvKBQ2r7AZlGE-ebEpO7dPNDVP5ChYppil9To,5020
|
|
6
|
-
modelcraft/contents.py,sha256=VEdFt1u6PDMUGjYbHa6eORr-9voi2zfzuc1CV1c5nuI,9860
|
|
7
|
-
modelcraft/environ.py,sha256=T8oMcx2rqc2FjNy-roKWl4CoVUnNJ1UOCecM0xbPC3E,553
|
|
8
|
-
modelcraft/geometry.py,sha256=ofgIgZ4G2W56vofldJVrkTjuxAbDhzOtsJckv-kCP_A,1218
|
|
9
|
-
modelcraft/job.py,sha256=RpM8UfIPH0uNf_yuwBTq4GLp2aY-4_yvJEQd7r3aL4o,4104
|
|
10
|
-
modelcraft/maps.py,sha256=Lyv3YjKNdUgi6vaLmQ8CcZFKq39EPL4NDC5qO_kCd0A,354
|
|
11
|
-
modelcraft/modelcraftem.py,sha256=AEZYS4zN_-O1cxv78K9Mf2dj_AMVEcAYmuThV-0S7Pw,5757
|
|
12
|
-
modelcraft/modelcraftxray.py,sha256=tRzxvhcC5opUiy24GeQaMLG2ZT_qvlcdq6ObFpA9nnM,13121
|
|
13
|
-
modelcraft/monlib.py,sha256=cEiYHKGEKpBlv-fJbKYJ91aZyMu9iAtmwdyuWeZj2F0,1482
|
|
14
|
-
modelcraft/pipeline.py,sha256=2fUmFcCyUG6EmAOxSHtcG91zRHHZmwjRkmJy5Y7Raus,2030
|
|
15
|
-
modelcraft/reflections.py,sha256=w8iV5NBcghUlufXWvxXLtbW8oNHR5Jx9ELKhgKThvkw,6274
|
|
16
|
-
modelcraft/solvent.py,sha256=beGtewZXoXzEdaadG4d0vu3hAL61XZdVue62Xldkw4k,6772
|
|
17
|
-
modelcraft/structure.py,sha256=A0KX9L1hI8Xbk-0dx82BfID3ot_FX2qRBCnWjjL3yko,4122
|
|
18
|
-
modelcraft/utils.py,sha256=1ljfNB-gIdfGjM1-o_U5jrjJc4f0E1213kpAFEVt5qw,192
|
|
19
|
-
modelcraft/coot/prune.py,sha256=-iGv3w8bubRuzZ9JeaSj5JoAiTwMPAZJrCqNLWwrC7g,35851
|
|
20
|
-
modelcraft/coot/sidechains.py,sha256=aOj8MHRGzs90VXsi2LdqUT4KcUDHB0yvSRLFvOuYqnY,1847
|
|
21
|
-
modelcraft/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
-
modelcraft/jobs/acedrg.py,sha256=nnf1Pe7U5hzY2GJVIluCjmbmQ5V6BayRmZQZD9vMZrs,984
|
|
23
|
-
modelcraft/jobs/acorn.py,sha256=wYyQMY6XoYejCvcIT0rBD0SyBcQ5Ewi01Bjb9totp5E,2465
|
|
24
|
-
modelcraft/jobs/buccaneer.py,sha256=7SintYeB4m4-C_yy5oj7rMwBirugF_ghVjSKCKVPslY,5533
|
|
25
|
-
modelcraft/jobs/comit.py,sha256=peQ5McTlPplTOSqXgkv_W1oB-X9HJ2B3zZQiudx9Ckg,1047
|
|
26
|
-
modelcraft/jobs/coot.py,sha256=GPWggYA2CUzVHY0ThsHDiCodyI9Hh8FmgycTWIG6vBI,3581
|
|
27
|
-
modelcraft/jobs/ctruncate.py,sha256=D-aXd6JY2F-XSZOW1Hj8gk1L-BhoRCxbqnUB34wjSVI,1659
|
|
28
|
-
modelcraft/jobs/emda.py,sha256=33Yr_quk-CDne8vkHrjjIUSCCeoRUlBVnhRZFO8wOXA,988
|
|
29
|
-
modelcraft/jobs/findwaters.py,sha256=nh0dRFAYYyBYi-8waLByBlV9xmuMog9kqJ5oSUxj2lQ,1700
|
|
30
|
-
modelcraft/jobs/freerflag.py,sha256=wQcAgTYhVNiAp4GXGNd8Zibg5fiWVmjqs83OTlk-u7A,846
|
|
31
|
-
modelcraft/jobs/libg.py,sha256=P1HTTz4DI_rQ157APFtdD2-Akx3bnrkckc9HVDC9YL4,650
|
|
32
|
-
modelcraft/jobs/molrep.py,sha256=yrSzJSxd1wV91ClcyHqF6ffD9gkQ5yerM0Bu1DZEJE4,2727
|
|
33
|
-
modelcraft/jobs/nautilus.py,sha256=eOpCynvFcGdlCwF9fE4oKlWnUPSP3sAnE5KLS0UfZGE,2837
|
|
34
|
-
modelcraft/jobs/parrot.py,sha256=G1ZYpnsu8_T_fUaO5VExMvzJjacsY8Avw4i_HBtSgi8,2190
|
|
35
|
-
modelcraft/jobs/phasematch.py,sha256=clUoRs4fptJa2Wy2sLYhRrfsutPtjqaIBwFwpOGdkuY,1841
|
|
36
|
-
modelcraft/jobs/refmac.py,sha256=sOVbLOq3t_SUH7zpUlLUrtHwzG_y_wkjIbIE9ec3iJE,5379
|
|
37
|
-
modelcraft/jobs/servalcat.py,sha256=lOvFvTJpfkE06IbfWF-K2WbtTjycebtZoAZL5UYH-wU,6598
|
|
38
|
-
modelcraft/jobs/sheetbend.py,sha256=Dmky59U0P2FeU_Ggy7502NQBErFiJ0xcShOkysZeDrc,1569
|
|
39
|
-
modelcraft/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
40
|
-
modelcraft/scripts/contents.py,sha256=LTu_v8YUYRgo_s7sK4Q1ikP95da49x-arsXAgtbsTyI,7694
|
|
41
|
-
modelcraft/scripts/copies.py,sha256=AQguOxG-mVhmQmqQq650WXagWyaWikpDKL0-WlW_m-U,2349
|
|
42
|
-
modelcraft/scripts/modelcraft.py,sha256=U4jlkDSRM5kqhseLnNwHX4dXxHZ_U9dwemGx7iP6LuA,428
|
|
43
|
-
modelcraft/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
44
|
-
modelcraft/tests/ccp4/__init__.py,sha256=8Y4OnTJhNgAuhm7XQxZz5DWqguL2lzMPIH8o8wsPt3w,2817
|
|
45
|
-
modelcraft/tests/ccp4/test_acedrg.py,sha256=f4i8DWleieXjpWXiLi9h6mFsX1-lk4mxw4-hYX29LzU,627
|
|
46
|
-
modelcraft/tests/ccp4/test_arguments.py,sha256=N011s4QYSxj4cMEDXRTlMTXE0JmDieLQaYOBb0DGrdE,1393
|
|
47
|
-
modelcraft/tests/ccp4/test_buccaneer.py,sha256=cNf40Nf_yzqdaaGN_jVBGQIwDxl2kXgNBvQqcON5soE,2258
|
|
48
|
-
modelcraft/tests/ccp4/test_cell.py,sha256=DcMTs_LZ-mw_ocUtAubljuJ_tk8Ye7gpxHDa9KVlPY0,1027
|
|
49
|
-
modelcraft/tests/ccp4/test_comit.py,sha256=77TQK5-cAK_LCPnhj7sbWQbNXLg_YxuBa-soldURYcs,533
|
|
50
|
-
modelcraft/tests/ccp4/test_contents.py,sha256=da0blxz6SUao2hE5cE1e5aPPHPHkldAxYObujhjTIwQ,6801
|
|
51
|
-
modelcraft/tests/ccp4/test_coot.py,sha256=59wzv62P2s9oUcmrnhZZmntJrCEwG0kRcrPaanqEkz8,924
|
|
52
|
-
modelcraft/tests/ccp4/test_copies.py,sha256=mU8qMzM0UFN19ASMUX5HWX1yOc5QPhtoEfbuzzj9MOc,315
|
|
53
|
-
modelcraft/tests/ccp4/test_ctruncate.py,sha256=q0QewF2v5-DfEYNrKq2oRluCYi1MDd41rNGFiiTwwlE,2277
|
|
54
|
-
modelcraft/tests/ccp4/test_findwaters.py,sha256=IEzazZXjt0uccLcUSJnacEeJZDrl1c_UmrcQaUJMgCI,1583
|
|
55
|
-
modelcraft/tests/ccp4/test_freerflag.py,sha256=2Z4nRka3VbXSx89qj-vIbAZ9m12Tl_O2szH3c19h71k,272
|
|
56
|
-
modelcraft/tests/ccp4/test_geometry.py,sha256=LFeCGHqALgWoiP5X2p1oRbsK8Mbk8p5ICk4CDbGAbKI,556
|
|
57
|
-
modelcraft/tests/ccp4/test_libg.py,sha256=JHGOeg3jSriWUH96H8aAVd3K9SrrE3qwHPMjpmv3vJg,256
|
|
58
|
-
modelcraft/tests/ccp4/test_molrep.py,sha256=ooyYNXtN5sNkpF-j59vJzRD4f1CEQkMQkVdatzIhA10,1318
|
|
59
|
-
modelcraft/tests/ccp4/test_monlib.py,sha256=vuU0EMNVBGqegF6JinUhw3FPJ6KB1Zdik8NV2p0gbJ0,1792
|
|
60
|
-
modelcraft/tests/ccp4/test_nautilus.py,sha256=rytNdr27fAtXajZk52fs3eYVi1_8WJbubeXnWd2XXOw,1946
|
|
61
|
-
modelcraft/tests/ccp4/test_parrot.py,sha256=0Qug6Q3UjH54DokA3C_vKyur7UiLyhyGK3w7Cfjfpxs,792
|
|
62
|
-
modelcraft/tests/ccp4/test_phasematch.py,sha256=mSWA2eBsipDe3xWyj5iRn7Yj8Gpav0Iva1DaGOHWYa8,1143
|
|
63
|
-
modelcraft/tests/ccp4/test_reflections.py,sha256=ihReZ4pCUNMf7PIELSzjYifpMjv3MvWMbC8buo8u1zs,1354
|
|
64
|
-
modelcraft/tests/ccp4/test_refmac.py,sha256=zAKAPd19uv5QznqZxmBvL1APTNUreEoBfQb4UzjQC00,1089
|
|
65
|
-
modelcraft/tests/ccp4/test_sheetbend.py,sha256=LgXAryITEtDWlIYsgUbKoEwa9G10o6eF5UzjSkkjhu0,636
|
|
66
|
-
modelcraft/tests/ccp4/test_solvent.py,sha256=DN42jpiqIXO5ogqvcsH2DX_-YGQRXJ-h3AKes6curpE,867
|
|
67
|
-
modelcraft/tests/ccp4/test_structure.py,sha256=zXEDHankyyIuMDF4wWVKowLKYvHbA0EpWM0bxZwo-Vg,336
|
|
68
|
-
modelcraft/tests/ccp4/test_xray.py,sha256=YExs_3_l8HEDJ3hjNCnvoF5rTd3mWrAdotywV_jK1Vk,2995
|
|
69
|
-
modelcraft/tests/ccpem/__init__.py,sha256=fY53G_EEc9LG4FmZ-IfQEhmEsNg5FZfxFwOCUQj019c,656
|
|
70
|
-
modelcraft/tests/ccpem/test_em.py,sha256=6fM4z1Zh27oTdo_4IY5p9jB0qQWdLri-TQUV3ea2TVE,1529
|
|
71
|
-
modelcraft/tests/ccpem/test_emda.py,sha256=Bd9Cv4EoDckLYLqsZg7XNTYnGogqELzWokiHs5bU1W4,399
|
|
72
|
-
modelcraft/tests/ccpem/test_refmac.py,sha256=AYpTftXpvKBUMi7VQw0cMOJVJ883z2RVAlCRAvLUBto,325
|
|
73
|
-
modelcraft/tests/ccpem/test_servalcat.py,sha256=X6d0z5yE-sxNa-6_WySn12QhvbJelYNnpOqfQju7PvM,1435
|
|
74
|
-
modelcraft/tests/unittests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
|
-
modelcraft/tests/unittests/test_contents.py,sha256=aAHha4pQYMyKes7OiOZ11_-9z-BVqh4OSmAL8gRUX_Y,3153
|
|
76
|
-
modelcraft/tests/unittests/test_reflections.py,sha256=xshb_2QcAko2l98-Pd1LuEjMZAVv-O7LkhtzGRnrbM4,3674
|
|
77
|
-
modelcraft-5.0.3.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
|
|
78
|
-
modelcraft-5.0.3.dist-info/METADATA,sha256=l8o8S5XGFS4xc3UUxd1PYCV1Az9Rc-c8uC3k9OhiVSg,2128
|
|
79
|
-
modelcraft-5.0.3.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
|
|
80
|
-
modelcraft-5.0.3.dist-info/entry_points.txt,sha256=bWef3WSAihTv1fI39wScTAmrKtn5mOYZ3SEeBpM4RrU,172
|
|
81
|
-
modelcraft-5.0.3.dist-info/top_level.txt,sha256=My5973x4fvPrlRfQOuuFxqultnVzrg_aamczcSijdlQ,11
|
|
82
|
-
modelcraft-5.0.3.dist-info/RECORD,,
|