예제 #1
0
 def test_factory_pm1(self):
     """Test that a ParsedMedication initialized with a parseable string 
     and a provenance yields the expected results."""
     provenance = "List 1"
     pm = medication.make_medication(self.original, provenance=provenance, mappings=mappings)
     self.assertTrue(isinstance(pm, medication.ParsedMedication))
     self.assertEqual(pm.original_string, self.original)
     self.assertEqual(pm.provenance, provenance)
예제 #2
0
 def test_factory_m2(self):
     """Test that a Medication initialized with an unparseable string and 
     without a provenance yields the expected results."""
     med_line = "James Beam (for medicinal purposes only)"
     provenance = ""
     m = medication.make_medication(med_line)
     self.assertTrue(isinstance(m, medication.Medication))
     self.assertEqual(m.original_string, med_line)
     self.assertEqual(m.provenance, provenance)
예제 #3
0
 def test_factory_m2(self):
     """Test that a Medication initialized with an unparseable string and 
     without a provenance yields the expected results."""
     med_line = "James Beam (for medicinal purposes only)"
     provenance = ""
     m = medication.make_medication(med_line)
     self.assertTrue(isinstance(m, medication.Medication))
     self.assertEqual(m.original_string, med_line)
     self.assertEqual(m.provenance, provenance)
예제 #4
0
 def test_factory_m1(self):
     """Test that a Medication initialized with an unparseable string and 
     a provenance yields the expected results."""
     med_line = "Take 2 aspirin and call me in the morning"
     provenance="List 2"
     m = medication.make_medication(med_line, provenance=provenance)
     self.assertTrue(isinstance(m, medication.Medication))
     self.assertEqual(m.original_string, med_line)
     self.assertEqual(m.provenance, provenance)
예제 #5
0
 def test_factory_m1(self):
     """Test that a Medication initialized with an unparseable string and 
     a provenance yields the expected results."""
     med_line = "Take 2 aspirin and call me in the morning"
     provenance = "List 2"
     m = medication.make_medication(med_line, provenance=provenance)
     self.assertTrue(isinstance(m, medication.Medication))
     self.assertEqual(m.original_string, med_line)
     self.assertEqual(m.provenance, provenance)
예제 #6
0
 def test_factory_pm1(self):
     """Test that a ParsedMedication initialized with a parseable string 
     and a provenance yields the expected results."""
     provenance = "List 1"
     pm = medication.make_medication(self.original,
                                     provenance=provenance,
                                     mappings=mappings)
     self.assertTrue(isinstance(pm, medication.ParsedMedication))
     self.assertEqual(pm.original_string, self.original)
     self.assertEqual(pm.provenance, provenance)
예제 #7
0
def reconciliation_setup(list1, list2, mappings, stats):
    print "********** BEFORE RECONCILIATION **********"
    print
    print "Original list 1=\n", '\n'.join(list1)
    print
    print "Original list 2=\n", '\n'.join(list2)
    print
    meds_list_1 = [make_medication(x, mappings, "List 1") for x in list1]
    meds_list_2 = [make_medication(x, mappings, "List 2") for x in list2]
    if stats is not None:
        stats['size_original_list_1'] = len(meds_list_1)
        stats['size_original_list_2'] = len(meds_list_2)
    # Remove empty meds (parsed blank lines)
    meds_list_1 = [x for x in meds_list_1 if not x.is_empty()]
    meds_list_2 = [x for x in meds_list_2 if not x.is_empty()]
    if stats is not None:
        stats['size_parsed_list_1'] = len(meds_list_1)
        stats['size_parsed_list_2'] = len(meds_list_2)
    print
    print "Parsed list 1=\n", '\n'.join(str(x) for x in meds_list_1)
    print
    print "Parsed list 2=\n", '\n'.join(str(x) for x in meds_list_2)
    return meds_list_1, meds_list_2, stats
