rcsb.workflow 0.64__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.
rcsb/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
File without changes
@@ -0,0 +1,333 @@
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
+ ContentTypeEnum = Enum(
31
+ "ContentTypeEnum",
32
+ [("EXPERIMENTAL", "pdb"), ("COMPUTATIONAL", "csm"), ("INTEGRATIVE", "ihm")],
33
+ )
34
+
35
+
36
+ def convertCifFilesToBcif(
37
+ listFileName: str,
38
+ listFileBase: str,
39
+ remotePath: str,
40
+ updateBase: str,
41
+ outfileSuffix: str,
42
+ contentType: str,
43
+ outputContentType: bool,
44
+ outputHash: bool,
45
+ inputHash: bool,
46
+ batchSize: int,
47
+ maxFiles: int,
48
+ pdbxDict: str,
49
+ maDict: str,
50
+ rcsbDict: str,
51
+ ihmDict: str,
52
+ flrDict: 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
+ logger.warning("No list file found at %s", listfilepath)
73
+ return
74
+ f = open(listfilepath, "r", encoding="utf-8")
75
+ for line in f:
76
+ files.append(line.strip())
77
+ if 0 < maxFiles <= len(files):
78
+ break
79
+ f.close()
80
+ if len(files) < 1:
81
+ raise ValueError("No files found in %s" % listfilepath)
82
+
83
+ # determine batch size
84
+ if (batchSize is None) or not str(batchSize).isdigit():
85
+ batchSize = 1
86
+ batchSize = int(batchSize)
87
+ if batchSize <= 0:
88
+ batchSize = 1
89
+ logger.info("distributing %d files across %d sublists", len(files), batchSize)
90
+
91
+ # form dictionary object
92
+ dictionaryApi = getDictionaryApi(pdbxDict, maDict, rcsbDict, ihmDict, flrDict)
93
+
94
+ # traverse sublist and send each input file to converter
95
+ temppath = tempfile.mkdtemp()
96
+ if batchSize == 1:
97
+ # process one file at a time
98
+ for line in files:
99
+ args = (
100
+ line,
101
+ remotePath,
102
+ updateBase,
103
+ outfileSuffix,
104
+ outputContentType,
105
+ outputHash,
106
+ inputHash,
107
+ contentType,
108
+ dictionaryApi,
109
+ temppath,
110
+ )
111
+ singleTask(*args)
112
+ elif batchSize > 1:
113
+ pool = multiprocessing.Pool(processes=batchSize)
114
+ results = []
115
+ for line in files:
116
+ entry = line.strip()
117
+ args = (
118
+ entry,
119
+ remotePath,
120
+ updateBase,
121
+ outfileSuffix,
122
+ outputContentType,
123
+ outputHash,
124
+ inputHash,
125
+ contentType,
126
+ dictionaryApi,
127
+ temppath,
128
+ )
129
+ results.append(pool.apply_async(singleTask, args))
130
+ for r in results:
131
+ r.get(timeout=60 * 5)
132
+ pool.close()
133
+ results.clear()
134
+
135
+ try:
136
+ if os.path.exists(temppath):
137
+ shutil.rmtree(temppath)
138
+ except Exception as e:
139
+ logger.error(str(e))
140
+
141
+ logger.info("Done with CIF to BCIF conversion")
142
+
143
+
144
+ def getDictionaryApi(
145
+ pdbxDict: str, maDict: str, rcsbDict: str, ihmDict: str, flrDict: str
146
+ ) -> DictionaryApi:
147
+ paths = [pdbxDict, maDict, rcsbDict, ihmDict, flrDict]
148
+ try:
149
+ adapter = IoAdapter(raiseExceptions=True)
150
+ containers = []
151
+ for path in paths:
152
+ containers += adapter.readFile(inputFilePath=path)
153
+ dictionaryApi = DictionaryApi(containerList=containers, consolidate=True)
154
+ except Exception as e:
155
+ raise FileNotFoundError("failed to create dictionary api: %s" % str(e)) from e
156
+ return dictionaryApi
157
+
158
+
159
+ def singleTask(
160
+ pdbId: str,
161
+ remotePath: str,
162
+ updateBase: str,
163
+ outfileSuffix: str,
164
+ outputContentType: bool,
165
+ outputHash: bool,
166
+ inputHash: bool,
167
+ contentType: str,
168
+ dictionaryApi: DictionaryApi,
169
+ temppath: str,
170
+ ) -> None:
171
+ remoteFileName = "%s%s" % (
172
+ getInputPdbId(pdbId, contentType),
173
+ outfileSuffix.replace(".bcif.gz", ".cif.gz").replace(".bcif", ".cif"),
174
+ )
175
+
176
+ # form input cifFilePath
177
+ if not remotePath.startswith("http"):
178
+ # local file
179
+ cifFilePath = os.path.join(remotePath, remoteFileName)
180
+ if inputHash:
181
+ cifFilePath = os.path.join(
182
+ remotePath,
183
+ getHash(getInputPdbId(pdbId, contentType), contentType),
184
+ remoteFileName,
185
+ )
186
+ if not os.path.exists(cifFilePath):
187
+ logger.warning("%s not found", cifFilePath)
188
+ return
189
+ else:
190
+ cifFilePath = getRemoteFilePath(
191
+ getInputPdbId(pdbId, contentType), contentType, remotePath, remoteFileName
192
+ )
193
+
194
+ # form output bcifFilePath
195
+ bcifFilePath = getBcifFilePath(
196
+ pdbId, outfileSuffix, updateBase, contentType, outputContentType, outputHash
197
+ )
198
+ if not bcifFilePath:
199
+ raise ValueError("could not form bcif file path for %s" % pdbId)
200
+
201
+ if os.path.exists(bcifFilePath):
202
+ # earlier timestamp ... overwrite
203
+ os.unlink(bcifFilePath)
204
+ if os.path.exists(bcifFilePath):
205
+ raise PermissionError("file %s not removed" % bcifFilePath)
206
+
207
+ # make nested directories
208
+ dirs = os.path.dirname(bcifFilePath)
209
+ if not os.path.exists(dirs):
210
+ os.makedirs(dirs)
211
+
212
+ # convert to bcif
213
+ result = convert(cifFilePath, bcifFilePath, temppath, dictionaryApi)
214
+ if not result:
215
+ raise Exception("failed to convert %s" % cifFilePath)
216
+
217
+
218
+ def getInputPdbId(pdbId: str, contentType: str) -> str:
219
+ """determine upper or lowercase id names for remote and local .cif input files"""
220
+ if contentType == ContentTypeEnum.COMPUTATIONAL.value:
221
+ return pdbId.upper()
222
+ return pdbId.lower()
223
+
224
+
225
+ def getOutputPdbId(pdbId: str) -> str:
226
+ """determine upper or lowercase id names for local .bcif output files"""
227
+ return pdbId.lower()
228
+
229
+
230
+ def getOutputContentType(contentType: str) -> str:
231
+ """prepended output folder name for local .bcif output files"""
232
+ if contentType in [ContentTypeEnum.EXPERIMENTAL.value, ContentTypeEnum.INTEGRATIVE.value]:
233
+ return "pdb"
234
+ return "csm"
235
+
236
+
237
+ def getHash(pdbId: str, contentType: str) -> str:
238
+ """get upper/lowercase pdb id prior to getting hash"""
239
+ result = pdbId[1:3]
240
+ if contentType == ContentTypeEnum.COMPUTATIONAL.value:
241
+ result = os.path.join(pdbId[0:2], pdbId[-6:-4], pdbId[-4:-2])
242
+ return result
243
+
244
+
245
+ def getRemoteFilePath(
246
+ pdbId: str, contentType: str, remotePath: str, remoteFileName: str
247
+ ) -> str:
248
+ """form hashed pash for remote cif file, only for input files"""
249
+ pdbId = getInputPdbId(pdbId, contentType)
250
+ result = os.path.join(remotePath, getHash(pdbId, contentType), remoteFileName)
251
+ if contentType == ContentTypeEnum.INTEGRATIVE.value:
252
+ result = os.path.join(
253
+ remotePath, getHash(pdbId, contentType), pdbId, "structures", remoteFileName
254
+ )
255
+ return result
256
+
257
+
258
+ def getBcifFilePath(
259
+ pdbId: str,
260
+ outfileSuffix: str,
261
+ updateBase: str,
262
+ contentType: str,
263
+ outputContentType: bool,
264
+ outputHash: bool,
265
+ ) -> Optional[str]:
266
+ """form optionally hashed path for local bcif file, only for output files"""
267
+ pdbId = getOutputPdbId(pdbId)
268
+ bcifFileName = "%s%s" % (pdbId, outfileSuffix)
269
+ bcifFilePath = None
270
+ if contentType in [
271
+ ContentTypeEnum.EXPERIMENTAL.value,
272
+ ContentTypeEnum.INTEGRATIVE.value,
273
+ ]:
274
+ if outputContentType and outputHash:
275
+ bcifFilePath = os.path.join(
276
+ updateBase, getOutputContentType(contentType), getHash(pdbId, contentType), bcifFileName
277
+ )
278
+ elif outputContentType:
279
+ bcifFilePath = os.path.join(updateBase, getOutputContentType(contentType), bcifFileName)
280
+ elif outputHash:
281
+ bcifFilePath = os.path.join(
282
+ updateBase, getHash(pdbId, contentType), bcifFileName
283
+ )
284
+ else:
285
+ bcifFilePath = os.path.join(updateBase, bcifFileName)
286
+ elif contentType == ContentTypeEnum.COMPUTATIONAL.value:
287
+ if outputContentType and outputHash:
288
+ bcifFilePath = os.path.join(
289
+ updateBase,
290
+ getOutputContentType(contentType),
291
+ getHash(pdbId, contentType),
292
+ bcifFileName,
293
+ )
294
+ elif outputContentType:
295
+ bcifFilePath = os.path.join(
296
+ updateBase,
297
+ getOutputContentType(contentType),
298
+ bcifFileName,
299
+ )
300
+ elif outputHash:
301
+ bcifFilePath = os.path.join(
302
+ updateBase,
303
+ getHash(pdbId, contentType),
304
+ bcifFileName,
305
+ )
306
+ else:
307
+ bcifFilePath = os.path.join(
308
+ updateBase,
309
+ bcifFileName,
310
+ )
311
+ return bcifFilePath
312
+
313
+
314
+ def convert(
315
+ infile: str, outfile: str, workpath: str, dictionaryApi: DictionaryApi
316
+ ) -> bool:
317
+ mu = MarshalUtil(workPath=workpath)
318
+ data = mu.doImport(infile, fmt="mmcif")
319
+ result = mu.doExport(outfile, data, fmt="bcif", dictionaryApi=dictionaryApi)
320
+ if not result:
321
+ return False
322
+ return True
323
+
324
+
325
+ def deconvert(
326
+ infile: str, outfile: str, workpath: str, dictionaryApi: DictionaryApi
327
+ ) -> bool:
328
+ mu = MarshalUtil(workPath=workpath)
329
+ data = mu.doImport(infile, fmt="bcif")
330
+ result = mu.doExport(outfile, data, fmt="mmcif", dictionaryApi=dictionaryApi)
331
+ if not result:
332
+ return False
333
+ return True
@@ -0,0 +1,96 @@
1
+ ##
2
+ # File: ChemCompFileWorkflow.py
3
+ # Date: 10-Mar-2020 jdw
4
+ #
5
+ # Workflow wrapper -- chemical component file conversion generator --
6
+ #
7
+ # Updates:
8
+ #
9
+ ##
10
+ __docformat__ = "google en"
11
+ __author__ = "John Westbrook"
12
+ __email__ = "jwest@rcsb.rutgers.edu"
13
+ __license__ = "Apache 2.0"
14
+
15
+ import logging
16
+ import os
17
+
18
+ from rcsb.utils.chem.OeIoUtils import OeIoUtils
19
+ from rcsb.utils.chem.OeMoleculeProvider import OeMoleculeProvider
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class ChemCompFileWorkflow(object):
25
+ def __init__(self, **kwargs):
26
+ """Module entry point for chemical component definition 2D image generation
27
+
28
+ Args:
29
+ ccUrlTarget (str): URL or path for concatenated chemical component dictionary (default: public wwPDB ftp)
30
+ birdUrlTarget (str): URL or path for concatenated BIRD dictionary (default: public wwPDB ftp)
31
+ licenseFilePath (str) = path to OpenEye license text file
32
+ fileDirPath(str): directory containing generated image tree
33
+ cachePath(str): cache directory for temporary files
34
+ molBuildType(str): build type for constructing OE moleclues ('ideal-xyz', 'model-xyz' default: 'ideal-xyz')
35
+ """
36
+ #
37
+ ccUrlTarget = kwargs.get("ccUrlTarget", None)
38
+ birdUrlTarget = kwargs.get("birdUrlTarget", None)
39
+ self.__licensePath = kwargs.get("licenseFilePath", "oe_license.txt")
40
+ self.__fileDirPath = kwargs.get("fileDirPath", ".")
41
+ self.__molBuildType = kwargs.get("molBuildType", "ideal-xyz")
42
+ cachePath = kwargs.get("cachePath", ".")
43
+ cachePath = os.path.abspath(cachePath)
44
+
45
+ #
46
+ self.__oemp = OeMoleculeProvider(
47
+ ccUrlTarget=ccUrlTarget,
48
+ birdUrlTarget=birdUrlTarget,
49
+ ccFileNamePrefix="cc-full",
50
+ cachePath=cachePath,
51
+ molBuildType=self.__molBuildType,
52
+ useCache=True,
53
+ oeFileNamePrefix="oe-full",
54
+ )
55
+ self.__oeMolD = self.__oemp.getOeMolD()
56
+
57
+ def __setLicense(self, licensePath):
58
+ ok = False
59
+ try:
60
+ if os.environ.get("OE_LICENSE") and os.access(os.environ["OE_LICENSE"], os.R_OK):
61
+ logger.info("Using license from environment %r", os.environ["OE_LICENSE"])
62
+ ok = True
63
+ elif os.access(licensePath, os.R_OK):
64
+ os.environ["OE_LICENSE"] = licensePath
65
+ logger.info("Setting environmenal variable OE_LICENSE to %r", os.environ["OE_LICENSE"])
66
+ ok = True
67
+ except Exception as e:
68
+ logger.error("Setting license file %r failing %s", licensePath, str(e))
69
+ return ok
70
+
71
+ def testCache(self):
72
+ return self.__oemp.testCache() if self.__oemp else False
73
+
74
+ def makeFiles(self, fmt="sdf"):
75
+ """Create files (mol, mol2) for all public chemical components."""
76
+ try:
77
+
78
+ if fmt not in ["mol", "mol2", "mol2h", "sdf"]:
79
+ return False
80
+ if not self.__setLicense(self.__licensePath):
81
+ logger.error("Invalid license details - exiting")
82
+ return False
83
+ for ccId, oeMol in self.__oeMolD.items():
84
+ if self.__molBuildType == "ideal-xyz":
85
+ filePath = os.path.join(self.__fileDirPath, fmt, ccId[0], ccId + "_ideal." + fmt)
86
+ oeioU = OeIoUtils()
87
+ oeioU.write(filePath, oeMol, constantMol=True)
88
+ else:
89
+ filePath = os.path.join(self.__fileDirPath, fmt, ccId[0], ccId + "_model." + fmt)
90
+ oeioU = OeIoUtils()
91
+ oeioU.write(filePath, oeMol, constantMol=True)
92
+
93
+ return True
94
+ except Exception as e:
95
+ logger.exception("Failing with %s", str(e))
96
+ return False
@@ -0,0 +1,133 @@
1
+ ##
2
+ # File: ChemCompImageWorkflow.py
3
+ # Date: 10-Mar-2020 jdw
4
+ #
5
+ # Workflow wrapper -- chemical component image generation --
6
+ #
7
+ # Updates:
8
+ #
9
+ ##
10
+ __docformat__ = "google en"
11
+ __author__ = "John Westbrook"
12
+ __email__ = "jwest@rcsb.rutgers.edu"
13
+ __license__ = "Apache 2.0"
14
+
15
+ import logging
16
+ import os
17
+
18
+ from rcsb.utils.chem.OeDepict import OeDepict
19
+ from rcsb.utils.chem.OeMoleculeProvider import OeMoleculeProvider
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class ChemCompImageWorkflow(object):
25
+ def __init__(self, **kwargs):
26
+ """Module entry point for chemical component definition 2D image generation
27
+
28
+ Args:
29
+ ccUrlTarget (str): URL or path for concatenated chemical component dictionary (default: public wwPDB ftp)
30
+ birdUrlTarget (str): URL or path for concatenated BIRD dictionary (default: public wwPDB ftp)
31
+ licenseFilePath (str) = path to OpenEye license text file
32
+ imagePath(str): directory containing generated image tree
33
+ cachePath(str): cache directory for temporary files
34
+
35
+ """
36
+ #
37
+ ccUrlTarget = kwargs.get("ccUrlTarget", None)
38
+ birdUrlTarget = kwargs.get("birdUrlTarget", None)
39
+ self.__licensePath = kwargs.get("licenseFilePath", "oe_license.txt")
40
+ self.__imagePath = kwargs.get("imagePath", ".")
41
+ cachePath = kwargs.get("cachePath", ".")
42
+ cachePath = os.path.abspath(cachePath)
43
+
44
+ #
45
+ # changed molBuildType from "model-xyz" to "connection-table" per ticket RO-3041
46
+ self.__oemp = OeMoleculeProvider(
47
+ ccUrlTarget=ccUrlTarget,
48
+ birdUrlTarget=birdUrlTarget,
49
+ ccFileNamePrefix="cc-full",
50
+ cachePath=cachePath,
51
+ molBuildType="connection-table",
52
+ useCache=True,
53
+ oeFileNamePrefix="oe-full",
54
+ )
55
+ self.__oeMolD = self.__oemp.getOeMolD()
56
+
57
+ def __setLicense(self, licensePath):
58
+ ok = False
59
+ try:
60
+ if os.environ.get("OE_LICENSE") and os.access(os.environ["OE_LICENSE"], os.R_OK):
61
+ logger.info("Using license from environment %r", os.environ["OE_LICENSE"])
62
+ ok = True
63
+ elif os.access(licensePath, os.R_OK):
64
+ os.environ["OE_LICENSE"] = licensePath
65
+ logger.info("Setting environmenal variable OE_LICENSE to %r", os.environ["OE_LICENSE"])
66
+ ok = True
67
+ except Exception as e:
68
+ logger.error("Setting license file %r failing %s", licensePath, str(e))
69
+ return ok
70
+
71
+ def testCache(self):
72
+ return self.__oemp.testCache() if self.__oemp else False
73
+
74
+ def makeImages(self):
75
+ """Create images for all public chemical components with and without atom labels."""
76
+ try:
77
+ if not self.__setLicense(self.__licensePath):
78
+ logger.error("Invalid license details - exiting")
79
+ return False
80
+ for ccId, oeMol in self.__oeMolD.items():
81
+ imagePath = os.path.join(self.__imagePath, "image", ccId[0], ccId + ".svg")
82
+ oed = OeDepict()
83
+ title = ""
84
+ oed.setMolTitleList([(ccId, oeMol, title)])
85
+ # ---
86
+ bondDisplayWidth = 10.0
87
+ numAtoms = oeMol.NumAtoms()
88
+ if numAtoms > 100 and numAtoms <= 200:
89
+ bondDisplayWidth = 6.0
90
+ elif numAtoms > 200:
91
+ bondDisplayWidth = 4.0
92
+ # ---
93
+ oed.setDisplayOptions(
94
+ labelAtomName=False,
95
+ labelAtomCIPStereo=True,
96
+ labelAtomIndex=False,
97
+ labelBondIndex=False,
98
+ labelBondCIPStereo=True,
99
+ cellBorders=False,
100
+ bondDisplayWidth=bondDisplayWidth,
101
+ )
102
+ oed.setGridOptions(rows=1, cols=1, cellBorders=False)
103
+ oed.prepare()
104
+ oed.write(imagePath)
105
+ for ccId, oeMol in self.__oeMolD.items():
106
+ imagePath = os.path.join(self.__imagePath, "image_labeled", ccId[0], ccId + ".svg")
107
+ oed = OeDepict()
108
+ title = ""
109
+ oed.setMolTitleList([(ccId, oeMol, title)])
110
+ # ---
111
+ bondDisplayWidth = 10.0
112
+ numAtoms = oeMol.NumAtoms()
113
+ if numAtoms > 100 and numAtoms <= 200:
114
+ bondDisplayWidth = 6.0
115
+ elif numAtoms > 200:
116
+ bondDisplayWidth = 4.0
117
+ # ---
118
+ oed.setDisplayOptions(
119
+ labelAtomName=True,
120
+ labelAtomCIPStereo=True,
121
+ labelAtomIndex=False,
122
+ labelBondIndex=False,
123
+ labelBondCIPStereo=True,
124
+ cellBorders=False,
125
+ bondDisplayWidth=bondDisplayWidth,
126
+ )
127
+ oed.setGridOptions(rows=1, cols=1, cellBorders=False)
128
+ oed.prepare()
129
+ oed.write(imagePath)
130
+ return True
131
+ except Exception as e:
132
+ logger.exception("Failing with %s", str(e))
133
+ return False
@@ -0,0 +1,99 @@
1
+ ##
2
+ # File: ChemCompIndexWorkflow.py
3
+ # Date: 2-Jun-2020 jdw
4
+ #
5
+ # Workflow wrapper -- generate chemical component and BIRD search indices --
6
+ #
7
+ # Updates:
8
+ # 10-Jun-2020 jdw Hookup to ChemCompSearchWrapper()
9
+ ##
10
+ __docformat__ = "google en"
11
+ __author__ = "John Westbrook"
12
+ __email__ = "jwest@rcsb.rutgers.edu"
13
+ __license__ = "Apache 2.0"
14
+
15
+ import logging
16
+ import os
17
+
18
+ from rcsb.utils.chem.ChemCompSearchWrapper import ChemCompSearchWrapper
19
+
20
+ logger = logging.getLogger(__name__)
21
+
22
+
23
+ class ChemCompSearchIndexWorkflow(object):
24
+ def __init__(self, **kwargs):
25
+ """Module entry point for chemical component and BIRD search index generation workflow.
26
+
27
+ Args:
28
+ cachePath(str, optional): cache directory to store indices and temporary files (default: '.')
29
+ licenseFilePath (str, optional) = path to OpenEye license text file (default: use enviroment OE_LICENSE setting)
30
+ ccFilNamePrefix (str, optional) = index prefix (default: "cc-full")
31
+ """
32
+ self.__licensePath = kwargs.get("licenseFilePath", "oe_license.txt")
33
+ cachePath = kwargs.get("cachePath", ".")
34
+ self.__cachePath = os.path.abspath(cachePath)
35
+ self.__ccFileNamePrefix = kwargs.get("ccFilNamePrefix", "cc-full")
36
+ self.__ccsw = ChemCompSearchWrapper(cachePath=self.__cachePath, ccFileNamePrefix=self.__ccFileNamePrefix)
37
+
38
+ def __setLicense(self, licensePath):
39
+ ok = False
40
+ try:
41
+ if os.environ.get("OE_LICENSE") and os.access(os.environ["OE_LICENSE"], os.R_OK):
42
+ logger.info("Using license from environment %r", os.environ["OE_LICENSE"])
43
+ ok = True
44
+ elif os.access(licensePath, os.R_OK):
45
+ os.environ["OE_LICENSE"] = licensePath
46
+ logger.info("Setting environmenal variable OE_LICENSE to %r", os.environ["OE_LICENSE"])
47
+ ok = True
48
+ except Exception as e:
49
+ logger.error("Setting Openeye license file %r failing %s", licensePath, str(e))
50
+ return ok
51
+
52
+ def testCache(self):
53
+ return True
54
+
55
+ def makeIndices(self, ccUrlTarget, birdUrlTarget, **kwargs):
56
+ """Build chemical component and BIRD search indices.
57
+
58
+ Args:
59
+ ccUrlTarget (str): URL or path for concatenated chemical component dictionary
60
+ birdUrlTarget (str): URL or path for concatenated BIRD dictionary
61
+
62
+ Other arguments may be supplied to change defaults for index generators (testing/troubleshooting)
63
+
64
+ Returns:
65
+ bool: True for success or False otherwise
66
+
67
+ """
68
+ ok = False
69
+ if not self.__setLicense(self.__licensePath):
70
+ logger.error("Invalid OpenEye license details - exiting")
71
+ return ok
72
+ #
73
+ try:
74
+ ok = self.__ccsw.buildDependenices(ccUrlTarget, birdUrlTarget, **kwargs)
75
+ except Exception as e:
76
+ logger.exception("Failing with %s", str(e))
77
+ return ok
78
+
79
+ def stashIndices(self, url, dirPath, bundleLabel="A", userName=None, pw=None):
80
+ """Store a copy of the bundled search dependencies remotely -
81
+
82
+ Args:
83
+ url (str): URL string for the destination host (e.g. sftp://myserver.net or None for a local file)
84
+ dirPath (str): directory path on the remote resource
85
+ bundleLabel (str, optional): optional label preppended to the stashed dependency bundle artifact (default='A')
86
+ userName (str, optional): optional access information. Defaults to None.
87
+ password (str, optional): optional access information. Defaults to None.
88
+
89
+ Returns:
90
+ bool: True for success or False otherwise
91
+
92
+ """
93
+ #
94
+ ok = False
95
+ try:
96
+ ok = self.__ccsw.stashDependencies(url, dirPath, bundleLabel=bundleLabel, userName=userName, pw=pw)
97
+ except Exception as e:
98
+ logger.exception("Failing with %s", str(e))
99
+ return ok
File without changes