Exemplo n.º 1
0
 def test_limit_scope3(self):
     """Test that two modifiers of the same type limit the scope of the first modifier."""
     doc = nlp("no evidence of CHF, neg for pneumonia")
     rule = ConTextRule("no evidence of", "DEFINITE_NEGATED_EXISTENCE",
                        "FORWARD")
     rule2 = ConTextRule("neg for", "DEFINITE_NEGATED_EXISTENCE", "FORWARD")
     modifier = ConTextModifier(rule, 0, 3, doc)
     modifier2 = ConTextModifier(rule2, 5, 7, doc)
     assert modifier.limit_scope(modifier2)
Exemplo n.º 2
0
 def test_from_dict_error(self):
     d = dict(
         literal="reason for examination",
         category="INDICATION",
         direction="FORWARD",
         invalid="this is an invalid key",
     )
     with pytest.raises(ValueError):
         ConTextRule.from_dict(d)
Exemplo n.º 3
0
    def test_terminate_limit_scope_backward(self):
        """Test that a 'TERMINATE' modifier will limit the scope of a 'BACKWARD' modifier.
        """
        doc = nlp("Pt has chf but pneumonia is ruled out")
        rule = ConTextRule("is ruled out", "NEGATED_EXISTENCE", "BACKWARD")
        modifier = ConTextModifier(rule, 6, 8, doc)

        rule2 = ConTextRule("but", "TERMINATE", "TERMINATE")
        modifier2 = ConTextModifier(rule2, 3, 4, doc)
        assert modifier.limit_scope(modifier2)
Exemplo n.º 4
0
    def test_terminate_stops_forward_modifier(self):
        context = ConTextComponent(nlp, rules=None)

        rule = ConTextRule("no evidence of", "NEGATED_EXISTENCE", "FORWARD")
        rule2 = ConTextRule("but", "TERMINATE", "TERMINATE")
        context.add([rule, rule2])
        doc = nlp("No evidence of chf but she has pneumonia.")
        doc.ents = (Span(doc, 3, 4, "PROBLEM"), Span(doc, 7, 8, "PROBLEM"))
        context(doc)
        chf, pneumonia = doc.ents
        assert len(chf._.modifiers) > 0
        assert len(pneumonia._.modifiers) == 0
Exemplo n.º 5
0
    def test_terminate_stops_backward_modifier(self):
        context = ConTextComponent(nlp, rules=None)

        rule = ConTextRule("is ruled out", "NEGATED_EXISTENCE", "BACKWARD")
        rule2 = ConTextRule("but", "CONJ", "TERMINATE")
        context.add([rule, rule2])
        doc = nlp("Pt has chf but pneumonia is ruled out")
        doc.ents = (Span(doc, 2, 3, "PROBLEM"), Span(doc, 4, 5, "PROBLEM"))
        context(doc)
        chf, pneumonia = doc.ents
        assert len(chf._.modifiers) == 0
        assert len(pneumonia._.modifiers) > 0
Exemplo n.º 6
0
    def test_prune_false(self):
        rules = [
            ConTextRule("history of", "HISTORICAL", direction="FORWARD"),
            ConTextRule("no history of",
                        "NEGATED_EXISTENCE",
                        direction="FORWARD"),
        ]
        context = ConTextComponent(nlp, rules=None, prune=False)
        context.add(rules)

        doc = nlp("No history of afib.")
        context(doc)

        assert len(doc._.context_graph.modifiers) == 2
Exemplo n.º 7
0
 def test_terminate_limit_scope_custom2(self):
     """Test that a modifier will be explicitly terminated by a modifier with a category
     in terminated_by."""
     doc = nlp("flu is negative, pneumonia is positive.")
     rule = ConTextRule("negative",
                        "NEGATED_EXISTENCE",
                        direction="BACKWARD")
     rule2 = ConTextRule("positive",
                         "POSITIVE_EXISTENCE",
                         direction="BACKWARD",
                         terminated_by={"NEGATED_EXISTENCE"})
     modifier = ConTextModifier(rule, 2, 3, doc)
     modifier2 = ConTextModifier(rule2, 6, 7, doc)
     assert modifier2.limit_scope(modifier)
