Skip to content

Commit

Permalink
Merge pull request #31 from DiamondLightSource/implicit-factory
Browse files Browse the repository at this point in the history
Implicit factory
  • Loading branch information
KarlLevik committed Jun 7, 2018
2 parents 201f10e + 292bc51 commit 7ee44f2
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 69 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -6,6 +6,7 @@ conf/config.cfg
__pycache__/
*.py[cod]
*$py.class
.pytest_cache

# C extensions
*.so
Expand Down
12 changes: 6 additions & 6 deletions README.md
Expand Up @@ -8,7 +8,7 @@

This package provides a way to write acquisition and processing results into
an ISPyB database. Currently, the only supported method is through stored
procedures, but the package is designed to allow for other methods as well, such
procedures, but the package is designed to allow for other methods as well, such
as webservices.

### Requirements
Expand All @@ -34,25 +34,25 @@ pip2.7 install --user ispyb

### Examples
```python
import ispyb.factory
import ispyb
from datetime import datetime

# Get a connection and data area objects
with ispyb.open('config.cfg') as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
mxacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXACQUISITION, conn)
core = conn.core
mx_acquisition = conn.mx_acquisition

# Find the id for a given visit
sessionid = core.retrieve_visit_id('cm14451-2')

# Create a new data collection group entry:
params = mxacquisition.get_data_collection_group_params()
params = mx_acquisition.get_data_collection_group_params()
params['parentid'] = sessionid
params['experimenttype'] = 'OSC'
params['starttime'] = datetime.strptime('2017-09-21 13:00:00', '%Y-%m-%d %H:%M:%S')
params['endtime'] = datetime.strptime('2017-09-21 13:00:10', '%Y-%m-%d %H:%M:%S')
params['comments'] = 'This is a test of data collection group.'
dcg_id = mxacquisition.insert_data_collection_group(list(params.values()))
dcg_id = mx_acquisition.insert_data_collection_group(list(params.values()))
print("dcg_id: %i" % dcg_id)
```

Expand Down
4 changes: 2 additions & 2 deletions bin/mxdatareduction2ispyb.py
Expand Up @@ -12,7 +12,7 @@
import sys
from datetime import datetime

import ispyb.factory
import ispyb
from ispyb.xmltools import mx_data_reduction_to_ispyb, xml_file_to_dict

if len(sys.argv) not in (3,4):
Expand All @@ -24,7 +24,7 @@
conf_file = sys.argv[1]

with ispyb.open(conf_file) as conn:
mxprocessing = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXPROCESSING, conn)
mxprocessing = conn.mx_processing

xml_file = sys.argv[2]
xml_dir = os.path.split(xml_file)[0]
Expand Down
11 changes: 6 additions & 5 deletions docs/pipeline2ispyb.py
Expand Up @@ -10,17 +10,18 @@
# data acquisition and processing pipeline.
#

from __future__ import absolute_import, division

import sys
from datetime import datetime

import ispyb.factory
import ispyb

with ispyb.open(sys.argv[1]) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
mxacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXACQUISITION, conn)
mxprocessing = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXPROCESSING, conn)
mxscreening = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXSCREENING, conn)
core = conn.core
mxacquisition = conn.mx_acquisition
mxprocessing = conn.mx_processing
mxscreening = conn.mx_screening

# Find the id for a given visit
sessionid = core.retrieve_visit_id('cm14451-2')
Expand Down
2 changes: 1 addition & 1 deletion ispyb/__init__.py
Expand Up @@ -6,7 +6,7 @@
import ConfigParser as configparser
import logging

__version__ = '4.6.0'
__version__ = '4.7.0'

_log = logging.getLogger('ispyb')

Expand Down
2 changes: 2 additions & 0 deletions ispyb/factory.py
Expand Up @@ -26,6 +26,8 @@ def create_connection(conf_file):
def create_data_area(data_area_type, conn):
'''Factory function. Given a DataArea type and a Connection object imports the relevant data area module and
returns the correct type of Data Area object with its connection as the Connection object.'''
import warnings
warnings.warn("deprecated, use the data area properties on the connection object", DeprecationWarning)
if not hasattr(data_area_type, 'module') or not hasattr(data_area_type, 'classname'):
raise AttributeError('DataArea type %s does not exist' % data_area_type)
da_mod = importlib.import_module('%s.%s' % (conn.get_data_area_package(), data_area_type.module))
Expand Down
3 changes: 2 additions & 1 deletion ispyb/interface/connection.py
@@ -1,8 +1,9 @@
import abc
import ispyb.interface.factory

ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) # compatible with Python 2 *and* 3

class IF(ABC):
class IF(ABC, ispyb.interface.factory.factory_mixin):
'''ISPyB connection interface definition object.'''

