Skip to Content
DocsРуководстваОптические системы

Оптические системы

SVETlANNa предоставляет LinearOpticalSetup для сборки последовательных оптических систем.

LinearOpticalSetup

Основной класс для создания последовательных оптических систем.

from svetlanna import LinearOpticalSetup from svetlanna.elements import ThinLens, FreeSpace, RoundAperture from svetlanna.units import ureg setup = LinearOpticalSetup([ RoundAperture(params, radius=2*ureg.mm), ThinLens(params, focal_length=100*ureg.mm), FreeSpace(params, distance=100*ureg.mm, method='AS'), ]) # Forward propagation wf_out = setup(wf_in) # Пошаговое распространение (возвращает промежуточные результаты) intermediates = setup.stepwise_forward(wf_in)

Все элементы в LinearOpticalSetup должны использовать один и тот же SimulationParameters. При несовпадении выводится предупреждение.

Методы

МетодОписание
forward(wf)Прямое распространение через все элементы
stepwise_forward(wf)Возвращает список промежуточных волновых фронтов

Обратное распространение

Если все элементы поддерживают reverse(), система автоматически создаёт обратную сеть:

# Обратное распространение (если поддерживается) if setup._reverse_net is not None: wf_back = setup._reverse_net(wf_out)

Альтернативы: nn.Sequential

Для простых случаев можно использовать стандартный nn.Sequential:

import torch.nn as nn system = nn.Sequential( RoundAperture(params, radius=2*ureg.mm), ThinLens(params, focal_length=100*ureg.mm), FreeSpace(params, distance=100*ureg.mm, method='AS'), ) wf_out = system(wf_in)

Классические оптические системы

Фокусирующая система

from svetlanna import LinearOpticalSetup def focusing_system(params, focal_length, aperture_radius=None): """Создаёт фокусирующую систему.""" elements = [] if aperture_radius is not None: elements.append(RoundAperture(params, radius=aperture_radius)) elements.extend([ ThinLens(params, focal_length=focal_length), FreeSpace(params, distance=focal_length, method='AS'), ]) return LinearOpticalSetup(elements) # Использование setup = focusing_system(params, focal_length=100*ureg.mm, aperture_radius=2*ureg.mm) wf_focus = setup(wf_in)

4f-система

def four_f_system(params, focal_length, filter_mask=None): """ 4f-система для оптической фильтрации. Структура: вход -> f -> L1 -> f -> [фильтр] -> f -> L2 -> f -> выход """ f = focal_length prop = lambda: FreeSpace(params, distance=f, method='AS') elements = [ prop(), ThinLens(params, focal_length=f), prop(), ] if filter_mask is not None: elements.append(Aperture(params, mask=filter_mask)) elements.extend([ prop(), ThinLens(params, focal_length=f), prop(), ]) return LinearOpticalSetup(elements)

Телескоп Кеплера

def kepler_telescope(params, f1, f2): """ Телескоп Кеплера. Увеличение M = -f2/f1 """ return LinearOpticalSetup([ ThinLens(params, focal_length=f1), FreeSpace(params, distance=f1 + f2, method='AS'), ThinLens(params, focal_length=f2), ]) telescope = kepler_telescope(params, f1=50*ureg.mm, f2=200*ureg.mm) # Увеличение: -4x

Дифракционные нейронные сети (DONN)

Многослойная D²NN

import torch import torch.nn as nn from svetlanna import LinearOpticalSetup from svetlanna.elements import DiffractiveLayer, FreeSpace class DONN(nn.Module): """Дифракционная оптическая нейронная сеть.""" def __init__(self, params, n_layers, layer_distance): super().__init__() elements = [] self.phase_masks = nn.ParameterList() for i in range(n_layers): # Обучаемая фазовая маска phase = nn.Parameter(torch.rand(512, 512) * 2 * torch.pi) self.phase_masks.append(phase) elements.append(DiffractiveLayer(params, mask=phase)) elements.append(FreeSpace(params, distance=layer_distance, method='AS')) self.optical = LinearOpticalSetup(elements) def forward(self, wf): return self.optical(wf) # Использование donn = DONN(params, n_layers=5, layer_distance=10*ureg.mm) wf_out = donn(wf_in)

С детектором для классификации

from svetlanna.detector import Detector, DetectorProcessorClf class DONNClassifier(nn.Module): def __init__(self, params, n_layers, n_classes): super().__init__() self.donn = DONN(params, n_layers=n_layers, layer_distance=10*ureg.mm) self.detector = Detector(params, func='intensity') self.processor = DetectorProcessorClf( num_classes=n_classes, simulation_parameters=params, segmentation_type='strips' ) def forward(self, wf): wf = self.donn(wf) intensity = self.detector(wf) return self.processor.batch_forward(intensity) classifier = DONNClassifier(params, n_layers=5, n_classes=10)

Промежуточные результаты

Метод stepwise_forward возвращает волновой фронт после каждого элемента:

setup = LinearOpticalSetup([ RoundAperture(params, radius=2*ureg.mm), ThinLens(params, focal_length=100*ureg.mm), FreeSpace(params, distance=100*ureg.mm, method='AS'), ]) intermediates = setup.stepwise_forward(wf_in) # intermediates[0] — после апертуры # intermediates[1] — после линзы # intermediates[2] — в фокусе import matplotlib.pyplot as plt fig, axes = plt.subplots(1, len(intermediates), figsize=(4*len(intermediates), 4)) for i, wf in enumerate(intermediates): axes[i].imshow(wf.intensity.cpu(), cmap='hot') axes[i].set_title(f'После элемента {i+1}')

Работа с GPU

# Способ 1: перенос params, затем создание системы params.to('cuda') setup = LinearOpticalSetup([...]) # Автоматически на GPU # Способ 2: перенос готовой системы setup = LinearOpticalSetup([...]) setup = setup.to('cuda') # Волновой фронт тоже должен быть на GPU wf_gpu = wf.to('cuda') wf_out = setup(wf_gpu)

Сериализация

# Сохранение torch.save(setup.state_dict(), 'optical_system.pth') # Загрузка setup = LinearOpticalSetup([...]) # Создать с той же структурой setup.load_state_dict(torch.load('optical_system.pth'))

См. также