""" Script used for parsing scan parameters from a CSV file as created by the motormap GUI. This needs to be reviewed and tested during the deployment phase.""" # pylint: skip-file import csv import os from collections import defaultdict from collections.abc import Callable from copy import deepcopy import numpy as np class ScanItem: def __init__(self, offset_xy: Callable) -> None: self.entry = None self.offset_xy = offset_xy self.split_upon_points = 8000 def to_scan_params(self) -> list[dict]: interval_x = int( np.round( np.abs(float(self.entry["X [start]"]) - float(self.entry["X [end]"])) / (float(self.entry["step_x [mu]"]) * 1e-3) ) ) interval_y = int( np.round( np.abs(float(self.entry["Y [start]"]) - float(self.entry["Y [end]"])) / (float(self.entry["step_y [mu]"]) * 1e-3) ) ) # if interval_x < 1 or interval_y < 1: # raise ValueError("Bugger off...") base_scan_params = { "start_x": float(self.entry["X [start]"]) + self.offset_xy()[0], "start_y": float(self.entry["Y [start]"]) + self.offset_xy()[1], "end_x": float(self.entry["X [end]"]) + self.offset_xy()[0], "end_y": float(self.entry["Y [end]"]) + self.offset_xy()[1], "interval_x": interval_x, "interval_y": interval_y, "exp_time": float(self.entry["exp_time [s]"]), "readout_time": 3e-3, "md": {"sample_name": self.entry["sample name"]}, # "tilt": self.entry["tilt [deg]"] } if interval_x * interval_y <= self.split_upon_points: return [base_scan_params] scan_params = [] # if we have more than 10000 points, split them along x num_blocks = int(np.ceil((interval_x * interval_y) / self.split_upon_points)) start_end_positions = np.linspace( base_scan_params["start_x"], base_scan_params["end_x"], num_blocks + 1 ) for block in range(num_blocks): block_params = deepcopy(base_scan_params) block_params["start_x"] = start_end_positions[block] block_params["end_x"] = start_end_positions[block + 1] block_params["interval_x"] = int( np.round( np.abs(block_params["start_x"] - block_params["end_x"]) / (float(self.entry["step_x [mu]"]) * 1e-3) ) ) scan_params.append(block_params) return scan_params class SAXSParams: def __init__(self, offset: Callable): self.offset_xy = offset self.data = defaultdict(lambda: ScanItem(offset)) self.global_suffix = 0 def load_from_csv(self, file_path: str) -> None: """ Load the acquisition parameter from a csv file. """ if not os.path.exists(file_path): raise FileNotFoundError( f"The specified CSV file could not be found. Please check that the given path is correct: {file_path}." ) with open(os.path.expanduser(file_path), "r") as file: csv_reader = csv.DictReader(file) for row in csv_reader: if self.data.get(row["sample name"], None) is None: self.data[row["sample name"]].entry = row else: self.data[f'{row["sample name"]}_{self.global_suffix}'].entry = row self.global_suffix += 1 if __name__ == "__main__": from pprint import pprint INPUT_FILE = "/sls/X12SA/data/e21206/Data10/software/test_script.csv" def my_offset(): return [0, 0] params = SAXSParams(my_offset) params.load_from_csv(INPUT_FILE) for key in params.data: pprint(params.data[key].to_scan_params())