pado.light.Light¶
- class Light(dim, pitch, wvl, field=None, device='cpu')[source]¶
Light wave with complex field wavefront.
Represent a light wave with complex field wavefront that can be manipulated through various optical operations.
- Parameters:
- __init__(dim, pitch, wvl, field=None, device='cpu')[source]¶
Create light wave instance with complex field wavefront.
- Parameters:
dim (tuple) – Field dimensions (B, Ch, R, C) for batch, channels, rows, cols
pitch (float) – Pixel pitch in meters
wvl (float or list) – Wavelength in meters. Can be single value or list for multi-wavelength
field (torch.Tensor, optional) – Initial complex field [B, Ch, R, C]
device (str) – Device for computation (‘cpu’, ‘cuda:0’, etc.)
Examples
>>> light = Light(dim=(1, 1, 1024, 1024), pitch=6.4e-6, wvl=633e-9) >>> light = Light(dim=(2, 3, 512, 512), pitch=2e-6, wvl=[450e-9, 550e-9, 650e-9])
- clone()[source]¶
Create deep copy of light instance.
- Returns:
New light instance with copied attributes
- Return type:
Examples
>>> light_copy = light.clone()
- pad(pad_width, padval=0)[source]¶
Pad light field with constant value.
- Parameters:
- Return type:
Examples
>>> light.pad((16, 16, 16, 16)) # Add 16 pixels padding on all sides
- set_real(real, c=None)[source]¶
Set real part of light wavefront.
- Parameters:
real (torch.Tensor) – Real part in rectangular representation. If c is None: Expected shape is (B,Ch,R,C) matching self.field.real.shape If c is provided: Expected shape is (B,R,C) matching self.field[:, c, …].real.shape where B=batch size, Ch=channels, R=rows, C=columns
c (int, optional) – Channel index to modify. If provided, only that specific channel will be updated.
- Return type:
Examples
>>> # Set real part for all channels (B=1, Ch=1, R=1024, C=1024) >>> real_part = torch.ones((1, 1, 1024, 1024)) # (B,Ch,R,C) >>> light.set_real(real_part) >>> >>> # Set real part for only channel 0 (B=1, R=1024, C=1024) >>> real_part_channel0 = torch.ones((1, 1024, 1024)) # (B,R,C) >>> light.set_real(real_part_channel0, c=0)
- set_imag(imag, c=None)[source]¶
Set imaginary part of light wavefront.
- Parameters:
imag (torch.Tensor) – Imaginary part in rectangular representation. If c is None: Expected shape is (B,Ch,R,C) matching self.field.imag.shape If c is provided: Expected shape is (B,R,C) matching self.field[:, c, …].imag.shape where B=batch size, Ch=channels, R=rows, C=columns
c (int, optional) – Channel index to modify. If provided, only that specific channel will be updated.
- Return type:
Examples
>>> # Set imaginary part for all channels (B=1, Ch=1, R=1024, C=1024) >>> imag_part = torch.ones((1, 1, 1024, 1024)) # (B,Ch,R,C) >>> light.set_imag(imag_part) >>> >>> # Set imaginary part for only channel 0 (B=1, R=1024, C=1024) >>> imag_part_channel0 = torch.ones((1, 1024, 1024)) # (B,R,C) >>> light.set_imag(imag_part_channel0, c=0)
- set_amplitude(amplitude, c=None)[source]¶
Set amplitude of light wavefront (keeps phase unchanged) without maintaining computation graph.
- Parameters:
amplitude (torch.Tensor) – Amplitude in polar representation.
c (int, optional) – Channel index to modify.
- Return type:
- set_phase(phase, c=None)[source]¶
Set phase of light wavefront (keeps amplitude unchanged).
- Parameters:
phase (torch.Tensor) – Phase in polar representation (in radians). If c is None: Expected shape is (B,Ch,R,C) matching self.field.shape If c is provided: Expected shape is (B,R,C) matching self.field[:, c, …].shape where B=batch size, Ch=channels, R=rows, C=columns
c (int, optional) – Channel index to modify. If provided, only that specific channel will be updated.
- Return type:
Examples
>>> # Set phase for all channels (B=1, Ch=1, R=1024, C=1024) >>> phase = torch.zeros((1, 1, 1024, 1024)) # (B,Ch,R,C) >>> light.set_phase(phase) >>> >>> # Set phase for only channel 0 (B=1, R=1024, C=1024) >>> phase_channel0 = torch.zeros((1, 1024, 1024)) # (B,R,C) >>> light.set_phase(phase_channel0, c=0)
- set_field(field, c=None)[source]¶
Set complex field of light wavefront.
- Parameters:
field (torch.Tensor) – Complex field tensor. If c is None: Expected shape is (B,Ch,R,C) matching self.field.shape If c is provided: Expected shape is (B,R,C) matching self.field[:, c, …].shape where B=batch size, Ch=channels, R=rows, C=columns
c (int, optional) – Channel index to modify. If provided, only that specific channel will be updated.
- Return type:
Examples
>>> # Set field for all channels (B=1, Ch=1, R=1024, C=1024) >>> field = torch.ones((1, 1, 1024, 1024), dtype=torch.complex64) # (B,Ch,R,C) >>> light.set_field(field) >>> >>> # Set field for only channel 0 (B=1, R=1024, C=1024) >>> field_channel0 = torch.ones((1, 1024, 1024), dtype=torch.complex64) # (B,R,C) >>> light.set_field(field_channel0, c=0)
- set_pitch(pitch)[source]¶
Set pixel pitch of light field.
Examples
>>> light.set_pitch(6.4e-6) # Set 6.4μm pitch
- get_channel()[source]¶
Return number of channels in light field.
- Returns:
Number of channels
- Return type:
Examples
>>> channels = light.get_channel()
- get_amplitude(c=None)[source]¶
Get amplitude of light wavefront.
- Parameters:
c (int, optional) – Channel index to retrieve. If provided, only that specific channel will be returned.
- Returns:
- Amplitude in polar representation.
If c is None: Shape is (B,Ch,R,C) If c is provided: Shape is (B,R,C) where B=batch size, Ch=channels, R=rows, C=columns
- Return type:
Examples
>>> # Get amplitude for all channels (B=1, Ch=1, R=1024, C=1024) >>> amp = light.get_amplitude() # Shape: (1, 1, 1024, 1024) >>> >>> # Get amplitude for only channel 0 (B=1, R=1024, C=1024) >>> amp_channel0 = light.get_amplitude(c=0) # Shape: (1, 1024, 1024)
- get_phase(c=None)[source]¶
Get phase of light wavefront.
- Parameters:
c (int, optional) – Channel index to retrieve. If provided, only that specific channel will be returned.
- Returns:
- Phase in polar representation (in radians).
If c is None: Shape is (B,Ch,R,C) If c is provided: Shape is (B,R,C) where B=batch size, Ch=channels, R=rows, C=columns
- Return type:
Examples
>>> # Get phase for all channels (B=1, Ch=1, R=1024, C=1024) >>> phase = light.get_phase() # Shape: (1, 1, 1024, 1024) >>> >>> # Get phase for only channel 0 (B=1, R=1024, C=1024) >>> phase_channel0 = light.get_phase(c=0) # Shape: (1, 1024, 1024)
- get_intensity(c=None)[source]¶
Get intensity (amplitude squared) of light wavefront.
- Parameters:
c (int, optional) – Channel index to retrieve. If provided, only that specific channel will be returned.
- Returns:
- Intensity values.
If c is None: Shape is (B,Ch,R,C) If c is provided: Shape is (B,R,C) where B=batch size, Ch=channels, R=rows, C=columns
- Return type:
Examples
>>> # Get intensity for all channels (B=1, Ch=1, R=1024, C=1024) >>> intensity = light.get_intensity() # Shape: (1, 1, 1024, 1024) >>> >>> # Get intensity for only channel 0 (B=1, R=1024, C=1024) >>> intensity_channel0 = light.get_intensity(c=0) # Shape: (1, 1024, 1024)
- get_field(c=None)[source]¶
Get complex field of light wavefront.
- Parameters:
c (int, optional) – Channel index to retrieve. If provided, only that specific channel will be returned.
- Returns:
- Complex field tensor.
If c is None: Shape is (B,Ch,R,C) If c is provided: Shape is (B,R,C) where B=batch size, Ch=channels, R=rows, C=columns
- Return type:
Examples
>>> # Get field for all channels (B=1, Ch=1, R=1024, C=1024) >>> field = light.get_field() # Shape: (1, 1, 1024, 1024), dtype=torch.complex64 >>> >>> # Get field for only channel 0 (B=1, R=1024, C=1024) >>> field_channel0 = light.get_field(c=0) # Shape: (1, 1024, 1024), dtype=torch.complex64
- get_device()[source]¶
Return device of light field.
- Returns:
Device name (‘cpu’, ‘cuda:0’, etc.)
- Return type:
Examples
>>> device = light.get_device()
- get_bandwidth()[source]¶
Return spatial bandwidth of light wavefront.
- Returns:
Spatial height and width of wavefront in meters
- Return type:
Examples
>>> height, width = light.get_bandwidth()
- get_ideal_angle_limit()[source]¶
Return ideal angle limit of light wavefront based on optical axis.
Calculate the maximum diffraction angle supported by the current sampling, based on the Nyquist sampling criterion: sin(θ_max) = λ/(2·pitch). Use the shortest wavelength for multi-wavelength cases.
- Returns:
Ideal angle limit in degrees
- Return type:
Examples
>>> angle_limit = light.get_ideal_angle_limit()
- magnify(scale_factor, interp_mode='nearest', c=None)[source]¶
Change wavefront resolution without changing pixel pitch.
- Parameters:
- Return type:
Examples
>>> light.magnify(2.0) # Double resolution >>> light.magnify(0.5, interp_mode='bilinear') # Half resolution
- resize(target_pitch, interp_mode='nearest')[source]¶
Resize wavefront by changing pixel pitch.
- Parameters:
- Return type:
Examples
>>> light.resize(4e-6) # Change pitch to 4μm
- set_spherical_light(z, dx=0.0, dy=0.0)[source]¶
Set spherical wavefront from point source.
- Parameters:
- Return type:
Examples
>>> light.set_spherical_light(z=0.1) # Source at 10cm >>> light.set_spherical_light(z=0.05, dx=1e-3) # Offset source
- set_plane_light(theta=0)[source]¶
Set plane wave with unit amplitude.
Examples
>>> light.set_plane_light(theta=15) # 15° incident angle
- set_amplitude_ones()[source]¶
Set amplitude to ones. :rtype:
None
Examples
>>> light.set_amplitude_ones()
- Return type:
None
- set_amplitude_zeros()[source]¶
Set amplitude to zeros. :rtype:
None
Examples
>>> light.set_amplitude_zeros()
- Return type:
None
- set_phase_zeros()[source]¶
Set phase to zeros. :rtype:
None
Examples
>>> light.set_phase_zeros()
- Return type:
None
- set_phase_random(std=1.5707963267948966, distribution='gaussian', c=None)[source]¶
Set random phase with specified distribution.
- Parameters:
std (float, optional) – Standard deviation for phase randomness. - For gaussian: Standard deviation in radians - For uniform: Half-width of uniform distribution in radians - For von_mises: Inverse of concentration parameter (1/κ) Defaults to π/2.
distribution (str, optional) – Type of random distribution. Must be one of [‘gaussian’, ‘uniform’, ‘von_mises’]. Defaults to ‘gaussian’.
c (int, optional) – Channel index to modify. If None, all channels are modified.
- Raises:
ValueError – If distribution is not one of the supported types.
- Return type:
Examples
>>> light.set_phase_random() # Default gaussian with π/2 std for all channels >>> light.set_phase_random(std=np.pi/4) # Reduced randomness >>> light.set_phase_random(distribution='uniform') # Uniform distribution >>> light.set_phase_random(std=0.25, distribution='von_mises') # von Mises with κ=4 >>> light.set_phase_random(c=0) # Only modify first channel
- save(fn)[source]¶
Save light field to file.
Examples
>>> light.save("field.pt") # Save as PyTorch format >>> light.save("field.npy") # Save as NumPy format >>> light.save("field.mat") # Save as MATLAB format
- adjust_amplitude_to_other_light(other_light)[source]¶
Scale amplitude to match average of another light field.
Examples
>>> target = Light(dim=(1,1,1024,1024), pitch=6.4e-6, wvl=633e-9) >>> light.adjust_amplitude_to_other_light(target)
- load_image(image_path, random_phase=False, std=3.141592653589793, distribution='uniform', batch_idx=None)[source]¶
Load image as amplitude pattern with optional random phase.
- Parameters:
image_path (str) – Path to image file.
random_phase (bool, optional) – Whether to apply random phase. Defaults to False.
std (float, optional) – Standard deviation for phase randomness. For gaussian: Standard deviation in radians For uniform: Half-width of uniform distribution in radians For von_mises: Inverse of concentration parameter (1/κ) Defaults to π.
distribution (str, optional) – Type of random distribution. Must be one of [‘gaussian’, ‘uniform’, ‘von_mises’]. Defaults to ‘uniform’.
batch_idx (int, optional) – Specific batch index to load the image into. If None, loads the image into all batches. Defaults to None.
- Return type:
Examples
>>> light.load_image("target.png") # No random phase, all batches >>> light.load_image("target.png", random_phase=True) # Default uniform, all batches >>> light.load_image("target.png", random_phase=True, std=np.pi/4) >>> light.load_image("target.png", random_phase=True, distribution='gaussian') >>> light.load_image("target.png", batch_idx=0) # Load only into first batch
- visualize(b=0, c=None, uniform_scale=False, vmin=None, vmax=None, fix_noise=True, amp_threshold=1e-05)[source]¶
Visualize amplitude, phase, and intensity of light field with improved noise handling.
- Parameters:
b (int) – Batch index
c (int, optional) – Channel index
uniform_scale (bool) – Use same scale for all channels
vmin (float, optional) – Intensity plot range
vmax (float, optional) – Intensity plot range
fix_noise (bool) – Whether to fix numerical noise in amplitude visualization
amp_threshold (float) – Threshold for detecting uniform amplitude with noise
- Return type:
Examples
>>> light.visualize() # Show all channels >>> light.visualize(c=0) # Show only first channel >>> light.visualize(uniform_scale=True) # Use uniform scaling >>> light.visualize(fix_noise=False) # Don't fix numerical noise >>> light.visualize(b=1) # Visualize the second batch
- visualize_image(b=0)[source]¶
Visualize amplitude, phase, and intensity as RGB images.
Examples
>>> light.visualize_image() >>> light.visualize_image(b=1) # Visualize the second batch