Model Interface¶
openlithohub.models.base
¶
Abstract base class for lithography optimization models.
PredictionResult
dataclass
¶
Result from a model prediction.
Output contract for mask:
- shape: same as the input
design((H, W),(C, H, W), or(B, C, H, W)). - dtype:
torch.float32. - range: values in
[0, 1]. Models that emit logits MUST applysigmoid(and any project-required binarization) before populating this field. - binarization: implementations should return binarized masks
(
mask > 0.5) by default so downstream metrics (DRC/MRC, PV-band, shot-count) see the same contract across baselines. Models that benefit from emitting a soft mask for further processing should document the deviation in theirpredict()docstring; the default Neural-ILT and GAN-OPC adapters both binarize.
contour is optional and used for vector-mode visualization /
GDS export. metadata carries per-model side-channel info
(weights provenance, iteration count, ...).
Source code in src/openlithohub/models/base.py
LithographyModel
¶
Bases: ABC
Abstract interface for lithography optimization models.
Any model (heuristic OPC, U-Net, diffusion-based ILT, curvyILT) can join the evaluation pipeline by implementing predict().
Subclasses MUST set the class-level NAME attribute. The registry
reads it without instantiating the class, so it cannot be set in
__init__.
Source code in src/openlithohub/models/base.py
RECEPTIVE_FIELD_PX = 0
class-attribute
¶
Half-width of the model's receptive field in pixels.
Tile inference adds at least this many pixels of halo on every side so the model sees real layout context, not zero-padding, at tile boundaries. Models with a static convolutional receptive field should set this on the subclass; iterative optimizers that consume their entire input (e.g. level-set ILT) can leave it 0 — their halo comes from the optical interaction radius of the process node.
name
property
¶
Human-readable model name for leaderboard display.
supports_curvilinear
property
¶
Whether this model produces curvilinear (non-Manhattan) output.
receptive_field_px
property
¶
Per-instance accessor for the class-level RECEPTIVE_FIELD_PX.
predict(design, **kwargs)
abstractmethod
¶
Run model inference on a design layout tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
design
|
Tensor
|
Input design tensor of shape (H, W) or (B, C, H, W). |
required |
**kwargs
|
Any
|
Model-specific parameters (process node, dose, etc.) |
{}
|
Returns:
| Type | Description |
|---|---|
PredictionResult
|
PredictionResult with the optimized mask and optional contour. |
Source code in src/openlithohub/models/base.py
setup()
¶
teardown()
¶
to_torch_module()
¶
Return a single nn.Module that maps an input mask/design tensor
to an output mask tensor, suitable for ONNX / TorchScript export.
Default raises NotImplementedError. Override this on models that
wrap a static nn.Module (e.g. Neural-ILT). Iterative optimizers
like Level-Set ILT do not have a single forward graph and cannot be
exported — those should keep the default.
The returned module must be in eval() mode and accept tensors
of shape (B, 1, H, W) in [0, 1], returning the same shape.
Source code in src/openlithohub/models/base.py
openlithohub.models.registry
¶
Model registry — discover and instantiate lithography models.
ModelRegistry
¶
Registry for discovering and instantiating lithography models.
Source code in src/openlithohub/models/registry.py
register(model_cls)
¶
Register a model class. Can be used as a decorator.
The model class must define NAME directly on itself (not inherit
it). The registry reads vars(model_cls) so that a default NAME
on a future base class cannot cause every concrete subclass that
forgets to override it to silently collide on the same key.
Re-registering an identical class (same module + qualname) is a
no-op — that happens when register_builtin_models is called
multiple times. A different class with the same NAME emits a
UserWarning and overrides; users who shadow a built-in by
accident will see the warning instead of silent replacement.
Source code in src/openlithohub/models/registry.py
get(name, **kwargs)
¶
Instantiate a registered model by name.
Kwargs that the target model's __init__ does not accept are
silently dropped, so optional CLI flags like --pretrained work
across the whole registry without each call site needing to know
which models support which options. Real bugs in the model's
__init__ (mistyped args, missing required positionals) still
propagate as TypeError.
Source code in src/openlithohub/models/registry.py
supports_kwargs(name, kwargs)
¶
Return a per-key flag indicating whether the named model accepts each kwarg.
Source code in src/openlithohub/models/registry.py
register_builtin_models()
¶
Side-effect import the in-tree models so the registry is populated.
Idempotent — Python caches modules in sys.modules so repeated calls
are cheap. Both the optimize CLI and the multiprocessing workers call
this so workers populate their registry the same way the parent does.
Source code in src/openlithohub/models/registry.py
openlithohub.models.levelset_ilt
¶
LevelSet-ILT: Iterative mask optimization via gradient descent.
The level-set / continuous-mask formulation of Inverse Lithography Technology dates to Pang, Liu & Abrams, Inverse lithography technology principles in practice: unintuitive patterns (Proc. SPIE 5992, 2005) and Poonawala & Milanfar, Mask design for optical microlithography — an inverse imaging problem (IEEE TIP 16(3), 2007). This implementation follows the SimpleILT-style L2 + total-variation formulation surveyed in [Yang2023_LithoBench, §3.3, p.5] (open-access substitute for the paywalled Granik / Pang journal write-ups).
Confidence B — algorithmic intent is matched against the
LithoBench narrative; specific hyperparameters here (lr,
sigma_px, tv_weight) are this project's defaults, not literal
paper values.
LevelSetILTModel
¶
Bases: LithographyModel
Inverse Lithography Technology via level-set gradient descent.
Optimizes a continuous mask representation to minimize the difference between the simulated resist image and the target design pattern. Supports two forward models:
gaussian(default): a single Gaussian PSF — fast, used in tests.hopkins: SOCS-truncated partial-coherence Hopkins imaging — physically faithful, suitable for end-to-end AI-OPC research.
When helmholtz_radius > 0, a differentiable Helmholtz PDE filter
is applied to the continuous mask before the aerial image simulation,
suppressing sub-resolution features and enforcing a minimum
manufacturable feature size (~2*radius).
Source code in src/openlithohub/models/levelset_ilt.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | |
predict(design, **kwargs)
¶
Optimize a mask to reproduce the target design under lithography simulation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
design
|
Tensor
|
Target design pattern (H, W), binary. |
required |
**kwargs
|
Any
|
Optional overrides — iterations, lr, sigma_px, tv_weight, forward_model, hopkins_params, helmholtz_radius, device, dtype, compile_forward, process_window, pw_corners, checkpoint_dir, save_freq, resume_from.
|
{}
|
Source code in src/openlithohub/models/levelset_ilt.py
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | |
openlithohub.models.neural_ilt
¶
Neural-ILT: U-Net based mask prediction model.
NeuralILTModel
¶
Bases: LithographyModel
U-Net mask predictor (Neural-ILT-style — see audit caveats below).
Predicts an optimised mask directly from the design layout in a single forward pass. Much faster than iterative methods at inference time, but requires pretrained weights for good results.
What this adapter is not. This is not a paper-faithful
re-implementation of Jiang2020_NeuralILT (ICCAD'20). It is a
U-Net mask predictor whose architecture is inspired by that paper.
The headline contribution of Jiang2020 — the differentiable ILT
correction layer that lets the L2/PVB loss flow back through a
forward simulator at training time — is not implemented here.
Eval-time forward simulation lives in the leaderboard scoring
pipeline (see benchmark/metrics/l2_error.py, which already
accepts simulator=); training-time loss-through-simulator is a
separate piece of code that is not in this adapter and has no
open issue or RFC pinned to it.
Lineage references (cite for architecture inspiration, not for
expected metric):
- Jiang2020_NeuralILT (ICCAD'20, paywalled) — original paper.
- Yang2023_LithoBench §4.3 (NeurIPS 2023, open access) —
restates the architecture and training schedule.
Architecture divergences vs. Jiang2020: - Backbone: 3-level U-Net (3 down / 3 up), paper uses 4 levels. - Channel widths: 32→64→128→256 (paper: 64→128→256→512). - Loss / training: not part of this adapter.
See docs/audits/neural-ilt-architecture.md for the full audit,
the 2026-05-23 decision record (option (b): downgrade naming
instead of implementing the correction layer), and re-audit
triggers.
Source code in src/openlithohub/models/neural_ilt.py
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | |
to_torch_module()
¶
Return the U-Net wrapped so the export forward emits a sigmoid mask
in [0, 1] directly — what a downstream production pipeline expects.
Source code in src/openlithohub/models/neural_ilt.py
openlithohub.models.rule_based_opc
¶
Rule-based geometric OPC baseline.
Classic non-AI optical proximity correction by morphological edge biasing. Serves as the geometric reference point that any learning-based method must beat: shows what plain dilation buys you and what it leaves on the table (line-end pull-back, corner rounding, MRC violations on tight pitch).
This implementation deliberately stays in the "no learning, no simulation" regime. It augments uniform dilation with three context-aware bias modes that are still pure geometry — directional hammerheads at line ends, serifs at concave inner corners, and an iso/dense bias split — plus an MRC self-check that reports (and optionally retreats from) violations caused by the bias itself. Everything runs on torch.nn.functional pooling; no scipy, no distance transforms.
Future work (intentionally out of scope here, to keep this a "minimal geometric baseline"): - SRAF placement (sub-resolution assist features) — needs distance transforms and per-process-node assist rules. - Segment-based fragmentation — break edges into segments and move each independently, the standard production OPC primitive. - Iterative bias loop (model-based OPC) — dilate → simulate → measure EPE → adjust bias. Crossing this line stops being "rule-based" by definition. - Per-layer rule tables — different metals / poly / via layers carry different bias tables in real flows.
RuleBasedOPCModel
¶
Bases: LithographyModel
Geometric edge-bias OPC with directional hammerheads and inner-corner serifs.
Default behaviour is conservative: uniform 1px dilation plus directional line-end extension. Inner-corner serifs, iso/dense split, and MRC retreat are all opt-in via constructor or per-call kwargs.
Source code in src/openlithohub/models/rule_based_opc.py
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | |
openlithohub.models.hub
¶
Model hub for downloading and caching pretrained weights.
Remote downloads (direct HTTPS URLs) require a known SHA256 — torch.load
on attacker-controlled bytes is a known RCE vector even with
weights_only=True. The HuggingFace path relies on the Hub's own
content-addressed verification.
ChecksumMismatchError
¶
ModelHub
¶
Manages download and caching of pretrained model weights.
Supports HuggingFace Hub (if installed) and direct URL downloads. Direct URL downloads MUST come with a SHA256 checksum.
Cache-key contract¶
Three identifier shapes flow through this class. Knowing which shape goes where prevents the kind of round-trip bug fixed in the May 2026 review:
owner/repo— the public form a caller passes to :meth:download_weightsfor a HuggingFace-style model.owner--repo— the on-disk form, with the path separator rewritten to a double-dash so the segment is filesystem-safe. :meth:list_cacheddecodes this back toowner/repo.url--<hex>— the on-disk form for direct-URL downloads, where<hex>is the first 32 hex chars ofsha256(url.encode()). :meth:list_cachedreturns this verbatim (there is no publicowner/repo-shaped name to decode back to), and :meth:clear_cacheaccepts both the original URL and the verbatimurl--<hex>segment so thelist_cached → clear_cachepipeline composes cleanly.
Every caller-supplied identifier passes through
_safe_cache_segment (or the URL hash) before it touches the
filesystem; .., embedded slashes, NUL bytes, and absolute
paths are rejected. URL-keyed segments accept only hex suffixes.
Source code in src/openlithohub/models/hub.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | |
download_weights(model_id, filename='model.pt', revision=_DEFAULT_REVISION, sha256=None)
¶
Download model weights, returning the cached file path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_id
|
str
|
A HuggingFace repo ID ( |
required |
filename
|
str
|
File name within the repo (HF Hub only). |
'model.pt'
|
revision
|
str
|
Git revision (HF Hub only). Pinning to a commit hash
(40-hex) makes the download exactly reproducible — the
default |
_DEFAULT_REVISION
|
sha256
|
str | None
|
Hex digest of the expected file contents. Verified
on both paths — direct HTTPS downloads and HF Hub
downloads. Issue #20: previously the HF Hub branch
silently ignored this argument, so a malicious or
accidentally-mutated repo at the configured revision
would have produced bytes whose hash did not match what
the caller pinned. |
None
|
Source code in src/openlithohub/models/hub.py
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |
list_cached()
¶
List model IDs that have cached weights.
HF-Hub-style entries are decoded from the on-disk owner--repo form
back to owner/repo. URL-keyed entries (stored under
url--<sha256>) are returned verbatim so a caller can hand the
result straight back to :meth:clear_cache without re-keying.
Source code in src/openlithohub/models/hub.py
clear_cache(model_id=None)
¶
Remove cached weights for a model (or all if model_id is None).
model_id is routed through the same per-segment validator used by
download_weights so a caller-supplied .. cannot escape the
cache directory and rmtree something it shouldn't. URL-keyed entries
(cached under the url--<sha256> segment that download_weights
creates) are also accepted.
Source code in src/openlithohub/models/hub.py
get_checksum(path)
¶
Compute SHA256 checksum of a file.
openlithohub.models.examples.dummy_model
¶
Dummy identity model for testing the evaluation pipeline.
DummyModel
¶
Bases: LithographyModel
Trivial model that returns the input design as the mask (identity).
Source code in src/openlithohub/models/examples/dummy_model.py
FailingDummyModel
¶
Bases: LithographyModel
Dummy model whose predict always raises.
Exists so the multi-GPU tile pipeline can exercise worker error propagation across processes — pickling a closure that raises does not survive the spawn boundary, but a registered model name does.
Source code in src/openlithohub/models/examples/dummy_model.py
Differentiable forward models¶
openlithohub._utils.forward_model
¶
Simplified aerial image forward model using Gaussian PSF convolution.
Padding contract¶
All convolutions in this module MUST use circular (periodic) padding, not
zero-padding. This is not stylistic — the Hopkins source-mask formulation
treats the mask as a tile in a periodic illumination, and zero-padding the
input introduces spurious dim-aerial fringes near the frame edge that
silently degrade EPE / PV-band metrics on layouts with features close to
the boundary. If you add a new conv-based simulator here, route it through
_circular_pad_clamped (or an equivalent mode="circular" call) — do
not switch to F.conv2d's default zero-pad as a "simplification".
simulate_aerial_image(mask, sigma_px, dose=1.0)
¶
Simulate aerial image via Gaussian PSF convolution.
Approximates Hopkins diffraction with a single Gaussian point spread function.
Accepts (H, W) for single-image use and (B, 1, H, W) for batched
forward passes — the output preserves the input rank.
Uses circular (periodic) padding to match the Hopkins forward model's convention. OPC treats the mask as a tile of an infinite layout, so zero-padding at the border would introduce spurious dim-aerial fringes that the Hopkins path does not have.
Source code in src/openlithohub/_utils/forward_model.py
apply_resist_threshold(aerial_image, threshold=THRESHOLD_GENERIC, *, resist_diffusion_nm=0.0, pixel_size_nm=1.0, quencher=0.0)
¶
Apply a hard resist threshold to produce a binary resist pattern.
The 0.5 default is a generic mid-intensity cutoff for ad-hoc use; the
canonical ICCAD16 / LithoBench cutoff is 0.225 (see
[Yang2023_LithoBench, §3.2, p.5] and SimulatorConfig.threshold).
Pass threshold=0.225 when reproducing benchmark numbers.
With resist_diffusion_nm=0.0 and quencher=0.0 (default) this
is constant threshold resist (CTR) without diffusion — the
sigmoid-on-aerial simplification documented in
docs/architecture.md → Resist Model Simplification. The output is
bit-identical to the legacy (aerial >= threshold).float() path.
With a positive resist_diffusion_nm the aerial image is first
blurred by a Gaussian whose sigma matches the acid diffusion length,
then quencher is subtracted, and finally the hard threshold is
applied. This models a simplified chemically-amplified resist (CAR).
Real per-node CTR parameters are foundry-confidential and cannot ship in an open-source repo; benchmark-relative comparison is unaffected, but absolute wafer prediction is not in scope.
Returns a hard 0/1 tensor — gradients do not flow back through
this function. The README's "end-to-end differentiable" claim refers
to the ILT optimizer path, which uses
:func:openlithohub._utils.resist_model.differentiable_threshold
(a temperature-controlled sigmoid). Use that helper for any
gradient-bearing forward; reserve this hard threshold for
measurement / scoring code (PVB envelopes, stochastic comparisons,
leaderboard pass/fail).
Source code in src/openlithohub/_utils/forward_model.py
openlithohub._utils.hopkins
¶
Differentiable Hopkins partial-coherence aerial image model via SOCS.
Hopkins formulation describes partial-coherent imaging through a Transmission Cross Coefficient (TCC):
I(x) = ∫∫ TCC(f1, f2) * M~(f1) * conj(M~(f2)) * exp(2πi (f1-f2) x) df1 df2
where M~ is the mask Fourier transform, J is the source intensity, P is the pupil function, and
TCC(f1, f2) = ∫ J(f) * P(f + f1) * conj(P(f + f2)) df
The Sum Of Coherent Systems (SOCS) decomposition is the eigendecomposition of TCC viewed as a Hermitian operator:
TCC = Σ_k w_k * φ_k(f1) * conj(φ_k(f2)) with w_k descending
Truncating at K kernels yields the standard fast OPC forward model:
I(x) ≈ Σ_k w_k * | (mask * φ_k)(x) |^2
This module implements both steps in pure PyTorch so the entire chain is auto-differentiable (the mask is the optimization variable in ILT).
HopkinsParams
dataclass
¶
Optical parameters for Hopkins partial-coherence imaging.
Attributes:
| Name | Type | Description |
|---|---|---|
wavelength_nm |
float
|
Exposure wavelength (193 nm = ArF, 13.5 nm = EUV). |
na |
float
|
Numerical aperture (image-side). 1.35 = ArF immersion, 0.33 = EUV NXE. |
sigma |
float
|
Partial-coherence factor for circular illumination, or outer sigma for annular/dipole/quasar. |
sigma_inner |
float
|
Inner sigma for annular/dipole/quasar (ignored for circular). |
pixel_size_nm |
float
|
Physical size of one mask pixel. |
num_kernels |
int
|
SOCS truncation order. Defaults to 24 to match the
|
illumination |
IlluminationKind
|
Source shape — circular, annular, dipole (X-direction poles), or quasar (4-pole, CQuad). |
dipole_angle_deg |
float
|
Pole-pair orientation for dipole/quasar (degrees). |
pole_opening_deg |
float
|
Half-angle of each pole wedge for dipole/quasar (degrees). 30° is a common production CQuad value. |
defocus_nm |
float
|
Defocus offset; affects the pupil phase only. |
Source code in src/openlithohub/_utils/hopkins.py
compute_socs_kernels(params, grid_size, device='cpu', dtype=torch.complex64)
¶
Compute SOCS kernels and their weights for a square grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
params
|
HopkinsParams
|
Optical parameters. |
required |
grid_size
|
int
|
Square grid edge length (pixels). |
required |
device
|
device | str
|
PyTorch device. |
'cpu'
|
dtype
|
dtype
|
Complex dtype of the returned kernels ( |
complex64
|
Returns:
| Name | Type | Description |
|---|---|---|
kernels |
Tensor
|
complex tensor of shape (K, H, W) with the requested dtype. Each kernel is in the spatial domain, ready for FFT-based convolution. |
weights |
Tensor
|
real float32 tensor of shape (K,). Sorted descending. |
The returned kernels are zero-centered (fftshift-style) with the kernel
support concentrated near the origin, which is what
simulate_aerial_image_hopkins expects.
Source code in src/openlithohub/_utils/hopkins.py
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | |
simulate_aerial_image_hopkins(mask, params=None, kernels=None, weights=None, dose=1.0, dtype=torch.float32, precomputed_kernels_f=None)
¶
Simulate aerial image via SOCS-truncated Hopkins imaging.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mask
|
Tensor
|
Real-valued mask (H, W) or (B, 1, H, W), values in [0, 1]. Differentiable: gradients flow back through the kernels. |
required |
params
|
HopkinsParams | None
|
Optical parameters. Required if |
None
|
kernels
|
Tensor | None
|
Pre-computed complex SOCS kernels (K, H, W). If provided,
|
None
|
weights
|
Tensor | None
|
Pre-computed real weights (K,). Must accompany |
None
|
dose
|
float
|
Linear dose multiplier on the resulting intensity. |
1.0
|
dtype
|
dtype
|
Real dtype of the returned aerial image ( |
float32
|
precomputed_kernels_f
|
Tensor | None
|
Optional pre-FFT'd kernels of shape
(K, H, W), complex64. When provided, the inner loop skips the
per-kernel |
None
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Real-valued aerial image with the same spatial shape as |
Source code in src/openlithohub/_utils/hopkins.py
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 | |
openlithohub._utils.resist_model
¶
Chemically-amplified resist simulation with acid diffusion.
differentiable_threshold(aerial_image, threshold=THRESHOLD_GENERIC, steepness=STEEPNESS_DEFAULT)
¶
Smooth, differentiable substitute for a hard resist threshold.
Returns sigmoid(steepness * (aerial - threshold)). As steepness
increases the output approaches a step function while remaining
differentiable everywhere — required for gradient-based ILT.
Source code in src/openlithohub/_utils/resist_model.py
simulate_resist(aerial_image, acid_diffusion_length_nm=5.0, pixel_size_nm=1.0, threshold=THRESHOLD_GENERIC, quencher_concentration=0.1)
¶
Simulate chemically-amplified resist response with acid diffusion.
Models a physically-motivated resist development process: 1. Photoacid generation proportional to aerial image intensity 2. Acid diffusion via Gaussian blur (diffusion length determines spread) 3. Quencher neutralization (constant subtraction) 4. Threshold to binary resist pattern
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
aerial_image
|
Tensor
|
Aerial image intensity (H, W), values in [0, 1]. |
required |
acid_diffusion_length_nm
|
float
|
Acid diffusion length in nanometers. |
5.0
|
pixel_size_nm
|
float
|
Physical pixel size for unit conversion. |
1.0
|
threshold
|
float
|
Development threshold applied to the post-quencher acid
field. The quencher is subtracted before thresholding, so an
aerial intensity of |
THRESHOLD_GENERIC
|
quencher_concentration
|
float
|
Base quencher level subtracted from acid. |
0.1
|
Returns:
| Type | Description |
|---|---|
Tensor
|
Binary resist pattern (H, W), 1.0 where resist remains. |
Source code in src/openlithohub/_utils/resist_model.py
simulate_resist_soft(aerial_image, acid_diffusion_length_nm=5.0, pixel_size_nm=1.0, threshold=THRESHOLD_GENERIC, quencher_concentration=0.1, steepness=STEEPNESS_DEFAULT)
¶
Differentiable resist simulation using sigmoid instead of hard threshold.
Same physics as simulate_resist but uses a smooth sigmoid for the
development step, making it suitable for gradient-based optimization.