Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/cidarlab/pyparchmint
Browse files Browse the repository at this point in the history
  • Loading branch information
rkrishnasanka committed May 30, 2022
2 parents 94e8778 + 5797979 commit f9b977f
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 150 deletions.
4 changes: 3 additions & 1 deletion parchmint/benchmarking.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ def characterize_devices(devices: List[Device]) -> npt.NDArray[Any]:

# Save yes if the device has a layer of type CONTROL
file_info[index, 5] = (
"YES" if "CONTROL" in [layer.type for layer in device.layers] else "NO"
"YES"
if "CONTROL" in [layer.layer_type for layer in device.layers]
else "NO"
)

# Save the max connectiveity of the connection in the device
Expand Down
73 changes: 38 additions & 35 deletions parchmint/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ def rotation(self) -> float:
"""
try:
return self.params.get_param("rotation")
except Exception:
print("Could not find rotation for component")
raise KeyError
except Exception as error:
print("Could not find rotation for component", error)
raise Exception("Could not find rotation for component") from error

@rotation.setter
def rotation(self, value):
Expand Down Expand Up @@ -258,15 +258,16 @@ def rotate_point(
Returns:
Tuple[float, float]: A tuple containing the rotated coordinates
"""
# pylint: disable=invalid-name, too-many-locals
# Setup the center to be used the translation matrices
center_x = self.xspan / 2
center_y = self.yspan / 2

# Setup all the corner points
old_topLeft = np.array((0, 0, 1)).transpose()
old_topRight = np.array((self.xspan, 0, 1)).transpose()
old_bottomLeft = np.array((0, self.yspan, 1)).transpose()
old_bottomRight = np.array((self.xspan, self.yspan, 1)).transpose()
old_topleft = np.array((0, 0, 1)).transpose()
old_topright = np.array((self.xspan, 0, 1)).transpose()
old_bottomleft = np.array((0, self.yspan, 1)).transpose()
old_bottomright = np.array((self.xspan, self.yspan, 1)).transpose()

pos = np.array(((xpos), (ypos), (1)))

