示例#1
0
    def _construct_model_json(self):
        self._out_json["model"]["id"] = self.name
        self._out_json["model"]["unit_models"] = {}
        self._out_json["model"]["arcs"] = {}

        for unit_model in self.unit_models.values():
            unit_name = unit_model["name"]
            unit_type = unit_model["type"]
            unit_icon = UnitModelIcon(unit_type)

            unit_contents = {
                "type": unit_type,
                "image": "/images/icons/" + unit_icon.icon,
            }
            if unit_name in self.serialized_contents:
                for pfx in "performance", "stream":
                    content_type = pfx + "_contents"
                    c = self.serialized_contents[unit_name][
                        content_type].to_dict("index")
                    # ensure that keys are strings (so it's valid JSON)
                    unit_contents[content_type] = {
                        str(k): v
                        for k, v in c.items()
                    }

            self._out_json["model"]["unit_models"][unit_name] = unit_contents

        for edge, edge_info in self.edges.items():
            self._out_json["model"]["arcs"][edge] = {
                "source": edge_info["source"].getname(),
                "dest": edge_info["dest"].getname(),
                "label": self.labels[edge],
            }
示例#2
0
    def _construct_model_json(self):
        from idaes.core.util.tables import create_stream_table_dataframe  # deferred to avoid circular import

        # Get the stream table and add it to the model json
        # Change the index of the pandas dataframe to not be the variables
        self._stream_table_df = (
            create_stream_table_dataframe(self.arcs)
            # Change the index of the pandas dataframe to not be the variables
            .reset_index().rename(columns={
                "index": "Variable"
            }).reset_index().rename(columns={
                "index": ""
            }).round(self._sig_figs))

        # Change NaNs to None for JSON
        self._stream_table_df = self._stream_table_df.where(
            (pd.notnull(self._stream_table_df)), None)

        # Puts df in this format for easier parsing in the javascript table:
        # {'index': ["('Liq', 'benzene')", "('Liq', 'toluene')", "('Liq', 'hydrogen')", "('Liq', 'methane')", "('Vap', 'benzene')", "('Vap', 'toluene')", "('Vap', 'hydrogen')", "('Vap', 'methane')", 'temperature', 'pressure'],
        # 'columns': ['s03', 's04', 's05', 's06', 's08', 's09', 's10'],
        # 'data': [[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5], [298.15, 298.15, 298.15, 298.15, 298.15, 298.15, 298.15], [101325.0, 101325.0, 101325.0, 101325.0, 101325.0, 101325.0, 101325.0]]}
        self._out_json["model"][
            "stream_table"] = self._stream_table_df.to_dict("split")

        self._out_json["model"]["id"] = self.name
        self._out_json["model"]["unit_models"] = {}
        self._out_json["model"]["arcs"] = {}

        for unit_model in self.unit_models.values():
            unit_name = unit_model["name"]
            unit_type = unit_model["type"]
            unit_icon = UnitModelIcon(unit_type)

            unit_contents = {
                "type": unit_type,
                "image": "/images/icons/" + unit_icon.icon,
            }
            if unit_name in self._serialized_contents:
                for pfx in "performance", "stream":
                    content_type = pfx + "_contents"
                    c = self._serialized_contents[unit_name][
                        content_type].round(self._sig_figs).to_dict("index")
                    # ensure that keys are strings (so it's valid JSON)
                    unit_contents[content_type] = {
                        str(k): v
                        for k, v in c.items()
                    }

            self._out_json["model"]["unit_models"][unit_name] = unit_contents

        for edge, edge_info in self.edges.items():
            self._out_json["model"]["arcs"][edge] = {
                "source": edge_info["source"].getname(),
                "dest": edge_info["dest"].getname(),
                "label": self.labels[edge],
            }
示例#3
0
 def create_jointjs_image(unit_icon: UnitModelIcon, unit_name,
                          unit_type, x_pos, y_pos):
     """Create jointjs element 'standard.Image' type in json format"""
     try:
         return self._create_image_jointjs_json(
             x_pos,
             y_pos,
             unit_name,
             unit_icon.icon,
             unit_type,
             unit_icon.link_positions,
         )
     except KeyError as e:
         self._logger.info(
             f'Unable to find icon for {unit_type}. Using default icon')
         default_icon = UnitModelIcon()
         return self._create_image_jointjs_json(
             x_pos,
             y_pos,
             unit_name,
             default_icon.icon,
             unit_type,
             default_icon.link_positions,
         )
