def LF_relative(span): """Context includes any familial mention (e.g., mother father)""" left = get_left_span(span, span.sentence, window=6) right = get_right_span(span, span.sentence, window=6) left_trigger = match_regex(rgx_relatives, left) right_trigger = match_regex(rgx_relatives, right) return OTHER if left_trigger or right_trigger else PATIENT
def LF_definite_right_expanded(span): right = get_right_span(span, span.sentence, window=6) rgx = r'''\b(not present|no evidence|is (absent|not seen)|ruled out|were negative)\b''' trigger = match_regex(rgx, right) if trigger and token_distance(trigger, span) <= 1: return NEGATED return ABSTAIN
def LF_header(span): rgx = re.compile( r'^(admitting diagnosis|chief complaint|discharge diagnosis|past medical history|history of present illness|indication)[:]*', re.I) v = rgx.search(span.sentence.text.strip()) is not None right = get_right_span(span, window=1).text v |= right == ':' return NON_NEGATED if v else ABSTAIN
def LF_social(span): rgx_social = re.compile(r'''\b(friend(s)*|roomate(s)*|passenger(s)*)\b''', re.I) left = get_left_span(span, span.sentence, window=6) right = get_right_span(span, span.sentence, window=6) left_trigger = match_regex(rgx_social, left) right_trigger = match_regex(rgx_social, right) return OTHER if left_trigger or right_trigger else ABSTAIN
def LF_probable_left_4_6(span, negex): left = get_left_span(span, span.sentence, window=6) trigger = match_regex(negex.rgxs['probable']['left'], left) if not trigger: return ABSTAIN dist = token_distance(trigger, span) right = get_right_span(trigger, window=2) if pseudo_negation.search(right.text): return ABSTAIN return NEGATED if (dist >= 4 and dist <= 6) else ABSTAIN
def LF_right_context(span): text = get_right_span(span, span.sentence, window=6).text regxes = [ r'''((?<!no )(mild|minimal|severe|moderate|extensive|coarse|marked|extreme|significant|trivial|progressive|slight)(ly)*)''', # LF_severity_right r'''(was (found to have|impaired|relieved|stable)|is present|withdrawal|of the)''' # LF_present_now_right ] regxes = [re.compile(rgx, re.I) for rgx in regxes] for rgx in regxes: if rgx.search(text): return NON_NEGATED return ABSTAIN
def LF_definite_left_7_10(span, negex): left = get_left_span(span, span.sentence) trigger = match_regex(negex.rgxs['definite']['left'], left) if not trigger: return ABSTAIN dist = token_distance(trigger, span) right = get_right_span(trigger, window=2) if pseudo_negation.search(right.text): return ABSTAIN return NEGATED if (dist >= 7 and dist <= 10) else ABSTAIN
def LF_definite_left_list(span, negex): left = get_left_span(span, span.sentence, window=100) trigger = match_regex(negex.rgxs['definite']['left'], left) if not trigger: return ABSTAIN dist = token_distance(trigger, span) btw = get_between_span(trigger, span) right = get_right_span(trigger, window=2) if pseudo_negation_rgx.search(right.text): return ABSTAIN return NEGATED if dist <= 10 and btw and len(re.findall(r'''[,;]''', btw.text)) > 1 else ABSTAIN
def LF_pseudo_negation_exclusion(span): left_rgx = r'''(inadequate\s+to|does\s+not|cannot|can't)\s+exclude''' right_rgx = r'''(cannot\s+be|not\s+be|doesn't|not|to)\s+exclude[d]*''' left = get_left_span(span) trigger = match_regex(left_rgx, left) if trigger and token_distance(trigger, span) <= 3: return NON_NEGATED right = get_right_span(span) trigger = match_regex(right_rgx, right) if trigger and token_distance(trigger, span) <= 3: return NON_NEGATED return ABSTAIN
def _apply_lfs(self, span, sentence, ngrams): """ Apply NegEx labeling functions. TODO: Window size is fixed here, choices of 5-8 perform well """ left = get_left_span(span, sentence, window=ngrams) right = get_right_span(span, sentence, window=ngrams) L = [] for name in sorted(self.negex.rgxs): for cxt in sorted(self.negex.rgxs[name]): v = 0 text = left.text if cxt == 'left' else right.text if self.negex.rgxs[name][cxt].search(text): v = self.class_map[name] L.append(v) return np.array(L)
def negation(self, span, category, direction, window=3): """ Return any matched negex phrases :param span: :param category: :param direction: :param window: :return: """ rgx = self.rgxs[category][direction] if not rgx.pattern: return None cxt = get_left_span(span, window=window) if direction == 'left' \ else get_right_span(span, window=window) m = rgx.findall(cxt.text) return m if m else None
def LF_none(span): right_rgx = r'''\bnone\b''' right = get_right_span(span) trigger = match_regex(right_rgx, right) return NEGATED if trigger and token_distance(trigger, span) <= 2 else ABSTAIN
def LF_probable_right(span, negex): text = get_right_span(span, span.sentence, window=6).text rgx = negex.rgxs['probable']['right'] if pseudo_negation(span): return ABSTAIN return NEGATED if rgx.search(text) else ABSTAIN