예제 #8
0
파일: reconcile.py 프로젝트: nhsland/MedRec
def reconciliation_setup(list1, list2, mappings, stats):
    print "********** BEFORE RECONCILIATION **********"
    print
    print "Original list 1=\n", '\n'.join(list1)
    print
    print "Original list 2=\n", '\n'.join(list2)
    print
    meds_list_1 = [make_medication(x, mappings, "List 1") for x in list1]
    meds_list_2 = [make_medication(x, mappings, "List 2") for x in list2]
    if stats is not None:
        stats['size_original_list_1'] = len(meds_list_1)
        stats['size_original_list_2'] = len(meds_list_2)
    # Remove empty meds (parsed blank lines)
    meds_list_1 = [x for x in meds_list_1 if not x.is_empty()]
    meds_list_2 = [x for x in meds_list_2 if not x.is_empty()]
    if stats is not None:
        stats['size_parsed_list_1'] = len(meds_list_1)
        stats['size_parsed_list_2'] = len(meds_list_2)
    print
    print "Parsed list 1=\n", '\n'.join(str(x) for x in meds_list_1)
    print
    print "Parsed list 2=\n", '\n'.join(str(x) for x in meds_list_2)
    return meds_list_1, meds_list_2, stats
예제 #9
0
 def test_factory_pm2(self):
     """Test that a ParsedMedication initialized with a dictionary 
     and a provenance yields the expected results."""
     original = 'Protonix 40 MG Tablet Delayed Release; TAKE 1 TABLET DAILY.; Rx'
     dikt = dict(
         name=self.name,
         units=self.units,
         dose=self.dose,
         formulation=self.formulation,
         instructions=self.instructions,
         original_line = original,
     )
     provenance = "List 3"
     pm = medication.make_medication(dikt, provenance=provenance, mappings=mappings)
     self.assertTrue(isinstance(pm, medication.ParsedMedication))
     self.assertEqual(pm.original_string, original)
     self.assertEqual(pm.provenance, provenance)
예제 #10
0
 def test_factory_pm3(self):
     """Test that a ParsedMedication initialized with a dictionary 
     containing a provenance and with a provenance yields 
     the expected results."""
     dikt = dict(
         name=self.name,
         units=self.units,
         dose=self.dose,
         formulation=self.formulation,
         instructions=self.instructions,
         original_line=self.original
     )
     provenance = "List 3"
     pm = medication.make_medication(dikt, provenance=provenance, mappings=mappings)
     self.assertTrue(isinstance(pm, medication.ParsedMedication))
     self.assertEqual(pm.original_string, self.original)
     self.assertEqual(pm.provenance, provenance)
예제 #11
0
 def test_factory_pm3(self):
     """Test that a ParsedMedication initialized with a dictionary 
     containing a provenance and with a provenance yields 
     the expected results."""
     dikt = dict(name=self.name,
                 units=self.units,
                 dose=self.dose,
                 formulation=self.formulation,
                 instructions=self.instructions,
                 original_line=self.original)
     provenance = "List 3"
     pm = medication.make_medication(dikt,
                                     provenance=provenance,
                                     mappings=mappings)
     self.assertTrue(isinstance(pm, medication.ParsedMedication))
     self.assertEqual(pm.original_string, self.original)
     self.assertEqual(pm.provenance, provenance)
예제 #12
0
 def test_factory_pm2(self):
     """Test that a ParsedMedication initialized with a dictionary 
     and a provenance yields the expected results."""
     original = 'Protonix 40 MG Tablet Delayed Release; TAKE 1 TABLET DAILY.; Rx'
     dikt = dict(
         name=self.name,
         units=self.units,
         dose=self.dose,
         formulation=self.formulation,
         instructions=self.instructions,
         original_line=original,
     )
     provenance = "List 3"
     pm = medication.make_medication(dikt,
                                     provenance=provenance,
                                     mappings=mappings)
     self.assertTrue(isinstance(pm, medication.ParsedMedication))
     self.assertEqual(pm.original_string, original)
     self.assertEqual(pm.provenance, provenance)