示例#4
0
    def _construct_jointjs_json(self):
        self._out_json["cells"] = []

        # Start out in the top left corner until we get a better inital layout
        x_pos = 10
        y_pos = 10
        y_starting_pos = 10

        default_icon = UnitModelIcon()
        for component, unit_attrs in self.unit_models.items():
            unit_icon = UnitModelIcon(unit_attrs["type"])
            try:
                self._create_image_jointjs_json(
                    x_pos,
                    y_pos,
                    unit_attrs["name"],
                    unit_icon.icon,
                    unit_attrs["type"],
                    unit_icon.link_positions,
                )
            except KeyError as e:
                self._logger.info(
                    f'Unable to find icon for {unit_attrs["type"]}. Using default icon'
                )
                self._create_image_jointjs_json(
                    x_pos,
                    y_pos,
                    unit_attrs["name"],
                    default_icon.icon,
                    unit_attrs["type"],
                    default_icon.link_positions,
                )

            # If x_pos it greater than 700 then start another diagonal line
            if x_pos >= 700:
                x_pos = 100
                y_pos = y_starting_pos
                y_starting_pos += 100
            else:
                x_pos += 100
                y_pos += 100

        for name, ports_dict in self.edges.items():
            umst = self.unit_models[ports_dict["source"]]["type"]  # alias
            dest = ports_dict["dest"]
            if hasattr(ports_dict["source"], "vap_outlet"):
                # TODO Figure out how to denote different outlet types. Need to
                # deal with multiple input/output offsets
                for arc in list(self.arcs.values()):
                    if (
                        self.ports[arc.dest] == dest
                        and arc.source == ports_dict["source"].vap_outlet
                    ):
                        source_anchor = "top"
                    else:
                        source_anchor = "bottom"
            else:
                source_anchor = "out"

            # The source_port and dest_port should be replaced by actual names in case there are multiple
            # inlets and outlets between the same two unit models
            source_port = "out"
            dest_port = "in"
            self._create_link_jointjs_json(
                source_port,
                dest_port,
                ports_dict["source"].getname(),
                dest.getname(),
                name,
                self.labels[name],
            )
示例#5
0
def test_link_position_mapping(model_name, expected):
    expected_dict = eval(expected)
    positions = UnitModelIcon(model_name).link_positions
    assert positions == expected_dict
示例#6
0
def test_icon_mapping(test_input, expected):
    assert UnitModelIcon(test_input).icon == expected
    with pytest.raises(ValueError):
        UnitModelIcon("unregistered_model", "not_default")
示例#7
0
def test_icon_mapping(test_input, expected):
    assert UnitModelIcon(test_input).icon == expected
