NanoFab Optimizer is a small research prototype for exploring binary illumination patterns for nanoscale optical fabrication. It generates 7×7 digital micromirror device (DMD) motifs, simulates their diffraction-limited projection, and trains a machine-learning surrogate to predict their peak intensity.
The current model is intentionally simplified. It is useful for investigating pattern geometry and optimization workflows, but its results are not yet validated fabrication recipes.
The repository implements this workflow:
- Reduce a 7×7 binary pattern to 13 independent variables by requiring C4 symmetry (invariance under 90-degree rotations).
- Enumerate all
2^13 = 8,192symmetric motifs. - Project each motif through a coherent Fourier-optics model with an ideal circular pupil.
- Measure peak intensity, horizontal full width at half maximum (FWHM), total energy, and active-pixel count.
- Train a random-forest surrogate that predicts peak intensity from motif geometry.
The default optical parameters are:
| Parameter | Value |
|---|---|
| Wavelength | 804 nm |
| Numerical aperture | 1.25 |
| Projected pixel pitch | 114 nm |
| Simulation grid | 128×128 |
src/nanofab_optimizer/
motifs.py C4 motif generation and 13-bit encoding
optics.py Coherent diffraction simulation and FWHM measurement
scripts/
run_motif.py Simulate and plot one example motif
generate_motif_dataset.py Simulate all 8,192 motifs
analyze_motif_dataset.py Summarize and visualize the dataset
train_peak_surrogate.py Train and evaluate random-forest models
tests/ Unit tests for motifs and optics
outputs/ Generated dataset and plots
The project requires Python 3.11 or newer and uses uv for environment and dependency management.
git clone <repository-url>
cd nanofab-optimizer
uv syncTo include the test and lint dependencies:
uv sync --group devRun a single example motif and create outputs/motif_v01.png:
uv run python scripts/run_motif.pyGenerate the complete C4-symmetric dataset:
uv run python scripts/generate_motif_dataset.pyThis writes outputs/motif_dataset_v02.npz. Analyze it and regenerate the
summary figures with:
uv run python scripts/analyze_motif_dataset.pyTrain and evaluate the peak-intensity surrogate:
uv run python scripts/train_peak_surrogate.pyRun the test suite:
uv run pytestThe checked-in dataset contains all 8,192 C4-symmetric motifs. Relative values use the fully illuminated 7×7 motif as the reference.
| Result | Value |
|---|---|
| Highest relative peak intensity | 1.1144 |
| FWHM of highest-peak motif | 440.5 nm |
| Active pixels in highest-peak motif | 37 of 49 |
| All-on reference FWHM | 531.6 nm |
| Narrowest measured FWHM | 330.4 nm |
| Relative peak of narrowest motif | 0.0052 |
The highest-peak motif is:
0 0 1 1 1 0 0
0 1 1 1 1 1 0
1 1 1 1 1 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
0 1 1 1 1 1 0
0 0 1 1 1 0 0
On the fixed 80/20 train/test split, the geometry-aware random forest achieves an R² of approximately 0.998 and identifies the true highest-peak motif. A baseline using only the number of active pixels achieves an R² of approximately 0.42, showing that spatial arrangement matters substantially.
simulate_motif treats the binary motif as a coherent input field. It centers
that field on the simulation grid, transforms it into spatial-frequency space,
removes frequencies above NA / wavelength, and inverse-transforms the filtered
field. Intensity is the squared magnitude of the resulting complex field.
FWHM is measured along the horizontal profile through the global intensity maximum, with linear interpolation at the half-maximum crossings.
The simulator is a V0.1 coherent diffraction model, not a complete GP-TPL or fabrication model. It currently omits effects such as:
- broadband femtosecond illumination;
- nonlinear two-photon material response and exposure thresholds;
- aberrations, polarization, and DMD phase effects;
- defocus and full 3D propagation;
- process constraints and experimental calibration.
The surrogate is also evaluated on samples drawn from the same finite design space used for training. Since the current 8,192-pattern space can be enumerated directly, its main purpose is to demonstrate an approach that can scale to larger, non-exhaustive searches.
Format and lint the project with Ruff:
uv run ruff check .
uv run ruff format --check .The reusable code lives under src/nanofab_optimizer; the scripts currently act
as direct, configuration-by-source research experiments.