DAQ: removed samcam script as it duplicated area_detector

This commit is contained in:
2026-01-29 16:46:54 +01:00
parent 871384d45d
commit f9970a66cb
-163
View File
@@ -1,163 +0,0 @@
from epics import PV
from aare.common.beamline import MXBeamline
class SamCam:
def __init__(self, bl: MXBeamline):
BEAMLINE = bl.value.upper()
sam_cam_pv_name = f"{BEAMLINE}-SAMCAM"
self.cam_exp = PV(f"{sam_cam_pv_name}:cam1:AcquireTime")
self.cam_gain = PV(f"{sam_cam_pv_name}:cam1:Gain")
self.cam_mean = PV(f"{sam_cam_pv_name}:Stats1:MeanValue_RBV")
def auto_exposure(self,
target_mean=128,
tolerance=5,
max_iterations=50,
timeout=30.0):
"""
Auto-expose a camera by adaptively adjusting exposure and gain.
Args:
cam_exp_pv: PV for exposure time (0 to 0.2s)
cam_gain_pv: PV for gain (36 to 512)
cam_mean_pv: PV for image mean value
target_mean: Target mean pixel value (default 128)
tolerance: Acceptable range ±tolerance (default ±5)
max_iterations: Maximum iterations before giving up
timeout: Total timeout in seconds
Returns:
dict with status, final_mean, iterations, exposure, gain
Raises:
TimeoutError if target not reached within timeout
ValueError if PVs are invalid
"""
import time
start_time = time.time()
# Validate PVs and get initial values
try:
exp = self.cam_exp.get()
gain = self.cam_gain.get()
mean = self.cam_mean.get()
except Exception as e:
raise ValueError(f"Failed to read camera PVs: {e}")
# Hardware limits
EXP_MIN, EXP_MAX = 0.0, 0.2
GAIN_MIN, GAIN_MAX = 36, 512
# Check if we're already in target range
if abs(mean - target_mean) <= tolerance:
return {
"status": "success",
"final_mean": mean,
"iterations": 0,
"exposure": exp,
"gain": gain,
"converged": True
}
iteration = 0
while iteration < max_iterations:
# Check timeout
if time.time() - start_time > timeout:
raise TimeoutError(
f"Auto-exposure failed to converge after {timeout}s. "
f"Last mean: {mean:.1f}"
)
iteration += 1
error = mean - target_mean # Positive = too bright, negative = too dark
# Calculate adaptive step size based on error magnitude
# Larger errors → larger steps for faster convergence
error_magnitude = abs(error)
if error_magnitude > 30: # Large error: aggressive steps
exp_step = 0.01
gain_step = 40
elif error_magnitude > 15: # Medium error: moderate steps
exp_step = 0.005
gain_step = 20
else: # Small error: fine adjustments
exp_step = 0.001
gain_step = 5
# Strategy: Prefer adjusting gain first (faster response), then exposure
# This prioritizes the parameter that responds more quickly to changes
if error > tolerance: # Too bright: reduce signal
# Try to reduce gain first (has faster effect on some cameras)
if gain > GAIN_MIN:
gain = max(GAIN_MIN, gain - gain_step)
self.cam_gain.put(gain)
elif exp > EXP_MIN:
exp = max(EXP_MIN, exp - exp_step)
self.cam_exp.put(exp)
else:
# Already at minimum - can't go darker
return {
"status": "warning_min_limits",
"final_mean": mean,
"iterations": iteration,
"exposure": exp,
"gain": gain,
"converged": False,
"message": "Reached minimum exposure/gain, cannot reduce further"
}
elif error < -tolerance: # Too dark: increase signal
# Try to increase exposure first (more precise control)
if exp < EXP_MAX:
exp = min(EXP_MAX, exp + exp_step)
self.cam_exp.put(exp)
elif gain < GAIN_MAX:
gain = min(GAIN_MAX, gain + gain_step)
self.cam_gain.put(gain)
else:
# Already at maximum - can't go brighter
return {
"status": "warning_max_limits",
"final_mean": mean,
"iterations": iteration,
"exposure": exp,
"gain": gain,
"converged": False,
"message": "Reached maximum exposure/gain, cannot increase further"
}
# Small settling time for camera to stabilize
time.sleep(0.1)
mean = self.cam_mean.get()
# Check convergence
if abs(mean - target_mean) <= tolerance:
return {
"status": "success",
"final_mean": mean,
"iterations": iteration,
"exposure": exp,
"gain": gain,
"converged": True
}
# Max iterations exceeded
return {
"status": "warning_max_iterations",
"final_mean": mean,
"iterations": iteration,
"exposure": exp,
"gain": gain,
"converged": False,
"message": f"Did not converge after {max_iterations} iterations. Final mean: {mean:.1f}"
}
if __name__ == "__main__":
from aare.common.beamline import mx_beamline
beamline = mx_beamline()