DAQ/GUI: update to version 0.2.62 - changed how raster scan works so always relative to top left corner of grid. This is then corrected in the appropriate places and has been updated in the visualiser
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "aaredaqlib"
|
||||
version = "0.2.61"
|
||||
version = "0.2.62"
|
||||
description = "Libraries shared between AareDAQ and AareGUI"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
|
||||
@@ -3,15 +3,16 @@ from typing import List, Optional, Callable
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
|
||||
from aaredaqlib.models import CrystalSize
|
||||
from aaredaqlib.coordinate import Coordinate
|
||||
from aaredaqlib.models import CrystalSize, CenterOfMassModel
|
||||
from aaredaqlib.raster_grid import RasterGridRequest
|
||||
from aaredaqlib.logger_config import setup_logger
|
||||
|
||||
logger = setup_logger('aareDAQ')
|
||||
|
||||
def identify_crystal_raster(result, r: RasterGridRequest):
|
||||
def identify_crystal_raster(result, r: RasterGridRequest) -> CenterOfMassModel | None:
|
||||
images = result.images
|
||||
# if images and any(getattr(img, "spots", 0) for img in images):
|
||||
if images and any(getattr(img, "spots", 0) for img in images):
|
||||
#
|
||||
# indexed_images = [img for img in images if img.index and img.spots_low_res > 4 and img.bkg > 4.5]
|
||||
#
|
||||
@@ -35,18 +36,21 @@ def identify_crystal_raster(result, r: RasterGridRequest):
|
||||
# logger.debug(f"Maximum spots_indexed value: {max_image.spots_indexed}")
|
||||
# logger.debug(f"Maximum spots_low_res value: {max_image.spots_low_res}")
|
||||
# else:
|
||||
logger.debug(f"Find image by maximum number of low resolution spots")
|
||||
max_image = max(images, key=lambda img: img.spots_low_res)
|
||||
logger.debug(f"Image with maximum spots_low_res: {max_image}")
|
||||
logger.debug(f"Maximum spots_low_res value: {max_image.spots_low_res}")
|
||||
logger.debug(f"Maximum image found at grid coordiantes {max_image.nx}, {max_image.ny}")
|
||||
logger.debug(f"Maximum image found at umL {max_image.nx * r.grid_size_mm.x}, {max_image.ny * r.grid_size_mm.y}")
|
||||
logger.debug(f"Find image by maximum number of low resolution spots")
|
||||
max_image = max(images, key=lambda img: img.spots_low_res)
|
||||
logger.debug(f"Image with maximum spots_low_res: {max_image}")
|
||||
logger.debug(f"Maximum spots_low_res value: {max_image.spots_low_res}")
|
||||
logger.debug(f"Maximum image found at grid coordiantes {max_image.nx}, {max_image.ny}")
|
||||
logger.debug(f"Maximum image found at umL {max_image.nx * r.grid_size_mm.x}, {max_image.ny * r.grid_size_mm.y}")
|
||||
com = CenterOfMassModel(n_x=max_image.n_x, n_y=max_image.n_y)
|
||||
com_mm = com.get_com_mm(r)
|
||||
grid_mm_x = com_mm.x
|
||||
grid_mm_y = com_mm.y
|
||||
|
||||
grid_mm_x = (max_image.nx+0.5) * r.grid_size_mm.x
|
||||
grid_mm_y = (max_image.ny+0.5) * r.grid_size_mm.y
|
||||
|
||||
logger.debug(f"Grid coordinates in mm: ({grid_mm_x}, {grid_mm_y})")
|
||||
return grid_mm_x, grid_mm_y
|
||||
logger.debug(f"Grid coordinates in mm: x={grid_mm_x}, y={grid_mm_y}")
|
||||
return com
|
||||
else:
|
||||
return None
|
||||
|
||||
def rebuild_array_from_scan_results(scan_results: List,
|
||||
value_field: str,
|
||||
@@ -254,7 +258,7 @@ def get_best_res(result_list: List):
|
||||
return best_res.res
|
||||
|
||||
def com_nan_check(com):
|
||||
if np.isnan(com[0]) or np.isnan(com[1]):
|
||||
if np.isnan(com.n_x) or np.isnan(com.n_y):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -276,23 +280,15 @@ def get_com_image_number(com, images):
|
||||
logger.info(f"com found for image: {image.number}")
|
||||
return
|
||||
|
||||
def get_grid_mm_from_com(com, r:RasterGridRequest):
|
||||
if not com_nan_check(com):
|
||||
grid_mm_x = None
|
||||
grid_mm_y = None
|
||||
else:
|
||||
grid_mm_x = com[0] * r.grid_size_mm.x
|
||||
grid_mm_y = com[1] * r.grid_size_mm.y
|
||||
if r.n_x == 1:
|
||||
grid_mm_x += (0.5 * r.grid_size_mm.x)
|
||||
else:
|
||||
grid_mm_y += (0.5 * r.grid_size_mm.y)
|
||||
return grid_mm_x, grid_mm_y
|
||||
|
||||
|
||||
def raster_centre_of_mass(result_array, r:RasterGridRequest):
|
||||
def raster_centre_of_mass(result_array, r:RasterGridRequest) -> CenterOfMassModel | None:
|
||||
# grid_mm_x and grid_mm_y are relative to the top left corner of raster grid
|
||||
com = ndimage.center_of_mass(result_array)
|
||||
logger.info(f"Center of mass: {com}")
|
||||
grid_mm_x, grid_mm_y = get_grid_mm_from_com(com, r)
|
||||
return grid_mm_x, grid_mm_y, com
|
||||
if com or not com_nan_check(com):
|
||||
logger.info(f"Center of mass: {com}")
|
||||
return CenterOfMassModel(n_x=com[0], n_y=com[1])
|
||||
else:
|
||||
logger.warning("No valid center of mass found")
|
||||
return None
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@ import re
|
||||
from enum import Enum
|
||||
from typing import Annotated, Literal, Tuple, List, Optional
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
import numpy as np
|
||||
from pydantic import BaseModel, Field, field_validator, AfterValidator
|
||||
|
||||
from aaredaqlib.coordinate import Coordinate
|
||||
from aaredaqlib.coordinate import Coordinate, positive_coords
|
||||
from aaredaqlib.diffraction_geometry import DiffractionGeometry
|
||||
from aaredaqlib.raster_grid import RasterGridRequest
|
||||
from aaredaqlib.sample_geometry import SampleGeometryModel
|
||||
from jfjoch_client.models.scan_result import ScanResult
|
||||
|
||||
from aaredaqlib.beamline import MXBeamline
|
||||
|
||||
@@ -776,4 +779,37 @@ class SimpleScanParameters(BaseModel):
|
||||
beam_size_y_um: float | None = None
|
||||
dose_rate_MGy_s: float | None = None
|
||||
d_vis: float | None = None
|
||||
d_tar: float | None = None
|
||||
d_tar: float | None = None
|
||||
|
||||
class RasterPayloadModel(BaseModel):
|
||||
request: RasterGridRequest
|
||||
result: ScanResult
|
||||
sample_id: int
|
||||
attach_image: bool = True
|
||||
center_pxl: Coordinate | None
|
||||
start_pxl: Coordinate
|
||||
cell_size_pxl: Annotated[Coordinate, AfterValidator(positive_coords)]
|
||||
|
||||
class CenterOfMassModel(BaseModel):
|
||||
n_x: float
|
||||
n_y: float
|
||||
|
||||
@classmethod
|
||||
def model_validate_maybe(cls, n_x: float, n_y: float) -> "CenterOfMassModel | None":
|
||||
# Return None if either coordinate is NaN
|
||||
if np.isnan(n_x) or np.isnan(n_y):
|
||||
return None
|
||||
return cls(n_x=float(n_x), n_y=float(n_y))
|
||||
|
||||
def get_com_mm(self, r:RasterGridRequest) -> Coordinate:
|
||||
#defines COM in mm at beam position, relative to the top left corner of grid
|
||||
return Coordinate(x=(self.n_x+0.5)*r.grid_size_mm.x, y=(self.n_y+0.5)*r.grid_size_mm.y)
|
||||
|
||||
def get_com_pxl(self, r:RasterGridRequest, geom:SampleGeometryModel) -> Coordinate:
|
||||
#defines COM in pixels at beam position, relative to the top left corner of grid
|
||||
com_mm = self.get_com_mm(r)
|
||||
return Coordinate(x=com_mm.x/geom.pixel_in_mm, y=com_mm.y/geom.pixel_in_mm)
|
||||
|
||||
def com_nan_check(self):
|
||||
# True if both values are finite (not NaN)
|
||||
return not (np.isnan(self.n_x) or np.isnan(self.n_y))
|
||||
@@ -20,8 +20,9 @@ class RasterGridRequest(BaseModel):
|
||||
# Size of grid elements
|
||||
grid_size_mm: Annotated[Coordinate, AfterValidator(positive_coords)]
|
||||
|
||||
# Coordinates of top left corner in Smargon (SH...) coordinates
|
||||
smargon: SmargonCoordinate
|
||||
# Coordinates of top left corner in Smargon (SH...) coordinates.
|
||||
# If None, measure from the current position.
|
||||
smargon_top_left: SmargonCoordinate | None
|
||||
|
||||
# omega angle
|
||||
omega_deg: float = 0.0
|
||||
@@ -35,7 +36,9 @@ class RasterGridRequest(BaseModel):
|
||||
return self.grid_size_mm / geom.pixel_in_mm
|
||||
|
||||
def start_pxl(self, geom: SampleGeometryModel) -> Coordinate:
|
||||
return geom.smargon_to_beamline(self.smargon.sh_mm)
|
||||
if self.smargon_top_left is None:
|
||||
return geom.smargon_to_beamline(geom.smargon.sh_mm)
|
||||
return geom.smargon_to_beamline(self.smargon_top_left.sh_mm)
|
||||
|
||||
class CompletedRasterGridElem(BaseModel):
|
||||
request: RasterGridRequest
|
||||
|
||||
@@ -44,6 +44,11 @@ class SampleGeometryModel(BaseModel):
|
||||
beam_pxl = (beam_mm - self.aerotech) / self.pixel_in_mm
|
||||
return beam_pxl + self.beam_location_pxl
|
||||
|
||||
def translate_smargon(self, coord: Coordinate) -> SmargonCoordinate:
|
||||
return SmargonCoordinate(sh_mm=self.smargon.sh_mm + self.smargon_nudge(coord),
|
||||
phi_deg=self.smargon.phi_deg,
|
||||
chi_deg=self.smargon.chi_deg)
|
||||
|
||||
def smargon_nudge(self, coord: Coordinate) -> Coordinate:
|
||||
phi = np.radians(np.around(self.smargon.phi_deg, decimals=1))
|
||||
chi = np.radians(np.around(self.smargon.chi_deg, decimals=1))
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "aaredaq"
|
||||
version = "0.2.61"
|
||||
version = "0.2.62"
|
||||
description = "AareDAQ data acquisition server"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
@@ -18,7 +18,7 @@ dependencies = [
|
||||
"python_multipart==0.0.20",
|
||||
"websocket-client==1.8.0",
|
||||
"sseclient-py==1.8.0",
|
||||
"aaredaqlib==0.2.4",
|
||||
"aaredaqlib==0.2.62",
|
||||
]
|
||||
|
||||
[lint]
|
||||
|
||||
+25
-29
@@ -21,6 +21,7 @@ from aareDBclient import (
|
||||
BeamlineParametersInput,
|
||||
ExperimentParametersCreate)
|
||||
|
||||
from aaredaqlib.coordinate import Coordinate
|
||||
from aaredaqlib.diffraction_geometry import DiffractionGeometry
|
||||
from aaredaqlib.logger_config import setup_logger
|
||||
from aaredaqlib.models import (
|
||||
@@ -28,7 +29,7 @@ from aaredaqlib.models import (
|
||||
PuckLoadedInfo,
|
||||
DewarAddress,
|
||||
SampleShortInfoList,
|
||||
DAQStatusModel, SessionStatus,
|
||||
DAQStatusModel, SessionStatus, RasterPayloadModel, CenterOfMassModel,
|
||||
)
|
||||
|
||||
from aaredaqlib.beamline import MXBeamline
|
||||
@@ -339,28 +340,13 @@ class AareWrapper:
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
def _create_default_geometry(self):
|
||||
"""Create default geometry configuration for raster grid ingestion."""
|
||||
return {
|
||||
'beam_location_pxl': {'x': 512, 'y': 384, 'z': 0},
|
||||
'pixel_in_mm': 0.01,
|
||||
'aerotech': {'x': 0, 'y': 0, 'z': 0},
|
||||
'aerotech_meas': {'x': 0, 'y': 0, 'z': 0},
|
||||
'smargon': {
|
||||
'sh_mm': {'x': 0, 'y': 0, 'z': 0},
|
||||
'phi_deg': 0,
|
||||
'chi_deg': 0
|
||||
},
|
||||
'omega_deg': 0,
|
||||
'beam_size_mm': {'x': 0.02, 'y': 0.02, 'z': 0},
|
||||
}
|
||||
def ingest_gridscan(self, sample: Optional[SampleShortInfo], raster_result: ScanResult,
|
||||
raster_request: RasterGridRequest, geom: SampleGeometryModel, com: Optional[CenterOfMassModel]):
|
||||
|
||||
def ingest_gridscan(self, s: Optional[SampleShortInfo], raster_result: ScanResult, r: RasterGridRequest):
|
||||
|
||||
if s is None:
|
||||
if sample is None:
|
||||
return
|
||||
|
||||
payload = self.format_gridscan_payload(s, raster_result, r)
|
||||
payload = self.format_gridscan_payload(sample, raster_result, raster_request, geom, com).model_dump()
|
||||
|
||||
if payload is None:
|
||||
return
|
||||
@@ -378,19 +364,29 @@ class AareWrapper:
|
||||
print(f"Response status code: {response.status_code}")
|
||||
|
||||
|
||||
def format_gridscan_payload(self, s: Optional[SampleShortInfo], raster_result:ScanResult, r:RasterGridRequest):
|
||||
def format_gridscan_payload(self, sample: Optional[SampleShortInfo], raster_result:ScanResult,
|
||||
raster_request:RasterGridRequest, geom:SampleGeometryModel,
|
||||
com: Optional[CenterOfMassModel]) -> RasterPayloadModel|None:
|
||||
|
||||
try:
|
||||
|
||||
geometry = self._create_default_geometry()
|
||||
if com:
|
||||
center_pxl = com.get_com_pxl(raster_request, geom)
|
||||
else:
|
||||
center_pxl = None
|
||||
|
||||
payload = {
|
||||
"request": r.model_dump(), # RasterGridRequest as dict
|
||||
"result": raster_result.model_dump(), # ScanResult as dict
|
||||
"geometry": geometry, # SampleGeometryModel as dict
|
||||
"sample_id": s.db_id,
|
||||
"attach_image": True,
|
||||
}
|
||||
cell_size_pxl = Coordinate(x=raster_request.grid_size_mm.x/geom.pixel_in_mm,
|
||||
y=raster_request.grid_size_mm.y/geom.pixel_in_mm)
|
||||
|
||||
payload = RasterPayloadModel(
|
||||
request = raster_request,
|
||||
result = raster_result,
|
||||
sample_id = sample.db_id,
|
||||
attach_image = True,
|
||||
start_pxl = raster_request.start_pxl(geom),
|
||||
center_pxl = center_pxl,
|
||||
cell_size_pxl = cell_size_pxl
|
||||
)
|
||||
|
||||
return payload
|
||||
|
||||
|
||||
+45
-44
@@ -468,7 +468,7 @@ class AareDAQ:
|
||||
|
||||
if r is not None:
|
||||
geom = self.sample_geometry
|
||||
grid.smargon = r.smargon
|
||||
grid.smargon_top_left = r.smargon_top_left
|
||||
grid.grid_size_mm = r.grid_size_mm
|
||||
grid.n_x = r.n_x
|
||||
grid.n_y = r.n_y
|
||||
@@ -488,9 +488,11 @@ class AareDAQ:
|
||||
grid.n_y = 50
|
||||
grid.file_prefix = f"{old_prefix}_{grid.omega_deg}deg"
|
||||
grid.grid_size_mm = Coordinate(x=geom.beam_size_mm.x, y=geom.beam_size_mm.y * 0.25)
|
||||
offset = Coordinate(x=0, y=-grid.n_y * grid.grid_size_mm.y / 2.0)
|
||||
offset = Coordinate(x=-grid.grid_size_mm.x/2.0, y=-(grid.n_y + 0.5) * grid.grid_size_mm.y / 2.0)
|
||||
geom = self.sample_geometry
|
||||
grid.smargon.sh_mm = geom.smargon.sh_mm + geom.smargon_nudge(offset)
|
||||
logger.debug(f"set offset y scan {offset}")
|
||||
# self.__devs.smargon.target = geom.translate_smargon(offset)
|
||||
grid.smargon_top_left = geom.translate_smargon(offset)
|
||||
res2 = self.__raster(grid)
|
||||
self.__devs.reflector_up = True
|
||||
time.sleep(0.1)
|
||||
@@ -502,7 +504,7 @@ class AareDAQ:
|
||||
return None
|
||||
|
||||
|
||||
def __raster(self, r: RasterGridRequest, corner_coord: bool) -> CompletedRasterGridElem:
|
||||
def __raster(self, r: RasterGridRequest) -> CompletedRasterGridElem:
|
||||
max_time = r.exp_time_s * r.n_y * r.n_x + 60
|
||||
|
||||
if r.dtz is not None:
|
||||
@@ -511,12 +513,12 @@ class AareDAQ:
|
||||
self.__set_state(BeamlineStateEnum.DataCollection)
|
||||
|
||||
save_smargon_position = self.__devs.smargon.readback
|
||||
if r.smargon_top_left is not None:
|
||||
delta_mm = self.sample_geometry.smargon_nudge(Coordinate(x=r.grid_size_mm.x / 2, y=r.grid_size_mm.y / 2))
|
||||
|
||||
delta_mm = self.sample_geometry.smargon_nudge(Coordinate(x=r.grid_size_mm.x / 2, y=r.grid_size_mm.y / 2))
|
||||
|
||||
self.__devs.smargon.target = SmargonCoordinate(sh_mm=r.smargon.sh_mm + delta_mm,
|
||||
phi_deg=r.smargon.phi_deg,
|
||||
chi_deg=r.smargon.chi_deg)
|
||||
self.__devs.smargon.target = SmargonCoordinate(sh_mm=r.smargon_top_left.sh_mm + delta_mm,
|
||||
phi_deg=r.smargon_top_left.phi_deg,
|
||||
chi_deg=r.smargon_top_left.chi_deg)
|
||||
if r.transmission is not None:
|
||||
self.__devs.transmission.set(r.transmission, wait=False)
|
||||
self.__devs.aerotech.move(r.omega_deg, wait=True, speed=360.0)
|
||||
@@ -543,59 +545,58 @@ class AareDAQ:
|
||||
self.__devs.abr_pos = self.__cfg.abr_meas_pos
|
||||
result = self.__jfjoch.wait_till_done(60)
|
||||
|
||||
if self.sample is not None and self.sample.db_id is not None and result is not None:
|
||||
try:
|
||||
self.__aare.ingest_gridscan(self.sample, result, r)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception ingesting grid scan: {e}")
|
||||
|
||||
images = result.images
|
||||
output_data = {
|
||||
'timestamp': time.ctime(),
|
||||
'scan_results': [image.model_dump() for image in images],
|
||||
'total_results': len([image for image in images])
|
||||
}
|
||||
if self.sample is not None and self.sample.db_id is not None:
|
||||
if r.n_x == 1:
|
||||
filename=f'/sls/MX/applications/raster_results/{self.sample.db_id}_scan_results_vertical.json'
|
||||
else:
|
||||
filename=f'/sls/MX/applications/raster_results/{self.sample.db_id}_scan_results_horizontal.json'
|
||||
with open(filename, 'w') as f:
|
||||
json.dump(output_data, f, indent=2)
|
||||
|
||||
result_array = create_quality_filtered_array(images, 'spots_low_res', min_spots=None,
|
||||
min_efficiency=1.0, min_background=None, min_low_res_spots=None)
|
||||
self.__cfg.crystal_size = get_xtal_size(self.__cfg.crystal_size, result_array, r)
|
||||
grid_mm_x, grid_mm_y, com = raster_centre_of_mass(result_array, r)
|
||||
|
||||
if grid_mm_x is None or grid_mm_y is None or com is None:
|
||||
com = raster_centre_of_mass(result_array, r)
|
||||
if com is None:
|
||||
logger.debug(f"using old method as COM is disabled")
|
||||
grid_mm_x, grid_mm_y = identify_crystal_raster(result, r)
|
||||
com = identify_crystal_raster(result, r)
|
||||
if com:
|
||||
com_mm = com.get_com_mm(r)
|
||||
grid_mm_x = com_mm.x
|
||||
grid_mm_y = com_mm.y
|
||||
else:
|
||||
grid_mm_x = None
|
||||
grid_mm_y = None
|
||||
|
||||
if grid_mm_x or grid_mm_y:
|
||||
|
||||
if r.n_x == 1:
|
||||
new_delta_mm = self.sample_geometry.smargon_nudge(Coordinate(x=grid_mm_x, y=grid_mm_y))
|
||||
new_delta_mm = self.sample_geometry.smargon_nudge(Coordinate(x=grid_mm_x, y=grid_mm_y))
|
||||
|
||||
else:
|
||||
if r.n_x != 1:
|
||||
result_list = get_result_list_from_com(images, com)
|
||||
self.__cfg.last_best_b_factor = get_best_b_factor(result_list)
|
||||
self.__cfg.last_best_res = get_best_res(result_list)
|
||||
logger.debug(f"b_factor: {self.__cfg.last_best_b_factor}, best_res: {self.__cfg.last_best_res}")
|
||||
new_delta_mm = self.sample_geometry.smargon_nudge(Coordinate(x=grid_mm_x, y=grid_mm_y))
|
||||
|
||||
else:
|
||||
new_delta_mm = None
|
||||
|
||||
if new_delta_mm is not None:
|
||||
logger.debug(f'{time.ctime()}, moving SMARGON to target new delta mm {r.smargon.sh_mm + new_delta_mm} mm')
|
||||
self.__devs.smargon.target = SmargonCoordinate(sh_mm=r.smargon.sh_mm + new_delta_mm,
|
||||
phi_deg=r.smargon.phi_deg,
|
||||
chi_deg=r.smargon.chi_deg)
|
||||
if r.smargon_top_left:
|
||||
new_target = r.smargon_top_left
|
||||
else:
|
||||
new_target = save_smargon_position
|
||||
|
||||
logger.debug(f'moving SMARGON to target new delta mm {new_target.sh_mm + new_delta_mm} mm')
|
||||
self.__devs.smargon.target = SmargonCoordinate(sh_mm=new_target.sh_mm + new_delta_mm,
|
||||
phi_deg=new_target.phi_deg,
|
||||
chi_deg=new_target.chi_deg)
|
||||
else:
|
||||
logger.error("Auto finding optimal image failed due to no images found. Using previous position.")
|
||||
self.__devs.smargon.target = save_smargon_position
|
||||
|
||||
if self.sample is not None and self.sample.db_id is not None and result is not None:
|
||||
try:
|
||||
self.__aare.ingest_gridscan(sample = self.sample, raster_result =result,
|
||||
raster_request = r, geom = self.sample_geometry,
|
||||
com = com)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception ingesting grid scan: {e}")
|
||||
|
||||
return CompletedRasterGridElem(request=copy.deepcopy(r), result=result)
|
||||
|
||||
def measure_raster(self, r: RasterGridRequest, auto: bool) -> CompletedRasterGrid:
|
||||
@@ -604,7 +605,7 @@ class AareDAQ:
|
||||
if auto:
|
||||
result = self.__auto_center(r)
|
||||
else:
|
||||
raster_result = self.__raster(r, True)
|
||||
raster_result = self.__raster(r)
|
||||
result = CompletedRasterGrid(r=[raster_result])
|
||||
self.__devs.reflector_up = True
|
||||
time.sleep(0.1)
|
||||
@@ -878,7 +879,7 @@ class AareDAQ:
|
||||
return RasterGridRequest(
|
||||
exp_time_s=0.02,
|
||||
transmission=1.0,
|
||||
smargon= SmargonCoordinate(chi_deg = geom.smargon.chi_deg,
|
||||
smargon_top_left = SmargonCoordinate(chi_deg = geom.smargon.chi_deg,
|
||||
phi_deg= geom.smargon.phi_deg,
|
||||
sh_mm=start_coord),
|
||||
n_x=n_x,
|
||||
@@ -1354,7 +1355,7 @@ class AareDAQ:
|
||||
if self.__auto_center(RasterGridRequest(
|
||||
exp_time_s=raster_params.exp_time_s,
|
||||
file_prefix=sample_prefix + f"_{hex_string}",
|
||||
smargon= SmargonCoordinate(),
|
||||
smargon_top_left= SmargonCoordinate(),
|
||||
n_x=1,
|
||||
n_y=1,
|
||||
dtz=raster_params.dtz,
|
||||
@@ -1383,14 +1384,14 @@ class AareDAQ:
|
||||
))
|
||||
logger.info(f"rotation done at {time.perf_counter() - start}")
|
||||
else:
|
||||
print("auto center failed")
|
||||
logger.error("auto center failed")
|
||||
self.__aare.axc_failed(sample)
|
||||
self.zoom = 1
|
||||
self.__cfg.zoom_mode = ZoomModeEnum.User
|
||||
self.__devs.samcam_settings = self.__cfg.zoom_settings.get_camera_settings(self.zoom)
|
||||
self.__cfg.state_busy = False
|
||||
except Exception as e:
|
||||
print(f"Error in measure: {e}")
|
||||
logger.error(f"Error in measure: {e}")
|
||||
self.__aare.sample_failed(sample)
|
||||
self.__cfg.state_busy = False
|
||||
end = time.perf_counter()
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "aaregui"
|
||||
version = "0.2.4"
|
||||
version = "0.2.62"
|
||||
description = "Beamline control GUI"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
@@ -9,7 +9,7 @@ dependencies = [
|
||||
"pyzmq==26.4.0",
|
||||
"opencv-python-headless==4.11.0.86",
|
||||
"PySide6==6.9.0",
|
||||
"aaredaqlib==0.2.4"
|
||||
"aaredaqlib==0.2.62"
|
||||
]
|
||||
|
||||
[lint]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from PySide6.QtCore import Signal, Slot, Qt
|
||||
from PySide6.QtWidgets import QFrame, QVBoxLayout, QHBoxLayout, QPushButton, QHeaderView, QSizePolicy, \
|
||||
QTableView
|
||||
QTableView, QMessageBox
|
||||
from PySide6.QtGui import QKeySequence, QShortcut
|
||||
from aaredaqlib.models import SampleShortInfoList, SampleShortInfo
|
||||
|
||||
@@ -92,8 +92,29 @@ class SampleQueuePanel(QFrame):
|
||||
sample = self.table_model.samples[row]
|
||||
self.table_model.remove_sample(sample.db_id)
|
||||
|
||||
def __ring_current_low_check(self) -> bool:
|
||||
if self.ring_current is not None and self.ring_current < 100:
|
||||
logger.debug(f"Ring current too low {self.ring_current}")
|
||||
self.table_model.set_running(False)
|
||||
self.set_to_pause = True
|
||||
self.__pause = True
|
||||
self.play_button.setText("▶ Run")
|
||||
reply = QMessageBox.question(self, "Ring current too low", f"Ring current is too low: {self.ring_current} mA. Do you wish to continue?",
|
||||
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
|
||||
QMessageBox.StandardButton.No)
|
||||
if reply == QMessageBox.StandardButton.Yes:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
logger.debug(f"Ring current: {self.ring_current}")
|
||||
return True
|
||||
|
||||
def run(self):
|
||||
if self.__pause:
|
||||
if not self.__ring_current_low_check():
|
||||
logger.debug("low ring current, skipping")
|
||||
return
|
||||
|
||||
elif self.__pause:
|
||||
if len(self.table_model.samples) > 0:
|
||||
self.table_model.set_running(True)
|
||||
self.__set_to_pause = False
|
||||
@@ -120,11 +141,9 @@ class SampleQueuePanel(QFrame):
|
||||
if self._current_db_id is not None and db_id != self._current_db_id:
|
||||
return
|
||||
|
||||
if self.ring_current is not None and self.ring_current < 100:
|
||||
self.table_model.set_running(False)
|
||||
self.__pause = True
|
||||
self.play_button.setText("▶ Run")
|
||||
|
||||
if not self.__ring_current_low_check():
|
||||
self.unmount.emit()
|
||||
return
|
||||
|
||||
if success:
|
||||
self.table_model.remove_sample(db_id)
|
||||
|
||||
@@ -104,7 +104,7 @@ class RasterGridManager(QObject):
|
||||
self.__active_grid : RasterGridRequest = RasterGridRequest(
|
||||
n_x= 0,
|
||||
n_y= 0,
|
||||
smargon = self.__geom.smargon,
|
||||
smargon_top_left = self.__geom.smargon,
|
||||
grid_size_mm=Coordinate(x= 0.8 * self.__beam_size_mm.x,
|
||||
y= 0.8 * self.__beam_size_mm.y),
|
||||
omega_deg=self.__geom.omega_deg,
|
||||
@@ -122,8 +122,8 @@ class RasterGridManager(QObject):
|
||||
if (
|
||||
grid.visible
|
||||
and abs(normalize_angle(grid.omega_deg - self.__geom.omega_deg)) < 0.2
|
||||
and abs(grid.smargon.phi_deg - self.__geom.smargon.phi_deg) < 0.2
|
||||
and abs(grid.smargon.chi_deg - self.__geom.smargon.chi_deg) < 0.2
|
||||
and abs(grid.smargon_top_left.phi_deg - self.__geom.smargon.phi_deg) < 0.2
|
||||
and abs(grid.smargon_top_left.chi_deg - self.__geom.smargon.chi_deg) < 0.2
|
||||
and grid.n_x > 0
|
||||
and grid.n_y > 0
|
||||
):
|
||||
@@ -132,7 +132,7 @@ class RasterGridManager(QObject):
|
||||
|
||||
@Slot(RasterGridRequest)
|
||||
def update_active_grid_request(self, grid: RasterGridRequest):
|
||||
self.__active_grid.smargon = grid.smargon
|
||||
self.__active_grid.smargon_top_left = grid.smargon_top_left
|
||||
self.__active_grid.omega_deg = grid.omega_deg
|
||||
self.__active_grid.grid_size_mm = grid.grid_size_mm
|
||||
self.__active_grid.n_x = grid.n_x
|
||||
@@ -176,7 +176,7 @@ class RasterGridManager(QObject):
|
||||
else:
|
||||
self.__start_point = start
|
||||
|
||||
self.__active_grid.smargon = SmargonCoordinate(
|
||||
self.__active_grid.smargon_top_left = SmargonCoordinate(
|
||||
sh_mm=self.__geom.beamline_to_smargon(c),
|
||||
phi_deg=self.__geom.smargon.phi_deg,
|
||||
chi_deg=self.__geom.smargon.chi_deg,
|
||||
@@ -196,8 +196,8 @@ class RasterGridManager(QObject):
|
||||
|
||||
delta_mm = self.__geom.smargon_nudge(delta_pxl * self.__geom.pixel_in_mm)
|
||||
|
||||
self.__active_grid.smargon = SmargonCoordinate(
|
||||
sh_mm=self.__active_grid.smargon.sh_mm + delta_mm,
|
||||
self.__active_grid.smargon_top_left = SmargonCoordinate(
|
||||
sh_mm=self.__active_grid.smargon_top_left.sh_mm + delta_mm,
|
||||
phi_deg=self.__geom.smargon.phi_deg,
|
||||
chi_deg=self.__geom.smargon.chi_deg,
|
||||
)
|
||||
@@ -213,7 +213,7 @@ class RasterGridManager(QObject):
|
||||
def get_grid_coord(self, grid: RasterGridRequest, point: QPointF) -> Tuple[int, int]:
|
||||
point_bl = self.__geom.picture_to_sample(Coordinate(x=point.x(), y=point.y()))
|
||||
|
||||
delta = point_bl - self.__geom.smargon_to_beamline(grid.smargon.sh_mm)
|
||||
delta = point_bl - self.__geom.smargon_to_beamline(grid.smargon_top_left.sh_mm)
|
||||
|
||||
elem_x = grid.grid_size_mm.x
|
||||
elem_y = grid.grid_size_mm.y
|
||||
@@ -247,7 +247,7 @@ class RasterGridManager(QObject):
|
||||
return False
|
||||
point_bl = self.__geom.picture_to_sample(Coordinate(x=point.x(), y=point.y()))
|
||||
|
||||
delta = point_bl - self.__geom.smargon_to_beamline(self.__active_grid.smargon.sh_mm)
|
||||
delta = point_bl - self.__geom.smargon_to_beamline(self.__active_grid.smargon_top_left.sh_mm)
|
||||
return (0 <= delta.x < self.__active_grid.n_x * self.__active_grid.grid_size_mm.x) and (
|
||||
0 <= delta.y < self.__active_grid.n_y * self.__active_grid.grid_size_mm.y
|
||||
)
|
||||
@@ -319,10 +319,10 @@ class RasterGridManager(QObject):
|
||||
n_x=ag.n_x,
|
||||
n_y=ag.n_y,
|
||||
grid_size_mm=Coordinate(x=ag.grid_size_mm.x, y=ag.grid_size_mm.y),
|
||||
smargon=SmargonCoordinate(
|
||||
sh_mm=Coordinate(x=ag.smargon.sh_mm.x, y=ag.smargon.sh_mm.y, z=ag.smargon.sh_mm.z),
|
||||
phi_deg=ag.smargon.phi_deg,
|
||||
chi_deg=ag.smargon.chi_deg,
|
||||
smargon_top_left=SmargonCoordinate(
|
||||
sh_mm=Coordinate(x=ag.smargon_top_left.sh_mm.x, y=ag.smargon_top_left.sh_mm.y, z=ag.smargon_top_left.sh_mm.z),
|
||||
phi_deg=ag.smargon_top_left.phi_deg,
|
||||
chi_deg=ag.smargon_top_left.chi_deg,
|
||||
),
|
||||
omega_deg=ag.omega_deg,
|
||||
visible=ag.visible,
|
||||
@@ -341,10 +341,10 @@ class RasterGridManager(QObject):
|
||||
n_x=ag.n_x,
|
||||
n_y=ag.n_y,
|
||||
grid_size_mm=Coordinate(x=ag.grid_size_mm.x, y=ag.grid_size_mm.y),
|
||||
smargon=SmargonCoordinate(
|
||||
sh_mm=Coordinate(x=ag.smargon.sh_mm.x, y=ag.smargon.sh_mm.y, z=ag.smargon.sh_mm.z),
|
||||
phi_deg=ag.smargon.phi_deg,
|
||||
chi_deg=ag.smargon.chi_deg,
|
||||
smargon_top_left=SmargonCoordinate(
|
||||
sh_mm=Coordinate(x=ag.smargon_top_left.sh_mm.x, y=ag.smargon_top_left.sh_mm.y, z=ag.smargon_top_left.sh_mm.z),
|
||||
phi_deg=ag.smargon_top_left.phi_deg,
|
||||
chi_deg=ag.smargon_top_left.chi_deg,
|
||||
),
|
||||
omega_deg=ag.omega_deg,
|
||||
visible=ag.visible,
|
||||
@@ -474,8 +474,8 @@ class RasterGridManager(QObject):
|
||||
if 0 <= row < len(self.__completed_grids):
|
||||
self.omega.emit(self.__completed_grids[row].request.omega_deg)
|
||||
self.smargon.emit(SmargonCoordinate(
|
||||
phi_deg=self.__completed_grids[row].request.smargon.phi_deg,
|
||||
chi_deg=self.__completed_grids[row].request.smargon.chi_deg,
|
||||
phi_deg=self.__completed_grids[row].request.smargon_top_left.phi_deg,
|
||||
chi_deg=self.__completed_grids[row].request.smargon_top_left.chi_deg,
|
||||
))
|
||||
|
||||
@Slot(int)
|
||||
@@ -485,10 +485,10 @@ class RasterGridManager(QObject):
|
||||
self.__active_grid.n_x = src.n_x
|
||||
self.__active_grid.n_y = src.n_y
|
||||
self.__active_grid.grid_size_mm = Coordinate(x=src.grid_size_mm.x, y=src.grid_size_mm.y)
|
||||
self.__active_grid.smargon = SmargonCoordinate(
|
||||
sh_mm=Coordinate(x=src.smargon.sh_mm.x, y=src.smargon.sh_mm.y, z=src.smargon.sh_mm.z),
|
||||
phi_deg=src.smargon.phi_deg,
|
||||
chi_deg=src.smargon.chi_deg,
|
||||
self.__active_grid.smargon_top_left = SmargonCoordinate(
|
||||
sh_mm=Coordinate(x=src.smargon_top_left.sh_mm.x, y=src.smargon_top_left.sh_mm.y, z=src.smargon_top_left.sh_mm.z),
|
||||
phi_deg=src.smargon_top_left.phi_deg,
|
||||
chi_deg=src.smargon_top_left.chi_deg,
|
||||
)
|
||||
self.__active_grid.omega_deg = src.omega_deg
|
||||
|
||||
|
||||
@@ -45,8 +45,8 @@ class RasterGridTable(QTableWidget):
|
||||
|
||||
# Add data cells
|
||||
self.setItem(row_position, 0, QTableWidgetItem(f"{req.omega_deg:.1f}"))
|
||||
self.setItem(row_position, 1, QTableWidgetItem(f"{req.smargon.chi_deg:.1f}"))
|
||||
self.setItem(row_position, 2, QTableWidgetItem(f"{req.smargon.phi_deg:.1f}"))
|
||||
self.setItem(row_position, 1, QTableWidgetItem(f"{req.smargon_top_left.chi_deg:.1f}"))
|
||||
self.setItem(row_position, 2, QTableWidgetItem(f"{req.smargon_top_left.phi_deg:.1f}"))
|
||||
self.setItem(row_position, 3, QTableWidgetItem(f"{req.n_x} x {req.n_y}"))
|
||||
|
||||
# Add action buttons
|
||||
|
||||
Reference in New Issue
Block a user