Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve reference naming #624

Merged
merged 3 commits into from
Aug 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 0 additions & 9 deletions gdsfactory/cell.py
Expand Up @@ -211,15 +211,6 @@ def _cell(*args, **kwargs):
if flatten:
component = component.flatten()

invalid_aliases = [
alias
for alias, ref in component.aliases.items()
if ref not in component.references
]

for i in invalid_aliases:
component.aliases.pop(i)

component.lock()
CACHE[name] = component
return component
Expand Down
66 changes: 40 additions & 26 deletions gdsfactory/component.py
Expand Up @@ -116,7 +116,6 @@ def __init__(
) -> None:
"""Initialize the Component object."""
self.__ports__ = {}
self.aliases = {}
self.uid = str(uuid.uuid4())[:8]
if "with_uuid" in kwargs or name == "Unnamed":
name += f"_{self.uid}"
Expand Down Expand Up @@ -168,6 +167,25 @@ def validate(cls, v):
), f"name `{v.name}` {len(v.name)} > {MAX_NAME_LENGTH} "
return v

@property
def named_references(self):
return {ref.name: ref for ref in self.references}

@property
def aliases(self):
warnings.warn(
"aliases attribute has been renamed to named_references and may be deprecated in a future version of gdsfactory",
DeprecationWarning,
)
return self.named_references

@aliases.setter
def aliases(self, value):
warnings.warn(
"Setting aliases is no longer supported. aliases attribute has been renamed to named_references and may be deprecated in a future version of gdsfactory. This operation will have no effect.",
DeprecationWarning,
)

