From d31d43e9b0cb3c90202cf39ccdfa3220f6300917 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 7 Mar 2024 15:55:56 +0100 Subject: [PATCH 01/22] refactor: subclasses can customize _update_img without redefining it --- src/crappy/tool/camera_config/camera_config.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/crappy/tool/camera_config/camera_config.py b/src/crappy/tool/camera_config/camera_config.py index 9662bbee..55be0b60 100644 --- a/src/crappy/tool/camera_config/camera_config.py +++ b/src/crappy/tool/camera_config/camera_config.py @@ -1050,6 +1050,7 @@ def _update_img(self) -> None: self.shape = img.shape self._cast_img(img) + self._draw_overlay() self._resize_img() self._calc_hist() @@ -1061,3 +1062,9 @@ def _update_img(self) -> None: self._update_pixel_value() self.update() + + def _draw_overlay(self) -> None: + """Method meant to be used by subclasses for drawing an overlay on top of + the image to display.""" + + ... From 4589a4b9e315e4dc1af885992df356e7b3af59a5 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 7 Mar 2024 16:03:34 +0100 Subject: [PATCH 02/22] refactor: replace _on_img_resize with _draw_overlay Avoids repeating code, and therefore prevents partial fixes in the future. --- .../tool/camera_config/dic_ve_config.py | 48 +---------------- .../tool/camera_config/dis_correl_config.py | 52 ++----------------- .../camera_config/video_extenso_config.py | 50 ++---------------- 3 files changed, 11 insertions(+), 139 deletions(-) diff --git a/src/crappy/tool/camera_config/dic_ve_config.py b/src/crappy/tool/camera_config/dic_ve_config.py index 6b1230b6..f67f2fb5 100644 --- a/src/crappy/tool/camera_config/dic_ve_config.py +++ b/src/crappy/tool/camera_config/dic_ve_config.py @@ -3,10 +3,6 @@ from typing import Optional from tkinter.messagebox import showerror import tkinter as tk -import numpy as np -from io import BytesIO -from pkg_resources import resource_string -from time import sleep import logging from multiprocessing.queues import Queue @@ -165,50 +161,10 @@ def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: self._display_img() self.update() - def _update_img(self) -> None: - """Same as in the parent class except it also draws the patches on top of - the displayed image.""" + def _draw_overlay(self) -> None: + """Draws the detected spots to track on top of the last acquired image.""" - self.log(logging.DEBUG, "Updating the image") - - ret = self._camera.get_image() - - # If no frame could be grabbed from the camera - if ret is None: - # If it's the first call, generate error image to initialize the window - if not self._n_loops: - self.log(logging.WARNING, "Could not get an image from the camera, " - "displaying an error image instead") - ret = None, np.array(Image.open(BytesIO(resource_string( - 'crappy', 'tool/data/no_image.png')))) - # Otherwise, just pass - else: - self.log(logging.DEBUG, "No image returned by the camera") - self.update() - sleep(0.001) - return - - self._n_loops += 1 - _, img = ret - - if img.dtype != self.dtype: - self.dtype = img.dtype - if self.shape != img.shape: - self.shape = img.shape - - self._cast_img(img) self._draw_spots() - self._resize_img() - - self._calc_hist() - self._resize_hist() - - self._display_img() - self._display_hist() - - self._update_pixel_value() - - self.update() def _handle_box_outside_img(self, box: Box) -> None: """If a patch is outside the image, warning the user and resetting the diff --git a/src/crappy/tool/camera_config/dis_correl_config.py b/src/crappy/tool/camera_config/dis_correl_config.py index da17bf95..d8330288 100644 --- a/src/crappy/tool/camera_config/dis_correl_config.py +++ b/src/crappy/tool/camera_config/dis_correl_config.py @@ -3,10 +3,6 @@ import tkinter as tk from tkinter.messagebox import showerror from typing import Optional -import numpy as np -from io import BytesIO -from pkg_resources import resource_string -from time import sleep import logging from multiprocessing.queues import Queue @@ -164,54 +160,16 @@ def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: self._resize_img() self._display_img() self.update() + def _draw_overlay(self) -> None: + """Draws the box to use for performing correlation on top of the last + acquired image. - def _update_img(self) -> None: - """Same as in the parent class except it also draws the select box on top - of the displayed image.""" + Does not draw the correl box is the user is using the selection box. + """ - self.log(logging.DEBUG, "Updating the image") - - ret = self._camera.get_image() - - # If no frame could be grabbed from the camera - if ret is None: - # If it's the first call, generate error image to initialize the window - if not self._n_loops: - self.log(logging.WARNING, "Could not get an image from the camera, " - "displaying an error image instead") - ret = None, np.array(Image.open(BytesIO(resource_string( - 'crappy', 'tool/data/no_image.png')))) - # Otherwise, just pass - else: - self.log(logging.DEBUG, "No image returned by the camera") - self.update() - sleep(0.001) - return - - self._n_loops += 1 - _, img = ret - - if img.dtype != self.dtype: - self.dtype = img.dtype - if self.shape != img.shape: - self.shape = img.shape - - self._cast_img(img) - # Do not draw the correl box if the user is creating the select box if self._draw_correl_box: self._draw_box(self._correl_box) self._draw_box(self._select_box) - self._resize_img() - - self._calc_hist() - self._resize_hist() - - self._display_img() - self._display_hist() - - self._update_pixel_value() - - self.update() def _handle_box_outside_img(self, _: Box) -> None: """If the correl box is outside the image, it means that the image size has diff --git a/src/crappy/tool/camera_config/video_extenso_config.py b/src/crappy/tool/camera_config/video_extenso_config.py index cacbbe8a..2ac4fd21 100644 --- a/src/crappy/tool/camera_config/video_extenso_config.py +++ b/src/crappy/tool/camera_config/video_extenso_config.py @@ -3,10 +3,6 @@ import tkinter as tk from tkinter.messagebox import showerror from typing import Optional -import numpy as np -from io import BytesIO -from pkg_resources import resource_string -from time import sleep import logging from multiprocessing.queues import Queue @@ -177,52 +173,14 @@ def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: self._resize_img() self._display_img() self.update() + def _draw_overlay(self) -> None: + """Draws the detected spots to track on top of the last acquired image. - def _update_img(self) -> None: - """Same as in the parent class except it also draws the patches and the - select box on top of the displayed image.""" + Also draws the selection box if the user is currently drawing one. + """ - self.log(logging.DEBUG, "Updating the image") - - ret = self._camera.get_image() - - # If no frame could be grabbed from the camera - if ret is None: - # If it's the first call, generate error image to initialize the window - if not self._n_loops: - self.log(logging.WARNING, "Could not get an image from the camera, " - "displaying an error image instead") - ret = None, np.array(Image.open(BytesIO(resource_string( - 'crappy', 'tool/data/no_image.png')))) - # Otherwise, just pass - else: - self.log(logging.DEBUG, "No image returned by the camera") - self.update() - sleep(0.001) - return - - self._n_loops += 1 - _, img = ret - - if img.dtype != self.dtype: - self.dtype = img.dtype - if self.shape != img.shape: - self.shape = img.shape - - self._cast_img(img) self._draw_box(self._select_box) self._draw_spots() - self._resize_img() - - self._calc_hist() - self._resize_hist() - - self._display_img() - self._display_hist() - - self._update_pixel_value() - - self.update() def _handle_box_outside_img(self, _: Box) -> None: """If a patch is outside the image, it means that the image size has been From 51b9644c1410fccc3cb09bf57770fd2b905d134b Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 7 Mar 2024 16:06:10 +0100 Subject: [PATCH 03/22] refactor: remove useless repetition of _on_img_resize removal permitted by the changes in d31d43e9 and 4589a4b9 --- src/crappy/tool/camera_config/camera_config.py | 2 ++ src/crappy/tool/camera_config/dic_ve_config.py | 11 ----------- src/crappy/tool/camera_config/dis_correl_config.py | 14 -------------- .../tool/camera_config/video_extenso_config.py | 11 ----------- 4 files changed, 2 insertions(+), 36 deletions(-) diff --git a/src/crappy/tool/camera_config/camera_config.py b/src/crappy/tool/camera_config/camera_config.py index 55be0b60..8fe53601 100644 --- a/src/crappy/tool/camera_config/camera_config.py +++ b/src/crappy/tool/camera_config/camera_config.py @@ -940,6 +940,8 @@ def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: self.log(logging.DEBUG, "The image canvas was resized") + self._draw_overlay() + self._resize_img() self._display_img() self.update() diff --git a/src/crappy/tool/camera_config/dic_ve_config.py b/src/crappy/tool/camera_config/dic_ve_config.py index f67f2fb5..5946a345 100644 --- a/src/crappy/tool/camera_config/dic_ve_config.py +++ b/src/crappy/tool/camera_config/dic_ve_config.py @@ -150,17 +150,6 @@ def _stop_box(self, _: tk.Event) -> None: # This box is not needed anymore self._select_box.reset() - def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: - """Same as in the parent class except it also draws the patches on top of - the displayed image.""" - - self.log(logging.DEBUG, "The image canvas was resized") - - self._draw_spots() - self._resize_img() - self._display_img() - self.update() - def _draw_overlay(self) -> None: """Draws the detected spots to track on top of the last acquired image.""" diff --git a/src/crappy/tool/camera_config/dis_correl_config.py b/src/crappy/tool/camera_config/dis_correl_config.py index d8330288..5a081de9 100644 --- a/src/crappy/tool/camera_config/dis_correl_config.py +++ b/src/crappy/tool/camera_config/dis_correl_config.py @@ -146,20 +146,6 @@ def _stop_box(self, _: tk.Event) -> None: self._draw_correl_box = True - def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: - """Same as in the parent class except it also draws the select box on top - of the displayed image.""" - - self.log(logging.DEBUG, "The image canvas was resized") - - # Do not draw the correl box if the user is creating the select box - if self._draw_correl_box: - self._draw_box(self._correl_box) - self._draw_box(self._select_box) - - self._resize_img() - self._display_img() - self.update() def _draw_overlay(self) -> None: """Draws the box to use for performing correlation on top of the last acquired image. diff --git a/src/crappy/tool/camera_config/video_extenso_config.py b/src/crappy/tool/camera_config/video_extenso_config.py index 2ac4fd21..7a757358 100644 --- a/src/crappy/tool/camera_config/video_extenso_config.py +++ b/src/crappy/tool/camera_config/video_extenso_config.py @@ -162,17 +162,6 @@ def _save_l0(self) -> None: f"Successfully saved L0 ! L0 x : {self._detector.spots.x_l0}, " f"L0 y : {self._detector.spots.y_l0}") - def _on_img_resize(self, _: Optional[tk.Event] = None) -> None: - """Same as in the parent class except it also draws the patches and the - select box on top of the displayed image.""" - - self.log(logging.DEBUG, "The image canvas was resized") - - self._draw_box(self._select_box) - self._draw_spots() - self._resize_img() - self._display_img() - self.update() def _draw_overlay(self) -> None: """Draws the detected spots to track on top of the last acquired image. From 75a87239639a354be111f8e9b927f42aa61b8f5b Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 7 Mar 2024 16:06:26 +0100 Subject: [PATCH 04/22] style: minor syntax improvement --- src/crappy/tool/camera_config/camera_config_boxes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crappy/tool/camera_config/camera_config_boxes.py b/src/crappy/tool/camera_config/camera_config_boxes.py index 069d47bf..4ec426b1 100644 --- a/src/crappy/tool/camera_config/camera_config_boxes.py +++ b/src/crappy/tool/camera_config/camera_config_boxes.py @@ -88,7 +88,7 @@ def _handle_box_outside_img(self, _: Box) -> None: """This method is meant to simplify the customization of the action to perform when a patch is outside the image in subclasses.""" - pass + ... def _draw_spots(self) -> None: """Simply draws every spot on top of the image.""" From cf5b58e35a9176e5930d2c5061c7b3ca2e3562b4 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 7 Mar 2024 16:07:14 +0100 Subject: [PATCH 05/22] refactor: remove additional code repetitions in subclasses --- src/crappy/tool/camera_config/dis_correl_config.py | 9 +-------- src/crappy/tool/camera_config/video_extenso_config.py | 5 +---- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/crappy/tool/camera_config/dis_correl_config.py b/src/crappy/tool/camera_config/dis_correl_config.py index 5a081de9..2d5871d2 100644 --- a/src/crappy/tool/camera_config/dis_correl_config.py +++ b/src/crappy/tool/camera_config/dis_correl_config.py @@ -108,14 +108,7 @@ def _start_box(self, event: tk.Event) -> None: """Simply saves the position of the user click, and disables the display of the current correl box.""" - self.log(logging.DEBUG, "Starting the selection box") - - # If the mouse is on the canvas but not on the image, do nothing - if not self._check_event_pos(event): - return - - self._select_box.x_start, \ - self._select_box.y_start = self._coord_to_pix(event.x, event.y) + super()._start_box(event) self._draw_correl_box = False diff --git a/src/crappy/tool/camera_config/video_extenso_config.py b/src/crappy/tool/camera_config/video_extenso_config.py index 7a757358..b18d4198 100644 --- a/src/crappy/tool/camera_config/video_extenso_config.py +++ b/src/crappy/tool/camera_config/video_extenso_config.py @@ -111,10 +111,7 @@ def _create_buttons(self) -> None: """Compared with the parent class, creates an extra button for saving the original position of the spots.""" - self._update_button = tk.Button(self._sets_frame, text="Apply Settings", - command=self._update_settings) - self._update_button.pack(expand=False, fill='none', ipadx=5, ipady=5, - padx=5, pady=5, anchor='n', side='top') + super()._create_buttons() self._update_button = tk.Button(self._sets_frame, text="Save L0", command=self._save_l0) From e099409b00aab02eb0eb11968590e9b4012f0706 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 7 Mar 2024 16:27:57 +0100 Subject: [PATCH 06/22] fix: bug in config window when using Camera object returning None The error image indicating that no image could be grabbed was being displayed recurrently, whereas it should only be before the very first image is captured. Fixes #113 --- src/crappy/tool/camera_config/camera_config.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/crappy/tool/camera_config/camera_config.py b/src/crappy/tool/camera_config/camera_config.py index 8fe53601..25792f5b 100644 --- a/src/crappy/tool/camera_config/camera_config.py +++ b/src/crappy/tool/camera_config/camera_config.py @@ -112,6 +112,7 @@ def __init__(self, self._run = True self._n_loops = 0 self._max_freq = max_freq + self._got_first_img: bool = False # Settings for adjusting the behavior of the zoom self._zoom_ratio = 0.9 @@ -1025,13 +1026,12 @@ def _update_img(self) -> None: ret = self._camera.get_image() # Flag raised if no image could be grabbed - no_img = False + no_img = ret is None # If no frame could be grabbed from the camera - if ret is None: - no_img = True + if no_img: # If it's the first call, generate error image to initialize the window - if not self._n_loops: + if not self._got_first_img: self.log(logging.WARNING, "Could not get an image from the camera, " "displaying an error image instead") ret = None, np.array(Image.open(BytesIO(resource_string( @@ -1043,6 +1043,8 @@ def _update_img(self) -> None: sleep(0.001) return + # Always set, so that the error image is only ever loaded once + self._got_first_img = True self._n_loops += 1 _, img = ret From ee20807899ca28f8b2a5b48900ac7faf5dc48004 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 18:20:04 +0200 Subject: [PATCH 07/22] refactor: rename python_package.yml to test_python_package.yml --- .github/workflows/{python_package.yml => test_python_package.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{python_package.yml => test_python_package.yml} (100%) diff --git a/.github/workflows/python_package.yml b/.github/workflows/test_python_package.yml similarity index 100% rename from .github/workflows/python_package.yml rename to .github/workflows/test_python_package.yml From ea269fa261df6375f35057545387f3344c5e9e78 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 18:44:09 +0200 Subject: [PATCH 08/22] ci: update name of jobs --- .github/workflows/test_python_package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_python_package.yml b/.github/workflows/test_python_package.yml index d052c21f..08f78a87 100644 --- a/.github/workflows/test_python_package.yml +++ b/.github/workflows/test_python_package.yml @@ -1,5 +1,5 @@ # Installs the Python dependencies, installs Crappy, and checks that it imports -name: Python Package +name: Test Python Package on: # Runs on pull requests targeting the default branch @@ -15,7 +15,7 @@ on: - cron: '0 12 1 * *' jobs: - build: + test-python-package: runs-on: ${{ matrix.os }} strategy: fail-fast: false From 81e9b133afa82f2a7bbc9cfad32b2f8903717dda Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 18:44:40 +0200 Subject: [PATCH 09/22] ci: add comments to the GitHub action code --- .github/workflows/test_python_package.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_python_package.yml b/.github/workflows/test_python_package.yml index 08f78a87..57e6a80c 100644 --- a/.github/workflows/test_python_package.yml +++ b/.github/workflows/test_python_package.yml @@ -2,7 +2,7 @@ name: Test Python Package on: - # Runs on pull requests targeting the default branch + # Runs on pull requests targeting the default branches pull_request: types: [opened, edited, reopened, synchronize] branches: ["master", "develop"] @@ -20,18 +20,24 @@ jobs: strategy: fail-fast: false matrix: + # Run on all the supported Python versions python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + # Run on all the supported platforms os: [ubuntu-latest, windows-latest, macos-latest] steps: + # Checkout the repository - name: Checkout uses: actions/checkout@v4 + # Set up the correct version of Python - name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + # Install the build dependencies - name: Install dependencies run: python -m pip install --upgrade pip wheel build setuptools + # Install the crappy Python module - name: Install Crappy run: python -m pip install . - name: Import Crappy From 6d5dcdd29d245fbede41b36f4831e6931dd74c5f Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 18:45:29 +0200 Subject: [PATCH 10/22] ci: update setup-python action from v4 to v5 --- .github/workflows/test_python_package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test_python_package.yml b/.github/workflows/test_python_package.yml index 57e6a80c..3be4b98d 100644 --- a/.github/workflows/test_python_package.yml +++ b/.github/workflows/test_python_package.yml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v4 # Set up the correct version of Python - name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} # Install the build dependencies From fc6642b47734ec34ff77b12b51b852e440b1dfae Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 18:46:56 +0200 Subject: [PATCH 11/22] ci: disable check with Python 3.7 run on macOS, no longer supported --- .github/workflows/test_python_package.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test_python_package.yml b/.github/workflows/test_python_package.yml index 3be4b98d..788385bc 100644 --- a/.github/workflows/test_python_package.yml +++ b/.github/workflows/test_python_package.yml @@ -40,5 +40,10 @@ jobs: # Install the crappy Python module - name: Install Crappy run: python -m pip install . + # Check if the module imports as expected + # Cannot run for Python 3.7 on macOS as it is not supported anymore - name: Import Crappy + if: | + contains(fromJSON('["Linux", "Windows"]'), runner.os) || + contains(fromJSON('["3.8", "3.9", "3.10", "3.11", "3.12"]'), matrix.python-version) run: python -c "import crappy; print(crappy.__version__)" From 618d6a78ce80396b0c311d213e533e9bc076ac1d Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 18:59:44 +0200 Subject: [PATCH 12/22] fix: misplaced if condition --- .github/workflows/test_python_package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_python_package.yml b/.github/workflows/test_python_package.yml index 788385bc..bc03f30a 100644 --- a/.github/workflows/test_python_package.yml +++ b/.github/workflows/test_python_package.yml @@ -24,6 +24,10 @@ jobs: python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] # Run on all the supported platforms os: [ubuntu-latest, windows-latest, macos-latest] + # Cannot run for Python 3.7 on macOS as it is no longer supported + if: | + contains(fromJSON('["Linux", "Windows"]'), runner.os) || + contains(fromJSON('["3.8", "3.9", "3.10", "3.11", "3.12"]'), matrix.python-version) steps: # Checkout the repository @@ -41,9 +45,5 @@ jobs: - name: Install Crappy run: python -m pip install . # Check if the module imports as expected - # Cannot run for Python 3.7 on macOS as it is not supported anymore - name: Import Crappy - if: | - contains(fromJSON('["Linux", "Windows"]'), runner.os) || - contains(fromJSON('["3.8", "3.9", "3.10", "3.11", "3.12"]'), matrix.python-version) run: python -c "import crappy; print(crappy.__version__)" From f1a8e3a8e48e4959660e2dfabd83489fd35b1ddc Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Thu, 2 May 2024 19:04:21 +0200 Subject: [PATCH 13/22] fix: replace if check with proper matrix exclusion --- .github/workflows/test_python_package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test_python_package.yml b/.github/workflows/test_python_package.yml index bc03f30a..3045b69d 100644 --- a/.github/workflows/test_python_package.yml +++ b/.github/workflows/test_python_package.yml @@ -24,10 +24,10 @@ jobs: python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] # Run on all the supported platforms os: [ubuntu-latest, windows-latest, macos-latest] - # Cannot run for Python 3.7 on macOS as it is no longer supported - if: | - contains(fromJSON('["Linux", "Windows"]'), runner.os) || - contains(fromJSON('["3.8", "3.9", "3.10", "3.11", "3.12"]'), matrix.python-version) + # Cannot run for Python 3.7 on macOS as it is no longer supported + exclude: + - os: macos-latest + python-version: 3.7 steps: # Checkout the repository From adbd2a2f6cb3bde4fdb69e0beb410aa810ffa1f4 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Wed, 9 Oct 2024 23:02:24 +0200 Subject: [PATCH 14/22] fix: R and B channels inverted when recording images with Pillow backend --- src/crappy/blocks/camera_processes/record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crappy/blocks/camera_processes/record.py b/src/crappy/blocks/camera_processes/record.py index 601d5aef..c0e81b82 100644 --- a/src/crappy/blocks/camera_processes/record.py +++ b/src/crappy/blocks/camera_processes/record.py @@ -232,7 +232,7 @@ def loop(self) -> None: cv2.imwrite(path, self.img) elif self._save_backend == 'pil': - PIL.Image.fromarray(self.img).save( + PIL.Image.fromarray(self.img[:, :, ::-1]).save( path, exif={TAGS_INV[key]: val for key, val in self.metadata.items() if key in TAGS_INV}) From 356ffd83cb8106ef35008ea8b653852500b1f895 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Wed, 9 Oct 2024 23:02:50 +0200 Subject: [PATCH 15/22] fix: image shape not preserved when recording images with SITK backend --- src/crappy/blocks/camera_processes/record.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/crappy/blocks/camera_processes/record.py b/src/crappy/blocks/camera_processes/record.py index c0e81b82..cdda99c1 100644 --- a/src/crappy/blocks/camera_processes/record.py +++ b/src/crappy/blocks/camera_processes/record.py @@ -226,7 +226,8 @@ def loop(self) -> None: # Saving the image at the destination path using the chosen backend self.log(logging.DEBUG, "Saving image") if self._save_backend == 'sitk': - Sitk.WriteImage(Sitk.GetImageFromArray(self.img), path) + Sitk.WriteImage(Sitk.GetImageFromArray(self.img[:, :, ::-1], + isVector=True), path) elif self._save_backend == 'cv2': cv2.imwrite(path, self.img) From 12ebb7200b35cc24a8d42545f5d70cdc42a7e293 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Wed, 9 Oct 2024 23:03:49 +0200 Subject: [PATCH 16/22] refactor: rearrange code to reflect default backend order --- src/crappy/blocks/camera_processes/record.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/crappy/blocks/camera_processes/record.py b/src/crappy/blocks/camera_processes/record.py index cdda99c1..5c2a9bc2 100644 --- a/src/crappy/blocks/camera_processes/record.py +++ b/src/crappy/blocks/camera_processes/record.py @@ -229,14 +229,14 @@ def loop(self) -> None: Sitk.WriteImage(Sitk.GetImageFromArray(self.img[:, :, ::-1], isVector=True), path) - elif self._save_backend == 'cv2': - cv2.imwrite(path, self.img) - elif self._save_backend == 'pil': PIL.Image.fromarray(self.img[:, :, ::-1]).save( path, exif={TAGS_INV[key]: val for key, val in self.metadata.items() if key in TAGS_INV}) + elif self._save_backend == 'cv2': + cv2.imwrite(path, self.img) + elif self._save_backend == 'npy': np.save(path, self.img) From 118df0b4197f52363349513159455c0a04cfe083 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Wed, 9 Oct 2024 23:15:10 +0200 Subject: [PATCH 17/22] fix: bug when saving grey level images introduced in 12ebb720 --- src/crappy/blocks/camera_processes/record.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/crappy/blocks/camera_processes/record.py b/src/crappy/blocks/camera_processes/record.py index 5c2a9bc2..db65271c 100644 --- a/src/crappy/blocks/camera_processes/record.py +++ b/src/crappy/blocks/camera_processes/record.py @@ -226,13 +226,21 @@ def loop(self) -> None: # Saving the image at the destination path using the chosen backend self.log(logging.DEBUG, "Saving image") if self._save_backend == 'sitk': - Sitk.WriteImage(Sitk.GetImageFromArray(self.img[:, :, ::-1], - isVector=True), path) + if len(self.img.shape) == 3: + Sitk.WriteImage(Sitk.GetImageFromArray(self.img[:, :, ::-1], + isVector=True), path) + else: + Sitk.WriteImage(Sitk.GetImageFromArray(self.img), path) elif self._save_backend == 'pil': - PIL.Image.fromarray(self.img[:, :, ::-1]).save( - path, exif={TAGS_INV[key]: val for key, val in self.metadata.items() - if key in TAGS_INV}) + if len(self.img.shape) == 3: + PIL.Image.fromarray(self.img[:, :, ::-1]).save( + path, exif={TAGS_INV[key]: val for key, val in self.metadata.items() + if key in TAGS_INV}) + else: + PIL.Image.fromarray(self.img).save( + path, exif={TAGS_INV[key]: val for key, val in self.metadata.items() + if key in TAGS_INV}) elif self._save_backend == 'cv2': cv2.imwrite(path, self.img) From 6a5583f8217a00beb38172603f370530a283a308 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Mon, 14 Oct 2024 23:08:55 +0200 Subject: [PATCH 18/22] docs: add missing example about using custom Generator conditions --- .../generator/generator_custom_condition.py | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 examples/blocks/generator/generator_custom_condition.py diff --git a/examples/blocks/generator/generator_custom_condition.py b/examples/blocks/generator/generator_custom_condition.py new file mode 100644 index 00000000..37176de5 --- /dev/null +++ b/examples/blocks/generator/generator_custom_condition.py @@ -0,0 +1,100 @@ +# coding: utf-8 + +""" +This example demonstrates the use of a Generator Block using a user-defined +condition to determine whether to switch to the next Path. It does not require +any specific hardware to run, but necessitates the matplotlib Python module to +be installed. + +The Generator Block outputs a signal following a provided path. Several paths +are available, each with a different behavior and different options. They can +be combined to form a custom global path. + +Here, the Generator outputs a simple constant signal, that switches to a +different value once the end condition is met. However, unlike the other +Generator example, the stop condition is not one of the standard ones defined +in Crappy, but rather an arbitrary callable defined by the user. Here, the +condition check whether a given file exists, but it could really have been any +other kind of condition. + +After starting this script, you should create the file 'test.txt' in the same +folder where this script is located. See how the value of the signal changes +once the file is created. Once you delete the newly created file, the test +should then end, due to the second custom condition. You can also end this demo +earlier by clicking on the stop button that appears. You can also hit CTRL+C, +but it is not a clean way to stop Crappy. +""" + +import crappy +from pathlib import Path + + +def file_exists(data): + """Returns True if the file 'test.txt' exists at the same level as the + running script, False otherwise. + + This arbitrary function can access the data received by the Generator Block, + which is exposed in the data argument as a dictionary. + + Args: + data: The data received by the Generator Block since its last loop. The + keys are the labels, and the values a list containing all the received + values for the given label. + """ + + return Path('./test.txt').exists() + + +def file_does_not_exist(data): + """Returns False if the file 'test.txt' exists at the same level as the + running script, True otherwise. + + This arbitrary function can access the data received by the Generator Block, + which is exposed in the data argument as a dictionary. + + Args: + data: The data received by the Generator Block since its last loop. The + keys are the labels, and the values a list containing all the received + values for the given label. + """ + + return not Path('./test.txt').exists() + + +if __name__ == '__main__': + + # This Generator Block generates a constant signal, and sends it to the + # Dashboard Block for display + # The signal first has a value of 0, then 1. + gen = crappy.blocks.Generator( + path=({'type': 'Constant', 'value': 0, + 'condition': file_exists}, + {'type': 'Constant', 'value': 1, + 'condition': file_does_not_exist}), + # The simple path to generate + # Notice how the functions defined earlier are included in the path and + # associated to the 'condition' key + freq=50, # Lowering the default frequency because it's just a demo + cmd_label='signal', # The label carrying the value of the generated + # signal + path_index_label='index', # This label carries the index of the current + # path + spam=True, # Send a value at each loop, for a nice display on the + # Dashboard + + # Sticking to default for the other arguments + ) + + # This Dashboard displays the signal it receives from the Generator + dash = crappy.blocks.Dashboard(('t(s)', 'signal')) + + # This Block allows the user to properly exit the script + stop = crappy.blocks.StopButton( + # No specific argument to give for this Block + ) + + # Linking the Block so that the information is correctly sent and received + crappy.link(gen, dash) + + # Mandatory line for starting the test, this call is blocking + crappy.start() From de36057f34a6ba11c57de9eb5695ae41ca8c86c4 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Mon, 14 Oct 2024 23:22:39 +0200 Subject: [PATCH 19/22] docs: update documentation to reflect changes in 07accf35 --- src/crappy/blocks/camera.py | 15 ++++++++------- src/crappy/blocks/dic_ve.py | 13 +++++++------ src/crappy/blocks/dis_correl.py | 13 +++++++------ src/crappy/blocks/gpu_correl.py | 13 +++++++------ src/crappy/blocks/gpu_ve.py | 13 +++++++------ src/crappy/blocks/video_extenso.py | 13 +++++++------ 6 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/crappy/blocks/camera.py b/src/crappy/blocks/camera.py index 55598bac..912b4c7a 100644 --- a/src/crappy/blocks/camera.py +++ b/src/crappy/blocks/camera.py @@ -194,20 +194,21 @@ def __init__(self, Ignored if ``save_images`` is :obj:`False`. .. versionadded:: 1.5.10 - save_backend: If ``save_images`` is :obj:`True`, the backend to use for + save_backend: If ``save_images`` is :obj:`True`, the backend to use for recording the images. It should be one of: :: - 'sitk', 'cv2', 'pil', 'npy' + 'sitk', 'pil', 'cv2', 'npy' - They correspond to the modules :mod:`SimpleITK`, :mod:`cv2` (OpenCV), - :mod:`PIL` (Pillow Fork), and :mod:`numpy`. Note that the ``'npy'`` + They correspond to the modules :mod:`SimpleITK`, :mod:`PIL` (Pillow + Fork), :mod:`cv2` (OpenCV), and :mod:`numpy`. Note that the ``'npy'`` backend saves the images as raw :obj:`numpy.array`, and thus ignores the ``img_extension`` argument. Depending on the machine, some backends may be faster or slower. For using each backend, the corresponding - Python must of course be installed. If not provided and ``save_images`` - is :obj:`True`, the backends are tried in the same order as given above - and the first available one is used. ``'npy'`` is always available. + Python module must of course be installed. If not provided and + ``save_images`` is :obj:`True`, the backends are tried in the same + order as given above and the first available one is used. ``'npy'`` is + always available. .. versionadded:: 1.5.10 image_generator: A callable taking two :obj:`float` as arguments and diff --git a/src/crappy/blocks/dic_ve.py b/src/crappy/blocks/dic_ve.py index 7985c9cc..1512a9e6 100644 --- a/src/crappy/blocks/dic_ve.py +++ b/src/crappy/blocks/dic_ve.py @@ -208,16 +208,17 @@ def __init__(self, recording the images. It should be one of: :: - 'sitk', 'cv2', 'pil', 'npy' + 'sitk', 'pil', 'cv2', 'npy' - They correspond to the modules :mod:`SimpleITK`, :mod:`cv2` (OpenCV), - :mod:`PIL` (Pillow Fork), and :mod:`numpy`. Note that the ``'npy'`` + They correspond to the modules :mod:`SimpleITK`, :mod:`PIL` (Pillow + Fork), :mod:`cv2` (OpenCV), and :mod:`numpy`. Note that the ``'npy'`` backend saves the images as raw :obj:`numpy.array`, and thus ignores the ``img_extension`` argument. Depending on the machine, some backends may be faster or slower. For using each backend, the corresponding - Python must of course be installed. If not provided and ``save_images`` - is :obj:`True`, the backends are tried in the same order as given above - and the first available one is used. ``'npy'`` is always available. + Python module must of course be installed. If not provided and + ``save_images`` is :obj:`True`, the backends are tried in the same + order as given above and the first available one is used. ``'npy'`` is + always available. .. versionadded:: 1.5.10 image_generator: A callable taking two :obj:`float` as arguments and diff --git a/src/crappy/blocks/dis_correl.py b/src/crappy/blocks/dis_correl.py index b22993b7..c95ba3c0 100644 --- a/src/crappy/blocks/dis_correl.py +++ b/src/crappy/blocks/dis_correl.py @@ -198,16 +198,17 @@ def __init__(self, recording the images. It should be one of: :: - 'sitk', 'cv2', 'pil', 'npy' + 'sitk', 'pil', 'cv2', 'npy' - They correspond to the modules :mod:`SimpleITK`, :mod:`cv2` (OpenCV), - :mod:`PIL` (Pillow Fork), and :mod:`numpy`. Note that the ``'npy'`` + They correspond to the modules :mod:`SimpleITK`, :mod:`PIL` (Pillow + Fork), :mod:`cv2` (OpenCV), and :mod:`numpy`. Note that the ``'npy'`` backend saves the images as raw :obj:`numpy.array`, and thus ignores the ``img_extension`` argument. Depending on the machine, some backends may be faster or slower. For using each backend, the corresponding - Python must of course be installed. If not provided and ``save_images`` - is :obj:`True`, the backends are tried in the same order as given above - and the first available one is used. ``'npy'`` is always available. + Python module must of course be installed. If not provided and + ``save_images`` is :obj:`True`, the backends are tried in the same + order as given above and the first available one is used. ``'npy'`` is + always available. .. versionadded:: 1.5.10 image_generator: A callable taking two :obj:`float` as arguments and diff --git a/src/crappy/blocks/gpu_correl.py b/src/crappy/blocks/gpu_correl.py index 20a656c7..fa538657 100644 --- a/src/crappy/blocks/gpu_correl.py +++ b/src/crappy/blocks/gpu_correl.py @@ -200,16 +200,17 @@ def __init__(self, recording the images. It should be one of: :: - 'sitk', 'cv2', 'pil', 'npy' + 'sitk', 'pil', 'cv2', 'npy' - They correspond to the modules :mod:`SimpleITK`, :mod:`cv2` (OpenCV), - :mod:`PIL` (Pillow Fork), and :mod:`numpy`. Note that the ``'npy'`` + They correspond to the modules :mod:`SimpleITK`, :mod:`PIL` (Pillow + Fork), :mod:`cv2` (OpenCV), and :mod:`numpy`. Note that the ``'npy'`` backend saves the images as raw :obj:`numpy.array`, and thus ignores the ``img_extension`` argument. Depending on the machine, some backends may be faster or slower. For using each backend, the corresponding - Python must of course be installed. If not provided and ``save_images`` - is :obj:`True`, the backends are tried in the same order as given above - and the first available one is used. ``'npy'`` is always available. + Python module must of course be installed. If not provided and + ``save_images`` is :obj:`True`, the backends are tried in the same + order as given above and the first available one is used. ``'npy'`` is + always available. .. versionadded:: 1.5.10 image_generator: A callable taking two :obj:`float` as arguments and diff --git a/src/crappy/blocks/gpu_ve.py b/src/crappy/blocks/gpu_ve.py index d9975e9f..74c85124 100644 --- a/src/crappy/blocks/gpu_ve.py +++ b/src/crappy/blocks/gpu_ve.py @@ -186,16 +186,17 @@ def __init__(self, recording the images. It should be one of: :: - 'sitk', 'cv2', 'pil', 'npy' + 'sitk', 'pil', 'cv2', 'npy' - They correspond to the modules :mod:`SimpleITK`, :mod:`cv2` (OpenCV), - :mod:`PIL` (Pillow Fork), and :mod:`numpy`. Note that the ``'npy'`` + They correspond to the modules :mod:`SimpleITK`, :mod:`PIL` (Pillow + Fork), :mod:`cv2` (OpenCV), and :mod:`numpy`. Note that the ``'npy'`` backend saves the images as raw :obj:`numpy.array`, and thus ignores the ``img_extension`` argument. Depending on the machine, some backends may be faster or slower. For using each backend, the corresponding - Python must of course be installed. If not provided and ``save_images`` - is :obj:`True`, the backends are tried in the same order as given above - and the first available one is used. ``'npy'`` is always available. + Python module must of course be installed. If not provided and + ``save_images`` is :obj:`True`, the backends are tried in the same + order as given above and the first available one is used. ``'npy'`` is + always available. .. versionadded:: 1.5.10 image_generator: A callable taking two :obj:`float` as arguments and diff --git a/src/crappy/blocks/video_extenso.py b/src/crappy/blocks/video_extenso.py index 2241a850..f5e80612 100644 --- a/src/crappy/blocks/video_extenso.py +++ b/src/crappy/blocks/video_extenso.py @@ -193,16 +193,17 @@ def __init__(self, recording the images. It should be one of: :: - 'sitk', 'cv2', 'pil', 'npy' + 'sitk', 'pil', 'cv2', 'npy' - They correspond to the modules :mod:`SimpleITK`, :mod:`cv2` (OpenCV), - :mod:`PIL` (Pillow Fork), and :mod:`numpy`. Note that the ``'npy'`` + They correspond to the modules :mod:`SimpleITK`, :mod:`PIL` (Pillow + Fork), :mod:`cv2` (OpenCV), and :mod:`numpy`. Note that the ``'npy'`` backend saves the images as raw :obj:`numpy.array`, and thus ignores the ``img_extension`` argument. Depending on the machine, some backends may be faster or slower. For using each backend, the corresponding - Python must of course be installed. If not provided and ``save_images`` - is :obj:`True`, the backends are tried in the same order as given above - and the first available one is used. ``'npy'`` is always available. + Python module must of course be installed. If not provided and + ``save_images`` is :obj:`True`, the backends are tried in the same + order as given above and the first available one is used. ``'npy'`` is + always available. .. versionadded:: 1.5.10 image_generator: A callable taking two :obj:`float` as arguments and From 421d0b80701b7d49eec086309cbea9a883e13ff1 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Mon, 14 Oct 2024 23:25:21 +0200 Subject: [PATCH 20/22] docs: add warning forgotten in 67854ce7 --- src/crappy/lamcube/bispectral.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/crappy/lamcube/bispectral.py b/src/crappy/lamcube/bispectral.py index 472a6002..170ab444 100644 --- a/src/crappy/lamcube/bispectral.py +++ b/src/crappy/lamcube/bispectral.py @@ -3,6 +3,7 @@ import numpy as np from typing import Tuple import logging +from warnings import warn from ..camera.cameralink import BaslerIronmanCameraLink @@ -86,11 +87,16 @@ class BiSpectral(BaslerIronmanCameraLink): .. versionadded:: 1.4.0 .. versionchanged:: 2.0.0 renamed from *Bispectral* to *BiSpectral* + .. versionremoved:: 2.1.0 """ def __init__(self) -> None: """Adds the various setting for the Camera.""" + warn(f"Starting from version 2.1.0, {type(self).__name__} will be " + f"deprecated and removed from Crappy. Please contact the maintainers " + f"if you still use this Camera.", FutureWarning) + super().__init__() self.add_scale_setting('width', 1, 640, self._get_w, self._set_w, 640) self.add_scale_setting('height', 1, 512, self._get_h, self._set_h, 512) From a6375735c737aff1789e29442baac6cb7f8d4821 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Tue, 15 Oct 2024 23:04:05 +0200 Subject: [PATCH 21/22] fix: cast numpy types to Python types wherever needed --- src/crappy/blocks/camera_processes/display.py | 4 ++-- .../blocks/camera_processes/gpu_correl.py | 3 ++- src/crappy/blocks/fake_machine.py | 7 ++++--- src/crappy/blocks/mean.py | 2 +- src/crappy/camera/seek_thermal_pro.py | 3 ++- src/crappy/modifier/demux.py | 12 ++++++------ src/crappy/modifier/mean.py | 2 +- src/crappy/modifier/median.py | 2 +- src/crappy/modifier/moving_avg.py | 2 +- src/crappy/modifier/moving_med.py | 2 +- src/crappy/tool/camera_config/camera_config.py | 17 +++++++++-------- src/crappy/tool/image_processing/dic_ve.py | 2 +- src/crappy/tool/image_processing/dis_correl.py | 7 ++++--- .../video_extenso/video_extenso.py | 18 +++++++++--------- 14 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/crappy/blocks/camera_processes/display.py b/src/crappy/blocks/camera_processes/display.py index 8f276693..2d9c503f 100644 --- a/src/crappy/blocks/camera_processes/display.py +++ b/src/crappy/blocks/camera_processes/display.py @@ -172,8 +172,8 @@ def loop(self) -> None: if self.img.dtype != np.uint8: self.log(logging.DEBUG, f"Casting displayed image from " f"{self.img.dtype} to uint8") - if np.max(self.img) > 255: - factor = max(ceil(log2(np.max(self.img) + 1) - 8), 0) + if int(np.max(self.img)) > 255: + factor = max(ceil(log2(int(np.max(self.img)) + 1) - 8), 0) img = (self.img / 2 ** factor).astype(np.uint8) else: img = self.img.astype(np.uint8) diff --git a/src/crappy/blocks/camera_processes/gpu_correl.py b/src/crappy/blocks/camera_processes/gpu_correl.py index 8b70e1e0..49f839f3 100644 --- a/src/crappy/blocks/camera_processes/gpu_correl.py +++ b/src/crappy/blocks/camera_processes/gpu_correl.py @@ -213,7 +213,8 @@ def loop(self) -> None: self._res_history.append(res) self._res_history = self._res_history[-self._discard_ref - 1:] - if res > self._discard_limit * np.average(self._res_history[:-1]): + if (res > self._discard_limit * + float(np.average(self._res_history[:-1]))): self.log(logging.WARNING, "Residual too high, not sending " "values") return diff --git a/src/crappy/blocks/fake_machine.py b/src/crappy/blocks/fake_machine.py index 88663ada..82ced1bb 100644 --- a/src/crappy/blocks/fake_machine.py +++ b/src/crappy/blocks/fake_machine.py @@ -138,10 +138,11 @@ def loop(self) -> None: # Calculating the speed based on the command and the mode if self._mode == 'speed': - speed = np.sign(cmd) * np.min((self._max_speed, np.abs(cmd))) + speed = float(np.sign(cmd)) * float(np.min((self._max_speed, + np.abs(cmd)))) elif self._mode == 'position': - speed = np.sign(cmd - self._current_pos) * np.min( - (self._max_speed, np.abs(cmd - self._current_pos) / delta_t)) + speed = float(np.sign(cmd - self._current_pos)) * float(np.min( + (self._max_speed, np.abs(cmd - self._current_pos) / delta_t))) else: raise ValueError(f'Invalid mode : {self._mode} !') diff --git a/src/crappy/blocks/mean.py b/src/crappy/blocks/mean.py index 96a77749..c61b5854 100644 --- a/src/crappy/blocks/mean.py +++ b/src/crappy/blocks/mean.py @@ -112,7 +112,7 @@ def loop(self) -> None: for label, values in data.items(): if self._out_labels is None or label in self._out_labels: try: - to_send[label] = np.mean(values) + to_send[label] = float(np.mean(values)) except (ValueError, TypeError): self.log(logging.WARNING, f"Cannot perform averaging on label " f"{label} with values: {values}") diff --git a/src/crappy/camera/seek_thermal_pro.py b/src/crappy/camera/seek_thermal_pro.py index ae0da8fa..048571fc 100644 --- a/src/crappy/camera/seek_thermal_pro.py +++ b/src/crappy/camera/seek_thermal_pro.py @@ -265,7 +265,8 @@ def _correct_dead_pixels(self, img: np.ndarray) -> np.ndarray: """ for i, j in self._dead_pixels: - img[i, j] = np.median(img[max(0, i - 1): i + 2, max(0, j - 1): j + 2]) + img[i, j] = float(np.median(img[max(0, i - 1): i + 2, + max(0, j - 1): j + 2])) return img def _write_data(self, request: int, data: bytes) -> int: diff --git a/src/crappy/modifier/demux.py b/src/crappy/modifier/demux.py index 4a88112a..b1772bbb 100644 --- a/src/crappy/modifier/demux.py +++ b/src/crappy/modifier/demux.py @@ -86,24 +86,24 @@ def __call__(self, data: Dict[str, np.ndarray]) -> Dict[str, Any]: # The data of a given label is on a same row if self._transpose: if self._mean: - data[label] = np.mean(data[self._stream_label][i, :]) + data[label] = float(np.mean(data[self._stream_label][i, :])) else: - data[label] = data[self._stream_label][i, 0] + data[label] = float(data[self._stream_label][i, 0]) # The data of a given label is on a same column else: if self._mean: - data[label] = np.mean(data[self._stream_label][:, i]) + data[label] = float(np.mean(data[self._stream_label][:, i])) else: - data[label] = data[self._stream_label][0, i] + data[label] = float(data[self._stream_label][0, i]) # Discarding the raw data del data[self._stream_label] # Keeping either the average or the first time value if self._mean: - data[self._time_label] = np.mean(data[self._time_label]) + data[self._time_label] = float(np.mean(data[self._time_label])) else: - data[self._time_label] = np.squeeze(data[self._time_label])[0] + data[self._time_label] = float(np.squeeze(data[self._time_label])[0]) self.log(logging.DEBUG, f"Sending {data}") diff --git a/src/crappy/modifier/mean.py b/src/crappy/modifier/mean.py index 7ce733a5..83633545 100644 --- a/src/crappy/modifier/mean.py +++ b/src/crappy/modifier/mean.py @@ -54,7 +54,7 @@ def __call__(self, data: Dict[str, Any]) -> Optional[Dict[str, Any]]: # Once there's enough data in the buffer, calculating the average value if len(self._buf[label]) == self._n_points: try: - ret[label] = np.mean(self._buf[label]) + ret[label] = float(np.mean(self._buf[label])) except TypeError: ret[label] = self._buf[label][-1] diff --git a/src/crappy/modifier/median.py b/src/crappy/modifier/median.py index 998e53b5..36c8e222 100644 --- a/src/crappy/modifier/median.py +++ b/src/crappy/modifier/median.py @@ -54,7 +54,7 @@ def __call__(self, data: Dict[str, Any]) -> Optional[Dict[str, Any]]: # Once there's enough data in the buffer, calculating the median value if len(self._buf[label]) == self._n_points: try: - ret[label] = np.median(self._buf[label]) + ret[label] = float(np.median(self._buf[label])) except TypeError: ret[label] = self._buf[label][-1] diff --git a/src/crappy/modifier/moving_avg.py b/src/crappy/modifier/moving_avg.py index 4c7f4381..398a236f 100644 --- a/src/crappy/modifier/moving_avg.py +++ b/src/crappy/modifier/moving_avg.py @@ -55,7 +55,7 @@ def __call__(self, data: Dict[str, Any]) -> Dict[str, Any]: # Calculating the average for each label try: - ret[label] = np.mean(self._buf[label]) + ret[label] = float(np.mean(self._buf[label])) except TypeError: ret[label] = self._buf[label][-1] diff --git a/src/crappy/modifier/moving_med.py b/src/crappy/modifier/moving_med.py index 80f0dd6c..c75f99e5 100644 --- a/src/crappy/modifier/moving_med.py +++ b/src/crappy/modifier/moving_med.py @@ -55,7 +55,7 @@ def __call__(self, data: Dict[str, Any]) -> Dict[str, Any]: # Calculating the median for each label try: - ret[label] = np.median(self._buf[label]) + ret[label] = float(np.median(self._buf[label])) except TypeError: ret[label] = self._buf[label][-1] diff --git a/src/crappy/tool/camera_config/camera_config.py b/src/crappy/tool/camera_config/camera_config.py index 25792f5b..e0801d71 100644 --- a/src/crappy/tool/camera_config/camera_config.py +++ b/src/crappy/tool/camera_config/camera_config.py @@ -522,13 +522,13 @@ def _update_pixel_value(self) -> None: self.log(logging.DEBUG, "Updating the value of the current pixel") try: - self._reticle_val.set(np.average(self._original_img[self._y_pos.get(), - self._x_pos.get()])) + self._reticle_val.set(int(np.average( + self._original_img[self._y_pos.get(), self._x_pos.get()]))) except IndexError: self._x_pos.set(0) self._y_pos.set(0) - self._reticle_val.set(np.average(self._original_img[self._y_pos.get(), - self._x_pos.get()])) + self._reticle_val.set(int(np.average( + self._original_img[self._y_pos.get(), self._x_pos.get()]))) def _coord_to_pix(self, x: int, y: int) -> Tuple[int, int]: """Converts the coordinates of the mouse in the GUI referential to @@ -859,19 +859,20 @@ def _cast_img(self, img: np.ndarray) -> None: # If the auto_range is set, adjusting the values to the range if self._auto_range.get(): self.log(logging.DEBUG, "Applying auto range to the image") - self._low_thresh, self._high_thresh = np.percentile(img, (3, 97)) + self._low_thresh, self._high_thresh = map(float, + np.percentile(img, (3, 97))) self._img = ((np.clip(img, self._low_thresh, self._high_thresh) - self._low_thresh) * 255 / (self._high_thresh - self._low_thresh)).astype('uint8') # The original image still needs to be saved as 8-bits - bit_depth = np.ceil(np.log2(np.max(img) + 1)) + bit_depth = int(np.ceil(np.log2(int(np.max(img)) + 1))) self._original_img = (img / 2 ** (bit_depth - 8)).astype('uint8') # Or if the image is not already 8 bits, casting to 8 bits elif img.dtype != np.uint8: self.log(logging.DEBUG, "Casting the image to 8 bits") - bit_depth = np.ceil(np.log2(np.max(img) + 1)) + bit_depth = int(np.ceil(np.log2(int(np.max(img)) + 1))) self._img = (img / 2 ** (bit_depth - 8)).astype('uint8') self._original_img = np.copy(self._img) @@ -881,7 +882,7 @@ def _cast_img(self, img: np.ndarray) -> None: self._original_img = np.copy(img) # Updating the information - self._nb_bits.set(int(np.ceil(np.log2(np.max(img) + 1)))) + self._nb_bits.set(int(np.ceil(np.log2(int(np.max(img)) + 1)))) self._max_pixel.set(int(np.max(img))) self._min_pixel.set(int(np.min(img))) diff --git a/src/crappy/tool/image_processing/dic_ve.py b/src/crappy/tool/image_processing/dic_ve.py index 38ba7f4c..b0b11fdc 100644 --- a/src/crappy/tool/image_processing/dic_ve.py +++ b/src/crappy/tool/image_processing/dic_ve.py @@ -307,7 +307,7 @@ def _parabola_fit(arr: np.ndarray) -> float: arr: This array contains the y values for the 3 points. """ - return (arr[0] - arr[2]) / (2 * (arr[0] - 2 * arr[1] + arr[2])) + return float((arr[0] - arr[2]) / (2 * (arr[0] - 2 * arr[1] + arr[2]))) @staticmethod def _cross_correlation(img0: np.ndarray, diff --git a/src/crappy/tool/image_processing/dis_correl.py b/src/crappy/tool/image_processing/dis_correl.py index 4224b324..6bbf9ea5 100644 --- a/src/crappy/tool/image_processing/dis_correl.py +++ b/src/crappy/tool/image_processing/dis_correl.py @@ -157,7 +157,7 @@ def set_box(self) -> None: # These attributes will be used later self._base = [fields[:, :, :, i] for i in range(fields.shape[3])] - self._norm2 = [np.sum(base_field ** 2) for base_field in self._base] + self._norm2 = [float(np.sum(base_field ** 2)) for base_field in self._base] def get_data(self, img: np.ndarray, @@ -192,12 +192,13 @@ def get_data(self, self._dis_flow = self._dis.calc(self._img0, img, None) # Getting the values to calculate as floats - ret = [np.sum(vec * self._crop(self._dis_flow)) / n2 for vec, n2 in + ret = [float(np.sum(vec * self._crop(self._dis_flow))) / n2 for vec, n2 in zip(self._base, self._norm2)] # Adding the average residual value if requested if residuals: - ret.append(np.average(np.abs(get_res(self._img0, img, self._dis_flow)))) + ret.append(float(np.average(np.abs(get_res(self._img0, img, + self._dis_flow))))) return ret diff --git a/src/crappy/tool/image_processing/video_extenso/video_extenso.py b/src/crappy/tool/image_processing/video_extenso/video_extenso.py index 003aa53e..fe9cf03c 100644 --- a/src/crappy/tool/image_processing/video_extenso/video_extenso.py +++ b/src/crappy/tool/image_processing/video_extenso/video_extenso.py @@ -243,15 +243,15 @@ def get_data(self, x_top_1, x_bottom_1, y_left_1, y_right_1 = box_1.sorted() x_top_2, x_bottom_2, y_left_2, y_right_2 = box_2.sorted() - box_1.x_start = min(x_top_1 + 1, box_1.x_centroid - 2) - box_1.y_start = min(y_left_1 + 1, box_1.y_centroid - 2) - box_1.x_end = max(x_bottom_1 - 1, box_1.x_centroid + 2) - box_1.y_end = max(y_right_1 - 1, box_1.y_centroid + 2) - - box_2.x_start = min(x_top_2 + 1, box_2.x_centroid - 2) - box_2.y_start = min(y_left_2 + 1, box_2.y_centroid - 2) - box_2.x_end = max(x_bottom_2 - 1, box_2.x_centroid + 2) - box_2.y_end = max(y_right_2 - 1, box_2.y_centroid + 2) + box_1.x_start = min(x_top_1 + 1, int(box_1.x_centroid - 2)) + box_1.y_start = min(y_left_1 + 1, int(box_1.y_centroid - 2)) + box_1.x_end = max(x_bottom_1 - 1, int(box_1.x_centroid + 2)) + box_1.y_end = max(y_right_1 - 1, int(box_1.y_centroid + 2)) + + box_2.x_start = min(x_top_2 + 1, int(box_2.x_centroid - 2)) + box_2.y_start = min(y_left_2 + 1, int(box_2.y_centroid - 2)) + box_2.x_end = max(x_bottom_2 - 1, int(box_2.x_centroid + 2)) + box_2.y_end = max(y_right_2 - 1, int(box_2.y_centroid + 2)) if overlap: self._consecutive_overlaps += 1 From 8c42b28e16b55af2d2001e8899462d8ea9024504 Mon Sep 17 00:00:00 2001 From: Antoine Weisrock Date: Tue, 15 Oct 2024 23:27:01 +0200 Subject: [PATCH 22/22] chore: update project version from 2.0.5 to 2.0.6 --- docs/source/conf.py | 2 +- pyproject.toml | 2 +- src/crappy/__version__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index 5b3d4d65..b4655a93 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -16,7 +16,7 @@ from time import gmtime, strftime from re import match -__version__ = '2.0.5' +__version__ = '2.0.6' # -- Project information ----------------------------------------------------- diff --git a/pyproject.toml b/pyproject.toml index 596d3faf..dd327e0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "crappy" dynamic = ["readme"] -version = "2.0.5" +version = "2.0.6" description = "Command and Real-time Acquisition in Parallelized Python" license = {file = "LICENSE"} keywords = ["control", "command", "acquisition", "multiprocessing"] diff --git a/src/crappy/__version__.py b/src/crappy/__version__.py index 7717659c..2a6cb509 100644 --- a/src/crappy/__version__.py +++ b/src/crappy/__version__.py @@ -1,3 +1,3 @@ # coding: utf-8 -__version__ = '2.0.5' +__version__ = '2.0.6'