Exemplo n.º 8
0
 def test_terminate_limit_scope_custom(self):
     """Test that a modifier will be explicitly terminated by a modifier with a category
     in terminated_by."""
     doc = nlp("negative for flu, positive for pneumonia.")
     rule = ConTextRule("negative for",
                        "NEGATED_EXISTENCE",
                        direction="FORWARD",
                        terminated_by={"POSITIVE_EXISTENCE"})
     rule2 = ConTextRule("positive for",
                         "POSITIVE_EXISTENCE",
                         direction="FORWARD")
     modifier = ConTextModifier(rule, 0, 2, doc)
     modifier2 = ConTextModifier(rule2, 4, 6, doc)
     assert modifier.limit_scope(modifier2)
Exemplo n.º 9
0
def load():
    import medspacy
    nlp = medspacy.load(enable=["sentencizer", "tokenizer"])

    # Add components
    from medspacy.target_matcher import TargetMatcher, TargetRule
    target_matcher = TargetMatcher(nlp)
    target_filepath = path.join(RESOURCES_DIR, "target_rules.json")
    target_rules = TargetRule.from_json(target_filepath)
    target_matcher.add(target_rules)
    nlp.add_pipe(target_matcher)

    from medspacy.context import ConTextComponent, ConTextRule
    context_filepath = path.join(RESOURCES_DIR, "context_rules.json")
    context = ConTextComponent(nlp, rules=None, add_attrs=CONTEXT_ATTRS)
    context_rules = ConTextRule.from_json(context_filepath)
    context.add(context_rules)
    nlp.add_pipe(context)

    from medspacy.section_detection import Sectionizer
    # TODO: Add radiology section rules
    sectionizer = Sectionizer(nlp)
    nlp.add_pipe(sectionizer)

    clf = DocumentClassifier(nlp)
    nlp.add_pipe(clf)

    return nlp
Exemplo n.º 10
0
 def test_metadata(self):
     literal = "no evidence of"
     category = "definite_negated_existence"
     rule = "forward"
     meta = {"comment": "This is a comment."}
     item = ConTextRule(literal, category, rule, metadata=meta)
     assert item.metadata
Exemplo n.º 11
0
 def test_rule_value_error(self):
     """Test that ConTextRule raises a ValueError if an invalid direction is passed in."""
     literal = "no evidence of"
     category = "definite_negated_existence"
     rule = "asdf"
     with pytest.raises(ValueError):
         ConTextRule(literal, category, rule)
Exemplo n.º 12
0
 def test_context_item_rule_upper(self):
     """Test that a ConTextRule direction is always upper"""
     literal = "no evidence of"
     category = "definite_negated_existence"
     rule = "forward"
     item = ConTextRule(literal, category, rule)
     assert item.direction == "FORWARD"
Exemplo n.º 13
0
 def test_context_item_category_upper(self):
     """Test that a ConTextRule category is always upper"""
     literal = "no evidence of"
     category = "definite_negated_existence"
     rule = "forward"
     item = ConTextRule(literal, category, rule)
     assert item.category == "DEFINITE_NEGATED_EXISTENCE"
Exemplo n.º 14
0
    def test_custom_terminate_stops_forward_modifier(self):
        doc = nlp("negative for flu, positive for pneumonia.")
        context = ConTextComponent(nlp, rules=None)

        rule = ConTextRule("negative for",
                           "NEGATED_EXISTENCE",
                           direction="FORWARD",
                           terminated_by={"POSITIVE_EXISTENCE"})
        rule2 = ConTextRule("positive for",
                            "POSITIVE_EXISTENCE",
                            direction="FORWARD")
        context.add([rule, rule2])
        doc.ents = (Span(doc, 2, 3, "PROBLEM"), Span(doc, 6, 7))
        flu, pneumonia = doc.ents
        context(doc)
        assert len(flu._.modifiers) == 1
        assert len(pneumonia._.modifiers) == 1
 def test_rule_modifier_termination(self):
     context = ConTextComponent(nlp, rules=None, terminations=None)
     rule = ConTextRule("no evidence of",
                        "NEGATED_EXISTENCE",
                        "FORWARD",
                        terminated_by={"POSITIVE_EXISTENCE", "UNCERTAIN"})
     context.add([rule])
     assert rule.terminated_by == {"POSITIVE_EXISTENCE", "UNCERTAIN"}
 def test_null_modifier_termination(self):
     context = ConTextComponent(nlp, rules=None, terminations=None)
     rule = ConTextRule("no evidence of",
                        "NEGATED_EXISTENCE",
                        "FORWARD",
                        terminated_by=None)
     context.add([rule])
     assert rule.terminated_by == set()