예제 #13
0
    def GET(self):
        # Fetch and use
        try:
            smart_oauth_header = web.input().oauth_header
        except:
            smart_oauth_header = session.oauth_header
            del session.oauth_header

        smart_oauth_header = urllib.unquote(smart_oauth_header)
        client = get_smart_client(smart_oauth_header)
        oauth_data = base64.b64encode(bz2.compress(smart_oauth_header, 9))
        #client = get_smart_client(oauth_data)

        # Represent the list as an RDF graph
        med_lists = client.records_X_medication_lists_GET()

        lists_q = """
            PREFIX dcterms:<http://purl.org/dc/terms/>
            PREFIX sp:<http://smartplatforms.org/terms#>
            PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
            select ?l ?s ?sname ?d
            where {
                ?l a sp:MedicationList.
                ?l sp:medListSource ?s.
                ?s dcterms:title ?sname.

                optional { ?l dcterms:date ?d }

            }"""

        lists = med_lists.graph.query(lists_q)

        def one_list(list_uri):
            one_list_q = """
            PREFIX dcterms:<http://purl.org/dc/terms/>
            PREFIX sp:<http://smartplatforms.org/terms#>
            PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
               SELECT  ?med  ?name ?rxcui ?quant ?quantunit ?freq ?frequnit ?inst ?startdate ?prov
               WHERE {
                    <""" + list_uri + """> sp:medication ?med.
                      ?med rdf:type sp:Medication .
                      ?med sp:drugName ?medc.
                      ?medc dcterms:title ?name.
                      ?medc sp:code ?code.
                      ?code dcterms:identifier ?rxcui.
                      OPTIONAL {?med sp:instructions ?inst.}
                      OPTIONAL {
                      ?med sp:quantity ?quantx.
                      ?quantx sp:value ?quant.
                      ?quantx sp:unit ?quantunit. }
                      OPTIONAL {
                      ?med sp:frequency ?freqx.
                      ?freqx sp:value ?freq.
                      ?freqx sp:unit ?frequnit. }
                      OPTIONAL {?med sp:startDate ?startdate.}
		      OPTIONAL { ?med sp:provenance ?prov. }
                }
            """
            #print one_list_q
            return med_lists.graph.query(one_list_q)

        if len(lists) < 2:
            #print "I am lame, and therefore expect exactly two lists. Besides, with less than two, what do you expect me to reconcile?"
            web.header('Content-Type', 'text/html')
            return "<html><head></head><body>Nothing to reconcile. There were less than two lists.</body></html>"

        lists = [x for x in lists]
        my_app_ui = APP_UI
        my_app_params = []
        if len(lists) > 2:
            #print "*** WARNING *** There were %d lists. Looking for user-chosen lists." % len(lists)
            try:
                # Chosen_lists should contain URIs
                chosen_lists = session.chosen_lists
                if chosen_lists is None:
                    raise AttributeError
                session.chosen_lists = None

                # If we are here, it's because the user chose lists already
                my_app_params.append(NO_SUMMARY)
            except AttributeError:
                # No chosen lists; make the user choose.
                list_metadata = [
                    dict(URL=str(x[0].toPython()),
                         source=str(x[1].toPython()),
                         name=str(x[2].toPython()),
                         date=str(x[3].toPython()) if x[3] is not None else "")
                    for x in lists
                ]
                lists = [one_list(x['URL']) for x in list_metadata]
                list_info = []
                for i in range(len(lists)):
                    list_info.append({
                        'meta': list_metadata[i],
                        'meds': [str(x[1]) for x in lists[i]]
                    })
                session.json_data = json.dumps(list_info)
                session.oauth_header = web.input().oauth_header
                #print session.json_data
                #print >> sys.stderr, "Session contents:", session.keys()
                raise web.seeother(LIST_CHOOSER)
        else:
            chosen_lists = (lists[0][0], lists[1][0])

        rdf_list_1 = one_list(chosen_lists[0])
        rdf_list_2 = one_list(chosen_lists[1])
        # print "LISTS", lists
        #         print "List 1:", len(rdf_list_1), "items"
        #         for x in rdf_list_1:
        #             print "Med=", x[0]
        #             print "Name=", x[1]
        #             print "RxCUI=", x[2]
        #             print "quant=", x[3]
        #             print "quantunit=", x[4]
        #             print "freq=", x[5]
        #             print "frequnit=", x[6]
        #             print "inst=", x[7]
        #             print "startdate=", x[8]
        #             print "provenance=", x[9]
        #             print

        # Find the last fulfillment date for each medication
        #self.last_pill_dates = {}
        #for pill in pills:
        #    self.update_pill_dates(pill)

        FREQ_UNITS = {
            'd': ['days', 'daily'],
            'wk': ['weeks', 'weekly'],
            'mo': ['months', 'monthly'],
            'hr': ['hours', 'hourly'],
            'min': ['minutes', 'every minute']
        }

        def make_med_from_rdf(rdf_results):
            drugName = str(rdf_results[1].toPython())
            rxCUI = str(rdf_results[2].toPython()
                        ) if rdf_results[2] is not None else None
            quantity = rdf_results[3].toPython(
            ) if rdf_results[3] is not None else "No quantity"
            quantity_unit = str(rdf_results[4].toPython(
            )) if rdf_results[4] is not None else "No quantity units"
            quantity_unit = get_unit_name(quantity_unit)
            frequency = rdf_results[5].toPython(
            ) if rdf_results[5] is not None else "No frequency"
            # TODO: Finish the rest of the conversion.
            freq_unit_uri = rdf_results[6]
            frequency_unit = "No frequency unit"

            if freq_unit_uri:
                (freqc,
                 frequ) = re.match("\/\(?(?:(\d*)\.)?(d|mo|min|hr|wk)?\)?",
                                   freq_unit_uri.toPython()).groups()
                try:
                    u = FREQ_UNITS[frequ]
                    frequency_unit = u[1]
                    if freqc:
                        freqc = int(freqc)
                        if freqc > 1:
                            frequency_unit = "per %s %s" % (freqc, frequ)

                except KeyError, ValueError:
                    print >> sys.stderr, "Could not parse", freq_unit_uri
                    pass
                    #print frequency_unit

            inst = str(rdf_results[7].toPython()
                       ) if rdf_results[7] else "No instructions"
            startdate = rdf_results[8].toPython(
            ) if rdf_results[8] else "No startdate"
            provenance = rdf_results[9].toPython(
            ) if rdf_results[9] is not None else ""
            med_dict = {
                'name': drugName,
                'rxCUI': rxCUI,
                'units': quantity_unit,
                'dose': quantity,
                'instructions': inst,
                'formulation': quantity_unit
            }
            #print med_dict

            if med_dict['rxCUI'] in mc._rxnorm.code_cui:
                med_dict['cuis'] = set(
                    [mc._rxnorm.code_cui[med_dict['rxCUI']]])
                #print "The CUI for", med_dict['rxCUI'], "is", med_dict['cuis']
            med = make_medication(med_dict, mc, provenance)
            return med
