def receive_subscribe(self, msg, content): """Override of KQMLModule default, expects a performative of ask-all. Gets the ask-all query from the message contents (the contents of the content variable is the query that we care about), then checks to see if the query head is in the dictionary of available asks and checks if the query string is in the dictionary of subscribers. If both of these are true we then append the message to the subscriber query, clean out any previous subscription data, and reply with a tell ok message. Arguments: msg {KQMLPerformative} -- performative to be passed along in reply and stored in the subscribers dictionary content {KQMLPerformative} -- ask-all for a query """ LOGGER.debug('received subscribe: %s', content) # lazy logging if content.head() == 'ask-all': # TODO - track msg ideas and use for filtering query = content.get('content') query_string = query.to_string() if query.head() in self.asks and query_string in self.subscribers: self.subscribers[query_string].append(msg) self.subcribe_data_old[query_string] = None self.subcribe_data_new[query_string] = None reply_msg = KQMLPerformative('tell') reply_msg.set(':sender', self.name) reply_msg.set('content', ':ok') self.reply(msg, reply_msg)
def send_display_figure(self, path): msg = KQMLPerformative('tell') content = KQMLList('display-image') content.set('type', 'simulation') content.sets('path', path) msg.set('content', content) self.send(msg)
def subscribe_tell(self, tell_type): msg = KQMLPerformative('subscribe') content = KQMLList('tell') content.append('&key') content.set('content', KQMLList.from_string('(%s . *)' % tell_type)) msg.set('content', content) self.send(msg)
def subscribe_request(self, req_type): msg = KQMLPerformative('subscribe') content = KQMLList('request') content.append('&key') content.set('content', KQMLList.from_string('(%s . *)' % req_type)) msg.set('content', content) self.send(msg)
def receive_other_performative(self, msg): """Override of KQMLModule default... ping isn't currently supported by pykqml so we handle other to catch ping and otherwise throw an error. Arguments: msg {KQMLPerformative} -- other type of performative, if ping we reply with a ping update otherwise error """ if msg.head() == 'ping': reply_content = KQMLList([':agent', self.name]) reply_content.append(':uptime') reply_content.append(self._uptime()) # TODO - check if .set('status', ':OK') can be used here instead reply_content.append(':status') reply_content.append(':OK') reply_content.append(':state') reply_content.append('idle') reply_content.append(':machine') reply_content.append(socket.gethostname()) reply = KQMLPerformative('update') reply.set('sender', self.name) # reply.set('receiver', msg.get('sender')) # reply.set('in-reply-to', msg.get('reply-with')) reply.set('content', reply_content) self.reply(msg, reply) else: self.error_reply(msg, 'unexpected performative: ' + str(msg))
def respond_remove_mechanism(self, content): """Return response content to model-remove-mechanism request.""" ekb = content.gets('description') model_id = self._get_model_id(content) no_display = content.get('no-display') try: res = self.mra.remove_mechanism(ekb, model_id) except Exception as e: raise InvalidModelDescriptionError(e) model_id = res.get('model_id') if model_id is None: raise InvalidModelDescriptionError('Could not find model id.') # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', str(model_id)) # Add the INDRA model json model = res.get('model') model_msg = encode_indra_stmts(model) msg.sets('model', model_msg) # Add the removed statements removed = res.get('removed') if removed: removed_msg = encode_indra_stmts(removed) msg.sets('removed', removed_msg) # Add the diagram diagrams = res.get('diagrams') if not no_display: if diagrams: rxn_diagram = diagrams.get('reactionnetwork') if rxn_diagram: msg.sets('diagram', rxn_diagram) self.send_display_model(rxn_diagram) return msg
def reply_with_content(self, msg, reply_content): "A wrapper around the reply method from KQMLModule." if not self.testing: reply_msg = KQMLPerformative('reply') reply_msg.set('content', reply_content) self.reply(msg, reply_msg) return (msg, reply_content)
def respond_phosphorylation_activating(self, content): """Return response content to phosphorylation_activating request.""" if not CAN_CHECK_STATEMENTS: return self.make_failure( 'NO_KNOWLEDGE_ACCESS', 'Cannot access the database through the web api.') heading = content.head() m = re.match(r'(\w+)-(\w+)', heading) if m is None: return self.make_failure('UNKNOWN_ACTION') action, polarity = [s.lower() for s in m.groups()] target_cljson = content.get('target') if target_cljson is None or not len(target_cljson): return self.make_failure('MISSING_TARGET') agent = self.get_agent(target_cljson) # This is a bug in the BA that we can handle here if isinstance(agent, list): agent = agent[0] logger.debug('Found agent (target): %s.' % agent.name) site = content.gets('site') if site is None: residue = None position = None else: try: residue, position = site.split('-') except: return self.make_failure('INVALID_SITE') finder = self.msa.find_phos_activeforms(agent, residue=residue, position=position, action=action, polarity=polarity) stmts = finder.get_statements() logger.info("Found %d matching statements." % len(stmts)) if not len(stmts): return self.make_failure( 'MISSING_MECHANISM', "Could not find statement matching phosphorylation activating " "%s, %s, %s, %s." % (agent.name, residue, position, 'phosphorylation')) else: description = finder.describe(include_negative=False) # self.say(description) msg = "phosphorylation at %s%s activates %s." \ % (residue, position, agent.name) self.send_provenance_for_stmts( stmts, msg, ev_counts=finder.get_ev_totals(), source_counts=finder.get_source_counts()) msg = KQMLPerformative('SUCCESS') msg.set('is-activating', 'TRUE') msg.sets('suggestion', description) return msg
def ask_agent(self, receiver, data, query_type='user::query'): msg = KQMLPerformative('ask-all') msg.set('sender', self.name) msg.set('receiver', receiver) if isinstance(data, KQMLList): msg.set('content', data) else: msg.set('content', listify(data)) msg.set('query-type', query_type) self.connect() #Non-pip: self.connect(self.host, self.port) self.send(msg)
def respond_get_common(self, content): """Find the common up/down streams of a protein.""" # TODO: This entire function could be part of the MSA. if not CAN_CHECK_STATEMENTS: return self.make_failure( 'NO_KNOWLEDGE_ACCESS', 'Cannot access the database through the web api.') genes_cljson = content.get('genes') agents = [self.get_agent(ag) for ag in genes_cljson] if len(agents) < 2: return self.make_failure('NO_TARGET', 'Only %d < 2 agents given.' % len(agents)) direction = content.gets('up-down') logger.info("Got genes: %s and direction %s." % (agents, direction)) # Choose some parameters based on direction. if direction == 'ONT::MORE': method = 'common_upstreams' prefix = 'up' elif direction == 'ONT::SUCCESSOR': method = 'common_downstreams' prefix = 'down' else: # TODO: With the new MSA we could handle common neighbors. return self.make_failure("UNKNOWN_ACTION", direction) # Find the commonalities. try: finder = self.msa.find_mechanisms(method, *agents) except EntityError as e: return self.make_failure("MISSING_TARGET", e.args[0]) # Get post statements to provenance. if len(agents) > 2: name_list = ', '.join(ag.name for ag in agents[:-1]) + ',' else: name_list = agents[0].name name_list += ' and ' + agents[-1].name msg = ('%sstreams of ' % prefix).capitalize() + name_list self.send_provenance_for_stmts( finder.get_statements(), msg, ev_counts=finder.get_ev_totals(), source_counts=finder.get_source_counts()) # Create the reply resp = KQMLPerformative('SUCCESS') agents = finder.get_other_agents() resp.set('entities-found', self.make_cljson(agents)) resp.sets('prefix', prefix) return resp
def respond_get_common(self, content): """Find the common up/down streams of a protein.""" # TODO: This entire function could be part of the MSA. if not CAN_CHECK_STATEMENTS: return self.make_failure( 'NO_KNOWLEDGE_ACCESS', 'Cannot access the database through the web api.' ) genes_ekb = content.gets('genes') agents = _get_agents(genes_ekb) if len(agents) < 2: return self.make_failure('NO_TARGET', 'Only %d < 2 agents given.' % len(agents)) direction = content.gets('up-down') logger.info("Got genes: %s and direction %s." % (agents, direction)) # Choose some parameters based on direction. if direction == 'ONT::MORE': method = 'common_upstreams' prefix = 'up' elif direction == 'ONT::SUCCESSOR': method = 'common_downstreams' prefix = 'down' else: # TODO: With the new MSA we could handle common neighbors. return self.make_failure("UNKNOWN_ACTION", direction) # Find the commonalities. try: finder = self.msa.find_mechanisms(method, *agents) except EntityError as e: return self.make_failure("MISSING_TARGET", e.args[0]) # Get post statements to provenance. if len(agents) > 2: name_list = ', '.join(ag.name for ag in agents[:-1]) + ',' else: name_list = agents[0].name name_list += ' and ' + agents[-1].name msg = ('%sstreams of ' % prefix).capitalize() + name_list self.send_provenance_for_stmts(finder.get_statements(), msg, ev_counts=finder.get_ev_totals()) # Create the reply resp = KQMLPerformative('SUCCESS') gene_list = KQMLList() for gene in finder.get_common_entities(): gene_list.append(gene) resp.set('commons', gene_list) resp.sets('prefix', prefix) return resp
def register(self): if self.name is not None: perf = KQMLPerformative('register') perf.set('name', self.name) if self.group_name is not None: try: if self.group_name.startswith('('): perf.sets('group', self.group_name) else: perf.set('group', self.group_name) except IOError: logger.error('bad group name: ' + self.group_name) self.send(perf)
def receive_tell(self, msg, content): """Override default KQMLModule tell to simply log the content and reply with nothing Arguments: msg {KQMLPerformative} -- tell to be passed along in reply content {KQMLPerformative} -- tell from companions to be logged """ LOGGER.debug('received tell: %s', content) # lazy logging reply_msg = KQMLPerformative('tell') reply_msg.set('sender', self.name) reply_msg.set('content', None) self.reply(msg, reply_msg)
def respond_phosphorylation_activating(self, content): """Return response content to phosphorylation_activating request.""" if not CAN_CHECK_STATEMENTS: return self.make_failure( 'NO_KNOWLEDGE_ACCESS', 'Cannot access the database through the web api.' ) heading = content.head() m = re.match('(\w+)-(\w+)', heading) if m is None: return self.make_failure('UNKNOWN_ACTION') action, polarity = [s.lower() for s in m.groups()] target_ekb = content.gets('target') if target_ekb is None or target_ekb == '': return self.make_failure('MISSING_TARGET') agent = _get_agent(target_ekb) logger.debug('Found agent (target): %s.' % agent.name) site = content.gets('site') if site is None: residue = None position = None else: try: residue, position = site.split('-') except: return self.make_failure('INVALID_SITE') finder = self.msa.find_phos_activeforms(agent, residue=residue, position=position, action=action, polarity=polarity) stmts = finder.get_statements() self.say(finder.describe()) logger.info("Found %d matching statements." % len(stmts)) if not len(stmts): return self.make_failure( 'MISSING_MECHANISM', "Could not find statement matching phosphorylation activating " "%s, %s, %s, %s." % (agent.name, residue, position, 'phosphorylation') ) else: msg = "phosphorylation at %s%s activates %s." \ % (residue, position, agent.name) self.send_provenance_for_stmts(stmts, msg, ev_counts=finder.get_ev_totals()) msg = KQMLPerformative('SUCCESS') msg.set('is-activating', 'TRUE') return msg
def _response_to_query(self, msg, content, results, response_type): """Based on the response type, will create a properly formed reply with the results either input as patterns or bound to the arguments from the results. The reply is a tell which is then sent to Companions. Goes through the arguments and the results together to either bind a argument to the result or simple return the result in the place of that argument. The reply content is filled with these argument/result lists (they are listified before appending) before being added to the tell message and subsequently sent off to Companions. Arguments: msg {KQMLPerformative} -- the message being passed along to reply content {[type]} -- query, starts with a predicate and the remainder is the arguments results {[type]} -- The results of performing the query response_type {[type]} -- the given response type, if it is not given or is given to be pattern, the variable will be set to True, otherwise False. """ response_type = response_type is None or response_type == ':pattern' reply_content = KQMLList(content.head()) results_list = results if isinstance(results, list) else [results] result_index = 0 arg_len = len(content.data[1:]) for i, each in enumerate(content.data[1:]): # if argument is a variable if str(each[0]) == '?': # if last argument and there's still more in results if i == arg_len and result_index < len(results_list) - 1: # get the remaining list pattern = results_list[result_index:] # pattern or binding... reply_with = pattern if response_type else (each, pattern) reply_content.append(listify(reply_with)) else: # same logic as above, just doesn't get the remaining list pattern = results_list[result_index] reply_with = pattern if response_type else (each, pattern) reply_content.append(listify(reply_with)) result_index += 1 else: if response_type: # only add the arguments if this is pattern reply_content.append(each) reply_msg = KQMLPerformative('tell') reply_msg.set('sender', self.name) reply_msg.set('content', reply_content) self.connect(self.host, self.port) self.reply(msg, reply_msg)
def reply_on_local_port(self, msg: KQMLPerformative, reply_msg: KQMLPerformative): """Replies to a message on the local port (listener port) Args: msg (KQMLPerformative): message to reply to reply_msg (KQMLPerformative): message to reply with """ sender = msg.get('sender') if sender is not None: reply_msg.set('receiver', sender) reply_with = msg.get('reply-with') if reply_with is not None: reply_msg.set('in-reply-to', reply_with) self.send_on_local_port(reply_msg)
def respond_choose_sense(self, content): """Return response content to choose-sense request.""" ekb = content.gets('ekb-term') agents, ambiguities = process_ekb(ekb) msg = KQMLPerformative('SUCCESS') if agents: kagents = [] for term_id, agent_tuple in agents.items(): kagent = get_kagent(agent_tuple, term_id) kagents.append(kagent) msg.set('agents', KQMLList(kagents)) if ambiguities: ambiguities_msg = get_ambiguities_msg(ambiguities) msg.set('ambiguities', ambiguities_msg) return msg
def receive_subscribe(self, msg, content): logger.debug('received subscribe: ' + str(content)) # content performative should be an ask-all if content.head() == 'ask-all': # if we kept track of msg ideas, could check for that, but we aren't # content of content is the query that we care about query = content.get('content') # as a KQMLList? query_string = query.to_string() if query.head() in self.asks and query_string in self.subscribers: self.subscribers[query_string].append(msg) self.subcribe_data_old[query_string] = None self.subcribe_data_new[query_string] = None reply_msg = KQMLPerformative('tell') reply_msg.set(':sender', self.name) reply_msg.set('content', ':ok') self.reply(msg, reply_msg)
def send_display_model(self, model, diagrams): msg = KQMLPerformative('tell') content = KQMLList('display-model') content.set('type', 'indra') content.sets('model', model) msg.set('content', content) self.send(msg) for diagram_type, path in diagrams.items(): if not path: continue msg = KQMLPerformative('tell') content = KQMLList('display-image') content.set('type', diagram_type) content.sets('path', path) msg.set('content', content) self.send(msg)
def receive_tell(self, msg, content): """Override to store content and reply with nothing Arguments: msg {KQMLPerformative} -- tell to be passed along in reply content {KQMLPerformative} -- tell from companions to be logged """ LOGGER.debug('received tell: %s', content) # lazy logging for c in content: self.facts.append(c) if self.ask_in_progress: self.ask_in_progress = False reply_msg = KQMLPerformative('tell') reply_msg.set('sender', self.name) reply_msg.set('content', None) self.reply(msg, reply_msg)
def respond_expand_model(self, content): """Return response content to expand-model request.""" descr = content.gets('description') model_id = self._get_model_id(content) descr_format = content.gets('format') no_display = content.get('no-display') try: if not descr_format or descr_format == 'ekb': res = self.mra.expand_model_from_ekb(descr, model_id) elif descr_format == 'indra_json': res = self.mra.expand_model_from_json(descr, model_id) else: err_msg = 'Invalid description format: %s' % descr_format raise InvalidModelDescriptionError(err_msg) except Exception as e: raise InvalidModelDescriptionError(e) new_model_id = res.get('model_id') if new_model_id is None: raise InvalidModelDescriptionError() # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', str(new_model_id)) # Add the INDRA model json model = res.get('model') model_msg = encode_indra_stmts(model) msg.sets('model', model_msg) # Add the INDRA model new json model_new = res.get('model_new') if model_new: self.send_background_support(model_new) model_new_msg = encode_indra_stmts(model_new) msg.sets('model-new', model_new_msg) # Add the diagram if not no_display: diagrams = res.get('diagrams') if diagrams: rxn_diagram = diagrams.get('reactionnetwork') if rxn_diagram: msg.sets('diagram', rxn_diagram) self.send_display_model(diagrams) ambiguities = res.get('ambiguities') if ambiguities: ambiguities_msg = get_ambiguities_msg(ambiguities) msg.set('ambiguities', ambiguities_msg) return msg
def receive_ping(self, msg): reply = KQMLPerformative('update') reply.set('sender', self.name) #reply.set('receiver', msg.get('sender')) #reply.set('in-reply-to', msg.get('reply-with')) reply_content = KQMLList([':agent', self.name]) reply_content.append(':uptime') reply_content.append(self.uptime()) # I think .set('status', ':OK') can be used here reply_content.append(':status') reply_content.append(':OK') reply_content.append(':state') reply_content.append('idle') reply_content.append(':machine') reply_content.append(socket.gethostname()) reply.set('content', reply_content) self.reply(msg, reply)
def handle_achieve_action(self, msg, content, action): if action.head() in self.achieves: try: args = action.data[1:] results = self.achieves[action.head()](*args) logger.debug("Return of achieve: " + str(results)) reply = KQMLPerformative('tell') reply.set('sender', self.name) results_list = listify(results) reply.set('content', results_list) self.reply(msg, reply) except Exception as ex: logger.debug(traceback.print_exc()) self.error_reply( msg, 'An error occurred while executing: ' + action.head()) else: self.error_reply(msg, 'unknown action: ' + action.head())
def respond_model_remove_mechanism(self, content): """Return response content to model-remove-mechanism request.""" ekb = content.gets('description') model_id = self._get_model_id(content) no_display = content.get('no-display') try: res = self.mra.remove_mechanism(ekb, model_id) except Exception as e: raise InvalidModelDescriptionError(e) model_id = res.get('model_id') if model_id is None: raise InvalidModelDescriptionError('Could not find model id.') # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', str(model_id)) # Add the INDRA model json model = res.get('model') model_msg = encode_indra_stmts(model) msg.sets('model', model_msg) # Handle empty model if not model: self.send_clean_model() # Get the action and add it to the message removed = res.get('removed') if not removed: msg = self.make_failure('REMOVE_FAILED') return msg else: actionl = KQMLList('remove_stmts') actionl.sets('statements', encode_indra_stmts(removed)) msg.set('action', actionl) # Add the diagram diagrams = res.get('diagrams') logger.info(diagrams) if not no_display: if diagrams: rxn_diagram = diagrams.get('reactionnetwork') if rxn_diagram: msg.sets('diagram', rxn_diagram) self.send_display_model(diagrams) return msg
def respond_choose_sense(self, content): """Return response content to choose-sense request.""" ekb = content.gets('ekb-term') msg = KQMLPerformative('SUCCESS') try: agents, ambiguities = self.bs.choose_sense(ekb) except InvalidAgentError: logger.info("agent not recognized:\n{}\n".format(ekb)) else: kagents = [] for term_id, agent_tuple in agents.items(): kagent = get_kagent(agent_tuple, term_id) kagents.append(kagent) msg.set('agents', KQMLList(kagents)) if ambiguities: ambiguities_msg = get_ambiguities_msg(ambiguities) msg.set('ambiguities', ambiguities_msg) return msg
def respond_with_pattern(self, msg, content, results): reply_content = KQMLList(content.head()) results_list = results if isinstance(results, list) else [results] result_index = 0 arg_len = len(content.data[1:]) for i, each in enumerate(content.data[1:]): if str(each[0]) == '?': #add result if i == arg_len and result_index < len(results_list) - 1: # shove the rest of the results into this one var reply_content.append(listify(results_list[result_index:])) else: reply_content.append(listify(results_list[result_index])) result_index += 1 else: reply_content.append(each) reply_msg = KQMLPerformative('tell') reply_msg.set('sender', self.name) reply_msg.set('content', reply_content) self.reply(msg, reply_msg)
def respond_model_has_mechanism(self, content): """Return response content to model-has-mechanism request.""" ekb = content.gets('description') model_id = self._get_model_id(content) try: res = self.mra.has_mechanism(ekb, model_id) except Exception as e: raise InvalidModelDescriptionError(e) # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', str(model_id)) # Add TRUE or FALSE for has-mechanism has_mechanism_msg = 'TRUE' if res['has_mechanism'] else 'FALSE' msg.set('has-mechanism', has_mechanism_msg) query = res.get('query') if query: query_msg = encode_indra_stmts([query]) msg.sets('query', query_msg) return msg
def respond_has_mechanism(self, content): """Return response content to model-has-mechanism request.""" ekb = content.gets('description') model_id = self._get_model_id(content) try: res = self.mra.has_mechanism(ekb, model_id) except Exception as e: raise InvalidModelDescriptionError(e) # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', str(model_id)) # Add TRUE or FALSE for has-mechanism has_mechanism_msg = 'TRUE' if res['has_mechanism'] else 'FALSE' msg.set('has-mechanism', has_mechanism_msg) query = res.get('query') if query: query_msg = encode_indra_stmts([query]) msg.sets('query', query_msg) return msg
def send_provenance(self, result): id1 = result['id1'] mods1 = result['mods1'] id2 = result['id2'] mods2 = result['mods2'] rel = result['rel'] title = str(id1) + ' ' + str(rel) + ' ' + str(id2) uri_str = result['uri_str'] pc_url = 'http://www.pathwaycommons.org/pc2/get?' + uri_str + 'format=SBGN' html = '<a href= \'' + pc_url + '\' target= \'_blank\' > PC link</a>' msg = KQMLPerformative('tell') content = KQMLList('add-provenance') content.sets('html', html) pc_url_formatted = "http://www.pathwaycommons.org/pc2/get?" + uri_str + "format=SBGN" content.sets('pc', pc_url_formatted) content.sets('title', title) msg.set('content', content) self.send(msg)
def achieve_on_agent(self, receiver, data): msg = KQMLPerformative('achieve') msg.set('sender', self.name) msg.set('receiver', receiver) msg.set('content', listify(data)) self.connect(self.host, self.port) self.send(msg)
def respond_get_paper_model(self, content): """Get and display the model from a paper, indicated by pmid.""" pmid_raw = content.gets('pmid') prefix = 'PMID-' if pmid_raw.startswith(prefix) and pmid_raw[len(prefix):].isdigit(): pmid = pmid_raw[len(prefix):] else: return self.make_failure('BAD_INPUT') try: stmts = get_statements_for_paper([('pmid', pmid)]) except IndraDBRestAPIError as e: if e.status_code == 404 and 'Invalid or unavailable' in e.reason: logger.error("Could not find pmid: %s" % e.reason) return self.make_failure('MISSING_MECHANISM') else: raise e if not stmts: resp = KQMLPerformative('SUCCESS') resp.set('relations-found', 0) return resp stmts = ac.map_grounding(stmts) stmts = ac.map_sequence(stmts) unique_stmts = ac.run_preassembly(stmts, return_toplevel=True) diagrams = _make_diagrams(stmts) self.send_display_model(diagrams) resp = KQMLPerformative('SUCCESS') resp.set('relations-found', len(unique_stmts)) resp.set('dump-limit', str(DUMP_LIMIT)) return resp
def insert_data(self, receiver, data, wm_only=False): """Takes the data input by the user and processes it into an insert message which is subsequently sent off to Companions. Arguments: receiver {str} -- name of the receiver data {[type]} -- anything that can be listified Keyword Arguments: wm_only {bool} -- whether or not this should only be inserted into the working memory (default: {False}) """ msg = KQMLPerformative('insert') msg.set('sender', self.name) msg.set('receiver', receiver) if wm_only: msg.data.append(':wm-only?') # KMQLPerformative has no function # append, instead we must access the KQMLList inside the # KQMLPerformative .data attribute... msg.set('content', listify(data)) # pylint: disable=no-member # pylint was unable to pick up on the host and port variables being in # a defaults dict which is then used to do __setattr__ with the key # value pairs from the dict. # self.connect(self.host, self.port) self.send(msg)
def respond_confirm_relation_from_literature(self, content): """Confirm a protein-protein interaction given subject, object, verb""" try: subj, obj, stmt_type, filter_agents = self._get_query_info(content) finder = \ self.msa.find_mechanism_from_input(subj, obj, None, stmt_type, ev_limit=5, persist=False, timeout=5, filter_agents=filter_agents) self._send_provenance_async(finder, 'confirming that some statements match') except MSALookupError as mle: return self.make_failure(mle.args[0]) stmts = finder.get_statements(timeout=20) if stmts is None: # TODO: Handle this more gracefully, if possible. return self.make_failure('MISSING_MECHANISM') num_stmts = len(stmts) description = finder.describe(include_negative=False) \ if stmts else None #self.say(description) resp = KQMLPerformative('SUCCESS') resp.set('some-relations-found', 'TRUE' if num_stmts else 'FALSE') resp.set('num-relations-found', str(num_stmts)) resp.set('dump-limit', str(DUMP_LIMIT)) resp.sets('suggestion', description if description else 'nil') return resp
def respond_get_paper_model(self, content): """Get and display the model from a paper, indicated by pmid.""" pmid_raw = content.gets('pmid') prefix = 'PMID-' if pmid_raw.startswith(prefix) and pmid_raw[len(prefix):].isdigit(): pmid = pmid_raw[len(prefix):] else: return self.make_failure('BAD_INPUT') try: stmts = get_statements_for_paper([('pmid', pmid)], simple_response=True) except IndraDBRestAPIError as e: if e.status_code == 404 and 'Invalid or unavailable' in e.reason: logger.error("Could not find pmid: %s" % e.reason) return self.make_failure('MISSING_MECHANISM') else: raise e if not stmts: resp = KQMLPerformative('SUCCESS') resp.set('relations-found', 0) return resp stmts = ac.map_grounding(stmts) stmts = ac.map_sequence(stmts) unique_stmts = ac.run_preassembly(stmts, return_toplevel=True) diagrams = _make_diagrams(stmts) self.send_display_model(diagrams) resp = KQMLPerformative('SUCCESS') resp.set('relations-found', len(unique_stmts)) resp.set('dump-limit', str(DUMP_LIMIT)) return resp
def create_message(self): content = KQMLPerformative('SATISFIES-PATTERN') content.set('model', self.model) patt = KQMLList() patt.sets('type', 'eventual_value') ents = KQMLList() ent = KQMLList() ent.sets('description', agent_clj_from_text('phosphorylated MAPK1')) ents.append(ent) patt.set('entities', ents) val = KQMLList() val.sets('type', 'qualitative') val.sets('value', 'low') patt.set('value', val) content.set('pattern', patt) conds = KQMLList() cond = KQMLList() cond.sets('type', 'multiple') quant = KQMLList() quant.sets('type', 'total') ent = KQMLList() ent.sets('description', agent_clj_from_text('DUSP6')) quant.set('entity', ent) cond.sets('quantity', quant) #val = KQMLList() #val.sets('type', 'number') cond.set('value', KQMLToken('10')) #cond.set('value', val) conds.append(cond) content.set('conditions', conds) msg = get_request(content) return msg, content
def receive_achieve(self, msg, content): """Overrides the default KQMLModule receive for achieves and instead does basic error checking before attempting the action by calling the proper ask function with the arguments passed along as inputs. Arguments: msg {KQMLPerformative} -- predicate/ signifier of task content {KQMLPerformative} -- action task is referring to """ if content.head() == 'task': action = content.get('action') if action: if action.head() in self.achieves: try: args = action.data[1:] results = self.achieves[action.head()](*args) LOGGER.debug("Return of achieve: %s", results) reply = KQMLPerformative('tell') reply.set('sender', self.name) reply.set('content', listify(results)) self.reply(msg, reply) # pylint: disable=broad-except # The above try can throw KQMLBadPerformativeException, # KQMLException, ValueError, and StopWaitingSignal at the # least. To stay simple and more in-line with PEP8 we are # logging the traceback and the user should be made aware # of the fact that an error occurred via the error_reply. # For these reasons the 'broad-except' is valid here. except Exception: LOGGER.debug(traceback.print_exc()) error_msg = 'An error occurred while executing: ' self.error_reply(msg, error_msg + action.head()) else: self.error_reply(msg, 'Unknown action: ' + action.head()) else: self.error_reply(msg, 'No action for achieve task provided') else: error_msg = 'Unexpected achieve command: ' self.error_reply(msg, error_msg + content.head())
def respond_model_undo(self, content): """Return response content to model-undo request.""" res = self.mra.model_undo() no_display = content.get('no-display') model_id = res.get('model_id') # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', 'NIL' if model_id is None else str(model_id)) # Add the INDRA model json model = res.get('model') # Handle empty model if not model: self.send_clean_model() model_msg = encode_indra_stmts(model) msg.sets('model', model_msg) # Get the action and add it to the message action = res.get('action') actionl = KQMLList() # Here we handle no action as effectively an empty remove action if action['action'] in ('no_op', 'remove_stmts'): actionl.append('remove_stmts') actionl.sets( 'statements', encode_indra_stmts(action['statements']) ) msg.set('action', actionl) # Add the diagram diagrams = res.get('diagrams') if not no_display: if diagrams: rxn_diagram = diagrams.get('reactionnetwork') if rxn_diagram: msg.sets('diagram', rxn_diagram) self.send_display_model(diagrams) return msg
def _get_perf(text, msg_id): """Return a request message for a given text.""" msg = KQMLPerformative('REQUEST') msg.set('receiver', 'READER') content = KQMLList('run-text') content.sets('text', text) msg.set('content', content) msg.set('reply-with', msg_id) return msg
def respond_build_model(self, content): """Return response content to build-model request.""" descr = content.gets('description') descr_format = content.gets('format') no_display = content.get('no-display') if not descr_format or descr_format == 'ekb': res = self.mra.build_model_from_ekb(descr) elif descr_format == 'indra_json': res = self.mra.build_model_from_json(descr) else: err_msg = 'Invalid description format: %s' % descr_format raise InvalidModelDescriptionError(err_msg) if res.get('error'): raise InvalidModelDescriptionError(res.get('error')) model_id = res.get('model_id') if model_id is None: raise InvalidModelDescriptionError() # Start a SUCCESS message msg = KQMLPerformative('SUCCESS') # Add the model id msg.set('model-id', str(model_id)) # Add the INDRA model json model = res.get('model') if model and (descr_format == 'ekb' or not descr_format): self.send_background_support(model) model_msg = encode_indra_stmts(model) msg.sets('model', model_msg) # Add the diagrams diagrams = res.get('diagrams') if not no_display: if diagrams: rxn_diagram = diagrams.get('reactionnetwork') if rxn_diagram: msg.sets('diagram', rxn_diagram) self.send_display_model(diagrams) # Indicate whether the goal has been explained has_expl = res.get('has_explanation') if has_expl is not None: msg.set('has_explanation', str(has_expl).upper()) # Send out various model diagnosis messages self.send_model_diagnoses(res) # Once we sent out the diagnosis messages, we make sure we keep # track of whether we have an explanation if has_expl: self.have_explanation = True # Analyze the model for issues # Report ambiguities ambiguities = res.get('ambiguities') if ambiguities: ambiguities_msg = get_ambiguities_msg(ambiguities) msg.set('ambiguities', ambiguities_msg) return msg
def read_pmc(self, pmcid): """Read a given PMC article. Parameters ---------- pmcid : str The PMC ID of the article to read. Note that only articles in the open-access subset of PMC will work. """ msg = KQMLPerformative('REQUEST') msg.set('receiver', 'READER') content = KQMLList('run-pmcid') content.sets('pmcid', pmcid) content.set('reply-when-done', 'true') msg.set('content', content) msg.set('reply-with', 'P-%s' % pmcid) self.reply_counter += 1 self.send(msg)
def respond_confirm_relation_from_literature(self, content): """Confirm a protein-protein interaction given subject, object, verb""" try: subj, obj, stmt_type = self._get_query_info(content) finder = \ self.msa.find_mechanism_from_input(subj, obj, None, stmt_type, ev_limit=5, persist=False, timeout=5) self._send_provenance_async(finder, 'confirming that some statements match') except MSALookupError as mle: return self.make_failure(mle.args[0]) stmts = finder.get_statements(timeout=20) if stmts is None: # TODO: Handle this more gracefully, if possible. return self.make_failure('MISSING_MECHANISM') num_stmts = len(stmts) self.say(finder.describe()) resp = KQMLPerformative('SUCCESS') resp.set('some-relations-found', 'TRUE' if num_stmts else 'FALSE') resp.set('num-relations-found', str(num_stmts)) resp.set('dump-limit', str(DUMP_LIMIT)) return resp
def ready(self): msg = KQMLPerformative('tell') content = KQMLList(['module-status', 'ready']) msg.set('content', content) self.send(msg)
def reply_with_content(self, msg, reply_content): """A wrapper around the reply method from KQMLModule.""" reply_msg = KQMLPerformative('reply') reply_msg.set('content', reply_content) self.reply(msg, reply_msg) return
def tell(self, content): """Send a tell message.""" msg = KQMLPerformative('tell') msg.set('content', content) return self.send(msg)
def request(self, content): """Send a request message.""" msg = KQMLPerformative('request') msg.set('content', content) return self.send(msg)
def create_message(self): content = KQMLList('TEST') content.sets('description', '') msg = KQMLPerformative('REQUEST') msg.set('content', content) return msg, content
def send_clean_model(self): msg = KQMLPerformative('request') content = KQMLList('clean-model') msg.set('content', content) self.send(msg)
def get_request(content): msg = KQMLPerformative('REQUEST') msg.set('content', content) msg.set('reply-with', 'IO-1') return msg
def respond_find_relations_from_literature(self, content): """Find statements matching some subject, verb, object information.""" try: subj, obj, stmt_type = self._get_query_info(content) finder = \ self.msa.find_mechanism_from_input(subj, obj, None, stmt_type, ev_limit=3, persist=False, timeout=5) self._send_provenance_async(finder, 'finding statements that match') except MSALookupError as mle: return self.make_failure(mle.args[0]) stmts = finder.get_statements(timeout=15) if stmts is None: # Calling this success may be a bit ambitious. resp = KQMLPerformative('SUCCESS') resp.set('status', 'WORKING') resp.set('relations-found', 'nil') resp.set('dump-limit', str(DUMP_LIMIT)) return resp self.say(finder.describe()) resp = KQMLPerformative('SUCCESS') resp.set('status', 'FINISHED') resp.set('relations-found', str(len(stmts))) resp.set('dump-limit', str(DUMP_LIMIT)) return resp