prefab 1.1.9__py3-none-any.whl → 1.2.0__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 CHANGED
@@ -5,7 +5,7 @@ Usage:
5
5
  import prefab as pf
6
6
  """
7
7
 
8
- __version__ = "1.1.9"
8
+ __version__ = "1.2.0"
9
9
 
10
10
  from . import compare, geometry, predict, read, shapes
11
11
  from .device import BufferSpec, Device
prefab/device.py CHANGED
@@ -397,6 +397,54 @@ class Device(BaseModel):
397
397
  semulated_array += np.random.normal(0, 0.03, semulated_array.shape)
398
398
  return self.model_copy(update={"device_array": semulated_array})
399
399
 
400
+ def segment(
401
+ self,
402
+ model: Model,
403
+ gpu: bool = False,
404
+ ) -> "Device":
405
+ """
406
+ Segment a scanning electron microscope (SEM) image into a binary mask.
407
+
408
+ This method applies a specified machine learning model to transform a grayscale
409
+ SEM image into a binary mask, where 1 represents the device structure and 0
410
+ represents the background. This is useful for extracting the device geometry
411
+ from experimental SEM images for analysis or comparison with design intent.
412
+
413
+ Parameters
414
+ ----------
415
+ model : Model
416
+ The model to use for segmentation, representing a specific fabrication
417
+ process and dataset. This model encapsulates details about the fabrication
418
+ foundry, process, material, technology, thickness, and sidewall presence, as
419
+ defined in `models.py`. Each model is associated with a version and dataset
420
+ that detail its creation and the data it was trained on, ensuring the
421
+ segmentation is tailored to specific fabrication parameters.
422
+ gpu : bool
423
+ If True, the prediction will be performed on a GPU. Defaults to False.
424
+ Note: The GPU option has more overhead and will take longer for small
425
+ devices, but will be faster for larger devices.
426
+
427
+ Returns
428
+ -------
429
+ Device
430
+ A new instance of the Device class with its geometry transformed into a
431
+ binary mask.
432
+
433
+ Raises
434
+ ------
435
+ RuntimeError
436
+ If the prediction service returns an error or if the response from the
437
+ service cannot be processed correctly.
438
+ """
439
+ segmented_array = predict_array(
440
+ device_array=self.normalize().device_array,
441
+ model=model,
442
+ model_type="b",
443
+ binarize=False,
444
+ gpu=gpu,
445
+ )
446
+ return self.model_copy(update={"device_array": segmented_array})
447
+
400
448
  def to_ndarray(self) -> np.ndarray:
401
449
  """
402
450
  Converts the device geometry to an ndarray.
@@ -520,7 +568,7 @@ class Device(BaseModel):
520
568
  gdstk.Cell
521
569
  The GDSTK cell object representing the device geometry.
