Camera Simulation
Overview
The camera simulation component in daolite (Durham Adaptive Optics Latency Inspection and Timing Estimator) models the behavior and timing of wavefront sensor cameras in adaptive optics systems. daolite provides detailed timing models for various camera readout patterns, frame rates, and data transfer mechanisms to accurately estimate the initial latency component in AO systems.
Key Camera Features
Detector Readout: Models various readout patterns and speeds
Frame Transfer: Simulates parallel and serial readout modes
Packetization: Models camera data packetization for streaming
Interface Timing: Simulates various camera interfaces (Camera Link, GigE Vision, etc.)
Region of Interest (ROI): Models the effect of ROI selection on readout time
Binning: Simulates on-chip binning effects on readout speed
Triggered Operation: Models triggered and free-running camera modes
Using Camera Components
Adding a camera simulator to your AO pipeline is straightforward:
from daolite import Pipeline, PipelineComponent, ComponentType
from daolite.simulation.camera import PCOCamLink
from daolite.compute import hardware
# Create a pipeline
pipeline = Pipeline()
# Define a CPU resource for camera simulation
cpu = hardware.amd_epyc_7763()
# Add camera component
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="WFS Camera",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 1024*1024, # 1 megapixel camera
"group": 50, # Read out in 50 groups
"readout": 500.0 # 500 µs readout time
}
))
Camera Configuration
Camera components accept various parameters to customize their behavior:
PCOCamLink Parameters:
params={
# Required parameters
"n_pixels": 1024*1024, # Total number of pixels
# Optional parameters
"group": 50, # Number of readout groups (default: 50)
"readout": 500.0, # Readout time in microseconds (default: 500)
"debug": False # Enable debug output
}
GigeVisionCamera Parameters:
params={
"n_pixels": 1024*1024, # Total number of pixels
"n_groups": 10, # Number of packet groups (default: 10)
"link_speed": 1e9, # 1 Gbps link speed (default)
"readout_time": 1000.0, # Readout time in microseconds
"debug": False
}
RollingShutterCamera Parameters:
params={
"n_pixels": 1024*1024, # Total number of pixels
"n_rows": 1024, # Number of rows
"row_readout_time": 10.0, # Time per row in microseconds
"debug": False
}
Available Camera Models
daolite provides timing models for the following camera readout methods:
Global Shutter Readout
Models cameras where all pixels are exposed simultaneously and then read out:
from daolite.simulation.camera import PCOCamLink
# Use as a standalone function
timing = PCOCamLink(
compute=cpu,
n_pixels=1024*1024,
bit_depth=12,
frame_rate=1000,
debug=True
)
# Or in a pipeline component
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Global Shutter WFS",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"frame_rate": 1000
}
))
Rolling Shutter Readout
Models cameras where rows are exposed and read out sequentially:
from daolite.simulation.camera import RollingShutterCamera
# Add as a pipeline component
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Rolling Shutter WFS",
compute=cpu,
function=RollingShutterCamera,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"frame_rate": 1000,
"row_readout_time": 10 # μs per row
}
))
Frame Transfer Readout
Models frame transfer CCDs where the image area is rapidly shifted to a storage area:
from daolite.simulation.camera import frame_transfer_readout
# Add as a pipeline component
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Frame Transfer WFS",
compute=cpu,
function=frame_transfer_readout,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"frame_rate": 1000,
"transfer_time": 50, # μs for frame transfer
"parallel_transfer_lines": 1 # Lines transferred in parallel
}
))
Packetized Readout
Models cameras that stream data in packets for processing before the full frame is read:
from daolite.simulation.camera import packetized_readout
# Add as a pipeline component
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Packetized WFS",
compute=cpu,
function=packetized_readout,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"frame_rate": 1000,
"packet_size": 1024, # Bytes per packet
"group_size": 64, # Packets per group
"protocol_overhead": 36 # Bytes of protocol overhead per packet
}
))
Region of Interest Readout
Models cameras reading out only a portion of the sensor:
from daolite.simulation.camera import roi_readout
# Add as a pipeline component
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="ROI WFS",
compute=cpu,
function=roi_readout,
params={
"n_pixels": 1024*1024, # Full sensor size
"bit_depth": 12,
"frame_rate": 1000,
"roi_width": 512, # ROI width
"roi_height": 512, # ROI height
"roi_x": 256, # ROI top-left X
"roi_y": 256 # ROI top-left Y
}
))
Flexible Camera Model
For convenience, daolite provides a combined camera function that can simulate various configurations:
from daolite.simulation.camera import PCOCamLink, GigeVisionCamera, RollingShutterCamera
# Add flexible camera to the pipeline
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Flexible WFS Camera",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 1024*1024,
"readout_mode": "global", # "global", "rolling", "frame-transfer"
"bit_depth": 12,
"frame_rate": 1000,
"packetization": True,
"group_size": 64,
"interface": "cameralink",
"use_roi": True,
"roi_width": 512,
"roi_height": 512
}
))
Performance Considerations
The computational cost and latency of camera operations depends on several factors:
Pixel Count: Total number of pixels to read out
Readout Mode: Global, rolling, or frame-transfer readout patterns
Frame Rate: Higher frame rates reduce exposure and readout times
Interface Bandwidth: Maximum data transfer rate
Packetization: Overhead from packet headers and protocol
ROI Size: Smaller regions of interest reduce readout time
Binning: On-chip binning can reduce readout time
Modeling ROI and Binning Effects
daolite accurately models how ROI and binning settings affect frame rate and latency:
# Configure camera with ROI and binning
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="ROI and Binning",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 2048*2048, # Full frame
"readout_mode": "global",
"bit_depth": 12,
"frame_rate": 500, # Base frame rate
"use_roi": True,
"roi_width": 512,
"roi_height": 512,
"binning": 2, # 2x2 binning
"calculated_frame_rate": True # Calculate max frame rate based on settings
}
))
Interface Timing Models
daolite models various camera interfaces and their timing characteristics:
# Camera Link interface timing
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="CameraLink Full",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"interface": "cameralink_full",
"bandwidth": 6.8e9, # 6.8 Gbps for CameraLink Full
"protocol_overhead": 0.05 # 5% overhead
}
))
# GigE Vision interface timing
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="GigE Vision WFS",
compute=cpu,
function=GigeVisionCamera,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"frame_rate": 1000,
"interface": "gige"
}
))
# CoaXPress interface timing
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="CoaXPress",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 1024*1024,
"bit_depth": 12,
"interface": "coaxpress",
"bandwidth": 12.5e9, # 12.5 Gbps (CXP-12)
"protocol_overhead": 0.02 # 2% overhead
}
))
Customizing Camera Models
daolite allows you to create custom camera models with your own timing characteristics:
def custom_camera_model(compute, n_pixels, frame_rate=1000, extra_param=1.0, debug=False):
"""
Custom camera timing model.
Args:
compute: Compute resource
n_pixels: Number of pixels
frame_rate: Frame rate in Hz
extra_param: Custom scaling parameter
debug: Enable debug output
Returns:
Numpy array with timing information
"""
# Calculate base exposure and readout times
frame_period = 1e6 / frame_rate # μs
exposure_ratio = 0.8 # 80% of frame period for exposure
exposure_time = frame_period * exposure_ratio
readout_time = frame_period * (1 - exposure_ratio)
# Calculate data transfer time
bits_per_pixel = 12
bytes_per_frame = n_pixels * bits_per_pixel / 8
interface_bandwidth = 6.8e9 / 8 # CameraLink Full in bytes/sec
transfer_time = bytes_per_frame / interface_bandwidth * 1e6 # μs
# Apply custom scaling
readout_time *= extra_param
transfer_time *= extra_param
# Total frame time (can't exceed frame period)
total_frame_time = min(frame_period, max(readout_time, transfer_time))
if debug:
print(f"Frame period: {frame_period:.2f} μs")
print(f"Exposure time: {exposure_time:.2f} μs")
print(f"Readout time: {readout_time:.2f} μs")
print(f"Transfer time: {transfer_time:.2f} μs")
print(f"Total frame time: {total_frame_time:.2f} μs")
# Create timing array for simulation
# We create one timing entry for each packet group
n_groups = 10 # Example: divide into 10 groups
timing = np.zeros([n_groups, 2])
# Set start and end times for each group
for i in range(n_groups):
# Start time is proportional to group index
timing[i, 0] = i * (total_frame_time / n_groups)
# End time includes the group processing time
timing[i, 1] = (i + 1) * (total_frame_time / n_groups)
return timing
# Use custom camera model in a pipeline
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CONTROLLER,
name="Custom Camera",
compute=cpu,
function=custom_camera_model,
params={
"n_pixels": 1024*1024,
"frame_rate": 1000,
"extra_param": 1.2,
"debug": True
}
))
Real-World Applications
Example: High-Speed WFS Camera
Camera configuration for a high-speed wavefront sensor:
# High-speed WFS camera for ExAO
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="ExAO WFS Camera",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 240*240, # Small format sensor
"readout_mode": "frame-transfer",
"bit_depth": 10, # Lower bit depth for speed
"frame_rate": 3000, # 3 kHz frame rate
"interface": "cameralink_full",
"packetization": True,
"group_size": 32,
"use_roi": True,
"roi_width": 160,
"roi_height": 160
}
))
Example: Large-Format Solar WFS
Camera configuration for a large-format solar wavefront sensor:
# Large-format solar WFS
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Solar WFS Camera",
compute=cpu,
function=PCOCamLink,
params={
"n_pixels": 2048*2048, # Large format sensor
"readout_mode": "global",
"bit_depth": 12,
"frame_rate": 1500, # 1.5 kHz frame rate
"interface": "coaxpress",
"bandwidth": 25e9, # Dual CXP-12 (25 Gbps)
"packetization": True,
"group_size": 128
}
))
Example: Multi-ROI Readout
Camera configuration for a wavefront sensor using multiple regions of interest:
# Multi-ROI readout
pipeline.add_component(PipelineComponent(
component_type=ComponentType.CAMERA,
name="Multi-ROI WFS",
compute=cpu,
function=multi_roi_readout,
params={
"n_pixels": 1024*1024, # Full sensor
"bit_depth": 12,
"frame_rate": 2000, # 2 kHz frame rate
"rois": [
{"x": 100, "y": 100, "width": 128, "height": 128},
{"x": 400, "y": 400, "width": 128, "height": 128},
{"x": 700, "y": 700, "width": 128, "height": 128}
],
"interface": "cameralink_medium"
}
))
Troubleshooting
Common issues and solutions:
Bandwidth Limitations: - Reduce bit depth or frame rate - Use ROI to read out smaller regions - Apply on-chip binning - Use a faster interface (CoaXPress instead of GigE Vision)
Exposure/Frame Rate Tradeoffs: - Use frame transfer mode to minimize dead time - Consider specialized fast readout modes - Use partial readout techniques
Latency Issues: - Enable packetization for earlier processing of partial frames - Optimize packet and group sizes - Use ROIs targeted to specific areas of interest - Consider triggered vs. free-running mode based on synchronization needs
API Reference
For complete API details, see the Camera API Reference section.
See also
Performance Considerations - For detailed information on camera timing
Real-World Applications - For practical camera configuration examples
Pipeline Architecture - Integration of cameras into the complete AO pipeline