prefab 0.4.2__py3-none-any.whl → 0.4.5__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
@@ -13,21 +13,22 @@ from prefab.predictor import correct
13
13
  # I/O Utilities
14
14
  # Function to load/save device images and gds files
15
15
  from prefab.io import (
16
- load_device_img, # Load device from an image file
17
- load_device_gds, # Load device from a GDSII file
18
- device_to_cell # Convert a device layout to a gdspy cell
16
+ load_device_img, # Load device from an image file
17
+ load_device_gds, # Load device from a GDSII file
18
+ device_to_cell, # Convert a device layout to a gdstk cell
19
19
  )
20
20
 
21
21
  # Import image processing utilities
22
22
  # Functions to modify and manipulate device images
23
23
  from prefab.processor import (
24
- binarize, # Soft binarization of grayscale images
25
- binarize_hard, # Hard binarization of grayscale images
26
- remove_padding, # Trims excess padding from device images
27
- zero_boundary, # Applies zero boundary to device images
28
- generate_device_contour, # Generates contour of device images
29
- calculate_prediction_uncertainty, # Computes prediction uncertainty for device images
30
- mse # Computes mean squared error between two images
24
+ binarize, # Soft binarization of grayscale images
25
+ binarize_hard, # Hard binarization of grayscale images
26
+ ternarize, # Ternarization of grayscale images
27
+ remove_padding, # Trims excess padding from device images
28
+ zero_boundary, # Applies zero boundary to device images
29
+ generate_device_contour, # Generates contour of device images
30
+ calculate_prediction_uncertainty, # Computes prediction uncertainty for device images
31
+ mse, # Computes mean squared error between two images
31
32
  )
32
33
 
