Skip to content

Commit

Permalink
Merge pull request #288 from SD2E/opil_recovery
Browse files Browse the repository at this point in the history
update parameter table creation to include obstacle course protocol
  • Loading branch information
tramyn authored Oct 27, 2020
2 parents a59bc10 + 6e7ad4e commit dfd08b8
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 85 deletions.
97 changes: 22 additions & 75 deletions intent_parser/accessor/strateos_accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from intent_parser.intent_parser_exceptions import IntentParserException
from transcriptic import Connection
import intent_parser.constants.intent_parser_constants as ip_constants
import intent_parser.utils.intent_parser_utils as ip_utils
import logging
import opil
import time
Expand All @@ -12,7 +11,7 @@ class StrateosAccessor(object):
"""
Retrieve protocols from Strateos
"""
SYNC_PERIOD = timedelta(minutes=10)
SYNC_PERIOD = timedelta(minutes=60)
logger = logging.getLogger('intent_parser_strateos_accessor')

def __init__(self, credential_path=None, use_cache=True):
Expand All @@ -24,8 +23,9 @@ def __init__(self, credential_path=None, use_cache=True):
self._use_cache = use_cache

self.protocol_lock = threading.Lock()
self.protocols = {}
self._map_name_protocol_docs = {}
self._map_name_to_protocol_interface = {}
self._map_name_to_protocol_id = {}
self._protocol_thread = threading.Thread(target=self._periodically_fetch_protocols)

def get_list_of_protocol_interface(self):
Expand All @@ -36,14 +36,19 @@ def get_protocol_parameter_values(self, protocol_name):
raise IntentParserException('Unable to identify %s as a protocol supported from Strateos' % protocol_name)

parameter_values = []
sbol_doc = self.protocols[protocol_name]
sbol_doc = self._map_name_protocol_docs[protocol_name]
for obj in sbol_doc.objects:
if type(obj) is opil.opil_factory.ProtocolInterface:
continue
parameter_values.append(obj)

return parameter_values

def get_protocol_id(self, protocol_name):
if protocol_name not in self._map_name_to_protocol_id:
raise IntentParserException('Unable to get protocol id: %s is not a supported protocol in Strateos.' % protocol_name)
return self._map_name_to_protocol_id[protocol_name]

