Пример #1
0
 def __init__(self, argv):
     # Call the constructor of TripsModule
     super(DTDA_Module, self).__init__(argv)
     self.tasks = [
         'IS-DRUG-TARGET', 'FIND-TARGET-DRUG', 'FIND-DISEASE-TARGETS',
         'FIND-TREATMENT'
     ]
     # Send subscribe messages
     for task in self.tasks:
         msg_txt =\
             '(subscribe :content (request &key :content (%s . *)))' % task
         self.send(KQMLPerformative.from_string(msg_txt))
     # Instantiate a singleton DTDA agent
     self.dtda = DTDA()
     # Send ready message
     self.ready()
     super(DTDA_Module, self).start()
Пример #2
0
 def init(self):
     '''
     Initialize TRIPS module
     '''
     super(DTDA_Module, self).init()
     # Send subscribe messages
     for task, subtasks in self.tasks.iteritems():
         for subtask in subtasks:
             msg_txt = '(subscribe :content (request &key :content ' +\
                 '(%s &key :content (%s . *))))' % (task, subtask)
             self.send(KQMLPerformative.fromString(msg_txt))
     # Instantiate a singleton DTDA agent
     self.dtda = DTDA()
     # Send ready message
     self.ready()
Пример #3
0
 def __init__(self, argv):
     # Call the constructor of TripsModule
     super(DTDA_Module, self).__init__(argv)
     self.tasks = ['IS-DRUG-TARGET', 'FIND-TARGET-DRUG',
                   'FIND-DISEASE-TARGETS', 'FIND-TREATMENT']
     # Send subscribe messages
     for task in self.tasks:
         msg_txt =\
             '(subscribe :content (request &key :content (%s . *)))' % task
         self.send(KQMLPerformative.from_string(msg_txt))
     # Instantiate a singleton DTDA agent
     self.dtda = DTDA()
     # Send ready message
     self.ready()
     super(DTDA_Module, self).start()
Пример #4
0
 def __init__(self, **kwargs):
     # Instantiate a singleton DTDA agent
     self.dtda = DTDA()
     super(DTDA_Module, self).__init__(**kwargs)