def add_label(
self,
text: str = "hello",
Expand Down Expand Up @@ -444,7 +462,7 @@ def ref_center(self, position=(0, 0)):

def __repr__(self) -> str:
"""Return a string representation of the object."""
return f"{self.name}: uid {self.uid}, ports {list(self.ports.keys())}, aliases {list(self.aliases.keys())}, {len(self.polygons)} polygons, {len(self.references)} references"
return f"{self.name}: uid {self.uid}, ports {list(self.ports.keys())}, references {list(self.named_references.keys())}, {len(self.polygons)} polygons"

def pprint(self) -> None:
"""Prints component info."""
Expand Down Expand Up @@ -730,11 +748,11 @@ def add(self, element) -> None:
"""
self._add(element)
if isinstance(element, (gdspy.CellReference, gdspy.CellArray)):
self._add_alias(element)
self._register_reference(element)
if isinstance(element, Iterable):
for i in element:
if isinstance(i, (gdspy.CellReference, gdspy.CellArray)):
self._add_alias(i)
self._register_reference(i)

def add_array(
self,
Expand Down Expand Up @@ -765,9 +783,7 @@ def add_array(
rows=int(round(rows)),
spacing=spacing,
)
ref.owner = self
self.add(ref) # Add ComponentReference Component
self._add_alias(reference=ref, alias=alias)
return ref

def flatten(self, single_layer: Optional[Tuple[int, int]] = None):
Expand Down Expand Up @@ -805,35 +821,33 @@ def add_ref(
if not isinstance(component, Device):
raise TypeError(f"type = {type(Component)} needs to be a Component.")
ref = ComponentReference(component)
ref.owner = self
self._add(ref)
self._add_alias(reference=ref, alias=alias)
self._register_reference(reference=ref, alias=alias)
return ref

def _add_alias(
def _register_reference(
self, reference: ComponentReference, alias: Optional[str] = None
) -> None:
component = reference.parent
if alias is None:
i = 0
prefix = (
component.settings.function_name
if hasattr(component, "settings")
and hasattr(component.settings, "function_name")
else component.name
)
alias = f"{prefix}_{i}"
reference.owner = self

while alias in self.aliases:
if alias is None:
if reference.name is not None:
alias = reference.name
else:
i = 0
prefix = (
component.settings.function_name
if hasattr(component, "settings")
and hasattr(component.settings, "function_name")
else component.name
)
alias = f"{prefix}_{i}"
i += 1
elif alias in self.aliases:
raise ValueError(
f"{alias} already in {list(self.aliases.keys())} in {self.name}"
)

self.aliases[alias] = reference
reference.alias = alias
while alias in self.named_references:
i += 1
alias = f"{prefix}_{i}"
reference.name = alias

def get_layers(self) -> Union[Set[Tuple[int, int]], Set[Tuple[int64, int64]]]:
"""Return a set of (layer, datatype).
Expand Down
42 changes: 40 additions & 2 deletions gdsfactory/component_reference.py
@@ -1,4 +1,5 @@
import typing
import warnings
from typing import Any, Dict, List, Optional, Tuple, Union, cast

import numpy as np
Expand Down Expand Up @@ -139,8 +140,8 @@ def __init__(
x_reflection=x_reflection,
ignore_missing=False,
)
self.owner = None
self.alias = None
self._owner = None
self._name = None

# The ports of a ComponentReference have their own unique id (uid),
# since two ComponentReferences of the same parent Component can be
Expand All @@ -159,6 +160,43 @@ def parent(self):
def parent(self, value):
self.ref_cell = value

@property
def owner(self):
return self._owner

@owner.setter
def owner(self, value):
if self._owner is None:
self._owner = value
elif value == self._owner:
pass
else:
raise ValueError(
f"Cannot reset owner of a reference once it has already been set! Reference: {self}. Current owner: {self._owner}. Attempting to re-assign to {value}"
)

@property
def name(self):
return self._name

@name.setter
def name(self, value: str):
if value != self._name:
if self.owner:
if value in self.owner.named_references:
raise ValueError(
f"This reference's owner already has a reference with name '{value}'. Please choose another name."
)
self._name = value

@property
def alias(self):
warnings.warn(
"alias attribute is deprecated and may be removed in a future version of gdsfactory",
DeprecationWarning,
)
return self.name

def __repr__(self) -> str:
"""Return a string representation of the object."""
return (
Expand Down
11 changes: 2 additions & 9 deletions gdsfactory/components/component_sequence.py
@@ -1,4 +1,3 @@
from itertools import count
from typing import Dict, Optional, Tuple

import gdsfactory as gf
Expand Down Expand Up @@ -124,19 +123,13 @@ def component_sequence(
while to_rm:
sequence.pop(to_rm.pop())

# To generate unique aliases for each instance
counters = {k: count(start=1) for k in symbol_to_component.keys()}

def _next_id(name) -> str:
return f"{name}{next(counters[name])}"

component = Component()

# Add first component reference and input port
name_start_device, do_flip = _parse_component_name(sequence[0])
_input_device, input_port, prev_port = symbol_to_component[name_start_device]

prev_device = component.add_ref(_input_device, alias=_next_id(name_start_device))
prev_device = component.add_ref(_input_device)

if do_flip:
prev_device = _flip_ref(prev_device, input_port)
Expand All @@ -157,7 +150,7 @@ def _next_id(name) -> str:

component_i, input_port, next_port = symbol_to_component[s]
component_i = gf.get_component(component_i)
ref = component.add_ref(component_i, alias=_next_id(s))
ref = component.add_ref(component_i)

if do_flip:
ref = _flip_ref(ref, input_port)
Expand Down
11 changes: 6 additions & 5 deletions gdsfactory/copy.py
@@ -1,7 +1,7 @@
import copy as python_copy

import gdspy
from phidl.device_layout import CellArray, DeviceReference
from phidl.device_layout import CellArray

from gdsfactory.component import Component, ComponentReference

Expand All @@ -17,7 +17,7 @@ def copy(
D_copy = Component()
D_copy.info = python_copy.deepcopy(D.info)
for ref in D.references:
if isinstance(ref, DeviceReference):
if isinstance(ref, gdspy.CellReference):
new_ref = ComponentReference(
ref.parent,
origin=ref.origin,
Expand All @@ -26,6 +26,7 @@ def copy(
x_reflection=ref.x_reflection,
)
new_ref.owner = D_copy
new_ref.name = ref.name
elif isinstance(ref, gdspy.CellArray):
new_ref = CellArray(
device=ref.parent,
Expand All @@ -37,10 +38,10 @@ def copy(
magnification=ref.magnification,
x_reflection=ref.x_reflection,
)
new_ref.name = ref.name
else:
raise ValueError(f"Got a reference of non-standard type: {type(ref)}")
D_copy.add(new_ref)
for alias_name, alias_ref in D.aliases.items():
if alias_ref == ref:
D_copy.aliases[alias_name] = new_ref

for port in D.ports.values():
D_copy.add_port(port=port)
Expand Down
6 changes: 1 addition & 5 deletions gdsfactory/get_netlist.py
Expand Up @@ -40,7 +40,7 @@ def get_instance_name_from_alias(
component: with labels.
reference: reference that needs naming.
"""
return reference.alias
return reference.name


def get_instance_name_from_label(
Expand All @@ -66,10 +66,6 @@ def get_instance_name_from_label(
# default instance name follows component.aliases
text = clean_name(f"{reference.parent.name}_{x}_{y}")

for alias, ref in component.aliases.items():
if ref == reference:
text = alias

# try to get the instance name from a label
for label in labels:
xl = snap_to_grid(label.position[0])
Expand Down