522
570
  """
523
- print(f"Creating cell '{cell_name}'...")
571
+ # print(f"Creating cell '{cell_name}'...")
524
572
  gdstk_cell = self.flatten()._device_to_gdstk(
525
573
  cell_name=cell_name,
526
574
  gds_layer=gds_layer,
prefab/predict.py CHANGED
@@ -5,6 +5,7 @@ import io
5
5
  import json
6
6
  import os
7
7
 
8
+ import gdstk
8
9
  import numpy as np
9
10
  import requests
10
11
  import toml
@@ -17,7 +18,175 @@ from .geometry import binarize_hard
17
18
  from .models import Model
18
19
 
19
20
  BASE_ENDPOINT_URL = "https://prefab-photonics--predict"
20
- ENDPOINT_VERSION = 2
21
+ ENDPOINT_VERSION = "2"
22
+
23
+
24
+ def _predict_poly(
25
+ polygon_points: list,
26
+ model: Model,
27
+ model_type: str,
28
+ eta: float = 0.5,
29
+ ) -> list:
30
+ """
31
+ Predict the nanofabrication outcome for a list of polygons.
32
+
33
+ This function sends polygon data to the server, which uses a specified machine
34
+ learning model to predict the outcome of the nanofabrication process.
35
+
36
+ Parameters
37
+ ----------
38
+ polygon_points : list
39
+ List of polygon points, where each polygon is a list of [x, y] coordinates.
40
+ model : Model
41
+ The model to use for prediction, representing a specific fabrication process and
42
+ dataset. This model encapsulates details about the fabrication foundry, process,
43
+ material, technology, thickness, and sidewall presence, as defined in
44
+ `models.py`. Each model is associated with a version and dataset that detail its
45
+ creation and the data it was trained on, ensuring the prediction is tailored to
46
+ specific fabrication parameters.
47
+ model_type : str
48
+ The type of model to use ('p' for prediction, 'c' for correction).
49
+ eta : float
50
+ The threshold value for binarization. Defaults to 0.5. Because intermediate
51
+ values cannot be preserved in the polygon data, the predicted polygons are
52
+ binarized using a threshold value of eta.
53
+
54
+ Returns
55
+ -------
56
+ list
57
+ List of predicted polygon points with channel information. Each polygon is a
58
+ dict with 'points' (list of coordinates) and 'channel' (int) keys.
59
+
60
+ Raises
61
+ ------
62
+ ValueError
63
+ If the server returns an error or empty response.
64
+ requests.exceptions.RequestException
65
+ If the request to the prediction service fails.
66
+ json.JSONDecodeError
67
+ If the response cannot be parsed as JSON.
68
+ """
69
+ predict_data = {
70
+ "polygons": polygon_points,
71
+ "model": model.to_json(),
72
+ "model_type": model_type,
73
+ "eta": eta,
74
+ }
75
+
76
+ endpoint_url = f"{BASE_ENDPOINT_URL}-poly-v{ENDPOINT_VERSION}.modal.run"
77
+ headers = _prepare_headers()
78
+
79
+ try:
80
+ response = requests.post(
81
+ endpoint_url, data=json.dumps(predict_data), headers=headers
82
+ )
83
+ response.raise_for_status()
84
+
85
+ if not response.content:
86
+ raise ValueError("Empty response received from server")
87
+
88
+ response_data = response.json()
89
+
90
+ if "polygons" in response_data:
91
+ polygons = response_data["polygons"]
92
+ if polygons and isinstance(polygons[0], dict) and "channel" in polygons[0]:
93
+ return polygons
94
+ else:
95
+ return [{"points": points, "channel": 0} for points in polygons]
96
+ else:
97
+ if "error" in response_data:
98
+ raise ValueError(f"Prediction error: {response_data['error']}")
99
+ return []
100
+
101
+ except requests.exceptions.RequestException as e:
102
+ print(f"Request failed: {str(e)}")
103
+ raise
104
+ except json.JSONDecodeError as e:
105
+ print(f"JSON decode error: {str(e)}")
106
+ raise
107
+
108
+
109
+ def predict_gdstk(
110
+ gdstk_cell: gdstk.Cell,
111
+ model: Model,
112
+ model_type: str,
113
+ gds_layer: tuple[int, int] = (1, 0),
114
+ eta: float = 0.5,
115
+ ) -> gdstk.Cell:
116
+ """
117
+ Predict the nanofabrication outcome of a gdstk cell using a specified model.
118
+
119
+ This function extracts polygons from a gdstk cell, sends them to the prediction
120
+ server, and returns a new cell containing the predicted polygons.
121
+
122
+ Parameters
123
+ ----------
124
+ gdstk_cell : gdstk.Cell
125
+ The gdstk.Cell object containing polygons to predict.
126
+ model : Model
127
+ The model to use for prediction, representing a specific fabrication process and
128
+ dataset. This model encapsulates details about the fabrication foundry, process,
129
+ material, technology, thickness, and sidewall presence, as defined in
130
+ `models.py`. Each model is associated with a version and dataset that detail its
131
+ creation and the data it was trained on, ensuring the prediction is tailored to
132
+ specific fabrication parameters.
133
+ model_type : str
134
+ The type of model to use ('p' for prediction, 'c' for correction).
135
+ gds_layer : tuple[int, int]
136
+ The layer and datatype to use within the GDSTK cell. Defaults to (1, 0).
137
+ eta : float
138
+ The threshold value for binarization. Defaults to 0.5. Because intermediate
139
+ values cannot be preserved in the polygon data, the predicted polygons are
140
+ binarized using a threshold value of eta.
141
+
142
+ Returns
143
+ -------
144
+ gdstk.Cell
145
+ A new gdstk cell containing the predicted polygons. For multi-level
146
+ predictions, each level's polygons will be placed on a different layer:
147
+ - Level 0: (layer, 99)
148
+ - Level 1: (layer, 100)
149
+
150
+ Raises
151
+ ------
152
+ ValueError
153
+ If no polygons are found in the specified layer.
154
+ """
155
+ polygons = gdstk_cell.get_polygons(layer=gds_layer[0], datatype=gds_layer[1])
156
+ if not polygons:
157
+ raise ValueError("No polygons found in the specified layer")
158
+
159
+ polygon_points = [polygon.points.tolist() for polygon in polygons]
160
+
161
+ predicted_polygon_data = _predict_poly(
162
+ polygon_points=polygon_points,
163
+ model=model,
164
+ model_type=model_type,
165
+ eta=eta,
166
+ )
167
+
168
+ result_cell = gdstk.Cell(f"{gdstk_cell.name}_predicted")
169
+
170
+ polygons_by_channel = {}
171
+ for polygon_data in predicted_polygon_data:
172
+ channel = polygon_data.get("channel", 0)
173
+ points = polygon_data.get("points", [])
174
+
175
+ if channel not in polygons_by_channel:
176
+ polygons_by_channel[channel] = []
177
+
178
+ polygons_by_channel[channel].append(points)
179
+
180
+ for channel, points_list in polygons_by_channel.items():
181
+ layer = gds_layer[0]
182
+ datatype = 99 + channel
183
+
184
+ for points in points_list:
185
+ points_array = np.array(points)
186
+ polygon = gdstk.Polygon(points_array, layer=layer, datatype=datatype)
187
+ result_cell.add(polygon)
188
+
189
+ return result_cell
21
190
 
22
191
 
23
192
  def predict_array(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefab
3
- Version: 1.1.9
3
+ Version: 1.2.0
4
4
  Summary: Artificial nanofabrication of integrated photonic circuits using deep learning
5
5
  Project-URL: Homepage, https://prefabphotonics.com
6
6
  Project-URL: Repository, https://github.com/PreFab-Photonics/PreFab
@@ -586,7 +586,7 @@ Before you can make PreFab requests, you will need to [create an account](https:
586
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.
587
587
 
588
588
  ```sh
589
- python3 -m prefab setup
589
+ prefab setup
590
590
  ```
591
591
 
592
592
  ### Guides
@@ -603,4 +603,4 @@ PreFab models are hosted on a [serverless cloud platform](https://modal.com/). P
603
603
 
604
604
  ## License
605
605
 
606
- This project is licensed under the LGPL-2.1 license. © 2024 PreFab Photonics.
606
+ This project is licensed under the LGPL-2.1 license. © 2025 PreFab Photonics.
@@ -0,0 +1,14 @@
1
+ prefab/__init__.py,sha256=1aWNs6J8s6UlWOvSlZscZ1W_uZboUlkhVkmJCWvJ7RU,425
2
+ prefab/__main__.py,sha256=1eXWiEoG7eetJMm1qRbK2I5MnzuRgKIoQtBeT-Ps8es,3523
3
+ prefab/compare.py,sha256=0Xgp3tFuP4of-ce9Opc19p8i8lIyXkbVGLuwWBaHSeE,3486
4
+ prefab/device.py,sha256=ZuppXLmDPSfym37U25hSsNu6JNM8ujrr4Bxh3VH4-4s,56582
5
+ prefab/geometry.py,sha256=4fekWMlkdS_qlPNTdPXPhwKuQ5qdQ1Zjf8m9JKd1dA8,12049
6
+ prefab/models.py,sha256=waPNGtuISyY0f8cz7dnbD451CKYCt8EpPGt-4lSOPNU,2581
7
+ prefab/predict.py,sha256=I0gdO0nNAdNQn_ALrHxrDjmBgxIGpPyU_hQYtnF9hYU,17733
8
+ prefab/read.py,sha256=WNqC3xENlndzFwXeCF2E7H3Iq2dO_6rPEPZ58DuloqY,16259
9
+ prefab/shapes.py,sha256=58cyXFNh1kEErq2jEbGd3dWSediU1OSmor_FWwc1V8A,25098
10
+ prefab-1.2.0.dist-info/METADATA,sha256=rd9O4Q3C0adI7BYkkuiEwlqkGw6UlQMpSAFA5Qbuwd0,35025
11
+ prefab-1.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
+ prefab-1.2.0.dist-info/entry_points.txt,sha256=h1_A9O9F3NAIoKXD1RPb3Eo-WCSiHhMB_AnagBi6XTQ,48
13
+ prefab-1.2.0.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
14
+ prefab-1.2.0.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- prefab/__init__.py,sha256=lrYoADI1MlequuC41Rly8vr1kAiFrG8zGw1PILM1rf4,425
2
- prefab/__main__.py,sha256=1eXWiEoG7eetJMm1qRbK2I5MnzuRgKIoQtBeT-Ps8es,3523
3
- prefab/compare.py,sha256=0Xgp3tFuP4of-ce9Opc19p8i8lIyXkbVGLuwWBaHSeE,3486
4
- prefab/device.py,sha256=bN-RkbjhUOXlrnYEJW4H2HqhyxvFrQa15EvhOmGXgkY,54603
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.9.dist-info/METADATA,sha256=Un--7bA5ihvvtaXK733Q1Zd_8d-EBl1ohWfcdJCdOBI,35036
11
- prefab-1.1.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
12
- prefab-1.1.9.dist-info/entry_points.txt,sha256=h1_A9O9F3NAIoKXD1RPb3Eo-WCSiHhMB_AnagBi6XTQ,48
13
- prefab-1.1.9.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
14
- prefab-1.1.9.dist-info/RECORD,,
File without changes