def get_protocol_interface(self, protocol_name):
if not self._use_cache:
self._fetch_protocols()
Expand All @@ -68,12 +73,11 @@ def get_protocol_as_schema(self, protocol):
Raises:
An Exception to indicate if a given protocol does not exist when calling the Strateos API.
"""

self.protocol_lock.acquire()
if protocol not in self.protocols:
if protocol not in self._map_name_protocol_docs:
raise Exception('Unable to get %s from Strateos' % protocol)

selected_protocol = self.protocols[protocol]
selected_protocol = self._map_name_protocol_docs[protocol]
self.protocol_lock.release()
return selected_protocol

Expand All @@ -94,25 +98,28 @@ def _fetch_protocols(self):
protocol_list = self.strateos_api.get_protocols()

self.protocol_lock.acquire()
# supported_protocols = [ip_constants.CELL_FREE_RIBO_SWITCH_PROTOCOL,
# ip_constants.GROWTH_CURVE_PROTOCOL,
# ip_constants.OBSTACLE_COURSE_PROTOCOL,
# ip_constants.TIME_SERIES_HTP_PROTOCOL]
supported_protocols = [ip_constants.OBSTACLE_COURSE_PROTOCOL]
supported_protocols = [ip_constants.CELL_FREE_RIBO_SWITCH_PROTOCOL,
ip_constants.GROWTH_CURVE_PROTOCOL,
ip_constants.OBSTACLE_COURSE_PROTOCOL,
ip_constants.TIME_SERIES_HTP_PROTOCOL]
for protocol in protocol_list:
if protocol['name'] not in supported_protocols:
continue

self.logger.info('Fetching protocol %s' % protocol['name'])
protocol_interface, sbol_doc = self._convert_protocol_as_opil(protocol)
self._map_name_to_protocol_id[protocol['name']] = protocol['id']
self._map_name_to_protocol_interface[protocol['name']] = protocol_interface
self.protocols[protocol['name']] = sbol_doc

self._map_name_protocol_docs[protocol['name']] = sbol_doc
self.protocol_lock.release()

def _convert_protocol_as_opil(self, protocol):
strateos_namespace = 'http://strateos.com/'
sg = opil.StrateosOpilGenerator()
sbol_doc = sg.parse_strateos_json(strateos_namespace, protocol['name'], protocol['inputs'])
sbol_doc = sg.parse_strateos_json(strateos_namespace,
protocol['name'],
protocol['id'],
protocol['inputs'])
protocol_interface = None
for obj in sbol_doc.objects:
if type(obj) is opil.opil_factory.ProtocolInterface:
Expand All @@ -123,63 +130,3 @@ def _convert_protocol_as_opil(self, protocol):

return protocol_interface, sbol_doc

def _parse_protocol(self, protocol):
queue = []
parameters = {}
for key, value in protocol.items():
queue.append(([key], value))

while len(queue) > 0:
names, protocol_field = queue.pop(0)
id = '.'.join(names)

if 'inputs' in protocol_field:
for key, value in protocol_field['inputs'].items():
queue.append((names + [key], value))
else:
parameter_field = ParameterField()
if 'default' in protocol_field:
parameter_field.set_default_value(protocol_field['default'])
if 'required' in protocol_field:
parameter_field.set_required(protocol_field['required'])
if 'options' in protocol_field:
for option in protocol_field['options']:
if 'name' in option and 'value' in option:
parameter_field.add_option(option['name'], option['value'])
parameters[id] = parameter_field

return parameters

class ParameterField(object):

def __init__(self, default_value=None, required=False):
self._default_value = default_value
self._required = required
self._options = []

def add_option(self, name, value):
option = ParameterFieldOption(name, value)
self._options.append(option)

def get_default_value(self):
if self._default_value is None:
return ' '
return str(self._default_value)

def is_required(self):
return self._required

def set_default_value(self, value):
if self._default_value:
raise IntentParserException('Conflict setting %s as a default value when it is currently set to %s' % (value, self._default_value))
self._default_value = value

def set_required(self, value: bool):
self._required = value


class ParameterFieldOption(object):

def __init__(self, name, value):
self._name = name
self._value = value
4 changes: 2 additions & 2 deletions intent_parser/intent_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from intent_parser.table.intent_parser_table_factory import IntentParserTableFactory
from intent_parser.table.lab_table import LabTable
from intent_parser.table.intent_parser_table_type import TableType
import intent_parser.constants.google_api_constants
import intent_parser.constants.google_api_constants as google_constants
import intent_parser.constants.intent_parser_constants as ip_constants
import intent_parser.constants.sd2_datacatalog_constants as dc_constants
import intent_parser.table.table_utils as table_utils
Expand Down Expand Up @@ -405,7 +405,7 @@ def _get_challenge_problem(self):
return dc_constants.UNDEFINED

def _get_experiment_reference_url(self):
return intent_parser.constants.google_api_constants.GOOGLE_DOC_URL_PREFIX + self.lab_experiment.document_id()
return google_constants.GOOGLE_DOC_URL_PREFIX + self.lab_experiment.document_id()

def _get_experiment_reference(self):
try:
Expand Down
6 changes: 6 additions & 0 deletions intent_parser/protocols/opil_parameter_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ def create_opil_URI_parameter_value(value_id: str, value: str):
parameter_value.value = value
return parameter_value

def get_protocol_id_from_annotaton(protocol):
namespace = 'http://strateos.com/'
id_annotation = sbol3.TextProperty(protocol, namespace + 'strateos_id', 0, 1)

return id_annotation.property_owner.strateos_id

def get_param_value_as_string(parameter_value):
if type(parameter_value) is opil.opil_factory.BooleanValue:
return str(parameter_value.value)
Expand Down
6 changes: 6 additions & 0 deletions intent_parser/protocols/protocol_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ def load_protocols_from_lab(self) -> List:
else:
raise IntentParserException('Intent Parser does not support fetching protocols from lab: %s.' % self.lab_name)

def get_protocol_id(self, protocol_name):
if self.lab_name == dc_constants.LAB_TRANSCRIPTIC:
return self.transcriptic_accessor.get_protocol_id(protocol_name)
else:
raise IntentParserException('Intent Parser unable to get protocol id for %s.' % self.lab_name)

def get_protocol_interface(self, selected_protocol):
if self.lab_name == dc_constants.LAB_TRANSCRIPTIC:
protocol = self.transcriptic_accessor.get_protocol_interface(selected_protocol)
Expand Down
2 changes: 1 addition & 1 deletion intent_parser/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ google-api-python-client
google-auth-httplib2
google-auth-oauthlib
jsonschema
opil==1.0a2.post1
opil==1.0a4
pymongo
pyspellchecker
python-docx
Expand Down
28 changes: 21 additions & 7 deletions intent_parser/server/intent_parser_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def process_run_experiment(self, http_message):
return self._create_http_response(HTTPStatus.OK, json.dumps({'authenticationLink': link}),
'application/json')

def process_experiment_execution_status(self, json_body, client_state):
def process_experiment_execution_status(self, json_body):
execution_id = 'ZzL5p65NgyXw' # TODO: placeholder to assume authentication was successful. Will need to update to correct execution_id
tacc_accessor = TACCGoAccessor()
status = tacc_accessor.get_status_of_experiment(execution_id)
Expand Down Expand Up @@ -600,7 +600,7 @@ def process_submit_form(self, http_message):
'results': {'operationSucceeded': True}
}
elif action == 'createParameterTable':
actions = self.process_create_parameter_table(data)
actions = self.process_create_parameter_table(data, json_body['documentId'])
result = {'actions': actions,
'results': {'operationSucceeded': True}
}
Expand Down Expand Up @@ -1691,7 +1691,7 @@ def process_create_experiment_specification_table(self, status_tables, table_ind
column_width = [len(header) for header in header_row]
return table_template, column_width

def process_create_parameter_table(self, data):
def process_create_parameter_table(self, data, document_id):
table_template = []
header_row = [intent_parser_constants.HEADER_PARAMETER_VALUE,
intent_parser_constants.HEADER_PARAMETER_VALUE_VALUE]
Expand Down Expand Up @@ -1721,7 +1721,11 @@ def process_create_parameter_table(self, data):
for param_val in parameter_values:
param_value_mapping[param_val.identity] = param_val

required_fields = self._add_required_parameters(ref_required_id_to_name, param_value_mapping)
protocol_id = opil_util.get_protocol_id_from_annotaton(protocol)
required_fields = self._add_required_parameters(ref_required_id_to_name,
param_value_mapping,
google_constants.GOOGLE_DOC_URL_PREFIX + document_id,
protocol_id)
table_template.extend(required_fields)

selected_optional_parameters = data[ip_addon_constants.HTML_OPTIONALPARAMETERS]
Expand All @@ -1734,13 +1738,23 @@ def process_create_parameter_table(self, data):
ip_addon_constants.TABLE_TYPE_PARAMETERS,
column_width)

def _add_required_parameters(self, ref_required_values, param_value_mapping):
required_parameters = []
def _add_required_parameters(self, ref_required_values, param_value_mapping, experiment_ref_url, protocol_id):
required_parameters = [[intent_parser_constants.PROTOCOL_FIELD_XPLAN_BASE_DIRECTORY, ''],
[intent_parser_constants.PROTOCOL_FIELD_XPLAN_REACTOR, 'xplan'],
[intent_parser_constants.PROTOCOL_FIELD_PLATE_SIZE, ''],
[intent_parser_constants.PARAMETER_PLATE_NUMBER, ' '],
[intent_parser_constants.PROTOCOL_FIELD_CONTAINER_SEARCH_STRING, ' '],
[intent_parser_constants.PARAMETER_STRAIN_PROPERTY, ' '],
[intent_parser_constants.PARAMETER_XPLAN_PATH, ''],
[intent_parser_constants.PARAMETER_SUBMIT, 'False'],
[intent_parser_constants.PARAMETER_PROTOCOL_ID, protocol_id],
[intent_parser_constants.PARAMETER_TEST_MODE, 'True'],
[intent_parser_constants.PARAMETER_EXPERIMENT_REFERENCE_URL_FOR_XPLAN, experiment_ref_url]]

for value_id, param_name in ref_required_values.items():
if value_id in param_value_mapping:
param_value = opil_util.get_param_value_as_string(param_value_mapping[value_id])
required_parameters.append([param_name, param_value])

else:
required_parameters.append([param_name, ' '])

Expand Down

0 comments on commit dfd08b8

Please sign in to comment.