Expand All @@ -278,23 +279,23 @@ def rotate_point(
T2 = np.array(((1, 0, center_x), (0, 1, center_y), (0, 0, 1)))

# Rotate the topRight corner and the bottomLeft corner about the center
rotated_topLeft = T2.dot(R.dot(T1.dot(old_bottomLeft)))
rotated_topRight = T2.dot(R.dot(T1.dot(old_topLeft)))
rotated_bottomRight = T2.dot(R.dot(T1.dot(old_topRight)))
rotated_bottomLeft = T2.dot(R.dot(T1.dot(old_bottomRight)))
rotated_topleft = T2.dot(R.dot(T1.dot(old_bottomleft)))
rotated_topright = T2.dot(R.dot(T1.dot(old_topleft)))
rotated_bottomright = T2.dot(R.dot(T1.dot(old_topright)))
rotated_bottomleft = T2.dot(R.dot(T1.dot(old_bottomright)))

# Find the new position of the topleft corner by finding the min of all the corner points
xmin = min(
rotated_topLeft[0],
rotated_topRight[0],
rotated_bottomLeft[0],
rotated_bottomRight[0],
rotated_topleft[0],
rotated_topright[0],
rotated_bottomleft[0],
rotated_bottomright[0],
)
ymin = min(
rotated_topLeft[1],
rotated_topRight[1],
rotated_bottomLeft[1],
rotated_bottomRight[1],
rotated_topleft[1],
rotated_topright[1],
rotated_bottomleft[1],
rotated_bottomright[1],
)

T3 = np.array(((1, 0, -xmin), (0, 1, -ymin), (0, 0, 1)))
Expand All @@ -315,6 +316,8 @@ def rotate_point_around_center(
Returns:
Tuple[float, float]: A tuple containing the rotated coordinates
"""
# pylint: disable=invalid-name,too-many-locals

# Setup the center to be used the translation matrices
center_x = self.xpos + self.xspan / 2
center_y = self.ypos + self.yspan / 2
Expand All @@ -340,23 +343,23 @@ def get_rotated_component_definition(self, angle: int) -> Component:
Returns:
Component: [description]
"""
new_topLeft = self.rotate_point(0, 0, angle)
new_topRight = self.rotate_point(self.xspan, 0, angle)
new_bottomLeft = self.rotate_point(0, self.yspan, angle)
new_bottomRight = self.rotate_point(self.xspan, self.yspan, angle)
new_topleft = self.rotate_point(0, 0, angle)
new_topright = self.rotate_point(self.xspan, 0, angle)
new_bottomleft = self.rotate_point(0, self.yspan, angle)
new_bottomright = self.rotate_point(self.xspan, self.yspan, angle)

# Find xmin, ymin, xmax, ymax for all the corner points
xmin = min(
new_topLeft[0], new_topRight[0], new_bottomLeft[0], new_bottomRight[0]
new_topleft[0], new_topright[0], new_bottomleft[0], new_bottomright[0]
)
ymin = min(
new_topLeft[1], new_topRight[1], new_bottomLeft[1], new_bottomRight[1]
new_topleft[1], new_topright[1], new_bottomleft[1], new_bottomright[1]
)
xmax = max(
new_topLeft[0], new_topRight[0], new_bottomLeft[0], new_bottomRight[0]
new_topleft[0], new_topright[0], new_bottomleft[0], new_bottomright[0]
)
ymax = max(
new_topLeft[1], new_topRight[1], new_bottomLeft[1], new_bottomRight[1]
new_topleft[1], new_topright[1], new_bottomleft[1], new_bottomright[1]
)

# Find the new xspan and yspan
Expand Down Expand Up @@ -408,31 +411,31 @@ def rotate_component(self) -> None:
port.x = new_location[0]
port.y = new_location[1]

new_topLeft = self.rotate_point_around_center(
new_topleft = self.rotate_point_around_center(
self.xpos + 0, self.ypos + 0, self.rotation
)
new_topRight = self.rotate_point_around_center(
new_topright = self.rotate_point_around_center(
self.xpos + self.xspan, self.ypos + 0, self.rotation
)
new_bottomLeft = self.rotate_point_around_center(
new_bottomleft = self.rotate_point_around_center(
self.xpos + 0, self.ypos + self.yspan, self.rotation
)
new_bottomRight = self.rotate_point_around_center(
new_bottomright = self.rotate_point_around_center(
self.xpos + self.xspan, self.ypos + self.yspan, self.rotation
)

# Find xmin, ymin, xmax, ymax for all the corner points
xmin = min(
new_topLeft[0], new_topRight[0], new_bottomLeft[0], new_bottomRight[0]
new_topleft[0], new_topright[0], new_bottomleft[0], new_bottomright[0]
)
ymin = min(
new_topLeft[1], new_topRight[1], new_bottomLeft[1], new_bottomRight[1]
new_topleft[1], new_topright[1], new_bottomleft[1], new_bottomright[1]
)
xmax = max(
new_topLeft[0], new_topRight[0], new_bottomLeft[0], new_bottomRight[0]
new_topleft[0], new_topright[0], new_bottomleft[0], new_bottomright[0]
)
ymax = max(
new_topLeft[1], new_topRight[1], new_bottomLeft[1], new_bottomRight[1]
new_topleft[1], new_topright[1], new_bottomleft[1], new_bottomright[1]
)

# Find the new xspan and yspan
Expand Down
62 changes: 38 additions & 24 deletions parchmint/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,17 @@ def remove_valve(self, valve_id) -> None:

self.remove_component(valve_id)

def compare(self, device: Device, ignore_parameter_diffs: bool = True) -> bool:
def compare(self, device: Device, compare_params: bool = False) -> bool:
"""compare against the input device. Return true if they are semnatcally feasible.
Args:
device (Device): expected device
ignore_parameter_diffs (bool): ignore parameter differences. Defaults to True.
compare_params (bool): comparision includes parameter differences. Defaults to False.
Returns:
bool: If semntically feasible, return true. Else false.
"""
matcher = SimilarityMatcher(self, device)
matcher = SimilarityMatcher(self, device, compare_params=compare_params)

is_same = matcher.is_isomorphic()
matcher.print_params_diff()
Expand Down Expand Up @@ -384,7 +384,7 @@ def remove_layer(self, layer_id: str) -> None:

# Remove all the components and connections associated with the layer
for component in self.components:
if set([layer.ID for layer in component.layers]) == set(layer_to_delete.ID):
if {[layer.ID for layer in component.layers]} == set(layer_to_delete.ID):
self.remove_component(component.ID)
else:
warn(
Expand Down Expand Up @@ -429,7 +429,8 @@ def merge_netlist(self, netlist: Device) -> None:
self.add_layer(layer)
layer_mapping[layer] = layer
else:
assert layer.ID is not None
if layer.ID is None:
raise Exception("Layer ID is None, cannot merge the layers")
layer_mapping[layer] = self.get_layer(layer.ID)

for component in netlist.components:
Expand Down Expand Up @@ -634,14 +635,16 @@ def to_parchmint_v1_2(self) -> Dict:
ret["version"] = "1.2"

# Add the valvemap information
valve_map = {}
valve_type_map = {}
valve_objects = []
for valve, connection in self._valve_map.items():
valve_map[valve.ID] = connection.ID
ret["valveMap"] = valve_map
for valve, valve_type in self._valve_type_map.items():
valve_type_map[valve.ID] = str(valve_type)
ret["valveTypeMap"] = valve_type_map
valve_object = {
"componentid": valve.ID,
"connectionid": connection.ID,
"type": str(self._valve_type_map[valve]),
}
valve_objects.append(valve_object)
ret["valves"] = valve_objects

return ret

@staticmethod
Expand Down Expand Up @@ -727,7 +730,7 @@ def from_parchmint_v1(json_data: Dict) -> Device:
# First always add the layers
if "layers" in json_data.keys():
for layer in json_data["layers"]:
device_ref.add_layer(Layer(layer))
device_ref.add_layer(Layer(json_data=layer))
else:
print("no layers found")

Expand Down Expand Up @@ -799,10 +802,16 @@ def from_parchmint_v1_2(json_data: Dict) -> Device:
# First always add the layers
if "layers" in json_data.keys():
for layer in json_data["layers"]:
device_ref.add_layer(Layer(layer))
device_ref.add_layer(Layer(json_data=layer))
else:
print("no layers found")

# Second add all the features
if "features" in json_data.keys():
for feature_json in json_data["features"]:
feature = Feature.from_parchmint_v1_2(feature_json, device_ref)
device_ref.add_feature(feature)

# Loop through the components
if "components" in json_data.keys():
for component_json in json_data["components"]:
Expand All @@ -829,23 +838,28 @@ def from_parchmint_v1_2(json_data: Dict) -> Device:
else:
print("no params found")

def get_valve_type(value: str):
if value is ValveType.NORMALLY_OPEN:
def get_valve_type(value: str) -> ValveType:
if value == ValveType.NORMALLY_OPEN:
return ValveType.NORMALLY_OPEN
elif value is ValveType.NORMALLY_CLOSED:
elif value == ValveType.NORMALLY_CLOSED:
return ValveType.NORMALLY_CLOSED
else:
raise Exception("Unknown valve type {}".format(value))

if "valveMap" in json_data.keys():
valve_map = json_data["valveMap"]
valve_type_map = json_data["valveTypeMap"]
if "valves" in json_data.keys():
valve_objects = json_data["valves"]

for key, value in valve_map.items():
for valve_object in valve_objects:
componentid = valve_object["componentid"]
connectionid = valve_object["connectionid"]
# Note - Sets it to default normally open if nothign is specified
valve_type = valve_object["type"] if "type" in valve_object else None
device_ref.map_valve(
device_ref.get_component(key),
device_ref.get_connection(value),
get_valve_type(valve_type_map[key]),
device_ref.get_component(componentid),
device_ref.get_connection(connectionid),
get_valve_type(valve_type)
if valve_type is not None
else ValveType.NORMALLY_OPEN,
)

return device_ref
44 changes: 35 additions & 9 deletions parchmint/layer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional
from typing import Dict, Optional

from parchmint.params import Params

Expand All @@ -9,17 +9,25 @@ class Layer:
Used to define a layer object that can be used in the device model.
"""

def __init__(self, json_data=None) -> None:
def __init__(
self,
layer_id: Optional[str] = None,
name: Optional[str] = None,
layer_type: Optional[str] = None,
group: Optional[str] = None,
params: Optional[Params] = None,
json_data: Optional[Dict] = None,
) -> None:
"""Creates a new instance Layer
Args:
json (dict, optional): json dict after json.loads(). Defaults to None.
"""
self._id: str = ""
self.name: str = ""
self.type: str = ""
self.group: str = ""
self.params: Params = Params()
self._id: str = "" if layer_id is None else layer_id
self.name: str = "" if name is None else name
self.layertype: str = "" if layer_type is None else layer_type
self.group: str = "" if group is None else group
self.params: Params = Params() if params is None else params

if json_data:
self.parse_from_json(json_data)
Expand All @@ -45,6 +53,24 @@ def ID(self, value: str) -> None:
"""
self._id = value

@property
def layer_type(self) -> str:
"""Returns the layer type
Returns:
str: layer type
"""
return self.layertype

@layer_type.setter
def layer_type(self, value: str) -> None:
"""Sets the layer type
Args:
value (str): layer type
"""
self.layertype = value

def parse_from_json(self, json_data):
"""Loads instance data json dict from json.loads()
Expand All @@ -53,7 +79,7 @@ def parse_from_json(self, json_data):
"""
self.name = json_data["name"]
self.ID = json_data["id"]
self.type = json_data["type"]
self.layertype = json_data["type"]
self.group = json_data["group"]
self.params = Params(json_data["params"])

Expand All @@ -66,7 +92,7 @@ def to_parchmint_v1(self):
return {
"name": self.name,
"id": self.ID,
"type": self.type,
"type": self.layertype,
"params": self.params.to_parchmint_v1(),
"group": self.group,
}
Expand Down
2 changes: 1 addition & 1 deletion parchmint/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def __init__(
layer: Optional[str] = None,
x: float = -1,
y: float = -1,
json_data: Dict = {},
json_data: Optional[Dict] = None,
):
"""Creates a ComponentPort which is used to represent the points
where a connection connects on the component
Expand Down
2 changes: 1 addition & 1 deletion parchmint/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def __init__(
self,
component_id: Optional[str] = None,
port: Optional[str] = None,
json_data: Dict = {},
json_data: Optional[Dict] = None,
):
"""Creates a Target object that describes where the connection will connect to
Expand Down

0 comments on commit f9b977f

Please sign in to comment.