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], }
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], }
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 _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], )
def test_link_position_mapping(model_name, expected): expected_dict = eval(expected) positions = UnitModelIcon(model_name).link_positions assert positions == expected_dict
def test_icon_mapping(test_input, expected): assert UnitModelIcon(test_input).icon == expected with pytest.raises(ValueError): UnitModelIcon("unregistered_model", "not_default")
def test_icon_mapping(test_input, expected): assert UnitModelIcon(test_input).icon == expected
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