@abc.abstractmethod
Expand Down
45 changes: 45 additions & 0 deletions ispyb/interface/factory.py
@@ -0,0 +1,45 @@
from __future__ import absolute_import, division, print_function

import importlib

class factory_mixin():
def _get_data_area(self, module, classname):
'''Helper function to instantiate a data area or return a cached instance.'''
if hasattr(self, '_cache_' + module):
return getattr(self, '_cache_' + module)
da_mod = importlib.import_module('%s.%s' % (self.get_data_area_package(), module))
DAClass = getattr(da_mod, classname)
da = DAClass()
da.set_connection(self)
setattr(self, '_cache_' + module, da)
return da

@property
def core(self):
'''Core part of the database schema'''
return self._get_data_area('core', 'Core')

@property
def mx_acquisition(self):
'''MX acquisition tables'''
return self._get_data_area('mxacquisition', 'MXAcquisition')

@property
def em_acquisition(self):
'''EM acquisition tables'''
return self._get_data_area('emacquisition', 'EMAcquisition')

@property
def mx_processing(self):
'''MX processing tables'''
return self._get_data_area('mxprocessing', 'MXProcessing')

@property
def mx_screening(self):
'''MX screening tables'''
return self._get_data_area('mxscreening', 'MXScreening')

@property
def shipping(self):
'''Shipping tables'''
return self._get_data_area('shipping', 'Shipping')
32 changes: 12 additions & 20 deletions tests/test_core.py
@@ -1,12 +1,12 @@
from __future__ import division, print_function
from __future__ import absolute_import, division, print_function

import context
import ispyb.factory
import ispyb
import time

