rcsb.db 1.812__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 (49) hide show
  1. rcsb/__init__.py +1 -0
  2. rcsb/db/__init__.py +1 -0
  3. rcsb/db/cli/ETLExec.py +180 -0
  4. rcsb/db/cli/RepoHoldingsEtlWorker.py +224 -0
  5. rcsb/db/cli/RepoLoadExec.py +323 -0
  6. rcsb/db/cli/RepoScanExec.py +235 -0
  7. rcsb/db/cli/SchemaUpdateExec.py +223 -0
  8. rcsb/db/cli/SequenceClustersEtlWorker.py +184 -0
  9. rcsb/db/cli/__init__.py +0 -0
  10. rcsb/db/config/exdb-config-example.yml +292 -0
  11. rcsb/db/define/ContentDefinition.py +741 -0
  12. rcsb/db/define/DataTypeApiProvider.py +110 -0
  13. rcsb/db/define/DataTypeApplicationInfo.py +489 -0
  14. rcsb/db/define/DataTypeInstanceInfo.py +125 -0
  15. rcsb/db/define/SchemaDefAccess.py +918 -0
  16. rcsb/db/define/SchemaDefAccess.py-prev +34 -0
  17. rcsb/db/define/SchemaDefBuild.py +1299 -0
  18. rcsb/db/define/__init__.py +0 -0
  19. rcsb/db/helpers/ContentDefinitionHelper.py +420 -0
  20. rcsb/db/helpers/DocumentDefinitionHelper.py +1006 -0
  21. rcsb/db/helpers/__init__.py +0 -0
  22. rcsb/db/mongo/Connection.py +116 -0
  23. rcsb/db/mongo/ConnectionBase.py +175 -0
  24. rcsb/db/mongo/DocumentLoader.py +366 -0
  25. rcsb/db/mongo/MongoDbUtil.py +562 -0
  26. rcsb/db/mongo/PdbxLoader.py +1253 -0
  27. rcsb/db/mongo/__init__.py +0 -0
  28. rcsb/db/processors/ClusterDataPrep.py +185 -0
  29. rcsb/db/processors/DataExchangeStatus.py +151 -0
  30. rcsb/db/processors/DataTransformFactory.py +468 -0
  31. rcsb/db/processors/RepoHoldingsDataPrep.py +711 -0
  32. rcsb/db/processors/RepoHoldingsRemoteDataPrep.py +174 -0
  33. rcsb/db/processors/SchemaDefDataPrep.py +795 -0
  34. rcsb/db/processors/SchemaDefReShape.py +596 -0
  35. rcsb/db/processors/__init__.py +0 -0
  36. rcsb/db/utils/CaseNormalizedDict.py +106 -0
  37. rcsb/db/utils/PdbxSchemaMapReader.py +299 -0
  38. rcsb/db/utils/ProvenanceProvider.py +106 -0
  39. rcsb/db/utils/SchemaProvider.py +499 -0
  40. rcsb/db/utils/TextUtil.py +46 -0
  41. rcsb/db/utils/TimeUtil.py +80 -0
  42. rcsb/db/utils/__init__.py +0 -0
  43. rcsb/db/wf/RepoLoadWorkflow.py +615 -0
  44. rcsb/db/wf/__init__.py +0 -0
  45. rcsb_db-1.812.dist-info/METADATA +541 -0
  46. rcsb_db-1.812.dist-info/RECORD +49 -0
  47. rcsb_db-1.812.dist-info/WHEEL +4 -0
  48. rcsb_db-1.812.dist-info/entry_points.txt +5 -0
  49. rcsb_db-1.812.dist-info/licenses/LICENSE +12 -0