33
34
  __all__ = (
@@ -37,9 +38,10 @@ __all__ = (
37
38
  "device_to_cell",
38
39
  "binarize",
39
40
  "binarize_hard",
41
+ "ternarize",
40
42
  "remove_padding",
41
43
  "zero_boundary",
42
44
  "generate_device_contour",
43
45
  "calculate_prediction_uncertainty",
44
- "mse"
46
+ "mse",
45
47
  )
prefab/io.py CHANGED
@@ -3,10 +3,10 @@ This module offers tools to import, export, and preprocess device layouts in mul
3
3
  nanofabrication prediction tasks.
4
4
  """
5
5
 
6
- from typing import Optional, List
6
+ from typing import Optional, List, Tuple
7
7
  import matplotlib.image as img
8
8
  import numpy as np
9
- import gdspy
9
+ import gdstk
10
10
  import cv2
11
11
  from prefab.processor import binarize_hard
12
12
 
@@ -15,7 +15,7 @@ def load_device_img(path: str, img_length_nm: int = None) -> np.ndarray:
15
15
  """
16
16
  Load, process and scale device image from file for prediction.
17
17
 
18
- This function reads an image file, scales it according to the provided image length in
18
+ This function reads an image file, scales it according to the provided image length in
19
19
  nanometers, and performs preprocessing tasks such as binarization, preparing it for prediction.
20
20
 
21
21
  Parameters
@@ -24,7 +24,7 @@ def load_device_img(path: str, img_length_nm: int = None) -> np.ndarray:
24
24
  Path to the device image file.
25
25
 
26
26
  img_length_nm : int, optional
27
- Desired length of the device image in nanometers for scaling. If not provided,
27
+ Desired length of the device image in nanometers for scaling. If not provided,
28
28
  the length of the original image is used.
29
29
 
30
30
  Returns
@@ -41,14 +41,18 @@ def load_device_img(path: str, img_length_nm: int = None) -> np.ndarray:
41
41
  return device
42
42
 
43
43
 
44
- def load_device_gds(path: str, cell_name: str,
45
- coords: Optional[List[List[int]]] = None) -> np.ndarray:
44
+ def load_device_gds(
45
+ path: str,
46
+ cell_name: str,
47
+ coords: Optional[List[List[int]]] = None,
48
+ layer: Tuple[int, int] = (1, 0),
49
+ ) -> np.ndarray:
46
50
  """
47
51
  Load and process a device layout from a GDSII file.
48
52
 
49
- This function reads a device layout from a GDSII file, performs necessary
53
+ This function reads a device layout from a GDSII file, performs necessary
50
54
  preprocessing tasks such as scaling and padding, and prepares it for prediction.
51
- Only the first layer (silicon) is loaded.
55
+ Only the specified layer is loaded.
52
56
 
53
57
  Parameters
54
58
  ----------
@@ -59,41 +63,73 @@ def load_device_gds(path: str, cell_name: str,
59
63
  Name of the GDSII cell to be loaded.
60
64
 
61
65
  coords : List[List[int]], optional
62
- A list of coordinates [[xmin, ymin], [xmax, ymax]] in nm, defining the
66
+ A list of coordinates [[xmin, ymin], [xmax, ymax]] in nm, defining the
63
67
  region of the cell to be loaded. If None, the entire cell is loaded.
64
68
 
69
+ layer : Tuple[int, int], optional
70
+ A tuple specifying the layer to be loaded. Default is (1, 0).
71
+
65
72
  Returns
66
73
  -------
67
74
  np.ndarray
68
75
  A 2D numpy array representing the preprocessed device layout, ready for prediction.
69
76
  """
70
- gds = gdspy.GdsLibrary(infile=path)
71
- cell = gds.cells[cell_name]
72
- polygons = cell.get_polygons(by_spec=(1, 0))
73
- bounds = 1000 * cell.get_bounding_box()
74
- device = np.zeros((int(bounds[1][1] - bounds[0][1]),
75
- int(bounds[1][0] - bounds[0][0])))
76
-
77
- contours = [np.array([[[int(1000*vertex[0] - bounds[0][0]),
78
- int(1000*vertex[1] - bounds[0][1])]] for vertex in polygon],
79
- dtype=np.int32)
80
- for polygon in polygons]
81
-
82
- for contour in contours:
83
- cv2.fillPoly(img=device, pts=[contour], color=(1, 1, 1))
77
+ gds = gdstk.read_gds(path)
78
+ cell = gds[cell_name]
79
+ polygons = cell.get_polygons(layer=layer[0], datatype=layer[1])
80
+ bounds = tuple(
81
+ tuple(1000 * x for x in sub_tuple) for sub_tuple in cell.bounding_box()
82
+ )
83
+ device = np.zeros(
84
+ (int(bounds[1][1] - bounds[0][1]), int(bounds[1][0] - bounds[0][0]))
85
+ )
86
+
87
+ contours = [
88
+ np.array(
89
+ [
90
+ [
91
+ [
92
+ int(1000 * vertex[0] - bounds[0][0]),
93
+ int(1000 * vertex[1] - bounds[0][1]),
94
+ ]
95
+ ]
96
+ for vertex in polygon.points
97
+ ],
98
+ dtype=np.int32,
99
+ )
100
+ for polygon in polygons
101
+ ]
102
+
103
+ cv2.fillPoly(img=device, pts=contours, color=(1, 1, 1))
84
104
 
85
105
  if coords is not None:
86
- device = device[int(coords[0][1] - bounds[0][1]):int(coords[1][1] - bounds[0][1]),
87
- int(coords[0][0] - bounds[0][0]):int(coords[1][0] - bounds[0][0])]
106
+ new_device = np.zeros(
107
+ (int(bounds[1][1] - bounds[0][1]), int(bounds[1][0] - bounds[0][0]))
108
+ )
109
+ new_device[
110
+ int(coords[0][1] - bounds[0][1]) : int(coords[1][1] - bounds[0][1]),
111
+ int(coords[0][0] - bounds[0][0]) : int(coords[1][0] - bounds[0][0]),
112
+ ] = device[
113
+ int(coords[0][1] - bounds[0][1]) : int(coords[1][1] - bounds[0][1]),
114
+ int(coords[0][0] - bounds[0][0]) : int(coords[1][0] - bounds[0][0]),
115
+ ]
116
+ device = new_device
88
117
 
89
118
  device = np.flipud(device)
90
119
  device = np.pad(device, 100)
120
+
91
121
  return device
92
122
 
93
123
 
94
- def device_to_cell(device: np.ndarray, cell_name: str, library: gdspy.GdsLibrary,
95
- resolution: float = 1.0, layer: int = 1, approximation_mode: int = 2) -> gdspy.Cell:
96
- """Converts a device layout to a gdspy cell for GDSII export.
124
+ def device_to_cell(
125
+ device: np.ndarray,
126
+ cell_name: str,
127
+ library: gdstk.Library,
128
+ resolution: float = 1.0,
129
+ layer: int = 1,
130
+ approximation_mode: int = 2,
131
+ ) -> gdstk.Cell:
132
+ """Converts a device layout to a gdstk cell for GDSII export.
97
133
 
98
134
  This function creates a cell that represents a device layout. The created cell
99
135
  is ready to be exported as a GDSII file.
@@ -106,14 +142,14 @@ def device_to_cell(device: np.ndarray, cell_name: str, library: gdspy.GdsLibrary
106
142
  cell_name : str
107
143
  Name for the new cell.
108
144
 
109
- library : gdspy.GdsLibrary
145
+ library : gdstk.Library
110
146
  Library to which the cell will be added.
111
147
 
112
148
  resolution : float, optional
113
149
  The resolution of the device in pixels per nm. Default is 1.0.
114
150
 
115
- layer : int, optional
116
- The GDSII layer to be used for the polygons. Default is 1.
151
+ layer : Tuple[int, int], optional
152
+ A tuple specifying the layer to be exported. Default is (1, 0).
117
153
 
118
154
  approximation_mode : int, optional
119
155
  The approximation method to be used for finding contours. Possible values are 1, 2, 3, and
@@ -121,17 +157,22 @@ def device_to_cell(device: np.ndarray, cell_name: str, library: gdspy.GdsLibrary
121
157
 
122
158
  Returns
123
159
  -------
124
- gdspy.Cell
160
+ gdstk.Cell
125
161
  The newly created cell containing the device layout.
126
162
  """
127
- approximation_method_mapping = {1: cv2.CHAIN_APPROX_NONE,
128
- 2: cv2.CHAIN_APPROX_SIMPLE,
129
- 3: cv2.CHAIN_APPROX_TC89_L1,
130
- 4: cv2.CHAIN_APPROX_TC89_KCOS}
163
+ approximation_method_mapping = {
164
+ 1: cv2.CHAIN_APPROX_NONE,
165
+ 2: cv2.CHAIN_APPROX_SIMPLE,
166
+ 3: cv2.CHAIN_APPROX_TC89_L1,
167
+ 4: cv2.CHAIN_APPROX_TC89_KCOS,
168
+ }
131
169
 
132
170
  device = np.flipud(device)
133
- contours, hierarchy = cv2.findContours(device.astype(np.uint8), cv2.RETR_CCOMP,
134
- approximation_method_mapping[approximation_mode])
171
+ contours, hierarchy = cv2.findContours(
172
+ device.astype(np.uint8),
173
+ cv2.RETR_CCOMP,
174
+ approximation_method_mapping[approximation_mode],
175
+ )
135
176
 
136
177
  outer_polygons = []
137
178
  inner_polygons = []
@@ -146,10 +187,14 @@ def device_to_cell(device: np.ndarray, cell_name: str, library: gdspy.GdsLibrary
146
187
  else:
147
188
  inner_polygons.append(points)
148
189
 
149
- polygons = gdspy.boolean(outer_polygons, inner_polygons, 'xor', layer=layer)
150
- polygons.scale(resolution, resolution)
190
+ polygons = gdstk.boolean(
191
+ outer_polygons, inner_polygons, "xor", layer=layer[0], datatype=layer[1]
192
+ )
193
+ for polygon in polygons:
194
+ polygon.scale(resolution, resolution)
151
195
 
152
196
  cell = library.new_cell(cell_name)
153
- cell.add(polygons)
197
+ for polygon in polygons:
198
+ cell.add(polygon)
154
199
 
155
200
  return cell
prefab/predictor.py CHANGED
@@ -9,12 +9,14 @@ import requests
9
9
  from cv2 import imencode, imdecode, IMREAD_GRAYSCALE
10
10
  from prefab.processor import binarize_hard
11
11
 
12
- def predict(device: np.ndarray, model_name: str, model_tag: str,
13
- binarize: bool = False) -> np.ndarray:
12
+
13
+ def predict(
14
+ device: np.ndarray, model_name: str, model_tags: str, binarize: bool = False
15
+ ) -> np.ndarray:
14
16
  """
15
17
  Generates a prediction for a photonic device using a specified cloud-based ML model.
16
18
 
17
- The function sends an image of the device to a cloud function, which uses the specified
19
+ The function sends an image of the device to a cloud function, which uses the specified
18
20
  machine learning model to generate a prediction.
19
21
 
20
22
  Parameters
@@ -23,12 +25,12 @@ def predict(device: np.ndarray, model_name: str, model_tag: str,
23
25
  A binary numpy matrix representing the shape of a device.
24
26
 
25
27
  model_name : str
26
- The name of the ML model to use for the prediction.
28
+ The name of the ML model to use for the prediction.
27
29
  Consult the module's documentation for available models.
28
30
 
29
- model_num : str
30
- The version number of the ML model.
31
- Consult the module's documentation for available versions.
31
+ model_tags : Union[str, List[str]]
32
+ The tags of the ML model.
33
+ Consult the module's documentation for available tags.
32
34
 
33
35
  binarize : bool, optional
34
36
  If set to True, the prediction will be binarized (default is False).
@@ -36,30 +38,36 @@ def predict(device: np.ndarray, model_name: str, model_tag: str,
36
38
  Returns
37
39
  -------
38
40
  np.ndarray
39
- A numpy matrix representing the predicted shape of the device. Pixel values closer
40
- to 1 indicate a higher likelihood of core material, while pixel values closer to 0
41
- suggest a higher likelihood of cladding material. Pixel values in between represent
41
+ A numpy matrix representing the predicted shape of the device. Pixel values closer
42
+ to 1 indicate a higher likelihood of core material, while pixel values closer to 0
43
+ suggest a higher likelihood of cladding material. Pixel values in between represent
42
44
  prediction uncertainty.
43
45
  """
44
- function_url = 'https://prefab-photonics--predict.modal.run'
46
+ function_url = "https://prefab-photonics--predict.modal.run"
45
47
 
46
- predict_data = {'device': _encode_image(device),
47
- 'model_name': model_name,
48
- 'model_tag': model_tag}
48
+ predict_data = {
49
+ "device": _encode_image(device),
50
+ "model_name": model_name,
51
+ "model_tags": model_tags,
52
+ }
49
53
 
50
- prediction = _decode_image(requests.post(function_url, json=predict_data, timeout=200))
54
+ prediction = _decode_image(
55
+ requests.post(function_url, json=predict_data, timeout=200)
56
+ )
51
57
 
52
58
  if binarize:
53
59
  prediction = binarize_hard(prediction)
54
60
 
55
61
  return prediction
56
62
 
57
- def correct(device: np.ndarray, model_name: str, model_tag: str,
58
- binarize: bool = False) -> np.ndarray:
63
+
64
+ def correct(
65
+ device: np.ndarray, model_name: str, model_tags: str, binarize: bool = False
66
+ ) -> np.ndarray:
59
67
  """
60
68
  Generates a correction for a photonic device using a specified cloud-based ML model.
61
69
 
62
- The function sends an image of the device to a cloud function, which uses the specified
70
+ The function sends an image of the device to a cloud function, which uses the specified
63
71
  machine learning model to generate a correction.
64
72
 
65
73
  Parameters
@@ -68,12 +76,12 @@ def correct(device: np.ndarray, model_name: str, model_tag: str,
68
76
  A binary numpy matrix representing the shape of a device.
69
77
 
70
78
  model_name : str
71
- The name of the ML model to use for the correction.
79
+ The name of the ML model to use for the correction.
72
80
  Consult the module's documentation for available models.
73
81
 
74
- model_num : str
75
- The version number of the ML model.
76
- Consult the module's documentation for available versions.
82
+ model_tags : Union[str, List[str]]
83
+ The tags of the ML model.
84
+ Consult the module's documentation for available tags.
77
85
 
78
86
  binarize : bool, optional
79
87
  If set to True, the correction will be binarized (default is False).
@@ -81,24 +89,29 @@ def correct(device: np.ndarray, model_name: str, model_tag: str,
81
89
  Returns
82
90
  -------
83
91
  np.ndarray
84
- A numpy matrix representing the corrected shape of the device. Pixel values closer
85
- to 1 indicate a higher likelihood of core material, while pixel values closer to 0
86
- suggest a higher likelihood of cladding material. Pixel values in between represent
92
+ A numpy matrix representing the corrected shape of the device. Pixel values closer
93
+ to 1 indicate a higher likelihood of core material, while pixel values closer to 0
94
+ suggest a higher likelihood of cladding material. Pixel values in between represent
87
95
  correction uncertainty.
88
96
  """
89
- function_url = 'https://prefab-photonics--correct.modal.run'
97
+ function_url = "https://prefab-photonics--correct.modal.run"
90
98
 
91
- correct_data = {'device': _encode_image(device),
92
- 'model_name': model_name,
93
- 'model_tag': model_tag}
99
+ correct_data = {
100
+ "device": _encode_image(device),
101
+ "model_name": model_name,
102
+ "model_tags": model_tags,
103
+ }
94
104
 
95
- correction = _decode_image(requests.post(function_url, json=correct_data, timeout=200))
105
+ correction = _decode_image(
106
+ requests.post(function_url, json=correct_data, timeout=200)
107
+ )
96
108
 
97
109
  if binarize:
98
110
  correction = binarize_hard(correction)
99
111
 
100
112
  return correction
101
113
 
114
+
102
115
  def _encode_image(image: np.ndarray) -> str:
103
116
  """
104
117
  Encodes a numpy image array to its base64 representation.
@@ -113,10 +126,11 @@ def _encode_image(image: np.ndarray) -> str:
113
126
  str
114
127
  The base64 encoded string of the image.
115
128
  """
116
- encoded_image = imencode('.png', 255 * image)[1].tobytes()
117
- encoded_image_base64 = base64.b64encode(encoded_image).decode('utf-8')
129
+ encoded_image = imencode(".png", 255 * image)[1].tobytes()
130
+ encoded_image_base64 = base64.b64encode(encoded_image).decode("utf-8")
118
131
  return encoded_image_base64
119
132
 
133
+
120
134
  def _decode_image(encoded_image_base64: str) -> np.ndarray:
121
135
  """
122
136
  Decodes a base64 encoded image to its numpy array representation.
prefab/processor.py CHANGED
@@ -13,10 +13,10 @@ def binarize(device: np.ndarray, eta: float = 0.5, beta: float = np.inf) -> np.n
13
13
  """
14
14
  Applies soft binarization to a device image using a sigmoid function.
15
15
 
16
- The binarization process can be controlled by adjusting the thresholding level (`eta`)
17
- and the steepness of the sigmoid function (`beta`). `eta` influences the threshold level
18
- for binarization, simulating under-etching for smaller values and over-etching for larger
19
- values. `beta` controls the steepness of the sigmoid function, thereby determining the
16
+ The binarization process can be controlled by adjusting the thresholding level (`eta`)
17
+ and the steepness of the sigmoid function (`beta`). `eta` influences the threshold level
18
+ for binarization, simulating under-etching for smaller values and over-etching for larger
19
+ values. `beta` controls the steepness of the sigmoid function, thereby determining the
20
20
  degree of binarization.
21
21
 
22
22
  Parameters
@@ -28,7 +28,7 @@ def binarize(device: np.ndarray, eta: float = 0.5, beta: float = np.inf) -> np.n
28
28
  Threshold level for binarization, with values between 0 and 1. Default is 0.5.
29
29
 
30
30
  beta : float, optional
31
- Controls the steepness of the sigmoid function and thereby the degree of
31
+ Controls the steepness of the sigmoid function and thereby the degree of
32
32
  binarization. Default is infinity, resulting in maximum binarization.
33
33
 
34
34
  Returns
@@ -36,8 +36,8 @@ def binarize(device: np.ndarray, eta: float = 0.5, beta: float = np.inf) -> np.n
36
36
  np.ndarray
37
37
  A 2D numpy array representing the binarized device image.
38
38
  """
39
- numerator = np.tanh(beta*eta) + np.tanh(beta*(device - eta))
40
- denominator = np.tanh(beta*eta) + np.tanh(beta*(1 - eta))
39
+ numerator = np.tanh(beta * eta) + np.tanh(beta * (device - eta))
40
+ denominator = np.tanh(beta * eta) + np.tanh(beta * (1 - eta))
41
41
  device_bin = numerator / denominator
42
42
  return device_bin
43
43
 
@@ -48,9 +48,9 @@ def binarize_hard(device: np.ndarray, eta: float = 0.5) -> np.ndarray:
48
48
 
49
49
  The binarization process depends solely on the threshold level (`eta`), which
50
50
  controls the demarcation point for determining the binary values in the output image.
51
- Smaller `eta` values simulate under-etching (more pixels are turned off), while
51
+ Smaller `eta` values simulate under-etching (more pixels are turned off), while
52
52
  larger `eta` values simulate over-etching (more pixels are turned on). Compared to the
53
- sigmoid binarization function, this hard binarization method is less likely to produce
53
+ sigmoid binarization function, this hard binarization method is less likely to produce
54
54
  NaN values and may sometimes yield better results.
55
55
 
56
56
  Parameters
@@ -72,12 +72,46 @@ def binarize_hard(device: np.ndarray, eta: float = 0.5) -> np.ndarray:
72
72
  return device_bin
73
73
 
74
74
 
75
+ def ternarize(device: np.ndarray, eta1: float = 0.33, eta2: float = 0.66) -> np.ndarray:
76
+ """
77
+ Applies ternarization to a device image using two thresholds.
78
+
79
+ This function performs a ternarization process on a given device image, dividing it into three
80
+ distinct regions based on two threshold values (`eta1` and `eta2`). It assigns three different
81
+ values (0, 1, or 2) to each pixel based on its intensity in relation to the thresholds.
82
+ Pixels with intensity less than `eta1` are assigned 0, pixels with intensity greater than or
83
+ equal to `eta2` are assigned 2, and pixels with intensity between `eta1` and `eta2` are
84
+ assigned 1. This function can be useful for categorizing different regions in a device image.
85
+
86
+ Parameters
87
+ ----------
88
+ device : np.ndarray
89
+ A 2D numpy array representing the grayscale device image to be ternarized.
90
+
91
+ eta1 : float, optional
92
+ First threshold level for ternarization, with values between 0 and 1. Default is 0.33.
93
+
94
+ eta2 : float, optional
95
+ Second threshold level for ternarization, with values between 0 and 1. Default is 0.66.
96
+
97
+ Returns
98
+ -------
99
+ np.ndarray
100
+ A 2D numpy array representing the ternarized device image.
101
+ """
102
+ device_ter = np.copy(device)
103
+ device_ter[device_ter < eta1] = 0
104
+ device_ter[device_ter >= eta2] = 1
105
+ device_ter[(device_ter >= eta1) & (device_ter < eta2)] = 0.5
106
+ return device_ter
107
+
108
+
75
109
  def remove_padding(device: np.ndarray) -> np.ndarray:
76
110
  """
77
111
  Removes the empty padding from the edges of a device.
78
112
 
79
- This function eliminates rows and columns from the edges of the device matrix
80
- that are entirely zeros, effectively removing any unnecessary padding present
113
+ This function eliminates rows and columns from the edges of the device matrix
114
+ that are entirely zeros, effectively removing any unnecessary padding present
81
115
  in the device representation.
82
116
 
83
117
  Parameters
@@ -92,8 +126,10 @@ def remove_padding(device: np.ndarray) -> np.ndarray:
92
126
  of equal or smaller size compared to the input device.
93
127
  """
94
128
  nonzero_rows, nonzero_cols = np.nonzero(device)
95
- trimmed_device = device[nonzero_rows.min():nonzero_rows.max()+1,
96
- nonzero_cols.min():nonzero_cols.max()+1]
129
+ trimmed_device = device[
130
+ nonzero_rows.min() : nonzero_rows.max() + 1,
131
+ nonzero_cols.min() : nonzero_cols.max() + 1,
132
+ ]
97
133
  return trimmed_device
98
134
 
99
135
 
@@ -101,8 +137,8 @@ def zero_boundary(device: np.ndarray, margin: int) -> np.ndarray:
101
137
  """
102
138
  Sets the boundaries of a device matrix to zero up to a specified margin.
103
139
 
104
- This function zeroes the outermost rows and columns of the device matrix
105
- up to a distance (margin) from the boundaries, effectively creating a
140
+ This function zeroes the outermost rows and columns of the device matrix
141
+ up to a distance (margin) from the boundaries, effectively creating a
106
142
  "zeroed" frame around the device representation.
107
143
 
108
144
  Parameters
@@ -116,7 +152,7 @@ def zero_boundary(device: np.ndarray, margin: int) -> np.ndarray:
116
152
  Returns
117
153
  -------
118
154
  np.ndarray
119
- A 2D numpy array representing the shape of the device with its outermost
155
+ A 2D numpy array representing the shape of the device with its outermost
120
156
  rows and columns up to 'margin' distance set to zero.
121
157
  """
122
158
  zeroed_device = device.copy()
@@ -127,12 +163,14 @@ def zero_boundary(device: np.ndarray, margin: int) -> np.ndarray:
127
163
  return zeroed_device
128
164
 
129
165
 
130
- def generate_device_contour(device: np.ndarray, linewidth: Optional[int] = None) -> np.ndarray:
166
+ def generate_device_contour(
167
+ device: np.ndarray, linewidth: Optional[int] = None
168
+ ) -> np.ndarray:
131
169
  """
132
170
  Generates a contour of a device for visualization purposes.
133
171
 
134
- This function generates a binary contour of a device's shape which can be overlaid
135
- on top of the device's image for better visualization. The thickness of the contour
172
+ This function generates a binary contour of a device's shape which can be overlaid
173
+ on top of the device's image for better visualization. The thickness of the contour
136
174
  line can be specified, with a default value calculated as 1% of the device's height.
137
175
 
138
176
  Parameters
@@ -141,7 +179,7 @@ def generate_device_contour(device: np.ndarray, linewidth: Optional[int] = None)
141
179
  A 2D numpy array representing the device's shape.
142
180
 
143
181
  linewidth : int, optional
144
- The width of the contour line. If not provided, the linewidth is set
182
+ The width of the contour line. If not provided, the linewidth is set
145
183
  to 1% of the device's height.
146
184
 
147
185
  Returns
@@ -153,8 +191,9 @@ def generate_device_contour(device: np.ndarray, linewidth: Optional[int] = None)
153
191
  linewidth = device.shape[0] // 100
154
192
 
155
193
  binary_device = binarize_hard(device).astype(np.uint8)
156
- contours, _ = cv2.findContours(binary_device, mode=cv2.RETR_CCOMP,
157
- method=cv2.CHAIN_APPROX_SIMPLE)
194
+ contours, _ = cv2.findContours(
195
+ binary_device, mode=cv2.RETR_CCOMP, method=cv2.CHAIN_APPROX_SIMPLE
196
+ )
158
197
 
159
198
  contour_overlay = np.zeros_like(device)
160
199
  cv2.drawContours(contour_overlay, contours, -1, (255, 255, 255), linewidth)
@@ -166,11 +205,11 @@ def calculate_prediction_uncertainty(prediction: np.ndarray) -> np.ndarray:
166
205
  """
167
206
  Computes the uncertainty profile of a non-binary prediction matrix.
168
207
 
169
- This function quantifies the level of uncertainty in a given prediction matrix by
170
- identifying the areas between the core (value 1) and cladding (value 0). These regions
171
- often correspond to the boundaries of the predicted structure and are represented by
172
- pixel values ranging between 0 and 1 in the prediction matrix. The function calculates
173
- the uncertainty as the distance from the pixel value to the nearest extreme (0 or 1),
208
+ This function quantifies the level of uncertainty in a given prediction matrix by
209
+ identifying the areas between the core (value 1) and cladding (value 0). These regions
210
+ often correspond to the boundaries of the predicted structure and are represented by
211
+ pixel values ranging between 0 and 1 in the prediction matrix. The function calculates
212
+ the uncertainty as the distance from the pixel value to the nearest extreme (0 or 1),
174
213
  highlighting regions of maximum uncertainty.
175
214
 
176
215
  Parameters
@@ -181,13 +220,14 @@ def calculate_prediction_uncertainty(prediction: np.ndarray) -> np.ndarray:
181
220
  Returns
182
221
  -------
183
222
  np.ndarray
184
- A 2D numpy array (same shape as the input prediction matrix) representing the
185
- uncertainty profile of the prediction. Higher values correspond to areas of higher
223
+ A 2D numpy array (same shape as the input prediction matrix) representing the
224
+ uncertainty profile of the prediction. Higher values correspond to areas of higher
186
225
  uncertainty.
187
226
  """
188
227
  uncertainty = 1 - 2 * np.abs(0.5 - prediction)
189
228
  return uncertainty
190
229
 
230
+
191
231
  def mse(prediction: np.ndarray, device: np.ndarray) -> float:
192
232
  """
193
233
  Computes the mean squared error (MSE) between a prediction and a device matrix.
@@ -205,4 +245,4 @@ def mse(prediction: np.ndarray, device: np.ndarray) -> float:
205
245
  float
206
246
  The mean squared error between the prediction and device matrices.
207
247
  """
208
- return np.mean((prediction - device)**2)
248
+ return np.mean((prediction - device) ** 2)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: prefab
3
- Version: 0.4.2
3
+ Version: 0.4.5
4
4
  Summary: Machine learning based prediction of photonic device fabrication
5
5
  Project-URL: Homepage, https://github.com/PreFab-Photonics/PreFab
6
6
  Author-email: Dusan Gostimirovic <dusan@prefabphotonics.com>
@@ -525,7 +525,7 @@ Description-Content-Type: text/markdown
525
525
 
526
526
  ![PreFab logo](https://github.com/PreFab-Photonics/PreFab/blob/main/assets/logo.png?raw=true)
527
527
 
528
- `PreFab` leverages **deep learning** to model fabrication-induced structural variations in integrated photonic devices. Through this *virtual nanofabrication environment*, we uncover valuable insights into nanofabrication processes and enhance device design accuracy.
528
+ `PreFab` leverages **deep learning** to model fabrication-induced structural variations in integrated photonic devices. Through this _virtual nanofabrication environment_, we uncover valuable insights into nanofabrication processes and enhance device design accuracy.
529
529
 
530
530
  ## Prediction
531
531
 
@@ -541,16 +541,16 @@ Description-Content-Type: text/markdown
541
541
 
542
542
  ## Models
543
543
 
544
- `PreFab` accommodates unique *predictor* and *corrector* models for each photonic foundry, regularly updated based on recent fabrication data. Current models include (see full list on [`docs/models.md`](docs/models.md)):
544
+ `PreFab` accommodates unique _predictor_ and _corrector_ models for each photonic foundry, regularly updated based on recent fabrication data. Current models include (see full list on [`docs/models.md`](docs/models.md)):
545
545
 
546
- | Foundry | Process | Latest Version | Latest Dataset | Model Name | Model Tag | Status |
547
- | ------- | ------- | -------------- | -------------- | ---------- |---------- | ------ |
548
- | ANT | [NanoSOI](https://www.appliednt.com/nanosoi-fabrication-service/) | v5 (Jun 3 2023) | d4 (Apr 12 2023) | ANT_NanoSOI | v5-d4 | Beta |
549
- | ANT | [SiN (Upper Edge)](https://www.appliednt.com/nanosoi/sys/resources/specs_nitride/) | v5 (Jun 3 2023) | d0 (Jun 1 2023) | ANT_SiN | v5-d0-upper | Alpha |
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 |
546
+ | Foundry | Process | Latest Version | Latest Dataset | Model Name | Model Tag | Status |
547
+ | --------- | ---------------------------------------------------------------------------------- | --------------- | ---------------- | ------------- | ----------- | ------ |
548
+ | ANT | [NanoSOI](https://www.appliednt.com/nanosoi-fabrication-service/) | v5 (Jun 3 2023) | d4 (Apr 12 2023) | ANT_NanoSOI | v5-d4 | Beta |
549
+ | ANT | [SiN (Upper Edge)](https://www.appliednt.com/nanosoi/sys/resources/specs_nitride/) | v5 (Jun 3 2023) | d0 (Jun 1 2023) | ANT_SiN | v5-d0-upper | Alpha |
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 |
552
552
 
553
- *New models and foundries are regularly added. Usage may change. For additional foundry and process models, feel free to contact us or raise an issue.*
553
+ _New models and foundries are regularly added. Usage may change. For additional foundry and process models, feel free to contact us or raise an issue._
554
554
 
555
555
  ## Installation
556
556
 
@@ -0,0 +1,8 @@
1
+ prefab/__init__.py,sha256=0r0FhWL0XnAE_rq9OuqrNsXNOWjU8eI3-wMvHVDBHWc,1461
2
+ prefab/io.py,sha256=lSjtxbk3YmWhG816Ok-LgjMceZIU1lRZy7pWaPlCpF4,6007
3
+ prefab/predictor.py,sha256=BvcmoUuN3g_MNb9IichHMmueqQILnQK7U8LureMXJec,4562
4
+ prefab/processor.py,sha256=lmSOTouyFOb8UZo7JLXi78VjdUz6eJoOyPZMn6IKraw,8996
5
+ prefab-0.4.5.dist-info/METADATA,sha256=GNbIUFC4ZQZZO0KEHxnVxnn6SxXMbczdrdhnjUZpXHw,35014
6
+ prefab-0.4.5.dist-info/WHEEL,sha256=mRYSEL3Ih6g5a_CVMIcwiF__0Ae4_gLYh01YFNwiq1k,87
7
+ prefab-0.4.5.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
8
+ prefab-0.4.5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.18.0
2
+ Generator: hatchling 1.21.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,8 +0,0 @@
1
- prefab/__init__.py,sha256=6PDbpXSExwKQHTl9AxJeSrB8EOPYcHCgq_7zsFcmGBY,1488
2
- prefab/io.py,sha256=1pkSb8OEz2woqYo81mJ-EgRqsLfh21YtvIi5OuSlZVk,5326
3
- prefab/predictor.py,sha256=fc7LRJgTc8SIm-bpNEoDspgth2Fd0k6UTdkAdgbmwBQ,4556
4
- prefab/processor.py,sha256=DH8IX7fx_TMbnvfjfR-acy-JAnYz1efxdQHgLFgF9_k,7580
5
- prefab-0.4.2.dist-info/METADATA,sha256=y3P_3VSWthzRd3vmD0bu-Wslz3_1JKQIVm6jvJhuaiU,34731
6
- prefab-0.4.2.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
7
- prefab-0.4.2.dist-info/licenses/LICENSE,sha256=IMF9i4xIpgCADf0U-V1cuf9HBmqWQd3qtI3FSuyW4zE,26526
8
- prefab-0.4.2.dist-info/RECORD,,