From f983004db3a2541e9345c68947fee6b2132f364d Mon Sep 17 00:00:00 2001 From: Markus Gerstel Date: Fri, 31 Aug 2018 15:05:46 +0100 Subject: [PATCH] Add a model object for integration results Resolves SCI-7754 --- ispyb/model/__future__.py | 14 ++++++ ispyb/model/datacollection.py | 5 ++ ispyb/model/integration.py | 87 +++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 ispyb/model/integration.py diff --git a/ispyb/model/__future__.py b/ispyb/model/__future__.py index db235641..03d6f5a2 100644 --- a/ispyb/model/__future__.py +++ b/ispyb/model/__future__.py @@ -30,6 +30,8 @@ def enable(configuration_file): _db = mysql.connector.connect(host=host, port=port, user=username, password=password, database=database) _db_cc = DictionaryContextcursorFactory(_db.cursor) + import ispyb.model.datacollection + ispyb.model.datacollection.DataCollection.integrations = _get_linked_autoprocintegration_for_dc import ispyb.model.gridinfo ispyb.model.gridinfo.GridInfo.reload = _get_gridinfo import ispyb.model.processingprogram @@ -99,3 +101,15 @@ def _get_autoprocprogram(self): "WHERE autoProcProgramId = %s " "LIMIT 1;", self._appid) self._data = cursor.fetchone() + +@property +def _get_linked_autoprocintegration_for_dc(self): + import ispyb.model.integration + with _db_cc() as cursor: + cursor.run("SELECT * " + "FROM AutoProcIntegration " + "WHERE dataCollectionId = %s", self.dcid) + return [ + ispyb.model.integration.IntegrationResult(ir['autoProcIntegrationId'], self._db, preload=ir) + for ir in cursor.fetchall() + ] diff --git a/ispyb/model/datacollection.py b/ispyb/model/datacollection.py index 2274c730..d39d2a51 100644 --- a/ispyb/model/datacollection.py +++ b/ispyb/model/datacollection.py @@ -43,6 +43,11 @@ def group(self): self._cache_group = DataCollectionGroup(self.dcgid, self._db.conn) return self._cache_group + @property + def integrations(self): + '''Returns the list of IntegrationResult objects associated with this DC.''' + raise NotImplementedError('TODO: Not implemented yet') + @property def file_template_full(self): '''Template for file names with full directory path. As with file_template diff --git a/ispyb/model/integration.py b/ispyb/model/integration.py new file mode 100644 index 00000000..16b57a20 --- /dev/null +++ b/ispyb/model/integration.py @@ -0,0 +1,87 @@ +from __future__ import absolute_import, division, print_function + +import collections + +import ispyb.model +import ispyb.model.processingprogram + +class IntegrationResult(ispyb.model.DBCache): + '''An object representing a data collection integration result database entry. + The object lazily accesses the underlying database when necessary and + exposes record data as python attributes. + ''' + + def __init__(self, apiid, db_conn, preload=None): + '''Create a IntegrationResult object for a defined AutoProcIntegrationID. + Requires a database connection object exposing further data access + methods. + + :param apiid: AutoProcIntegrationID + :param db_conn: ISPyB database connection object + :return: An IntegrationResult object representing the database entry for + the specified AutoProcIntegrationID + ''' + self._cache_dc = None + self._cache_app = None + self._db = db_conn + self._apiid = int(apiid) + if preload: + self._data = preload + + def reload(self): + '''Load/update information from the database.''' + raise NotImplementedError('TODO: Not implemented yet') + + @property + def DCID(self): + '''Returns the main data collection id.''' + dcid = self._data['dataCollectionId'] + if dcid is None: + return None + return int(dcid) + + @property + def data_collection(self): + '''Returns the DataCollection model object for the main data collection of + the ProcessingJob.''' + if self._cache_dc is None: + if self.DCID is None: + return None + self._cache_dc = self._db.get_data_collection(self.DCID) + return self._cache_dc + + @property + def APIID(self): + '''Returns the AutoProcIntegrationID.''' + return self._apiid + + def __repr__(self): + '''Returns an object representation, including the AutoProcIntegrationID, + the database connection interface object, and the cache status.''' + return '' % ( + self._apiid, + 'cached' if self.cached else 'uncached', + self._db + ) + + def __str__(self): + '''Returns a pretty-printed object representation.''' + if not self.cached: + return 'IntegrationResult #%d (not yet loaded from database)' % self._apiid + return ('\n'.join(( + 'IntegrationResult #{ir.APIID}', + ' DCID : {ir.DCID}', + ' APPID : {ir.APPID}', + ' Start Image : {ir.image_start}', + ' End Image : {ir.image_end}', + ' Detector Distance: {ir.detector_distance}', + ' Timestamp : {ir.timestamp}', + ))).format(ir=self) + +ispyb.model.add_properties(IntegrationResult, ( + ('APPID', 'autoProcProgramId'), + ('image_start', 'startImageNumber'), + ('image_end', 'endImageNumber'), + ('detector_distance', 'refinedDetectorDistance'), + ('timestamp', 'recordTimeStamp'), +))