Commit 54b889b3 authored by Matias Guijarro's avatar Matias Guijarro
Browse files

Merge branch '2777-automatic-rois-transforms-after-cam-geometry-modification' into 'master'

Resolve "automatic rois transforms after cam geometry modification"

Closes #2777

See merge request !3730
parents 031f48d2 7d8c2f22
Pipeline #47475 passed with stages
in 122 minutes and 24 seconds
......@@ -28,8 +28,6 @@ from bliss.common.logtools import log_debug
# ----------------- helpers for ROI coordinates (x,y,w,h) transformations (flip, rotation, binning) --------------
_DEG2RAD = numpy.pi / 180.0
def current_coords_to_raw_coords(coords_list, img_size, flip, rotation, binning):
......@@ -132,7 +130,7 @@ def calc_pts_rotation(pts, angle, img_size):
frame = numpy.array([[0, 0], [w0, h0]])
# define the rotation matrix
theta = _DEG2RAD * angle * -1 # Lima rotation is clockwise !
theta = numpy.deg2rad(angle) * -1 # Lima rotation is clockwise !
R = numpy.array(
[[numpy.cos(theta), -numpy.sin(theta)], [numpy.sin(theta), numpy.cos(theta)]]
)
......@@ -395,12 +393,13 @@ class ImageCounter(Counter):
h = y1 - y0
self.roi = [x0, y0, w, h]
def _update_roi(self):
def _update_roi(self, update_dependencies=True):
detector_size = self._get_detector_max_size()
self._cur_roi = raw_roi_to_current_roi(
self.raw_roi, detector_size, self.flip, self.rotation, self.binning
)
self._counter_controller._update_lima_rois()
if update_dependencies:
self._counter_controller._update_lima_rois()
def _calc_raw_roi(self, roi):
""" computes the raw_roi from a given roi and current bin, flip, rot """
......@@ -480,6 +479,17 @@ class ImageCounter(Counter):
"roi": self.roi,
}
def set_geometry(self, binning, flip, rotation, roi=None):
self._image_params.binning = binning
self._image_params.flip = flip
self._image_params.rotation = rotation
if roi is None:
self._update_roi()
else:
self._update_roi(update_dependencies=False)
self.roi = roi
def update_max_size(self):
""" Update the image maximum size (reading the device proxy)
and reset the ROI to the new full frame.
......
......@@ -797,13 +797,16 @@ class Lima(CounterController, HasMetadataForScan):
# do not use the property to avoid recursive calls
if self.__roi_counters is not None:
self.__roi_counters._check_rois_counters() # remove this line to post pone the update at next scan
self.__roi_counters._needs_update = True
self.__roi_counters._restore_rois_from_settings() # remove this line to post pone the update at next scan
if self.__roi_profiles is not None:
self.__roi_profiles._check_rois_counters() # remove this line to post pone the update at next scan
self.__roi_profiles._needs_update = True
self.__roi_profiles._restore_rois_from_settings() # remove this line to post pone the update at next scan
if self.__roi_collection is not None:
self.__roi_collection._check_rois_counters() # remove this line to post pone the update at next scan
self.__roi_collection._needs_update = True
self.__roi_collection._restore_rois_from_settings() # remove this line to post pone the update at next scan
# Expose counters
......
This diff is collapsed.
import os
import pytest
import numpy
import time
import gevent
from bliss.common.scans import ct
from bliss.controllers.lima.limatools import (
......
......@@ -20,13 +20,7 @@ from bliss.common.image_tools import draw_arc, draw_rect, array_to_file, file_to
from bliss.scanning.acquisition.timer import SoftwareTimerMaster
from bliss.common.tango import DevFailed
from bliss.common.counter import Counter
from bliss.controllers.lima.roi import (
Roi,
ArcRoi,
RoiProfile,
ROI_PROFILE_MODES,
RoiStat,
)
from bliss.controllers.lima.roi import Roi, ArcRoi, RoiProfile, ROI_PROFILE_MODES
from bliss.controllers.lima.roi import RoiProfileCounter, RoiStatCounter
from bliss.common.scans import loopscan, timescan, sct, ct, DEFAULT_CHAIN
from bliss.controllers.lima.limatools import load_simulator_frames, reset_cam
......@@ -146,7 +140,7 @@ def assert_lima_rois(simulator, rois):
assert rois == lima_rois
def test_rois(beacon, lima_simulator):
def test_rect_rois(beacon, lima_simulator):
cam = beacon.get("lima_simulator")
rois = cam.roi_counters
......@@ -221,7 +215,7 @@ def test_arc_rois(beacon, default_session, lima_simulator, images_directory):
assert asum >= _PI_ * (radius - 1) ** 2
def test_lima_roi_counters_api(beacon, default_session, lima_simulator):
def test_roi_counters_api(beacon, default_session, lima_simulator):
cam = beacon.get("lima_simulator")
cnt_per_roi = 5
......@@ -298,189 +292,7 @@ def test_lima_roi_counters_api(beacon, default_session, lima_simulator):
assert len(cam.roi_counters.counters) == 0
def test_lima_roi_counters_measurements(
beacon, default_session, lima_simulator, images_directory
):
cam = beacon.get("lima_simulator")
cam.roi_counters.clear()
img_path = os.path.join(str(images_directory), "arc.edf")
# generate test image and save as file
# arc rois
cx, cy = 250, 350
r1, r2 = 80, 100
a1, a2 = 10, 45
arry = numpy.ones((800, 600))
arry = draw_arc(arry, cx, cy, r1, r2, a1, a2, fill_value=0)
arry = draw_arc(arry, cx, cy, r1, r2, a1 + 90, a2 + 90, fill_value=0)
arry = draw_arc(arry, cx, cy, r1, r2, a1 + 180, a2 + 180, fill_value=0)
arry = draw_arc(arry, cx, cy, r1, r2, a1 + 270, a2 + 270, fill_value=0)
arry = draw_arc(arry, cx, cy, r2 + 10, r2 + 20, 10, 100, fill_value=0)
arry = draw_arc(arry, cx, cy, r2 + 30, r2 + 40, 10, 190, fill_value=0)
arry = draw_arc(arry, cx, cy, r2 + 50, r2 + 60, 10, 260, fill_value=0)
arry = draw_arc(arry, cx, cy, r2 + 70, r2 + 80, 10, 350, fill_value=0)
# rect roi
w0, h0 = 60, 30
arry = draw_rect(arry, cx, cy, w0, h0, fill_value=0)
array_to_file(arry.astype("uint32"), img_path)
# load simulator with test image
load_simulator_frames(cam, 1, img_path)
ox, oy, ow, oh = 10, 50, 500, 650
reset_cam(cam, roi=[ox, oy, ow, oh])
cx, cy = cx - ox, cy - oy # take into account the image roi offset
debug = 0
if debug:
import matplotlib.pyplot as plt
plt.imshow(file_to_array(img_path))
plt.show()
from bliss.shell.standard import flint
pf = flint()
cam.roi_counters["a1"] = cx, cy, r1, r2, a1, a2
cam.roi_counters["a2"] = cx, cy, r1, r2, a1 + 90, a2 + 90
cam.roi_counters["a3"] = cx, cy, r1, r2, a1 + 180, a2 + 180
cam.roi_counters["a4"] = cx, cy, r1, r2, a1 + 270, a2 + 270
cam.roi_counters["a5"] = cx, cy, r2 + 10, r2 + 20, 10, 100
cam.roi_counters["a6"] = cx, cy, r2 + 30, r2 + 40, 10, 190
cam.roi_counters["a7"] = cx, cy, r2 + 50, r2 + 60, 10, 260
cam.roi_counters["a8"] = cx, cy, r2 + 70, r2 + 80, 10, 350
cam.roi_counters["r1"] = cx, cy, w0, h0
s = ct(0.01, cam)
assert s.get_data("a1_sum")[0] == 0.0
assert s.get_data("a2_sum")[0] == 0.0
assert s.get_data("a3_sum")[0] == 0.0
assert s.get_data("a4_sum")[0] == 0.0
assert s.get_data("r1_sum")[0] == 0.0
if debug:
pf.wait_end_of_scans()
time.sleep(1)
def test_lima_roi_validity(beacon, default_session, lima_simulator, images_directory):
cam = beacon.get("lima_simulator")
cam.roi_counters.clear()
cam.roi_profiles.clear()
cam.roi_collection.clear()
img_path = os.path.join(str(images_directory), "arc.edf")
# generate test image and save as file
# arc rois
cx, cy = 250, 350
r1, r2 = 80, 100
a1, a2 = 10, 45
arry = numpy.ones((800, 600))
arry = draw_arc(arry, cx, cy, r1, r2, a1, a2, fill_value=0)
arry = draw_arc(arry, cx, cy, r1, r2, a1 + 90, a2 + 90, fill_value=0)
arry = draw_arc(arry, cx, cy, r1, r2, a1 + 180, a2 + 180, fill_value=0)
arry = draw_arc(arry, cx, cy, r1, r2, a1 + 270, a2 + 270, fill_value=0)
# rect roi
w0, h0 = 60, 30
arry = draw_rect(arry, cx, cy, w0, h0, fill_value=0)
# roi profile
x1, y1, w1, h1 = 500, 400, 60, 30
arry = draw_rect(arry, x1, y1, w1, h1, fill_value=0)
# roi collection
w2, h2 = 6, 4
collec = {}
nx, ny = 3, 3
for j in range(ny):
for i in range(nx):
x = i * 2 * w2 + 500
y = j * 2 * h2 + 100
arry = draw_rect(arry, x, y, w2, h2, fill_value=0)
collec[f"c{nx*j+i}"] = [x, y, w2, h2]
array_to_file(arry.astype("uint32"), img_path)
debug = 0
if debug:
import matplotlib.pyplot as plt
plt.imshow(file_to_array(img_path))
plt.show()
from bliss.shell.standard import flint
pf = flint()
# load simulator with test image
load_simulator_frames(cam, 1, img_path)
reset_cam(cam, roi=[0, 0, 0, 0])
cam.roi_counters["a1"] = cx, cy, r1, r2, a1, a2
cam.roi_counters["a2"] = cx, cy, r1, r2, a1 + 90, a2 + 90
cam.roi_counters["a3"] = cx, cy, r1, r2, a1 + 180, a2 + 180
cam.roi_counters["a4"] = cx, cy, r1, r2, a1 + 270, a2 + 270
cam.roi_counters["r1"] = cx, cy, w0, h0
cam.roi_profiles["p1"] = x1, y1, w1, h1
for k, v in collec.items():
cam.roi_collection[k] = v
assert len(list(cam.roi_counters.counters)) == 5 * 5 # because 5 counters per roi
assert len(list(cam.roi_profiles.counters)) == 1
assert len(list(cam.roi_collection.counters)) == 1 # one for the collection of rois
# applying this roi should discard 2 rois
cam.image.roi = 0, 0, 240, 500
if debug:
s = ct(0.01, cam)
pf.wait_end_of_scans()
time.sleep(1)
assert len(list(cam.roi_counters.counters)) == 2 * 5
assert len(list(cam.roi_profiles.counters)) == 0
assert (
len(list(cam.roi_collection.counters)) == 0
) # if no rois in collection then no counter
# back to full frame should re-activate the 2 rois discarde previously
cam.image.roi = 0, 0, 0, 0
if debug:
s = ct(0.01, cam)
pf.wait_end_of_scans()
time.sleep(1)
assert len(list(cam.roi_counters.counters)) == 5 * 5
assert len(list(cam.roi_profiles.counters)) == 1
assert len(list(cam.roi_collection.counters)) == 1
assert len(cam.roi_collection.get_rois()) == nx * ny
cam.roi_collection.clear()
assert len(cam.roi_collection.get_rois()) == 0
assert len(list(cam.roi_collection.counters)) == 0
cam.roi_profiles.clear()
assert len(cam.roi_profiles.get_rois()) == 0
assert len(list(cam.roi_profiles.counters)) == 0
cam.roi_counters.clear()
assert len(cam.roi_counters.get_rois()) == 0
assert len(list(cam.roi_counters.counters)) == 0
def test_lima_roi_profiles_api(beacon, default_session, lima_simulator):
def test_roi_profiles_api(beacon, default_session, lima_simulator):
cam = beacon.get("lima_simulator")
hmode = ROI_PROFILE_MODES["horizontal"].name
......@@ -581,7 +393,7 @@ def test_lima_roi_profiles_api(beacon, default_session, lima_simulator):
assert len(cam.roi_profiles.counters) == 0
def test_lima_roi_profile_measurements(
def test_roi_profiles_measurements(
beacon, default_session, lima_simulator, images_directory
):
......@@ -706,6 +518,207 @@ def test_lima_roi_profile_measurements(
assert all_equal([len(x) for x in d1])
def test_all_rois_validity(beacon, default_session, lima_simulator):
cam = beacon.get("lima_simulator")
reset_cam(cam, roi=[0, 0, 0, 0])
# arc rois
cx, cy = 250, 350
r1, r2 = 80, 100
a1, a2 = 10, 45
cam.roi_counters["a1"] = cx, cy, r1, r2, a1, a2
cam.roi_counters["a2"] = cx, cy, r1, r2, a1 + 90, a2 + 90
cam.roi_counters["a3"] = cx, cy, r1, r2, a1 + 180, a2 + 180
cam.roi_counters["a4"] = cx, cy, r1, r2, a1 + 270, a2 + 270
# rect roi
w0, h0 = 60, 30
cam.roi_counters["r1"] = cx, cy, w0, h0
# roi profile
x1, y1, w1, h1 = 500, 400, 60, 30
cam.roi_profiles["p1"] = x1, y1, w1, h1
# roi collection
w2, h2 = 6, 4
nx, ny = 3, 3
for j in range(ny):
for i in range(nx):
x = i * 2 * w2 + 500
y = j * 2 * h2 + 100
cam.roi_collection[f"c{nx*j+i}"] = [x, y, w2, h2]
assert len(list(cam.roi_counters.counters)) == 5 * 5 # because 5 counters per roi
assert len(list(cam.roi_profiles.counters)) == 1
assert len(list(cam.roi_collection.counters)) == 1 # one for the collection of rois
# applying this roi should discard 2 rois
cam.image.roi = 0, 0, 240, 500
assert len(list(cam.roi_counters.counters)) == 2 * 5
assert len(list(cam.roi_profiles.counters)) == 0
assert (
len(list(cam.roi_collection.counters)) == 0
) # if no rois in collection then no counter
# back to full frame should re-activate the 2 rois discarde previously
cam.image.roi = 0, 0, 0, 0
assert len(list(cam.roi_counters.counters)) == 5 * 5
assert len(list(cam.roi_profiles.counters)) == 1
assert len(list(cam.roi_collection.counters)) == 1
assert len(cam.roi_collection.get_rois()) == nx * ny
cam.roi_collection.clear()
assert len(cam.roi_collection.get_rois()) == 0
assert len(list(cam.roi_collection.counters)) == 0
cam.roi_profiles.clear()
assert len(cam.roi_profiles.get_rois()) == 0
assert len(list(cam.roi_profiles.counters)) == 0
cam.roi_counters.clear()
assert len(cam.roi_counters.get_rois()) == 0
assert len(list(cam.roi_counters.counters)) == 0
def test_lima_geometry_and_rois_measurements(
beacon, default_session, lima_simulator, images_directory
):
cam = beacon.get("lima_simulator")
cam.roi_counters.clear()
cam.roi_profiles.clear()
cam.roi_collection.clear()
reset_cam(cam, roi=[0, 0, 0, 0])
img = cam.image
img_path = os.path.join(str(images_directory), "testimg.edf")
arry = numpy.ones((1400, 1200))
cx, cy = 620, 720
# --- rect regions
arry = draw_rect(arry, cx, cy, 40, 10, fill_value=0)
arry = draw_rect(arry, cx, cy + 10, 40, 10, fill_value=2)
# --- arc regions (slightly larger than arc rois for binning matters)
arc_params = [
(cx, cy, 120, 140, 10, 45), # a0
(cx, cy, 160, 180, 10, 90), # a1
(cx, cy, 200, 220, 10, 180), # a2 !
(cx, cy, 240, 260, 10, 350), # a3 !
(cx, cy, 280, 300, 10, 182), # a4 !
(cx, cy, 320, 340, 100, 200), # a5
(cx, cy, 360, 380, 190, 280), # a6
(cx, cy, 400, 420, 200, 350), # a7
]
arc_rois = {}
for idx, (cx, cy, r1, r2, a1, a2) in enumerate(arc_params):
arry = draw_arc(arry, cx, cy, r1 - 4, r2 + 4, a1 - 4, a2 + 4)
arc_rois[f"a{idx}"] = cx, cy, r1, r2, a1, a2
# --- collection of rect regions
w2, h2 = 6, 4
nx, ny = 10, 10
collec = {}
for j in range(ny):
for i in range(nx):
x = i * 2 * w2 + 500
y = j * 2 * h2 + 100
arry = draw_rect(arry, x, y, w2, h2, fill_value=0)
collec[f"c{nx*j+i}"] = [x, y, w2, h2]
array_to_file(arry.astype("uint32"), img_path)
load_simulator_frames(cam, 1, img_path)
debug = 0
if debug:
import matplotlib.pyplot as plt
plt.imshow(file_to_array(img_path))
plt.show()
from bliss.shell.standard import flint
pf = flint()
# ==== measure in raw state ======
# --- rect rois
cam.roi_counters["r1"] = cx, cy, 40, 10
cam.roi_counters["r2"] = cx, cy + 10, 40, 10
# --- arc rois
for name, roi in arc_rois.items():
cam.roi_counters[name] = roi
# --- roi profiles
cam.roi_profiles["p1"] = cx, cy, 40, 20, "horizontal"
# --- roi collectio
for name, roi in collec.items():
cam.roi_collection[name] = roi
s = ct(0.001, cam)
if debug:
pf.wait_end_of_scans()
time.sleep(1)
assert s.get_data("r1_sum")[0] == 0
assert s.get_data("r2_sum")[0] == 2 * 40 * 10
assert numpy.all(s.get_data("p1")[0] == 20)
for name in arc_rois.keys():
assert s.get_data(name + "_sum")[0] == 0
assert numpy.all(s.get_data("roi_collection_counter")[0] == 0)
print("=== raw rois ==========")
print(cam.roi_counters.__info__())
# ==== test recalc on geometry changes ======
flipvals = [[False, False], [True, False], [True, True], [False, True]]
binvals = [
[1, 1],
[2, 2],
] # lima fails with bin 3,3 for rect roi at rot 90 but not for bin 4,4 !
rotvals = [0, 90, 180, 270]
for binning in binvals:
for flip in flipvals:
for rotation in rotvals:
img.set_geometry(binning, flip, rotation)
s = ct(0.01, cam)
print("=== ", binning, flip, rotation)
print(cam.roi_counters.__info__())
print(cam.roi_profiles.__info__())
print(cam.roi_collection.__info__())
assert s.get_data("r1_sum")[0] == 0
assert s.get_data("r2_sum")[0] == 2 * 40 * 10
assert numpy.all(s.get_data("p1")[0] == 20 * binning[0])
for name in arc_rois.keys():
assert s.get_data(name + "_sum")[0] == 0
assert numpy.all(s.get_data("roi_collection_counter")[0] == 0)
if debug:
pf.wait_end_of_scans()
time.sleep(1)
cam.roi_counters.clear()
cam.roi_profiles.clear()
cam.roi_collection.clear()
def test_directories_mapping(beacon, lima_simulator):
simulator = beacon.get("lima_simulator")
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment