This notebook offers an interactive tutorial on using PreFab to predict the fabrication result of a 500 nm-wide target nanostructure on a silicon-on-insulator (SOI) e-beam lithography process. This tutorial is structured as follows:
- Preparing a test device for prediction
- Executing a prediction
- Analyzing the prediction and uncertainty
To begin, we need to import the necessary libraries:
import prefab as pf
Loading a device¶
The first step involves preparing a device for prediction. Device
is the base class that represents photonic design geometries in PreFab and can be instantiated by loading an image or GDS layout as an ndarray with binary pixel values: 0 or 1. In this tutorial, we'll use a small target structure, but feel free to explore other structures available in the shapes.py
module, or add your own.
device = pf.shapes.target(width=500, arm_width=60)
device.plot(show_buffer=False)
<Axes: xlabel='x (nm)', ylabel='y (nm)'>
Predicting a device¶
We proceed with the prediction of the device for a specific fabrication model. Each model is labeled by its fabrication facility and process name, model version, and dataset version. Refer to docs/models.md
for a library of available models.
You can also select if you want a binarized output. The prediction model, by default, produces raw outputs, which includes "fuzzy" edges of the structure that may vary between different fabrication runs or even different device instances on the same chip. When binarized, the prediction model outputs the most probable fabrication outcome (i.e., a threshold of 50%). Post-prediction binarization is also an option, as we'll show here.
Note: Initial prediction/correction may take longer due to server startup and model loading. Subsequent predictions should be quicker.
MODEL_NAME = "ANT_NanoSOI_ANF1_d10"
prediction = device.predict(model=pf.models[MODEL_NAME])
prediction_bin = prediction.binarize()
prediction.plot(show_buffer=False)
prediction_bin.plot(show_buffer=False)
Prediction: 100%|██████████████████████████████| 100/100 [00:02<00:00, 43.12%/s]
<Axes: xlabel='x (nm)', ylabel='y (nm)'>
Analyzing a prediction¶
Comparing the (binary) prediction with the nominal device, we can observe erosion (or corner rounding, or over-etching) in the 60 nm-wide arms and convex corners of the target geometry. We also see dilation (or under-etching) for the concave corners in the center, as well as the complete filling of the center opening.
prediction_bin.plot_compare(ref_device=device, show_buffer=False)
<Axes: xlabel='x (nm)', ylabel='y (nm)'>
To evaluate the quality of the prediction quantitatively, PreFab provides a function to compute the Intersection over Union (IoU) between the prediction and the nominal device. This metric measures the overlap between the two geometries, where 1.0 indicates a perfect match and 0.0 indicates no overlap.
print(
f"Prediction IoU: {pf.compare.intersection_over_union(device, prediction_bin):.2f}"
)
Prediction IoU: 0.83
83% is not great, but the feature size was demanding. Try other values for arm_width
and see how it affects the results.
We can further visualize and understand the prediction by highlighting the "fuzzy" edge regions. This is a measure of the uncertainty of the prediction model due to stochastic variance in the fabrication process and the modelling process. From device-to-device, run-to-run, the device edge may lie anywhere in this uncertainty region. Although PreFab cannot correct for uncertainty, visualizing it is valuable in identifying features with high variance.
prediction.plot_uncertainty(show_buffer=False)
<Axes: xlabel='x (nm)', ylabel='y (nm)'>
And that's it! See the next example to learn how to restore this nanostructure using PreFab's correction capabilities.