Пример #1
0
    def test_apply_changes(self):
        model = Model(view)
        leaf_a_label = 'stervormige'
        leaf_a_field = 'margin'

        report_leaf_a = LabelNode(leaf_a_field, [], (leaf_a_label, 55),
                                  (leaf_a_label, 55))
        report_node_1 = Node('mass', children=[report_leaf_a])
        report_node_2 = Node('positive_finding', children=[report_node_1])
        root = Node('root', children=[report_node_2])
        model.tree = root
        model.create_identifiers(root)
        json_tree = view.generate_tree(model)

        # Test label change
        self.assertEqual(json_tree[4]["text"], leaf_a_label)  # pre change
        leaf_a_id = json_tree[3]["nodeId"]
        leaf_a_new_label = "circumscribed"
        model.change(leaf_a_id, "label", leaf_a_new_label)
        model.apply_back_changes()
        json_tree = view.generate_tree(model)
        self.assertEqual(json_tree[4]["text"], leaf_a_new_label)  # post change

        # Test ignore warning
        self.assertEqual(json_tree[3]["lowConfidence"], True)  # pre change
        self.assertEqual(json_tree[4]["lowConfidence"],
                         False)  # false because of edit
        label_a_id = json_tree[3]["nodeId"]
        leaf_a_id = json_tree[4]["nodeId"]
        model.change(label_a_id, "warning", False)
        json_tree = view.generate_tree(model)
        self.assertEqual(json_tree[3]["lowConfidence"], False)
        model.change(leaf_a_id, "warning", True)
        json_tree = view.generate_tree(model)
        self.assertEqual(json_tree[4]["lowConfidence"], True)
Пример #2
0
 def test_text(self):
     node = Node("category")
     self.assertIsNone(node.text)
     node = Node("category", ("This is text", 60))
     self.assertEqual(node.text, "This is text")
     node.corr_text = "Text is corrected"
     self.assertEqual(node.text, "Text is corrected")
Пример #3
0
 def test_other(self):
     json = [('wat?', 'B-a/O', 1), ('dit', 'I-a/B-b', 1), ('is', 'I-a/I-b', 1),
             ('een', 'I-a/O', 1), ('test', 'I-a/O', 1)]
     actual, _, _ = make_tree(["B-a"], json)
     expected = Node('a', ("wat? dit is een test", 100), children=[
         Node('O', ("wat?", 100)),
         Node('b', ("dit is", 100)),
         Node('O', ("een test", 100))
     ])
     self.assertEqual(expected, actual)
Пример #4
0
 def apply_change(self, node: Node):
     """
     Method used to apply a BackChange to a node
     :param node: the node which needs to be changed
     """
     change = self.back_changes.get(self.tree_identifiers[id(node)],
                                    BackChange())
     node.corr_text = change.text
     if isinstance(node, LabelNode):
         node.corr_label = change.label
Пример #5
0
    def test_identifier_function(self):
        model = Model(view)
        node_1_label = 'mass'
        node_2_label = 'positive_finding'
        node_3_label = 'negative_finding'
        root_label = 'root'

        report_node_1 = Node(node_1_label, children=[])
        report_node_2 = Node(node_2_label, children=[report_node_1])
        report_node_3 = Node(node_1_label, children=[])
        report_node_4 = Node(node_2_label, children=[report_node_3])
        report_node_5 = Node(node_1_label, children=[])
        report_node_6 = Node(node_3_label, children=[report_node_5])
        report_node_7 = Node(node_1_label, children=[])
        report_node_8 = Node(node_3_label, children=[report_node_7])
        root = Node(root_label,
                    children=[
                        report_node_2, report_node_4, report_node_6,
                        report_node_8
                    ])
        model.create_identifiers(root)

        # test if no duplicates
        identifiers = model.tree_identifiers.values()
        self.assertEqual(len(identifiers), len(set(identifiers)))