Пример #5
0
class DTDA_Module(Bioagent):
    """The DTDA module is a TRIPS module built around the DTDA agent.
    Its role is to receive and decode messages and send responses from and
    to other agents in the system."""
    name = "DTDA"
    tasks = [
        'IS-DRUG-TARGET', 'FIND-TARGET-DRUG', 'FIND-DISEASE-TARGETS',
        'FIND-TREATMENT'
    ]

    def __init__(self, **kwargs):
        # Instantiate a singleton DTDA agent
        self.dtda = DTDA()
        super(DTDA_Module, self).__init__(**kwargs)

    def respond_is_drug_target(self, content):
        """Response content to is-drug-target request."""
        try:
            drug_arg = content.gets('drug')
        except:
            reply = make_failure('INVALID_DRUG')
        try:
            drug = self._get_target(drug_arg)
        except Exception as e:
            reply = make_failure('DRUG_NOT_FOUND')
            return reply
        drug_name = drug.name
        try:
            target_arg = content.gets('target')
            target = self._get_target(target_arg)
            target_name = target.name
        except:
            reply = make_failure('INVALID_TARGET')
            return reply

        try:
            is_target = self.dtda.is_nominal_drug_target(
                drug_name, target_name)
        except DrugNotFoundException:
            reply = make_failure('DRUG_NOT_FOUND')
            return reply
        reply = KQMLList('SUCCESS')
        reply.set('is-target', 'TRUE' if is_target else 'FALSE')
        return reply

    def respond_find_target_drug(self, content):
        """Response content to find-target-drug request."""
        try:
            target_arg = content.gets('target')
            target = self._get_target(target_arg)
            target_name = target.name
        except Exception as e:
            reply = make_failure('INVALID_TARGET')
            return reply
        drug_names, pubchem_ids = self.dtda.find_target_drugs(target_name)
        reply = KQMLList('SUCCESS')
        drugs = KQMLList()
        for dn, pci in zip(drug_names, pubchem_ids):
            drug = KQMLList()
            drug.set('name', dn.replace(' ', '-'))
            if pci:
                drug.set('pubchem_id', pci)
            drugs.append(drug)
        reply.set('drugs', drugs)
        return reply

    def respond_find_disease_targets(self, content):
        """Response content to find-disease-targets request."""
        try:
            disease_arg = content.gets('disease')
            disease = self.get_disease(disease_arg)
        except Exception as e:
            logger.error(e)
            reply = make_failure('INVALID_DISEASE')
            return reply

        if disease.disease_type != 'cancer':
            reply = make_failure('DISEASE_NOT_FOUND')
            return reply

        logger.debug('Disease: %s' % disease.name)

        try:
            mut_protein, mut_percent = \
                self.dtda.get_top_mutation(disease.name)
        except DiseaseNotFoundException:
            reply = make_failure('DISEASE_NOT_FOUND')
            return reply

        # TODO: get functional effect from actual mutations
        # TODO: add list of actual mutations to response
        # TODO: get fraction not percentage from DTDA
        reply = KQMLList('SUCCESS')
        protein = KQMLList()
        protein.set('name', mut_protein)
        protein.set('hgnc', mut_protein)
        reply.set('protein', protein)
        reply.set('prevalence', '%.2f' % (mut_percent / 100.0))
        reply.set('functional-effect', 'ACTIVE')
        return reply

    def respond_find_treatment(self, content):
        """Response content to find-treatment request."""
        try:
            disease_arg = content.gets('disease')
            disease = self.get_disease(disease_arg)
        except Exception as e:
            logger.error(e)
            reply = make_failure('INVALID_DISEASE')
            return reply

        if disease.disease_type != 'cancer':
            reply = make_failure('DISEASE_NOT_FOUND')
            return reply

        logger.debug('Disease: %s' % disease.name)

        try:
            mut_protein, mut_percent = \
                self.dtda.get_top_mutation(disease.name)
        except DiseaseNotFoundException:
            reply = make_failure('DISEASE_NOT_FOUND')
            return reply

        reply = KQMLList()

        # TODO: get functional effect from actual mutations
        # TODO: add list of actual mutations to response
        # TODO: get fraction not percentage from DTDA
        reply1 = KQMLList('SUCCESS')
        protein = KQMLList()
        protein.set('name', mut_protein)
        protein.set('hgnc', mut_protein)
        reply1.set('protein', protein)
        reply1.set('prevalence', '%.2f' % (mut_percent / 100.0))
        reply1.set('functional-effect', 'ACTIVE')
        reply.append(reply1)

        reply2 = KQMLList('SUCCESS')
        drug_names, pubchem_ids = self.dtda.find_target_drugs(mut_protein)
        drugs = KQMLList()
        for dn, pci in zip(drug_names, pubchem_ids):
            drug = KQMLList()
            drug.sets('name', dn.replace(' ', '-'))
            if pci:
                drug.set('pubchem_id', pci)
            drugs.append(drug)
        reply2.set('drugs', drugs)

        reply.append(reply2)
        return reply

    def _get_target(self, target_str):
        tp = TripsProcessor(target_str)
        terms = tp.tree.findall('TERM')
        term_id = terms[0].attrib['id']
        agent = tp._get_agent_by_id(term_id, None)
        return agent

    def get_disease(self, disease_str):
        term = ET.fromstring(disease_str).find('TERM')
        disease_type = term.find('type').text
        if disease_type.startswith('ONT::'):
            disease_type = disease_type[5:].lower()
        drum_term = term.find('drum-terms/drum-term')
        dbname = drum_term.attrib['name']
        dbid = term.attrib['dbid']
        dbids = dbid.split('|')
        dbid_dict = {k: v for k, v in [d.split(':') for d in dbids]}
        disease = Disease(disease_type, dbname, dbid_dict)
        return disease
