rcsb.workflow 0.52__tar.gz → 0.53__tar.gz
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.
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/HISTORY.txt +1 -0
- {rcsb_workflow-0.52/rcsb.workflow.egg-info → rcsb_workflow-0.53}/PKG-INFO +4 -2
- {rcsb_workflow-0.52/rcsb/workflow/chem → rcsb_workflow-0.53/rcsb/workflow/bcif}/__init__.py +0 -0
- rcsb_workflow-0.53/rcsb/workflow/bcif/task_functions.py +315 -0
- rcsb_workflow-0.53/rcsb/workflow/cli/BcifExec.py +174 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/cli/__init__.py +1 -1
- rcsb_workflow-0.53/rcsb/workflow/wuw/BcifWorkflow.py +85 -0
- rcsb_workflow-0.53/rcsb/workflow/wuw/__init__.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53/rcsb.workflow.egg-info}/PKG-INFO +4 -2
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb.workflow.egg-info/SOURCES.txt +4 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb.workflow.egg-info/entry_points.txt +1 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb.workflow.egg-info/requires.txt +3 -1
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/requirements.txt +3 -1
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/setup.py +1 -1
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/LICENSE +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/MANIFEST.in +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/README.md +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/__init__.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/__init__.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/chem/ChemCompFileWorkflow.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/chem/ChemCompImageWorkflow.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/chem/ChemCompSearchIndexWorkflow.py +0 -0
- {rcsb_workflow-0.52/rcsb/workflow/targets → rcsb_workflow-0.53/rcsb/workflow/chem}/__init__.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/cli/ExDbExec.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/cli/ImgExec.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/targets/ProteinTargetSequenceExecutionWorkflow.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/targets/ProteinTargetSequenceWorkflow.py +0 -0
- {rcsb_workflow-0.52/rcsb/workflow/wuw → rcsb_workflow-0.53/rcsb/workflow/targets}/__init__.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/wuw/ExDbWorkflow.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/wuw/PdbCsmImageWorkflow.py +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb.workflow.egg-info/dependency_links.txt +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb.workflow.egg-info/not-zip-safe +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb.workflow.egg-info/top_level.txt +0 -0
- {rcsb_workflow-0.52 → rcsb_workflow-0.53}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rcsb.workflow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.53
|
|
4
4
|
Summary: RCSB Python data processing and ETL/ELT workflow entry points
|
|
5
5
|
Home-page: https://github.com/rcsb/py-rcsb_workflow
|
|
6
6
|
Author: John Westbrook
|
|
@@ -22,7 +22,9 @@ Requires-Dist: rcsb.utils.targets>=0.82
|
|
|
22
22
|
Requires-Dist: rcsb.utils.seqalign>=0.31
|
|
23
23
|
Requires-Dist: rcsb.utils.io>=1.48
|
|
24
24
|
Requires-Dist: rcsb.exdb>=1.28
|
|
25
|
-
Requires-Dist: rcsb.db>=1.
|
|
25
|
+
Requires-Dist: rcsb.db>=1.801
|
|
26
|
+
Requires-Dist: requests>=2.32.3
|
|
27
|
+
Requires-Dist: mmcif>=0.91.0
|
|
26
28
|
Provides-Extra: dev
|
|
27
29
|
Requires-Dist: check-manifest; extra == "dev"
|
|
28
30
|
Provides-Extra: test
|
|
File without changes
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
##
|
|
2
|
+
# File: task_functions.py
|
|
3
|
+
# Author: James Smith
|
|
4
|
+
# Date: 21-Feb-2025
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Workflow task descriptors.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__docformat__ = "google en"
|
|
12
|
+
__author__ = "James Smith"
|
|
13
|
+
__email__ = "james.smith@rcsb.org"
|
|
14
|
+
__license__ = "Apache 2.0"
|
|
15
|
+
|
|
16
|
+
import multiprocessing
|
|
17
|
+
import os
|
|
18
|
+
import shutil
|
|
19
|
+
import tempfile
|
|
20
|
+
import logging
|
|
21
|
+
from enum import Enum
|
|
22
|
+
from typing import Optional
|
|
23
|
+
from mmcif.api.DictionaryApi import DictionaryApi
|
|
24
|
+
from mmcif.io.IoAdapterPy import IoAdapterPy as IoAdapter
|
|
25
|
+
from rcsb.utils.io.MarshalUtil import MarshalUtil
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
logger.setLevel(logging.INFO)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
ContentTypeEnum = Enum(
|
|
32
|
+
"ContentTypeEnum",
|
|
33
|
+
[("EXPERIMENTAL", "pdb"), ("COMPUTATIONAL", "csm"), ("INTEGRATIVE", "ihm")],
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def convertCifFilesToBcif(
|
|
38
|
+
listFileName: str,
|
|
39
|
+
listFileBase: str,
|
|
40
|
+
remotePath: str,
|
|
41
|
+
updateBase: str,
|
|
42
|
+
outfileSuffix: str,
|
|
43
|
+
contentType: str,
|
|
44
|
+
outputContentType: bool,
|
|
45
|
+
outputHash: bool,
|
|
46
|
+
inputHash: bool,
|
|
47
|
+
batchSize: int,
|
|
48
|
+
maxFiles: int,
|
|
49
|
+
pdbxDict: str,
|
|
50
|
+
maDict: str,
|
|
51
|
+
rcsbDict: str,
|
|
52
|
+
ihmDict: str,
|
|
53
|
+
):
|
|
54
|
+
"""
|
|
55
|
+
Converts CIF files to BCIF format based on a given list file.
|
|
56
|
+
|
|
57
|
+
Raises:
|
|
58
|
+
FileNotFoundError: If the specified list file does not exist.
|
|
59
|
+
ValueError: If the list file is empty.
|
|
60
|
+
RuntimeError: If processing fails for some files.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
# read sublist
|
|
64
|
+
listfilepath = os.path.join(listFileBase, listFileName)
|
|
65
|
+
logger.info(
|
|
66
|
+
"reading list file %s and remote path %s",
|
|
67
|
+
listfilepath,
|
|
68
|
+
remotePath,
|
|
69
|
+
)
|
|
70
|
+
files = []
|
|
71
|
+
if not os.path.exists(listfilepath):
|
|
72
|
+
raise FileNotFoundError("No list file found at %s" % listfilepath)
|
|
73
|
+
f = open(listfilepath, "r", encoding="utf-8")
|
|
74
|
+
for line in f:
|
|
75
|
+
files.append(line.strip())
|
|
76
|
+
if 0 < maxFiles <= len(files):
|
|
77
|
+
break
|
|
78
|
+
f.close()
|
|
79
|
+
if len(files) < 1:
|
|
80
|
+
raise ValueError("No files found in %s" % listfilepath)
|
|
81
|
+
|
|
82
|
+
# determine batch size
|
|
83
|
+
if (batchSize is None) or not str(batchSize).isdigit():
|
|
84
|
+
batchSize = 1
|
|
85
|
+
batchSize = int(batchSize)
|
|
86
|
+
if batchSize <= 0:
|
|
87
|
+
batchSize = 1
|
|
88
|
+
logger.info("distributing %d files across %d sublists", len(files), batchSize)
|
|
89
|
+
|
|
90
|
+
# form dictionary object
|
|
91
|
+
dictionaryApi = getDictionaryApi(pdbxDict, maDict, rcsbDict, ihmDict)
|
|
92
|
+
|
|
93
|
+
# traverse sublist and send each input file to converter
|
|
94
|
+
temppath = tempfile.mkdtemp()
|
|
95
|
+
if batchSize == 1:
|
|
96
|
+
# process one file at a time
|
|
97
|
+
for line in files:
|
|
98
|
+
args = (
|
|
99
|
+
line,
|
|
100
|
+
remotePath,
|
|
101
|
+
updateBase,
|
|
102
|
+
outfileSuffix,
|
|
103
|
+
outputContentType,
|
|
104
|
+
outputHash,
|
|
105
|
+
inputHash,
|
|
106
|
+
contentType,
|
|
107
|
+
dictionaryApi,
|
|
108
|
+
temppath,
|
|
109
|
+
)
|
|
110
|
+
singleTask(*args)
|
|
111
|
+
elif batchSize > 1:
|
|
112
|
+
pool = multiprocessing.Pool(processes=batchSize)
|
|
113
|
+
results = []
|
|
114
|
+
for line in files:
|
|
115
|
+
entry = line.strip()
|
|
116
|
+
args = (
|
|
117
|
+
entry,
|
|
118
|
+
remotePath,
|
|
119
|
+
updateBase,
|
|
120
|
+
outfileSuffix,
|
|
121
|
+
outputContentType,
|
|
122
|
+
outputHash,
|
|
123
|
+
inputHash,
|
|
124
|
+
contentType,
|
|
125
|
+
dictionaryApi,
|
|
126
|
+
temppath,
|
|
127
|
+
)
|
|
128
|
+
results.append(pool.apply_async(singleTask, args))
|
|
129
|
+
for r in results:
|
|
130
|
+
r.get(timeout=60 * 5)
|
|
131
|
+
pool.close()
|
|
132
|
+
results.clear()
|
|
133
|
+
|
|
134
|
+
try:
|
|
135
|
+
if os.path.exists(temppath):
|
|
136
|
+
shutil.rmtree(temppath)
|
|
137
|
+
except Exception as e:
|
|
138
|
+
logger.error(str(e))
|
|
139
|
+
|
|
140
|
+
logger.info("Done with CIF to BCIF conversion")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def getDictionaryApi(
|
|
144
|
+
pdbxDict: str, maDict: str, rcsbDict: str, ihmDict: str
|
|
145
|
+
) -> DictionaryApi:
|
|
146
|
+
paths = [pdbxDict, maDict, rcsbDict, ihmDict]
|
|
147
|
+
try:
|
|
148
|
+
adapter = IoAdapter(raiseExceptions=True)
|
|
149
|
+
containers = []
|
|
150
|
+
for path in paths:
|
|
151
|
+
containers += adapter.readFile(inputFilePath=path)
|
|
152
|
+
dictionaryApi = DictionaryApi(containerList=containers, consolidate=True)
|
|
153
|
+
except Exception as e:
|
|
154
|
+
raise FileNotFoundError("failed to create dictionary api: %s" % str(e)) from e
|
|
155
|
+
return dictionaryApi
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def singleTask(
|
|
159
|
+
pdbId: str,
|
|
160
|
+
remotePath: str,
|
|
161
|
+
updateBase: str,
|
|
162
|
+
outfileSuffix: str,
|
|
163
|
+
outputContentType: bool,
|
|
164
|
+
outputHash: bool,
|
|
165
|
+
inputHash: bool,
|
|
166
|
+
contentType: str,
|
|
167
|
+
dictionaryApi: DictionaryApi,
|
|
168
|
+
temppath: str,
|
|
169
|
+
) -> None:
|
|
170
|
+
if contentType in [
|
|
171
|
+
ContentTypeEnum.EXPERIMENTAL.value,
|
|
172
|
+
ContentTypeEnum.INTEGRATIVE.value,
|
|
173
|
+
]:
|
|
174
|
+
pdbId = pdbId.lower()
|
|
175
|
+
elif contentType == ContentTypeEnum.COMPUTATIONAL.value:
|
|
176
|
+
pdbId = pdbId.upper()
|
|
177
|
+
remoteFileName = "%s%s" % (
|
|
178
|
+
pdbId,
|
|
179
|
+
outfileSuffix.replace(".bcif.gz", ".cif.gz").replace(".bcif", ".cif"),
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# form input cifFilePath
|
|
183
|
+
if not remotePath.startswith("http"):
|
|
184
|
+
# local file
|
|
185
|
+
cifFilePath = os.path.join(remotePath, remoteFileName)
|
|
186
|
+
if inputHash:
|
|
187
|
+
cifFilePath = os.path.join(
|
|
188
|
+
remotePath, getHash(pdbId, contentType), remoteFileName
|
|
189
|
+
)
|
|
190
|
+
if not os.path.exists(cifFilePath):
|
|
191
|
+
logger.warning("%s not found", cifFilePath)
|
|
192
|
+
return
|
|
193
|
+
else:
|
|
194
|
+
cifFilePath = getRemoteFilePath(pdbId, contentType, remotePath, remoteFileName)
|
|
195
|
+
|
|
196
|
+
# form output bcifFilePath
|
|
197
|
+
bcifFilePath = getBcifFilePath(
|
|
198
|
+
pdbId, outfileSuffix, updateBase, contentType, outputContentType, outputHash
|
|
199
|
+
)
|
|
200
|
+
if not bcifFilePath:
|
|
201
|
+
raise ValueError("could not form bcif file path for %s" % pdbId)
|
|
202
|
+
|
|
203
|
+
if os.path.exists(bcifFilePath):
|
|
204
|
+
# earlier timestamp ... overwrite
|
|
205
|
+
os.unlink(bcifFilePath)
|
|
206
|
+
if os.path.exists(bcifFilePath):
|
|
207
|
+
raise PermissionError("file %s not removed" % bcifFilePath)
|
|
208
|
+
|
|
209
|
+
# make nested directories
|
|
210
|
+
dirs = os.path.dirname(bcifFilePath)
|
|
211
|
+
if not os.path.exists(dirs):
|
|
212
|
+
os.makedirs(dirs)
|
|
213
|
+
|
|
214
|
+
# convert to bcif
|
|
215
|
+
result = convert(cifFilePath, bcifFilePath, temppath, dictionaryApi)
|
|
216
|
+
if not result:
|
|
217
|
+
raise Exception("failed to convert %s" % cifFilePath)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def getHash(pdbId: str, contentType: str) -> str:
|
|
221
|
+
if contentType == ContentTypeEnum.COMPUTATIONAL.value:
|
|
222
|
+
pdbId = pdbId.upper()
|
|
223
|
+
else:
|
|
224
|
+
pdbId = pdbId.lower()
|
|
225
|
+
result = pdbId[1:3]
|
|
226
|
+
if contentType == ContentTypeEnum.COMPUTATIONAL.value:
|
|
227
|
+
result = os.path.join(pdbId[0:2], pdbId[-6:-4], pdbId[-4:-2])
|
|
228
|
+
return result
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def getRemoteFilePath(
|
|
232
|
+
pdbId: str, contentType: str, remotePath: str, remoteFileName: str
|
|
233
|
+
) -> str:
|
|
234
|
+
result = os.path.join(remotePath, getHash(pdbId, contentType), remoteFileName)
|
|
235
|
+
if contentType == ContentTypeEnum.INTEGRATIVE.value:
|
|
236
|
+
result = os.path.join(
|
|
237
|
+
remotePath, getHash(pdbId, contentType), pdbId, "structures", remoteFileName
|
|
238
|
+
)
|
|
239
|
+
return result
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def getBcifFilePath(
|
|
243
|
+
pdbId: str,
|
|
244
|
+
outfileSuffix: str,
|
|
245
|
+
updateBase: str,
|
|
246
|
+
contentType: str,
|
|
247
|
+
outputContentType: bool,
|
|
248
|
+
outputHash: bool,
|
|
249
|
+
) -> Optional[str]:
|
|
250
|
+
bcifFileName = "%s%s" % (pdbId, outfileSuffix)
|
|
251
|
+
bcifFilePath = None
|
|
252
|
+
if contentType in [
|
|
253
|
+
ContentTypeEnum.EXPERIMENTAL.value,
|
|
254
|
+
ContentTypeEnum.INTEGRATIVE.value,
|
|
255
|
+
]:
|
|
256
|
+
if outputContentType and outputHash:
|
|
257
|
+
bcifFilePath = os.path.join(
|
|
258
|
+
updateBase, contentType, getHash(pdbId, contentType), bcifFileName
|
|
259
|
+
)
|
|
260
|
+
elif outputContentType:
|
|
261
|
+
bcifFilePath = os.path.join(updateBase, contentType, bcifFileName)
|
|
262
|
+
elif outputHash:
|
|
263
|
+
bcifFilePath = os.path.join(
|
|
264
|
+
updateBase, getHash(pdbId, contentType), bcifFileName
|
|
265
|
+
)
|
|
266
|
+
else:
|
|
267
|
+
bcifFilePath = os.path.join(updateBase, bcifFileName)
|
|
268
|
+
elif contentType == ContentTypeEnum.COMPUTATIONAL.value:
|
|
269
|
+
if outputContentType and outputHash:
|
|
270
|
+
bcifFilePath = os.path.join(
|
|
271
|
+
updateBase,
|
|
272
|
+
contentType,
|
|
273
|
+
getHash(pdbId, contentType),
|
|
274
|
+
bcifFileName,
|
|
275
|
+
)
|
|
276
|
+
elif outputContentType:
|
|
277
|
+
bcifFilePath = os.path.join(
|
|
278
|
+
updateBase,
|
|
279
|
+
contentType,
|
|
280
|
+
bcifFileName,
|
|
281
|
+
)
|
|
282
|
+
elif outputHash:
|
|
283
|
+
bcifFilePath = os.path.join(
|
|
284
|
+
updateBase,
|
|
285
|
+
getHash(pdbId, contentType),
|
|
286
|
+
bcifFileName,
|
|
287
|
+
)
|
|
288
|
+
else:
|
|
289
|
+
bcifFilePath = os.path.join(
|
|
290
|
+
updateBase,
|
|
291
|
+
bcifFileName,
|
|
292
|
+
)
|
|
293
|
+
return bcifFilePath
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def convert(
|
|
297
|
+
infile: str, outfile: str, workpath: str, dictionaryApi: DictionaryApi
|
|
298
|
+
) -> bool:
|
|
299
|
+
mu = MarshalUtil(workPath=workpath)
|
|
300
|
+
data = mu.doImport(infile, fmt="mmcif")
|
|
301
|
+
result = mu.doExport(outfile, data, fmt="bcif", dictionaryApi=dictionaryApi)
|
|
302
|
+
if not result:
|
|
303
|
+
return False
|
|
304
|
+
return True
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def deconvert(
|
|
308
|
+
infile: str, outfile: str, workpath: str, dictionaryApi: DictionaryApi
|
|
309
|
+
) -> bool:
|
|
310
|
+
mu = MarshalUtil(workPath=workpath)
|
|
311
|
+
data = mu.doImport(infile, fmt="bcif")
|
|
312
|
+
result = mu.doExport(outfile, data, fmt="mmcif", dictionaryApi=dictionaryApi)
|
|
313
|
+
if not result:
|
|
314
|
+
return False
|
|
315
|
+
return True
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
##
|
|
2
|
+
# File: BcifExec.py
|
|
3
|
+
# Author: James Smith
|
|
4
|
+
# Date: 21-Feb-2025
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Entry point for bcif command line interface.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__docformat__ = "google en"
|
|
12
|
+
__author__ = "James Smith"
|
|
13
|
+
__email__ = "james.smith@rcsb.org"
|
|
14
|
+
__license__ = "Apache 2.0"
|
|
15
|
+
|
|
16
|
+
import argparse
|
|
17
|
+
import os
|
|
18
|
+
import logging
|
|
19
|
+
import time
|
|
20
|
+
from rcsb.workflow.wuw.BcifWorkflow import BcifWorkflow
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def main():
|
|
26
|
+
|
|
27
|
+
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
|
|
28
|
+
# paths
|
|
29
|
+
parser.add_argument(
|
|
30
|
+
"--listFileBase",
|
|
31
|
+
default="/tmp",
|
|
32
|
+
required=True,
|
|
33
|
+
help="path for input lists",
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--listFileName",
|
|
37
|
+
default="pdbx_core_ids-1.txt",
|
|
38
|
+
required=True,
|
|
39
|
+
help="name of list file to read",
|
|
40
|
+
)
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--remotePath",
|
|
43
|
+
default="http://prereleaseftp-external-east.rcsb.org/pdb/data/structures/divided/mmCIF/",
|
|
44
|
+
required=True,
|
|
45
|
+
help="url or directory for cif files",
|
|
46
|
+
)
|
|
47
|
+
parser.add_argument(
|
|
48
|
+
"--outputPath",
|
|
49
|
+
default="/mnt/vdb1/out",
|
|
50
|
+
required=True,
|
|
51
|
+
help="output directory for bcif files",
|
|
52
|
+
)
|
|
53
|
+
# settings
|
|
54
|
+
parser.add_argument(
|
|
55
|
+
"--contentType",
|
|
56
|
+
default="pdb",
|
|
57
|
+
required=True,
|
|
58
|
+
choices=["pdb", "csm", "ihm"],
|
|
59
|
+
help="which type of experiment was performed",
|
|
60
|
+
)
|
|
61
|
+
parser.add_argument(
|
|
62
|
+
"--nfiles",
|
|
63
|
+
default=0,
|
|
64
|
+
required=False,
|
|
65
|
+
help="set 0 for all files, set less than N for a test run, will not produce exactly n files",
|
|
66
|
+
)
|
|
67
|
+
parser.add_argument(
|
|
68
|
+
"--outfileSuffix",
|
|
69
|
+
default=".bcif.gz",
|
|
70
|
+
required=False,
|
|
71
|
+
choices=[".bcif", ".bcif.gz"],
|
|
72
|
+
help="whether to use additional gzip compression",
|
|
73
|
+
)
|
|
74
|
+
parser.add_argument(
|
|
75
|
+
"--batchSize",
|
|
76
|
+
default=1,
|
|
77
|
+
required=False,
|
|
78
|
+
help="optional subdivisions of sublists for pdb list and csm list",
|
|
79
|
+
)
|
|
80
|
+
# output folder structure, default none (save all output files in one folder)
|
|
81
|
+
parser.add_argument(
|
|
82
|
+
"--outputContentType",
|
|
83
|
+
action="store_true",
|
|
84
|
+
default=False,
|
|
85
|
+
required=False,
|
|
86
|
+
help="whether output paths should include a directory for the content type (pdb, csm)",
|
|
87
|
+
)
|
|
88
|
+
parser.add_argument(
|
|
89
|
+
"--outputHash",
|
|
90
|
+
action="store_true",
|
|
91
|
+
default=False,
|
|
92
|
+
required=False,
|
|
93
|
+
help="whether output paths should include the hash for the entry",
|
|
94
|
+
)
|
|
95
|
+
# input folder structure, default none (read all input files from one folder)
|
|
96
|
+
parser.add_argument(
|
|
97
|
+
"--inputHash",
|
|
98
|
+
action="store_true",
|
|
99
|
+
default=False,
|
|
100
|
+
required=False,
|
|
101
|
+
help="whether local input paths should include the hash for the entry",
|
|
102
|
+
)
|
|
103
|
+
# config
|
|
104
|
+
parser.add_argument(
|
|
105
|
+
"--pdbxDict",
|
|
106
|
+
default="https://raw.githubusercontent.com/wwpdb-dictionaries/mmcif_pdbx/master/dist/mmcif_pdbx_v5_next.dic",
|
|
107
|
+
required=False,
|
|
108
|
+
)
|
|
109
|
+
parser.add_argument(
|
|
110
|
+
"--maDict",
|
|
111
|
+
default="https://raw.githubusercontent.com/ihmwg/ModelCIF/master/dist/mmcif_ma_ext.dic",
|
|
112
|
+
required=False,
|
|
113
|
+
)
|
|
114
|
+
parser.add_argument(
|
|
115
|
+
"--rcsbDict",
|
|
116
|
+
default="https://raw.githubusercontent.com/rcsb/py-rcsb_exdb_assets/master/dictionary_files/dist/rcsb_mmcif_ext.dic",
|
|
117
|
+
required=False,
|
|
118
|
+
)
|
|
119
|
+
parser.add_argument(
|
|
120
|
+
"--ihmDict",
|
|
121
|
+
default="https://raw.githubusercontent.com/rcsb/py-rcsb_exdb_assets/pdb-ihm-2/dictionary_files/reference/mmcif_ihm_ext.dic",
|
|
122
|
+
required=False,
|
|
123
|
+
)
|
|
124
|
+
# logging
|
|
125
|
+
parser.add_argument("--log_file_path", required=False)
|
|
126
|
+
parser.add_argument("--debug", action="store_true", default=False, required=False)
|
|
127
|
+
|
|
128
|
+
args = parser.parse_args()
|
|
129
|
+
|
|
130
|
+
logFilePath = args.log_file_path
|
|
131
|
+
debugFlag = args.debug
|
|
132
|
+
if debugFlag:
|
|
133
|
+
logger.setLevel(logging.DEBUG)
|
|
134
|
+
else:
|
|
135
|
+
logger.setLevel(logging.INFO)
|
|
136
|
+
if logFilePath:
|
|
137
|
+
logDir = os.path.dirname(logFilePath)
|
|
138
|
+
if not os.path.isdir(logDir):
|
|
139
|
+
os.makedirs(logDir)
|
|
140
|
+
handler = logging.FileHandler(logFilePath, mode="a")
|
|
141
|
+
if debugFlag:
|
|
142
|
+
handler.setLevel(logging.DEBUG)
|
|
143
|
+
else:
|
|
144
|
+
handler.setLevel(logging.INFO)
|
|
145
|
+
formatter = logging.Formatter(
|
|
146
|
+
fmt="%(asctime)s @%(process)s [%(levelname)s]-%(module)s: %(message)s"
|
|
147
|
+
)
|
|
148
|
+
handler.setFormatter(formatter)
|
|
149
|
+
logger.addHandler(handler)
|
|
150
|
+
else:
|
|
151
|
+
handler = logging.StreamHandler()
|
|
152
|
+
formatter = logging.Formatter(
|
|
153
|
+
fmt="%(asctime)s @%(process)s [%(levelname)s]-%(module)s: %(message)s"
|
|
154
|
+
)
|
|
155
|
+
handler.setFormatter(formatter)
|
|
156
|
+
logger.addHandler(handler)
|
|
157
|
+
|
|
158
|
+
logger.info("bcif workflow initialized")
|
|
159
|
+
|
|
160
|
+
try:
|
|
161
|
+
(BcifWorkflow(args))()
|
|
162
|
+
except RuntimeError as e:
|
|
163
|
+
raise Exception(str(e)) from e
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
if __name__ == "__main__":
|
|
167
|
+
t = time.time()
|
|
168
|
+
try:
|
|
169
|
+
main()
|
|
170
|
+
except Exception as e:
|
|
171
|
+
logger.exception(str(e))
|
|
172
|
+
raise e
|
|
173
|
+
t2 = time.time() - t
|
|
174
|
+
logger.info("completed in %.2f s", t2)
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
##
|
|
2
|
+
# File: BcifWorkflow.py
|
|
3
|
+
# Author: James Smith
|
|
4
|
+
# Date: 21-Feb-2025
|
|
5
|
+
##
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Run workflow for pdb entries specified in input list.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
__docformat__ = "google en"
|
|
12
|
+
__author__ = "James Smith"
|
|
13
|
+
__email__ = "james.smith@rcsb.org"
|
|
14
|
+
__license__ = "Apache 2.0"
|
|
15
|
+
|
|
16
|
+
import os
|
|
17
|
+
import logging
|
|
18
|
+
from rcsb.workflow.bcif.task_functions import convertCifFilesToBcif
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BcifWorkflow:
|
|
24
|
+
|
|
25
|
+
def __init__(self, args):
|
|
26
|
+
|
|
27
|
+
# paths and files
|
|
28
|
+
self.listFileBase = args.listFileBase
|
|
29
|
+
self.listFileName = args.listFileName
|
|
30
|
+
self.remotePath = args.remotePath
|
|
31
|
+
self.outputPath = args.outputPath
|
|
32
|
+
# settings
|
|
33
|
+
self.contentType = args.contentType
|
|
34
|
+
self.nfiles = int(args.nfiles)
|
|
35
|
+
self.outfileSuffix = args.outfileSuffix
|
|
36
|
+
self.outputContentType = bool(args.outputContentType)
|
|
37
|
+
self.outputHash = bool(args.outputHash)
|
|
38
|
+
self.inputHash = bool(args.inputHash)
|
|
39
|
+
self.batchSize = int(args.batchSize)
|
|
40
|
+
# config
|
|
41
|
+
self.pdbxDict = args.pdbxDict
|
|
42
|
+
self.maDict = args.maDict
|
|
43
|
+
self.rcsbDict = args.rcsbDict
|
|
44
|
+
self.ihmDict = args.ihmDict
|
|
45
|
+
#
|
|
46
|
+
self.validate()
|
|
47
|
+
|
|
48
|
+
# public method required by pylint
|
|
49
|
+
def validate(self):
|
|
50
|
+
|
|
51
|
+
assert (
|
|
52
|
+
self.outfileSuffix == ".bcif" or self.outfileSuffix == ".bcif.gz"
|
|
53
|
+
), "error - require either .bcif or .bcif.gz output file"
|
|
54
|
+
|
|
55
|
+
assert self.contentType in [
|
|
56
|
+
"pdb",
|
|
57
|
+
"csm",
|
|
58
|
+
"ihm",
|
|
59
|
+
], "error - content type must be pdb, csm, or ihm"
|
|
60
|
+
|
|
61
|
+
def __call__(self):
|
|
62
|
+
|
|
63
|
+
logger.info(
|
|
64
|
+
"running bcif workflow on %s and %s",
|
|
65
|
+
os.path.join(self.listFileBase, self.listFileName),
|
|
66
|
+
self.remotePath,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
convertCifFilesToBcif(
|
|
70
|
+
self.listFileName,
|
|
71
|
+
self.listFileBase,
|
|
72
|
+
self.remotePath,
|
|
73
|
+
self.outputPath,
|
|
74
|
+
self.outfileSuffix,
|
|
75
|
+
self.contentType,
|
|
76
|
+
self.outputContentType,
|
|
77
|
+
self.outputHash,
|
|
78
|
+
self.inputHash,
|
|
79
|
+
self.batchSize,
|
|
80
|
+
self.nfiles,
|
|
81
|
+
self.pdbxDict,
|
|
82
|
+
self.maDict,
|
|
83
|
+
self.rcsbDict,
|
|
84
|
+
self.ihmDict,
|
|
85
|
+
)
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rcsb.workflow
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.53
|
|
4
4
|
Summary: RCSB Python data processing and ETL/ELT workflow entry points
|
|
5
5
|
Home-page: https://github.com/rcsb/py-rcsb_workflow
|
|
6
6
|
Author: John Westbrook
|
|
@@ -22,7 +22,9 @@ Requires-Dist: rcsb.utils.targets>=0.82
|
|
|
22
22
|
Requires-Dist: rcsb.utils.seqalign>=0.31
|
|
23
23
|
Requires-Dist: rcsb.utils.io>=1.48
|
|
24
24
|
Requires-Dist: rcsb.exdb>=1.28
|
|
25
|
-
Requires-Dist: rcsb.db>=1.
|
|
25
|
+
Requires-Dist: rcsb.db>=1.801
|
|
26
|
+
Requires-Dist: requests>=2.32.3
|
|
27
|
+
Requires-Dist: mmcif>=0.91.0
|
|
26
28
|
Provides-Extra: dev
|
|
27
29
|
Requires-Dist: check-manifest; extra == "dev"
|
|
28
30
|
Provides-Extra: test
|
|
@@ -14,16 +14,20 @@ rcsb.workflow.egg-info/not-zip-safe
|
|
|
14
14
|
rcsb.workflow.egg-info/requires.txt
|
|
15
15
|
rcsb.workflow.egg-info/top_level.txt
|
|
16
16
|
rcsb/workflow/__init__.py
|
|
17
|
+
rcsb/workflow/bcif/__init__.py
|
|
18
|
+
rcsb/workflow/bcif/task_functions.py
|
|
17
19
|
rcsb/workflow/chem/ChemCompFileWorkflow.py
|
|
18
20
|
rcsb/workflow/chem/ChemCompImageWorkflow.py
|
|
19
21
|
rcsb/workflow/chem/ChemCompSearchIndexWorkflow.py
|
|
20
22
|
rcsb/workflow/chem/__init__.py
|
|
23
|
+
rcsb/workflow/cli/BcifExec.py
|
|
21
24
|
rcsb/workflow/cli/ExDbExec.py
|
|
22
25
|
rcsb/workflow/cli/ImgExec.py
|
|
23
26
|
rcsb/workflow/cli/__init__.py
|
|
24
27
|
rcsb/workflow/targets/ProteinTargetSequenceExecutionWorkflow.py
|
|
25
28
|
rcsb/workflow/targets/ProteinTargetSequenceWorkflow.py
|
|
26
29
|
rcsb/workflow/targets/__init__.py
|
|
30
|
+
rcsb/workflow/wuw/BcifWorkflow.py
|
|
27
31
|
rcsb/workflow/wuw/ExDbWorkflow.py
|
|
28
32
|
rcsb/workflow/wuw/PdbCsmImageWorkflow.py
|
|
29
33
|
rcsb/workflow/wuw/__init__.py
|
|
@@ -49,7 +49,7 @@ setup(
|
|
|
49
49
|
"Programming Language :: Python :: 3.10",
|
|
50
50
|
],
|
|
51
51
|
# entry_points={"console_scripts": ["cactvs_annotate_mol=rcsb.workflow.cactvsAnnotateMol:main"]},
|
|
52
|
-
entry_points={"console_scripts": ["exdb_wf_cli=rcsb.workflow.cli.ExDbExec:main", "imgs_exec_cli=rcsb.workflow.cli.ImgExec:main"]},
|
|
52
|
+
entry_points={"console_scripts": ["exdb_wf_cli=rcsb.workflow.cli.ExDbExec:main", "imgs_exec_cli=rcsb.workflow.cli.ImgExec:main", "bcif_exec_cli=rcsb.workflow.cli.BcifExec:main"]},
|
|
53
53
|
# The following is somewhat flakey --
|
|
54
54
|
# dependency_links=[],
|
|
55
55
|
install_requires=packagesRequired[1:],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rcsb_workflow-0.52/rcsb/workflow/targets → rcsb_workflow-0.53/rcsb/workflow/chem}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rcsb_workflow-0.52 → rcsb_workflow-0.53}/rcsb/workflow/targets/ProteinTargetSequenceWorkflow.py
RENAMED
|
File without changes
|
{rcsb_workflow-0.52/rcsb/workflow/wuw → rcsb_workflow-0.53/rcsb/workflow/targets}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|