samplemaker-sparrow 5.4.8__tar.gz → 5.4.9__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.8 → samplemaker_sparrow-5.4.9}/.github/workflows/build_wheels.yml +2 -2
- samplemaker_sparrow-5.4.9/.github/workflows/ruff.yml +19 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/.gitignore +4 -0
- samplemaker_sparrow-5.4.9/.python-version +1 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/PKG-INFO +2 -1
- samplemaker_sparrow-5.4.9/flake.lock +61 -0
- samplemaker_sparrow-5.4.9/flake.nix +96 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/pyproject.toml +50 -14
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/__init__.py +8 -8
- samplemaker_sparrow-5.4.9/src/samplemaker/_legacy.py +142 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/baselib/__init__.py +2 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/baselib/devices.py +90 -18
- samplemaker_sparrow-5.4.9/src/samplemaker/baselib/waveguides.py +688 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/devices.py +894 -447
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/gdsreader.py +58 -27
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/gdswriter.py +146 -134
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/layout.py +617 -311
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/makers.py +170 -137
- samplemaker_sparrow-5.4.9/src/samplemaker/phc.py +686 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/resources/__init__.py +1 -2
- samplemaker_sparrow-5.4.9/src/samplemaker/routers.py +419 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/sequencer.py +125 -63
- samplemaker_sparrow-5.4.9/src/samplemaker/shapes.py +4381 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/viewers.py +100 -52
- samplemaker_sparrow-5.4.9/tests/__init__.py +4 -0
- samplemaker_sparrow-5.4.9/tests/conftest.py +60 -0
- samplemaker_sparrow-5.4.9/tests/dummy.py +107 -0
- samplemaker_sparrow-5.4.9/tests/fakes.py +51 -0
- samplemaker_sparrow-5.4.9/tests/test_baselib_devices.py +128 -0
- samplemaker_sparrow-5.4.9/tests/test_baselib_waveguides.py +332 -0
- samplemaker_sparrow-5.4.9/tests/test_devices.py +691 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tests/test_gdsreader.py +6 -9
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tests/test_gdswriter.py +7 -8
- samplemaker_sparrow-5.4.9/tests/test_layout.py +839 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tests/test_makers.py +26 -25
- samplemaker_sparrow-5.4.9/tests/test_phc.py +369 -0
- samplemaker_sparrow-5.4.9/tests/test_routers.py +217 -0
- samplemaker_sparrow-5.4.9/tests/test_sequencer.py +504 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tests/test_shapes.py +127 -123
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/00_Tutorial_BasicDrawing.py +6 -6
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/01_Tutorial_Shapes.py +2 -2
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/02_Tutorial_CellReferences.py +5 -5
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/03_Tutorial_GroupManipulation.py +3 -3
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/04_Tutorial_Boolean.py +2 -2
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/05_Tutorial_Devices.py +6 -6
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/06_Tutorial_DeviceTables.py +2 -2
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/07_Tutorial_Waveguides.py +2 -2
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/08_Tutorial_WaveguideDevices.py +6 -6
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/09_Tutorial_Circuits.py +3 -3
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/10_Tutorial_ElectricalPorts.py +6 -4
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/11_Tutorial_LayoutAssembly.py +5 -5
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/12_Tutorial_ImportingCircuits.py +4 -4
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/TutorialCollection.py +3 -3
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/uv.lock +186 -1
- samplemaker_sparrow-5.4.8/src/samplemaker/baselib/waveguides.py +0 -358
- samplemaker_sparrow-5.4.8/src/samplemaker/phc.py +0 -528
- samplemaker_sparrow-5.4.8/src/samplemaker/routers.py +0 -352
- samplemaker_sparrow-5.4.8/src/samplemaker/shapes.py +0 -2362
- samplemaker_sparrow-5.4.8/tests/fixtures.py +0 -19
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/.github/ISSUE_TEMPLATE/fault.yml +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/.github/ISSUE_TEMPLATE/improvement.yml +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/BUILD.md +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/LICENSE.md +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/README.md +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/boopy/CMakeLists.txt +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/boopy/boopy.cpp +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/documentation.md +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/resources/boopy.pyi +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/src/samplemaker/resources/sm_stencil_font.txt +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/.pylint.d/12_Tutorial_LayoutAssembly1.stats +0 -0
- {samplemaker_sparrow-5.4.8 → samplemaker_sparrow-5.4.9}/tutorials/CircuitFile.txt +0 -0
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
- name: Build wheels
|
|
26
26
|
uses: pypa/cibuildwheel@v3.3.0
|
|
27
27
|
|
|
28
|
-
- uses: actions/upload-artifact@
|
|
28
|
+
- uses: actions/upload-artifact@v7
|
|
29
29
|
with:
|
|
30
30
|
name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }}
|
|
31
31
|
path: ./wheelhouse/*.whl
|
|
@@ -41,7 +41,7 @@ jobs:
|
|
|
41
41
|
- name: Build SDist
|
|
42
42
|
run: pipx run build --sdist
|
|
43
43
|
|
|
44
|
-
- uses: actions/upload-artifact@
|
|
44
|
+
- uses: actions/upload-artifact@v7
|
|
45
45
|
with:
|
|
46
46
|
name: cibw-sdist
|
|
47
47
|
path: dist/*.tar.gz
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Ruff Check
|
|
2
|
+
on: push
|
|
3
|
+
jobs:
|
|
4
|
+
build:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
steps:
|
|
7
|
+
- uses: actions/checkout@v4
|
|
8
|
+
- name: Install Python
|
|
9
|
+
uses: actions/setup-python@v5
|
|
10
|
+
with:
|
|
11
|
+
python-version: "3.13"
|
|
12
|
+
- name: Install dependencies
|
|
13
|
+
run: |
|
|
14
|
+
python -m pip install --upgrade pip
|
|
15
|
+
pip install ruff==0.15.1
|
|
16
|
+
- name: Run Ruff Linter
|
|
17
|
+
run: ruff check --output-format=github .
|
|
18
|
+
- name: Check Ruff formatting
|
|
19
|
+
run: ruff format --check --diff .
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13.13
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: samplemaker-sparrow
|
|
3
|
-
Version: 5.4.
|
|
3
|
+
Version: 5.4.9
|
|
4
4
|
Summary: Lithographic mask design package
|
|
5
5
|
Author-Email: Leonardo Midolo <midolo@nbi.ku.dk>, Jeppe Roulund <jeppe.roulund@sparrowquantum.com>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -19,6 +19,7 @@ Classifier: Operating System :: Unix
|
|
|
19
19
|
Classifier: Operating System :: POSIX :: Linux
|
|
20
20
|
Project-URL: Repository, https://github.com/SparrowQuantum/samplemaker.git
|
|
21
21
|
Requires-Python: <3.15,>=3.11
|
|
22
|
+
Requires-Dist: asteval>=1.0.9
|
|
22
23
|
Requires-Dist: matplotlib>=3.10.5
|
|
23
24
|
Requires-Dist: numpy==2.*
|
|
24
25
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nodes": {
|
|
3
|
+
"flake-utils": {
|
|
4
|
+
"inputs": {
|
|
5
|
+
"systems": "systems"
|
|
6
|
+
},
|
|
7
|
+
"locked": {
|
|
8
|
+
"lastModified": 1731533236,
|
|
9
|
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
10
|
+
"owner": "numtide",
|
|
11
|
+
"repo": "flake-utils",
|
|
12
|
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
13
|
+
"type": "github"
|
|
14
|
+
},
|
|
15
|
+
"original": {
|
|
16
|
+
"owner": "numtide",
|
|
17
|
+
"repo": "flake-utils",
|
|
18
|
+
"type": "github"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"nixpkgs": {
|
|
22
|
+
"locked": {
|
|
23
|
+
"lastModified": 1780749050,
|
|
24
|
+
"narHash": "sha256-3av0pIjlOWQ6rDbNOmpUSvbNnJkGORQKKjb4LtCZsIY=",
|
|
25
|
+
"owner": "NixOS",
|
|
26
|
+
"repo": "nixpkgs",
|
|
27
|
+
"rev": "a799d3e3886da994fa307f817a6bc705ae538eeb",
|
|
28
|
+
"type": "github"
|
|
29
|
+
},
|
|
30
|
+
"original": {
|
|
31
|
+
"owner": "NixOS",
|
|
32
|
+
"ref": "nixos-unstable",
|
|
33
|
+
"repo": "nixpkgs",
|
|
34
|
+
"type": "github"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"root": {
|
|
38
|
+
"inputs": {
|
|
39
|
+
"flake-utils": "flake-utils",
|
|
40
|
+
"nixpkgs": "nixpkgs"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"systems": {
|
|
44
|
+
"locked": {
|
|
45
|
+
"lastModified": 1681028828,
|
|
46
|
+
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
47
|
+
"owner": "nix-systems",
|
|
48
|
+
"repo": "default",
|
|
49
|
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
50
|
+
"type": "github"
|
|
51
|
+
},
|
|
52
|
+
"original": {
|
|
53
|
+
"owner": "nix-systems",
|
|
54
|
+
"repo": "default",
|
|
55
|
+
"type": "github"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"root": "root",
|
|
60
|
+
"version": 7
|
|
61
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
description = "samplemaker-sparrow lithographic mask design package";
|
|
3
|
+
|
|
4
|
+
inputs = {
|
|
5
|
+
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
6
|
+
flake-utils.url = "github:numtide/flake-utils";
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
outputs = {
|
|
10
|
+
nixpkgs,
|
|
11
|
+
flake-utils,
|
|
12
|
+
...
|
|
13
|
+
}:
|
|
14
|
+
flake-utils.lib.eachDefaultSystem (
|
|
15
|
+
system: let
|
|
16
|
+
pkgs = nixpkgs.legacyPackages.${system};
|
|
17
|
+
python = pkgs.python313;
|
|
18
|
+
pyPkgs = python.pkgs;
|
|
19
|
+
|
|
20
|
+
pyProj = pkgs.lib.trivial.importTOML ./pyproject.toml;
|
|
21
|
+
samplemaker = pyPkgs.buildPythonPackage {
|
|
22
|
+
pname = "samplemaker-sparrow";
|
|
23
|
+
version = pyProj.project.version;
|
|
24
|
+
pyproject = true;
|
|
25
|
+
|
|
26
|
+
src = ./.;
|
|
27
|
+
|
|
28
|
+
build-system = [
|
|
29
|
+
pyPkgs.scikit-build-core
|
|
30
|
+
pyPkgs.pybind11
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
nativeBuildInputs = [
|
|
34
|
+
pkgs.cmake
|
|
35
|
+
pkgs.ninja
|
|
36
|
+
];
|
|
37
|
+
|
|
38
|
+
buildInputs = [
|
|
39
|
+
pkgs.boost.dev
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
dependencies = [
|
|
43
|
+
pyPkgs.matplotlib
|
|
44
|
+
pyPkgs.numpy
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
# scikit-build-core invokes cmake internally; skip Nix's cmake configure hook
|
|
48
|
+
dontUseCmakeConfigure = true;
|
|
49
|
+
|
|
50
|
+
meta = with pkgs.lib; {
|
|
51
|
+
description = "Lithographic mask design package";
|
|
52
|
+
homepage = "https://github.com/SparrowQuantum/samplemaker";
|
|
53
|
+
license = licenses.bsd3;
|
|
54
|
+
};
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
devEnv = python.withPackages (ps: [
|
|
58
|
+
samplemaker
|
|
59
|
+
ps.pytest
|
|
60
|
+
ps.pytest-cov
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
fmtPackage = pkgs.writeShellScriptBin "fmt" ''
|
|
64
|
+
${pkgs.alejandra}/bin/alejandra . --quiet
|
|
65
|
+
'';
|
|
66
|
+
in {
|
|
67
|
+
packages = {
|
|
68
|
+
default = samplemaker;
|
|
69
|
+
samplemaker = samplemaker;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
devShells = {
|
|
73
|
+
default = pkgs.mkShell {
|
|
74
|
+
packages = [
|
|
75
|
+
pkgs.ruff
|
|
76
|
+
pkgs.alejandra
|
|
77
|
+
pkgs.deadnix
|
|
78
|
+
devEnv
|
|
79
|
+
];
|
|
80
|
+
};
|
|
81
|
+
uv = pkgs.mkShell {
|
|
82
|
+
packages = with pkgs; [
|
|
83
|
+
uv
|
|
84
|
+
cmake
|
|
85
|
+
ninja
|
|
86
|
+
boost.dev
|
|
87
|
+
alejandra
|
|
88
|
+
deadnix
|
|
89
|
+
];
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
formatter = fmtPackage;
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
}
|
|
@@ -5,19 +5,16 @@ 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"},
|
|
9
|
-
{ name = "Jeppe Roulund", email = "jeppe.roulund@sparrowquantum.com"}
|
|
8
|
+
{ name = "Leonardo Midolo", email = "midolo@nbi.ku.dk" },
|
|
9
|
+
{ name = "Jeppe Roulund", email = "jeppe.roulund@sparrowquantum.com" },
|
|
10
10
|
]
|
|
11
11
|
description = "Lithographic mask design package"
|
|
12
12
|
readme = "README.md"
|
|
13
13
|
requires-python = ">=3.11,<3.15"
|
|
14
14
|
license-files = ["LICENSE.md"]
|
|
15
15
|
license = "BSD-3-Clause"
|
|
16
|
-
version = "5.4.
|
|
17
|
-
dependencies = [
|
|
18
|
-
"matplotlib>=3.10.5",
|
|
19
|
-
"numpy==2.*",
|
|
20
|
-
]
|
|
16
|
+
version = "5.4.9"
|
|
17
|
+
dependencies = ["asteval>=1.0.9", "matplotlib>=3.10.5", "numpy==2.*"]
|
|
21
18
|
classifiers = [
|
|
22
19
|
"Programming Language :: C++",
|
|
23
20
|
"Programming Language :: Python",
|
|
@@ -36,6 +33,50 @@ classifiers = [
|
|
|
36
33
|
[project.urls]
|
|
37
34
|
Repository = "https://github.com/SparrowQuantum/samplemaker.git"
|
|
38
35
|
|
|
36
|
+
[tool.ruff]
|
|
37
|
+
extend-exclude = ["tutorials/*"]
|
|
38
|
+
|
|
39
|
+
[tool.ruff.lint]
|
|
40
|
+
extend-select = [
|
|
41
|
+
"D", # Pydocstyle
|
|
42
|
+
"E", # Pycodestyle errors
|
|
43
|
+
"W", # Pycodestyle warnings
|
|
44
|
+
"ANN", # flake8-annotations
|
|
45
|
+
"BLE", # flake8-blind-except
|
|
46
|
+
"B", # flake8-bugbear
|
|
47
|
+
"S", # flake8-bandit
|
|
48
|
+
"A", # flake8-builtins
|
|
49
|
+
"C4", # flake8-comprehensions
|
|
50
|
+
"T100", # flake8-debugger
|
|
51
|
+
"EM", # flake8-errmsg
|
|
52
|
+
"FIX", # flake8-fixme
|
|
53
|
+
"INP", # flake8-no-pep420
|
|
54
|
+
"PIE", # flake8-pie
|
|
55
|
+
"PYI", # flake8-pyi
|
|
56
|
+
"PT", # flake8-pytest-style
|
|
57
|
+
"RSE", # flake8-raise
|
|
58
|
+
"RET", # flake8-return
|
|
59
|
+
"SIM", # flake8-simplify
|
|
60
|
+
"TC", # flake8-type-checking
|
|
61
|
+
"ARG", # flake8-unused-arguments
|
|
62
|
+
"PTH", # flake8-use-pathlib
|
|
63
|
+
"I", # isort
|
|
64
|
+
"NPY", # Numpy specific rules
|
|
65
|
+
"UP", # Pyupgrade
|
|
66
|
+
"F", # pyflakes
|
|
67
|
+
"PL", # pylint
|
|
68
|
+
"FURB", # refurb
|
|
69
|
+
"RUF", # ruff
|
|
70
|
+
"PGH", # pygrep-hooks
|
|
71
|
+
"PERF", # perflint
|
|
72
|
+
"N", # pep8-naming
|
|
73
|
+
]
|
|
74
|
+
ignore = ["D203", "D213", "PLR2004", "PLR091"]
|
|
75
|
+
|
|
76
|
+
[tool.ruff.lint.extend-per-file-ignores]
|
|
77
|
+
"tests/*" = ["D1", "S101", "ARG"]
|
|
78
|
+
"*.pyi" = ["N802"]
|
|
79
|
+
|
|
39
80
|
[tool.scikit-build]
|
|
40
81
|
minimum-version = "0.11.6"
|
|
41
82
|
build-dir = "build/{wheel_tag}"
|
|
@@ -57,12 +98,7 @@ before-all = "brew install boost"
|
|
|
57
98
|
|
|
58
99
|
[tool.cibuildwheel.windows]
|
|
59
100
|
environment = { BOOST_ROOT = "C:/vcpkg/installed/x64-windows" }
|
|
60
|
-
before-all = [
|
|
61
|
-
"vcpkg install boost-polygon:x64-windows",
|
|
62
|
-
]
|
|
101
|
+
before-all = ["vcpkg install boost-polygon:x64-windows"]
|
|
63
102
|
|
|
64
103
|
[dependency-groups]
|
|
65
|
-
dev = [
|
|
66
|
-
"pytest==9.0.2",
|
|
67
|
-
"ruff==0.15.1",
|
|
68
|
-
]
|
|
104
|
+
dev = ["pytest==9.0.2", "pytest-cov==7.1.0", "ruff==0.15.1"]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""The Python version of Sample Maker.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Sample Maker is a scripting tool for designing lithographic masks in the GDSII format.
|
|
4
|
+
The package `samplemaker` comes with different tools and submodules for the creation
|
|
5
|
+
and manipulation of basic shapes, periodic shapes, sequences (e.g. waveguides),
|
|
6
|
+
circuits, and complex devices.
|
|
7
7
|
|
|
8
8
|
The code has been developed primarily for nanophotonics, but it can be easily extended
|
|
9
9
|
to different applications in micro and nano device fabrication.
|
|
@@ -13,9 +13,9 @@ University of Copenhagen). It is based on the MATLAB(R) code developed by Leonar
|
|
|
13
13
|
Midolo between 2013 and 2019. The first version of the rewritten Python code has been
|
|
14
14
|
released in October 2021.
|
|
15
15
|
|
|
16
|
-
This software has been realized with the financial support from
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
This software has been realized with the financial support from the European Research
|
|
17
|
+
Council (ERC) under the European Union's Horizon 2020 research and innovation programme
|
|
18
|
+
(Grant agreement No. 949043, NANOMEQ).
|
|
19
19
|
|
|
20
20
|
.. include:: ./documentation.md
|
|
21
21
|
"""
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"""Common helper functions used for backwards compatibility.
|
|
2
|
+
|
|
3
|
+
The main purpose of these functions is to assist in replacing uppercase function/method
|
|
4
|
+
keyword arguments with lowercase ones, while still allowing the uppercase ones to be
|
|
5
|
+
used for a transition period.
|
|
6
|
+
|
|
7
|
+
Optional argument example
|
|
8
|
+
-------------------------
|
|
9
|
+
|
|
10
|
+
To replace an optional argument (in this case Npts -> npts), do the following:
|
|
11
|
+
|
|
12
|
+
def my_func(npts: int = 100, **kwargs: int) -> None:
|
|
13
|
+
npts = get_optional_kwarg("npts", npts, 100, "Npts", kwargs)
|
|
14
|
+
ensure_empty_kwargs("my_func", kwargs)
|
|
15
|
+
|
|
16
|
+
# rest of function body
|
|
17
|
+
...
|
|
18
|
+
|
|
19
|
+
Required argument example
|
|
20
|
+
-------------------------
|
|
21
|
+
|
|
22
|
+
To replace a required argument (in this case Npts -> npts), do the following:
|
|
23
|
+
|
|
24
|
+
def my_func(npts: int | MissingType = MISSING, **kwargs: int) -> None:
|
|
25
|
+
npts = get_kwarg("npts", npts, "Npts", kwargs)
|
|
26
|
+
ensure_empty_kwargs("my_func", kwargs)
|
|
27
|
+
check_missing_args("my_func", npts=npts)
|
|
28
|
+
|
|
29
|
+
# Filter out the MissingType type hint for the rest of the function body.
|
|
30
|
+
npts = ensure_arg_type("npts", npts)
|
|
31
|
+
|
|
32
|
+
# Rest of function body
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
If there are required arguments following the one being replaced, they should also be
|
|
36
|
+
given a default value of MISSING, after which check_missing_args should be called with
|
|
37
|
+
all of the required arguments:
|
|
38
|
+
|
|
39
|
+
def my_func(
|
|
40
|
+
npts: int | MissingType = MISSING,
|
|
41
|
+
other_arg: str | MissingType = MISSING,
|
|
42
|
+
**kwargs: int,
|
|
43
|
+
) -> None:
|
|
44
|
+
npts = get_kwarg("npts", npts, "Npts", kwargs)
|
|
45
|
+
ensure_empty_kwargs("my_func", kwargs)
|
|
46
|
+
check_missing_args("my_func", npts=npts, other_arg=other_arg)
|
|
47
|
+
|
|
48
|
+
# We cast both npts and other_arg this time
|
|
49
|
+
npts = ensure_arg_type("npts", npts)
|
|
50
|
+
other_arg = ensure_arg_type("other_arg", other_arg)
|
|
51
|
+
|
|
52
|
+
# Rest of function body
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
import warnings
|
|
58
|
+
from typing import Any, TypeVar
|
|
59
|
+
|
|
60
|
+
T = TypeVar("T")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# Sentinel for missing arguments
|
|
64
|
+
class MissingType:
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
MISSING = MissingType()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_kwarg(
|
|
72
|
+
new_name: str, new_value: T | MissingType, legacy_name: str, kwargs: dict[str, T]
|
|
73
|
+
) -> T | MissingType:
|
|
74
|
+
if legacy_name in kwargs:
|
|
75
|
+
if not isinstance(new_value, MissingType):
|
|
76
|
+
msg = (
|
|
77
|
+
f"Cannot specify both {new_name} and {legacy_name}. "
|
|
78
|
+
f"Please use {new_name} only."
|
|
79
|
+
)
|
|
80
|
+
raise TypeError(msg)
|
|
81
|
+
warnings.warn(
|
|
82
|
+
f"Passing {legacy_name} as a keyword argument is deprecated and "
|
|
83
|
+
f"will be removed in a future version. Use {new_name} instead.",
|
|
84
|
+
DeprecationWarning,
|
|
85
|
+
stacklevel=3,
|
|
86
|
+
)
|
|
87
|
+
return kwargs.pop(legacy_name)
|
|
88
|
+
return new_value
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_optional_kwarg(
|
|
92
|
+
new_name: str,
|
|
93
|
+
new_value: T,
|
|
94
|
+
default_value: T,
|
|
95
|
+
legacy_name: str,
|
|
96
|
+
kwargs: dict[str, T],
|
|
97
|
+
) -> T:
|
|
98
|
+
if legacy_name in kwargs:
|
|
99
|
+
if new_value != default_value:
|
|
100
|
+
msg = (
|
|
101
|
+
f"Cannot specify both {new_name} and {legacy_name}. "
|
|
102
|
+
f"Please use {new_name} only."
|
|
103
|
+
)
|
|
104
|
+
raise TypeError(msg)
|
|
105
|
+
warnings.warn(
|
|
106
|
+
f"Passing {legacy_name} as a keyword argument is deprecated and "
|
|
107
|
+
f"will be removed in a future version. Use {new_name} instead.",
|
|
108
|
+
DeprecationWarning,
|
|
109
|
+
stacklevel=3,
|
|
110
|
+
)
|
|
111
|
+
return kwargs.pop(legacy_name)
|
|
112
|
+
return new_value
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def check_missing_args(func_name: str, **kwargs: Any) -> None: # noqa: ANN401
|
|
116
|
+
missing_args = [name for name, value in kwargs.items() if value is MISSING]
|
|
117
|
+
if missing_args:
|
|
118
|
+
n_missing = len(missing_args)
|
|
119
|
+
if n_missing == 1:
|
|
120
|
+
arg_word = "argument"
|
|
121
|
+
arg_str = missing_args[0]
|
|
122
|
+
else:
|
|
123
|
+
arg_word = "arguments"
|
|
124
|
+
arg_str = ", ".join(missing_args[:-1]) + f", and {missing_args[-1]}"
|
|
125
|
+
msg = f"{func_name}() missing {n_missing} required {arg_word}: {arg_str}"
|
|
126
|
+
raise TypeError(msg)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def ensure_arg_type(name: str, value: T | MissingType) -> T:
|
|
130
|
+
if isinstance(value, MissingType):
|
|
131
|
+
msg = f"Missing required argument, {name}."
|
|
132
|
+
raise TypeError(msg)
|
|
133
|
+
return value
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def ensure_empty_kwargs(func_name: str, kwargs: dict[str, Any]) -> None:
|
|
137
|
+
if not kwargs:
|
|
138
|
+
return
|
|
139
|
+
arg_word = "argument" if len(kwargs) == 1 else "arguments"
|
|
140
|
+
unexpected = ", ".join(kwargs.keys())
|
|
141
|
+
msg = f"{func_name}() got unexpected keyword {arg_word}: {unexpected}"
|
|
142
|
+
raise TypeError(msg)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Base device library.
|
|
1
|
+
"""Base device library.
|
|
3
2
|
|
|
4
3
|
This is a collection of some simple demo devices distributed with the base version of
|
|
5
4
|
`samplemaker`. It can be used as template for creating new libraries or to learn how to
|
|
@@ -15,15 +14,32 @@ import numpy as np
|
|
|
15
14
|
|
|
16
15
|
import samplemaker.makers as sm
|
|
17
16
|
from samplemaker.baselib.waveguides import BaseWaveguidePort, BaseWaveguideSequencer
|
|
18
|
-
from samplemaker.devices import Device,
|
|
17
|
+
from samplemaker.devices import Device, register_devices_in_module
|
|
18
|
+
from samplemaker.shapes import GeomGroup
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
class CrossMark(Device):
|
|
22
|
-
|
|
22
|
+
"""Generic cross marker for lithographic mask alignment."""
|
|
23
|
+
|
|
24
|
+
def initialize(self) -> None:
|
|
25
|
+
"""Initialize the cross mark device.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
None
|
|
30
|
+
|
|
31
|
+
"""
|
|
23
32
|
self.set_name("BASELIB_CMARK")
|
|
24
33
|
self.set_description("Generic cross marker for mask alignment.")
|
|
25
34
|
|
|
26
|
-
def parameters(self):
|
|
35
|
+
def parameters(self) -> None:
|
|
36
|
+
"""Define the parameters of the cross mark.
|
|
37
|
+
|
|
38
|
+
Returns
|
|
39
|
+
-------
|
|
40
|
+
None
|
|
41
|
+
|
|
42
|
+
"""
|
|
27
43
|
self.addparameter(
|
|
28
44
|
param_name="length1",
|
|
29
45
|
default_value=20,
|
|
@@ -69,7 +85,15 @@ class CrossMark(Device):
|
|
|
69
85
|
param_type=float,
|
|
70
86
|
)
|
|
71
87
|
|
|
72
|
-
def geom(self):
|
|
88
|
+
def geom(self) -> GeomGroup:
|
|
89
|
+
"""Define the geometry of the cross mark.
|
|
90
|
+
|
|
91
|
+
Returns
|
|
92
|
+
-------
|
|
93
|
+
GeomGroup
|
|
94
|
+
The geometry of the cross mark.
|
|
95
|
+
|
|
96
|
+
"""
|
|
73
97
|
p = self.get_params()
|
|
74
98
|
cross = sm.make_rect(0, 0, p["length1"], p["width1"], layer=1)
|
|
75
99
|
cross += sm.make_rect(0, 0, p["width1"], p["length1"], layer=1)
|
|
@@ -92,11 +116,27 @@ class CrossMark(Device):
|
|
|
92
116
|
|
|
93
117
|
|
|
94
118
|
class DirectionalCoupler(Device):
|
|
95
|
-
|
|
119
|
+
"""Simple symmetric directional coupler."""
|
|
120
|
+
|
|
121
|
+
def initialize(self) -> None:
|
|
122
|
+
"""Initialize the directional coupler device.
|
|
123
|
+
|
|
124
|
+
Returns
|
|
125
|
+
-------
|
|
126
|
+
None
|
|
127
|
+
|
|
128
|
+
"""
|
|
96
129
|
self.set_name("BASELIB_DCPL")
|
|
97
130
|
self.set_description("Simple symmetric directional coupler")
|
|
98
131
|
|
|
99
|
-
def parameters(self):
|
|
132
|
+
def parameters(self) -> None:
|
|
133
|
+
"""Define the parameters of the directional coupler.
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
None
|
|
138
|
+
|
|
139
|
+
"""
|
|
100
140
|
self.addparameter("length", 20, "Coupling length", float)
|
|
101
141
|
self.addparameter(
|
|
102
142
|
param_name="width",
|
|
@@ -126,7 +166,15 @@ class DirectionalCoupler(Device):
|
|
|
126
166
|
param_range=(3, np.inf),
|
|
127
167
|
)
|
|
128
168
|
|
|
129
|
-
def geom(self):
|
|
169
|
+
def geom(self) -> GeomGroup:
|
|
170
|
+
"""Define the geometry of the directional coupler.
|
|
171
|
+
|
|
172
|
+
Returns
|
|
173
|
+
-------
|
|
174
|
+
GeomGroup
|
|
175
|
+
The geometry of the directional coupler.
|
|
176
|
+
|
|
177
|
+
"""
|
|
130
178
|
p = self.get_params()
|
|
131
179
|
# Draw the upper arm, then mirror
|
|
132
180
|
off = p["input_dist"] / 2
|
|
@@ -136,11 +184,11 @@ class DirectionalCoupler(Device):
|
|
|
136
184
|
ss = BaseWaveguideSequencer(seq)
|
|
137
185
|
dc = ss.run()
|
|
138
186
|
dc2 = dc.copy()
|
|
139
|
-
dc2.
|
|
187
|
+
dc2.mirror_x(ltot / 2)
|
|
140
188
|
dc += dc2
|
|
141
189
|
dc.translate(-ltot / 2, off + p["gap"] / 2 + p["width"] / 2)
|
|
142
190
|
dc3 = dc.copy()
|
|
143
|
-
dc3.
|
|
191
|
+
dc3.mirror_y(0)
|
|
144
192
|
dc += dc3
|
|
145
193
|
|
|
146
194
|
# Add ports
|
|
@@ -157,11 +205,27 @@ class DirectionalCoupler(Device):
|
|
|
157
205
|
|
|
158
206
|
|
|
159
207
|
class FocusingGratingCoupler(Device):
|
|
160
|
-
|
|
208
|
+
"""Apodized focusing grating coupler."""
|
|
209
|
+
|
|
210
|
+
def initialize(self) -> None:
|
|
211
|
+
"""Initialize the grating coupler device.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
None
|
|
216
|
+
|
|
217
|
+
"""
|
|
161
218
|
self.set_name("BASELIB_FGC")
|
|
162
219
|
self.set_description("Grating coupler demo.")
|
|
163
220
|
|
|
164
|
-
def parameters(self):
|
|
221
|
+
def parameters(self) -> None:
|
|
222
|
+
"""Define the parameters for the grating coupler.
|
|
223
|
+
|
|
224
|
+
Returns
|
|
225
|
+
-------
|
|
226
|
+
None
|
|
227
|
+
|
|
228
|
+
"""
|
|
165
229
|
self.addparameter(
|
|
166
230
|
param_name="w0",
|
|
167
231
|
default_value=0.3,
|
|
@@ -229,7 +293,15 @@ class FocusingGratingCoupler(Device):
|
|
|
229
293
|
param_type=bool,
|
|
230
294
|
)
|
|
231
295
|
|
|
232
|
-
def geom(self):
|
|
296
|
+
def geom(self) -> GeomGroup:
|
|
297
|
+
"""Define the grating coupler geometry.
|
|
298
|
+
|
|
299
|
+
Returns
|
|
300
|
+
-------
|
|
301
|
+
GeomGroup
|
|
302
|
+
The geometry of the grating coupler.
|
|
303
|
+
|
|
304
|
+
"""
|
|
233
305
|
# Grating first
|
|
234
306
|
p = self.get_params()
|
|
235
307
|
theta = math.radians(p["theta"])
|
|
@@ -244,7 +316,7 @@ class FocusingGratingCoupler(Device):
|
|
|
244
316
|
nr_apo = p["nr_Apo"]
|
|
245
317
|
ff_coef = p["ff_coef"]
|
|
246
318
|
|
|
247
|
-
g =
|
|
319
|
+
g = GeomGroup()
|
|
248
320
|
for q in range(q0, qn):
|
|
249
321
|
b = q * p0
|
|
250
322
|
x0 = b * b * math.sin(theta) / (q * lambda0)
|
|
@@ -258,8 +330,8 @@ class FocusingGratingCoupler(Device):
|
|
|
258
330
|
g += sm.make_arc(
|
|
259
331
|
x0=x0,
|
|
260
332
|
y0=0,
|
|
261
|
-
|
|
262
|
-
|
|
333
|
+
rx=a,
|
|
334
|
+
ry=b,
|
|
263
335
|
rot=0,
|
|
264
336
|
w=w,
|
|
265
337
|
a1=-div_angle - 5,
|
|
@@ -292,4 +364,4 @@ class FocusingGratingCoupler(Device):
|
|
|
292
364
|
|
|
293
365
|
|
|
294
366
|
# Register all devices here in this module
|
|
295
|
-
|
|
367
|
+
register_devices_in_module(__name__)
|