From 2d765284f5c93b1095e93a1141a2b5fb7f6bf362 Mon Sep 17 00:00:00 2001 From: bsnyder Date: Mon, 11 Jul 2022 23:27:57 +0200 Subject: [PATCH 1/7] Add grid snapping to grating_coupler_elliptical (cherry picked from commit fd107da4150d1fb6d9c3d285e7b2918f95d574ee) --- gdsfactory/components/grating_coupler_elliptical.py | 2 ++ gdsfactory/geometry/functions.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/gdsfactory/components/grating_coupler_elliptical.py b/gdsfactory/components/grating_coupler_elliptical.py index 4ad45885a4..129cf908d3 100644 --- a/gdsfactory/components/grating_coupler_elliptical.py +++ b/gdsfactory/components/grating_coupler_elliptical.py @@ -33,7 +33,9 @@ def ellipse_arc( """ theta = np.arange(theta_min, theta_max + angle_step, angle_step) * DEG2RAD xs = a * np.cos(theta) + x0 + xs = gf.snap.snap_to_grid(xs) ys = b * np.sin(theta) + ys = gf.snap.snap_to_grid(ys) return np.column_stack([xs, ys]) diff --git a/gdsfactory/geometry/functions.py b/gdsfactory/geometry/functions.py index 1b88ca484f..c87b10e2ec 100644 --- a/gdsfactory/geometry/functions.py +++ b/gdsfactory/geometry/functions.py @@ -165,7 +165,7 @@ def extrude_path( spike_length: Union[float64, int, float] = 0, start_angle: Optional[int] = None, end_angle: Optional[int] = None, - grid: float = 0.001, + grid: float = 0.005, ) -> ndarray: """Deprecated. Use gf.path.Path.extrude() instead. From 102708c80dbf62244ff9f154bfc364f169685cac Mon Sep 17 00:00:00 2001 From: bsnyder Date: Tue, 21 Jun 2022 23:32:12 +0200 Subject: [PATCH 2/7] Change numeric default layers to named layers in port and cross_section (cherry picked from commit b694d6612f0411b6019135b865c478549d5f838f) --- gdsfactory/cross_section.py | 2 +- gdsfactory/port.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gdsfactory/cross_section.py b/gdsfactory/cross_section.py index 0e84d6a910..e15db3f215 100644 --- a/gdsfactory/cross_section.py +++ b/gdsfactory/cross_section.py @@ -26,7 +26,7 @@ Floats = Tuple[float, ...] port_names_electrical = ("e1", "e2") port_types_electrical = ("electrical", "electrical") -cladding_layers_optical = ((68, 0),) # for SiEPIC verification +cladding_layers_optical = ("DEVREC",) # for SiEPIC verification cladding_offsets_optical = (0,) # for SiEPIC verification diff --git a/gdsfactory/port.py b/gdsfactory/port.py index 82ce947ce1..e2eb3a7180 100644 --- a/gdsfactory/port.py +++ b/gdsfactory/port.py @@ -401,8 +401,8 @@ def port_array( ] -def read_port_markers(component: object, layers: LayerSpecs = ((1, 10),)) -> Component: - """Loads a GDS and returns the extracted ports from layer markers. +def read_port_markers(component: object, layers: LayerSpecs = ("PORT",)) -> Component: + """Loads a GDS and returns the extracted ports from layer markers Args: component: or Component From 82aba327ef70d0846bcf243f11bddd28841e3e98 Mon Sep 17 00:00:00 2001 From: bsnyder Date: Wed, 13 Jul 2022 01:05:19 +0200 Subject: [PATCH 3/7] Grid snapping and defaults fixes (cherry picked from commit df950ad25ef202cc77d4107ee8c170c146153089) --- gdsfactory/components/bend_circular.py | 2 +- gdsfactory/read/from_picwriter.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gdsfactory/components/bend_circular.py b/gdsfactory/components/bend_circular.py index e3e0c81fa2..63faa72da5 100644 --- a/gdsfactory/components/bend_circular.py +++ b/gdsfactory/components/bend_circular.py @@ -12,7 +12,7 @@ def bend_circular( angle: float = 90.0, npoints: int = 720, with_bbox: bool = True, - cross_section: CrossSectionSpec = strip, + cross_section: CrossSectionSpec = "strip", **kwargs ) -> Component: """Returns a radial arc. diff --git a/gdsfactory/read/from_picwriter.py b/gdsfactory/read/from_picwriter.py index 5cd76892de..6439025336 100644 --- a/gdsfactory/read/from_picwriter.py +++ b/gdsfactory/read/from_picwriter.py @@ -79,6 +79,7 @@ def from_picwriter( datatypes = poly.datatypes for polygon, layer, datatype in zip(polygons, layers, datatypes): + polygon = gf.snap.snap_to_grid(polygon) c.add_polygon(polygon, layer=(layer, datatype)) c2 = Component(c.name) From 8fac7db8b788118c6d9ca72936d654218db46f81 Mon Sep 17 00:00:00 2001 From: bsnyder Date: Fri, 15 Jul 2022 19:14:28 +0200 Subject: [PATCH 4/7] Fixed default of get_route_from_steps (cherry picked from commit 66ce68b927db385dbfc2e131d583639ebb02793b) --- gdsfactory/routing/get_route_from_steps.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gdsfactory/routing/get_route_from_steps.py b/gdsfactory/routing/get_route_from_steps.py index bef39047d8..1aefba4b9e 100644 --- a/gdsfactory/routing/get_route_from_steps.py +++ b/gdsfactory/routing/get_route_from_steps.py @@ -4,7 +4,6 @@ import gdsfactory as gf from gdsfactory.components.via_corner import via_corner -from gdsfactory.cross_section import strip from gdsfactory.port import Port from gdsfactory.routing.manhattan import round_corners from gdsfactory.types import ( @@ -21,7 +20,7 @@ def get_route_from_steps( steps: Optional[List[Dict[str, float]]] = None, bend: ComponentSpec = "bend_euler", taper: Optional[ComponentSpec] = "taper", - cross_section: Union[CrossSectionSpec, MultiCrossSectionAngleSpec] = strip, + cross_section: Union[CrossSectionSpec, MultiCrossSectionAngleSpec] = "strip", **kwargs ) -> Route: """Returns a route formed by the given waypoints steps. From e69644499eaf1648a1ad0de8db6795e12eceb511 Mon Sep 17 00:00:00 2001 From: bsnyder Date: Wed, 13 Jul 2022 01:05:19 +0200 Subject: [PATCH 5/7] Grid snapping and defaults fixes (cherry picked from commit 3834ca5fa3767321ed11dadc8a9fb5db67b0b1e4) --- gdsfactory/components/bend_circular.py | 1 - 1 file changed, 1 deletion(-) diff --git a/gdsfactory/components/bend_circular.py b/gdsfactory/components/bend_circular.py index 63faa72da5..eed3453da0 100644 --- a/gdsfactory/components/bend_circular.py +++ b/gdsfactory/components/bend_circular.py @@ -1,7 +1,6 @@ import gdsfactory as gf from gdsfactory.add_padding import get_padding_points from gdsfactory.component import Component -from gdsfactory.cross_section import strip from gdsfactory.path import arc, extrude from gdsfactory.snap import snap_to_grid from gdsfactory.types import CrossSectionSpec From 5a7abfdb18c77206f071e3cdf26e1ebfebdda552 Mon Sep 17 00:00:00 2001 From: bsnyder Date: Wed, 3 Aug 2022 01:09:31 +0200 Subject: [PATCH 6/7] Read grid size from PDK and grid snapping fixes --- gdsfactory/component.py | 6 ++++- .../grating_coupler_rectangular_arbitrary.py | 25 ++++++++++--------- gdsfactory/geometry/boolean.py | 5 ++-- gdsfactory/snap.py | 14 ++++++++--- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/gdsfactory/component.py b/gdsfactory/component.py index a90da3582c..9c7e0b2d44 100644 --- a/gdsfactory/component.py +++ b/gdsfactory/component.py @@ -1096,7 +1096,7 @@ def write_gds( gdspath: Optional[PathType] = None, gdsdir: Optional[PathType] = None, unit: float = 1e-6, - precision: float = 1e-9, + precision: Optional[float] = None, timestamp: Optional[datetime.datetime] = _timestamp2019, logging: bool = True, on_duplicate_cell: Optional[str] = "warn", @@ -1117,6 +1117,10 @@ def write_gds( "overwrite": overwrite all duplicate cells with one of the duplicates, without warning. None: do not try to resolve (at your own risk!) """ + from gdsfactory.pdk import get_grid_size + + precision = precision or get_grid_size() * 1e-6 + gdsdir = ( gdsdir or pathlib.Path(tempfile.TemporaryDirectory().name) / "gdsfactory" ) diff --git a/gdsfactory/components/grating_coupler_rectangular_arbitrary.py b/gdsfactory/components/grating_coupler_rectangular_arbitrary.py index 88b90033c0..72225e6ad1 100644 --- a/gdsfactory/components/grating_coupler_rectangular_arbitrary.py +++ b/gdsfactory/components/grating_coupler_rectangular_arbitrary.py @@ -4,7 +4,6 @@ import gdsfactory as gf from gdsfactory.component import Component -from gdsfactory.components.rectangle import rectangle from gdsfactory.components.taper import taper as taper_function from gdsfactory.types import ComponentSpec, CrossSectionSpec, Floats, LayerSpec @@ -96,18 +95,20 @@ def grating_coupler_rectangular_arbitrary( gaps = gf.snap.snap_to_grid(gaps) for width, gap in zip(widths, gaps): - xi += gap + width / 2 - cgrating = c.add_ref( - rectangle( - size=(width, width_grating), - layer=layer, - port_type=None, - centered=True, - ) + xi += gap + cgrating = c.add_polygon( + [ + (0.0, 0.0), + (0.0, width_grating), + (width, width_grating), + (width, 0.0), + ], + layer, + ) + cgrating.move( + (gf.snap.snap_to_grid(xi), gf.snap.snap_to_grid(-0.5 * width_grating)) ) - cgrating.x = gf.snap.snap_to_grid(xi) - cgrating.y = 0 - xi += width / 2 + xi += width if layer_slab: slab_xmin += length_taper diff --git a/gdsfactory/geometry/boolean.py b/gdsfactory/geometry/boolean.py index bd5759cb07..085a6d0299 100644 --- a/gdsfactory/geometry/boolean.py +++ b/gdsfactory/geometry/boolean.py @@ -8,7 +8,7 @@ import gdsfactory as gf from gdsfactory.component import Component from gdsfactory.component_reference import ComponentReference -from gdsfactory.types import ComponentOrReference, Int2, Layer +from gdsfactory.types import ComponentOrReference, Int2, LayerSpec @gf.cell @@ -19,7 +19,7 @@ def boolean( precision: float = 1e-4, num_divisions: Union[int, Int2] = (1, 1), max_points: int = 4000, - layer: Layer = (1, 0), + layer: LayerSpec = (1, 0), ) -> Component: """Performs boolean operations between 2 Component/Reference/list objects. @@ -64,6 +64,7 @@ def boolean( elif isinstance(e, Polygon): polys.extend(e.polygons) + layer = gf.pdk.get_layer(layer) gds_layer, gds_datatype = _parse_layer(layer) operation = operation.lower().replace(" ", "") diff --git a/gdsfactory/snap.py b/gdsfactory/snap.py index 30e5f84341..5f51773d32 100644 --- a/gdsfactory/snap.py +++ b/gdsfactory/snap.py @@ -1,5 +1,5 @@ """snaps values and coordinates to the GDS grid in nm.""" -from typing import Tuple, Union +from typing import Optional, Tuple, Union import numpy as np @@ -21,13 +21,19 @@ def assert_on_2nm_grid(x: float) -> None: def snap_to_grid( - x: Union[float, Tuple, np.ndarray], nm: int = 1 + x: Union[float, Tuple, np.ndarray], nm: Optional[int] = None ) -> Union[float, Tuple, np.ndarray]: - if nm == 0: + + if nm is None: + from gdsfactory.pdk import get_grid_size + + nm = int(get_grid_size() * 1000) + elif nm == 0: return x elif nm < 0: raise ValueError("nm must be an integer tolerance value greater than zero") - elif nm == 1: + + if nm == 1: y = np.round(np.asarray(x, dtype=float), 3) else: y = nm * np.round(np.asarray(x, dtype=float) * 1e3 / nm) / 1e3 From 55210a1e2b9ae9e9e432b03f3ba51eac3dd06004 Mon Sep 17 00:00:00 2001 From: bsnyder Date: Sun, 25 Sep 2022 21:32:04 +0200 Subject: [PATCH 7/7] Added parabolic width_type to taper_cross_section --- gdsfactory/components/__init__.py | 2 ++ gdsfactory/components/taper_cross_section.py | 7 ++++++- gdsfactory/cross_section.py | 2 +- gdsfactory/path.py | 15 ++++++++++++++- gdsfactory/types.py | 2 +- 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/gdsfactory/components/__init__.py b/gdsfactory/components/__init__.py index 4cad19ad14..216801bbf3 100644 --- a/gdsfactory/components/__init__.py +++ b/gdsfactory/components/__init__.py @@ -220,6 +220,7 @@ ) from gdsfactory.components.taper_cross_section import ( taper_cross_section_linear, + taper_cross_section_parabolic, taper_cross_section_sine, ) from gdsfactory.components.taper_from_csv import ( @@ -270,6 +271,7 @@ crossing45=crossing45, taper_cross_section_linear=taper_cross_section_linear, taper_cross_section_sine=taper_cross_section_sine, + taper_cross_section_parabolic=taper_cross_section_parabolic, taper=taper, taper2=taper2, taper_0p5_to_3_l36=taper_0p5_to_3_l36, diff --git a/gdsfactory/components/taper_cross_section.py b/gdsfactory/components/taper_cross_section.py index 55b721fa03..e969da462c 100644 --- a/gdsfactory/components/taper_cross_section.py +++ b/gdsfactory/components/taper_cross_section.py @@ -12,6 +12,7 @@ def taper_cross_section( length: float = 10, npoints: int = 100, linear: bool = False, + width_type: str = "sine", **kwargs ) -> Component: r"""Returns taper transition between cross_section1 and cross_section2. @@ -22,6 +23,7 @@ def taper_cross_section( length: transition length. npoints: number of points. linear: shape of the transition, sine when False. + width_type: shape of the transition ONLY IF linear is False kwargs: cross_section settings for section2. @@ -42,7 +44,7 @@ def taper_cross_section( transition = gf.path.transition( cross_section1=gf.get_cross_section(cross_section1), cross_section2=gf.get_cross_section(cross_section2, **kwargs), - width_type="linear" if linear else "sine", + width_type="linear" if linear else width_type, ) taper_path = gf.path.straight(length=length, npoints=npoints) @@ -54,6 +56,9 @@ def taper_cross_section( taper_cross_section_linear = gf.partial(taper_cross_section, linear=True, npoints=2) taper_cross_section_sine = gf.partial(taper_cross_section, linear=False, npoints=101) +taper_cross_section_parabolic = gf.partial( + taper_cross_section, linear=False, width_type="parabolic", npoints=101 +) if __name__ == "__main__": diff --git a/gdsfactory/cross_section.py b/gdsfactory/cross_section.py index e15db3f215..e2d7ff6baf 100644 --- a/gdsfactory/cross_section.py +++ b/gdsfactory/cross_section.py @@ -19,7 +19,7 @@ LAYER = TECH.layer Layer = Tuple[int, int] Layers = Tuple[Layer, ...] -WidthTypes = Literal["sine", "linear"] +WidthTypes = Literal["sine", "linear", "parabolic"] LayerSpec = Union[Layer, int, str, None] LayerSpecs = Union[List[LayerSpec], Tuple[LayerSpec, ...]] diff --git a/gdsfactory/path.py b/gdsfactory/path.py index 7911ade99c..cb19834a15 100644 --- a/gdsfactory/path.py +++ b/gdsfactory/path.py @@ -137,6 +137,15 @@ def sine(t): return sine +def _parabolic_transition(y1, y2): + dy = y2 - y1 + + def parabolic(t): + return y1 + np.sqrt(t) * dy + + return parabolic + + def _linear_transition(y1, y2): dy = y2 - y1 @@ -225,8 +234,12 @@ def transition( width_fun = _linear_transition(width1, width2) elif width_type == "sine": width_fun = _sinusoidal_transition(width1, width2) + elif width_type == "parabolic": + width_fun = _parabolic_transition(width1, width2) else: - raise ValueError(f"width_type={width_type!r} must be {'sine','linear'}") + raise ValueError( + f"width_type={width_type!r} must be {'sine','linear','parabolic'}" + ) if section1.layer != section2.layer: hidden = True diff --git a/gdsfactory/types.py b/gdsfactory/types.py index 9aca6f5bd4..c22a30c804 100644 --- a/gdsfactory/types.py +++ b/gdsfactory/types.py @@ -58,7 +58,7 @@ ] Axis = Literal["x", "y"] NSEW = Literal["N", "S", "E", "W"] -WidthTypes = Literal["sine", "linear"] +WidthTypes = Literal["sine", "linear", "parabolic"] class Label(LabelPhidl):