multiport-interferometer 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+
2
+ from .functions import sdict_to_matrix, bell_circuit_schematic, decom_to_model
3
+ from .ideal_models import ideal_bell_models, ideal_clements_tbu_model, ideal_mzi, ideal_phaseshifter, ideal_waveguide
4
+ from .bell_decomposer import decompose_bell
5
+ from .bell_class import Bell
6
+ from .clements_class import Clements
7
+ from .bell_models import phase_shifter_model, edge_phaser_model, mzi_model, calibrated_mzi_model, plain_wvgd_model
@@ -0,0 +1,324 @@
1
+ '''
2
+ Copyright 2026 Carl Abi Nakad
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ '''
16
+
17
+ from . import bell_components
18
+ from . import bell_decomposer
19
+ from . import functions as f
20
+ import sax
21
+ import numpy as np
22
+ try:
23
+ from . import bell_models
24
+ except ImportError:
25
+ bell_models=None
26
+ import gdsfactory as gf
27
+
28
+ class Bell:
29
+ def __init__(self, dimension):
30
+ if not isinstance(dimension, int) or dimension < 2:
31
+ raise ValueError("Dimension must be an integer >= 2")
32
+ self.dimension = dimension
33
+ self.components = self.load_components() #dictionaro of components
34
+ self.gds_component, self.sax_netlist = self.build()
35
+ if bell_models is not None:
36
+ self.models = self.load_models()
37
+ self.phase_offset = bell_models.phase_offset
38
+ self.phase_step = bell_models.phase_step
39
+ else:
40
+ self.models = None
41
+ print("No models.py found. SAX models were not loaded.")
42
+
43
+ def gds(self):
44
+ return self.gds_component
45
+
46
+ def load_components(self):
47
+ return {"tbu":bell_components.tbu,
48
+ "phase_shifter": bell_components.phase_shifter,
49
+ "edge_phase_shifter": bell_components.edge_phase_shifter,
50
+ "waveguide": bell_components.plain_wvgd,
51
+ "edge_waveguide":bell_components.edge_wvgd
52
+ }
53
+
54
+ def load_models(self):
55
+ return {"tbu_model":bell_models.tbu_model,
56
+ "phase_shifter_model": bell_models.phase_shifter_model,
57
+ "edge_phase_shifter_model": bell_models.edge_phase_shifter_model,
58
+ "plain_wvgd_model": bell_models.plain_wvgd_model}
59
+
60
+ def emulate(self, target):
61
+ if np.shape(target)[0] != self.dimension:
62
+ raise ValueError("Target matrix incompatible with Interferometer Dimension")
63
+ decom = bell_decomposer.decompose_bell(target)
64
+ self.values = f.decom_to_model(self.models,decom)
65
+ circuit, info = sax.circuit(netlist=self.sax_netlist, models = self.values)
66
+ S = circuit()
67
+ return S
68
+ def phase_corrected(self, S):
69
+ correction = self.phase_offset + (self.dimension-2)*self.phase_step
70
+ Smat = f.sdict_to_matrix(S)*np.exp(-1j*correction)
71
+ return Smat
72
+
73
+ def build(self):
74
+ bell_components._check_pdk()
75
+ dim = self.dimension
76
+ c = gf.Component()
77
+ mzi_cell = self.components["tbu"]()
78
+ phaser_cell = self.components["phase_shifter"]()
79
+ edge_phaser_cell = self.components["edge_phase_shifter"]()
80
+ plain_wvgd = self.components["waveguide"]()
81
+ edge_wvgd = self.components["edge_waveguide"]()
82
+
83
+ last = dim-2
84
+ end = dim-1
85
+
86
+ instances = {}
87
+ connections = {}
88
+ ports = {}
89
+
90
+ phase_i = [None]*dim
91
+ phase_o = [None]*dim
92
+ phasers = {}
93
+ mzms = {}
94
+ wvgds = {}
95
+
96
+ # creating top boundary connector waveguides
97
+ for j in range(1, dim, 2):
98
+ wvgds[(j)] = c<<plain_wvgd
99
+ instances[f"wvgd_{j}"] = "wvgd"
100
+
101
+ # creating bottom boundary phase shifters
102
+ if dim % 2 == 0:
103
+ for j in range(1, dim, 2):
104
+ phasers[(end, j)] = c << phaser_cell
105
+ instances[f"phaser_{end}_{j}"] = f"phaser_{end}_{j}"
106
+ else:
107
+ for j in range(0, dim, 2):
108
+ phasers[(end, j)] = c << phaser_cell
109
+ instances[f"phaser_{end}_{j}"] = f"phaser_{end}_{j}"
110
+
111
+ # creating input and output edge phase shifters
112
+ if dim%2!=0:
113
+ for i in range(0,dim,2):
114
+ if i>0:
115
+ phaser_o = c << edge_phaser_cell
116
+ phaser_o.mirror_x()
117
+ phase_o[i-1] = phaser_o
118
+ phase_i[i-1] = c<<edge_wvgd
119
+ instances[f"phaser_o{i-1}"] = f"phaser_o{i-1}"
120
+ instances[f"phaser_i{i-1}"] = f"phaser_i{i-1}"
121
+ if i<dim-1:
122
+ phaser_i = c << edge_phaser_cell
123
+ phase_i[i] = phaser_i
124
+ phase_o[i] = c<<edge_wvgd
125
+ instances[f"phaser_i{i}"] = f"phaser_i{i}"
126
+ instances[f"phaser_o{i}"] = f"phaser_o{i}"
127
+ else:
128
+ phase_i[i] = c<<edge_wvgd
129
+ phase_o[i] = c<<edge_wvgd
130
+ instances[f"phaser_i{i}"] = f"phaser_i{i}"
131
+ instances[f"phaser_o{i}"] = f"phaser_o{i}"
132
+ else:
133
+ for i in range(dim):
134
+ if i%2==0:
135
+ if i<dim:
136
+ phaser_i =c<<edge_phaser_cell
137
+ phase_i[i] = phaser_i
138
+ phaser_o = c<<edge_phaser_cell
139
+ phase_o[i] = phaser_o
140
+ instances[f"phaser_i{i}"] = f"phaser_i{i}"
141
+ instances[f"phaser_o{i}"] = f"phaser_o{i}"
142
+ else:
143
+ phase_i[i] = c<<edge_wvgd
144
+ phase_o[i] = c<<edge_wvgd
145
+ instances[f"phaser_i{i}"] = f"phaser_i{i}"
146
+ instances[f"phaser_o{i}"] = f"phaser_o{i}"
147
+ else:
148
+ phase_i[i] = c<<edge_wvgd
149
+ phase_o[i] = c<<edge_wvgd
150
+ instances[f"phaser_i{i}"] = f"phaser_i{i}"
151
+ instances[f"phaser_o{i}"] = f"phaser_o{i}"
152
+
153
+ # creating top and bottom mzis
154
+ for i in range(0, dim, 2):
155
+ # top mode mzis
156
+ mzm_top = c << mzi_cell
157
+ mzms[f"(0_{i})"] = mzm_top
158
+ instances[f"mzm_0_{i}"] = f"mzm_0_{i}"
159
+ if dim % 2 == 0: # even bottom mode mzis
160
+ mzm_bottom = c << mzi_cell
161
+ mzms[f"({last}_{i})"] = mzm_bottom
162
+ instances[f"mzm_{last}_{i}"] = f"mzm_{last}_{i}"
163
+ else: # odd bottom mode mzis
164
+ j = i + 1
165
+ if j > end:
166
+ continue
167
+ mzm_bottom = c << mzi_cell
168
+ mzms[f"({last}_{j})"] = mzm_bottom
169
+ instances[f"mzm_{last}_{j}"] = f"mzm_{last}_{j}"
170
+
171
+ # create middle mzis
172
+ for i in range(1, last):
173
+ if i % 2 == 0:
174
+ for j in np.arange(0, dim, 2):
175
+ mzm = c << mzi_cell
176
+ mzms[f"({i}_{j})"] = mzm
177
+ instances[f"mzm_{i}_{j}"] = f"mzm_{i}_{j}"
178
+ else:
179
+ for j in range(1, dim, 2):
180
+ mzm = c << mzi_cell
181
+ mzms[f"({i}_{j})"] = mzm
182
+ instances[f"mzm_{i}_{j}"] = f"mzm_{i}_{j}"
183
+
184
+ # Connecting Mesh
185
+ for i in range(dim):
186
+
187
+ # Top boundary Connections
188
+ if i == 0:
189
+ if dim % 2 == 0:
190
+ for j in range(0, dim - 2, 2):
191
+ p = wvgds[(j+1)]
192
+ p.connect("o1",mzms[f"({i}_{j})"].ports["o3"])
193
+ mzms[f"({i}_{j+2})"].connect("o2",p.ports["o2"])
194
+ connections[f"mzm_{i}_{j},out0"] = f"wvgd_{j+1},in0"
195
+ connections[f"wvgd_{j+1},out0"] = f"mzm_{i}_{j+2},in0"
196
+ p = wvgds[(end)]
197
+ p.connect("o1",mzms[f"({i}_{dim-2})"].ports["o3"])
198
+ connections[f"mzm_{i}_{dim-2},out0"] =f"wvgd_{end},in0"
199
+ else:
200
+ for j in range(0, dim - 2, 2):
201
+ p = wvgds[(j+1)]
202
+ if j < last:
203
+ p.connect("o1",mzms[f"({i}_{j})"].ports["o3"])
204
+ connections[f"mzm_{i}_{j},out0"] =f"wvgd_{j+1},in0"
205
+ if f"({i}_{j+2})" in mzms:
206
+ mzms[f"({i}_{j+2})"].connect("o2",p.ports["o2"])
207
+ connections[f"wvgd_{j+1},out0"] = f"mzm_{i}_{j+2},in0"
208
+
209
+ # Connecting diagonal mzis
210
+ for j in range(dim):
211
+ key = f"({i}_{j})"
212
+ if key not in mzms:
213
+ continue
214
+ #up-right connection
215
+ if i > 0:
216
+ upper_right = f"({i-1}_{j+1})"
217
+ if upper_right in mzms:
218
+ mzms[key].connect("o3",mzms[upper_right].ports["o1"])
219
+ connections[f"mzm_{i}_{j},out0"] = f"mzm_{i-1}_{j+1},in1"
220
+ # downward-right connection
221
+ target = f"({i+1}_{j+1})"
222
+ if target in mzms:
223
+ mzms[target].connect("o2", mzms[key].ports["o4"])
224
+ connections[f"mzm_{i}_{j},out1"] = f"mzm_{i+1}_{j+1},in0"
225
+
226
+ # bottom boundary connections
227
+ if i == last:
228
+ if dim % 2 == 0:
229
+ for j in range(1, last, 2):
230
+ p = phasers[(end, j)]
231
+ p.connect("o1", mzms[f"({i}_{j-1})"].ports["o4"])
232
+ p.connect("o2", mzms[f"({i}_{j+1})"].ports["o1"])
233
+ connections[f"mzm_{i}_{j-1},out1"] = f"phaser_{end}_{j},in0"
234
+ connections[f"phaser_{end}_{j},out0"] = f"mzm_{i}_{j+1},in1"
235
+ # last bottom phaser
236
+ p = phasers[(end, end)]
237
+ p.connect("o1", mzms[f"({last}_{last})"].ports["o4"])
238
+ connections[f"mzm_{last}_{last},out1"] = f"phaser_{end}_{end},in0"
239
+ else:
240
+ # first bottom phaser
241
+ p = phasers[(end, 0)]
242
+ p.connect("o2", mzms[f"({last}_1)"].ports["o1"])
243
+ connections[f"phaser_{end}_0,out0"] = f"mzm_{last}_1,in1"
244
+
245
+ # last bottom phaser
246
+ p = phasers[(end, end)]
247
+ p.connect("o1",mzms[f"({last}_{last})"].ports["o4"])
248
+ connections[f"mzm_{last}_{last},out1"] = f"phaser_{end}_{end},in0"
249
+
250
+ # intermediate bottom phasers
251
+ for j in range(2, last, 2):
252
+ p = phasers[(end, j)]
253
+ p.connect("o1",mzms[f"({i}_{j-1})"].ports["o4"])
254
+ connections[f"mzm_{i}_{j-1},out1"] = f"phaser_{end}_{j},in0"
255
+ p.connect("o2",mzms[f"({i}_{j+1})"].ports["o1"])
256
+ connections[f"phaser_{end}_{j},out0"] = f"mzm_{i}_{j+1},in1"
257
+
258
+ # connecting input phaseshifters
259
+ for i in range(0, dim - 1, 2):
260
+ phase_i[i].connect("o2",mzms[f"({i}_0)"].ports["o2"])
261
+ connections[f"phaser_i{i},out0"] = f"mzm_{i}_0,in0" #these are sax connections, port naming is swapped with the gds naming because sax component models using standard matrix convention
262
+ phase_i[i+1].connect("o2",mzms[f"({i}_0)"].ports["o1"])
263
+ connections[f"phaser_i{i+1},out0"] = f"mzm_{i}_0,in1"
264
+ c.add_port(f"in{i}",port=phase_i[i].ports["o1"])
265
+ ports[f"in{i}"] = f"phaser_i{i},in0"
266
+ c.add_port(f"in{i+1}",port=phase_i[i+1].ports["o1"])
267
+ ports[f"in{i+1}"] = f"phaser_i{i+1},in0"
268
+
269
+ # odd final input phaseshifter
270
+ if dim % 2 != 0:
271
+ phase_i[end].connect("o2",phasers[(end, 0)].ports["o1"])
272
+ connections[f"phaser_i{end},out0"] = f"phaser_{end}_0,in0"
273
+ c.add_port(f"in{end}",port=phase_i[end].ports["o1"])
274
+ ports[f"in{end}"] = f"phaser_i{end},in0"
275
+
276
+ # Connecting output phase shifters - Even
277
+ if dim % 2 == 0:
278
+ # top mode
279
+ phase_o[0].connect("o2",wvgds[(end)].ports["o2"])
280
+ connections[f"wvgd_{end},out0"] = "phaser_o0,in0"
281
+ c.add_port("out0",port=phase_o[0].ports["o1"])
282
+ ports["out0"] = "phaser_o0,out0"
283
+
284
+ # middle modes
285
+ for i in range(1, end, 2):
286
+ phase_o[i].connect("o2",mzms[f"({i}_{end})"].ports["o3"])
287
+ phase_o[i+1].connect("o2",mzms[f"({i}_{end})"].ports["o4"])
288
+ connections[f"mzm_{i}_{end},out0"] = f"phaser_o{i},in0"
289
+ connections[f"mzm_{i}_{end},out1"] = f"phaser_o{i+1},in0"
290
+ c.add_port(f"out{i}",port=phase_o[i].ports["o1"])
291
+ c.add_port(f"out{i+1}",port=phase_o[i+1].ports["o1"])
292
+ ports[f"out{i}"] = f"phaser_o{i},out0"
293
+ ports[f"out{i+1}"] = f"phaser_o{i+1},out0"
294
+
295
+ # bottom mode
296
+ phase_o[end].connect("o2", phasers[(end, end)].ports["o2"])
297
+ connections[f"phaser_{end}_{end},out0"] = f"phaser_o{end},in0"
298
+ c.add_port(f"out{end}", port=phase_o[end].ports["o1"])
299
+ ports[f"out{end}"] = f"phaser_o{end},out0"
300
+
301
+ # Connecting output phase shifters - Even
302
+ else:
303
+ output_col = end
304
+ for i in range(0, dim - 1, 2):
305
+ phase_o[i].connect("o2", mzms[f"({i}_{output_col})"].ports["o3"])
306
+ connections[f"mzm_{i}_{output_col},out0"] = f"phaser_o{i},in0"
307
+ phase_o[i+1].connect("o2", mzms[f"({i}_{output_col})"].ports["o4"])
308
+ connections[f"mzm_{i}_{output_col},out1"] = f"phaser_o{i+1},in0"
309
+ c.add_port(f"out{i}", port=phase_o[i].ports["o1"])
310
+ ports[f"out{i}"] = f"phaser_o{i},out0"
311
+ c.add_port(f"out{i+1}", port=phase_o[i+1].ports["o1"])
312
+ ports[f"out{i+1}"] = f"phaser_o{i+1},out0"
313
+
314
+ # bottom mode
315
+ phase_o[end].connect("o2", phasers[(end, end)].ports["o2"])
316
+ connections[f"phaser_{end}_{end},out0"] = f"phaser_o{end},in0"
317
+ c.add_port(f"out{end}", port=phase_o[end].ports["o1"])
318
+ ports[f"out{end}"] = f"phaser_o{end},out0"
319
+
320
+ netlist = {}
321
+ netlist["instances"]=instances
322
+ netlist["connections"]=connections
323
+ netlist["ports"]=ports
324
+ return c, netlist
@@ -0,0 +1,219 @@
1
+ '''
2
+ File of my custom gdsfactory component functions to be used in the project
3
+ '''
4
+
5
+ import gdsfactory as gf
6
+ import uuid
7
+
8
+ # I use the Si 220 cband pdk from cornerstone
9
+ from cspdk.si220.cband import cells, PDK, LAYER_STACK
10
+
11
+ def activate_pdk():
12
+ PDK.activate()
13
+
14
+ def _check_pdk():
15
+ if gf.get_active_pdk().name != PDK.name:
16
+ raise RuntimeError("Activate the Cornerstone Si220 C-band PDK first.")
17
+
18
+ '''
19
+ The circuit requires the 4 component names:
20
+ '''
21
+ def tbu():
22
+ return mzi()
23
+ def phase_shifter():
24
+ return phaser()
25
+ def edge_phase_shifter():
26
+ return edge_phaser()
27
+ def plain_wvgd():
28
+ return plain()
29
+ #def edge_wvgd(): already exists with correct name
30
+
31
+ '''
32
+ the actual gdscomponents:
33
+ '''
34
+
35
+ phaser_len = 150
36
+
37
+ @gf.cell
38
+ def s_bend():
39
+ c = gf.Component()
40
+ bend = cells.bend_euler()
41
+ up = c << bend
42
+ down = c<< bend
43
+ up.rotate(90)
44
+ down.rotate(-90)
45
+ down.connect("o1", up.ports["o1"])
46
+ c.add_port("o1", port=up.ports["o2"])
47
+ c.add_port("o2", port = down.ports["o2"])
48
+ return c
49
+
50
+ @gf.cell
51
+ def mzi():
52
+ c = gf.Component()
53
+ coupler = cells.coupler()
54
+ phaser = cells.straight_heater_metal(length = phaser_len)
55
+ bend = s_bend()
56
+ i_up = c<<bend
57
+ i_down = c<<bend
58
+ i_down.mirror()
59
+ o_up = c << bend
60
+ o_down = c<<bend
61
+ o_up.mirror()
62
+ top = c<<phaser
63
+ bottom = c<<phaser
64
+ top_left= c<<bend
65
+ top_left.mirror()
66
+ top_right = c<<bend
67
+ bottom_left = c<<bend
68
+ bottom_right = c<<bend
69
+ bottom_right.mirror()
70
+ coupler1 = c<<coupler
71
+ coupler2 = c<<coupler
72
+ i_down.connect("o1", coupler1.ports["o1"])
73
+ i_up.connect("o1", coupler1.ports["o2"])
74
+ top_left.connect("o1", coupler1.ports["o3"])
75
+ bottom_left.connect("o1", coupler1.ports["o4"])
76
+ top.connect("o1", top_left["o2"])
77
+ bottom.connect("o1", bottom_left["o2"])
78
+ top_right.connect("o1", top['o2'])
79
+ bottom_right.connect("o1", bottom['o2'])
80
+ coupler2.connect("o1", bottom_right["o2"])
81
+ coupler2.connect("o2", top_right["o2"])
82
+ o_up.connect('o1', coupler2["o3"])
83
+ o_down.connect('o1', coupler2["o4"])
84
+ c.add_port(name="o1", port=i_down['o2'])
85
+ c.add_port(name = 'o2', port=i_up['o2'])
86
+ c.add_port(name = 'o3', port=o_up['o2'])
87
+ c.add_port(name = 'o4', port=o_down['o2'])
88
+ return c
89
+
90
+ @gf.cell
91
+ def edge_phaser(phase_len=phaser_len):
92
+ c = gf.Component()
93
+ wvgd = cells.straight(cross_section="strip")
94
+ phaser = cells.straight_heater_metal(length= phase_len)
95
+ w = c<<wvgd
96
+ p = c<<phaser
97
+ p.connect("o1", w["o2"])
98
+ c.add_port(name="o1", port = w["o1"])
99
+ c.add_port(name = "o2", port=p["o2"])
100
+ return c
101
+
102
+ @gf.cell
103
+ def edge_wvgd(phase_len=phaser_len):
104
+ c = gf.Component()
105
+ wvgd1 = cells.straight(cross_section="strip")
106
+ wvgd2 = cells.straight(length= phase_len)
107
+ w1 = c<<wvgd1
108
+ w2 = c<<wvgd2
109
+ w2.connect("o1", w1["o2"])
110
+ c.add_port(name="o1", port = w1["o1"])
111
+ c.add_port(name = "o2", port=w2["o2"])
112
+ return c
113
+
114
+ def coupler_single_arm(keep="top"):
115
+ c = gf.Component(f"coupler_single_arm_{keep}_{uuid.uuid4().hex[:6]}")
116
+
117
+ cp = cells.coupler()
118
+ cp = cp.copy()
119
+ cp.flatten()
120
+
121
+ WG_LAYER = gf.get_active_pdk().layers.WG
122
+ wg = cp.extract(layers=[WG_LAYER])
123
+
124
+ bbox = wg.bbox()
125
+ xmin = bbox.left
126
+ xmax = bbox.right
127
+ ymin = bbox.bottom
128
+ ymax = bbox.top
129
+ ymid = (ymin + ymax) / 2
130
+
131
+ if keep == "top":
132
+ y0 = ymid
133
+ height = ymax - ymid
134
+ else:
135
+ y0 = ymin
136
+ height = ymid - ymin
137
+
138
+ clip = gf.components.rectangle(
139
+ size=(xmax - xmin, height),
140
+ layer=WG_LAYER,
141
+ )
142
+
143
+ clip_component = gf.Component(f"clip_{uuid.uuid4().hex[:6]}")
144
+ r = clip_component << clip
145
+ r.move((xmin, y0))
146
+
147
+ arm = gf.boolean(
148
+ A=wg,
149
+ B=clip_component,
150
+ operation="and",
151
+ layer=WG_LAYER,
152
+ )
153
+
154
+ c << arm
155
+
156
+ cp_original = cells.coupler()
157
+ cp_ports = list(cp_original.ports)
158
+
159
+ if keep == "top":
160
+ selected_ports = [p for p in cp_ports if p.center[1] > ymid]
161
+ else:
162
+ selected_ports = [p for p in cp_ports if p.center[1] < ymid]
163
+
164
+ selected_ports = sorted(selected_ports, key=lambda p: p.center[0])
165
+
166
+ c.add_port(name="o1", port=selected_ports[0])
167
+ c.add_port(name="o2", port=selected_ports[1])
168
+
169
+ return c
170
+
171
+ @gf.cell
172
+ def phaser(phase_len=phaser_len):
173
+ c = gf.Component()
174
+ bottom = coupler_single_arm("bottom")
175
+ bend = s_bend()
176
+ phase_shift = cells.straight_heater_metal(length =phase_len)
177
+ i = c<<bend
178
+ o = c<<bend
179
+ o.mirror()
180
+ left = c<<bend
181
+ left.mirror()
182
+ right = c<<bend
183
+ s1 = c<<bottom
184
+ s2 = c<<bottom
185
+ phaser = c<<phase_shift
186
+ s1.connect("o1", i["o2"])
187
+ left.connect("o1", s1['o2'])
188
+ phaser.connect("o1", left['o2'])
189
+ right.connect('o1', phaser['o2'])
190
+ s2.connect('o1', right['o2'])
191
+ o.connect('o1', s2['o2'])
192
+ c.add_port(name='o1', port=i['o1'])
193
+ c.add_port(name = 'o2', port=o['o2'])
194
+ return c
195
+
196
+ @gf.cell
197
+ def plain(lent=phaser_len):
198
+ c = gf.Component()
199
+ bottom = coupler_single_arm("bottom")
200
+ bend = s_bend()
201
+ straight = cells.straight(length =lent)
202
+ i = c<<bend
203
+ o = c<<bend
204
+ o.mirror()
205
+ left = c<<bend
206
+ left.mirror()
207
+ right = c<<bend
208
+ s1 = c<<bottom
209
+ s2 = c<<bottom
210
+ wvgd = c<<straight
211
+ s1.connect("o1", i["o2"])
212
+ left.connect("o1", s1['o2'])
213
+ wvgd.connect("o1", left['o2'])
214
+ right.connect('o1', wvgd['o2'])
215
+ s2.connect('o1', right['o2'])
216
+ o.connect('o1', s2['o2'])
217
+ c.add_port(name='o1', port=i['o1'])
218
+ c.add_port(name = 'o2', port=o['o2'])
219
+ return c