def test_sheets_to_dataframe(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        ex_f = DATA_DIRECTORY / "Composition Example Model Baseline.xlsx"
        translator = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                                  json_data=data)
        evaluator = Evaluator(excel_file=ex_f, translator=translator)
        file_name = "Composition Example Model Baseline.xlsx"
        evaluator.sheets_to_dataframe(excel_file=DATA_DIRECTORY / file_name)
        columns_list = [col for col in evaluator.df.columns]
        self.assertListEqual(["Component", "Position", "Part"], columns_list)

        # 63 ids provided .
        self.assertEqual(63, len(evaluator.df_ids))

        data2 = (PATTERNS / "Composition.json").read_text()
        data2 = json.loads(data2)

        ex_f2 = DATA_DIRECTORY / "Composition Example 2 Model Changed.xlsx"
        tr2 = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                           json_data=data2)
        eval = Evaluator(excel_file=ex_f2, translator=tr2)

        self.assertFalse(eval.df_renames.empty)
        self.assertFalse(eval.df_ids.empty)
    def test_to_property_di_graph(self):
        # the goal is to create a graph object.
        # networkx provides the functionality to get the data into the graph
        # the graph itself will be tested so I should just test that a graph
        # obj exists.
        # TODO: create tests for the properties on the Evaluator class.
        json_data = (PATTERNS / "Composition.json").read_text()
        json_data = json.loads(json_data)
        tr = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                          json_data=json_data)
        file = DATA_DIRECTORY / "Composition Example 2 Model partial_map.xlsx"
        evaluator = Evaluator(excel_file=file, translator=tr)
        evaluator.rename_df_columns()
        evaluator.add_missing_columns()
        evaluator.to_property_di_graph()
        pdg = evaluator.prop_di_graph

        for node in list(pdg):
            self.assertEqual(node, pdg.nodes[node][node].name)

        for edge in list(pdg.edges):
            source_edge = edge[0]
            target_edge = edge[1]
            pdg_edge = pdg.edges[edge]["diedge"]
            source_pdg = pdg_edge.named_edge_triple[0]
            target_pdg = pdg_edge.named_edge_triple[1]
            self.assertEqual(source_edge, source_pdg)
            self.assertEqual(target_edge, target_pdg)
    def test_has_rename(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        translator = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                                  json_data=data)
        excel_file = DATA_DIRECTORY / "Composition Example Model Changed.xlsx"
        evaluator = Evaluator(excel_file=excel_file, translator=translator)
        self.assertTrue(evaluator.has_rename)
        excel_no_rename = (DATA_DIRECTORY /
                           "Composition Example Model Baseline.xlsx")
        evaluator_no_rename = Evaluator(excel_file=excel_no_rename,
                                        translator=translator)
        self.assertFalse(evaluator_no_rename.has_rename)
    def setUp(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        self.translator = MDTranslator(json_path=(PATTERNS /
                                                  "Composition.json"),
                                       json_data=data)

        # Create Baby dataset to deal with manual checking
        data_dict = {
            "Composite Thing": ["Car", "Car", "Wheel", "Engine"],
            "component": ["engine", "rear driver", "hub", "drive output"],
            "Atomic Thing": ["Engine", "Wheel", "Hub", "Drive Output"],
        }
        df = pd.DataFrame(data=data_dict)
        self.evaluator = Evaluator(
            excel_file=(DATA_DIRECTORY / "Composition Example.xlsx"),
            translator=self.translator,
        )
        self.evaluator.df = df
        self.evaluator.rename_df_columns()
        self.evaluator.add_missing_columns()
        self.evaluator.to_property_di_graph()
        self.Graph = self.evaluator.prop_di_graph
Beispiel #5
0
def create_md_model(input_paths, input_patterns="", output_path=""):
    """
    For each Excel file in input_paths create a JSON file that creates
    the desired model in MagicDraw, as long as it corresponds to a valid
    pattern sheet.

    Parameters
    ----------
    input_paths : list of str
        List of strings parsed from the command line.

    input_patterns : list of str
        List of paths to pattern file provided by the user.

    output_path : str
        String of the desired location for the output. This is optional
        and if omitted then the output files will be placed in the same
        directory as the input files.

    Returns
    -------
    output : JSON file
        Generates a JSON file as output that the Player Piano digests to
        generate a new MagicDraw model.
    """
    wkbk_paths = []
    here = Path(os.getcwd())

    for path in input_paths:
        p = Path(path)
        if not p.is_absolute():
            p = here / p
        if p.is_dir():
            p = list(p.glob("*.xlsx"))
        else:
            p = [p]

        wkbk_paths.extend(p)

    json_patterns = {
        pattern_path.name.split(".")[0].lower(): pattern_path
        for pattern_path in PATTERNS.glob("*.json")
    }
    if input_patterns:
        for in_pat in map(Path, input_patterns):
            if in_pat.is_dir():
                new_pats = {
                    inp.name.split(".")[0].lower(): inp
                    for inp in in_pat.glob("*.json")
                }
            else:
                new_pats = {in_pat.name.split(".")[0].lower(): in_pat}
            json_patterns.update(new_pats)

    for wkbk in wkbk_paths:
        if wkbk.parts[-1].split(".")[-1] != "xlsx":
            msg = ("\n" + "This program only supports Excel Files." +
                   ' "{0}" was skipped, not an Excel File').format(
                       wkbk.parts[-1])
            warnings.warn(msg)
            continue
        xl = pd.ExcelFile(wkbk)
        not_found = 0
        pattern_sheet = ""
        for sheet in xl.sheet_names:
            if sheet.lower() not in json_patterns.keys():
                not_found += 1
                if not_found == len(xl.sheet_names):
                    warn_msg = (
                        'The Excel File "{0}" cannot be processed as none of the worksheets match a '
                        + "supported pattern type.").format(wkbk.parts[-1])
                    patterns_msg = (
                        "The currently supported " +
                        "patterns are: {0}".format([*json_patterns]))
                    patts = ("New patterns may be added in the" +
                             " ingrid/src/model_processing/patterns directory")
                    warnings.warn("\n" + warn_msg + "\n" + patterns_msg +
                                  "\n" + patts)
                    break
                else:
                    continue
            else:
                pattern_sheet = sheet.lower()
                break

        if pattern_sheet:
            data = (json_patterns[pattern_sheet]).read_text()
            data = json.loads(data)
        else:
            continue
        translator = MDTranslator(json_path=json_patterns[pattern_sheet],
                                  json_data=data)
        evaluator = Evaluator(excel_file=wkbk, translator=translator)
        evaluator.rename_df_columns()
        evaluator.add_missing_columns()
        evaluator.to_property_di_graph()
        property_di_graph = evaluator.prop_di_graph
        vert_set = property_di_graph.vertex_set
        json_out = {"modification targets": []}
        decs_json = []
        edge_json = []
        for vertex in vert_set:
            vert_uml, decs_uml, edge_uml = vertex.create_node_to_uml(
                translator=translator)
            json_out["modification targets"].extend(vert_uml)
            decs_json.extend(decs_uml)
            edge_json.extend(edge_uml)

        json_out["modification targets"].extend(decs_json)
        json_out["modification targets"].extend(edge_json)

        if not output_path:
            outfile = wkbk.parent.joinpath(wkbk.parts[-1]).with_suffix(".json")
        else:
            outpath = Path(output_path)
            if not outpath.is_absolute():
                if outpath.parts[-1] == here.parts[-1]:
                    outpath = here
                else:
                    outpath = here / outpath
            outfile = (Path(outpath).joinpath(
                wkbk.parts[-1]).with_suffix(".json"))

        (outfile).write_text(json.dumps(json_out, indent=4, sort_keys=True))

        print("Creation Complete")
class TestPropertyDiGraph(unittest.TestCase):
    def setUp(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        self.translator = MDTranslator(json_path=(PATTERNS /
                                                  "Composition.json"),
                                       json_data=data)

        # Create Baby dataset to deal with manual checking
        data_dict = {
            "Composite Thing": ["Car", "Car", "Wheel", "Engine"],
            "component": ["engine", "rear driver", "hub", "drive output"],
            "Atomic Thing": ["Engine", "Wheel", "Hub", "Drive Output"],
        }
        df = pd.DataFrame(data=data_dict)
        self.evaluator = Evaluator(
            excel_file=(DATA_DIRECTORY / "Composition Example.xlsx"),
            translator=self.translator,
        )
        self.evaluator.df = df
        self.evaluator.rename_df_columns()
        self.evaluator.add_missing_columns()
        self.evaluator.to_property_di_graph()
        self.Graph = self.evaluator.prop_di_graph

    def test_named_vertex_set(self):
        expect_vert_set = {
            "car qua engine context",
            "Car",
            "car qua rear driver context",
            "Wheel",
            "engine qua drive output context",
            "Engine",
            "engine",
            "rear driver",
            "hub",
            "Hub",
            "drive output",
            "Drive Output",
            "A_car qua engine context_engine",
            "A_car qua rear driver context_rear driver",
            "A_wheel qua hub context_hub",
            "A_engine qua drive output context_drive output",
            "wheel qua hub context",
        }
        self.assertSetEqual(expect_vert_set, self.Graph.named_vertex_set)

    def test_vertex_set(self):
        # idea: check that the vertex_set contains the vert objects expect
        # check that each element in the vertex_set is a vertex object and
        # then check their names.
        expect_vert_set = {
            "car qua engine context",
            "Car",
            "car qua rear driver context",
            "Wheel",
            "engine qua drive output context",
            "Engine",
            "engine",
            "rear driver",
            "hub",
            "Hub",
            "drive output",
            "Drive Output",
            "A_car qua engine context_engine",
            "A_car qua rear driver context_rear driver",
            "A_wheel qua hub context_hub",
            "A_engine qua drive output context_drive output",
            "wheel qua hub context",
        }

        for vertex in self.Graph.vertex_set:
            self.assertIsInstance(vertex, Vertex)
            self.assertIn(vertex.name, expect_vert_set)

    def test_edge_set(self):
        # check each element of edge_set is infact a DiEdge
        # then that it should be an edge at all.
        # TODO: Find a way to use the self.Graph.edges tuples with the
        # edge attr because these show up as source, targ.
        expected_edge_set = {
            ("car qua engine context", "Car", "type"),
            ("car qua rear driver context", "Car", "type"),
            ("wheel qua hub context", "Wheel", "type"),
            ("engine qua drive output context", "Engine", "type"),
            ("engine", "Engine", "type"),
            ("rear driver", "Wheel", "type"),
            ("hub", "Hub", "type"),
            ("drive output", "Drive Output", "type"),
            (
                "A_car qua rear driver context_rear driver",
                "car qua rear driver context",
                "memberEnd",
            ),
            (
                "A_car qua engine context_engine",
                "car qua engine context",
                "memberEnd",
            ),
            (
                "A_wheel qua hub context_hub",
                "wheel qua hub context",
                "memberEnd",
            ),
            (
                "A_engine qua drive output context_drive output",
                "engine qua drive output context",
                "memberEnd",
            ),
            ("A_car qua engine context_engine", "engine", "memberEnd"),
            (
                "A_car qua rear driver context_rear driver",
                "rear driver",
                "memberEnd",
            ),
            ("A_wheel qua hub context_hub", "hub", "memberEnd"),
            (
                "A_engine qua drive output context_drive output",
                "drive output",
                "memberEnd",
            ),
            ("engine", "Car", "owner"),
            ("rear driver", "Car", "owner"),
            ("hub", "Wheel", "owner"),
            ("drive output", "Engine", "owner"),
            (
                "engine qua drive output context",
                "A_engine qua drive output context_drive output",
                "owner",
            ),
            (
                "car qua rear driver context",
                "A_car qua rear driver context_rear driver",
                "owner",
            ),
            ("wheel qua hub context", "A_wheel qua hub context_hub", "owner"),
            (
                "engine qua drive output context",
                "A_engine qua drive output context_drive output",
                "owner",
            ),
            (
                "car qua engine context",
                "A_car qua engine context_engine",
                "owner",
            ),
        }
        for edge in self.Graph.edge_set:
            self.assertIsInstance(edge, DiEdge)
            self.assertIn(edge.named_edge_triple, expected_edge_set)

    def tearDown(self):
        pass
    def test_add_missing_columns(self):
        # TODO: explicitly check that the new columns are made.
        # TODO: remove reliance on excelfile data.
        # TODO: This is an incomplete test because it does not test for
        # the case of no space column to be created.
        evaluator = Evaluator(
            excel_file=DATA_DIRECTORY / "Composition Example.xlsx",
            translator=self.translator,
        )
        evaluator.translator.data["Pattern Graph Edges"].extend([
            ["cardinal", "Atomic Thing", "owner"],
            ["Composite Thing", "component context", "type"],
            [
                "A_composite owner_component-end1",
                "A_composite owner_component",
                "memberEnd",
            ],
        ])

        data_dict = {
            "Composite Thing": ["Car", "Wheel", "Engine"],
            "component": ["chassis", "tire", "mount"],
            "Atomic Thing": ["Chassis", "Tire", "Mount"],
        }
        df = pd.DataFrame(data=data_dict)
        evaluator.df = df
        evaluator.rename_df_columns()
        expected_cols = {
            "Composite Thing",
            "component",
            "Atomic Thing",
            "composite owner",
            "A_composite owner_component",
            "cardinal",
            "component context",
            "A_composite owner_component-end1",
        }
        evaluator.add_missing_columns()

        self.assertSetEqual(expected_cols, set(evaluator.df.columns))

        expected_composite_owner = [
            "car qua chassis context",
            "wheel qua tire context",
            "engine qua mount context",
        ]
        expected_comp_owner_comp = [
            "A_car qua chassis context_chassis",
            "A_wheel qua tire context_tire",
            "A_engine qua mount context_mount",
        ]
        expect_cardinal = [
            "car cardinal",
            "wheel cardinal",
            "engine cardinal",
        ]
        expect_space_in_df = [
            "chassis qua context context",
            "tire qua context context",
            "mount qua context context",
        ]
        expect_dash = [
            "A_car qua chassis context_chassis-end1",
            "A_wheel qua tire context_tire-end1",
            "A_engine qua mount context_mount-end1",
        ]
        self.assertListEqual(expected_composite_owner,
                             list(evaluator.df["composite owner"]))
        self.assertListEqual(
            expected_comp_owner_comp,
            list(evaluator.df["A_composite owner_component"]),
        )
        self.assertListEqual(expect_cardinal, list(evaluator.df["cardinal"]))
        self.assertListEqual(expect_space_in_df,
                             list(evaluator.df["component context"]))
        self.assertListEqual(
            expect_dash,
            list(evaluator.df["A_composite owner_component-end1"]),
        )
    def setUp(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        self.translator = MDTranslator(json_path=(PATTERNS /
                                                  "Composition.json"),
                                       json_data=data)
        self.evaluator = Evaluator(
            excel_file=DATA_DIRECTORY / "Composition Example.xlsx",
            translator=self.translator,
        )

        data_dict = {
            "Component": [
                "Car",
                "Car",
                "Car",
                "Car",
                "Car",
                "Car",
                "Car",
                "Wheel",
                "Wheel",
                "Wheel",
                "Engine",
                "Engine",
                "Engine",
                "Engine",
                "Engine",
                "Engine",
            ],
            "Position": [
                "engine",
                "chassis",
                "driveshaft",
                "front passenger",
                "front driver",
                "rear passenger",
                "rear driver",
                "hub",
                "tire",
                "lug nut",
                "one",
                "two",
                "three",
                "four",
                "drive output",
                "mount",
            ],
            "Part": [
                "Engine",
                "Chassis",
                "Driveshaft",
                "Wheel",
                "Wheel",
                "Wheel",
                "Wheel",
                "Hub",
                "Tire",
                "Lug Nut",
                "Cylinder",
                "Cylinder",
                "Cylinder",
                "Cylinder",
                "Drive Output",
                "Mount",
            ],
        }
        self.evaluator.df = pd.DataFrame(data=data_dict)
class TestEvaluator(unittest.TestCase):
    # TODO: Make sure all additional graph objects that are desired are
    # created by the graph creation logic.
    # TODO: Test the PROCESS of some of these functions.

    def setUp(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        self.translator = MDTranslator(json_path=(PATTERNS /
                                                  "Composition.json"),
                                       json_data=data)
        self.evaluator = Evaluator(
            excel_file=DATA_DIRECTORY / "Composition Example.xlsx",
            translator=self.translator,
        )

        data_dict = {
            "Component": [
                "Car",
                "Car",
                "Car",
                "Car",
                "Car",
                "Car",
                "Car",
                "Wheel",
                "Wheel",
                "Wheel",
                "Engine",
                "Engine",
                "Engine",
                "Engine",
                "Engine",
                "Engine",
            ],
            "Position": [
                "engine",
                "chassis",
                "driveshaft",
                "front passenger",
                "front driver",
                "rear passenger",
                "rear driver",
                "hub",
                "tire",
                "lug nut",
                "one",
                "two",
                "three",
                "four",
                "drive output",
                "mount",
            ],
            "Part": [
                "Engine",
                "Chassis",
                "Driveshaft",
                "Wheel",
                "Wheel",
                "Wheel",
                "Wheel",
                "Hub",
                "Tire",
                "Lug Nut",
                "Cylinder",
                "Cylinder",
                "Cylinder",
                "Cylinder",
                "Drive Output",
                "Mount",
            ],
        }
        self.evaluator.df = pd.DataFrame(data=data_dict)

    def test_sheets_to_dataframe(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        ex_f = DATA_DIRECTORY / "Composition Example Model Baseline.xlsx"
        translator = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                                  json_data=data)
        evaluator = Evaluator(excel_file=ex_f, translator=translator)
        file_name = "Composition Example Model Baseline.xlsx"
        evaluator.sheets_to_dataframe(excel_file=DATA_DIRECTORY / file_name)
        columns_list = [col for col in evaluator.df.columns]
        self.assertListEqual(["Component", "Position", "Part"], columns_list)

        # 63 ids provided .
        self.assertEqual(63, len(evaluator.df_ids))

        data2 = (PATTERNS / "Composition.json").read_text()
        data2 = json.loads(data2)

        ex_f2 = DATA_DIRECTORY / "Composition Example 2 Model Changed.xlsx"
        tr2 = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                           json_data=data2)
        eval = Evaluator(excel_file=ex_f2, translator=tr2)

        self.assertFalse(eval.df_renames.empty)
        self.assertFalse(eval.df_ids.empty)

    def test_has_rename(self):
        data = (PATTERNS / "Composition.json").read_text()
        data = json.loads(data)

        translator = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                                  json_data=data)
        excel_file = DATA_DIRECTORY / "Composition Example Model Changed.xlsx"
        evaluator = Evaluator(excel_file=excel_file, translator=translator)
        self.assertTrue(evaluator.has_rename)
        excel_no_rename = (DATA_DIRECTORY /
                           "Composition Example Model Baseline.xlsx")
        evaluator_no_rename = Evaluator(excel_file=excel_no_rename,
                                        translator=translator)
        self.assertFalse(evaluator_no_rename.has_rename)

    def test_rename_df_columns(self):
        # just need to test that the columns are as expected.
        # utils tests the two auxiliary functions that rename df entries.
        expected_cols = ["Composite Thing", "component", "Atomic Thing"]
        self.evaluator.rename_df_columns()
        self.assertListEqual(expected_cols, list(self.evaluator.df.columns))
        self.assertEqual(set(), self.evaluator.root_node_attr_columns)

    def test_add_missing_columns(self):
        # TODO: explicitly check that the new columns are made.
        # TODO: remove reliance on excelfile data.
        # TODO: This is an incomplete test because it does not test for
        # the case of no space column to be created.
        evaluator = Evaluator(
            excel_file=DATA_DIRECTORY / "Composition Example.xlsx",
            translator=self.translator,
        )
        evaluator.translator.data["Pattern Graph Edges"].extend([
            ["cardinal", "Atomic Thing", "owner"],
            ["Composite Thing", "component context", "type"],
            [
                "A_composite owner_component-end1",
                "A_composite owner_component",
                "memberEnd",
            ],
        ])

        data_dict = {
            "Composite Thing": ["Car", "Wheel", "Engine"],
            "component": ["chassis", "tire", "mount"],
            "Atomic Thing": ["Chassis", "Tire", "Mount"],
        }
        df = pd.DataFrame(data=data_dict)
        evaluator.df = df
        evaluator.rename_df_columns()
        expected_cols = {
            "Composite Thing",
            "component",
            "Atomic Thing",
            "composite owner",
            "A_composite owner_component",
            "cardinal",
            "component context",
            "A_composite owner_component-end1",
        }
        evaluator.add_missing_columns()

        self.assertSetEqual(expected_cols, set(evaluator.df.columns))

        expected_composite_owner = [
            "car qua chassis context",
            "wheel qua tire context",
            "engine qua mount context",
        ]
        expected_comp_owner_comp = [
            "A_car qua chassis context_chassis",
            "A_wheel qua tire context_tire",
            "A_engine qua mount context_mount",
        ]
        expect_cardinal = [
            "car cardinal",
            "wheel cardinal",
            "engine cardinal",
        ]
        expect_space_in_df = [
            "chassis qua context context",
            "tire qua context context",
            "mount qua context context",
        ]
        expect_dash = [
            "A_car qua chassis context_chassis-end1",
            "A_wheel qua tire context_tire-end1",
            "A_engine qua mount context_mount-end1",
        ]
        self.assertListEqual(expected_composite_owner,
                             list(evaluator.df["composite owner"]))
        self.assertListEqual(
            expected_comp_owner_comp,
            list(evaluator.df["A_composite owner_component"]),
        )
        self.assertListEqual(expect_cardinal, list(evaluator.df["cardinal"]))
        self.assertListEqual(expect_space_in_df,
                             list(evaluator.df["component context"]))
        self.assertListEqual(
            expect_dash,
            list(evaluator.df["A_composite owner_component-end1"]),
        )

    def test_to_property_di_graph(self):
        # the goal is to create a graph object.
        # networkx provides the functionality to get the data into the graph
        # the graph itself will be tested so I should just test that a graph
        # obj exists.
        # TODO: create tests for the properties on the Evaluator class.
        json_data = (PATTERNS / "Composition.json").read_text()
        json_data = json.loads(json_data)
        tr = MDTranslator(json_path=(PATTERNS / "Composition.json"),
                          json_data=json_data)
        file = DATA_DIRECTORY / "Composition Example 2 Model partial_map.xlsx"
        evaluator = Evaluator(excel_file=file, translator=tr)
        evaluator.rename_df_columns()
        evaluator.add_missing_columns()
        evaluator.to_property_di_graph()
        pdg = evaluator.prop_di_graph

        for node in list(pdg):
            self.assertEqual(node, pdg.nodes[node][node].name)

        for edge in list(pdg.edges):
            source_edge = edge[0]
            target_edge = edge[1]
            pdg_edge = pdg.edges[edge]["diedge"]
            source_pdg = pdg_edge.named_edge_triple[0]
            target_pdg = pdg_edge.named_edge_triple[1]
            self.assertEqual(source_edge, source_pdg)
            self.assertEqual(target_edge, target_pdg)

    def tearDown(self):
        pass