Пример #6
0
class DTDA_Module(trips_module.TripsModule):
    '''
    The DTDA module is a TRIPS module built around the DTDA agent.
    Its role is to receive and decode messages and send responses from and
    to other agents in the system.
    '''
    def __init__(self, argv):
        # Call the constructor of TripsModule
        super(DTDA_Module, self).__init__(argv)
        self.tasks = [
            'IS-DRUG-TARGET', 'FIND-TARGET-DRUG', 'FIND-DISEASE-TARGETS',
            'FIND-TREATMENT'
        ]
        # Send subscribe messages
        for task in self.tasks:
            msg_txt =\
                '(subscribe :content (request &key :content (%s . *)))' % task
            self.send(KQMLPerformative.from_string(msg_txt))
        # Instantiate a singleton DTDA agent
        self.dtda = DTDA()
        # Send ready message
        self.ready()
        super(DTDA_Module, self).start()

    def receive_request(self, msg, content):
        '''
        If a "request" message is received, decode the task and the content
        and call the appropriate function to prepare the response. A reply
        message is then sent back.
        '''
        content_list = content
        task_str = content_list[0].to_string().upper()
        if task_str == 'IS-DRUG-TARGET':
            reply_content = self.respond_is_drug_target(content_list)
        elif task_str == 'FIND-TARGET-DRUG':
            reply_content = self.respond_find_target_drug(content_list)
        elif task_str == 'FIND-DISEASE-TARGETS':
            reply_content = self.respond_find_disease_targets(content_list)
        elif task_str == 'FIND-TREATMENT':
            reply_content = self.respond_find_treatment(content_list)
            if reply_content is None:
                self.respond_dont_know(msg,
                                       '(ONT::A X1 :instance-of ONT::DRUG)')
                return
        else:
            self.error_reply(msg, 'unknown request task ' + task_str)
            return

        reply_msg = KQMLPerformative('reply')
        reply_msg.set_parameter(':content', reply_content)
        self.reply(msg, reply_msg)

    def respond_dont_know(self, msg, content_string):
        resp = '(ONT::TELL :content (ONT::DONT-KNOW :content %s))' %\
            content_string
        resp_list = KQMLList.from_string(resp)
        reply_msg = KQMLPerformative('reply')
        reply_msg.set_parameter(':content', resp_list)
        self.reply(msg, reply_msg)

    def respond_is_drug_target(self, content_list):
        '''
        Response content to is-drug-target request
        '''
        drug_arg = content_list.get_keyword_arg(':drug')
        drug = drug_arg[0].to_string()
        target_arg = content_list.get_keyword_arg(':target')
        target = target_arg[0].to_string()
        reply_content = KQMLList()
        try:
            is_target = self.dtda.is_nominal_drug_target(drug, target)
        except DrugNotFoundException:
            reply_content.add('FAILURE :reason DRUG_NOT_FOUND')
            return reply_content
        status = 'SUCCESS'
        if is_target:
            is_target_str = 'TRUE'
        else:
            is_target_str = 'FALSE'
        msg_str = '%s :is-target %s' %\
                  (status, is_target_str)
        reply_content.add(msg_str)
        return reply_content

    def respond_find_target_drug(self, content_list):
        '''
        Response content to find-target-drug request
        '''
        target = content_list.get_keyword_arg(':target')
        target_str = target.to_string()[1:-1]
        drug_names, chebi_ids = self.dtda.find_target_drugs(target_str)
        drug_list_str = ''
        for dn, ci in zip(drug_names, chebi_ids):
            if ci is None:
                drug_list_str += '(:name %s) ' % dn.encode('ascii', 'ignore')
            else:
                drug_list_str += '(:name %s :chebi_id %s) ' % (dn, ci)
        reply_content = KQMLList.from_string('(SUCCESS :drugs (' +
                                             drug_list_str + '))')
        return reply_content

    def respond_find_disease_targets(self, content_list):
        '''
        Response content to find-disease-targets request
        '''
        disease_arg = content_list.get_keyword_arg(':disease')
        try:
            disease = self.get_disease(disease_arg)
        except Exception as e:
            logger.error(e)
            msg_str = '(FAILURE :reason INVALID_DISEASE)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        if disease.disease_type != 'cancer':
            msg_str = '(FAILURE :reason DISEASE_NOT_FOUND)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        logger.debug('Disease: %s' % disease.name)

        try:
            mut_protein, mut_percent =\
                self.dtda.get_top_mutation(disease.name)
        except DiseaseNotFoundException:
            msg_str = '(FAILURE :reason DISEASE_NOT_FOUND)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        # TODO: get functional effect from actual mutations
        # TODO: add list of actual mutations to response
        # TODO: get fraction not percentage from DTDA
        reply_content =\
            KQMLList.from_string(
                '(SUCCESS ' +
                ':protein (:name %s :hgnc %s) ' % (mut_protein, mut_protein) +
                ':prevalence %.2f ' % (mut_percent/100.0) +
                ':functional-effect ACTIVE)')

        return reply_content

    def respond_find_treatment(self, content_list):
        '''
        Response content to find-treatment request
        '''
        reply_content = KQMLList()
        #TODO: eliminate code duplication here
        disease_arg = content_list.get_keyword_arg(':disease')
        try:
            disease = self.get_disease(disease_arg)
        except Exception as e:
            logger.error(e)
            msg_str = '(FAILURE :reason INVALID_DISEASE)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        if disease.disease_type != 'cancer':
            reply_content.add('FAILURE :reason DISEASE_NOT_FOUND')
            return reply_content

        logger.debug('Disease: %s' % disease.name)

        try:
            mut_protein, mut_percent = \
                self.dtda.get_top_mutation(disease.name)
        except DiseaseNotFoundException:
            reply_content.add('FAILURE :reason DISEASE_NOT_FOUND')
            return reply_content

        # TODO: get functional effect from actual mutations
        # TODO: add list of actual mutations to response
        # TODO: get fraction not percentage from DTDA
        reply_content.add(
            KQMLList.from_string('(SUCCESS ' +
                                 ':protein (:name %s :hgnc %s) ' %
                                 (mut_protein, mut_protein) +
                                 ':prevalence %.2f ' % (mut_percent / 100.0) +
                                 ':functional-effect ACTIVE)'))

        # Try to find a drug
        drug_names, chebi_ids = self.dtda.find_target_drugs(mut_protein)
        drug_list_str = ''
        for dn, ci in zip(drug_names, chebi_ids):
            if ci is None:
                drug_list_str += '(:name %s) ' % dn.encode('ascii', 'ignore')
            else:
                drug_list_str += '(:name %s :chebi_id %s) ' % (dn, ci)
        reply_content.add(
            KQMLList.from_string('(SUCCESS :drugs (' + drug_list_str + '))'))

        return reply_content

    @staticmethod
    def get_disease(disease_arg):
        disease_type = str(disease_arg[0]).lower()
        dbname = str(disease_arg.get_keyword_arg(':dbname'))[1:-1]
        dbid = str(disease_arg.get_keyword_arg(':dbid'))[1:-1]
        dbids = dbid.split('|')
        dbid_dict = {k: v for k, v in [d.split(':') for d in dbids]}
        disease = Disease(disease_type, dbname, dbid_dict)
        return disease

    @staticmethod
    def get_single_argument(arg):
        if arg is None:
            return None
        arg_str = arg.to_string()
        if arg_str[0] == '(' and arg_str[-1] == ')':
            arg_str = arg_str[1:-1]
        arg_str = arg_str.lower()
        return arg_str