예제 #14
0
class TestFunctions(unittest.TestCase):
    """A set of unit tests to exercise the functions in the 'match' module. 
    """
    medString1 = 'Lisinopril 5 MG Tablet;TAKE  TABLET TWICE DAILY; Rx'
    pMed1 = ParsedMedication(medString1, mappings)
    pMed1CUIs = set(['C0065374'])
    pMed1Tradenames = [
        'C0591228', 'C0591229', 'C0678140', 'C0701176', 'C0722805', 'C1602677',
        'C2368718', 'C2368722', 'C2368725'
    ]
    medString2 = 'Pramipexole 0.5 MG Tablet;TAKE 1 TABLET 3 TIMES DAILY.; Rx'
    pMed2 = ParsedMedication(medString2, mappings)
    pMed2CUIs = set(['C0074710'])
    pMed2Tradenames = ['C0721754']
    medString2a = 'PRAMIPEXOLE 0.5 MG TABLET;take 1 tablet 3 times daily.; rx'
    pMed2a = ParsedMedication(medString2a, mappings)
    pMed2aCUIs = set(['C0074710'])
    pMed2aTradenames = ['C0721754']
    medString2b = 'Mirapex 0.5 MG Tablet;TAKE 1 TABLET 3 TIMES DAILY.; Rx'
    pMed2b = ParsedMedication(medString2b, mappings)
    pMed2bCUIs = set(['C0721754'])
    pMed2bTradenames = []
    medString3 = 'Warfarin Sodium 2.5 MG Tablet;TAKE AS DIRECTED.; Rx'
    pMed3 = ParsedMedication(medString3, mappings)
    pMed3CUIs = set(['C0376218'])
    pMed3Tradenames = []
    medString4 = 'Protonix 40 MG Tablet Delayed Release;TAKE 1 TABLET DAILY.; Rx'
    pMed4 = ParsedMedication(medString4, mappings)
    medString5 = 'Pantoprazole Sodium 40 MG Tablet Delayed Release;TAKE 1 TABLET DAILY.; Rx'
    pMed5 = ParsedMedication(medString5, mappings)
    medString6 = 'Paroxetine 20 MG Tablet; TAKE 1 TABLET DAILY.; Rx'
    pMed6 = ParsedMedication(medString6, mappings)
    medString7 = 'Sertraline 50 MG Tablet;TAKE 1 TABLET BY MOUTH EVERY DAY; Rx'
    pMed7 = ParsedMedication(medString7, mappings)
    medString8 = 'Razadyne 16 MG Capsule Extended Release 24 Hour;TAKE 1 CAPSULE DAILY IN THE MORNING take with meal daily; Rx.'
    pMed8 = ParsedMedication(medString8, mappings)
    medString9 = 'Cyclandelate 16 MG Capsule Extended Release 24 Hour;TAKE 1 CAPSULE DAILY IN THE MORNING take with meal daily; Rx.'
    pMed9 = ParsedMedication(medString9, mappings)
    medString10 = 'docosahexaenoic acid 200 mg capsules; one cap BID'
    pMed10 = ParsedMedication(medString10, mappings)
    medString11 = 'Exelon 4.6 MG/24HR Transdermal Patch 24 Hour;APPLY 1 PATCH DAILY AS DIRECTED.; Rx'
    pMed11 = ParsedMedication(medString11, mappings)
    list1 = [pMed1, pMed2]
    list1rev = [pMed2, pMed1]
    list2 = [pMed2a, pMed3]
    list2rev = [pMed3, pMed2a]
    list3 = [pMed2b, pMed3]
    list3rev = [pMed3, pMed2b]
    medication_list_test_CUIs = [
        pMed1CUIs, pMed2CUIs, pMed2aCUIs, pMed3CUIs, pMed2bCUIs, pMed3CUIs
    ]
    medication_list_test_tradenames = [
        pMed1Tradenames, pMed2Tradenames, pMed2aTradenames, pMed3Tradenames,
        pMed2bTradenames, pMed3Tradenames
    ]
    test_objects = None
    if test_match_objects:
        test_objects = test_match_objects['TestFunctions']
    matched_by_strings = match.match_by_strings(list1, list2)
    matched_by_strings_rev = match.match_by_strings(list1rev, list2rev)
    if mappings:
        matched_by_brand_name1 = match.match_by_brand_name(list1, list3)
        matched_by_brand_name1_rev = match.match_by_brand_name(
            list1rev, list3rev)
        matched_by_brand_name2 = match.match_by_brand_name(list3, list1)
        matched_by_ingredients_above = match.match_by_ingredients(
            [pMed4], [pMed5], min_match_threshold=0.6)
        matched_by_ingredients_below = match.match_by_ingredients(
            [pMed4], [pMed5], min_match_threshold=0.7)
        matched_by_ingredients_rev_above = match.match_by_ingredients(
            [pMed5], [pMed4], min_match_threshold=0.6)
        matched_by_ingredients_rev_below = match.match_by_ingredients(
            [pMed5], [pMed4], min_match_threshold=0.7)
        if mappings.treatment:
            matched_by_treatment_above = match.match_by_treatment(
                [pMed6], [pMed7], mappings, match_acceptance_threshold=0.3)
            matched_by_treatment_below = match.match_by_treatment([pMed6],
                                                                  [pMed7],
                                                                  mappings)
            matched_by_treatment_05_yes = match.match_by_treatment(
                [pMed8], [pMed9], mappings, match_acceptance_threshold=0.5)
            matched_by_treatment_05_no = match.match_by_treatment(
                [pMed8], [pMed9], mappings, match_acceptance_threshold=0.51)
            matched_by_treatment_04_yes = match.match_by_treatment(
                [pMed10], [pMed11], mappings, match_acceptance_threshold=0.4)
            matched_by_treatment_04_no = match.match_by_treatment(
                [pMed10], [pMed11], mappings, match_acceptance_threshold=0.43)
    # Use the demo lists for testing; this code was previously  in TestMatchResult
    demo_list_1 = [
        pm for pm in [
            make_medication(x, mappings, "List 1")
            for x in constants.demo_list_1
        ] if isinstance(pm, ParsedMedication)
    ]
    demo_list_2 = [
        pm for pm in [
            make_medication(x, mappings, "List 2")
            for x in constants.demo_list_2
        ] if isinstance(pm, ParsedMedication)
    ]
    demo_matched_by_strings = match.match_by_strings(demo_list_1, demo_list_2)
    demo_matched_by_strings_rev = match.match_by_strings(
        demo_list_2, demo_list_1)
    if mappings:
        demo_matched_by_brand_name = match.match_by_brand_name(
            demo_list_1, demo_list_2)
        demo_matched_by_brand_name_rev = match.match_by_brand_name(
            demo_list_2, demo_list_1)
        demo_matched_by_ingredients = match.match_by_ingredients(
            demo_list_1, demo_list_2)
        demo_matched_by_ingredients_rev = match.match_by_ingredients(
            demo_list_2, demo_list_1)

    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_strings(self):
        "Test that the MatchResult from a by-string match contains the lists we expect."
        self.assertEqual(self.matched_by_strings,
                         self.test_objects['matched_by_strings'])

    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_strings_rev(self):
        """Test that the MatchResult from a by-string match is order-independent
        with respect to the order the medication lists are passed in."""
        self.assertEqual(self.matched_by_strings_rev,
                         self.test_objects['matched_by_strings_rev'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    def test_medication_list_CUIs(self):
        "Test the operation of match.medication_list_CUIs()"
        cuis = match.medication_list_CUIs(self.list1 + self.list2 + self.list3)
        self.assertEqual(cuis, self.medication_list_test_CUIs)

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_medication_list_tradenames(self):
        "Test the operation of match.medication_list_tradenames()"
        tradenames = match.medication_list_tradenames(self.list1 + self.list2 +
                                                      self.list3)
        self.assertEqual(tradenames, self.medication_list_test_tradenames)

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_brand_name1(self):
        """Test that the MatchResult from a by-brand-name match contains the 
        lists we expect."""
        self.assertEqual(self.matched_by_brand_name1,
                         self.test_objects['matched_by_brand_name1'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_brand_name1_rev(self):
        """Test that the MatchResult from a by-brand-name match is order-independent
        with respect to the order the medication lists are passed in."""
        self.assertEqual(self.matched_by_brand_name1_rev,
                         self.test_objects['matched_by_brand_name1_rev'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_brand_name2(self):
        """Test that the MatchResult from a by-brand-name match contains the
        lists we expect."""
        self.assertEqual(self.matched_by_brand_name2,
                         self.test_objects['matched_by_brand_name2'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_ingredients_above(self):
        """Test reconcilation of medications by treatment intent that should
        match at a threshold of 0.6."""
        self.assertEqual(self.matched_by_ingredients_above,
                         self.test_objects['matched_by_ingredients_above'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_ingredients_below(self):
        """Test reconcilation of medications by treatment intent that should
        not match at a threshold of 0.7."""
        self.assertEqual(self.matched_by_ingredients_below,
                         self.test_objects['matched_by_ingredients_below'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_ingredients_rev_above(self):
        """Test order independence of the reconcilation of medications by 
        treatment intent that should match at a threshold of 0.6."""
        self.assertEqual(self.matched_by_ingredients_rev_above,
                         self.test_objects['matched_by_ingredients_rev_above'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_match_by_ingredients_rev_below(self):
        """Test order independence of the reconcilation of medications by 
        treatment intent that should not match at a threshold of 0.7."""
        self.assertEqual(self.matched_by_ingredients_rev_below,
                         self.test_objects['matched_by_ingredients_rev_below'])

    @unittest.skipUnless(test_objects, 'missing test_objects data')
    def test_demo_match_by_strings(self):
        """Use demo lists to test matching by strings."""
        self.assertEqual(self.demo_matched_by_strings,
                         self.test_objects['demo_matched_by_strings'])

    @unittest.skipUnless(test_objects, 'missing test_objects data')
    def test_demo_match_by_strings_rev(self):
        """Use demo lists to test order independence of matching by strings."""
        self.assertEqual(self.demo_matched_by_strings_rev,
                         self.test_objects['demo_matched_by_strings_rev'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(mappings and test_objects,
                         'missing MappingContext with RXNORM data')
    def test_demo_match_by_brand_name(self):
        """Use demo lists to test matching by brand names."""
        self.assertEqual(self.demo_matched_by_brand_name,
                         self.test_objects['demo_matched_by_brand_name'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(mappings and test_objects,
                         'missing MappingContext with RXNORM data')
    def test_demo_match_by_brand_name_rev(self):
        """Use demo lists to test order independence of matching by brand names."""
        self.assertEqual(self.demo_matched_by_brand_name_rev,
                         self.test_objects['demo_matched_by_brand_name_rev'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(mappings and test_objects,
                         'missing MappingContext with RXNORM data')
    def test_demo_match_by_ingredients_list(self):
        """Use demo lists to test matching by ingredients."""
        self.assertEqual(self.demo_matched_by_ingredients,
                         self.test_objects['demo_matched_by_ingredients'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(test_objects, 'missing test_match data')
    def test_demo_match_by_ingredients_list_rev(self):
        """Use demo lists to test order independence of matching by ingredients."""
        self.assertEqual(self.demo_matched_by_ingredients_rev,
                         self.test_objects['demo_matched_by_ingredients_rev'])

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(mappings and mappings.treatment,
                         'MappingContext lacks treatment data')
    def test_match_by_treatment_above(self):
        """These two medications should match by treatment if the 
        match_acceptance_threshold is set to 0.3; note that this
        behavior may change as the underlying 'treats' data change."""
        self.assertEqual(len(self.matched_by_treatment_above.reconciled), 1)

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(mappings and mappings.treatment,
                         'MappingContext lacks treatment data')
    def test_match_by_treatment_below(self):
        """These two medications should not match by treatment if the
        match_acceptance_threshold is set to default (0.5); note that this
        behavior may change as the underlying 'treats' data change."""
        self.assertEqual(len(self.matched_by_treatment_below.reconciled), 0)

    @unittest.skipUnless(mappings, 'missing MappingContext with RXNORM data')
    @unittest.skipUnless(mappings and mappings.treatment,
                         'MappingContext lacks treatment data')
    def test_match_by_treatment_varies(self):
        """Test matching by treatment intent, varying thresholds to induce
        matches and non-matches on the same two sets of medication lists.
        """
        self.assertEqual(len(self.matched_by_treatment_05_yes.reconciled), 1)
        self.assertEqual(len(self.matched_by_treatment_05_no.reconciled), 0)
        self.assertEqual(len(self.matched_by_treatment_04_yes.reconciled), 1)
        self.assertEqual(len(self.matched_by_treatment_04_no.reconciled), 0)
예제 #15
0
    def GET(self):
        # Fetch and use
        try:
            smart_oauth_header = web.input().oauth_header
        except:
            smart_oauth_header = session.oauth_header
            del session.oauth_header

        smart_oauth_header = urllib.unquote(smart_oauth_header)
        client = get_smart_client(smart_oauth_header)
        oauth_data = base64.b64encode(bz2.compress(smart_oauth_header, 9))
        #client = get_smart_client(oauth_data)

        # Represent the list as an RDF graph
        med_lists = client.records_X_medication_lists_GET()

        lists_q = """
            PREFIX dcterms:<http://purl.org/dc/terms/>
            PREFIX sp:<http://smartplatforms.org/terms#>
            PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
            select ?l ?s ?sname ?d
            where {
                ?l a sp:MedicationList.
                ?l sp:medListSource ?s.
                ?s dcterms:title ?sname.

                optional { ?l dcterms:date ?d }

            }"""

        lists = med_lists.graph.query(lists_q)

        def one_list(list_uri):
            one_list_q = """
            PREFIX dcterms:<http://purl.org/dc/terms/>
            PREFIX sp:<http://smartplatforms.org/terms#>
            PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
               SELECT  ?med  ?name ?rxcui ?quant ?quantunit ?freq ?frequnit ?inst ?startdate ?prov
               WHERE {
                    <""" + list_uri + """> sp:medication ?med.
                      ?med rdf:type sp:Medication .
                      ?med sp:drugName ?medc.
                      ?medc dcterms:title ?name.
                      ?medc sp:code ?code.
                      ?code dcterms:identifier ?rxcui.
                      OPTIONAL {?med sp:instructions ?inst.}
                      OPTIONAL {
                      ?med sp:quantity ?quantx.
                      ?quantx sp:value ?quant.
                      ?quantx sp:unit ?quantunit. }
                      OPTIONAL {
                      ?med sp:frequency ?freqx.
                      ?freqx sp:value ?freq.
                      ?freqx sp:unit ?frequnit. }
                      OPTIONAL {?med sp:startDate ?startdate.}
		      OPTIONAL { ?med sp:provenance ?prov. }
                }
            """
            #print one_list_q
            return med_lists.graph.query(one_list_q)

        if len(lists) < 2:
            #print "I am lame, and therefore expect exactly two lists. Besides, with less than two, what do you expect me to reconcile?"
            web.header('Content-Type', 'text/html')
            return "<html><head></head><body>Nothing to reconcile. There were less than two lists.</body></html>"

        lists = [x for x in lists]
        my_app_ui = APP_UI
        my_app_params = []
        if len(lists) > 2:
            #print "*** WARNING *** There were %d lists. Looking for user-chosen lists." % len(lists)
            try:
                # Chosen_lists should contain URIs
                chosen_lists = session.chosen_lists
                if chosen_lists is None:
                    raise AttributeError
                session.chosen_lists = None

                # If we are here, it's because the user chose lists already
                my_app_params.append(NO_SUMMARY)
            except AttributeError:
                # No chosen lists; make the user choose.
                list_metadata = [dict(
                    URL=str(x[0].toPython()),
                    source=str(x[1].toPython()),
                    name=str(x[2].toPython()),
                    date=str(x[3].toPython()) if x[3] is not None else "") for x in lists]
                lists = [one_list(x['URL']) for x in list_metadata]
                list_info = []
                for i in range(len(lists)):
                    list_info.append({'meta': list_metadata[i], 'meds': [str(x[1]) for x in lists[i]]})
                session.json_data = json.dumps(list_info)
                session.oauth_header = web.input().oauth_header
                #print session.json_data
                #print >> sys.stderr, "Session contents:", session.keys()
                raise web.seeother(LIST_CHOOSER)
        else:
            chosen_lists = (lists[0][0], lists[1][0])

        rdf_list_1 = one_list(chosen_lists[0])
        rdf_list_2 = one_list(chosen_lists[1])
        # print "LISTS", lists
        #         print "List 1:", len(rdf_list_1), "items"
        #         for x in rdf_list_1:
        #             print "Med=", x[0]
        #             print "Name=", x[1]
        #             print "RxCUI=", x[2]
        #             print "quant=", x[3]
        #             print "quantunit=", x[4]
        #             print "freq=", x[5]
        #             print "frequnit=", x[6]
        #             print "inst=", x[7]
        #             print "startdate=", x[8]
        #             print "provenance=", x[9]
        #             print

        # Find the last fulfillment date for each medication
        #self.last_pill_dates = {}
        #for pill in pills:
        #    self.update_pill_dates(pill)

        FREQ_UNITS = {
            'd': ['days', 'daily'],
            'wk': ['weeks', 'weekly'],
            'mo': ['months', 'monthly'],
            'hr': ['hours', 'hourly'],
            'min': ['minutes', 'every minute']
        }

        def make_med_from_rdf(rdf_results):
            drugName = str(rdf_results[1].toPython())
            rxCUI = str(rdf_results[2].toPython()) if rdf_results[2] is not None else None
            quantity = rdf_results[3].toPython() if rdf_results[3] is not None else "No quantity"
            quantity_unit = str(rdf_results[4].toPython()) if rdf_results[4] is not None else "No quantity units"
            quantity_unit = get_unit_name(quantity_unit)
            frequency = rdf_results[5].toPython() if rdf_results[5] is not None else "No frequency"
            # TODO: Finish the rest of the conversion.
            freq_unit_uri = rdf_results[6]
            frequency_unit = "No frequency unit"

            if freq_unit_uri:
                (freqc, frequ) = re.match("\/\(?(?:(\d*)\.)?(d|mo|min|hr|wk)?\)?", freq_unit_uri.toPython()).groups()
                try:
                    u = FREQ_UNITS[frequ]
                    frequency_unit = u[1]
                    if freqc:
                        freqc = int(freqc)
                        if freqc > 1:
                            frequency_unit = "per %s %s" % (freqc, frequ)

                except KeyError, ValueError:
                    print >> sys.stderr, "Could not parse", freq_unit_uri
                    pass
                    #print frequency_unit

            inst = str(rdf_results[7].toPython()) if rdf_results[7] else "No instructions"
            startdate = rdf_results[8].toPython() if rdf_results[8] else "No startdate"
            provenance = rdf_results[9].toPython() if rdf_results[9] is not None else ""
            med_dict = {'name': drugName,
                        'rxCUI': rxCUI,
                        'units': quantity_unit,
                        'dose': quantity,
                        'instructions': inst,
                        'formulation': quantity_unit
            }
            #print med_dict

            if med_dict['rxCUI'] in mc._rxnorm.code_cui:
                med_dict['cuis'] = set([mc._rxnorm.code_cui[med_dict['rxCUI']]])
                #print "The CUI for", med_dict['rxCUI'], "is", med_dict['cuis']
            med = make_medication(med_dict, mc, provenance)
            return med