11import copy
22
33import gdsfactory as gf
4+ from gdsfactory .technology .layer_stack import DerivedLayer , LayerLevel
5+ from gdsfactory .typings import Port
46import klayout .db as kdb
5- from gdsfactory import Component
7+ from gdsfactory import Component , LayerEnum
68from gdsfactory .technology import LayerStack , LogicalLayer
79
810
@@ -25,7 +27,9 @@ def get_component_layer_stack(
2527 layernames_dict = new_layer_stack .get_layer_to_layername ()
2628 layernames_present = [
2729 name
28- for sublist in [layernames_dict [LogicalLayer (layer = layer )] for layer in layers_present ]
30+ for sublist in [
31+ layernames_dict [LogicalLayer (layer = layer )] for layer in layers_present
32+ ]
2933 for name in sublist
3034 ]
3135 for key in list (new_layer_stack .layers .keys ()):
@@ -35,6 +39,43 @@ def get_component_layer_stack(
3539 return new_layer_stack
3640
3741
42+ def compare_layerlevel_and_port_layers (layer_level : LayerLevel , port : Port ) -> bool :
43+ """Compare the layer information between a :class:`~LayerLevel` and a :class:`~Port`.
44+
45+ Note:
46+ If ``layer_level.layer`` is :class:`~LogicalLayer`, ``layer_level.layer`` is used.
47+ If ``layer_level.layer`` is :class:`~DerivedLayer`, ``layer_level.derived_layer`` is used.
48+
49+ Args:
50+ layer_level: The LayerLevel object containing layer information
51+ port: The Port object containing layer_info with layer and datatype
52+
53+ Returns:
54+ bool: True if the layer and datatype match between both objects
55+ """
56+
57+ port_layer_tuple = (
58+ port .layer_info .layer ,
59+ port .layer_info .datatype ,
60+ )
61+
62+ is_derived_layer = isinstance (layer_level .layer , DerivedLayer )
63+ if is_derived_layer :
64+ layer_level_tuple = (layer_level .derived_layer .layer .layer , layer_level .derived_layer .layer .datatype )
65+ return layer_level_tuple == port_layer_tuple
66+
67+ layer_enum_or_tuple = layer_level .layer .layer
68+ if isinstance (layer_enum_or_tuple , tuple ):
69+ layer_level_tuple = layer_enum_or_tuple
70+ else :
71+ layer_level_tuple = (
72+ layer_enum_or_tuple .layer ,
73+ layer_enum_or_tuple .datatype ,
74+ )
75+
76+ return layer_level_tuple == port_layer_tuple
77+
78+
3879def get_component_with_net_layers (
3980 component : Component ,
4081 layer_stack : LayerStack ,
@@ -56,57 +97,78 @@ def get_component_with_net_layers(
5697 new_layers_init: initial layer number for the temporary new layers.
5798 add_to_layerstack: True by default, but can be set to False to disable parsing of the layerstack.
5899 """
59- # return NotImplementedError(
60- # "Meshing component with net layers not implemented in gdsfactory8 yet."
61- # )
62100
63101 # Initialize returned component
64102 net_component = component .copy ()
65103
104+ new_layerlevels = []
66105 # For each port to consider, convert relevant polygons
67- for i , portname in enumerate (port_names ):
68- port = component .ports [portname ]
106+ for i , port_name in enumerate (port_names ):
107+ port = component .ports [port_name ]
69108 # Get original port layer polygons, and modify a new component without that layer
70109 polygons = (
71110 net_component .extract (layers = (port .layer ,))
72111 .get_polygons ()
73112 .get (port .layer , [])
74113 )
75- net_component = net_component .remove_layers (layers = (port .layer ,),recursive = False )
114+ net_component = net_component .remove_layers (
115+ layers = (port .layer ,), recursive = False
116+ )
76117 for polygon in polygons :
77118 # If polygon belongs to port, create a unique new layer, and add the polygon to it
78119 if polygon .sized (int (3 * gf .kcl .dbu )).inside (
79120 kdb .Point (* port .to_itype ().center )
80121 ):
81- # if gdstk.inside(
82- # [port.center],
83- # gdstk.offset(gdstk.Polygon(polygon), gf.get_active_pdk().grid_size),
84- # )[0]:
85122 try :
86- port_layernames = layer_stack .get_layer_to_layername ()[
87- LogicalLayer (layer = port .layer )
123+ derived_layerlevels_touching_port = [
124+ e
125+ for e in layer_stack .layers .values ()
126+ if e .derived_layer is not None
127+ and e not in new_layerlevels
128+ and compare_layerlevel_and_port_layers (e , port )
88129 ]
130+ logical_layerlevels_touching_port = [
131+ e
132+ for e in layer_stack .layers .values ()
133+ if not isinstance (
134+ e .layer , gf .technology .layer_stack .DerivedLayer
135+ )
136+ and e not in new_layerlevels
137+ and compare_layerlevel_and_port_layers (e , port )
138+ ]
139+
140+ layerlevels_touching_port = (
141+ derived_layerlevels_touching_port
142+ + logical_layerlevels_touching_port
143+ )
89144 except KeyError as e :
90145 raise KeyError (
91146 "Make sure your `layer_stack` contains all layers with ports"
92147 ) from e
93- for j , old_layername in enumerate (port_layernames ):
148+
149+ for j , old_layerlevel in enumerate (layerlevels_touching_port ):
94150 new_layer_number = (
95151 new_layers_init [0 ] + i ,
96152 new_layers_init [1 ] + j ,
97153 )
98154 if add_to_layerstack :
99- new_layer = copy .deepcopy (layer_stack .layers [old_layername ])
100- new_layer .layer = LogicalLayer (
155+ # new_layer = copy.deepcopy(layer_stack.layers[old_layerlevel])
156+ new_layerlevel = copy .deepcopy (old_layerlevel )
157+ new_layerlevel .layer = LogicalLayer (
101158 layer = (
102159 new_layers_init [0 ] + i ,
103160 new_layers_init [1 ] + j ,
104161 )
105162 )
106- new_layer .name = f"{ old_layername } { delimiter } { portname } "
107- layer_stack .layers [f"{ old_layername } { delimiter } { portname } " ] = (
108- new_layer
163+ new_layerlevel .name = (
164+ f"{ old_layerlevel .name } { delimiter } { port_name } "
109165 )
166+ # Increase mesh order to ensure new layer is on top old
167+ new_layerlevel .mesh_order = old_layerlevel .mesh_order - 1
168+ layer_stack .layers [
169+ f"{ old_layerlevel .name } { delimiter } { port_name } "
170+ ] = new_layerlevel
171+ new_layerlevels .append (new_layerlevel )
110172 net_component .add_polygon (polygon , layer = new_layer_number )
111173 # Otherwise put the polygon back on the same layer
112174 else :
0 commit comments