rcsb/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
rcsb/db/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __path__ = __import__("pkgutil").extend_path(__path__, __name__)
rcsb/db/cli/ETLExec.py ADDED
@@ -0,0 +1,180 @@
1
+ ##
2
+ # File: ETLExec.py
3
+ # Date: 2-Jul-2018 jdw
4
+ #
5
+ # Execution wrapper -- ETL utilities for derived and remote data sources -
6
+ #
7
+ # Updates:
8
+ # 15-Jul-2018 jdw add repository holdings, move all path configuration to a separate site dependent config section.
9
+ # 9-Dec-2018 jdw add chemical reference ETL options
10
+ # 4-Jan-2019 jdw differentiate config sections for provenance
11
+ # 9-Apr-2019 jdw add tree node list loader
12
+ # 25-Apr-2019 jdw move the --etl_tree_node_lists function to the rcsb.exdb package.
13
+ # 2-Sep-2019 jdw add cache options and move trees and chemref to module rcsb.exdb
14
+ #
15
+ ##
16
+ __docformat__ = "restructuredtext en"
17
+ __author__ = "John Westbrook"
18
+ __email__ = "jwest@rcsb.rutgers.edu"
19
+ __license__ = "Apache 2.0"
20
+
21
+ import argparse
22
+ import logging
23
+ import os
24
+ import sys
25
+
26
+ from rcsb.db.cli.RepoHoldingsEtlWorker import RepoHoldingsEtlWorker
27
+ from rcsb.db.cli.SequenceClustersEtlWorker import SequenceClustersEtlWorker
28
+
29
+ # from rcsb.db.cli.TreeNodeListWorker import TreeNodeListWorker
30
+ from rcsb.utils.dictionary.DictMethodResourceProvider import DictMethodResourceProvider
31
+ from rcsb.db.mongo.DocumentLoader import DocumentLoader
32
+ from rcsb.db.utils.TimeUtil import TimeUtil
33
+ from rcsb.utils.config.ConfigUtil import ConfigUtil
34
+
35
+ HERE = os.path.abspath(os.path.dirname(__file__))
36
+ TOPDIR = os.path.dirname(os.path.dirname(os.path.dirname(HERE)))
37
+
38
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s]-%(module)s.%(funcName)s: %(message)s")
39
+ logger = logging.getLogger()
40
+
41
+
42
+ def loadStatus(statusList, cfgOb, cachePath, readBackCheck=True):
43
+ sectionName = "data_exchange_configuration"
44
+ dl = DocumentLoader(cfgOb, cachePath, "MONGO_DB", numProc=2, chunkSize=2, documentLimit=None, verbose=False, readBackCheck=readBackCheck)
45
+ #
46
+ databaseName = cfgOb.get("DATABASE_NAME", sectionName=sectionName)
47
+ collectionName = cfgOb.get("COLLECTION_UPDATE_STATUS", sectionName=sectionName)
48
+ ok = dl.load(databaseName, collectionName, loadType="append", documentList=statusList, indexAttributeList=["update_id", "database_name", "object_name"], keyNames=None)
49
+ return ok
50
+
51
+
52
+ def buildResourceCache(cfgOb, configName, cachePath, rebuildCache=False):
53
+ """Generate and cache resource dependencies."""
54
+ ret = False
55
+ try:
56
+ rp = DictMethodResourceProvider(cfgOb, configName=configName, cachePath=cachePath)
57
+ ret = rp.cacheResources(useCache=not rebuildCache)
58
+ except Exception as e:
59
+ logger.exception("Failing with %s", str(e))
60
+ return ret
61
+
62
+
63
+ def main():
64
+ parser = argparse.ArgumentParser()
65
+ #
66
+ defaultConfigName = "site_info_configuration"
67
+ #
68
+ parser.add_argument("--full", default=True, action="store_true", help="Fresh full load in a new tables/collections (Default)")
69
+ #
70
+ parser.add_argument("--etl_entity_sequence_clusters", default=False, action="store_true", help="ETL entity sequence clusters")
71
+ parser.add_argument("--etl_repository_holdings", default=False, action="store_true", help="ETL repository holdings")
72
+ # parser.add_argument("--etl_chemref", default=False, action="store_true", help="ETL integrated chemical reference data")
73
+ # parser.add_argument("--etl_tree_node_lists", default=False, action='store_true', help="ETL tree node lists")
74
+
75
+ parser.add_argument("--data_set_id", default=None, help="Data set identifier (default= 2018_14 for current week)")
76
+ #
77
+ parser.add_argument("--sequence_cluster_data_path", default=None, help="Sequence cluster data path (default set by configuration")
78
+ parser.add_argument("--sandbox_data_path", default=None, help="Date exchange sandboxPath data path (default set by configuration")
79
+
80
+ #
81
+ parser.add_argument("--config_path", default=None, help="Path to configuration options file")
82
+ parser.add_argument("--config_name", default=defaultConfigName, help="Configuration section name")
83
+
84
+ parser.add_argument("--db_type", default="mongo", help="Database server type (default=mongo)")
85
+
86
+ # parser.add_argument("--document_style", default="rowwise_by_name_with_cardinality",
87
+ # help="Document organization (rowwise_by_name_with_cardinality|rowwise_by_name|columnwise_by_name|rowwise_by_id|rowwise_no_name")
88
+ parser.add_argument("--read_back_check", default=False, action="store_true", help="Perform read back check on all documents")
89
+ #
90
+ parser.add_argument("--num_proc", default=2, help="Number of processes to execute (default=2)")
91
+ parser.add_argument("--chunk_size", default=10, help="Number of files loaded per process")
92
+ parser.add_argument("--document_limit", default=None, help="Load document limit for testing")
93
+ parser.add_argument("--prune_document_size", default=None, help="Prune large documents to this size limit (MB)")
94
+ parser.add_argument("--debug", default=False, action="store_true", help="Turn on verbose logging")
95
+ parser.add_argument("--mock", default=False, action="store_true", help="Use MOCK repository configuration for testing")
96
+ parser.add_argument("--cache_path", default=None, help="Path containing cache directories")
97
+ # parser.add_argument("--use_cache", default=False, action="store_true", help="Use cache files from remote resources")
98
+ parser.add_argument("--rebuild_cache", default=False, action="store_true", help="Rebuild cached resource files")
99
+ # parser.add_argument("--rebuild_schema", default=False, action="store_true", help="Rebuild schema on-the-fly if not cached")
100
+ #
101
+ #
102
+ args = parser.parse_args()
103
+ #
104
+ debugFlag = args.debug
105
+ if debugFlag:
106
+ logger.setLevel(logging.DEBUG)
107
+ # ----------------------- - ----------------------- - ----------------------- - ----------------------- - ----------------------- -
108
+ # Configuration Details
109
+ configPath = args.config_path
110
+ configName = args.config_name
111
+ # useCache = args.use_cache
112
+ if not configPath:
113
+ configPath = os.getenv("DBLOAD_CONFIG_PATH", None)
114
+ try:
115
+ if os.access(configPath, os.R_OK):
116
+ os.environ["DBLOAD_CONFIG_PATH"] = configPath
117
+ logger.info("Using configuation path %s (%s)", configPath, configName)
118
+ else:
119
+ logger.error("Missing or access issue with config file %r", configPath)
120
+ exit(1)
121
+ mockTopPath = os.path.join(TOPDIR, "rcsb", "mock-data") if args.mock else None
122
+ cfgOb = ConfigUtil(configPath=configPath, defaultSectionName=defaultConfigName, mockTopPath=mockTopPath)
123
+ if configName != defaultConfigName:
124
+ cfgOb.replaceSectionName(defaultConfigName, configName)
125
+ #
126
+ except Exception as e:
127
+ logger.error("Missing or access issue with config file %r with %s", configPath, str(e))
128
+ exit(1)
129
+
130
+ #
131
+ try:
132
+ readBackCheck = args.read_back_check
133
+ tU = TimeUtil()
134
+ dataSetId = args.data_set_id if args.data_set_id else tU.getCurrentWeekSignature()
135
+ seqDataLocator = args.sequence_cluster_data_path if args.sequence_cluster_data_path else cfgOb.getPath("RCSB_SEQUENCE_CLUSTER_DATA_PATH", sectionName=configName)
136
+ sandboxPath = args.sandbox_data_path if args.sandbox_data_path else cfgOb.getPath("RCSB_EXCHANGE_SANDBOX_PATH", sectionName=configName)
137
+ numProc = int(args.num_proc)
138
+ chunkSize = int(args.chunk_size)
139
+ documentLimit = int(args.document_limit) if args.document_limit else None
140
+
141
+ loadType = "full" if args.full else "replace"
142
+ # loadType = 'replace' if args.replace else 'full'
143
+
144
+ cachePath = args.cache_path if args.cache_path else "."
145
+ rebuildCache = args.rebuild_cache if args.rebuild_cache else False
146
+ # rebuildSchemaFlag = args.rebuild_schema if args.rebuild_schema else False
147
+ #
148
+ # if args.document_style not in ['rowwise_by_name', 'rowwise_by_name_with_cardinality', 'columnwise_by_name', 'rowwise_by_id', 'rowwise_no_name']:
149
+ # logger.error("Unsupported document style %s" % args.document_style)
150
+
151
+ if args.db_type != "mongo":
152
+ logger.error("Unsupported database server type %s", args.db_type)
153
+ except Exception as e:
154
+ logger.exception("Argument processing problem %s", str(e))
155
+ parser.print_help(sys.stderr)
156
+ exit(1)
157
+ # ----------------------- - ----------------------- - ----------------------- - ----------------------- - ----------------------- -
158
+ # Rebuild or check resource cache
159
+ ok = buildResourceCache(cfgOb, configName, cachePath, rebuildCache=rebuildCache)
160
+ if not ok:
161
+ logger.error("Cache rebuild or check failure (rebuild %r) %r", rebuildCache, cachePath)
162
+ exit(1)
163
+ ##
164
+ if args.db_type == "mongo":
165
+ okS = True
166
+ if args.etl_entity_sequence_clusters:
167
+ cw = SequenceClustersEtlWorker(cfgOb, numProc=numProc, chunkSize=chunkSize, documentLimit=documentLimit, verbose=debugFlag, readBackCheck=readBackCheck, workPath=cachePath)
168
+ ok = cw.etl(dataSetId, seqDataLocator, loadType=loadType)
169
+ okS = loadStatus(cw.getLoadStatus(), cfgOb, cachePath, readBackCheck=readBackCheck)
170
+
171
+ if args.etl_repository_holdings:
172
+ rhw = RepoHoldingsEtlWorker(cfgOb, sandboxPath, cachePath, numProc=numProc, chunkSize=chunkSize, documentLimit=documentLimit, verbose=debugFlag, readBackCheck=readBackCheck)
173
+ ok = rhw.load(dataSetId)
174
+ okS = loadStatus(rhw.getLoadStatus(), cfgOb, cachePath, readBackCheck=readBackCheck)
175
+
176
+ logger.info("Operation completed with status %r " % ok and okS)
177
+
178
+
179
+ if __name__ == "__main__":
180
+ main()
@@ -0,0 +1,224 @@
1
+ ##
2
+ # File: RepoHoldingsEtlWorker.py
3
+ # Date: 2-Jul-2018 jdw
4
+ #
5
+ # ETL utilities for processing repository holding data.
6
+ # Updates:
7
+ # 15-Jul-2018 jdw split out to separate module and add status tracking
8
+ # 26-Nov-2018 jdw add COLLECTION_HOLDINGS_PRERELEASE
9
+ # 14-Dec-2019 jdw reorganize and consolidate repository_holdings collections
10
+ # 25-Sep-2021 jdw substitute RepoHoldingsRemoteDataPrep() for data processing
11
+ # 4-Apr-2023 dwp Add maxStepLength input argument; update success/failure catching logic;
12
+ # add final verification step to ensure all entries were loaded
13
+ # 16-Oct-2024 dwp Remove usage of EDMAPS holdings file
14
+ # 18-Feb-2025 dwp Add support for IHM repository holdings file loading;
15
+ # Change indexed field to be 'rcsb_id'
16
+ # 15-Jul-2025 dwp Adjust loader to load holdings data to DW repository_holdings collections;
17
+ # Turn off loading of repository_holdings_update_entry (since not used by anything downstream);
18
+ # Use indexes defined in py-rcsb_exdb_assets schemas and configuration
19
+ # 6-Aug-2025 dwp Make use of schema configuration file for loading collections and setting indexed fields
20
+ # 6-Oct-2025 dwp Turned OFF loading of "repository_holdings_update_entry" collection as part of transition to DW consolidation (since not used by anything)
21
+ #
22
+ ##
23
+ __docformat__ = "restructuredtext en"
24
+ __author__ = "John Westbrook"
25
+ __email__ = "jwest@rcsb.rutgers.edu"
26
+ __license__ = "Apache 2.0"
27
+
28
+ import logging
29
+ import os
30
+
31
+ from rcsb.db.mongo.DocumentLoader import DocumentLoader
32
+ from rcsb.db.processors.DataExchangeStatus import DataExchangeStatus
33
+ from rcsb.db.processors.RepoHoldingsDataPrep import RepoHoldingsDataPrep
34
+ from rcsb.db.processors.RepoHoldingsRemoteDataPrep import RepoHoldingsRemoteDataPrep
35
+ from rcsb.db.mongo.Connection import Connection
36
+ from rcsb.db.mongo.MongoDbUtil import MongoDbUtil
37
+ from rcsb.db.utils.SchemaProvider import SchemaProvider
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+
42
+ class RepoHoldingsEtlWorker(object):
43
+ """Prepare and load repository holdings and repository update data."""
44
+
45
+ def __init__(self, cfgOb, sandboxPath, cachePath, numProc=2, chunkSize=10, maxStepLength=4000, readBackCheck=False, documentLimit=None, verbose=False):
46
+ self.__cfgOb = cfgOb
47
+ self.__cfgSectionName = self.__cfgOb.getDefaultSectionName()
48
+ self.__sandboxPath = sandboxPath
49
+ self.__cachePath = cachePath
50
+ self.__readBackCheck = readBackCheck
51
+ self.__numProc = numProc
52
+ self.__chunkSize = chunkSize
53
+ self.__maxStepLength = maxStepLength
54
+ self.__documentLimit = documentLimit
55
+ self.__resourceName = "MONGO_DB"
56
+ self.__filterType = "assign-dates"
57
+ self.__verbose = verbose
58
+ self.__statusList = []
59
+ #
60
+ self.__collectionGroupName = "repository_holdings"
61
+ self.__schP = SchemaProvider(self.__cfgOb, self.__cachePath)
62
+ self.__databaseNameMongo = self.__schP.getDatabaseMongoName(collectionGroupName=self.__collectionGroupName)
63
+
64
+ def __updateStatus(self, updateId, databaseName, collectionName, status, startTimestamp):
65
+ try:
66
+ sFlag = "Y" if status else "N"
67
+ desp = DataExchangeStatus()
68
+ desp.setStartTime(tS=startTimestamp)
69
+ desp.setObject(databaseName, collectionName)
70
+ desp.setStatus(updateId=updateId, successFlag=sFlag)
71
+ desp.setEndTime()
72
+ self.__statusList.append(desp.getStatus())
73
+ return True
74
+ except Exception as e:
75
+ logger.exception("Failing with %s", str(e))
76
+ return False
77
+
78
+ def load(self, updateId):
79
+ # First load PDB holdings (with loadType="full")
80
+ ok1 = self.loadRepoType(updateId, loadType="full", repoType="pdb")
81
+ #
82
+ # Next load IHM holdings (with loadType="replace")
83
+ ok2 = self.loadRepoType(updateId, loadType="replace", repoType="pdb_ihm")
84
+ #
85
+ # Last, verify all pdbx_core data has been loaded (based on repository holdings)
86
+ ok3 = self.verifyCompleteLoad()
87
+ logger.info("Verification of complete load status %r", ok3)
88
+ #
89
+ ok = ok1 and ok2 and ok3
90
+ return ok
91
+
92
+ def loadRepoType(self, updateId, loadType="full", repoType="pdb"):
93
+ """Load legacy repository holdings and status data -
94
+ """
95
+ try:
96
+ self.__statusList = []
97
+ desp = DataExchangeStatus()
98
+ statusStartTimestamp = desp.setStartTime()
99
+ # ---
100
+ discoveryMode = self.__cfgOb.get("DISCOVERY_MODE", sectionName=self.__cfgSectionName, default="local")
101
+ baseUrlPDB = self.__cfgOb.getPath("PDB_REPO_URL", sectionName=self.__cfgSectionName, default="https://files.wwpdb.org/pub")
102
+ fallbackUrlPDB = self.__cfgOb.getPath("PDB_REPO_FALLBACK_URL", sectionName=self.__cfgSectionName, default="https://files.wwpdb.org/pub")
103
+ # addValues = {"_schema_version": collectionVersion}
104
+ addValues = None
105
+ #
106
+ kwD = {
107
+ "repoType": repoType, # either "pdb" or "pdb_ihm"
108
+ "holdingsTargetUrl": os.path.join(baseUrlPDB, repoType, "holdings"),
109
+ "holdingsFallbackUrl": os.path.join(fallbackUrlPDB, repoType, "holdings"),
110
+ "updateTargetUrl": os.path.join(baseUrlPDB, repoType, "data", "status", "latest"),
111
+ "updateFallbackUrl": os.path.join(fallbackUrlPDB, repoType, "data", "status", "latest"),
112
+ "filterType": self.__filterType,
113
+ }
114
+ # ---
115
+ if discoveryMode == "local":
116
+ rhdp = RepoHoldingsDataPrep(cfgOb=self.__cfgOb, sandboxPath=self.__sandboxPath, cachePath=self.__cachePath, filterType=self.__filterType)
117
+ else:
118
+ rhdp = RepoHoldingsRemoteDataPrep(cachePath=self.__cachePath, **kwD)
119
+ #
120
+ dl = DocumentLoader(
121
+ self.__cfgOb,
122
+ self.__cachePath,
123
+ self.__resourceName,
124
+ numProc=self.__numProc,
125
+ chunkSize=self.__chunkSize,
126
+ maxStepLength=self.__maxStepLength,
127
+ documentLimit=self.__documentLimit,
128
+ verbose=self.__verbose,
129
+ readBackCheck=self.__readBackCheck,
130
+ )
131
+ _, _, collectionNameList, docIndexD = self.__schP.getSchemaInfo(collectionGroupName=self.__collectionGroupName, dataTyping="ANY")
132
+ collectionNameList = [cN for cN in collectionNameList if "_update_entry" not in cN] # Turned OFF loading "update" collection in OCT 2025 for transition to DW loading
133
+ # ['repository_holdings_combined_entry', 'repository_holdings_current_entry', 'repository_holdings_unreleased_entry', 'repository_holdings_removed_entry']
134
+ logger.info("RepoHoldings collectionNameList: %r", collectionNameList)
135
+
136
+ ok = True
137
+ for collectionName in collectionNameList:
138
+ indexDL = docIndexD[collectionName] if collectionName in docIndexD else []
139
+ dList = self.__getHoldingsDocList(repoType, collectionName, rhdp, updateId)
140
+ if dList:
141
+ ok = dl.load(self.__databaseNameMongo, collectionName, loadType=loadType, documentList=dList, keyNames=None, addValues=addValues, indexDL=indexDL) and ok
142
+ self.__updateStatus(updateId, self.__databaseNameMongo, collectionName, ok, statusStartTimestamp)
143
+ logger.info(
144
+ "Completed load of repository holdings for repoType %r, database %r, collection %r, len(dList) %r (status %r)",
145
+ repoType, self.__databaseNameMongo, collectionName, len(dList), ok
146
+ )
147
+ logger.info("Completed load of repository holdings for repoType %r, loadType %r (status %r)", repoType, loadType, ok)
148
+ return ok
149
+ except Exception as e:
150
+ logger.exception("Failing with %s", str(e))
151
+ return False
152
+
153
+ def getLoadStatus(self):
154
+ return self.__statusList
155
+
156
+ def verifyCompleteLoad(self):
157
+ """
158
+ Compare the document counts of the pdbx_core and repository holdings collections.
159
+ """
160
+ ok = True
161
+
162
+ pdbxCoreEntryL = self.__getUniqueLoadedRcsbIds("pdbx_core", "pdbx_core_entry")
163
+
164
+ repoHoldingsCurrentEntryL = self.__getUniqueLoadedRcsbIds(self.__databaseNameMongo, "repository_holdings_current_entry")
165
+ repoHoldingsCombinedEntryL = self.__getUniqueLoadedRcsbIds(self.__databaseNameMongo, "repository_holdings_combined_entry")
166
+ repoHoldingsRemovedEntryL = self.__getUniqueLoadedRcsbIds(self.__databaseNameMongo, "repository_holdings_removed_entry")
167
+ repoHoldingsUnreleasedEntryL = self.__getUniqueLoadedRcsbIds(self.__databaseNameMongo, "repository_holdings_unreleased_entry")
168
+
169
+ combinedHoldingsExpectedCount = len(repoHoldingsCurrentEntryL) + len(repoHoldingsRemovedEntryL) + len(repoHoldingsUnreleasedEntryL)
170
+
171
+ if len(pdbxCoreEntryL) != len(repoHoldingsCurrentEntryL):
172
+ logger.error(
173
+ "The total entries in the collections of core entry (%d) and current repository holdings (%d) differ.",
174
+ len(pdbxCoreEntryL),
175
+ len(repoHoldingsCurrentEntryL)
176
+ )
177
+ delta = list(set(pdbxCoreEntryL) ^ set(repoHoldingsCurrentEntryL))
178
+ logger.error("List delta is of length %r", len(delta))
179
+ if len(delta) > 0 and len(delta) < 10000:
180
+ logger.error("Delta entry ID list: %r", delta)
181
+ ok = False
182
+ if len(repoHoldingsCombinedEntryL) != combinedHoldingsExpectedCount:
183
+ logger.error(
184
+ "The total entries in repoHoldingsCombinedEntryL (%d) and combinedHoldingsExpectedCount (%d) differ.",
185
+ len(repoHoldingsCombinedEntryL),
186
+ combinedHoldingsExpectedCount
187
+ )
188
+ ok = False
189
+
190
+ if not ok:
191
+ raise ValueError("Data Errors found in ExchangeDB loading")
192
+
193
+ return ok
194
+
195
+ def __getUniqueLoadedRcsbIds(self, databaseName, collectionName):
196
+ """Get the list of unique loaded 'rcsb_id' values in the given database and collection"""
197
+ loadedRcsbIdL = []
198
+ try:
199
+ #
200
+ with Connection(cfgOb=self.__cfgOb, resourceName=self.__resourceName) as client:
201
+ mg = MongoDbUtil(client)
202
+ selectL = ["rcsb_id"]
203
+ queryD = {}
204
+ loadedDocL = mg.fetch(databaseName, collectionName, selectL, queryD=queryD, suppressId=True)
205
+ loadedRcsbIdL = [docD["rcsb_id"] for docD in loadedDocL]
206
+ loadedRcsbIdL = list(set(loadedRcsbIdL))
207
+ logger.info("Number of entries loaded to database %s collection %s: %r", databaseName, collectionName, len(loadedRcsbIdL))
208
+ except Exception as e:
209
+ logger.exception("Failing with %s", str(e))
210
+ return loadedRcsbIdL
211
+
212
+ def __getHoldingsDocList(self, repoType, holdingsCollectionName, repoHoldingsDataPrep, updateId):
213
+ dList = []
214
+ if "_current_" in holdingsCollectionName.lower():
215
+ dList = repoHoldingsDataPrep.getHoldingsCurrentEntry(updateId=updateId)
216
+ elif "_unreleased_" in holdingsCollectionName.lower():
217
+ dList = repoHoldingsDataPrep.getHoldingsUnreleasedEntry(updateId=updateId)
218
+ elif "_combined_" in holdingsCollectionName.lower():
219
+ dList = repoHoldingsDataPrep.getHoldingsCombinedEntry(updateId=updateId)
220
+ elif repoType != "pdb_ihm" and "_removed_" in holdingsCollectionName.lower():
221
+ dList = repoHoldingsDataPrep.getHoldingsRemovedEntry(updateId=updateId)
222
+ # elif repoType != "pdb_ihm" and "_update_" in holdingsCollectionName.lower(): # TURNED OFF 15-JUL-2025 for transition to DW loading (since not used by anything)
223
+ # dList = repoHoldingsDataPrep.getHoldingsUpdateEntry(updateId=updateId)
224
+ return dList