samplemaker-sparrow 5.4.5__tar.gz → 5.4.7__tar.gz
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.
- samplemaker_sparrow-5.4.7/.github/ISSUE_TEMPLATE/config.yml +1 -0
- samplemaker_sparrow-5.4.7/.github/ISSUE_TEMPLATE/fault.yml +81 -0
- samplemaker_sparrow-5.4.7/.github/ISSUE_TEMPLATE/feature_request.yml +42 -0
- samplemaker_sparrow-5.4.7/.github/ISSUE_TEMPLATE/improvement.yml +34 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/.gitignore +4 -1
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/BUILD.md +22 -2
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/PKG-INFO +13 -7
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/README.md +7 -1
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/pyproject.toml +16 -6
- samplemaker_sparrow-5.4.7/src/samplemaker/__init__.py +48 -0
- samplemaker_sparrow-5.4.7/src/samplemaker/baselib/__init__.py +3 -0
- samplemaker_sparrow-5.4.7/src/samplemaker/baselib/devices.py +295 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/baselib/waveguides.py +151 -112
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/devices.py +614 -527
- samplemaker_sparrow-5.4.7/src/samplemaker/gdsreader.py +274 -0
- samplemaker_sparrow-5.4.7/src/samplemaker/gdswriter.py +437 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/layout.py +463 -340
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/makers.py +258 -158
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/phc.py +231 -185
- samplemaker_sparrow-5.4.7/src/samplemaker/routers.py +352 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/sequencer.py +150 -127
- samplemaker_sparrow-5.4.7/src/samplemaker/shapes.py +2362 -0
- samplemaker_sparrow-5.4.7/src/samplemaker/viewers.py +248 -0
- samplemaker_sparrow-5.4.7/tests/fixtures.py +19 -0
- samplemaker_sparrow-5.4.7/tests/test_gdsreader.py +246 -0
- samplemaker_sparrow-5.4.7/tests/test_gdswriter.py +253 -0
- samplemaker_sparrow-5.4.7/tests/test_makers.py +519 -0
- samplemaker_sparrow-5.4.7/tests/test_shapes.py +2005 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/00_Tutorial_BasicDrawing.py +13 -12
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/01_Tutorial_Shapes.py +34 -34
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/02_Tutorial_CellReferences.py +26 -24
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/03_Tutorial_GroupManipulation.py +24 -23
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/04_Tutorial_Boolean.py +23 -21
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/05_Tutorial_Devices.py +53 -43
- samplemaker_sparrow-5.4.7/tutorials/06_Tutorial_DeviceTables.py +66 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/07_Tutorial_Waveguides.py +45 -34
- samplemaker_sparrow-5.4.7/tutorials/08_Tutorial_WaveguideDevices.py +124 -0
- samplemaker_sparrow-5.4.7/tutorials/09_Tutorial_Circuits.py +105 -0
- samplemaker_sparrow-5.4.7/tutorials/10_Tutorial_ElectricalPorts.py +126 -0
- samplemaker_sparrow-5.4.7/tutorials/11_Tutorial_LayoutAssembly.py +74 -0
- samplemaker_sparrow-5.4.7/tutorials/12_Tutorial_ImportingCircuits.py +36 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/TutorialCollection.py +27 -21
- samplemaker_sparrow-5.4.7/uv.lock +606 -0
- samplemaker_sparrow-5.4.5/src/samplemaker/__init__.py +0 -36
- samplemaker_sparrow-5.4.5/src/samplemaker/baselib/__init__.py +0 -4
- samplemaker_sparrow-5.4.5/src/samplemaker/baselib/devices.py +0 -160
- samplemaker_sparrow-5.4.5/src/samplemaker/gdsreader.py +0 -251
- samplemaker_sparrow-5.4.5/src/samplemaker/gdswriter.py +0 -367
- samplemaker_sparrow-5.4.5/src/samplemaker/routers.py +0 -339
- samplemaker_sparrow-5.4.5/src/samplemaker/shapes.py +0 -2263
- samplemaker_sparrow-5.4.5/src/samplemaker/viewers.py +0 -234
- samplemaker_sparrow-5.4.5/tutorials/06_Tutorial_DeviceTables.py +0 -60
- samplemaker_sparrow-5.4.5/tutorials/08_Tutorial_WaveguideDevices.py +0 -93
- samplemaker_sparrow-5.4.5/tutorials/09_Tutorial_Circuits.py +0 -96
- samplemaker_sparrow-5.4.5/tutorials/10_Tutorial_ElectricalPorts.py +0 -114
- samplemaker_sparrow-5.4.5/tutorials/11_Tutorial_LayoutAssembly.py +0 -74
- samplemaker_sparrow-5.4.5/tutorials/12_Tutorial_ImportingCircuits.py +0 -39
- samplemaker_sparrow-5.4.5/uv.lock +0 -588
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/.github/workflows/build_wheels.yml +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/LICENSE.md +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/boopy/CMakeLists.txt +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/boopy/boopy.cpp +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/documentation.md +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/resources/__init__.py +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/resources/boopy.pyi +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/src/samplemaker/resources/sm_stencil_font.txt +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/.pylint.d/12_Tutorial_LayoutAssembly1.stats +0 -0
- {samplemaker_sparrow-5.4.5 → samplemaker_sparrow-5.4.7}/tutorials/CircuitFile.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: Fault
|
|
2
|
+
description: Report a bug or unexpected behavior
|
|
3
|
+
title: "Fault: "
|
|
4
|
+
labels: ["fault", "needs-triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: checkboxes
|
|
7
|
+
id: preflight
|
|
8
|
+
attributes:
|
|
9
|
+
label: Before filing
|
|
10
|
+
options:
|
|
11
|
+
- label: I have searched existing issues and this is not a duplicate
|
|
12
|
+
required: true
|
|
13
|
+
|
|
14
|
+
- type: textarea
|
|
15
|
+
id: what
|
|
16
|
+
attributes:
|
|
17
|
+
label: What is broken?
|
|
18
|
+
description: Which tool, system, or process is affected?
|
|
19
|
+
placeholder: "e.g. The data export stops partway through and shows an error"
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
|
|
23
|
+
- type: dropdown
|
|
24
|
+
id: regression
|
|
25
|
+
attributes:
|
|
26
|
+
label: Is this a regression?
|
|
27
|
+
description: Did this work correctly before?
|
|
28
|
+
options:
|
|
29
|
+
- "Unknown"
|
|
30
|
+
- "Yes - it worked before"
|
|
31
|
+
- "No - it has never worked"
|
|
32
|
+
validations:
|
|
33
|
+
required: false
|
|
34
|
+
|
|
35
|
+
- type: textarea
|
|
36
|
+
id: environment
|
|
37
|
+
attributes:
|
|
38
|
+
label: Where did this happen?
|
|
39
|
+
placeholder: |
|
|
40
|
+
- Computer / OS:
|
|
41
|
+
- Software version:
|
|
42
|
+
- Equipment:
|
|
43
|
+
validations:
|
|
44
|
+
required: true
|
|
45
|
+
|
|
46
|
+
- type: textarea
|
|
47
|
+
id: reproduce
|
|
48
|
+
attributes:
|
|
49
|
+
label: What were you doing when it happened?
|
|
50
|
+
description: Step by step if possible.
|
|
51
|
+
placeholder: |
|
|
52
|
+
1.
|
|
53
|
+
2.
|
|
54
|
+
3.
|
|
55
|
+
validations:
|
|
56
|
+
required: true
|
|
57
|
+
|
|
58
|
+
- type: textarea
|
|
59
|
+
id: expected
|
|
60
|
+
attributes:
|
|
61
|
+
label: What did you expect to happen?
|
|
62
|
+
placeholder: "e.g. The export completed and a file appeared in the output folder"
|
|
63
|
+
validations:
|
|
64
|
+
required: true
|
|
65
|
+
|
|
66
|
+
- type: textarea
|
|
67
|
+
id: actual
|
|
68
|
+
attributes:
|
|
69
|
+
label: What actually happened?
|
|
70
|
+
placeholder: "e.g. The program showed an error message and closed"
|
|
71
|
+
validations:
|
|
72
|
+
required: true
|
|
73
|
+
|
|
74
|
+
- type: textarea
|
|
75
|
+
id: logs
|
|
76
|
+
attributes:
|
|
77
|
+
label: Error messages (if any)
|
|
78
|
+
description: Copy and paste any error text here.
|
|
79
|
+
render: shell
|
|
80
|
+
validations:
|
|
81
|
+
required: false
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
name: Feature request
|
|
2
|
+
description: Suggest an idea for this project
|
|
3
|
+
title: "Feature: "
|
|
4
|
+
labels: ["feature", "needs-triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: need
|
|
8
|
+
attributes:
|
|
9
|
+
label: What problem does this solve?
|
|
10
|
+
description: Focus on the need, not the solution.
|
|
11
|
+
placeholder: "e.g. We have to manually copy files after every run, which takes time and is easy to forget"
|
|
12
|
+
validations:
|
|
13
|
+
required: true
|
|
14
|
+
- type: textarea
|
|
15
|
+
id: proposal
|
|
16
|
+
attributes:
|
|
17
|
+
label: What would you like it to do?
|
|
18
|
+
placeholder: "e.g. Automatically save results to a shared folder at the end of each run"
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: constraints
|
|
23
|
+
attributes:
|
|
24
|
+
label: Any requirements or limitations?
|
|
25
|
+
placeholder: "e.g. Must work without an internet connection; needs to support existing file formats"
|
|
26
|
+
validations:
|
|
27
|
+
required: false
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: acceptance
|
|
30
|
+
attributes:
|
|
31
|
+
label: How will we know it is done?
|
|
32
|
+
placeholder: |
|
|
33
|
+
- [ ]
|
|
34
|
+
- [ ]
|
|
35
|
+
validations:
|
|
36
|
+
required: true
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: context
|
|
39
|
+
attributes:
|
|
40
|
+
label: Anything else?
|
|
41
|
+
validations:
|
|
42
|
+
required: false
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Improvement
|
|
2
|
+
description: Suggest an improvement to this project
|
|
3
|
+
title: "Improvement: "
|
|
4
|
+
labels: ["improvement", "needs-triage"]
|
|
5
|
+
body:
|
|
6
|
+
- type: textarea
|
|
7
|
+
id: current
|
|
8
|
+
attributes:
|
|
9
|
+
label: What is the problem with how it works today?
|
|
10
|
+
placeholder: "e.g. The search only matches exact words, so it is easy to miss results with slightly different names"
|
|
11
|
+
validations:
|
|
12
|
+
required: true
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: proposed
|
|
15
|
+
attributes:
|
|
16
|
+
label: What would better look like?
|
|
17
|
+
placeholder: "e.g. Search should still find results when words are partially typed or spelled differently"
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: textarea
|
|
21
|
+
id: acceptance
|
|
22
|
+
attributes:
|
|
23
|
+
label: How will we know it is done?
|
|
24
|
+
placeholder: |
|
|
25
|
+
- [ ]
|
|
26
|
+
- [ ]
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
- type: textarea
|
|
30
|
+
id: context
|
|
31
|
+
attributes:
|
|
32
|
+
label: Anything else?
|
|
33
|
+
validations:
|
|
34
|
+
required: false
|
|
@@ -26,6 +26,9 @@ dist/
|
|
|
26
26
|
# JetBrains IDE
|
|
27
27
|
.idea/
|
|
28
28
|
|
|
29
|
+
# Visual Studio Code
|
|
30
|
+
.vscode/
|
|
31
|
+
|
|
29
32
|
# Unit test reports
|
|
30
33
|
TEST*.xml
|
|
31
34
|
|
|
@@ -54,7 +57,7 @@ Thumbs.db
|
|
|
54
57
|
*.gds
|
|
55
58
|
src/boopy/*.pro.user
|
|
56
59
|
html/
|
|
57
|
-
|
|
60
|
+
|
|
58
61
|
# Python build artifacts
|
|
59
62
|
build/
|
|
60
63
|
*.egg-info/
|
|
@@ -45,7 +45,19 @@ pip install -e .
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
### macOS
|
|
48
|
-
|
|
48
|
+
|
|
49
|
+
Install the required packages using Homebrew:
|
|
50
|
+
```bash
|
|
51
|
+
brew install cmake boost
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Navigate to the project directory and build:
|
|
55
|
+
```bash
|
|
56
|
+
# Using Astral uv (recommended)
|
|
57
|
+
uv sync
|
|
58
|
+
# Using pip
|
|
59
|
+
pip install -e .
|
|
60
|
+
```
|
|
49
61
|
|
|
50
62
|
### Windows
|
|
51
63
|
To build on Windows, ensure you have Visual Studio with C++ build tools installed.
|
|
@@ -113,7 +125,15 @@ cibuildwheel .
|
|
|
113
125
|
```
|
|
114
126
|
|
|
115
127
|
### macOS
|
|
116
|
-
|
|
128
|
+
On macOS, you can build wheels directly without Docker. Run the following command in the project directory:
|
|
129
|
+
```bash
|
|
130
|
+
# Using Astral uv (recommended)
|
|
131
|
+
uvx cibuildwheel .
|
|
132
|
+
|
|
133
|
+
# Using pip
|
|
134
|
+
pip install cibuildwheel
|
|
135
|
+
cibuildwheel .
|
|
136
|
+
```
|
|
117
137
|
|
|
118
138
|
### Windows
|
|
119
139
|
To build Windows wheels locally, the correct version of `vcpkg` must be added to the PATH environment variable.
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: samplemaker-sparrow
|
|
3
|
-
Version: 5.4.
|
|
3
|
+
Version: 5.4.7
|
|
4
4
|
Summary: Lithographic mask design package
|
|
5
|
-
Author-Email: Leonardo Midolo <midolo@nbi.ku.dk>
|
|
5
|
+
Author-Email: Leonardo Midolo <midolo@nbi.ku.dk>, Jeppe Roulund <jeppe.roulund@sparrowquantum.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
7
7
|
License-File: LICENSE.md
|
|
8
8
|
Classifier: Programming Language :: C++
|
|
9
9
|
Classifier: Programming Language :: Python
|
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
|
11
11
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
16
|
Classifier: Operating System :: Microsoft :: Windows
|
|
17
17
|
Classifier: Operating System :: MacOS
|
|
18
18
|
Classifier: Operating System :: Unix
|
|
19
19
|
Classifier: Operating System :: POSIX :: Linux
|
|
20
|
-
Project-URL: Repository, https://github.com/
|
|
21
|
-
Requires-Python: <3.
|
|
22
|
-
Requires-Dist: matplotlib>=3.
|
|
20
|
+
Project-URL: Repository, https://github.com/SparrowQuantum/samplemaker.git
|
|
21
|
+
Requires-Python: <3.15,>=3.11
|
|
22
|
+
Requires-Dist: matplotlib>=3.10.5
|
|
23
23
|
Requires-Dist: numpy==2.*
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
|
|
@@ -37,4 +37,10 @@ the European Research Council (ERC) under the European Union’s Horizon 2020 re
|
|
|
37
37
|
|
|
38
38
|
### How do I get set up?
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
The package can be installed on most platforms via pip:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install samplemaker-sparrow
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For local development build instructions, please refer to [BUILD.md](https://github.com/SparrowQuantum/samplemaker/blob/master/BUILD.md).
|
|
@@ -12,4 +12,10 @@ the European Research Council (ERC) under the European Union’s Horizon 2020 re
|
|
|
12
12
|
|
|
13
13
|
### How do I get set up?
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
The package can be installed on most platforms via pip:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install samplemaker-sparrow
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For local development build instructions, please refer to [BUILD.md](https://github.com/SparrowQuantum/samplemaker/blob/master/BUILD.md).
|
|
@@ -5,16 +5,17 @@ build-backend = "scikit_build_core.build"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "samplemaker-sparrow"
|
|
7
7
|
authors = [
|
|
8
|
-
{ name = "Leonardo Midolo", email = "midolo@nbi.ku.dk"}
|
|
8
|
+
{ name = "Leonardo Midolo", email = "midolo@nbi.ku.dk"},
|
|
9
|
+
{ name = "Jeppe Roulund", email = "jeppe.roulund@sparrowquantum.com"}
|
|
9
10
|
]
|
|
10
11
|
description = "Lithographic mask design package"
|
|
11
12
|
readme = "README.md"
|
|
12
|
-
requires-python = ">=3.
|
|
13
|
+
requires-python = ">=3.11,<3.15"
|
|
13
14
|
license-files = ["LICENSE.md"]
|
|
14
15
|
license = "BSD-3-Clause"
|
|
15
|
-
version = "5.4.
|
|
16
|
+
version = "5.4.7"
|
|
16
17
|
dependencies = [
|
|
17
|
-
"matplotlib>=3.
|
|
18
|
+
"matplotlib>=3.10.5",
|
|
18
19
|
"numpy==2.*",
|
|
19
20
|
]
|
|
20
21
|
classifiers = [
|
|
@@ -22,10 +23,10 @@ classifiers = [
|
|
|
22
23
|
"Programming Language :: Python",
|
|
23
24
|
"Programming Language :: Python :: 3",
|
|
24
25
|
"Programming Language :: Python :: 3 :: Only",
|
|
25
|
-
"Programming Language :: Python :: 3.10",
|
|
26
26
|
"Programming Language :: Python :: 3.11",
|
|
27
27
|
"Programming Language :: Python :: 3.12",
|
|
28
28
|
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Programming Language :: Python :: 3.14",
|
|
29
30
|
"Operating System :: Microsoft :: Windows",
|
|
30
31
|
"Operating System :: MacOS",
|
|
31
32
|
"Operating System :: Unix",
|
|
@@ -33,7 +34,7 @@ classifiers = [
|
|
|
33
34
|
]
|
|
34
35
|
|
|
35
36
|
[project.urls]
|
|
36
|
-
Repository = "https://github.com/
|
|
37
|
+
Repository = "https://github.com/SparrowQuantum/samplemaker.git"
|
|
37
38
|
|
|
38
39
|
[tool.scikit-build]
|
|
39
40
|
minimum-version = "0.11.6"
|
|
@@ -44,6 +45,9 @@ wheel.packages = ["src/samplemaker"]
|
|
|
44
45
|
|
|
45
46
|
[tool.cibuildwheel]
|
|
46
47
|
skip = ["*-musllinux*", "*-win32*"]
|
|
48
|
+
test-requires = "pytest"
|
|
49
|
+
test-sources = ["tests"]
|
|
50
|
+
test-command = "pytest {project}/tests"
|
|
47
51
|
|
|
48
52
|
[tool.cibuildwheel.linux]
|
|
49
53
|
before-all = "yum install -y boost-devel"
|
|
@@ -56,3 +60,9 @@ environment = { BOOST_ROOT = "C:/vcpkg/installed/x64-windows" }
|
|
|
56
60
|
before-all = [
|
|
57
61
|
"vcpkg install boost-polygon:x64-windows",
|
|
58
62
|
]
|
|
63
|
+
|
|
64
|
+
[dependency-groups]
|
|
65
|
+
dev = [
|
|
66
|
+
"pytest==9.0.2",
|
|
67
|
+
"ruff==0.15.1",
|
|
68
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
|
|
3
|
+
This is the Python version of Sample Maker, a scripting tool for designing lithographic
|
|
4
|
+
masks in the GDSII format. Package `samplemaker` comes with different tools and
|
|
5
|
+
submodules for the creation and manipulation of basic shapes, periodic shapes, sequences
|
|
6
|
+
(e.g. waveguides), circuits, and complex devices.
|
|
7
|
+
|
|
8
|
+
The code has been developed primarily for nanophotonics, but it can be easily extended
|
|
9
|
+
to different applications in micro and nano device fabrication.
|
|
10
|
+
|
|
11
|
+
Sample Maker is developed and maintained by Leonardo Midolo (Niels Bohr Institute,
|
|
12
|
+
University of Copenhagen). It is based on the MATLAB(R) code developed by Leonardo
|
|
13
|
+
Midolo between 2013 and 2019. The first version of the rewritten Python code has been
|
|
14
|
+
released in October 2021.
|
|
15
|
+
|
|
16
|
+
This software has been realized with the financial support from
|
|
17
|
+
the European Research Council (ERC) under the European Union’s Horizon 2020 research and
|
|
18
|
+
innovation programme (Grant agreement No. 949043, NANOMEQ).
|
|
19
|
+
|
|
20
|
+
.. include:: ./documentation.md
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
__pdoc__: dict[str, bool | str] = {
|
|
24
|
+
"samplemaker.Tutorials": False,
|
|
25
|
+
"samplemaker.tests": False,
|
|
26
|
+
"samplemaker.resources": False,
|
|
27
|
+
"samplemaker.gdsreader": False,
|
|
28
|
+
"samplemaker.devices.DevicePort": False,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
# The LayoutPool contains all the current layout, this class should generally not
|
|
32
|
+
# be used directly, but only through the Mask class.
|
|
33
|
+
LayoutPool = {} # connects a SREF name to a particular geomgroup in the current memory
|
|
34
|
+
|
|
35
|
+
# Additional cache pool:
|
|
36
|
+
|
|
37
|
+
# _DevicePool Connects a device hash to a SREF to be instantiated:
|
|
38
|
+
_DevicePool = {}
|
|
39
|
+
|
|
40
|
+
# _DeviceLocalParamPool connects a device hash to local parameters created by the call
|
|
41
|
+
# to geom():
|
|
42
|
+
_DeviceLocalParamPool = {}
|
|
43
|
+
|
|
44
|
+
# _DeviceCountPool connects a device name to a device count
|
|
45
|
+
_DeviceCountPool = {}
|
|
46
|
+
|
|
47
|
+
# _BoundingBoxPool connects a SREF name to its bounding box
|
|
48
|
+
_BoundingBoxPool = {}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base device library.
|
|
3
|
+
|
|
4
|
+
This is a collection of some simple demo devices distributed with the base version of
|
|
5
|
+
`samplemaker`. It can be used as template for creating new libraries or to learn how to
|
|
6
|
+
design them.
|
|
7
|
+
|
|
8
|
+
Note that individual device methods are not documented but should be readable and
|
|
9
|
+
self-explanatory.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import math
|
|
13
|
+
|
|
14
|
+
import numpy as np
|
|
15
|
+
|
|
16
|
+
import samplemaker.makers as sm
|
|
17
|
+
from samplemaker.baselib.waveguides import BaseWaveguidePort, BaseWaveguideSequencer
|
|
18
|
+
from samplemaker.devices import Device, registerDevicesInModule
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CrossMark(Device):
|
|
22
|
+
def initialize(self):
|
|
23
|
+
self.set_name("BASELIB_CMARK")
|
|
24
|
+
self.set_description("Generic cross marker for mask alignment.")
|
|
25
|
+
|
|
26
|
+
def parameters(self):
|
|
27
|
+
self.addparameter(
|
|
28
|
+
param_name="length1",
|
|
29
|
+
default_value=20,
|
|
30
|
+
param_description="Length of inner cross",
|
|
31
|
+
param_type=float,
|
|
32
|
+
)
|
|
33
|
+
self.addparameter(
|
|
34
|
+
param_name="length2",
|
|
35
|
+
default_value=10,
|
|
36
|
+
param_description="Length of outer cross",
|
|
37
|
+
param_type=float,
|
|
38
|
+
)
|
|
39
|
+
self.addparameter(
|
|
40
|
+
param_name="width1",
|
|
41
|
+
default_value=0.5,
|
|
42
|
+
param_description="Width of inner cross",
|
|
43
|
+
param_type=float,
|
|
44
|
+
)
|
|
45
|
+
self.addparameter(
|
|
46
|
+
param_name="width2",
|
|
47
|
+
default_value=2,
|
|
48
|
+
param_description="width of outer cross",
|
|
49
|
+
param_type=float,
|
|
50
|
+
)
|
|
51
|
+
self.addparameter(
|
|
52
|
+
param_name="layer",
|
|
53
|
+
default_value=4,
|
|
54
|
+
param_description="Layer to use for cross",
|
|
55
|
+
param_type=int,
|
|
56
|
+
param_range=(0, 255),
|
|
57
|
+
)
|
|
58
|
+
self.addparameter(
|
|
59
|
+
param_name="mark_number",
|
|
60
|
+
default_value=0,
|
|
61
|
+
param_description="Places a square in the corner, use 0 to remove",
|
|
62
|
+
param_type=float,
|
|
63
|
+
param_range=(0, 4),
|
|
64
|
+
)
|
|
65
|
+
self.addparameter(
|
|
66
|
+
param_name="square_size",
|
|
67
|
+
default_value=10,
|
|
68
|
+
param_description="Size of the square in the corner",
|
|
69
|
+
param_type=float,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def geom(self):
|
|
73
|
+
p = self.get_params()
|
|
74
|
+
cross = sm.make_rect(0, 0, p["length1"], p["width1"], layer=1)
|
|
75
|
+
cross += sm.make_rect(0, 0, p["width1"], p["length1"], layer=1)
|
|
76
|
+
cross.boolean_union(1)
|
|
77
|
+
ocross = sm.make_rect(p["length1"] / 2, 0, p["length2"], p["width2"], numkey=4)
|
|
78
|
+
for i in range(4):
|
|
79
|
+
c = ocross.copy()
|
|
80
|
+
c.rotate(0, 0, 90 * i)
|
|
81
|
+
cross += c
|
|
82
|
+
if p["mark_number"] > 0:
|
|
83
|
+
rot = 90 * (p["mark_number"] - 1)
|
|
84
|
+
sq_dim = p["length1"] / 2 + p["length2"]
|
|
85
|
+
sq_size = p["square_size"]
|
|
86
|
+
square = sm.make_rect(sq_dim, sq_dim, sq_size, sq_size, numkey=1)
|
|
87
|
+
square.rotate(0, 0, rot)
|
|
88
|
+
cross += square
|
|
89
|
+
|
|
90
|
+
cross.set_layer(p["layer"])
|
|
91
|
+
return cross
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class DirectionalCoupler(Device):
|
|
95
|
+
def initialize(self):
|
|
96
|
+
self.set_name("BASELIB_DCPL")
|
|
97
|
+
self.set_description("Simple symmetric directional coupler")
|
|
98
|
+
|
|
99
|
+
def parameters(self):
|
|
100
|
+
self.addparameter("length", 20, "Coupling length", float)
|
|
101
|
+
self.addparameter(
|
|
102
|
+
param_name="width",
|
|
103
|
+
default_value=0.3,
|
|
104
|
+
param_description="Width of the waveguides in the coupling section",
|
|
105
|
+
param_type=float,
|
|
106
|
+
param_range=(0.01, 1),
|
|
107
|
+
)
|
|
108
|
+
self.addparameter(
|
|
109
|
+
param_name="gap",
|
|
110
|
+
default_value=0.5,
|
|
111
|
+
param_description="Distance between waveguides in the coupling section",
|
|
112
|
+
param_type=float,
|
|
113
|
+
)
|
|
114
|
+
self.addparameter(
|
|
115
|
+
param_name="input_dist",
|
|
116
|
+
default_value=5,
|
|
117
|
+
param_description="Distance between waveguides at input",
|
|
118
|
+
param_type=float,
|
|
119
|
+
param_range=(0.01, np.inf),
|
|
120
|
+
)
|
|
121
|
+
self.addparameter(
|
|
122
|
+
param_name="input_len",
|
|
123
|
+
default_value=7,
|
|
124
|
+
param_description="Length of the input section from input to coupling",
|
|
125
|
+
param_type=float,
|
|
126
|
+
param_range=(3, np.inf),
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def geom(self):
|
|
130
|
+
p = self.get_params()
|
|
131
|
+
# Draw the upper arm, then mirror
|
|
132
|
+
off = p["input_dist"] / 2
|
|
133
|
+
clen = (p["input_len"] - 1) / 2
|
|
134
|
+
ltot = p["length"] + p["input_len"] * 2
|
|
135
|
+
seq = [["T", 1, p["width"]], ["C", -off, clen], ["S", p["length"] / 2]]
|
|
136
|
+
ss = BaseWaveguideSequencer(seq)
|
|
137
|
+
dc = ss.run()
|
|
138
|
+
dc2 = dc.copy()
|
|
139
|
+
dc2.mirrorX(ltot / 2)
|
|
140
|
+
dc += dc2
|
|
141
|
+
dc.translate(-ltot / 2, off + p["gap"] / 2 + p["width"] / 2)
|
|
142
|
+
dc3 = dc.copy()
|
|
143
|
+
dc3.mirrorY(0)
|
|
144
|
+
dc += dc3
|
|
145
|
+
|
|
146
|
+
# Add ports
|
|
147
|
+
xp = ltot / 2
|
|
148
|
+
yp = off + p["gap"] / 2 + p["width"] / 2
|
|
149
|
+
nw_port = BaseWaveguidePort(-xp, yp, "west", ss.options["defaultWidth"], "p1")
|
|
150
|
+
ne_port = BaseWaveguidePort(xp, yp, "east", ss.options["defaultWidth"], "p2")
|
|
151
|
+
sw_port = BaseWaveguidePort(-xp, -yp, "west", ss.options["defaultWidth"], "p3")
|
|
152
|
+
se_port = BaseWaveguidePort(xp, -yp, "east", ss.options["defaultWidth"], "p4")
|
|
153
|
+
for port in (nw_port, ne_port, sw_port, se_port):
|
|
154
|
+
self.addlocalport(port)
|
|
155
|
+
|
|
156
|
+
return dc
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class FocusingGratingCoupler(Device):
|
|
160
|
+
def initialize(self):
|
|
161
|
+
self.set_name("BASELIB_FGC")
|
|
162
|
+
self.set_description("Grating coupler demo.")
|
|
163
|
+
|
|
164
|
+
def parameters(self):
|
|
165
|
+
self.addparameter(
|
|
166
|
+
param_name="w0",
|
|
167
|
+
default_value=0.3,
|
|
168
|
+
param_description="Width of the waveguide at the start",
|
|
169
|
+
param_type=float,
|
|
170
|
+
)
|
|
171
|
+
self.addparameter(
|
|
172
|
+
param_name="pitch",
|
|
173
|
+
default_value=0.355,
|
|
174
|
+
param_description="Grating default pitch",
|
|
175
|
+
param_type=float,
|
|
176
|
+
)
|
|
177
|
+
self.addparameter(
|
|
178
|
+
param_name="ff",
|
|
179
|
+
default_value=0.5,
|
|
180
|
+
param_description="Fill factor",
|
|
181
|
+
param_type=float,
|
|
182
|
+
)
|
|
183
|
+
self.addparameter(
|
|
184
|
+
param_name="theta",
|
|
185
|
+
default_value=10,
|
|
186
|
+
param_description="Emission angle at central wavelength",
|
|
187
|
+
param_type=float,
|
|
188
|
+
)
|
|
189
|
+
self.addparameter(
|
|
190
|
+
param_name="lambda0",
|
|
191
|
+
default_value=0.94,
|
|
192
|
+
param_description="Central wavelength",
|
|
193
|
+
param_type=float,
|
|
194
|
+
)
|
|
195
|
+
self.addparameter(
|
|
196
|
+
param_name="nr_Apo",
|
|
197
|
+
default_value=11,
|
|
198
|
+
param_description="nr of the 1st arc with pitch and ff",
|
|
199
|
+
param_type=int,
|
|
200
|
+
)
|
|
201
|
+
self.addparameter(
|
|
202
|
+
param_name="ff_coef",
|
|
203
|
+
default_value=0.5,
|
|
204
|
+
param_description="min ff_apod = ff_coef*ff",
|
|
205
|
+
param_type=float,
|
|
206
|
+
)
|
|
207
|
+
self.addparameter(
|
|
208
|
+
param_name="order_start",
|
|
209
|
+
default_value=10,
|
|
210
|
+
param_description="Starting period",
|
|
211
|
+
param_type=int,
|
|
212
|
+
)
|
|
213
|
+
self.addparameter(
|
|
214
|
+
param_name="order",
|
|
215
|
+
default_value=15,
|
|
216
|
+
param_description="Number of periods",
|
|
217
|
+
param_type=int,
|
|
218
|
+
)
|
|
219
|
+
self.addparameter(
|
|
220
|
+
param_name="diverg_angle",
|
|
221
|
+
default_value=20,
|
|
222
|
+
param_description="GRT divergence angle/2, deg",
|
|
223
|
+
param_type=float,
|
|
224
|
+
)
|
|
225
|
+
self.addparameter(
|
|
226
|
+
param_name="pre_split",
|
|
227
|
+
default_value=True,
|
|
228
|
+
param_description="Split in quads = false",
|
|
229
|
+
param_type=bool,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
def geom(self):
|
|
233
|
+
# Grating first
|
|
234
|
+
p = self.get_params()
|
|
235
|
+
theta = math.radians(p["theta"])
|
|
236
|
+
div_angle = p["diverg_angle"]
|
|
237
|
+
q0 = p["order_start"]
|
|
238
|
+
qn = q0 + p["order"] + 1
|
|
239
|
+
lambda0 = p["lambda0"]
|
|
240
|
+
pitch = p["pitch"]
|
|
241
|
+
n = math.sin(theta) + lambda0 / pitch # Effective refractive index
|
|
242
|
+
p0 = lambda0 / math.sqrt(n * n - np.power(math.sin(theta), 2))
|
|
243
|
+
ff = p["ff"]
|
|
244
|
+
nr_apo = p["nr_Apo"]
|
|
245
|
+
ff_coef = p["ff_coef"]
|
|
246
|
+
|
|
247
|
+
g = sm.GeomGroup()
|
|
248
|
+
for q in range(q0, qn):
|
|
249
|
+
b = q * p0
|
|
250
|
+
x0 = b * b * math.sin(theta) / (q * lambda0)
|
|
251
|
+
a = b * b * n / (q * lambda0)
|
|
252
|
+
if q <= q0 + nr_apo - 1:
|
|
253
|
+
ff_chi = ff - (1 - ff_coef) * ff / (nr_apo - 2) * (q0 + nr_apo - q)
|
|
254
|
+
else:
|
|
255
|
+
ff_chi = ff
|
|
256
|
+
|
|
257
|
+
w = ff_chi * pitch
|
|
258
|
+
g += sm.make_arc(
|
|
259
|
+
x0=x0,
|
|
260
|
+
y0=0,
|
|
261
|
+
rX=a,
|
|
262
|
+
rY=b,
|
|
263
|
+
rot=0,
|
|
264
|
+
w=w,
|
|
265
|
+
a1=-div_angle - 5,
|
|
266
|
+
a2=div_angle + 5,
|
|
267
|
+
layer=3,
|
|
268
|
+
to_poly=True,
|
|
269
|
+
vertices=40,
|
|
270
|
+
split=p["pre_split"],
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
# waveguide
|
|
274
|
+
l_taper = 1
|
|
275
|
+
g_taper = qn * pitch
|
|
276
|
+
w_taper = g_taper * math.tan(math.radians(div_angle)) * 2
|
|
277
|
+
|
|
278
|
+
seq = [
|
|
279
|
+
["T", l_taper, p["w0"]],
|
|
280
|
+
["CENTER", 0, 0],
|
|
281
|
+
["T", g_taper, w_taper],
|
|
282
|
+
["STATE", "w", 2.5],
|
|
283
|
+
["S", 1],
|
|
284
|
+
]
|
|
285
|
+
|
|
286
|
+
ss = BaseWaveguideSequencer(seq)
|
|
287
|
+
g += ss.run()
|
|
288
|
+
|
|
289
|
+
self.addlocalport(BaseWaveguidePort(-l_taper, 0, "west", p["w0"], "p1"))
|
|
290
|
+
|
|
291
|
+
return g
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
# Register all devices here in this module
|
|
295
|
+
registerDevicesInModule(__name__)
|