Пример #6
0
    def test_eq(self):
        leaf1 = Node("field1", text_prediction=("text1", 70), hint="hint1")
        leaf1a = Node("field1", text_prediction=("text1", 70), hint="hint2")
        leaf2 = Node("field2", text_prediction=("text1", 70), hint="hint3")
        self.assertEqual(leaf1, leaf1a)
        self.assertEqual(leaf2, leaf2)
        self.assertNotEqual(leaf1, leaf2)

        leaf = LabelNode("field", ["one", "other"], ("text", 70),
                         ("label", 80),
                         hint="hint")
        other = LabelNode("field", ["one", "other"], ("text", 70),
                          ("label", 80),
                          hint="hint")
        self.assertEqual(leaf, other)
        other = LabelNode("other", ["one", "other"], ("text", 70),
                          ("label", 80),
                          hint="hint")
        self.assertNotEqual(leaf, other)
        other = LabelNode("field", ["one", "other"], ("text", 80),
                          ("label", 80),
                          hint="hint")
        self.assertEqual(leaf, other)
        other = LabelNode("field", ["one", "other"], ("other", 70),
                          ("label", 80),
                          hint="hint")
        self.assertNotEqual(leaf, other)
        other = LabelNode("field", ["two", "other"], ("text", 70),
                          ("label", 80),
                          hint="hint")
        self.assertNotEqual(leaf, other)
        other = LabelNode("field", ["other", "one"], ("text", 70),
                          ("label", 80),
                          hint="hint")
        self.assertNotEqual(
            leaf, other, "Options in different orders shouldn't be the same")
        other = LabelNode("field", ["one", "other"], ("text", 70),
                          ("other", 80),
                          hint="hint")
        self.assertNotEqual(leaf, other)
        other = LabelNode("field", ["one", "other"], ("text", 70),
                          ("label", 70),
                          hint="hint")
        self.assertEqual(leaf, other)
        other = LabelNode("field", ["one", "other"], ("text", 70),
                          ("label", 80),
                          hint="other")
        self.assertEqual(leaf, other)
Пример #7
0
def make_tree(base: List[str], items: list) -> Tuple[Node, List[str], float]:
    """
    Make a tree based on a linear list of items
    :param base: the category of created Node
    :param items: items left for processing. Will be mutated!
    :return: the created Node, the text of the node and the confidence
    """
    base_length = len(base)
    agg_text = []
    sum_conf = 0
    count = 0
    children = []
    first = True
    # loop while items exist and the current label descents from the base (break statement)
    while items:
        (text, label_text, conf) = items[0]
        labels = label_text.split("/")
        # break if the label has a new base
        if not first and not has_base(labels, base):
            break
        # make sure that only the first B-flag is ignored
        first = False

        # the base equals the alternatives, collect all the text and confidences
        if base_length == len(labels):
            agg_text.append(text)
            sum_conf += conf
            count += 1
            items.pop(0)
        # the new label should not be ignored
        else:
            # make a new tree that has a base that goes one label deeper
            child, child_agg_text, child_sum_conf = make_tree(labels[:base_length + 1], items)
            children.append(child)
            agg_text += child_agg_text
            sum_conf += child_sum_conf

    category = clean(base[-1]) if base else 'report'
    if not agg_text:
        return Node(category, children=children), agg_text, sum_conf

    pred_text = ' '.join(agg_text)
    conf = int(sum_conf / len(agg_text) * 100)
    if category in OPTIONS:
        return LabelNode(category, OPTIONS[category], text_prediction=(pred_text, conf)), agg_text, sum_conf
    return Node(category, text_prediction=(pred_text, conf), children=children), agg_text, sum_conf
Пример #8
0
    def test_make_tree(self):
        json = [('dit', 'B-a', 1), ('is', 'I-a', 1), ('een', 'I-a', 1), ('test', 'I-a', 1)]
        actual, _, _ = make_tree([], json)
        expected = Node('a', ("dit is een test", 100))
        self.assertIsInstance(actual, Node)
        self.assertEqual("report", actual.category)
        self.assertEqual(expected, actual.children[0])

        json = [('dit', 'B-a', 1), ('is', 'B-a', 1), ('een', 'B-a', 1), ('test', 'B-a', 1)]
        actual, _, _ = make_tree([], json)
        self.assertEqual(4, len(actual.children))

        actual, _, _ = make_tree([], [])
        expected = Node("report")
        self.assertEqual(expected, actual)

        json = [('niet', 'O', 1), ('kan', 'B-a', 1), ('niet', 'O', 1), ('dit', 'I-a', 1), ('niet', 'O', 1),
                ('ook?', 'I-a', 1), ('niet', 'O', 1)]
        actual, _, _ = make_tree([], json)
        unexpected = Node('a', ("kan dit ook?", 100))
        self.assertNotEqual(unexpected, actual.children[0])

        json = [('nested', 'B-a/B-b/B-c', 1), ('attribute', 'I-a/I-b/B-d', 1), ('too', 'I-a/I-e', 1)]
        actual, _, _ = make_tree(["B-a"], json)
        expected = Node('a', ("nested attribute too", 100), children=[
            Node('b', ("nested attribute", 100), children=[Node('c', ("nested", 100)), Node('d', ("attribute", 100))]),
            Node('e', ("too", 100))
        ])
        self.assertEqual(expected, actual)
