prefab 0.5.1__py3-none-any.whl → 1.1.8__py3-none-any.whl
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.
- prefab/__init__.py +15 -38
- prefab/__main__.py +33 -19
- prefab/compare.py +126 -0
- prefab/device.py +1486 -0
- prefab/geometry.py +394 -0
- prefab/models.py +114 -0
- prefab/predict.py +337 -0
- prefab/read.py +503 -0
- prefab/shapes.py +773 -0
- {prefab-0.5.1.dist-info → prefab-1.1.8.dist-info}/METADATA +37 -36
- prefab-1.1.8.dist-info/RECORD +14 -0
- {prefab-0.5.1.dist-info → prefab-1.1.8.dist-info}/WHEEL +1 -1
- prefab-1.1.8.dist-info/entry_points.txt +2 -0
- prefab/io.py +0 -214
- prefab/predictor.py +0 -231
- prefab/processor.py +0 -248
- prefab-0.5.1.dist-info/RECORD +0 -9
- {prefab-0.5.1.dist-info → prefab-1.1.8.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: prefab
|
|
3
|
-
Version:
|
|
4
|
-
Summary:
|
|
5
|
-
Project-URL: Homepage, https://
|
|
6
|
-
|
|
3
|
+
Version: 1.1.8
|
|
4
|
+
Summary: Artificial nanofabrication of integrated photonic circuits using deep learning
|
|
5
|
+
Project-URL: Homepage, https://prefabphotonics.com
|
|
6
|
+
Project-URL: Repository, https://github.com/PreFab-Photonics/PreFab
|
|
7
|
+
Project-URL: Docs, https://docs.prefabphotonics.com
|
|
8
|
+
Author-email: "PreFab Photonics Inc." <hi@prefabphotonics.com>
|
|
7
9
|
License: GNU LESSER GENERAL PUBLIC LICENSE
|
|
8
10
|
Version 2.1, February 1999
|
|
9
11
|
|
|
@@ -509,54 +511,59 @@ License: GNU LESSER GENERAL PUBLIC LICENSE
|
|
|
509
511
|
|
|
510
512
|
That's all there is to it!
|
|
511
513
|
License-File: LICENSE
|
|
512
|
-
Keywords:
|
|
514
|
+
Keywords: computer-vision,deep-learning,electronic-design-automation,integrated-photonics,machine-learning,nanofabrication,semiconductor-manufacturing
|
|
513
515
|
Classifier: License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)
|
|
514
516
|
Classifier: Operating System :: OS Independent
|
|
515
517
|
Classifier: Programming Language :: Python :: 3
|
|
516
518
|
Requires-Python: >=3.9
|
|
517
|
-
Requires-Dist:
|
|
519
|
+
Requires-Dist: autograd
|
|
520
|
+
Requires-Dist: gdstk>=0.9.55
|
|
518
521
|
Requires-Dist: matplotlib
|
|
519
522
|
Requires-Dist: numpy
|
|
520
523
|
Requires-Dist: opencv-python-headless
|
|
524
|
+
Requires-Dist: pillow
|
|
525
|
+
Requires-Dist: pydantic>=2.10
|
|
521
526
|
Requires-Dist: requests
|
|
527
|
+
Requires-Dist: scikit-image
|
|
528
|
+
Requires-Dist: scipy
|
|
529
|
+
Requires-Dist: toml
|
|
530
|
+
Requires-Dist: tqdm
|
|
522
531
|
Description-Content-Type: text/markdown
|
|
523
532
|
|
|
524
533
|
# PreFab
|
|
525
534
|
|
|
526
|
-

|
|
535
|
+

