diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index bda59a47..d8c8bf83 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -9,7 +9,7 @@ jobs: pytest: strategy: matrix: - python-version: [3.5, 3.6, 3.7, 3.8, 3.9] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] fail-fast: false runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index c47d0c83..207953d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 1.6.2 (July 25, 2022) + +### New features +- Addition of `pg.snspd_candelabra()` which creates an optimally-rounded SNSPD with low current crowding and arbtitrarily-high fill factor (thanks Dileep Reddy @dileepvr) +- Lazy loading of `matplotlib`, allowing loading the base phidl libraries much faster (thanks Joaquin Matres @joamatab) + + +### Changes +- Modification to `pg.boolean()` s othat `OR`/union will merge all shapes within one Device, even if the second Device is `None` (thanks +Stijn Balk @sbalk) + +### Bugfixes +- Modifying the `parent` of a `DeviceReference` now correctly updates the reference cell (thanks Joaquin Matres @joamatab) +- Fix bug in `pg.outline()` when `distance < 0` (thanks @yoshi74ls181) +- GDS path objects now copy over when using `pg.import_gds()` (thanks Bas Nijholt @basnijholt) +- Preserve Polygon.properties and DeviceReference.properties when saving and loading (thanks Bas Nijholt @basnijholt) +- `D.remove_layers()` works also with GDS path objects (thanks Joaquin Matres @joamatab) + + ## 1.6.1 (April 7, 2022) ### New features diff --git a/README.md b/README.md index ca103374..eb23e48a 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ GDS scripting for Python that's intuitive, fast, and powerful. - [**Installation / requirements**](#installation--requirements) - [**Tutorial + examples**](https://phidl.readthedocs.io/en/latest/tutorials.html) (or [try an interactive notebook](https://mybinder.org/v2/gh/amccaugh/phidl/master?filepath=phidl_tutorial_example.ipynb)) - [**Geometry library + function documentation**](https://phidl.readthedocs.io/en/latest/geometry_reference.html) -- [Changelog](https://github.com/amccaugh/phidl/blob/master/CHANGELOG.md) (latest update 1.6.1 on April 7, 2022) +- [Changelog](https://github.com/amccaugh/phidl/blob/master/CHANGELOG.md) (latest update 1.6.2 on July 25, 2022) - Huge new routing rewrite for `phidl.routing`, including automatic manhattan routing with custom cross-sections! See [the routing documentation](https://phidl.readthedocs.io/en/latest/tutorials/routing.html) for details. Big thanks to Jeffrey Holzgrafe @jolzgrafe for this contribution - `Path`s can now be used to produce sharp angles, in addition to smooth bends. See [the Path documentation](https://phidl.readthedocs.io/en/latest/tutorials/waveguides.html#Sharp/angular-paths) @@ -30,7 +30,7 @@ If you found PHIDL useful, please consider citing it in (just one!) of your publ # Installation / requirements - Install or upgrade with `pip install -U phidl` -- Python version >=3.5 +- Python version >=3.6 - If you are on Windows or Mac and don't already have `gdspy` installed, you will need a C++ compiler - For Windows + Python 3, install ["Build Tools for Visual Studio"](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) (make sure to check the "C++ build tools" checkbox when installing) - For Mac, install "Xcode" from the App Store, then run the command `xcode-select --install` in the terminal diff --git a/docs/API.rst b/docs/API.rst index 396fba16..21928847 100644 --- a/docs/API.rst +++ b/docs/API.rst @@ -299,6 +299,12 @@ snspd_expanded .. autofunction:: phidl.geometry.snspd_expanded +snspd_candelabra +============== + +.. autofunction:: phidl.geometry.snspd_candelabra + + straight ======== diff --git a/docs/gen_API.py b/docs/gen_API.py index 1b080ec4..5e6e94f4 100644 --- a/docs/gen_API.py +++ b/docs/gen_API.py @@ -62,7 +62,7 @@ class B(*): if os.stat(fwrite).st_size == 0: fw.write( "#" * len(main_header) - + "\n{}\n".format(main_header) + + f"\n{main_header}\n" + "#" * len(main_header) + "\n\n\n" ) @@ -81,7 +81,7 @@ class B(*): fread_header = fread_header.capitalize() fw.write( "*" * (len(fread_header) + len(sub_header)) - + "\n{}{}\n".format(fread_header, sub_header) + + f"\n{fread_header}{sub_header}\n" + "*" * (len(fread_header) + len(sub_header)) + "\n\n" ) @@ -116,14 +116,14 @@ class B(*): fw.write(name[0] + "\n") fw.write(("=" * len(name[0])) + "\n\n") if name[1] == "C": - fw.write(".. autoclass:: phidl.{}.{}\n".format(fread_name, name[0])) + fw.write(f".. autoclass:: phidl.{fread_name}.{name[0]}\n") fw.write( " :members:\n" " :inherited-members:\n" " :show-inheritance:\n\n\n" ) else: - fw.write(".. autofunction:: phidl.{}.{}\n\n\n".format(fread_name, name[0])) + fw.write(f".. autofunction:: phidl.{fread_name}.{name[0]}\n\n\n") fw.close() diff --git a/docs/geometry_reference.ipynb b/docs/geometry_reference.ipynb index 4a26d8e2..2ace70d1 100644 --- a/docs/geometry_reference.ipynb +++ b/docs/geometry_reference.ipynb @@ -967,7 +967,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Alternatively, we can spread them out on a fixed grid by setting ``separation = False``. Here we align the left edge (``edge = 'min'``) of each object along a grid spacing of 100:" + "Alternatively, we can spread them out on a fixed grid by setting ``separation = False``. Here we align the left edge (``edge = 'ymin'``) of each object along a grid spacing of 100:" ] }, { @@ -996,7 +996,10 @@ "D = Device()\n", "[D.add_ref(pg.rectangle(size = [n*15+20,n*15+20]).move((n,n*4))) for n in [0,2,3,1,2]]\n", "D.distribute(elements = 'all', direction = 'x', spacing = 100, separation = False,\n", - " edge = 'xmin') # edge must be either 'xmin' (left), 'xmax' (right), or 'x' (center)\n", + " edge = 'xmin')\n", + "# edge must be either 'xmin' (left), 'xmax' (right), or 'x' (x-center)\n", + "# or if direction = 'y' then\n", + "# edge must be either 'ymin' (bottom), 'ymax' (top), or 'y' (y-center)\n", "\n", "qp(D) # quickplot the geometry" ] @@ -1005,7 +1008,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The alignment can be done along the right edge as well by setting ``edge = 'max'``, or along the center by setting ``edge = 'center'`` like in the following:" + "The alignment can be done along the right edge as well by setting ``edge = 'xmax'``, or along the x-center by setting ``edge = 'x'`` like in the following:" ] }, { @@ -1034,7 +1037,10 @@ "D = Device()\n", "[D.add_ref(pg.rectangle(size = [n*15+20,n*15+20]).move((n-10,n*4))) for n in [0,2,3,1,2]]\n", "D.distribute(elements = 'all', direction = 'x', spacing = 100, separation = False,\n", - " edge = 'x') # edge must be either 'xmin' (left), 'xmax' (right), or 'x' (center)\n", + " edge = 'x')\n", + "# edge must be either 'xmin' (left), 'xmax' (right), or 'x' (x-center)\n", + "# or if direction = 'y' then\n", + "# edge must be either 'ymin' (bottom), 'ymax' (top), or 'y' (y-center)\n", "\n", "qp(D) # quickplot the geometry" ] @@ -1202,17 +1208,19 @@ "\n", "The ``pg.boolean()`` function can perform AND/OR/NOT/XOR operations, and will return a new geometry with the result of that operation.\n", "\n", + "All shapes in a single device can be merged with `pg.boolean(Device, None, opertion = 'or')`.\n", + "\n", "Speedup note: The ``num_divisions`` argument can be used to divide up the geometry into multiple rectangular regions and process each region sequentially (which is more computationally efficient). If you have a large geometry that takes a long time to process, try using ``num_divisions = [10,10]`` to optimize the operation." ] }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 2, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -1228,17 +1236,27 @@ "from phidl import quickplot as qp\n", "from phidl import Device\n", "\n", - "E = pg.ellipse(radii = (10,5), layer = 1)\n", - "R = pg.rectangle(size = [15,5], layer = 2).movey(-1.5)\n", - "C = pg.boolean(A = E, B = R, operation = 'not', precision = 1e-6,\n", + "D1 = pg.circle(radius = 5, layer = 1).move([5,5])\n", + "D2 = pg.rectangle(size = [10, 10], layer = 2).move([-5,-5])\n", + "NOT = pg.boolean(A = D1, B = D2, operation = 'not', precision = 1e-6,\n", + " num_divisions = [1,1], layer = 0)\n", + "AND = pg.boolean(A = D1, B = D2, operation = 'and', precision = 1e-6,\n", + " num_divisions = [1,1], layer = 0)\n", + "OR = pg.boolean(A = D1, B = D2, operation = 'or', precision = 1e-6,\n", " num_divisions = [1,1], layer = 0)\n", - "# Other operations include 'and', 'or', 'xor', or equivalently 'A-B', 'B-A', 'A+B'\n", + "XOR = pg.boolean(A = D1, B = D2, operation = 'xor', precision = 1e-6,\n", + " num_divisions = [1,1], layer = 0)\n", + "# ‘A+B’ is equivalent to ‘or’. ‘A-B’ is equivalent to ‘not’.\n", + "# ‘B-A’ is equivalent to ‘not’ with the operands switched.\n", "\n", "# Plot the originals and the result\n", "D = Device()\n", - "D.add_ref(E)\n", - "D.add_ref(R)\n", - "D.add_ref(C).movex(30)\n", + "D.add_ref(D1)\n", + "D.add_ref(D2)\n", + "D.add_ref(NOT).move([25, 10]) # top left\n", + "D.add_ref(AND).move([45, 10]) # top right\n", + "D.add_ref(OR).move([25, -10]) # bottom left\n", + "D.add_ref(XOR).move([45, -10]) # bottom right\n", "qp(D) # quickplot the geometry" ] }, @@ -2920,6 +2938,40 @@ "qp(D) # quickplot the geometry" ] }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "import phidl.geometry as pg\n", + "from phidl import quickplot as qp\n", + "\n", + "D = pg.snspd_candelabra(\n", + " wire_width=0.52,\n", + " wire_pitch=0.56,\n", + " haxis=40,\n", + " vaxis=20,\n", + " equalize_path_lengths=False,\n", + " xwing=False,\n", + " layer=0,\n", + ")\n", + "qp(D) # quickplot the geometry" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -3057,7 +3109,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.6" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/phidl/device_layout.py b/phidl/device_layout.py index 5ed7af7e..669708ec 100644 --- a/phidl/device_layout.py +++ b/phidl/device_layout.py @@ -36,6 +36,7 @@ import hashlib +import numbers import warnings from copy import deepcopy as _deepcopy @@ -51,7 +52,7 @@ gdspy.library.use_current_library = False -__version__ = "1.6.1" +__version__ = "1.6.2" # ============================================================================== @@ -540,7 +541,7 @@ def _parse_layer(layer): gds_layer, gds_datatype = layer[0], 0 elif layer is None: gds_layer, gds_datatype = 0, 0 - elif isinstance(layer, (int, float)): + elif isinstance(layer, numbers.Number): gds_layer, gds_datatype = layer, 0 else: raise ValueError( @@ -1206,9 +1207,13 @@ def add_polygon(self, points, layer=np.nan): layers = zip(points.layers, points.datatypes) else: layers = [layer] * len(points.polygons) - return [ - self.add_polygon(p, layer) for p, layer in zip(points.polygons, layers) - ] + + polygons = [] + for p, layer in zip(points.polygons, layers): + new_polygon = self.add_polygon(p, layer) + new_polygon.properties = points.properties + polygons.append(new_polygon) + return polygons if layer is np.nan: layer = 0 @@ -1516,6 +1521,14 @@ def remove_layers(self, layers=(), include_labels=True, invert_selection=False): p for p, keep in zip(polygonset.datatypes, polygons_to_keep) if keep ] + paths = [] + for path in D.paths: + for layer in zip(path.layers, path.datatypes): + if layer not in layers: + paths.append(path) + + D.paths = paths + if include_labels: new_labels = [] for l in D.labels: @@ -1907,7 +1920,6 @@ def __init__( x_reflection=x_reflection, ignore_missing=False, ) - self.parent = device self.owner = None # The ports of a DeviceReference have their own unique id (uid), # since two DeviceReferences of the same parent Device can be @@ -1916,6 +1928,14 @@ def __init__( name: port._copy(new_uid=True) for name, port in device.ports.items() } + @property + def parent(self): + return self.ref_cell + + @parent.setter + def parent(self, value): + self.ref_cell = value + def __repr__(self): """Prints a description of the DeviceReference, including parent Device, ports, origin, rotation, and x_reflection. diff --git a/phidl/font.py b/phidl/font.py index f1b81a6e..5705f0da 100644 --- a/phidl/font.py +++ b/phidl/font.py @@ -93,7 +93,7 @@ def _get_glyph(font, letter): # noqa: C901 # If there is no postscript name, use the family name font_name = font.family_name.replace(" ", "_") - block_name = "*char_{}_0x{:2X}".format(font_name, ord(letter)) + block_name = f"*char_{font_name}_0x{ord(letter):2X}" # Load control points from font file font.load_char(letter, freetype.FT_LOAD_FLAGS["FT_LOAD_NO_BITMAP"]) diff --git a/phidl/geometry.py b/phidl/geometry.py index 79a53554..49c1fc52 100644 --- a/phidl/geometry.py +++ b/phidl/geometry.py @@ -591,7 +591,7 @@ def boolean( # noqa: C901 ) # Check for trivial solutions - if (len(A_polys) == 0) or (len(B_polys) == 0): + if ((len(A_polys) == 0) or (len(B_polys) == 0)) and (operation != "or"): if operation == "not": if len(A_polys) == 0: p = None @@ -599,13 +599,15 @@ def boolean( # noqa: C901 p = A_polys elif operation == "and": p = None - elif (operation == "or") or (operation == "xor"): + elif operation == "xor": if (len(A_polys) == 0) and (len(B_polys) == 0): p = None elif len(A_polys) == 0: p = B_polys elif len(B_polys) == 0: p = A_polys + elif (len(A_polys) == 0) and (len(B_polys) == 0) and (operation == "or"): + p = None else: # If no trivial solutions, run boolean operation either in parallel or # straight @@ -728,7 +730,7 @@ def outline( Outline = boolean( A=D_bloated, B=[D, Trim], - operation="A-B", + operation="A-B" if distance > 0 else "B-A", num_divisions=num_divisions, max_points=max_points, precision=precision, @@ -740,10 +742,6 @@ def outline( return Outline -def inset(elements, distance=0.1, join_first=True, precision=1e-4, layer=0): - raise ValueError("[PHIDL] pg.inset() is deprecated, " "please use pg.offset()") - - def invert( elements, border=10, precision=1e-4, num_divisions=[1, 1], max_points=4000, layer=0 ): @@ -1802,6 +1800,7 @@ def import_gds(filename, cellname=None, flatten=False): D.polygons = cell.polygons D.references = cell.references D.name = cell.name + D.paths = cell.paths for label in cell.labels: rotation = label.rotation if rotation is None: @@ -1814,7 +1813,7 @@ def import_gds(filename, cellname=None, flatten=False): layer=(label.layer, label.texttype), ) l.anchor = label.anchor - c2dmap.update({cell: D}) + c2dmap[cell] = D D_list.append(D) for D in D_list: @@ -1830,6 +1829,7 @@ def import_gds(filename, cellname=None, flatten=False): magnification=e.magnification, x_reflection=e.x_reflection, ) + dr.properties = e.properties dr.owner = D converted_references.append(dr) elif isinstance(e, gdspy.CellArray): @@ -1915,7 +1915,7 @@ def preview_layerset(ls, size=100, spacing=100): for n, layer in enumerate(sorted_layers): R = rectangle(size=(100 * scale, 100 * scale), layer=layer) T = text( - text="{}\n{} / {}".format(layer.name, layer.gds_layer, layer.gds_datatype), + text=f"{layer.name}\n{layer.gds_layer} / {layer.gds_datatype}", size=20 * scale, justify="center", layer=layer, @@ -1981,9 +1981,7 @@ def _convert_port_to_geometry(port, layer=0): The Port must start with a parent. """ if port.parent is None: - raise ValueError( - "Port {}: Port needs a parent in which to draw".format(port.name) - ) + raise ValueError(f"Port {port.name}: Port needs a parent in which to draw") if isinstance(port.parent, DeviceReference): device = port.parent.parent else: @@ -3452,7 +3450,7 @@ def _gen_param_variations( D_new = make_device(function, config=param_defaults, **new_params) label_text = "" for name, value in params.items(): - label_text += ("{}={}".format(name, value)) + "\n" + label_text += (f"{name}={value}") + "\n" if label_layer is not None: D_new.add_label(text=label_text, position=D_new.center, layer=label_layer) @@ -5396,6 +5394,316 @@ def snspd_expanded( # quickplot(s) +def snspd_candelabra( # noqa: C901 + wire_width=0.52, + wire_pitch=0.56, + haxis=90, + vaxis=50, + equalize_path_lengths=False, + xwing=False, + layer=0, +): + """Creates an optimally-rounded SNSPD with low current crowding and + arbtitrarily-high fill factor as described by Reddy et. al., + APL Photonics 7, 051302 (2022) https://doi.org/10.1063/5.0088007 + + Parameters + ---------- + wire_width : int or float + Width of the wire. + wire_pitch : int or float + Distance between two adjacent wires. Must be greater than `width`. + haxis : int or float + Length of horizontal diagonal of the rhomboidal active area. + The parameter `haxis` is prioritized over `vaxis`. + vaxis : int or float + Length of vertical diagonal of the rhomboidal active area. + equalize_path_lengths : bool + If True, adds wire segments to hairpin bends to equalize path lengths + from center to center for all parallel wires in active area. + xwing : bool + If True, replaces 90-degree bends with 135-degree bends. + layer : int + Specific layer to put polygon geometry on. + + Returns + ------- + D : Device + A Device containing an optimally-rounded SNSPD with minimized current + crowding for any fill factor. + """ + + def off_axis_uturn( + wire_width=0.52, + wire_pitch=0.56, + pfact=10.0 / 3, + sharp=False, + pad_length=0, + layer=0, + ): + """Returns phidl device low-crowding u-turn for candelabra meander.""" + barc = optimal_90deg(width=wire_width, layer=layer) + if not sharp: + # For non-rounded outer radii + # Not fully implemented + port1mp = [barc.ports[1].x, barc.ports[1].y] + port1or = barc.ports[1].orientation + port2mp = [barc.ports[2].x, barc.ports[2].y] + port2or = barc.ports[2].orientation + barc = boolean( + A=barc, + B=copy(barc).move([-wire_width, -wire_width]), + operation="not", + layer=layer, + ) + barc.add_port( + name=1, midpoint=port1mp, width=wire_width, orientation=port1or + ) + barc.add_port( + name=2, midpoint=port2mp, width=wire_width, orientation=port2or + ) + pin = optimal_hairpin( + width=wire_width, + pitch=pfact * wire_width, + length=8 * wire_width, + layer=layer, + ) + pas = compass(size=(wire_width, wire_pitch), layer=layer) + D = Device() + arc1 = D.add_ref(barc) + arc1.rotate(90) + pin1 = D.add_ref(pin) + pin1.connect(1, arc1.ports[2]) + pas1 = D.add_ref(pas) + pas1.connect(pas1.ports["N"], pin1.ports[2]) + arc2 = D.add_ref(barc) + arc2.connect(2, pas1.ports["S"]) + if pad_length > 0: + pin1.movey(pad_length * 0.5) + tempc = D.add_ref( + compass( + size=(pin1.ports[1].width, pin1.ports[1].y - arc1.ports[2].y), + layer=layer, + ) + ) + tempc.connect("N", pin1.ports[1]) + tempc = D.add_ref( + compass( + size=(pin1.ports[2].width, pin1.ports[2].y - pas1.ports["N"].y), + layer=layer, + ) + ) + tempc.connect("N", pin1.ports[2]) + D.add_port( + name=1, + midpoint=arc1.ports[1].midpoint, + width=wire_width, + orientation=arc1.ports[1].orientation, + ) + D.add_port( + name=2, + midpoint=arc2.ports[1].midpoint, + width=wire_width, + orientation=arc2.ports[1].orientation, + ) + return D + + def xwing_uturn( + wire_width=0.52, wire_pitch=0.56, pfact=10.0 / 3, pad_length=0, layer=0 + ): + """Returns phidl device low-crowding u-turn for X-wing meander.""" + barc = arc( + radius=wire_width * 3, width=wire_width, layer=layer, theta=45 + ).rotate(180) + + pin = optimal_hairpin( + width=wire_width, + pitch=pfact * wire_width, + length=15 * wire_width, + layer=layer, + ) + + paslen = pfact * wire_width - np.sqrt(2) * wire_pitch + pas = compass(size=(wire_width, abs(paslen)), layer=layer) + Dtemp = Device() + arc1 = Dtemp.add_ref(barc) + arc1.rotate(90) + pin1 = Dtemp.add_ref(pin) + pas1 = Dtemp.add_ref(pas) + arc2 = Dtemp.add_ref(barc) + if paslen > 0: + pas1.connect(pas1.ports["S"], arc1.ports[2]) + pin1.connect(1, pas1.ports["N"]) + arc2.connect(2, pin1.ports[2]) + else: + pin1.connect(1, arc1.ports[2]) + pas1.connect("N", pin1.ports[2]) + arc2.connect(2, pas1.ports["S"]) + if pad_length > 0: + pin1.move([pad_length * 0.5 / np.sqrt(2), pad_length * 0.5 / np.sqrt(2)]) + if paslen > 0: + indx1 = 2 + indx2 = 1 + myarc = arc2 + else: + indx1 = 1 + indx2 = 2 + myarc = arc1 + compdist = np.sqrt( + np.sum(np.square(pin1.ports[indx1].midpoint - myarc.ports[2].midpoint)) + ) + tempc = Dtemp.add_ref( + compass(size=(pin1.ports[indx1].width, compdist), layer=layer) + ) + tempc.connect("N", pin1.ports[indx1]) + compdist = np.sqrt( + np.sum(np.square(pin1.ports[indx2].midpoint - pas1.ports["N"].midpoint)) + ) + tempc = Dtemp.add_ref( + compass(size=(pin1.ports[indx2].width, compdist), layer=layer) + ) + tempc.connect("N", pin1.ports[indx2]) + + Dtemp.add_port( + name=1, + midpoint=arc1.ports[1].midpoint, + width=wire_width, + orientation=arc1.ports[1].orientation, + ) + Dtemp.add_port( + name=2, + midpoint=arc2.ports[1].midpoint, + width=wire_width, + orientation=arc2.ports[1].orientation, + ) + + return Dtemp + + D = Device(name="snspd_candelabra") + if xwing: + Dtemp = xwing_uturn(wire_width=wire_width, wire_pitch=wire_pitch, layer=layer) + else: + Dtemp = off_axis_uturn( + wire_width=wire_width, wire_pitch=wire_pitch, layer=layer + ) + Dtemp_mirrored = deepcopy(Dtemp).mirror([0, 0], [0, 1]) + padding = Dtemp.xsize + maxll = haxis - 2 * padding + dll = abs(Dtemp.ports[1].x - Dtemp.ports[2].x) + wire_pitch + half_num_meanders = int(np.ceil(0.5 * vaxis / wire_pitch)) + 2 + + if xwing: + bend = D.add_ref( + arc(radius=wire_width * 3, width=wire_width, theta=90, layer=layer) + ).rotate(180) + else: + bend = D.add_ref(optimal_90deg(width=wire_width, layer=layer)) + if (maxll - dll * half_num_meanders) <= 0.0: + while (maxll - dll * half_num_meanders) <= 0.0: + half_num_meanders = half_num_meanders - 1 + fpas = D.add_ref( + compass(size=(0.5 * (maxll - dll * half_num_meanders), wire_width), layer=layer) + ) + D.movex(-bend.ports[1].x) + fpas.connect(fpas.ports["W"], bend.ports[2]) + ll = D.xsize * 2 - wire_width + if equalize_path_lengths: + if xwing: + Dtemp = xwing_uturn( + wire_width=wire_width, + wire_pitch=wire_pitch, + pad_length=(maxll - ll - dll) * equalize_path_lengths, + layer=layer, + ) + else: + Dtemp = off_axis_uturn( + wire_width=wire_width, + wire_pitch=wire_pitch, + pad_length=(maxll - ll - dll) * equalize_path_lengths, + layer=layer, + ) + uturn = D.add_ref(Dtemp) + uturn.connect(1, fpas.ports["E"]) + dir_left = True + + turn_padding = maxll - ll - 2 * dll + + while ll < maxll - dll: + ll = ll + dll + if equalize_path_lengths: + if xwing: + Dtemp = xwing_uturn( + wire_width=wire_width, + wire_pitch=wire_pitch, + pad_length=turn_padding * equalize_path_lengths, + layer=layer, + ) + else: + Dtemp = off_axis_uturn( + wire_width=wire_width, + wire_pitch=wire_pitch, + pad_length=turn_padding * equalize_path_lengths, + layer=layer, + ) + turn_padding = turn_padding - dll + newpas = D.add_ref(compass(size=(ll, wire_width), layer=layer)) + if dir_left: + newpas.connect(newpas.ports["E"], uturn.ports[2]) + if equalize_path_lengths: + uturn = D.add_ref(Dtemp.mirror([0, 0], [0, 1])) + else: + uturn = D.add_ref(Dtemp_mirrored) + uturn.connect(1, newpas.ports["W"]) + dir_left = False + else: + newpas.connect(newpas.ports["W"], uturn.ports[2]) + uturn = D.add_ref(Dtemp) + uturn.connect(1, newpas.ports["E"]) + dir_left = True + + newpas = D.add_ref(compass(size=(ll / 2, wire_width), layer=layer)) + if dir_left: + newpas.connect(newpas.ports["E"], uturn.ports[2]) + dir_left = False + else: + newpas.connect(newpas.ports["W"], uturn.ports[2]) + dir_left = True + + D.movex(-D.x) + if not xwing: + bend.movex(-bend.ports[1].x) + if (fpas.ports["W"].x - bend.ports[2].x) > 0: + tempc = D.add_ref( + compass( + size=(fpas.ports["W"].x - bend.ports[2].x, bend.ports[2].width), + layer=layer, + ) + ) + tempc.connect("E", fpas.ports["W"]) + D.move([-D.x, -D.ymin - wire_width * 0.5]) + D.add_port(name=1, port=bend.ports[1]) + if dir_left: + D.add_port(name=2, port=newpas.ports["E"]) + else: + D.add_port(name=2, port=newpas.ports["W"]) + + Dout = Device() + D1 = Dout.add_ref(D) + D2 = Dout.add_ref(copy(D).rotate(180)) + tempc = Dout.add_ref( + compass( + size=(abs(D1.ports[2].x - D2.ports[2].x), D1.ports[2].width), layer=layer + ) + ) + if D1.ports[2].x > D2.ports[2].x: + tempc.connect("E", D1.ports[2]) + else: + tempc.connect("W", D1.ports[2]) + Dout.add_port(name=1, port=D1.ports[1]) + Dout.add_port(name=2, port=D2.ports[1]) + return Dout + + def ytron_round( rho=1, arm_lengths=(500, 300), diff --git a/phidl/quickplotter.py b/phidl/quickplotter.py index 2cf7939a..d527559b 100644 --- a/phidl/quickplotter.py +++ b/phidl/quickplotter.py @@ -6,7 +6,6 @@ import gdspy import numpy as np -from matplotlib.lines import Line2D import phidl from phidl.device_layout import ( @@ -22,15 +21,6 @@ _SUBPORT_RGB = (0, 120, 120) _PORT_RGB = (190, 0, 0) -try: - import matplotlib - from matplotlib import pyplot as plt - from matplotlib.collections import PolyCollection - from matplotlib.widgets import RectangleSelector - - matplotlib_imported = True -except ImportError: - matplotlib_imported = False try: from PyQt5 import QtCore, QtGui @@ -108,6 +98,8 @@ def zoom_fun(event, ax, scale): def _rectangle_selector_factory(fig, ax): + from matplotlib.widgets import RectangleSelector + def line_select_callback(eclick, erelease): x1, y1 = eclick.xdata, eclick.ydata x2, y2 = erelease.xdata, erelease.ydata @@ -202,6 +194,13 @@ def quickplot(items): # noqa: C901 >>> quickplot([R, E]) """ + try: + from matplotlib import pyplot as plt + + matplotlib_imported = True + except ImportError: + matplotlib_imported = False + # Override default options with _quickplot_options show_ports = _quickplot_options["show_ports"] show_subports = _quickplot_options["show_subports"] @@ -330,6 +329,8 @@ def quickplot(items): # noqa: C901 def _use_interactive_zoom(): """Checks whether the current matplotlib backend is compatible with interactive zoom""" + import matplotlib + if _quickplot_options["interactive_zoom"] is not None: return _quickplot_options["interactive_zoom"] forbidden_backends = ["nbagg"] @@ -382,6 +383,8 @@ def _get_layerprop(layer, datatype): def _draw_polygons(polygons, ax, **kwargs): + from matplotlib.collections import PolyCollection + coll = PolyCollection(polygons, **kwargs) ax.add_collection(coll) stacked_polygons = np.vstack(polygons) @@ -392,6 +395,8 @@ def _draw_polygons(polygons, ax, **kwargs): def _draw_line(x, y, ax, **kwargs): + from matplotlib.lines import Line2D + line = Line2D(x, y, **kwargs) ax.add_line(line) xmin, ymin = np.min(x), np.min(y) @@ -447,6 +452,8 @@ def _draw_port(ax, port, is_subport, color): def _draw_port_as_point(ax, port, **kwargs): + from matplotlib import pyplot as plt + x = port.midpoint[0] y = port.midpoint[1] plt.plot(x, y, "r+", alpha=0.5, markersize=15, markeredgewidth=2) # Draw port edge diff --git a/phidl/routing.py b/phidl/routing.py index 93508dc9..29df319d 100644 --- a/phidl/routing.py +++ b/phidl/routing.py @@ -297,7 +297,7 @@ def route_smooth( manual_path=None, smooth_options={"corner_fun": pp.euler, "use_eff": True}, layer=np.nan, - **kwargs + **kwargs, ): """Convenience function that routes a path between ports using pp.smooth(), @@ -416,7 +416,7 @@ def route_sharp( path_type="manhattan", manual_path=None, layer=np.nan, - **kwargs + **kwargs, ): """Convenience function that routes a path between ports and immediately @@ -953,7 +953,7 @@ def route_manhattan( # noqa: C901 valid_bend_types = ["circular", "gradual"] if bendType not in valid_bend_types: - raise ValueError("bendType{}= not in {}".format(bendType, valid_bend_types)) + raise ValueError(f"bendType{bendType}= not in {valid_bend_types}") if bendType == "gradual": b = _gradual_bend(radius=radius) diff --git a/phidl/utilities.py b/phidl/utilities.py index a5f36791..7f0b150d 100644 --- a/phidl/utilities.py +++ b/phidl/utilities.py @@ -32,7 +32,7 @@ def write_lyp(filename, layerset): gds_datatype = layer.gds_datatype color = layer.color - name = "{}/{} - ".format(str(gds_layer), str(gds_datatype)) + layer.name + name = f"{str(gds_layer)}/{str(gds_datatype)} - " + layer.name if layer.description is not None: name = name + " - (" + layer.description + ")" @@ -83,9 +83,7 @@ def write_lyp(filename, layerset): # Writing line to specify layer name f.write(" %s\n" % name) # Writing line to specify source - f.write( - " {}/{}@1\n".format(str(gds_layer), str(gds_datatype)) - ) + f.write(f" {str(gds_layer)}/{str(gds_datatype)}@1\n") # Writing properties closer for specific layer f.write(" \n") diff --git a/setup.py b/setup.py index 1d5be498..03ef6cf3 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ setup( name="phidl", - version="1.6.1", + version="1.6.2", description="PHIDL", long_description=long_description, long_description_content_type="text/markdown", diff --git a/tests/test_device.py b/tests/test_device.py index 4d67c1e7..3bcdb1e2 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -1,7 +1,10 @@ +import os +import tempfile + import numpy as np import phidl.geometry as pg -from phidl import Device, Group # , Layer, LayerSet, make_device, Port +from phidl import Device, Group # import phidl.routing as pr # import phidl.utilities as pu @@ -328,3 +331,15 @@ def test_polygon_simplify(): h = D.hash_geometry(precision=1e-4) assert h == "7d9ebcb231fb0107cbbf618353adeb583782ca11" # qp(D) + + +def test_preserve_properties(): + fname = os.path.join(tempfile.mkdtemp(), "properties.gds") + d = pg.bbox() + d.polygons[0].properties[1] = "yolo" + r = d << pg.bbox() + r.properties[1] = "foo" + d.write_gds(fname) + d2 = pg.import_gds(fname) + assert d2.polygons[0].properties == d.polygons[0].properties + assert d2.references[0].properties == r.properties