Пример #9
0
 def test_instance(self):
     text = Node("field", ("text", 70), hint="hint")
     label = LabelNode("field", ["one", "other"], ("text", 70),
                       ("label", 80),
                       hint="hint")
     self.assertIsInstance(text, Node)
     self.assertNotIsInstance(text, LabelNode)
     self.assertIsInstance(label, LabelNode)
     self.assertIsInstance(label, Node)
Пример #10
0
 def __init__(self, view):
     self.view = view
     self.environments = {}  # Dictionary for environments {name: endpoint}
     self.environment = None
     self.text = ""
     self.colours = {}
     self.tree = Node("report")
     self.tree_identifiers = {}
     self.back_changes = {}
     self.front_changes = {}
Пример #11
0
    def test_set_change_function(self):
        model = Model(view)

        leaf_a_label = 'stervormige'
        leaf_a_label_confidence = 70
        leaf_a_field = 'margin'
        leaf_a_field_confidence = 55
        leaf_b_text = 'laterale bovenkwadrant linkermamma'
        leaf_b_field = 'location'
        leaf_b_field_confidence = 92
        spec_c_field = 'shape'
        node_1_label = 'mass'
        node_2_label = 'positive_finding'
        root_label = 'root'

        change1 = 'changed_label1'
        change2 = 'changed_label2'

        report_leaf_a = LabelNode(leaf_a_field, [],
                                  (leaf_a_label, leaf_a_field_confidence),
                                  (leaf_a_label, leaf_a_label_confidence))
        report_leaf_b = Node(leaf_b_field,
                             (leaf_b_text, leaf_b_field_confidence))
        spec_leaf_c = Node(spec_c_field)
        report_node_1 = Node(
            node_1_label, children=[report_leaf_a, report_leaf_b, spec_leaf_c])
        report_node_2 = Node(node_2_label, children=[report_node_1])
        root = Node(root_label, children=[report_node_2])
        model.tree = root
        model.create_identifiers(root)
        json_tree = view.generate_tree(model)

        # Test leaf label change
        model.change(json_tree[4]['nodeId'], "label", change1)
        model.apply_back_changes()
        json_tree = view.generate_tree(model)
        self.assertEqual(change1, json_tree[4]['text'])
        model.change(json_tree[4]['nodeId'], "label", change2)
        model.apply_back_changes()
        json_tree = view.generate_tree(model)
        self.assertEqual(change2, json_tree[4]['text'])
Пример #12
0
 def test_add_child(self):
     child0 = Node("child0")
     child1 = Node("child1")
     node = Node("label")
     node.add_child(child0)
     node.add_child(child1)
     self.assertEqual(node.children[0], child0)
     self.assertEqual(node.children[1], child1)
Пример #13
0
 def hint(self, node: Node, expected):
     """
     Method used recursively to add hints and expectations to nodes in the node structure
     :param node: The node for which the hints and expectations should be added
     :param expected: The expected nodes at the current level
     """
     if expected:
         found = [child.category for child in node]
         if isinstance(expected.get(node.category), list):
             for category in expected[node.category]:
                 if category not in found:
                     if category in self.labels:
                         leaf = LabelNode(category, self.labels[category])
                     else:
                         leaf = Node(category)
                     node.add_child(leaf)
     for child in node:
         if child.category in self.hints:
             child.hint = self.hints[child.category]
         if expected:
             next_level = expected.get(node.category)
             if isinstance(next_level, dict):
                 self.hint(child, next_level)
Пример #14
0
def get(env_selected):
    """
    Method used to get the right environment
    :param env_selected: The current selected environment, functions as endpoint
    :return: Returns the HTTPResponse generated by the selected environment
    """
    data = request.get_json()

    if data['text'] is None:
        abort(404, message="Text needed for nlp processing")
    text = data["text"]
    if len(text) == 0:
        ret = jsonpickle.encode(Node("root"))
    else:
        ret = jsonpickle.encode(ENVS[env_selected].process(text))
    return {"Response": 200, "Data": ret}