Exemplo n.º 17
0
 def create_objects(self):
     doc = nlp(
         "family history of breast cancer but no diabetes. She has afib.")
     rule = ConTextRule("family history of",
                        "FAMILY_HISTORY",
                        direction="FORWARD")
     modifier = ConTextModifier(rule, 0, 3, doc)
     return doc, rule, modifier
    def test_is_historical(self):
        doc = nlp("History of pneumonia.")
        context = ConTextComponent(nlp, add_attrs=True, rules=None)
        rules = [ConTextRule("history of", "HISTORICAL", direction="forward")]
        context.add(rules)
        doc.ents = (doc[-2:-1], )
        context(doc)

        assert doc.ents[0]._.is_historical is True
    def test_pseudo_modifier(self):
        rules = [
            ConTextRule("negative", "NEGATED_EXISTENCE"),
            ConTextRule("negative attitude",
                        "PSEUDO_NEGATED_EXISTENCE",
                        direction="PSEUDO"),
        ]
        context = ConTextComponent(nlp, rules=None)
        context.add(rules)

        doc = nlp("She has a negative attitude about her treatment.")
        doc.ents = (doc[-2:-1], )
        context(doc)

        assert len(doc.ents[0]._.modifiers) == 0
        assert len(doc._.context_graph.modifiers) == 1
        assert doc._.context_graph.modifiers[
            0].category == "PSEUDO_NEGATED_EXISTENCE"
Exemplo n.º 20
0
    def test_to_json(self):
        import json, os

        dname = os.path.join(tmpdirname.name, "test_modifiers.json")

        literal = "no evidence of"
        category = "definite_negated_existence"
        rule = "forward"
        item = ConTextRule(literal, category, rule)
        ConTextRule.to_json([item], dname)

        with open(dname) as f:
            data = json.load(f)
        assert "context_rules" in data
        assert len(data["context_rules"]) == 1
        item = data["context_rules"][0]
        for key in ["literal", "category", "direction"]:
            assert key in item
Exemplo n.º 21
0
 def test_set_scope_context_window_no_sentences(self):
     """Test that setting the scope succeeds if sentence boundaries haven't been set but _use_context_window is True."""
     doc = nlp.tokenizer(
         "family history of breast cancer but no diabetes. She has afib.")
     rule = ConTextRule("family history of",
                        "FAMILY_HISTORY",
                        direction="FORWARD",
                        max_scope=2)
     modifier = ConTextModifier(rule, 0, 3, doc, _use_context_window=True)
     assert modifier.scope == doc[3:5]
Exemplo n.º 22
0
    def context_graph(self):
        doc = nlp.tokenizer("There is no evidence of pneumonia but there is chf.")
        doc[0].is_sent_start = True
        for token in doc[1:]:
            token.is_sent_start = False
        item_data1 = ConTextRule(
            "no evidence of", "DEFINITE_NEGATED_EXISTENCE", "forward"
        )
        tag_object1 = ConTextModifier(item_data1, 2, 5, doc)

        item_data2 = ConTextRule("evidence of", "DEFINITE_EXISTENCE", "forward")
        tag_object2 = ConTextModifier(item_data2, 3, 5, doc)

        item_data3 = ConTextRule("but", "TERMINATE", "TERMINATE")
        tag_object3 = ConTextModifier(item_data3, 6, 7, doc)

        graph = ConTextGraph()
        graph.modifiers = [tag_object1, tag_object2, tag_object3]
        return doc, graph
