diff --git a/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py b/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py index 053fed0..693f9b9 100644 --- a/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py +++ b/csaxs_bec/bec_ipython_client/plugins/LamNI/x_ray_eye_align.py @@ -525,6 +525,7 @@ class LamNI(LamNIOpticsMixin): self._beam_is_okay = True self._stop_beam_check_event = None self.beam_check_thread = None + self.progress = {} def get_beamline_checks_enabled(self): print( @@ -587,6 +588,27 @@ class LamNI(LamNIOpticsMixin): def tomo_circfov(self, val: float): self.client.set_global_var("tomo_circfov", val) + @property + def tomo_type(self): + val = self.client.get_global_var("tomo_type") + if val is None: + return 1 + return val + + @tomo_type.setter + def tomo_type(self, val: float): + if val == 1: + # equally spaced tomography with 8 sub tomograms + self.client.set_global_var("tomo_type", val) + #elif val == 2: + # # golden ratio tomography (sorted bunches) + # self.client.set_global_var("tomo_type", val) + #elif val == 3: + # # equally spaced tomography with starting angles shifted by golden ratio + # self.client.set_global_var("tomo_type", val) + else: + raise ValueError("Unknown tomo_type.") + @property def tomo_countingtime(self): val = self.client.get_global_var("tomo_countingtime") @@ -949,47 +971,73 @@ class LamNI(LamNIOpticsMixin): # _tomo_shift_angles (potential global variable) _tomo_shift_angles = 0 angle_end = start_angle + 360 - for angle in np.linspace( + angles = np.linspace( start_angle + _tomo_shift_angles, angle_end, num=int(360 / self.tomo_angle_stepsize) + 1, endpoint=True, - ): - successful = False - error_caught = False - if 0 <= angle < 360.05: - print(f"Starting LamNI scan for angle {angle}") - while not successful: - self._start_beam_check() - if not self.special_angles: - self._current_special_angles = [] - if self._current_special_angles: - next_special_angle = self._current_special_angles[0] - if np.isclose(angle, next_special_angle, atol=0.5): - self._current_special_angles.pop(0) - num_repeats = self.special_angle_repeats - else: - num_repeats = 1 - try: - start_scan_number = bec.queue.next_scan_number - for i in range(num_repeats): - self._at_each_angle(angle) - error_caught = False - except AlarmBase as exc: - if exc.alarm_type == "TimeoutError": - bec.queue.request_queue_reset() - time.sleep(2) - error_caught = True - else: - raise exc + ) + # reverse even sub-tomograms + if not (subtomo_number % 2): + angles = np.flip(angles) + for angle in angles: + self.progress["subtomo"] = subtomo_number + self.progress["subtomo_projection"] = angles.index(angle) + self.progress["subtomo_total_projections"] = 180 / self.tomo_angle_stepsize + self.progress["projection"] = (subtomo_number - 1) * self.progress[ + "subtomo_total_projections" + ] + self.progress["subtomo_projection"] + self.progress["total_projections"] = 180 / self.tomo_angle_stepsize * 8 + self.progress["angle"] = angle + self._tomo_scan_at_angle(angle, subtomo_number) - if self._was_beam_okay() and not error_caught: - successful = True + def _print_progress(self): + print("\x1b[95mProgress report:") + print(f"Tomo type: ....................... {self.progress['tomo_type']}") + print(f"Projection: ...................... {self.progress['projection']}") + print(f"Total projections expected ....... {self.progress['total_projections']}") + print(f"Angle: ........................... {self.progress['angle']}") + print(f"Current subtomo: ................. {self.progress['subtomo']}") + print(f"Current projection within subtomo: {self.progress['subtomo_projection']}\x1b[0m") + + + def _tomo_scan_at_angle(self, angle, subtomo_number): + successful = False + error_caught = False + if 0 <= angle < 360.05: + print(f"Starting LamNI scan for angle {angle} in subtomo {subtomo_number}") + self._print_progress() + while not successful: + self._start_beam_check() + if not self.special_angles: + self._current_special_angles = [] + if self._current_special_angles: + next_special_angle = self._current_special_angles[0] + if np.isclose(angle, next_special_angle, atol=0.5): + self._current_special_angles.pop(0) + num_repeats = self.special_angle_repeats + else: + num_repeats = 1 + try: + start_scan_number = bec.queue.next_scan_number + for i in range(num_repeats): + self._at_each_angle(angle) + error_caught = False + except AlarmBase as exc: + if exc.alarm_type == "TimeoutError": + bec.queue.request_queue_reset() + time.sleep(2) + error_caught = True else: - self._wait_for_beamline_checks() - end_scan_number = bec.queue.next_scan_number - for scan_nr in range(start_scan_number, end_scan_number): - self._write_tomo_scan_number(scan_nr, angle, subtomo_number) + raise exc + + if self._was_beam_okay() and not error_caught: + successful = True + else: + self._wait_for_beamline_checks() + end_scan_number = bec.queue.next_scan_number + for scan_nr in range(start_scan_number, end_scan_number): + self._write_tomo_scan_number(scan_nr, angle, subtomo_number) def _write_tomo_scan_number(self, scan_number: int, angle: float, subtomo_number: int) -> None: tomo_scan_numbers_file = os.path.expanduser( @@ -1007,22 +1055,29 @@ class LamNI(LamNIOpticsMixin): scans = builtins.__dict__.get("scans") self._current_special_angles = self.special_angles.copy() - if subtomo_start == 1 and start_angle is None: + if (self.tomo_type == 1 and subtomo_start == 1 and start_angle is None): # pylint: disable=undefined-variable - self.tomo_id = self.add_sample_database( - self.sample_name, - str(datetime.date.today()), - bec.active_account.decode(), - bec.queue.next_scan_number, - "lamni", - "test additional info", - "BEC", - ) - self.write_pdf_report() + if bec.active_account != "": + self.tomo_id = self.add_sample_database( + self.sample_name, + str(datetime.date.today()), + bec.active_account.decode(), + bec.queue.next_scan_number, + "lamni", + "test additional info", + "BEC", + ) + self.write_pdf_report() + else: + self.tomo_id = 0 + with scans.dataset_id_on_hold: - for ii in range(subtomo_start, 9): - self.sub_tomo_scan(ii, start_angle=start_angle) - start_angle = None + if self.tomo_type == 1: + # 8 equally spaced sub-tomograms + self.progress["tomo_type"] = "Equally spaced sub-tomograms" + for ii in range(subtomo_start, 9): + self.sub_tomo_scan(ii, start_angle=start_angle) + start_angle = None def tomo_parameters(self): """print and update the tomo parameters""" @@ -1045,8 +1100,10 @@ class LamNI(LamNIOpticsMixin): print(f" _tomo_fovy_offset = {self.align.tomo_fovy_offset}") print(f" _manual_shift_x = {self.manual_shift_x}") print(f" _manual_shift_y = {self.manual_shift_y}") - print(f"Angular step within sub-tomogram: {self.tomo_angle_stepsize} degrees") - print(f"Resulting in number of projections: {360/self.tomo_angle_stepsize*8}") + if self.tomo_type == 1: + print("\x1b[1mTomo type 1:\x1b[0m 8 equally spaced sub-tomograms") + print(f"Total number of projections: {360/self.tomo_angle_stepsize*8}") + print(f"Angular step within sub-tomogram: {self.tomo_angle_stepsize} degrees") print(f"Sample name: {self.sample_name}\n") user_input = input("Are these parameters correctly set for your scan? ")