示例#8
0
    def _construct_jointjs_json(self):
        def create_jointjs_image(unit_icon: UnitModelIcon, unit_name,
                                 unit_type, x_pos, y_pos):
            """Create jointjs element 'standard.Image' type in json format"""
            try:
                return self._create_image_jointjs_json(
                    x_pos,
                    y_pos,
                    unit_name,
                    unit_icon.icon,
                    unit_type,
                    unit_icon.link_positions,
                )
            except KeyError as e:
                self._logger.info(
                    f'Unable to find icon for {unit_type}. Using default icon')
                default_icon = UnitModelIcon()
                return self._create_image_jointjs_json(
                    x_pos,
                    y_pos,
                    unit_name,
                    default_icon.icon,
                    unit_type,
                    default_icon.link_positions,
                )

        def adjust_image_position(x_pos, y_pos, y_starting_pos):
            """Based on the position of the last added element, we calculate
            the x,y position of the next element.
            """
            # If x_pos it greater than 700 then start another diagonal line
            if x_pos >= 700:
                x_pos = 100
                y_pos = y_starting_pos
                y_starting_pos += 100
            else:
                x_pos += 100
                y_pos += 100

            return x_pos, y_pos, y_starting_pos

        self._out_json["cells"] = []

        # Start out in the top left corner until we get a better inital layout
        x_pos = 10
        y_pos = 10
        y_starting_pos = 10

        track_jointjs_elements = {}

        port_index_increment = 0

        # Go through all the edges/links and create the necessary Unit models
        # that are connected to these edges.
        for link_name, ports_dict in self.edges.items():
            src = ports_dict["source"]
            dest = ports_dict["dest"]

            src_unit_name = self.unit_models[src]["name"]
            src_unit_type = self.unit_models[src]["type"]
            src_unit_icon = UnitModelIcon(src_unit_type)

            dest_unit_name = self.unit_models[dest]["name"]
            dest_unit_type = self.unit_models[dest]["type"]
            dest_unit_icon = UnitModelIcon(dest_unit_type)

            if src_unit_name not in track_jointjs_elements:
                cell_index = create_jointjs_image(src_unit_icon, src_unit_name,
                                                  src_unit_type, x_pos, y_pos)
                x_pos, y_pos, y_starting_pos = adjust_image_position(
                    x_pos, y_pos, y_starting_pos)
                track_jointjs_elements[src_unit_name] = cell_index

            if dest_unit_name not in track_jointjs_elements:
                cell_index = create_jointjs_image(dest_unit_icon,
                                                  dest_unit_name,
                                                  dest_unit_type, x_pos, y_pos)
                x_pos, y_pos, y_starting_pos = adjust_image_position(
                    x_pos, y_pos, y_starting_pos)
                track_jointjs_elements[dest_unit_name] = cell_index

            if hasattr(ports_dict["source"], "vap_outlet"):
                # TODO Figure out how to denote different outlet types. Need to
                # deal with multiple input/output offsets
                for arc in list(self.arcs.values()):
                    if (self.ports[arc.dest] == dest
                            and arc.source == ports_dict["source"].vap_outlet):
                        source_anchor = "top"
                    else:
                        source_anchor = "bottom"
            else:
                source_anchor = "out"

            # The source_port and dest_port should be replaced by actual names in case there are multiple
            # inlets and outlets between the same two unit models
            src_port = "out"
            dest_port = "in"

            # We create port ids for both ends: Source and Destination elements
            # and pass it to the link jointjs element for accurate port representation
            src_port_id = port_index_increment
            port_index_increment += 1
            dest_port_id = port_index_increment
            port_index_increment += 1

            # Add source port
            self._add_port_item(track_jointjs_elements[src_unit_name],
                                src_port, src_port_id)
            # Add destination port
            self._add_port_item(track_jointjs_elements[dest_unit_name],
                                dest_port, dest_port_id)

            link_index = self._create_link_jointjs_json(
                src_port_id,
                dest_port_id,
                src.getname(),
                dest.getname(),
                link_name,
                self.labels[link_name],
            )

            # Add routing config if edge/link has source or destination elements
            # that has routing specifications. e.g. If destination element requires
            # the link to connect horizontally from the left side.
            if src_unit_icon.routing_config and src_port in src_unit_icon.routing_config:
                if link_name not in self._out_json["routing_config"]:
                    self._out_json["routing_config"][link_name] = {
                        'cell_index': link_index
                    }
                # The port group has to be specified in the routing config
                self._out_json["routing_config"][link_name][
                    "source"] = src_unit_icon.routing_config[src_port]

            if dest_unit_icon.routing_config and dest_port in dest_unit_icon.routing_config:
                if link_name not in self._out_json["routing_config"]:
                    self._out_json["routing_config"][link_name] = {
                        'cell_index': link_index
                    }
                # The port group has to be specified in the routing config
                self._out_json["routing_config"][link_name][
                    "destination"] = dest_unit_icon.routing_config[dest_port]

        # Make sure that all registered Unit Models are created
        for _, unit_attrs in self.unit_models.items():
            unit_name = unit_attrs['name']
            unit_type = unit_attrs['type']
            unit_icon = UnitModelIcon(unit_type)
            if unit_name in track_jointjs_elements:
                # skip if unit is already added to the list of created cells
                continue
            cell_index = create_jointjs_image(unit_icon, unit_name, unit_type,
                                              x_pos, y_pos)
            x_pos, y_pos, y_starting_pos = adjust_image_position(
                x_pos, y_pos, y_starting_pos)
            track_jointjs_elements[unit_name] = cell_index