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)
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)
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)
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)
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
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)
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)
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)
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)
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
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)
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