Repository navigation
Camera plugin base independent of pylablib, with a driver contract - #11
Merged
Merged
Conversation
CameraBase (new module camera_base) holds the acquisition thread, the ROI shared with the viewer, the binning, the exposure and the FPS. It does not import pylablib, and opencv is only needed for the colour conversion. CameraBasePyLabLib becomes a thin subclass that adds the serial number setting, and the names the plugins import from camera_base_pylablib (cam_params, CameraCallback, Grab) are kept. CameraDriverBase documents the methods the plugin calls on its controller, those of the pylablib cameras, so that the driver of any other camera can be written against it. The behaviour is unchanged. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg
The binning branch of commit_settings read get_roi() as (x, width, y, height) while pylablib returns (hstart, hend, vstart, vend, hbin, vbin), so changing the binning of a ROI that does not start at 0 enlarged it. The ROI is now always passed in pylablib order, which also makes the "unchanged ROI" comparison of update_rois effective, and it is clipped to the sensor. The size of the viewer axes comes from the image shape (it ignored the binning), the ROI string is read-only and no longer evaluated, the first image emitted to set up the viewer is a DataToExport, and the generic plugin does not name it Thorlabs. Tests drive the plugin with a fake driver. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg
When the driver has a get_pixel_size method returning (x, y) in micrometers, the axes of the viewer are calibrated in micrometers, scaled by the binning, and a ROI drawn in the viewer is converted back to sensor pixels. Without the method (the pylablib cameras) the axes stay in pixels. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg
Changing the ROI or the binning while live cleared the acquisition under the thread that waits for the frames. pylablib then returns from wait_for_frame at once and read_multiple_images gives no frame, so the loop of CameraCallback spun without handling the event that stops it, and closing the plugin blocked on the thread. The loop now ends when a read gives no frame and the acquisition is stopped. update_rois stops the acquisition before it sets the ROI (most cameras refuse to change it while a buffer exists) and restarts the live afterwards. stop() now resets is_live. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Before: the camera plugin base (
CameraBasePyLabLib) imported pylablib and opencv at module level, so a camera that pylablib does not drive could not reuse its acquisition thread, viewer ROI and binning. Changing the binning of a ROI that does not start at 0 enlarged the ROI, the viewer axes ignored the binning, and changing the ROI during a live acquisition could block the plugin on closing.After:
CameraBaseis the generic plugin class (no pylablib import, opencv only for the colour conversion) andCameraBasePyLabLibis a thin subclass of it.CameraDriverBasedocuments the methods the plugin calls on its driver (those of the pylablib cameras, which satisfy it unchanged); a driver written against it just reimplements the methods that raiseNotImplementedError. The ROI, binning and live bugs are fixed and the viewer axes can be in micrometers.What changes, in four commits:
camera_base.py(CameraBase,Grab,CameraCallback,cam_params) andcamera_driver.py(CameraDriverBase).camera_base_pylablibkeeps exportingCameraBasePyLabLib,cam_params,CameraCallbackandGrab, so the Thorlabs and Andor plugins are untouched. No behaviour change.get_roi()as (x, width, y, height) while pylablib returns (hstart, hend, vstart, vend, hbin, vbin). The ROI is now always handled in pylablib order and clipped to the sensor (this also makes the "ROI unchanged" test inupdate_roiseffective), the viewer axis size comes from the image shape, the ROI string is read-only instead of beingevaled, and the first image sent to set up the viewer is aDataToExport.get_pixel_size()on the driver gives axes in µm (scaled by the binning), and a ROI drawn in the viewer is converted back to sensor pixels. Drivers without it keep pixel axes.CameraCallbackended only on an event it never handled once the acquisition was cleared under it (pylablib returns fromwait_for_frameat once when stopped), so closing the plugin blocked. It now ends when a read gives no frame and the acquisition is stopped;update_roisstops the acquisition beforeset_roi(most cameras refuse to change the ROI otherwise) and restarts the live afterwards.How:
tests/test_camera_base.pydrives the plugin with a fake driver throughpymodaq.utils.plugin_testing(26 tests, no pylablib or opencv needed); the binning test fails on the previous code. The blocking case of commit 4 is reproduced by the live test of the camera recipe in pymodaq_plugins_mockexamples (a driver with a real thread); the fake driver of this repo does not reproduce it. Tested against fakes only: not on a real camera, and the Thorlabs and Andor plugins could not be run here (no pylablib, no hardware), only their imports fromcamera_base_pylablibwere checked. The CookbookCamera recipe ofpymodaq_plugins_mockexamplesbuilds on this.🤖 Generated with Claude Code
https://claude.ai/code/session_01Tdiso1u1ZhikSutj2Qs5Cg