import csv import os from collections import defaultdict from collections.abc import Callable import numpy as np class ScanItem: def __init__(self, offset_xy: Callable) -> None: self.start_entry = None self.end_entry = None self.offset_xy = offset_xy def to_scan_params(self) -> dict: scan_params = { "start_x": float(self.start_entry["X"]) + self.offset_xy()[0], "start_y": float(self.start_entry["Y"]) + self.offset_xy()[1], "end_x": float(self.end_entry["X"]) + self.offset_xy()[0], "end_y": float(self.end_entry["Y"]) + self.offset_xy()[1], "interval_x": int( np.round( np.abs(float(self.start_entry["X"]) - float(self.end_entry["X"])) / (float(self.start_entry["step_x [mu]"]) * 1e-3) ) ), "interval_y": int( np.round( np.abs(float(self.start_entry["Y"]) - float(self.end_entry["Y"])) / (float(self.start_entry["step_y [mu]"]) * 1e-3) ) ), "exp_time": float(self.start_entry["exp_time [s]"]), "readout_time": 3e-3, "md": {"sample_name": self.start_entry["sample name"]}, } if scan_params["interval_x"] < 1 or scan_params["interval_x"] < 1: raise ValueError("Bugger off...") return scan_params class SAXSParams: def __init__(self, offset: Callable): self.offset_xy = offset self.data = defaultdict(lambda: ScanItem(offset)) 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}." ) data_transposed = defaultdict(lambda: []) with open(os.path.expanduser(file_path), "r") as file: csv_reader = csv.DictReader(file) for row in csv_reader: for key, val in row.items(): data_transposed[key].append(val) if int(row["start"]): self.data[row["sample name"]].start_entry = row else: self.data[row["sample name"]].end_entry = row self._check_params(dict(data_transposed)) def _check_params(self, data_transposed: dict) -> dict: sample_names = set(data_transposed["sample name"]) if len(data_transposed["start"]) != len(sample_names) * 2: raise ValueError( f"The given params file does not provide N*2 start/stop positions. Found {len(sample_names)} samples and {len(data_transposed['start'])} start/stop positions." ) 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())