prefab 0.4.7__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 +95 -0
- 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.4.7.dist-info → prefab-1.1.8.dist-info}/METADATA +47 -34
- prefab-1.1.8.dist-info/RECORD +14 -0
- {prefab-0.4.7.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 -200
- prefab/predictor.py +0 -161
- prefab/processor.py +0 -248
- prefab-0.4.7.dist-info/RECORD +0 -8
- {prefab-0.4.7.dist-info → prefab-1.1.8.dist-info}/licenses/LICENSE +0 -0
prefab/geometry.py
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
"""Provides functions for manipulating ndarrays of device geometries."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import cv2
|
|
6
|
+
import numpy as np
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def normalize(device_array: np.ndarray) -> np.ndarray:
|
|
10
|
+
"""
|
|
11
|
+
Normalize the input ndarray to have values between 0 and 1.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
device_array : np.ndarray
|
|
16
|
+
The input array to be normalized.
|
|
17
|
+
|
|
18
|
+
Returns
|
|
19
|
+
-------
|
|
20
|
+
np.ndarray
|
|
21
|
+
The normalized array with values scaled between 0 and 1.
|
|
22
|
+
"""
|
|
23
|
+
return (device_array - np.min(device_array)) / (
|
|
24
|
+
np.max(device_array) - np.min(device_array)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def binarize(
|
|
29
|
+
device_array: np.ndarray, eta: float = 0.5, beta: float = np.inf
|
|
30
|
+
) -> np.ndarray:
|
|
31
|
+
"""
|
|
32
|
+
Binarize the input ndarray based on a threshold and a scaling factor.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
device_array : np.ndarray
|
|
37
|
+
The input array to be binarized.
|
|
38
|
+
eta : float
|
|
39
|
+
The threshold value for binarization. Defaults to 0.5.
|
|
40
|
+
beta : float
|
|
41
|
+
The scaling factor for the binarization process. A higher value makes the
|
|
42
|
+
transition sharper. Defaults to np.inf, which results in a hard threshold.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
np.ndarray
|
|
47
|
+
The binarized array with elements scaled to 0 or 1.
|
|
48
|
+
"""
|
|
49
|
+
return (np.tanh(beta * eta) + np.tanh(beta * (device_array - eta))) / (
|
|
50
|
+
np.tanh(beta * eta) + np.tanh(beta * (1 - eta))
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def binarize_hard(device_array: np.ndarray, eta: float = 0.5) -> np.ndarray:
|
|
55
|
+
"""
|
|
56
|
+
Apply a hard threshold to binarize the input ndarray. The `binarize` function is
|
|
57
|
+
generally preferred for most use cases, but it can create numerical artifacts for
|
|
58
|
+
large beta values.
|
|
59
|
+
|
|
60
|
+
Parameters
|
|
61
|
+
----------
|
|
62
|
+
device_array : np.ndarray
|
|
63
|
+
The input array to be binarized.
|
|
64
|
+
eta : float
|
|
65
|
+
The threshold value for binarization. Defaults to 0.5.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
np.ndarray
|
|
70
|
+
The binarized array with elements set to 0 or 1 based on the threshold.
|
|
71
|
+
"""
|
|
72
|
+
return np.where(device_array < eta, 0.0, 1.0)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def binarize_sem(sem_array: np.ndarray) -> np.ndarray:
|
|
76
|
+
"""
|
|
77
|
+
Binarize a grayscale scanning electron microscope (SEM) image.
|
|
78
|
+
|
|
79
|
+
This function applies Otsu's method to automatically determine the optimal threshold
|
|
80
|
+
value for binarization of a grayscale SEM image.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
sem_array : np.ndarray
|
|
85
|
+
The input SEM image array to be binarized.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
np.ndarray
|
|
90
|
+
The binarized SEM image array with elements scaled to 0 or 1.
|
|
91
|
+
"""
|
|
92
|
+
return cv2.threshold(
|
|
93
|
+
sem_array.astype("uint8"), 0, 1, cv2.THRESH_BINARY + cv2.THRESH_OTSU
|
|
94
|
+
)[1]
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def binarize_monte_carlo(
|
|
98
|
+
device_array: np.ndarray,
|
|
99
|
+
noise_magnitude: float,
|
|
100
|
+
blur_radius: float,
|
|
101
|
+
) -> np.ndarray:
|
|
102
|
+
"""
|
|
103
|
+
Binarize the input ndarray using a dynamic thresholding approach to simulate surface
|
|
104
|
+
roughness.
|
|
105
|
+
|
|
106
|
+
This function applies a dynamic thresholding technique where the threshold value is
|
|
107
|
+
determined by a base value perturbed by Gaussian-distributed random noise. The
|
|
108
|
+
threshold is then spatially varied across the array using Gaussian blurring,
|
|
109
|
+
simulating a potentially more realistic scenario where the threshold is not uniform
|
|
110
|
+
across the device.
|
|
111
|
+
|
|
112
|
+
Notes
|
|
113
|
+
-----
|
|
114
|
+
This is a temporary solution, where the defaults are chosen based on what looks
|
|
115
|
+
good. A better, data-driven approach is needed.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
device_array : np.ndarray
|
|
120
|
+
The input array to be binarized.
|
|
121
|
+
noise_magnitude : float
|
|
122
|
+
The standard deviation of the Gaussian distribution used to generate noise for
|
|
123
|
+
the threshold values. This controls the amount of randomness in the threshold.
|
|
124
|
+
blur_radius : float
|
|
125
|
+
The standard deviation for the Gaussian kernel used in blurring the threshold
|
|
126
|
+
map. This controls the spatial variation of the threshold across the array.
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
np.ndarray
|
|
131
|
+
The binarized array with elements set to 0 or 1 based on the dynamically
|
|
132
|
+
generated threshold.
|
|
133
|
+
"""
|
|
134
|
+
device_array = np.squeeze(device_array)
|
|
135
|
+
base_threshold = np.random.normal(loc=0.5, scale=0.1)
|
|
136
|
+
threshold_noise = np.random.normal(
|
|
137
|
+
loc=0, scale=noise_magnitude, size=device_array.shape
|
|
138
|
+
)
|
|
139
|
+
spatial_threshold = cv2.GaussianBlur(
|
|
140
|
+
threshold_noise, ksize=(0, 0), sigmaX=blur_radius
|
|
141
|
+
)
|
|
142
|
+
dynamic_threshold = base_threshold + spatial_threshold
|
|
143
|
+
binarized_array = np.where(device_array < dynamic_threshold, 0.0, 1.0)
|
|
144
|
+
binarized_array = np.expand_dims(binarized_array, axis=-1)
|
|
145
|
+
return binarized_array
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def ternarize(
|
|
149
|
+
device_array: np.ndarray, eta1: float = 1 / 3, eta2: float = 2 / 3
|
|
150
|
+
) -> np.ndarray:
|
|
151
|
+
"""
|
|
152
|
+
Ternarize the input ndarray based on two thresholds. This function is useful for
|
|
153
|
+
flattened devices with angled sidewalls (i.e., three segments).
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
device_array : np.ndarray
|
|
158
|
+
The input array to be ternarized.
|
|
159
|
+
eta1 : float
|
|
160
|
+
The first threshold value for ternarization. Defaults to 1/3.
|
|
161
|
+
eta2 : float
|
|
162
|
+
The second threshold value for ternarization. Defaults to 2/3.
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
np.ndarray
|
|
167
|
+
The ternarized array with elements set to 0, 0.5, or 1 based on the thresholds.
|
|
168
|
+
"""
|
|
169
|
+
return np.where(device_array < eta1, 0.0, np.where(device_array >= eta2, 1.0, 0.5))
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def trim(
|
|
173
|
+
device_array: np.ndarray, buffer_thickness: Optional[dict[str, int]] = None
|
|
174
|
+
) -> np.ndarray:
|
|
175
|
+
"""
|
|
176
|
+
Trim the input ndarray by removing rows and columns that are completely zero.
|
|
177
|
+
|
|
178
|
+
Parameters
|
|
179
|
+
----------
|
|
180
|
+
device_array : np.ndarray
|
|
181
|
+
The input array to be trimmed.
|
|
182
|
+
buffer_thickness : Optional[dict[str, int]]
|
|
183
|
+
A dictionary specifying the thickness of the buffer to leave around the non-zero
|
|
184
|
+
elements of the array. Should contain keys 'top', 'bottom', 'left', 'right'.
|
|
185
|
+
Defaults to None, which means no buffer is added.
|
|
186
|
+
|
|
187
|
+
Returns
|
|
188
|
+
-------
|
|
189
|
+
np.ndarray
|
|
190
|
+
The trimmed array, potentially with a buffer around the non-zero elements.
|
|
191
|
+
"""
|
|
192
|
+
if buffer_thickness is None:
|
|
193
|
+
buffer_thickness = {"top": 0, "bottom": 0, "left": 0, "right": 0}
|
|
194
|
+
|
|
195
|
+
nonzero_rows, nonzero_cols = np.nonzero(np.squeeze(device_array))
|
|
196
|
+
row_min = max(nonzero_rows.min() - buffer_thickness.get("top", 0), 0)
|
|
197
|
+
row_max = min(
|
|
198
|
+
nonzero_rows.max() + buffer_thickness.get("bottom", 0) + 1,
|
|
199
|
+
device_array.shape[0],
|
|
200
|
+
)
|
|
201
|
+
col_min = max(nonzero_cols.min() - buffer_thickness.get("left", 0), 0)
|
|
202
|
+
col_max = min(
|
|
203
|
+
nonzero_cols.max() + buffer_thickness.get("right", 0) + 1,
|
|
204
|
+
device_array.shape[1],
|
|
205
|
+
)
|
|
206
|
+
return device_array[
|
|
207
|
+
row_min:row_max,
|
|
208
|
+
col_min:col_max,
|
|
209
|
+
]
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def pad(device_array: np.ndarray, pad_width: int) -> np.ndarray:
|
|
213
|
+
"""
|
|
214
|
+
Pad the input ndarray uniformly with a specified width on all sides.
|
|
215
|
+
|
|
216
|
+
Parameters
|
|
217
|
+
----------
|
|
218
|
+
device_array : np.ndarray
|
|
219
|
+
The input array to be padded.
|
|
220
|
+
pad_width : int
|
|
221
|
+
The number of pixels to pad on each side.
|
|
222
|
+
|
|
223
|
+
Returns
|
|
224
|
+
-------
|
|
225
|
+
np.ndarray
|
|
226
|
+
The padded array.
|
|
227
|
+
"""
|
|
228
|
+
return np.pad(
|
|
229
|
+
device_array,
|
|
230
|
+
pad_width=((pad_width, pad_width), (pad_width, pad_width), (0, 0)),
|
|
231
|
+
mode="constant",
|
|
232
|
+
constant_values=0,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
def blur(device_array: np.ndarray, sigma: float = 1.0) -> np.ndarray:
|
|
237
|
+
"""
|
|
238
|
+
Apply Gaussian blur to the input ndarray and normalize the result.
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
device_array : np.ndarray
|
|
243
|
+
The input array to be blurred.
|
|
244
|
+
sigma : float
|
|
245
|
+
The standard deviation for the Gaussian kernel. This controls the amount of
|
|
246
|
+
blurring. Defaults to 1.0.
|
|
247
|
+
|
|
248
|
+
Returns
|
|
249
|
+
-------
|
|
250
|
+
np.ndarray
|
|
251
|
+
The blurred and normalized array with values scaled between 0 and 1.
|
|
252
|
+
"""
|
|
253
|
+
return np.expand_dims(
|
|
254
|
+
normalize(cv2.GaussianBlur(device_array, ksize=(0, 0), sigmaX=sigma)), axis=-1
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def rotate(device_array: np.ndarray, angle: float) -> np.ndarray:
|
|
259
|
+
"""
|
|
260
|
+
Rotate the input ndarray by a given angle.
|
|
261
|
+
|
|
262
|
+
Parameters
|
|
263
|
+
----------
|
|
264
|
+
device_array : np.ndarray
|
|
265
|
+
The input array to be rotated.
|
|
266
|
+
angle : float
|
|
267
|
+
The angle of rotation in degrees. Positive values mean counter-clockwise
|
|
268
|
+
rotation.
|
|
269
|
+
|
|
270
|
+
Returns
|
|
271
|
+
-------
|
|
272
|
+
np.ndarray
|
|
273
|
+
The rotated array.
|
|
274
|
+
"""
|
|
275
|
+
center = (device_array.shape[1] / 2, device_array.shape[0] / 2)
|
|
276
|
+
rotation_matrix = cv2.getRotationMatrix2D(center=center, angle=angle, scale=1)
|
|
277
|
+
return np.expand_dims(
|
|
278
|
+
cv2.warpAffine(
|
|
279
|
+
device_array,
|
|
280
|
+
M=rotation_matrix,
|
|
281
|
+
dsize=(device_array.shape[1], device_array.shape[0]),
|
|
282
|
+
),
|
|
283
|
+
axis=-1,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
def erode(device_array: np.ndarray, kernel_size: int) -> np.ndarray:
|
|
288
|
+
"""
|
|
289
|
+
Erode the input ndarray using a specified kernel size and number of iterations.
|
|
290
|
+
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
device_array : np.ndarray
|
|
294
|
+
The input array representing the device geometry to be eroded.
|
|
295
|
+
kernel_size : int
|
|
296
|
+
The size of the kernel used for erosion.
|
|
297
|
+
|
|
298
|
+
Returns
|
|
299
|
+
-------
|
|
300
|
+
np.ndarray
|
|
301
|
+
The eroded array.
|
|
302
|
+
"""
|
|
303
|
+
kernel = np.ones((kernel_size, kernel_size), dtype=np.uint8)
|
|
304
|
+
return np.expand_dims(cv2.erode(device_array, kernel=kernel), axis=-1)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def dilate(device_array: np.ndarray, kernel_size: int) -> np.ndarray:
|
|
308
|
+
"""
|
|
309
|
+
Dilate the input ndarray using a specified kernel size.
|
|
310
|
+
|
|
311
|
+
Parameters
|
|
312
|
+
----------
|
|
313
|
+
device_array : np.ndarray
|
|
314
|
+
The input array representing the device geometry to be dilated.
|
|
315
|
+
kernel_size : int
|
|
316
|
+
The size of the kernel used for dilation.
|
|
317
|
+
|
|
318
|
+
Returns
|
|
319
|
+
-------
|
|
320
|
+
np.ndarray
|
|
321
|
+
The dilated array.
|
|
322
|
+
"""
|
|
323
|
+
kernel = np.ones((kernel_size, kernel_size), dtype=np.uint8)
|
|
324
|
+
return np.expand_dims(cv2.dilate(device_array, kernel=kernel), axis=-1)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def flatten(device_array: np.ndarray) -> np.ndarray:
|
|
328
|
+
"""
|
|
329
|
+
Flatten the input ndarray by summing the vertical layers and normalizing the result.
|
|
330
|
+
|
|
331
|
+
Parameters
|
|
332
|
+
----------
|
|
333
|
+
device_array : np.ndarray
|
|
334
|
+
The input array to be flattened.
|
|
335
|
+
|
|
336
|
+
Returns
|
|
337
|
+
-------
|
|
338
|
+
np.ndarray
|
|
339
|
+
The flattened array with values scaled between 0 and 1.
|
|
340
|
+
"""
|
|
341
|
+
return normalize(np.sum(device_array, axis=-1, keepdims=True))
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def enforce_feature_size(
|
|
345
|
+
device_array: np.ndarray, min_feature_size: int, strel: str = "disk"
|
|
346
|
+
) -> np.ndarray:
|
|
347
|
+
"""
|
|
348
|
+
Enforce a minimum feature size on the device geometry.
|
|
349
|
+
|
|
350
|
+
This function applies morphological operations to ensure that all features in the
|
|
351
|
+
device geometry are at least the specified minimum size. It uses either a disk
|
|
352
|
+
or square structuring element for the operations.
|
|
353
|
+
|
|
354
|
+
Notes
|
|
355
|
+
-----
|
|
356
|
+
This function does not guarantee that the minimum feature size is enforced in all
|
|
357
|
+
cases. A better process is needed.
|
|
358
|
+
|
|
359
|
+
Parameters
|
|
360
|
+
----------
|
|
361
|
+
device_array : np.ndarray
|
|
362
|
+
The input array representing the device geometry.
|
|
363
|
+
min_feature_size : int
|
|
364
|
+
The minimum feature size to enforce, in nanometers.
|
|
365
|
+
strel : str
|
|
366
|
+
The type of structuring element to use. Can be either "disk" or "square".
|
|
367
|
+
Defaults to "disk".
|
|
368
|
+
|
|
369
|
+
Returns
|
|
370
|
+
-------
|
|
371
|
+
np.ndarray
|
|
372
|
+
The modified device array with enforced feature size.
|
|
373
|
+
|
|
374
|
+
Raises
|
|
375
|
+
------
|
|
376
|
+
ValueError
|
|
377
|
+
If an invalid structuring element type is specified.
|
|
378
|
+
"""
|
|
379
|
+
if strel == "disk":
|
|
380
|
+
kernel = cv2.getStructuringElement(
|
|
381
|
+
cv2.MORPH_ELLIPSE, (min_feature_size, min_feature_size)
|
|
382
|
+
)
|
|
383
|
+
elif strel == "square":
|
|
384
|
+
kernel = cv2.getStructuringElement(
|
|
385
|
+
cv2.MORPH_RECT, (min_feature_size, min_feature_size)
|
|
386
|
+
)
|
|
387
|
+
else:
|
|
388
|
+
raise ValueError(f"Invalid structuring element: {strel}")
|
|
389
|
+
|
|
390
|
+
device_array_2d = (device_array[:, :, 0] * 255).astype(np.uint8)
|
|
391
|
+
modified_geometry = cv2.morphologyEx(device_array_2d, cv2.MORPH_CLOSE, kernel)
|
|
392
|
+
modified_geometry = cv2.morphologyEx(modified_geometry, cv2.MORPH_OPEN, kernel)
|
|
393
|
+
|
|
394
|
+
return np.expand_dims(modified_geometry.astype(float) / 255, axis=-1)
|
prefab/models.py
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Models for the PreFab library."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from datetime import date
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Fab(BaseModel):
|
|
10
|
+
"""
|
|
11
|
+
Represents a fabrication process in the PreFab model library.
|
|
12
|
+
|
|
13
|
+
Attributes
|
|
14
|
+
----------
|
|
15
|
+
foundry : str
|
|
16
|
+
The name of the foundry where the fabrication process takes place.
|
|
17
|
+
process : str
|
|
18
|
+
The specific process used in the fabrication.
|
|
19
|
+
material : str
|
|
20
|
+
The material used in the fabrication process.
|
|
21
|
+
technology : str
|
|
22
|
+
The technology used in the fabrication process.
|
|
23
|
+
thickness : int
|
|
24
|
+
The thickness of the material used, measured in nanometers.
|
|
25
|
+
has_sidewall : bool
|
|
26
|
+
Indicates whether the fabrication has angled sidewalls.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
foundry: str
|
|
30
|
+
process: str
|
|
31
|
+
material: str
|
|
32
|
+
technology: str
|
|
33
|
+
thickness: int
|
|
34
|
+
has_sidewall: bool
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Model(BaseModel):
|
|
38
|
+
"""
|
|
39
|
+
Represents a model of a fabrication process including versioning and dataset detail.
|
|
40
|
+
|
|
41
|
+
Attributes
|
|
42
|
+
----------
|
|
43
|
+
fab : Fab
|
|
44
|
+
An instance of the Fab class representing the fabrication details.
|
|
45
|
+
version : str
|
|
46
|
+
The version identifier of the model.
|
|
47
|
+
version_date : date
|
|
48
|
+
The release date of this version of the model.
|
|
49
|
+
dataset : str
|
|
50
|
+
The identifier for the dataset used in this model.
|
|
51
|
+
dataset_date : date
|
|
52
|
+
The date when the dataset was last updated or released.
|
|
53
|
+
tag : str
|
|
54
|
+
An optional tag for additional categorization or notes.
|
|
55
|
+
|
|
56
|
+
Methods
|
|
57
|
+
-------
|
|
58
|
+
to_json()
|
|
59
|
+
Serializes the model instance to a JSON formatted string.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
fab: Fab
|
|
63
|
+
version: str
|
|
64
|
+
version_date: date
|
|
65
|
+
dataset: str
|
|
66
|
+
dataset_date: date
|
|
67
|
+
tag: str
|
|
68
|
+
|
|
69
|
+
def to_json(self):
|
|
70
|
+
return json.dumps(self.dict(), default=str)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
ANT_NanoSOI = Fab(
|
|
74
|
+
foundry="ANT",
|
|
75
|
+
process="NanoSOI",
|
|
76
|
+
material="SOI",
|
|
77
|
+
technology="E-Beam",
|
|
78
|
+
thickness=220,
|
|
79
|
+
has_sidewall=False,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
ANT_SiN = Fab(
|
|
83
|
+
foundry="ANT",
|
|
84
|
+
process="SiN",
|
|
85
|
+
material="SiN",
|
|
86
|
+
technology="E-Beam",
|
|
87
|
+
thickness=400,
|
|
88
|
+
has_sidewall=True,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
ANT_NanoSOI_ANF1_d10 = Model(
|
|
92
|
+
fab=ANT_NanoSOI,
|
|
93
|
+
version="ANF1",
|
|
94
|
+
version_date=date(2024, 5, 6),
|
|
95
|
+
dataset="d10",
|
|
96
|
+
dataset_date=date(2024, 6, 8),
|
|
97
|
+
tag="",
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
ANT_SiN_ANF1_d1 = Model(
|
|
101
|
+
fab=ANT_SiN,
|
|
102
|
+
version="ANF1",
|
|
103
|
+
version_date=date(2024, 5, 6),
|
|
104
|
+
dataset="d1",
|
|
105
|
+
dataset_date=date(2024, 1, 31),
|
|
106
|
+
tag="",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
models = dict(
|
|
110
|
+
ANT_NanoSOI=ANT_NanoSOI_ANF1_d10,
|
|
111
|
+
ANT_NanoSOI_ANF1_d10=ANT_NanoSOI_ANF1_d10,
|
|
112
|
+
ANT_SiN=ANT_SiN_ANF1_d1,
|
|
113
|
+
ANT_SiN_ANF1_d1=ANT_SiN_ANF1_d1,
|
|
114
|
+
)
|