Пример #7
0
class DTDA_Module(trips_module.TripsModule):
    '''
    The DTDA module is a TRIPS module built around the DTDA agent. Its role is to
    receive and decode messages and send responses from and to other agents in 
    the system.
    '''
    def __init__(self, argv):
        # Call the constructor of TripsModule
        super(DTDA_Module, self).__init__(argv)
        self.tasks = {'ONT::PERFORM': ['ONT::IS-DRUG-TARGET', 
                    'ONT::FIND-TARGET-DRUG', 'ONT::FIND-DISEASE-TARGETS', 
                    'ONT::FIND-TREATMENT']}

    def init(self):
        '''
        Initialize TRIPS module
        '''
        super(DTDA_Module, self).init()
        # Send subscribe messages
        for task, subtasks in self.tasks.iteritems():
            for subtask in subtasks:
                msg_txt = '(subscribe :content (request &key :content ' +\
                    '(%s &key :content (%s . *))))' % (task, subtask)
                self.send(KQMLPerformative.fromString(msg_txt))
        # Instantiate a singleton DTDA agent
        self.dtda = DTDA()
        # Send ready message
        self.ready()

    def receive_request(self, msg, content):
        '''
        If a "request" message is received, decode the task and the content
        and call the appropriate function to prepare the response. A reply 
        "tell" message is then sent back.
        '''
        content_list = cast(KQMLList, content)
        task_str = content_list.get(0).toString().upper()
        if task_str == 'ONT::PERFORM':
            subtask = cast(KQMLList,content_list.getKeywordArg(':content'))
            subtask_str = subtask.get(0).toString().upper()
            if subtask_str == 'ONT::IS-DRUG-TARGET':
                reply_content = self.respond_is_drug_target(content_list)
            elif subtask_str == 'ONT::FIND-TARGET-DRUG':
                reply_content = self.respond_find_target_drug(content_list)
            elif subtask_str == 'ONT::FIND-DISEASE-TARGETS':
                reply_content = self.respond_find_disease_targets(content_list)
            elif subtask_str == 'ONT::FIND-TREATMENT':
                reply_content = self.respond_find_treatment(subtask)
                if reply_content is None:
                    self.respond_dont_know(msg, '(ONT::A X1 :instance-of ONT::DRUG)')
                    return
            else:
                self.error_reply(msg, 'unknown request subtask ' + subtask_str)
                return
        else:
            self.error_reply(msg, 'unknown request task ' + task_str)
            return
        
        reply_msg = KQMLPerformative('reply')
        reply_msg.setParameter(':content', cast(KQMLObject, reply_content))
        self.reply(msg, reply_msg)
   
    def respond_dont_know(self, msg, content_string):
        resp = '(ONT::TELL :content (ONT::DONT-KNOW :content %s))' % content_string
        resp_list = KQMLList.fromString(resp)
        reply_msg = KQMLPerformative('reply')
        reply_msg.setParameter(':content', cast(KQMLObject, resp_list))
        self.reply(msg, reply_msg)

    def respond_is_drug_target(self, content_list):
        '''
        Response content to is-drug-target request
        '''
        # TODO: get parameters from content
        is_target = self.dtda.is_nominal_drug_target('Vemurafenib', 'BRAF')
        reply_content = KQMLList()
        if is_target:
            msg_str = 'TRUE'
        else:
            msg_str = 'FALSE'
        reply_content.add(msg_str)
        return reply_content
    
    def respond_find_target_drug(self, content_list):
        '''
        Response content to find-target-drug request
        '''
        # TODO: implement
        reply_content = KQMLList()
        reply_content.add('')
        return reply_content
    
    def respond_find_disease_targets(self, content_list):
        '''
        Response content to find-disease-targets request
        '''
        # TODO: implement
        self.dtda.get_mutation_statistics('pancreatic', 'missense')
        reply_content = KQMLList()
        reply_content.add('')
        return reply_content

    def respond_find_treatment(self, content_list):
        '''
        Response content to find-treatment request
        '''
        reply_content = KQMLList()
        
        # Parse content
        disease_str = content_list.getKeywordArg(':disease')
        if disease_str is None:
            print 'no disease set'
            return None
        disease_str = disease_str.toString()
        disease_terms = disease_str[1:-1].split(' ')
        disease = disease_terms[0]
        disease_type = disease_terms[1]
        disease_str = disease[3:].lower()

        if disease_str not in ['cancer', 'tumor'] and\
            disease_str.find('carcinoma') == -1 and\
            disease_str.find('cancer') == -1 and\
            disease_str.find('melanoma') == -1:
            print 'problem with disease name'
            return None
        if disease_type == '-':
            disease_type_filter = disease_str
            disease_type_filter = disease_type_filter.replace('cancer', '')
            disease_type_filter = disease_type_filter.replace('-', '')
        else:
            disease_type_filter = disease_type[3:].lower()
       
        print disease_type_filter

        # First, look for possible disease targets
        mutation_stats = self.dtda.get_mutation_statistics(disease_type_filter, 'missense')
        if mutation_stats is None:
            print 'no mutation stats'
            return None

        # Return the top mutation as a possible target
        mutations_sorted = sorted(mutation_stats.items(), 
            key=operator.itemgetter(1), reverse=True)
        top_mutation = mutations_sorted[0]
        mut_protein = top_mutation[0]
        mut_percent = int(top_mutation[1][0]*100.0)
        
        mut_response = KQMLList.fromString('(ONT::TELL :content ' +\
            '(ONT::PROPORTION :refset (ONT::CANCER-PATIENT) ' +\
            ':quan (ONT::PERCENT %d) ' % mut_percent +\
            ':content (ONT::MUTATION :affected ONT::%s)))' % mut_protein)

        # Try to find a drug targeting KRAS
        drugs = self.dtda.find_target_drug(mut_protein)
        #import ipdb; ipdb.set_trace()
        if not drugs:
            drug_response = KQMLList.fromString('(ONT::TELL :content (ONT::DONT-KNOW :content (ONT::A X1 :instance-of ONT::DRUG)))')
        else:
            drugs_str = ', '.join(drugs)
            drug_response = KQMLList.fromString('(ONT::TELL :content (%s))' % drugs_str)
        reply_content.add(KQMLList(mut_response))
        reply_content.add(KQMLList(drug_response))

        return reply_content