Exemplo n.º 23
0
    def test_overlapping_target(self):
        """Test that a modifier will not modify a target if it is
        in the same span as the modifier.
        """
        doc = nlp("Pt presents for r/o of pneumonia.")
        rule = ConTextRule("r/o", "UNCERTAIN", direction="BIDIRECTIONAL")
        modifier = ConTextModifier(rule, 3, 4, doc)
        target = Span(doc, 3, 4, "TEST")

        assert modifier.modifies(target) is False
    def test_is_family(self):
        doc = nlp("Family history of breast cancer.")
        context = ConTextComponent(nlp, add_attrs=True, rules=None)
        rules = [
            ConTextRule("family history of", "FAMILY", direction="forward")
        ]
        context.add(rules)
        doc.ents = (doc[-3:-1], )
        context(doc)

        assert doc.ents[0]._.is_family is True
Exemplo n.º 25
0
    def test_on_modifies_true(self):
        def on_modifies(target, modifier, span_between):
            return True

        rule = ConTextRule("no evidence of",
                           "NEGATED_EXISTENCE",
                           on_modifies=on_modifies)
        doc = nlp("There is no evidence of pneumonia or chf.")
        doc.ents = (Span(doc, 5, 6, "CONDITION"), Span(doc, 6, 8, "CONDITION"))
        mod = ConTextModifier(rule, 2, 5, doc)

        assert mod.modifies(doc.ents[0]) is True
 def test_global_allowed_types2(self):
     """Check that if the ConTextComponent does not have allowed_types defined
     and a ConTextRule does, the ConTextRule will not receive the component's
     value.
     """
     context = ConTextComponent(nlp, rules=None, allowed_types=None)
     rule = ConTextRule("no evidence of",
                        "NEGATED_EXISTENCE",
                        "FORWARD",
                        allowed_types={"PROBLEM"})
     context.add([rule])
     assert rule.allowed_types == {"PROBLEM"}
Exemplo n.º 27
0
    def test_no_limit_scope_same_category_different_allowed_types(self):
        """Test that a two ConTextModifiers of the same type but with different
         allowed types does not limits the scope of the modifier object.
         """
        doc = nlp("no history of travel to Puerto Rico, neg for pneumonia")

        rule = ConTextRule(
            "no history of",
            "DEFINITE_NEGATED_EXISTENCE",
            "FORWARD",
            allowed_types={"TRAVEL"},
        )
        rule2 = ConTextRule(
            "neg for",
            "DEFINITE_NEGATED_EXISTENCE",
            "FORWARD",
            allowed_types={"CONDITION"},
        )
        modifier = ConTextModifier(rule, 0, 3, doc)
        modifier2 = ConTextModifier(rule2, 8, 10, doc)
        assert not modifier.limit_scope(modifier2)
Exemplo n.º 28
0
 def test_set_scope_fails_no_sentences(self):
     """Test that setting the scope fails if sentence boundaries haven't been set."""
     doc = nlp.tokenizer(
         "family history of breast cancer but no diabetes. She has afib.")
     rule = ConTextRule("family history of",
                        "FAMILY_HISTORY",
                        direction="FORWARD")
     with pytest.raises(ValueError) as exception_info:
         # This should fail because doc.sents are None
         ConTextModifier(rule, 0, 3, doc)
     exception_info.match(
         "ConText failed because sentence boundaries have not been set")
Exemplo n.º 29
0
    def test_on_modifies_false(self):
        def on_modifies(target, modifier, span_between):
            return False

        rule = ConTextRule("no evidence of",
                           "NEGATED_EXISTENCE",
                           on_modifies=on_modifies)
        doc = nlp("There is no evidence of pneumonia or chf.")
        doc.ents = (doc[5:6], doc[7:8])
        modifier = ConTextModifier(rule, 2, 5, doc)

        assert modifier.modifies(doc.ents[0]) is False
Exemplo n.º 30
0
 def test_no_types(self):
     """Test that not specifying allowed_types or excluded_types will modify all targets."""
     doc = self.create_target_type_examples()
     rule = ConTextRule(
         "no history of travel to",
         category="DEFINITE_NEGATED_EXISTENCE",
         direction="FORWARD",
     )
     modifier = ConTextModifier(rule, 0, 5, doc)
     modifier.set_scope()
     travel, condition = doc.ents  # "puerto rico", "pneumonia"
     assert modifier.modifies(travel) is True
     assert modifier.modifies(condition) is True