From 1986988e27573505fdd47e99c03fef445d145a18 Mon Sep 17 00:00:00 2001 From: Sidney Buchbinder Date: Fri, 3 Jan 2020 09:38:54 -0800 Subject: [PATCH 1/6] Adding support for multi-layer objects --- BPG/lumerical/objects.py | 200 +++++++++++++++++++++++---------------- 1 file changed, 119 insertions(+), 81 deletions(-) diff --git a/BPG/lumerical/objects.py b/BPG/lumerical/objects.py index 50d2dd5..84a5f0b 100644 --- a/BPG/lumerical/objects.py +++ b/BPG/lumerical/objects.py @@ -554,49 +554,62 @@ def lsf_export(cls, spx, spy = spx * 1e-6, spy * 1e-6 lsf_code = [] - if rin == 0: - for x_count in range(nx): - for y_count in range(ny): - lsf_code.append('\n') - lsf_code.append('addcircle;\n') + if not isinstance(layer_prop['z_min'], list): + z_min_list = [layer_prop['z_min']] + else: + z_min_list = layer_prop['z_min'] + if not isinstance(layer_prop['z_max'], list): + z_max_list = [layer_prop['z_max']] + else: + z_max_list = layer_prop['z_max'] - # Set material properties - lsf_code.append('set("material", "{}");\n'.format(layer_prop['material'])) - lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha'])) + for z_min_val, z_max_val in zip(z_min_list, z_max_list): + z_min = CoordBase(z_min_val).meters + z_max = CoordBase(z_max_val).meters - # Set radius - lsf_code.append('set(radius, {});\n'.format(rout * 1e-6)) + if rin == 0: + for x_count in range(nx): + for y_count in range(ny): + lsf_code.append('\n') + lsf_code.append('addcircle;\n') - # Compute the x and y coordinates for each rectangle - lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count)) - lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count)) + # Set material properties + lsf_code.append('set("material", "{}");\n'.format(layer_prop['material'])) + lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha'])) - # Extract the thickness values from the layermap file - lsf_code.append('set("z min", {});\n'.format(layer_prop['z_min'] * 1e-6)) - lsf_code.append('set("z max", {});\n'.format(layer_prop['z_max'] * 1e-6)) - else: - for x_count in range(nx): - for y_count in range(ny): - lsf_code.append('\n') - lsf_code.append('addring;\n') + # Set radius + lsf_code.append('set(radius, {});\n'.format(rout * 1e-6)) - # Set material properties - lsf_code.append('set("material", "{}");\n'.format(layer_prop['material'])) - lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha'])) + # Compute the x and y coordinates for each rectangle + lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count)) + lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count)) - # Set dimensions/angles - lsf_code.append('set("outer radius", {});\n'.format(rout * 1e-6)) - lsf_code.append('set("inner radius", {});\n'.format(rin * 1e-6)) - lsf_code.append('set("theta start", {});\n'.format(theta0)) - lsf_code.append('set("theta stop", {});\n'.format(theta1)) + # Extract the thickness values from the layermap file + lsf_code.append('set("z min", {});\n'.format(z_min)) + lsf_code.append('set("z max", {});\n'.format(z_max)) + else: + for x_count in range(nx): + for y_count in range(ny): + lsf_code.append('\n') + lsf_code.append('addring;\n') - # Compute the x and y coordinates for each rectangle - lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count)) - lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count)) + # Set material properties + lsf_code.append('set("material", "{}");\n'.format(layer_prop['material'])) + lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha'])) - # Extract the thickness values from the layermap file - lsf_code.append('set("z min", {});\n'.format(layer_prop['z_min'] * 1e-6)) - lsf_code.append('set("z max", {});\n'.format(layer_prop['z_max'] * 1e-6)) + # Set dimensions/angles + lsf_code.append('set("outer radius", {});\n'.format(rout * 1e-6)) + lsf_code.append('set("inner radius", {});\n'.format(rin * 1e-6)) + lsf_code.append('set("theta start", {});\n'.format(theta0)) + lsf_code.append('set("theta stop", {});\n'.format(theta1)) + + # Compute the x and y coordinates for each rectangle + lsf_code.append('set("x", {});\n'.format(x0 + spx * x_count)) + lsf_code.append('set("y", {});\n'.format(y0 + spy * y_count)) + + # Extract the thickness values from the layermap file + lsf_code.append('set("z min", {});\n'.format(z_min)) + lsf_code.append('set("z max", {});\n'.format(z_max)) return lsf_code @@ -721,6 +734,8 @@ def lsf_export(cls, bbox, layer_prop, nx=1, ny=1, spx=0.0, spy=0.0) -> List[str] lsf_code : List[str] list of str containing the lsf code required to create specified rectangles """ + # Write the lumerical code for each rectangle in the array + lsf_code = [] # Calculate the width and length of the rectangle in meters x_span = CoordBase(bbox[1][0] - bbox[0][0]).meters @@ -730,32 +745,39 @@ def lsf_export(cls, bbox, layer_prop, nx=1, ny=1, spx=0.0, spy=0.0) -> List[str] base_x_center = CoordBase((bbox[1][0] + bbox[0][0]) / 2).meters base_y_center = CoordBase((bbox[1][1] + bbox[0][1]) / 2).meters - # Get vertical dimensions - z_min = CoordBase(layer_prop['z_min']).meters - z_max = CoordBase(layer_prop['z_max']).meters + if not isinstance(layer_prop['z_min'], list): + z_min_list = [layer_prop['z_min']] + else: + z_min_list = layer_prop['z_min'] + if not isinstance(layer_prop['z_max'], list): + z_max_list = [layer_prop['z_max']] + else: + z_max_list = layer_prop['z_max'] - # Write the lumerical code for each rectangle in the array - lsf_code = [] - for x_count in range(nx): - for y_count in range(ny): - lsf_code.append('\n') - lsf_code.append('addrect;\n') - lsf_code.append('set("material", "{}");\n'.format(layer_prop['material'])) - lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha'])) + for z_min_val, z_max_val in zip(z_min_list, z_max_list): + z_min = CoordBase(z_min_val).meters + z_max = CoordBase(z_max_val).meters + + for x_count in range(nx): + for y_count in range(ny): + lsf_code.append('\n') + lsf_code.append('addrect;\n') + lsf_code.append('set("material", "{}");\n'.format(layer_prop['material'])) + lsf_code.append('set("alpha", {});\n'.format(layer_prop['alpha'])) - # Compute the x and y coordinates for each rectangle - lsf_code.append('set("x span", {});\n'.format(x_span)) - lsf_code.append('set("x", {});\n'.format(base_x_center + CoordBase(spx * x_count).meters)) - lsf_code.append('set("y span", {});\n'.format(y_span)) - lsf_code.append('set("y", {});\n'.format(base_y_center + CoordBase(spy * y_count).meters)) + # Compute the x and y coordinates for each rectangle + lsf_code.append('set("x span", {});\n'.format(x_span)) + lsf_code.append('set("x", {});\n'.format(base_x_center + CoordBase(spx * x_count).meters)) + lsf_code.append('set("y span", {});\n'.format(y_span)) + lsf_code.append('set("y", {});\n'.format(base_y_center + CoordBase(spy * y_count).meters)) - # Extract the thickness values from the layermap file - lsf_code.append('set("z min", {});\n'.format(z_min)) - lsf_code.append('set("z max", {});\n'.format(z_max)) + # Extract the thickness values from the layermap file + lsf_code.append('set("z min", {});\n'.format(z_min)) + lsf_code.append('set("z max", {});\n'.format(z_max)) - if 'mesh_order' in layer_prop: - lsf_code.append('set("override mesh order from material database", 1);\n') - lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order'])) + if 'mesh_order' in layer_prop: + lsf_code.append('set("override mesh order from material database", 1);\n') + lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order'])) return lsf_code @@ -1282,30 +1304,46 @@ def lsf_export(cls, vertices, layer_prop) -> List[str]: poly_len = len(vertices) # Write the lumerical code for the polygon - lsf_code = ['\n', - 'addpoly;\n', - 'set("material", "{}");\n'.format(layer_prop['material']), - 'set("alpha", {});\n'.format(layer_prop['alpha']), - - # Set center reference to (0, 0) to fix lumericals relative coordinates - 'set("x", 0);\n', - 'set("y", 0);\n', - 'set("use relative coordinates", 0);\n' - - # Create matrix to hold vertices, Note that the Lumerical uses meters as the base unit - 'V = matrix({},2);\n'.format(poly_len), - 'V(1:{},1) = {};\n'.format(poly_len, [CoordBase(point[0]).meters for point in vertices]), - 'V(1:{},2) = {};\n'.format(poly_len, [CoordBase(point[1]).meters for point in vertices]), - 'set("vertices", V);\n', - - # Set the thickness values from the layermap file - 'set("z min", {});\n'.format(CoordBase(layer_prop['z_min']).meters), - 'set("z max", {});\n'.format(CoordBase(layer_prop['z_max']).meters) - ] - - if 'mesh_order' in layer_prop: - lsf_code.append('set("override mesh order from material database", 1);\n') - lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order'])) + lsf_code = [] + + if not isinstance(layer_prop['z_min'], list): + z_min_list = [layer_prop['z_min']] + else: + z_min_list = layer_prop['z_min'] + if not isinstance(layer_prop['z_max'], list): + z_max_list = [layer_prop['z_max']] + else: + z_max_list = layer_prop['z_max'] + + for z_min_val, z_max_val in zip(z_min_list, z_max_list): + z_min = CoordBase(z_min_val).meters + z_max = CoordBase(z_max_val).meters + + lsf_code.extend = [ + '\n', + 'addpoly;\n', + 'set("material", "{}");\n'.format(layer_prop['material']), + 'set("alpha", {});\n'.format(layer_prop['alpha']), + + # Set center reference to (0, 0) to fix lumericals relative coordinates + 'set("x", 0);\n', + 'set("y", 0);\n', + 'set("use relative coordinates", 0);\n' + + # Create matrix to hold vertices, Note that the Lumerical uses meters as the base unit + 'V = matrix({},2);\n'.format(poly_len), + 'V(1:{},1) = {};\n'.format(poly_len, [CoordBase(point[0]).meters for point in vertices]), + 'V(1:{},2) = {};\n'.format(poly_len, [CoordBase(point[1]).meters for point in vertices]), + 'set("vertices", V);\n', + + # Set the thickness values from the layermap file + 'set("z min", {});\n'.format(z_min), + 'set("z max", {});\n'.format(z_max) + ] + + if 'mesh_order' in layer_prop: + lsf_code.append('set("override mesh order from material database", 1);\n') + lsf_code.append('set("mesh order", {});\n'.format(layer_prop['mesh_order'])) return lsf_code From b9da4803c0b6cb33793ef22de41c8a656b8b8540 Mon Sep 17 00:00:00 2001 From: Sidney Buchbinder Date: Sun, 5 Jan 2020 11:34:00 -0800 Subject: [PATCH 2/6] Fixing lumerical export bug where empty material dict fails. Fixing bug in polygon export code --- BPG/lumerical/code_generator.py | 5 +++-- BPG/lumerical/objects.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/BPG/lumerical/code_generator.py b/BPG/lumerical/code_generator.py index 230039b..d584aa9 100644 --- a/BPG/lumerical/code_generator.py +++ b/BPG/lumerical/code_generator.py @@ -217,8 +217,9 @@ def import_material_file(self, material_dict) -> None: material_dict : dict dict of dicts specifying the materials to be created """ - for key, value in material_dict.items(): - self.import_material_from_dict(material_name=key, prop_dict=value) + if material_dict is not None: + for key, value in material_dict.items(): + self.import_material_from_dict(material_name=key, prop_dict=value) def export_to_lsf(self): file = self.get_file_header() diff --git a/BPG/lumerical/objects.py b/BPG/lumerical/objects.py index 84a5f0b..9e1486e 100644 --- a/BPG/lumerical/objects.py +++ b/BPG/lumerical/objects.py @@ -1319,7 +1319,7 @@ def lsf_export(cls, vertices, layer_prop) -> List[str]: z_min = CoordBase(z_min_val).meters z_max = CoordBase(z_max_val).meters - lsf_code.extend = [ + lsf_code.extend([ '\n', 'addpoly;\n', 'set("material", "{}");\n'.format(layer_prop['material']), @@ -1339,7 +1339,7 @@ def lsf_export(cls, vertices, layer_prop) -> List[str]: # Set the thickness values from the layermap file 'set("z min", {});\n'.format(z_min), 'set("z max", {});\n'.format(z_max) - ] + ]) if 'mesh_order' in layer_prop: lsf_code.append('set("override mesh order from material database", 1);\n') From 316e89112463ec74571a51ea0272413c1d619e0f Mon Sep 17 00:00:00 2001 From: Sidney Buchbinder Date: Sun, 5 Jan 2020 11:45:00 -0800 Subject: [PATCH 3/6] Pinning GDSPY version because updates break syntax --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7ab6b71..b834d33 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ 'numpy>=1.10', 'pytest>=4', 'matplotlib>=3', - 'gdspy>=1.4', + 'gdspy==1.4.3', 'scipy>=1.1.0', 'memory_profiler>=0.54.0', 'Jinja2>=2.10.1', From 5cfb7215de2dafff7bce199902e6ddadf414ab71 Mon Sep 17 00:00:00 2001 From: Sidney Buchbinder Date: Sun, 5 Jan 2020 11:52:53 -0800 Subject: [PATCH 4/6] Fixing the gdspy version pin --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b834d33..cd3220c 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ 'numpy>=1.10', 'pytest>=4', 'matplotlib>=3', - 'gdspy==1.4.3', + 'gdspy==1.4', 'scipy>=1.1.0', 'memory_profiler>=0.54.0', 'Jinja2>=2.10.1', From cc89b21d474128dc914945c7ad4c8df6d459e518 Mon Sep 17 00:00:00 2001 From: Sidney Buchbinder Date: Sun, 5 Jan 2020 12:13:44 -0800 Subject: [PATCH 5/6] Fixing the gdspy version pin --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cd3220c..9c0c336 100644 --- a/setup.py +++ b/setup.py @@ -18,10 +18,13 @@ 'numpy>=1.10', 'pytest>=4', 'matplotlib>=3', - 'gdspy==1.4', + 'gdspy @ https://github.com/heitzmann/gdspy/archive/900ec9efecd066e3440e502bd8a046789bbab552.zip', 'scipy>=1.1.0', 'memory_profiler>=0.54.0', 'Jinja2>=2.10.1', + ], + dependency_links=[ + ], url='https://github.com/BerkeleyPhotonicsGenerator/BPG', license='BSD-3-Clause', From abf8d3bd6c63ece677672f43a4eb583fa40be4a5 Mon Sep 17 00:00:00 2001 From: Sidney Buchbinder Date: Sun, 5 Jan 2020 12:15:24 -0800 Subject: [PATCH 6/6] Removing unused dependency_links --- setup.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.py b/setup.py index 9c0c336..a25c9ba 100644 --- a/setup.py +++ b/setup.py @@ -22,9 +22,6 @@ 'scipy>=1.1.0', 'memory_profiler>=0.54.0', 'Jinja2>=2.10.1', - ], - dependency_links=[ - ], url='https://github.com/BerkeleyPhotonicsGenerator/BPG', license='BSD-3-Clause',