Пример #15
0
    def test_hint(self):
        expected = {
            # 'a': ['b', 'e', 'f'] ReportNodes are not checked, only ReportLeaves
            'a': ['e', 'f']
        }
        labels = {'f': ['l1', 'l2', 'l3']}
        hints = {'e': "hint"}
        hinter = Hinter(expected, labels, hints)
        tree = Node('a',
                    children=[
                        Node('b',
                             children=[
                                 Node('c', ("nested", 100)),
                                 Node('d', ("attribute", 100))
                             ]),
                        Node('e', ("too", 100))
                    ])

        testtree = Node(
            'report',
            children=[
                Node('positive_finding',
                     children=[Node('mass', children=[Node('margin')])])
            ])

        hinter.hint(testtree, EXPECTED_LEAVES)

        hinter.hint(tree, expected)

        self.assertEqual(3, len(tree.children),
                         "make sure the missing LabelNode is added")
        self.assertIsInstance(tree.children[2], LabelNode)
        self.assertEqual(labels['f'], tree.children[2].options)

        self.assertIsNone(tree.children[0].children[0].hint)
        self.assertIsNone(tree.children[0].children[1].hint)
        self.assertEqual("hint", tree.children[1].hint)
Пример #16
0
def make_node(node: Node, identifier: str, parent_id: str,
              model: Model) -> list:
    """
    Method used to create a json template from a node
    :param node: The node that needs to be converted into a json representation
    :param identifier: The identifier of the node
    :param parent_id: The id of the parent of the node
    :param model: The current state of the program
    :return: list of json representations of the node
    """
    change = model.front_changes.get(identifier, FrontChange())
    tmp = json_node_template(node, identifier, parent_id, change, False)
    if node.is_leaf():
        value_identifier = identifier + "_value"
        change = model.front_changes.get(value_identifier, FrontChange())
        field = json_node_template(node, value_identifier, identifier, change,
                                   True)
        return [tmp, field]
    return [tmp]
Пример #17
0
def set_leaf_colours(node: Node, parent_label: str, colours: Dict[str, str]):
    """
    Method used to create the text object with colour for the leaves
    :param node: The TextLeaf which needs to get a colour
    :param parent_label: The label of the parent
    :param colours: The colour dictionary for the current environment
    :return: Returns the object needed for the frontend
    """

    if node.is_speculative():
        return ""
    label = parent_label + node.category
    if node.category == "O":
        result_type = "other"
        colour = None
    else:
        result_type = "label"
        colour = colours.get(node.category, FALLBACK_COLOUR)
    return {
        "text": node.text,
        "colour": colour,
        "type": result_type,
        "label": label,
    }
Пример #18
0
    def test_build_json_tree(self):
        model = Model(view)
        leaf_a_label = 'stervormige'
        leaf_a_label_confidence = 70
        leaf_a_field = 'margin'
        leaf_a_field_confidence = 55
        leaf_b_text = 'laterale bovenkwadrant linkermamma'
        leaf_b_field = 'location'
        leaf_b_field_confidence = 92
        spec_c_field = 'shape'
        node_1_label = 'mass'
        node_2_label = 'positive_finding'
        root_label = 'root'

        report_leaf_a = LabelNode(leaf_a_field, [],
                                  (leaf_a_label, leaf_a_field_confidence),
                                  (leaf_a_label, leaf_a_label_confidence))
        report_leaf_b = Node(leaf_b_field,
                             (leaf_b_text, leaf_b_field_confidence))
        spec_leaf_c = Node(spec_c_field)
        report_node_1 = Node(
            node_1_label, children=[report_leaf_a, report_leaf_b, spec_leaf_c])
        report_node_2 = Node(node_2_label, children=[report_node_1])
        root = Node(root_label, children=[report_node_2])
        model.tree = root
        model.create_identifiers(root)
        json_tree = view.generate_tree(model)

        # test root
        self.assertEqual(json_tree[0]["parentNodeId"], None)
        self.assertEqual(json_tree[0]["template"],
                         "<div class=\"domStyle\"><span>root</span></div>")
        self.assertEqual(json_tree[0]["text"], root_label)

        # test finding
        self.assertEqual(json_tree[1]["parentNodeId"], root_label)
        self.assertEqual(json_tree[1]["text"], node_2_label)

        # test category (mass)
        self.assertEqual(json_tree[2]["parentNodeId"], node_2_label)
        self.assertEqual(json_tree[2]["text"], node_1_label)

        # test labelLeaf field
        self.assertEqual(json_tree[3]["parentNodeId"], node_1_label)
        self.assertEqual(json_tree[3]["text"], leaf_a_field)

        # test labelLeaf label with low confidence
        self.assertEqual(json_tree[4]["parentNodeId"], leaf_a_field)
        self.assertEqual(json_tree[4]["lowConfidence"], True)
        self.assertEqual(json_tree[4]["text"], leaf_a_label)

        # test textLeaf field
        self.assertEqual(json_tree[5]["parentNodeId"], node_1_label)
        self.assertEqual(json_tree[5]["text"], leaf_b_field)

        # test textLeaf text
        self.assertEqual(json_tree[6]["parentNodeId"], leaf_b_field)
        self.assertEqual(json_tree[6]["text"], leaf_b_text)

        # test spec_leaf
        self.assertEqual(json_tree[7]["parentNodeId"], node_1_label)
        self.assertEqual(json_tree[7]["speculative"], True)
        self.assertEqual(json_tree[7]["text"], spec_c_field)