Пример #8
0
class DTDA_Module(KQMLModule):
    '''
    The DTDA module is a TRIPS module built around the DTDA agent.
    Its role is to receive and decode messages and send responses from and
    to other agents in the system.
    '''
    def __init__(self, argv):
        # Call the constructor of TripsModule
        super(DTDA_Module, self).__init__(argv)
        self.tasks = ['IS-DRUG-TARGET', 'FIND-TARGET-DRUG',
                      'FIND-DISEASE-TARGETS', 'FIND-TREATMENT']
        # Send subscribe messages
        for task in self.tasks:
            msg_txt =\
                '(subscribe :content (request &key :content (%s . *)))' % task
            self.send(KQMLPerformative.from_string(msg_txt))
        # Instantiate a singleton DTDA agent
        self.dtda = DTDA()
        # Send ready message
        self.ready()
        super(DTDA_Module, self).start()

    def receive_request(self, msg, content):
        '''
        If a "request" message is received, decode the task and the content
        and call the appropriate function to prepare the response. A reply
        message is then sent back.
        '''
        content_list = content
        task_str = content_list[0].to_string().upper()
        if task_str == 'IS-DRUG-TARGET':
            reply_content = self.respond_is_drug_target(content_list)
        elif task_str == 'FIND-TARGET-DRUG':
            reply_content = self.respond_find_target_drug(content_list)
        elif task_str == 'FIND-DISEASE-TARGETS':
            reply_content = self.respond_find_disease_targets(content_list)
        elif task_str == 'FIND-TREATMENT':
            reply_content = self.respond_find_treatment(content_list)
            if reply_content is None:
                self.respond_dont_know(msg,
                                       '(ONT::A X1 :instance-of ONT::DRUG)')
                return
        else:
            self.error_reply(msg, 'unknown request task ' + task_str)
            return

        reply_msg = KQMLPerformative('reply')
        reply_msg.set_parameter(':content', reply_content)
        self.reply(msg, reply_msg)

    def respond_dont_know(self, msg, content_string):
        resp = '(ONT::TELL :content (ONT::DONT-KNOW :content %s))' %\
            content_string
        resp_list = KQMLList.from_string(resp)
        reply_msg = KQMLPerformative('reply')
        reply_msg.set_parameter(':content', resp_list)
        self.reply(msg, reply_msg)

    def respond_is_drug_target(self, content_list):
        '''
        Response content to is-drug-target request
        '''
        drug_arg = content_list.get_keyword_arg(':drug')
        drug = drug_arg[0].to_string()
        target_arg = content_list.get_keyword_arg(':target')
        target = self._get_target(target_arg)
        target_name = target.name
        reply_content = KQMLList()
        try:
            is_target = self.dtda.is_nominal_drug_target(drug, target_name)
        except DrugNotFoundException:
            reply_content.add('FAILURE :reason DRUG_NOT_FOUND')
            return reply_content
        status = 'SUCCESS'
        if is_target:
            is_target_str = 'TRUE'
        else:
            is_target_str = 'FALSE'
        msg_str = '%s :is-target %s' %\
                  (status, is_target_str)
        reply_content.add(msg_str)
        return reply_content

    def respond_find_target_drug(self, content_list):
        '''
        Response content to find-target-drug request
        '''
        target_arg = content_list.get_keyword_arg(':target')
        target = self._get_target(target_arg)
        target_name = target.name
        drug_names, chebi_ids = self.dtda.find_target_drugs(target_name)
        drug_list_str = ''
        for dn, ci in zip(drug_names, chebi_ids):
            if ci is None:
                drug_list_str += '(:name %s) ' % dn.encode('ascii', 'ignore')
            else:
                drug_list_str += '(:name %s :chebi_id %s) ' % (dn, ci)
        reply_content = KQMLList.from_string(
            '(SUCCESS :drugs (' + drug_list_str + '))')
        return reply_content

    def respond_find_disease_targets(self, content_list):
        '''
        Response content to find-disease-targets request
        '''
        disease_arg = content_list.get_keyword_arg(':disease')
        try:
            disease = self.get_disease(disease_arg)
        except Exception as e:
            logger.error(e)
            msg_str = '(FAILURE :reason INVALID_DISEASE)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        if disease.disease_type != 'cancer':
            msg_str = '(FAILURE :reason DISEASE_NOT_FOUND)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        logger.debug('Disease: %s' % disease.name)

        try:
            mut_protein, mut_percent =\
                self.dtda.get_top_mutation(disease.name)
        except DiseaseNotFoundException:
            msg_str = '(FAILURE :reason DISEASE_NOT_FOUND)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        # TODO: get functional effect from actual mutations
        # TODO: add list of actual mutations to response
        # TODO: get fraction not percentage from DTDA
        reply_content =\
            KQMLList.from_string(
                '(SUCCESS ' +
                ':protein (:name %s :hgnc %s) ' % (mut_protein, mut_protein) +
                ':prevalence %.2f ' % (mut_percent/100.0) +
                ':functional-effect ACTIVE)')

        return reply_content

    def respond_find_treatment(self, content_list):
        '''
        Response content to find-treatment request
        '''
        reply_content = KQMLList()
        #TODO: eliminate code duplication here
        disease_arg = content_list.get_keyword_arg(':disease')
        try:
            disease = self.get_disease(disease_arg)
        except Exception as e:
            logger.error(e)
            msg_str = '(FAILURE :reason INVALID_DISEASE)'
            reply_content = KQMLList.from_string(msg_str)
            return reply_content

        if disease.disease_type != 'cancer':
            reply_content.add('FAILURE :reason DISEASE_NOT_FOUND')
            return reply_content

        logger.debug('Disease: %s' % disease.name)

        try:
            mut_protein, mut_percent = \
                self.dtda.get_top_mutation(disease.name)
        except DiseaseNotFoundException:
            reply_content.add('FAILURE :reason DISEASE_NOT_FOUND')
            return reply_content

        # TODO: get functional effect from actual mutations
        # TODO: add list of actual mutations to response
        # TODO: get fraction not percentage from DTDA
        reply_content.add(KQMLList.from_string(
                '(SUCCESS ' +
                ':protein (:name %s :hgnc %s) ' % (mut_protein, mut_protein) +
                ':prevalence %.2f ' % (mut_percent/100.0) +
                ':functional-effect ACTIVE)'))

        # Try to find a drug
        drug_names, chebi_ids = self.dtda.find_target_drugs(mut_protein)
        drug_list_str = ''
        for dn, ci in zip(drug_names, chebi_ids):
            if ci is None:
                drug_list_str += '(:name %s) ' % dn.encode('ascii', 'ignore')
            else:
                drug_list_str += '(:name %s :chebi_id %s) ' % (dn, ci)
        reply_content.add(KQMLList.from_string(
            '(SUCCESS :drugs (' + drug_list_str + '))'))

        return reply_content

    def _get_target(self, target_arg):
        target_str = str(target_arg)
        target_str = self.decode_description('<ekb>' + target_str + '</ekb>')
        tp = TripsProcessor(target_str)
        terms = tp.tree.findall('TERM')
        term_id = terms[0].attrib['id']
        agent = tp._get_agent_by_id(term_id, None)
        return agent

    def get_disease(self, disease_arg):
        disease_str = str(disease_arg)
        disease_str = self.decode_description(disease_str)
        term = ET.fromstring(disease_str)
        disease_type = term.find('type').text
        if disease_type.startswith('ONT::'):
            disease_type = disease_type[5:].lower()
        drum_term = term.find('drum-terms/drum-term')
        dbname = drum_term.attrib['name']
        dbid = term.attrib['dbid']
        dbids = dbid.split('|')
        dbid_dict = {k: v for k, v in [d.split(':') for d in dbids]}
        disease = Disease(disease_type, dbname, dbid_dict)
        return disease

    @staticmethod
    def get_single_argument(arg):
        if arg is None:
            return None
        arg_str = arg.to_string()
        if arg_str[0] == '(' and arg_str[-1] == ')':
             arg_str = arg_str[1:-1]
        arg_str = arg_str.lower()
        return arg_str

    @staticmethod
    def decode_description(descr):
        if descr[0] == '"':
            descr = descr[1:]
        if descr[-1] == '"':
            descr = descr[:-1]
        descr = descr.replace('\\"', '"')
        return descr