@@ -11,7 +11,7 @@ def normalize_pattern(self):
1111 # and join them with a | character
1212 # and add them to the route_patterns array
1313 route_patterns .append (r'|' .join (p ))
14- pattern = re .compile (r'\b (?P<route>' + r'|' .join (route_patterns ) + r')\b ' , flags = re .I )
14+ pattern = re .compile (r'(?P<route>' + r'|' .join (route_patterns ) + r')' , flags = re .I )
1515 return pattern
1616 def normalize_match (self , match ):
1717 route = get_normalized (ROUTES , match .group ('route' ))
@@ -32,7 +32,7 @@ def normalize_pattern(self):
3232 # and join them with a | character
3333 # and add them to the route_patterns array
3434 route_patterns .append (r'|' .join (p ))
35- pattern = re .compile (r'\b (?P<route>' + r'|' .join (route_patterns ) + r')\b ' , flags = re .I )
35+ pattern = re .compile (r'(?P<route>' + r'|' .join (route_patterns ) + r')' , flags = re .I )
3636 return pattern
3737 def normalize_match (self , match ):
3838 route = get_normalized (INHALATION_ROUTES , match .group ('route' ))
@@ -51,7 +51,7 @@ def normalize_pattern(self):
5151 # and join them with a | character
5252 # and add them to the route_patterns array
5353 topical_route_patterns .append (r'|' .join (p ))
54- pattern = re .compile (r'\b (?P<route>' + r'|' .join (topical_route_patterns ) + r')(?!\s?pain)\b ' , flags = re .I )
54+ pattern = re .compile (r'(?P<route>' + r'|' .join (topical_route_patterns ) + r')(?!\s?pain)' , flags = re .I )
5555 return pattern
5656 def normalize_match (self , match ):
5757 route = get_normalized (TOPICAL_ROUTES , match .group ('route' ))
@@ -113,8 +113,9 @@ def parse(self, sig):
113113 self .matches = matches
114114 return matches
115115
116+
116117class InferredOralRouteParser (RouteParser ):
117- pattern = r'\b (?P<route>(?!vaginal|sublingual)tab(?:let)?(?:s)?(?!.*(?:sublingual(?:ly)?|into|per|on the|between the|under|by sublingual route|by buccal route))|cap(?:sule)?(?:s)?|chew(?:able)?|\dpo|capful|pill)\b '
118+ pattern = r'(?P<route>(?!vaginal|sublingual)tab(?:let)?(?:s)?(?!.*(?:sublingual(?:ly)?|into|per|on the|between the|under|by sublingual route|by buccal route))|cap(?:sule)?(?:s)?|chew(?:able)?|\dpo|capful|pill)'
118119 def normalize_pattern (self ):
119120 return re .compile (self .pattern , flags = re .I )
120121 def normalize_match (self , match ):
@@ -124,13 +125,48 @@ def normalize_match(self, match):
124125 route_readable = self .get_readable (route = route )
125126 return self .generate_match ({'route' : route , 'route_text_start' : route_text_start , 'route_text_end' : route_text_end , 'route_text' : route_text , 'route_readable' : route_readable })
126127
128+
129+ # infers inhalation route for things like 'puffs' in the absence of other more specific routes
130+ class InferredInhalationRouteParser (RouteParser ):
131+ pattern = r'puff(?:s)?(?! in each nostril)(?! in the nose)(?! each nostril)(?! in nostril)'
132+ def normalize_pattern (self ):
133+ return re .compile (self .pattern , flags = re .I )
134+ def normalize_match (self , match ):
135+ route = 'into the lungs'
136+ route_text_start , route_text_end = match .span ()
137+ route_text = match [0 ]
138+ route_readable = self .get_readable (route = route )
139+ return self .generate_match ({'route' : route , 'route_text_start' : route_text_start , 'route_text_end' : route_text_end , 'route_text' : route_text , 'route_readable' : route_readable })
140+
141+
142+ class MiscellaneousRouteParser (RouteParser ):
143+ def normalize_pattern (self ):
144+ dose_patterns = []
145+ for n , p in MISCELLANEOUS_ROUTES .items ():
146+ # add the name of the pattern to the list of matched patterns
147+ p .append (n )
148+ # and join them with a | character
149+ # and add them to the dose_patterns array
150+ dose_patterns .append (r'|' .join (p ))
151+ pattern = re .compile (r'(' + r'|' .join (dose_patterns ) + r')' , flags = re .I )
152+ return pattern
153+ def normalize_match (self , match ):
154+ route = 'miscellaneous'
155+ route_text_start , route_text_end = match .span ()
156+ route_text = match [0 ]
157+ route_readable = self .get_readable (route = route )
158+ return self .generate_match ({'route' : route , 'route_text_start' : route_text_start , 'route_text_end' : route_text_end , 'route_text' : route_text , 'route_readable' : route_readable })
159+
160+
127161# NOTE: moved InhalationRouteParser above RouteParser here so that "2 PUFFS BY MOUTH DAILY" resolved to "into the lungs" instead of "by mouth"...
128162# however, left it in different order above for class inheritance
129163parsers = [
130- # InhalationRouteParser(), # turned off for VUMC - TODO: need to create customer "settings"
164+ InhalationRouteParser (),
131165 RouteParser (),
132166 TopicalRouteParser (),
133- # InferredOralRouteParser()
167+ # InferredOralRouteParser(), # turned off for VUMC - TODO: need to create customer "settings"
168+ # InferredInhalationRouteParser(), # turned off for VUMC - TODO: need to create customer "settings"
169+ MiscellaneousRouteParser (),
134170]
135171
136172#print(RouteParser().parse('take one by mouth daily'))
0 commit comments