Пример #19
0
 def test_init(self):
     child = Node("child")
     node = Node("category", children=[child])
     self.assertEqual(node.category, "category")
     self.assertEqual(node.children[0], child)
Пример #20
0
def parse(text: str) -> Node:
    """
    Method used to process hersen text
    :param text: Text that needs processing
    :return: For now a stub reportnode, as hinternlp is not implemented
    """

    text = "ongeveer 2, 3 cm zichtbaar ependymomas"
    root = Node("report", (text, 96))
    pos1 = Node("positive finding", (text, 96))
    mass1 = Node("mass", (text, 96))
    size1 = Node("size", ("ongeveer 2, 3 cm", 40), hint="The size of the mass")
    multifocality1 = Node("Multifocality", ("zichtbaar ependymomas", 80))
    hin = ("Multiple tumors in the brain usually indicate metastatic disease (figure)."
           "Primary brain tumors are typically seen in a single region, but some brain tumors like lymphomas, "
           "multicentric glioblastomas and gliomatosis cerebri can be multifocal. Some tumors can be multifocal"
           " as a result of seeding metastases: this can occur in medulloblastomas (PNET-MB), ependymomas, GBMs "
           "and oligodendrogliomas. Meningiomas and schwannomas can be multiple, especially in neurofibromatosis"
           " type II")
    types = ["meningiomas", "ependymomas", "choroid plexus papillomas"]
    mass1.add_child(size1)
    neur = LabelNode("Neurofibromatosis II", types, ("zichtbaar ependymomas", 80), ("ependymomas", 80), hint=hin)
    multifocality1.add_child(neur)
    mass1.add_child(multifocality1)

    # speculative child
    location = Node("location")
    mass1.add_child(location)

    pos1.add_child(mass1)
    root.add_child(pos1)

    return root
Пример #21
0
def json_node_template(node: Node, identifier: str, parent_id: str,
                       change: FrontChange, leaf: bool) -> dict:
    """
    Method used to create a json template of any node in the tree
    :param node: The node for which
    :param identifier: The identifier of the node
    :param parent_id: The identifier of the parent
    :param change: the frontend changes for the node
    :param leaf: whether the node is a the end of a branch
    :return:
    """
    alternatives = None
    low_confidence = False
    percentage = None
    if leaf:
        if isinstance(node, LabelNode):
            alternatives = node.options
            text = node.label
            if not node.is_corrected():
                percentage = node.pred_label_conf
            hint = node.text
        else:
            text = node.text
            hint = None
    else:
        text = node.category
        percentage = node.pred_text_conf
        hint = node.hint

    if not text:
        text = "?"
    orgtemplate = "<div class=\"domStyle\"><span>{}</span></div>".format(text)
    template = orgtemplate
    if percentage:
        low_confidence = percentage < 75
        template = orgtemplate + "<span class=\"confidence\">{}%</span>".format(
            percentage)
    if leaf:
        if node.is_corrected():
            template = orgtemplate + "</div></span><span class=\"material-icons\">mode</span>"

    background_color = COLOUR_DICT[leaf][node.is_speculative()]
    outline_color = background_color

    jsonnode = {
        "nodeId": identifier,
        "parentNodeId": parent_id,
        "lowConfidence": low_confidence,
        "width": 347,
        "height": 147,
        "template": template,
        "alternatives": alternatives,
        "hint": hint,
        "text": text,
        "isCorrected": node.is_corrected(),
        "speculative": node.is_speculative(),
        "backgroundColor": background_color,
        "textColor": "#FFFFFF",
        "outlineColor": outline_color,
        "leaf": leaf,
    }

    apply_change(jsonnode, change)
    return jsonnode