def test_insert_session_for_proposal_code_number(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
core = conn.core

# Test upsert_person:
params = core.get_person_params()
Expand Down Expand Up @@ -72,7 +72,7 @@ def test_insert_session_for_proposal_code_number(testconfig):

def test_upsert_sample(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
core = conn.core
params = core.get_sample_params()
params['containerid'] = 1326
params['crystalid'] = 3918
Expand All @@ -89,50 +89,42 @@ def test_upsert_sample(testconfig):

def test_retrieve_visit_id(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
id = core.retrieve_visit_id('cm14451-2')
id = conn.core.retrieve_visit_id('cm14451-2')
assert id == 55168

def test_retrieve_current_sessions(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
rs = core.retrieve_current_sessions('i03', 24*60*30000)
rs = conn.core.retrieve_current_sessions('i03', 24*60*30000)
assert len(rs) > 0

def test_retrieve_current_sessions_for_person(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
rs = core.retrieve_current_sessions_for_person('i03', 'boaty', tolerance_mins=24*60*30000)
rs = conn.core.retrieve_current_sessions_for_person('i03', 'boaty', tolerance_mins=24*60*30000)
assert len(rs) > 0

def test_retrieve_most_recent_session(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
rs = core.retrieve_most_recent_session('i03', 'cm')
rs = conn.core.retrieve_most_recent_session('i03', 'cm')
assert len(rs) == 1

def test_retrieve_persons_for_proposal(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
rs = core.retrieve_persons_for_proposal('cm', 14451)
rs = conn.core.retrieve_persons_for_proposal('cm', 14451)
assert len(rs) == 1
login = rs[0]['login']
assert login is not None

def test_retrieve_current_cm_sessions(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
rs = core.retrieve_current_cm_sessions('i03')
rs = conn.core.retrieve_current_cm_sessions('i03')
assert len(rs) > 0

def test_retrieve_active_plates(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
rs = core.retrieve_active_plates('i02-2')
rs = conn.core.retrieve_active_plates('i02-2')
assert len(rs) >= 0

def test_retrieve_proposal_title(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
title = core.retrieve_proposal_title('cm', 14451)
title = conn.core.retrieve_proposal_title('cm', 14451)
assert title.strip() == 'I03 Commissioning Directory 2016'
12 changes: 6 additions & 6 deletions tests/test_em_structures.py
@@ -1,11 +1,11 @@
from __future__ import division, print_function
from __future__ import absolute_import, division, print_function

import context
import ispyb.factory
import ispyb

def test_insert_movie(testconfig):
with ispyb.open(testconfig) as conn:
emacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.EMACQUISITION, conn)
emacquisition = conn.em_acquisition
group_params = emacquisition.get_data_collection_group_params()
group_params['parentid'] = 55168
group_id = emacquisition.insert_data_collection_group(list(group_params.values()))
Expand All @@ -25,7 +25,7 @@ def test_insert_movie(testconfig):

def test_insert_motion_correction(testconfig):
with ispyb.open(testconfig) as conn:
emacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.EMACQUISITION, conn)
emacquisition = conn.em_acquisition
group_params = emacquisition.get_data_collection_group_params()
group_params['parentid'] = 55168
group_id = emacquisition.insert_data_collection_group(list(group_params.values()))
Expand All @@ -48,7 +48,7 @@ def test_insert_motion_correction(testconfig):

def test_insert_ctf(testconfig):
with ispyb.open(testconfig) as conn:
emacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.EMACQUISITION, conn)
emacquisition = conn.em_acquisition
group_params = emacquisition.get_data_collection_group_params()
group_params['parentid'] = 55168
group_id = emacquisition.insert_data_collection_group(list(group_params.values()))
Expand All @@ -75,7 +75,7 @@ def test_insert_ctf(testconfig):

def test_insert_drift(testconfig):
with ispyb.open(testconfig) as conn:
emacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.EMACQUISITION, conn)
emacquisition = conn.em_acquisition
group_params = emacquisition.get_data_collection_group_params()
group_params['parentid'] = 55168
group_id = emacquisition.insert_data_collection_group(list(group_params.values()))
Expand Down
8 changes: 3 additions & 5 deletions tests/test_misc.py
@@ -1,4 +1,4 @@
from __future__ import division, print_function
from __future__ import absolute_import, division, print_function

import threading

Expand All @@ -8,7 +8,7 @@

def test_multi_threads_upsert(testconfig):
with ispyb.open(testconfig) as conn:
mxprocessing = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXPROCESSING, conn)
mxprocessing = conn.mx_processing

params = mxprocessing.get_program_params()
params['cmd_line'] = 'dials -xia2 /path/to/files'
Expand Down Expand Up @@ -40,7 +40,5 @@ def test_multi_threads_upsert(testconfig):

def test_retrieve_failure(testconfig):
with ispyb.open(testconfig) as conn:
mxacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXACQUISITION, conn)

with pytest.raises(ispyb.exception.ISPyBNoResultException):
rs = mxacquisition.retrieve_data_collection_main(0)
rs = conn.mx_acquisition.retrieve_data_collection_main(0)
6 changes: 3 additions & 3 deletions tests/test_mxacquisition.py
@@ -1,12 +1,12 @@
from __future__ import division, print_function
from __future__ import absolute_import, division, print_function

import context
from datetime import datetime
import ispyb.factory
import ispyb

def test_mxacquisition_methods(testconfig):
with ispyb.open(testconfig) as conn:
mxacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXACQUISITION, conn)
mxacquisition = conn.mx_acquisition

params = mxacquisition.get_data_collection_group_params()
params['parentid'] = 55168 # sessionId
Expand Down
10 changes: 5 additions & 5 deletions tests/test_mxprocessing.py
@@ -1,11 +1,11 @@
from __future__ import division, print_function
from __future__ import absolute_import, division, print_function

import context
import ispyb.factory
import ispyb

def test_processing_jobs(testconfig):
with ispyb.open(testconfig) as conn:
mxprocessing = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXPROCESSING, conn)
mxprocessing = conn.mx_processing

params = mxprocessing.get_job_params()
params['datacollectionid'] = 993677
Expand Down Expand Up @@ -52,7 +52,7 @@ def test_processing_jobs(testconfig):

def test_processing(testconfig):
with ispyb.open(testconfig) as conn:
mxprocessing = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXPROCESSING, conn)
mxprocessing = conn.mx_processing

params = mxprocessing.get_program_params()
params['cmd_line'] = 'ls -ltr'
Expand Down Expand Up @@ -153,7 +153,7 @@ def test_processing(testconfig):

def test_post_processing(testconfig):
with ispyb.open(testconfig) as conn:
mxprocessing = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXPROCESSING, conn)
mxprocessing = conn.mx_processing

params = mxprocessing.get_run_params()
params['parentid'] = 596133 # some autoProcScalingId
Expand Down
10 changes: 5 additions & 5 deletions tests/test_mxscreening.py
@@ -1,15 +1,15 @@
from __future__ import division, print_function
from __future__ import absolute_import, division, print_function

from datetime import datetime

import context
import ispyb.factory
import ispyb

def test_insert_all_screening(testconfig):
with ispyb.open(testconfig) as conn:
core = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.CORE, conn)
mxscreening = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXSCREENING, conn)
mxacquisition = ispyb.factory.create_data_area(ispyb.factory.DataAreaType.MXACQUISITION, conn)
core = conn.core
mxscreening = conn.mx_screening
mxacquisition = conn.mx_acquisition

test_session = 'cm14451-2'
session_id = core.retrieve_visit_id(test_session)
Expand Down

0 comments on commit 7ee44f2

Please sign in to comment.