|
|
527
536
|
|
|
528
|
-
|
|
537
|
+
PreFab is a _virtual nanofabrication environment_ that leverages **deep learning** and **computer vision** to predict and correct for structural variations in integrated photonic devices during nanofabrication.
|
|
538
|
+
|
|
539
|
+
> **Try Rosette**: Want a more visual experience? Try [Rosette](https://rosette.dev) - our new layout tool with PreFab models built in, designed for rapid chip design.
|
|
529
540
|
|
|
530
541
|
## Prediction
|
|
531
542
|
|
|
532
|
-
|
|
543
|
+
PreFab predicts process-induced structural variations, including corner rounding, loss of small lines and islands, filling of narrow holes and channels, sidewall angle deviations, and stochastic effects. This allows designers to rapidly prototype and evaluate expected performance pre-fabrication.
|
|
533
544
|
|
|
534
|
-

|
|
545
|
+

|
|
535
546
|
|
|
536
547
|
## Correction
|
|
537
548
|
|
|
538
|
-
|
|
549
|
+
PreFab corrects device designs to ensure that the fabricated outcome closely matches the intended specifications. This minimizes structural variations and reduces performance discrepancies between simulations and actual experiments.
|
|
539
550
|
|
|
540
|
-

|
|
551
|
+

|
|
541
552
|
|
|
542
553
|
## Models
|
|
543
554
|
|
|
544
|
-
|
|
555
|
+
Each photonic nanofabrication process requires unique models, which are regularly updated with the latest data. The current models include (see the full list in [`docs/models.md`](https://github.com/PreFab-Photonics/PreFab/blob/main/docs/models.md)):
|
|
545
556
|
|
|
546
|
-
| Foundry
|
|
547
|
-
|
|
|
548
|
-
| ANT
|
|
549
|
-
| ANT
|
|
550
|
-
| ANT | [SiN (Lower Edge)](https://www.appliednt.com/nanosoi/sys/resources/specs_nitride/) | v5 (Jun 3 2023) | d0 (Jun 1 2023) | ANT_SiN | v5-d0-lower | Alpha |
|
|
551
|
-
| SiEPICfab | [SOI](https://siepic.ca/fabrication/) | v5 (Jun 3 2023) | d0 (Jun 14 2023) | SiEPICfab_SOI | v5-d0 | Alpha |
|
|
557
|
+
| Foundry | Process | Latest Version | Latest Dataset | Model Name |
|
|
558
|
+
| ------- | ------- | ----------------- | ---------------- | ----------- |
|
|
559
|
+
| ANT | NanoSOI | ANF1 (May 6 2024) | d10 (Jun 8 2024) | ANT_NanoSOI_ANF1_d10 |
|
|
560
|
+
| ANT | SiN | ANF1 (May 6 2024) | d1 (Jan 31 2024) | ANT_SiN_ANF1_d1 |
|
|
552
561
|
|
|
553
|
-
_New models
|
|
562
|
+
> _New models are to be regularly added. Usage may change. For additional foundry and process models, feel free to [contact us](mailto:hi@prefabphotonics.com) or raise an issue._
|
|
554
563
|
|
|
555
564
|
## Installation
|
|
556
565
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
Install `PreFab` via pip:
|
|
566
|
+
Install PreFab via pip:
|
|
560
567
|
|
|
561
568
|
```sh
|
|
562
569
|
pip install prefab
|
|
@@ -570,19 +577,13 @@ cd PreFab
|
|
|
570
577
|
pip install -e .
|
|
571
578
|
```
|
|
572
579
|
|
|
573
|
-
### Online
|
|
574
|
-
|
|
575
|
-
Use `PreFab` online through GitHub Codespaces:
|
|
576
|
-
|
|
577
|
-
[](https://github.com/codespaces/new?machine=basicLinux32gb&repo=608330448&ref=main&devcontainer_path=.devcontainer%2Fdevcontainer.json&location=EastUs)
|
|
578
|
-
|
|
579
580
|
## Getting Started
|
|
580
581
|
|
|
581
582
|
### Account setup
|
|
582
583
|
|
|
583
584
|
Before you can make PreFab requests, you will need to [create an account](https://www.prefabphotonics.com/login).
|
|
584
585
|
|
|
585
|
-
To link your account, you will need
|
|
586
|
+
To link your account, you will need an token. You can do this by running the following command in your terminal. This will open a browser window where you can log in and authenticate your token.
|
|
586
587
|
|
|
587
588
|
```sh
|
|
588
589
|
python3 -m prefab setup
|
|
@@ -590,15 +591,15 @@ python3 -m prefab setup
|
|
|
590
591
|
|
|
591
592
|
### Guides
|
|
592
593
|
|
|
593
|
-
Visit [`/examples`](https://github.com/PreFab-Photonics/PreFab/tree/main/examples) or our [
|
|
594
|
+
Visit [`/docs/examples`](https://github.com/PreFab-Photonics/PreFab/tree/main/docs/examples) or our [docs](https://docs.prefabphotonics.com/) to get started with your first predictions.
|
|
594
595
|
|
|
595
596
|
## Performance and Usage
|
|
596
597
|
|
|
597
|
-
|
|
598
|
+
PreFab models are hosted on a [serverless cloud platform](https://modal.com/). Please keep in mind:
|
|
598
599
|
|
|
599
|
-
- 🐢 CPU inference may
|
|
600
|
-
- 🥶 The first prediction may take longer due to cold start server loading. Subsequent predictions will be faster.
|
|
601
|
-
- 😊
|
|
600
|
+
- 🐢 Default CPU inference may be slower.
|
|
601
|
+
- 🥶 The first prediction using optional GPU inference may take longer due to cold start server loading. Subsequent predictions will be faster.
|
|
602
|
+
- 😊 Please be considerate of usage. Start with small tasks and limit usage during the initial stages. Thank you!
|
|
602
603
|
|
|
603
604
|
## License
|
|
604
605
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
prefab/__init__.py,sha256=V4m0w3VrKeMgeNeqyc_45E5KXH9fVOQKO5xyH42uDmg,425
|
|
2
|
+
prefab/__main__.py,sha256=1eXWiEoG7eetJMm1qRbK2I5MnzuRgKIoQtBeT-Ps8es,3523
|
|
3
|
+
prefab/compare.py,sha256=0Xgp3tFuP4of-ce9Opc19p8i8lIyXkbVGLuwWBaHSeE,3486
|
|
4
|
+
prefab/device.py,sha256=1rqs_VQ7am6W473C-EZTsPFDlqNIMMd26VZAUV1tNS0,54885
|
|
5
|
+
prefab/geometry.py,sha256=4fekWMlkdS_qlPNTdPXPhwKuQ5qdQ1Zjf8m9JKd1dA8,12049
|
|
6
|
+
prefab/models.py,sha256=waPNGtuISyY0f8cz7dnbD451CKYCt8EpPGt-4lSOPNU,2581
|
|
7
|
+
prefab/predict.py,sha256=h13523jasg1WbdiYbkXy43SWTGfQXjq6oEe0O8DT2U0,11731
|
|
8
|
+
prefab/read.py,sha256=WNqC3xENlndzFwXeCF2E7H3Iq2dO_6rPEPZ58DuloqY,16259
|
|
9
|
+
prefab/shapes.py,sha256=58cyXFNh1kEErq2jEbGd3dWSediU1OSmor_FWwc1V8A,25098
|
|
10
|
+
prefab-1.1.8.dist-info/METADATA,sha256=d5ide0FP2wUQALM_2SSFhA_BGU6s3waxWjtXwsbjivs,35036
|
|
11
|
+
prefab-1.1.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
12
|
+
prefab-1.1.8.dist-info/entry_points.txt,sha256=h1_A9O9F3NAIoKXD1RPb3Eo-WCSiHhMB_AnagBi6XTQ,48
|
|
13
|
+
prefab-1.1.8.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
|
|
14
|
+
prefab-1.1.8.dist-info/RECORD,,
|
prefab/io.py
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module offers tools to import, export, and preprocess device layouts in multiple formats for
|
|
3
|
-
nanofabrication prediction tasks.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from typing import List, Optional, Tuple
|
|
7
|
-
|
|
8
|
-
import cv2
|
|
9
|
-
import gdstk
|
|
10
|
-
import matplotlib.image as img
|
|
11
|
-
import numpy as np
|
|
12
|
-
|
|
13
|
-
from prefab.processor import binarize_hard
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def load_device_img(path: str, img_length_nm: int = None) -> np.ndarray:
|
|
17
|
-
"""
|
|
18
|
-
Load, process and scale device image from file for prediction.
|
|
19
|
-
|
|
20
|
-
This function reads an image file, scales it according to the provided image length in
|
|
21
|
-
nanometers, and performs preprocessing tasks such as binarization, preparing it for prediction.
|
|
22
|
-
|
|
23
|
-
Parameters
|
|
24
|
-
----------
|
|
25
|
-
path : str
|
|
26
|
-
Path to the device image file.
|
|
27
|
-
|
|
28
|
-
img_length_nm : int, optional
|
|
29
|
-
Desired length of the device image in nanometers for scaling. If not provided,
|
|
30
|
-
the length of the original image is used.
|
|
31
|
-
|
|
32
|
-
Returns
|
|
33
|
-
-------
|
|
34
|
-
np.ndarray
|
|
35
|
-
A 2D numpy array representing the preprocessed and scaled device, ready for prediction.
|
|
36
|
-
"""
|
|
37
|
-
device = img.imread(path)[:, :, 1]
|
|
38
|
-
if img_length_nm is None:
|
|
39
|
-
img_length_nm = device.shape[1]
|
|
40
|
-
scale = img_length_nm / device.shape[1]
|
|
41
|
-
device = cv2.resize(device, (0, 0), fx=scale, fy=scale)
|
|
42
|
-
device = binarize_hard(device)
|
|
43
|
-
return device
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def load_device_gds(
|
|
47
|
-
path: str,
|
|
48
|
-
cell_name: str,
|
|
49
|
-
coords: Optional[List[List[int]]] = None,
|
|
50
|
-
layer: Tuple[int, int] = (1, 0),
|
|
51
|
-
) -> np.ndarray:
|
|
52
|
-
"""
|
|
53
|
-
Load and process a device layout from a GDSII file.
|
|
54
|
-
|
|
55
|
-
This function reads a device layout from a GDSII file, performs necessary
|
|
56
|
-
preprocessing tasks such as scaling and padding, and prepares it for prediction.
|
|
57
|
-
Only the specified layer is loaded.
|
|
58
|
-
|
|
59
|
-
Parameters
|
|
60
|
-
----------
|
|
61
|
-
path : str
|
|
62
|
-
Path to the GDSII layout file.
|
|
63
|
-
|
|
64
|
-
cell_name : str
|
|
65
|
-
Name of the GDSII cell to be loaded.
|
|
66
|
-
|
|
67
|
-
coords : List[List[int]], optional
|
|
68
|
-
A list of coordinates [[xmin, ymin], [xmax, ymax]] in nm, defining the
|
|
69
|
-
region of the cell to be loaded. If None, the entire cell is loaded.
|
|
70
|
-
|
|
71
|
-
layer : Tuple[int, int], optional
|
|
72
|
-
A tuple specifying the layer to be loaded. Default is (1, 0).
|
|
73
|
-
|
|
74
|
-
Returns
|
|
75
|
-
-------
|
|
76
|
-
np.ndarray
|
|
77
|
-
A 2D numpy array representing the preprocessed device layout, ready for prediction.
|
|
78
|
-
"""
|
|
79
|
-
gds = gdstk.read_gds(path)
|
|
80
|
-
cell = gds[cell_name]
|
|
81
|
-
polygons = cell.get_polygons(layer=layer[0], datatype=layer[1])
|
|
82
|
-
bounds = tuple(
|
|
83
|
-
tuple(1000 * x for x in sub_tuple) for sub_tuple in cell.bounding_box()
|
|
84
|
-
)
|
|
85
|
-
device = np.zeros(
|
|
86
|
-
(int(bounds[1][1] - bounds[0][1]), int(bounds[1][0] - bounds[0][0]))
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
contours = [
|
|
90
|
-
np.array(
|
|
91
|
-
[
|
|
92
|
-
[
|
|
93
|
-
[
|
|
94
|
-
int(1000 * vertex[0] - bounds[0][0]),
|
|
95
|
-
int(1000 * vertex[1] - bounds[0][1]),
|
|
96
|
-
]
|
|
97
|
-
]
|
|
98
|
-
for vertex in polygon.points
|
|
99
|
-
],
|
|
100
|
-
dtype=np.int32,
|
|
101
|
-
)
|
|
102
|
-
for polygon in polygons
|
|
103
|
-
]
|
|
104
|
-
|
|
105
|
-
cv2.fillPoly(img=device, pts=contours, color=(1, 1, 1))
|
|
106
|
-
|
|
107
|
-
if coords is not None:
|
|
108
|
-
new_device = np.zeros(
|
|
109
|
-
(int(bounds[1][1] - bounds[0][1]), int(bounds[1][0] - bounds[0][0]))
|
|
110
|
-
)
|
|
111
|
-
new_device[
|
|
112
|
-
int(coords[0][1] - bounds[0][1]) : int(coords[1][1] - bounds[0][1]),
|
|
113
|
-
int(coords[0][0] - bounds[0][0]) : int(coords[1][0] - bounds[0][0]),
|
|
114
|
-
] = device[
|
|
115
|
-
int(coords[0][1] - bounds[0][1]) : int(coords[1][1] - bounds[0][1]),
|
|
116
|
-
int(coords[0][0] - bounds[0][0]) : int(coords[1][0] - bounds[0][0]),
|
|
117
|
-
]
|
|
118
|
-
device = new_device
|
|
119
|
-
|
|
120
|
-
device = np.flipud(device)
|
|
121
|
-
device = np.pad(device, 200)
|
|
122
|
-
|
|
123
|
-
return device.astype(np.float32)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def device_to_cell(
|
|
127
|
-
device: np.ndarray,
|
|
128
|
-
cell_name: str,
|
|
129
|
-
library: gdstk.Library,
|
|
130
|
-
resolution: float = 1.0,
|
|
131
|
-
layer: Tuple[int, int] = (1, 0),
|
|
132
|
-
approximation_mode: int = 2,
|
|
133
|
-
) -> gdstk.Cell:
|
|
134
|
-
"""Converts a device layout to a gdstk cell for GDSII export.
|
|
135
|
-
|
|
136
|
-
This function creates a cell that represents a device layout. The created cell
|
|
137
|
-
is ready to be exported as a GDSII file.
|
|
138
|
-
|
|
139
|
-
Parameters
|
|
140
|
-
----------
|
|
141
|
-
device : np.ndarray
|
|
142
|
-
A 2D numpy array representing the device layout.
|
|
143
|
-
|
|
144
|
-
cell_name : str
|
|
145
|
-
Name for the new cell.
|
|
146
|
-
|
|
147
|
-
library : gdstk.Library
|
|
148
|
-
Library to which the cell will be added.
|
|
149
|
-
|
|
150
|
-
resolution : float, optional
|
|
151
|
-
The resolution of the device in pixels per nm. Default is 1.0.
|
|
152
|
-
|
|
153
|
-
layer : Tuple[int, int], optional
|
|
154
|
-
A tuple specifying the layer to be exported. Default is (1, 0).
|
|
155
|
-
|
|
156
|
-
approximation_mode : int, optional
|
|
157
|
-
The approximation method to be used for finding contours. Possible values are 1, 2, 3, and
|
|
158
|
-
4. Larger values mean more approximation. Default is 1.
|
|
159
|
-
|
|
160
|
-
Returns
|
|
161
|
-
-------
|
|
162
|
-
gdstk.Cell
|
|
163
|
-
The newly created cell containing the device layout.
|
|
164
|
-
"""
|
|
165
|
-
approximation_method_mapping = {
|
|
166
|
-
1: cv2.CHAIN_APPROX_NONE,
|
|
167
|
-
2: cv2.CHAIN_APPROX_SIMPLE,
|
|
168
|
-
3: cv2.CHAIN_APPROX_TC89_L1,
|
|
169
|
-
4: cv2.CHAIN_APPROX_TC89_KCOS,
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
device = np.flipud(device)
|
|
173
|
-
contours, hierarchy = cv2.findContours(
|
|
174
|
-
device.astype(np.uint8),
|
|
175
|
-
cv2.RETR_TREE,
|
|
176
|
-
approximation_method_mapping[approximation_mode],
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
hierarchy_polygons = {}
|
|
180
|
-
|
|
181
|
-
for idx, contour in enumerate(contours):
|
|
182
|
-
level = 0
|
|
183
|
-
current_idx = idx
|
|
184
|
-
while hierarchy[0][current_idx][3] != -1:
|
|
185
|
-
level += 1
|
|
186
|
-
current_idx = hierarchy[0][current_idx][3]
|
|
187
|
-
|
|
188
|
-
if len(contour) > 2:
|
|
189
|
-
contour = contour / 1000 # μm to nm
|
|
190
|
-
points = [tuple(point) for point in contour.squeeze().tolist()]
|
|
191
|
-
if level not in hierarchy_polygons:
|
|
192
|
-
hierarchy_polygons[level] = []
|
|
193
|
-
hierarchy_polygons[level].append(points)
|
|
194
|
-
|
|
195
|
-
cell = library.new_cell(cell_name)
|
|
196
|
-
processed_polygons = []
|
|
197
|
-
# Process polygons by hierarchy level, alternating between adding and XORing
|
|
198
|
-
for level in sorted(hierarchy_polygons.keys()):
|
|
199
|
-
operation = "or" if level % 2 == 0 else "xor"
|
|
200
|
-
polygons_to_process = hierarchy_polygons[level]
|
|
201
|
-
|
|
202
|
-
if polygons_to_process:
|
|
203
|
-
processed_polygons = gdstk.boolean(
|
|
204
|
-
polygons_to_process,
|
|
205
|
-
processed_polygons,
|
|
206
|
-
operation,
|
|
207
|
-
layer=layer[0],
|
|
208
|
-
datatype=layer[1],
|
|
209
|
-
)
|
|
210
|
-
for polygon in processed_polygons:
|
|
211
|
-
polygon.scale(resolution, resolution)
|
|
212
|
-
cell.add(polygon)
|
|
213
|
-
|
|
214
|
-
return cell
|
prefab/predictor.py
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
A module for making predictions on fabrication variations in photonic devices
|
|
3
|
-
using machine learning models deployed in the cloud.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import base64
|
|
7
|
-
import os
|
|
8
|
-
|
|
9
|
-
import numpy as np
|
|
10
|
-
import requests
|
|
11
|
-
import toml
|
|
12
|
-
from cv2 import IMREAD_GRAYSCALE, imdecode, imencode
|
|
13
|
-
|
|
14
|
-
from prefab.processor import binarize_hard
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def predict(
|
|
18
|
-
device: np.ndarray, model_name: str, model_tags: str, binarize: bool = False
|
|
19
|
-
) -> np.ndarray:
|
|
20
|
-
"""
|
|
21
|
-
Generates a prediction for a photonic device using a specified cloud-based ML model.
|
|
22
|
-
|
|
23
|
-
The function sends an image of the device to a cloud function, which uses the specified
|
|
24
|
-
machine learning model to generate a prediction.
|
|
25
|
-
|
|
26
|
-
Parameters
|
|
27
|
-
----------
|
|
28
|
-
device : np.ndarray
|
|
29
|
-
A binary numpy matrix representing the shape of a device.
|
|
30
|
-
|
|
31
|
-
model_name : str
|
|
32
|
-
The name of the ML model to use for the prediction.
|
|
33
|
-
Consult the module's documentation for available models.
|
|
34
|
-
|
|
35
|
-
model_tags : Union[str, List[str]]
|
|
36
|
-
The tags of the ML model.
|
|
37
|
-
Consult the module's documentation for available tags.
|
|
38
|
-
|
|
39
|
-
binarize : bool, optional
|
|
40
|
-
If set to True, the prediction will be binarized (default is False).
|
|
41
|
-
|
|
42
|
-
Returns
|
|
43
|
-
-------
|
|
44
|
-
np.ndarray
|
|
45
|
-
A numpy matrix representing the predicted shape of the device. Pixel values closer
|
|
46
|
-
to 1 indicate a higher likelihood of core material, while pixel values closer to 0
|
|
47
|
-
suggest a higher likelihood of cladding material. Pixel values in between represent
|
|
48
|
-
prediction uncertainty.
|
|
49
|
-
"""
|
|
50
|
-
function_url = "https://prefab-photonics--predict.modal.run"
|
|
51
|
-
|
|
52
|
-
predict_data = {
|
|
53
|
-
"device": _encode_image(device),
|
|
54
|
-
"model_name": model_name,
|
|
55
|
-
"model_tags": model_tags,
|
|
56
|
-
"binary": binarize,
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
with open(os.path.expanduser("~/.prefab.toml"), "r") as file:
|
|
60
|
-
content = file.readlines()
|
|
61
|
-
for line in content:
|
|
62
|
-
if "access_token" in line:
|
|
63
|
-
access_token = line.split("=")[1].strip().strip('"')
|
|
64
|
-
if "refresh_token" in line:
|
|
65
|
-
refresh_token = line.split("=")[1].strip().strip('"')
|
|
66
|
-
break
|
|
67
|
-
|
|
68
|
-
headers = {
|
|
69
|
-
"Authorization": f"Bearer {access_token}",
|
|
70
|
-
"X-Refresh-Token": refresh_token,
|
|
71
|
-
}
|
|
72
|
-
response = requests.post(
|
|
73
|
-
url=function_url,
|
|
74
|
-
json=predict_data,
|
|
75
|
-
headers=headers,
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
if response.status_code != 200:
|
|
79
|
-
raise ValueError(response.text)
|
|
80
|
-
else:
|
|
81
|
-
response_data = response.json()
|
|
82
|
-
if "error" in response_data:
|
|
83
|
-
raise ValueError(response_data["error"])
|
|
84
|
-
if "prediction" in response_data:
|
|
85
|
-
prediction = _decode_image(response_data["prediction"])
|
|
86
|
-
if "new_refresh_token" in response_data:
|
|
87
|
-
prefab_file_path = os.path.expanduser("~/.prefab.toml")
|
|
88
|
-
with open(prefab_file_path, "w", encoding="utf-8") as toml_file:
|
|
89
|
-
toml.dump(
|
|
90
|
-
{
|
|
91
|
-
"access_token": response_data["new_access_token"],
|
|
92
|
-
"refresh_token": response_data["new_refresh_token"],
|
|
93
|
-
},
|
|
94
|
-
toml_file,
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
if binarize:
|
|
98
|
-
prediction = binarize_hard(prediction)
|
|
99
|
-
|
|
100
|
-
return prediction
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def correct(
|
|
104
|
-
device: np.ndarray,
|
|
105
|
-
model_name: str,
|
|
106
|
-
model_tags: str,
|
|
107
|
-
binarize: bool = True,
|
|
108
|
-
multi_correct: bool = False,
|
|
109
|
-
) -> np.ndarray:
|
|
110
|
-
"""
|
|
111
|
-
Generates a correction for a photonic device using a specified cloud-based ML model.
|
|
112
|
-
|
|
113
|
-
The function sends an image of the device to a cloud function, which uses the specified
|
|
114
|
-
machine learning model to generate a correction.
|
|
115
|
-
|
|
116
|
-
Parameters
|
|
117
|
-
----------
|
|
118
|
-
device : np.ndarray
|
|
119
|
-
A binary numpy matrix representing the shape of a device.
|
|
120
|
-
|
|
121
|
-
model_name : str
|
|
122
|
-
The name of the ML model to use for the correction.
|
|
123
|
-
Consult the module's documentation for available models.
|
|
124
|
-
|
|
125
|
-
model_tags : Union[str, List[str]]
|
|
126
|
-
The tags of the ML model.
|
|
127
|
-
Consult the module's documentation for available tags.
|
|
128
|
-
|
|
129
|
-
binarize : bool, optional
|
|
130
|
-
If set to True, the correction will be binarized (default is True).
|
|
131
|
-
|
|
132
|
-
multi_correct : bool, optional
|
|
133
|
-
If set to True, the correction will be generated using a iterative approach.
|
|
134
|
-
(default is False).
|
|
135
|
-
|
|
136
|
-
Returns
|
|
137
|
-
-------
|
|
138
|
-
np.ndarray
|
|
139
|
-
A numpy matrix representing the corrected shape of the device. Pixel values closer
|
|
140
|
-
to 1 indicate a higher likelihood of core material, while pixel values closer to 0
|
|
141
|
-
suggest a higher likelihood of cladding material. Pixel values in between represent
|
|
142
|
-
correction uncertainty.
|
|
143
|
-
"""
|
|
144
|
-
function_url = "https://prefab-photonics--correct.modal.run"
|
|
145
|
-
|
|
146
|
-
correct_data = {
|
|
147
|
-
"device": _encode_image(device),
|
|
148
|
-
"model_name": model_name,
|
|
149
|
-
"model_tags": model_tags,
|
|
150
|
-
"binary": binarize,
|
|
151
|
-
"multi_correct": multi_correct,
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
with open(os.path.expanduser("~/.prefab.toml"), "r") as file:
|
|
155
|
-
content = file.readlines()
|
|
156
|
-
for line in content:
|
|
157
|
-
if "access_token" in line:
|
|
158
|
-
access_token = line.split("=")[1].strip().strip('"')
|
|
159
|
-
if "refresh_token" in line:
|
|
160
|
-
refresh_token = line.split("=")[1].strip().strip('"')
|
|
161
|
-
break
|
|
162
|
-
|
|
163
|
-
headers = {
|
|
164
|
-
"Authorization": f"Bearer {access_token}",
|
|
165
|
-
"X-Refresh-Token": refresh_token,
|
|
166
|
-
}
|
|
167
|
-
response = requests.post(
|
|
168
|
-
url=function_url,
|
|
169
|
-
json=correct_data,
|
|
170
|
-
headers=headers,
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
if response.status_code != 200:
|
|
174
|
-
raise ValueError(response.text)
|
|
175
|
-
else:
|
|
176
|
-
response_data = response.json()
|
|
177
|
-
if "error" in response_data:
|
|
178
|
-
raise ValueError(response_data["error"])
|
|
179
|
-
if "correction" in response_data:
|
|
180
|
-
correction = _decode_image(response_data["correction"])
|
|
181
|
-
if "new_refresh_token" in response_data:
|
|
182
|
-
prefab_file_path = os.path.expanduser("~/.prefab.toml")
|
|
183
|
-
with open(prefab_file_path, "w", encoding="utf-8") as toml_file:
|
|
184
|
-
toml.dump(
|
|
185
|
-
{
|
|
186
|
-
"access_token": response_data["new_access_token"],
|
|
187
|
-
"refresh_token": response_data["new_refresh_token"],
|
|
188
|
-
},
|
|
189
|
-
toml_file,
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
return correction
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
def _encode_image(image: np.ndarray) -> str:
|
|
196
|
-
"""
|
|
197
|
-
Encodes a numpy image array to its base64 representation.
|
|
198
|
-
|
|
199
|
-
Parameters
|
|
200
|
-
----------
|
|
201
|
-
image : np.ndarray
|
|
202
|
-
The image in numpy array format.
|
|
203
|
-
|
|
204
|
-
Returns
|
|
205
|
-
-------
|
|
206
|
-
str
|
|
207
|
-
The base64 encoded string of the image.
|
|
208
|
-
"""
|
|
209
|
-
encoded_image = imencode(".png", 255 * image)[1].tobytes()
|
|
210
|
-
encoded_image_base64 = base64.b64encode(encoded_image).decode("utf-8")
|
|
211
|
-
return encoded_image_base64
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
def _decode_image(encoded_image_base64: str) -> np.ndarray:
|
|
215
|
-
"""
|
|
216
|
-
Decodes a base64 encoded image to its numpy array representation.
|
|
217
|
-
|
|
218
|
-
Parameters
|
|
219
|
-
----------
|
|
220
|
-
encoded_image_base64 : str
|
|
221
|
-
The base64 encoded string of the image.
|
|
222
|
-
|
|
223
|
-
Returns
|
|
224
|
-
-------
|
|
225
|
-
np.ndarray
|
|
226
|
-
The decoded image in numpy array format.
|
|
227
|
-
"""
|
|
228
|
-
encoded_image = base64.b64decode(encoded_image_base64)
|
|
229
|
-
decoded_image = np.frombuffer(encoded_image, np.uint8)
|
|
230
|
-
decoded_image = imdecode(decoded_image, IMREAD_GRAYSCALE) / 255
|
|
231
|
-
return decoded_image
|