Commit 7ba7f1e6 authored by bliss administrator's avatar bliss administrator
Browse files

Fix pcotomo restructuration and optics

parent 7a002959
......@@ -49,6 +49,7 @@ class SoftTriggerMusstAcquisitionMaster(MusstAcquisitionMaster):
pass
def trigger(self):
gevent.sleep(0.2)
self.musst.run(self.program_abort_name)
while self.musst.STATE == self.musst.RUN_STATE:
gevent.idle()
......
......@@ -199,10 +199,6 @@ class Tomo(TomoParameters):
param_name = tomo_name + f":optic_parameters"
optic_defaults = {}
optic_defaults["active_optic"] = None
optic_defaults["manual_pixel_size"] = False
optic_defaults["unbinned_pixel_size"] = 0
optic_defaults["image_pixel_size"] = 0
optic_defaults["scintillator"] = None
self._tomo_optic = tomo.TomoOptic(
self.tomo_name, config, param_name, optic_defaults
......@@ -312,7 +308,7 @@ class Tomo(TomoParameters):
self.fasttomo = tomo.FastTomo(self)
self.halftomo = tomo.HalfTomo(self)
self.pcotomo = tomo.PcoTomo(self)
self.topotomo = tomo.TopoTomo(self)
self.topotomo = None
self.sequence = "tomo:basic"
self.field_of_view = "Full"
self.active_tomo = self.fasttomo
......@@ -410,11 +406,10 @@ class Tomo(TomoParameters):
choice = "scan"
default = 0
while ret is False and choice != "exit":
while ret and choice != "exit":
dlg1 = UserChoice(values=value_list, defval=default)
ret = BlissDialog([[dlg1]], title="Tomo Setup").show()
# returns False on cancel
if ret != False:
choice = ret[dlg1]
......@@ -432,6 +427,10 @@ class Tomo(TomoParameters):
cancel = self.select_optic()
if not cancel:
self.optic.setup(self.tomo_ccd.detector)
self._tomo_optic.parameters.manual_pixel_size = self.optic.parameters.manual_pixel_size
self._tomo_optic.parameters.image_pixel_size = self.optic.parameters.image_pixel_size
self._tomo_optic.parameters.unbinned_pixel_size = self.optic.parameters.unbinned_pixel_size
self._tomo_optic.parameters.scintillator = self.optic.parameters.scintillator
if choice == "reference":
self.reference.setup()
if choice == "saving":
......@@ -699,7 +698,11 @@ class Tomo(TomoParameters):
break
def pcotomo_setup(self):
trange = int(self.parameters.end_pos-self.parameters.start_pos)
dlg_trange = UserIntInput(
label="Tomo Range?", defval=trange
)
dlg_ntomo = UserIntInput(
label="Number of Consecutive Tomo?", defval=self.pcotomo.parameters.ntomo
)
......@@ -720,12 +723,13 @@ class Tomo(TomoParameters):
defval=self.pcotomo.parameters.start_turn,
)
ret = BlissDialog(
[[dlg_ntomo], [dlg_nwait], [dlg_nloop], [dlg_useroutput], [dlg_startturn]],
[[dlg_trange], [dlg_ntomo], [dlg_nwait], [dlg_nloop], [dlg_useroutput], [dlg_startturn]],
title="PcoTomo Setup",
).show()
# returns False on cancel
if ret != False:
self.parameters.end_pos = self.parameters.start_pos + ret[dlg_trange]
self.pcotomo.parameters.ntomo = ret[dlg_ntomo]
self.pcotomo.parameters.nwait = ret[dlg_nwait]
self.pcotomo.parameters.nloop = ret[dlg_nloop]
......@@ -742,7 +746,7 @@ class Tomo(TomoParameters):
label=f"Transfer Rate: {self.pcotomo.in_pars['transferrate']} MB/s"
)
dlg_roi = UserMsg(
label=f"ROI: {self.tomo.tomo_ccd.detector.image.width} x {self.tomo.tomo_ccd.detector.image.height}\n"
label=f"ROI: {self.tomo_ccd.detector.image.width} x {self.tomo_ccd.detector.image.height}\n"
)
dlg_continuous_mode = UserCheckBox(
......@@ -779,7 +783,7 @@ class Tomo(TomoParameters):
label=f"You will collect a total of {self.pcotomo.in_pars['numberofscans']} scans\n"
)
dlg_waiting_turns = UserMsg(
label=f"You will wait {self.parameters.nwait} turns between each scan"
label=f"You will wait {self.pcotomo.parameters.nwait} turns between each scan"
)
dlg_acq_time = UserMsg(
label=f"One scan of {self.pcotomo.in_pars['time']} s every {self.pcotomo.in_pars['frequency']} s during {self.pcotomo.in_pars['totaltime']} s ({round(self.pcotomo.in_pars['totaltime'] / 60, 2)} min) \n"
......@@ -1302,7 +1306,7 @@ class Tomo(TomoParameters):
# Start and end positions of reference groups
group_start = self.in_pars["start_group_pos"]
group_end = self.in_pars["start_group_pos"][1:]
group_end.append(self.parameters.end_pos)
group_end.append(self.in_pars['end_pos'])
# loop over reference groups
for i in range(len(group_start)):
......@@ -1387,7 +1391,6 @@ class Tomo(TomoParameters):
setup_globals.SCAN_DISPLAY.auto = scan_display
self.active_tomo = self.fasttomo
<<<<<<< HEAD
else:
# sequence preset stop
for preset in self.sequence_preset:
......@@ -1399,54 +1402,6 @@ class Tomo(TomoParameters):
self.active_tomo = self.fasttomo
print(f"\n{self.sequence.split(':')[-1]} sequence ended well!\n")
=======
# get the last projection scan
# last_scan = self.get_projection_scan()[-1] if type(self.get_projection_scan()) == list else self.get_projection_scan()
# last_image_acquired = len(last_scan.get_data(f'{self.tomo_ccd.detector.name}')) - 1
# self.tomo_scan.last_motor_pos = last_scan.get_data(f'{self.tomo_musst.storelist[-1]}')[last_image_acquired]/self.tomo_musst.motor.steps_per_unit
else:
# get the last projection scan
last_scan = (
self.get_projection_scan()[-1]
if type(self.get_projection_scan()) == list
else self.get_projection_scan()
)
if (
len(last_scan.get_data(f"{self.tomo_ccd.detector.name}:image"))
!= self.in_pars["nb_group_points"][i]
and self.parameters.scan_type == ScanType.CONTINUOUS_HARD
and self.sequence != "tomo:topo"
):
log_error(self, "Watchdog NoDataError not raised")
with open(
"/users/blissadm/local/log_tomo/log_file.txt", "a"
) as log_file:
log_file.write(f"{time.ctime()}\n")
log_file.write("Scan failed without any exceptions\n")
nb_trig = len(
last_scan.get_data(f"{self.tomo_musst.storelist[-1]}")
)
log_file.write(f"Number of triggers sent {nb_trig}\n")
nb_img = len(
last_scan.get_data(f"{self.tomo_ccd.detector.name}:image")
)
log_file.write(f"Number of images acquired {nb_img}\n")
last_motor_pos = last_scan.get_data(
f"{self.rotation_axis._Axis__name}"
)[-1]
log_file.write(f"Last motor position {last_motor_pos}\n")
# sequence preset stop
for preset in self.sequence_preset:
preset.stop()
setup_globals.SCAN_DISPLAY.auto = scan_display
self.active_tomo = self.fasttomo
# last_image_acquired = len(last_scan.get_data(f'{self.tomo_ccd.detector.name}:image')) - 1
# self.tomo_scan.last_motor_pos = last_scan.get_data(f'{self.rotation_axis._Axis__name}')[last_image_acquired]
else:
print(f"\n{self.sequence.split(':')[-1]} sequence ended well!\n")
scan_tend = datetime.datetime.fromtimestamp(time.time())
print("Total scan sequence took {0}".format(scan_tend - scan_t0))
......@@ -1454,7 +1409,6 @@ class Tomo(TomoParameters):
log_info(self, "sequence ended")
def show_scan_info(self):
"""
Displays information about tomo scan
......@@ -1469,6 +1423,7 @@ class Tomo(TomoParameters):
f"Scan point time: {self.tomo_scan.in_pars['scan_point_time']:.4f} sec (Exposure time: {self.tomo_scan.in_pars['scan_point_time'] * self.tomo_scan.in_pars['integration_ratio']} sec)"
)
print(f"Scan speed: {self.tomo_scan.in_pars['scan_speed']:.2f} degrees / sec")
print(f"Integration ratio ==> {self.tomo_scan.in_pars['integration_ratio']*100:.2f} %")
print(f"Saving path: {current_session.scan_saving.get_path()}")
print(f"Image file format: {self.tomo_ccd.detector.saving.file_format}")
print(f"Frames per file: {self.tomo_ccd.detector.saving.frames_per_file}")
......@@ -1525,7 +1480,7 @@ class Tomo(TomoParameters):
self.pcotomo.parameters.ntomo = ntomo
self.pcotomo.parameters.nloop = nloop
self.pcotomo.parameters.nwait = nwait
self.pcotomo.parameters.noread = 1
self.pcotomo.parameters.noread = 0
elif mode == "endless":
self.pcotomo.parameters.ntomo = ntomo
self.pcotomo.parameters.nloop = nloop
......
......@@ -60,9 +60,15 @@ class TomoOptic(TomoParameters):
self.__name = name
self.__config = config
param_defaults["manual_pixel_size"] = False
param_defaults["unbinned_pixel_size"] = 0
param_defaults["image_pixel_size"] = 0
param_defaults["scintillator"] = 'None'
# Initialise the TomoParameters class
super().__init__(param_name, param_defaults)
try:
self.__scintillators = config["scintillator"]
......@@ -108,22 +114,15 @@ class TomoOptic(TomoParameters):
self.__focus_lim_neg = config["focus_lim_neg"]
except:
self.__focus_lim_neg = 0
try:
self.__manual_pixel_size = config["manual_pixel_size"]
except:
self.__manual_pixel_size = False
try:
self.__unbinned_pixel_size = config["unbinned_pixel_size"]
except:
self.__unbinned_pixel_size = 0
try:
self.__image_pixel_size = config["image_pixel_size"]
except:
self.__image_pixel_size = 0
try:
self.__scintillator = config["scintillator"]
except:
self.__scintillator = None
self.__manual_pixel_size = self.parameters.manual_pixel_size
self.__unbinned_pixel_size = self.parameters.unbinned_pixel_size
self.__image_pixel_size = self.parameters.image_pixel_size
log_info(self, "__init__() leaving")
def manual_pixel_size_setup(self):
......@@ -133,7 +132,7 @@ class TomoOptic(TomoParameters):
dlg1 = UserYesNo(label="Do you want to set pixel size manually?")
ret = display(dlg1, title="Manual Pixel Size")
if ret != False:
if ret is True:
self.manual_pixel_size = True
dlg1 = UserFloatInput(
label="Unbinned pixel size in um", defval=self.unbinned_pixel_size
......@@ -141,7 +140,7 @@ class TomoOptic(TomoParameters):
ct1 = Container([dlg1], title="Unbinned Pixel Size")
ret = BlissDialog([[ct1]], title="Pixel Size Setup").show()
if ret != False:
if ret is not False:
self.unbinned_pixel_size = ret[dlg1]
return True
else:
......@@ -161,7 +160,7 @@ class TomoOptic(TomoParameters):
)
ret = display(dlg1, title="Correct Pixel Size")
if ret is False:
if ret is True:
dlg1 = UserFloatInput(
label="Corrected unbinned pixel size in um",
defval=self.unbinned_pixel_size,
......@@ -169,7 +168,7 @@ class TomoOptic(TomoParameters):
ct1 = Container([dlg1], title="Corrected Pixel Size")
ret = BlissDialog([[ct1]], title="Pixel Size Setup").show()
if ret is False:
if ret is not False:
self.unbinned_pixel_size = ret[dlg1]
else:
self.unbinned_pixel_size = (
......@@ -268,6 +267,7 @@ class TomoOptic(TomoParameters):
Sets the name of the scintillator associated with the optic
"""
self.__scintillator = value
self.parameters.scintillator = value
@property
def manual_pixel_size(self):
......@@ -282,6 +282,7 @@ class TomoOptic(TomoParameters):
Sets if pixel size is manually set or not
"""
self.__manual_pixel_size = value
self.parameters.manual_pixel_size = value
@property
def unbinned_pixel_size(self):
......@@ -296,6 +297,7 @@ class TomoOptic(TomoParameters):
Sets pixel size without binnning to value
"""
self.__unbinned_pixel_size = value
self.parameters.unbinned_pixel_size = value
@property
def image_pixel_size(self):
......@@ -310,6 +312,7 @@ class TomoOptic(TomoParameters):
Sets pixel size without binnning to value
"""
self.__image_pixel_size = value
self.parameters.image_pixel_size = value
@property
def magnification(self):
......
......@@ -89,8 +89,6 @@ class TomoScan:
self.in_pars['scan_point_time'] = step_time
self.in_pars['scan_speed'] = abs(self.in_pars['scan_step_size']/self.in_pars['scan_point_time'])
self.in_pars['integration_ratio'] = integ_ratio
print(f"Integration ratio ==> {integ_ratio*100:.2f} %")
def step_scan(self, start_pos, end_pos, nb_points, exposure_time,
......
......@@ -145,9 +145,11 @@ class FastTomo:
nb_groups,
)
)
self.tomo.in_pars["nb_group_points"] = nb_points
self.tomo.in_pars["end_pos"] = self.tomo.parameters.end_pos
self.tomo.in_pars["sample_pixel_size"] = self.tomo.optic.image_pixel_size
log_info(self, "calculate_parameters() leaving")
......@@ -1537,7 +1539,7 @@ class PcoTomo(FastTomo, TomoParameters):
self.tomo = tomo
tomo.tomo_scan = PcoTomoScan(tomo)
self.tomo_tools = PcoTomoTools(self)
self.tomo_tools = PcoTomoTools(tomo)
self.tomo_musst = PcoTomoMusst(
self.name,
self.tomo.musst_card,
......@@ -1573,7 +1575,7 @@ class PcoTomo(FastTomo, TomoParameters):
f"Time to download film: {round((sizeofonescan * numberofscans) / (transferrate / 1024), 2)} s ({round((sizeofonescan * numberofscans) / (transferrate / 1024) / 60, 2)} min)\n"
)
elif mode == "multiple":
elif self.parameters.mode == "multiple":
print("\n\nWaiting Turns Between Each Scan")
print(f"You will collect a total of {numberofscans} scans\n")
print(f"You will wait {self.parameters.nwait} turns between each scan")
......@@ -1584,7 +1586,7 @@ class PcoTomo(FastTomo, TomoParameters):
f"Time to download film: {round((sizeofonescan * numberofscans) / (transferrate / 1024), 2)} s ({round((sizeofonescan * numberofscans) / (transferrate / 1024) / 60, 2)} min)\n"
)
elif mode == "endless":
elif self.parameters.mode == "endless":
print(
f"\n\nYou will wait {unlimitwaitingturns} turns between each scan, during this time, scan is downloaded"
)
......@@ -1595,6 +1597,11 @@ class PcoTomo(FastTomo, TomoParameters):
def calculate_parameters(self):
super().calculate_parameters()
self.tomo.in_pars["end_pos"] = self.tomo.parameters.start_pos + (self.tomo.parameters.end_pos - self.tomo.parameters.start_pos) * self.parameters.ntomo
self.tomo.in_pars["nb_group_points"] = [nb_points*self.parameters.ntomo for nb_points in self.tomo.in_pars["nb_group_points"]]
depth = self.tomo.tomo_ccd.detector.image.depth
width = self.tomo.tomo_ccd.detector.image.width
height = self.tomo.tomo_ccd.detector.image.height
......@@ -1614,9 +1621,10 @@ class PcoTomo(FastTomo, TomoParameters):
+ self.tomo.parameters.latency_time
)
totalcontinuoustime = numberofscans * time
trange = self.tomo.parameters.end_pos - self.tomo.parameters.start_pos
waitingtime = (
(360 / self.parameters.trange) * self.parameters.nwait
+ int(180 / self.parameters.trange)
(360 / trange) * self.parameters.nwait
+ int(180 / trange)
) * time
frequency = waitingtime + time
totaltime = frequency * numberofscans
......@@ -1626,13 +1634,13 @@ class PcoTomo(FastTomo, TomoParameters):
unlimitwaitingturns = (
int(
((sizeofonescan / (transferrate / 1024)) / time)
/ (360 / self.parameters.trange)
/ (360 / trange)
)
+ 2
)
unlimitwaitingtime = (
(360 / self.parameters.trange) * unlimitwaitingturns
+ int(180 / self.parameters.trange)
(360 / trange) * unlimitwaitingturns
+ int(180 / trange)
) * time
unlimitfrequency = unlimitwaitingtime + time
......@@ -1665,8 +1673,8 @@ class PcoTomo(FastTomo, TomoParameters):
"""
Calculates scan parameters and contructs acquisition chain corresponding to scan type
"""
super().calculate_parameters()
self.calculate_parameters()
self.tomo.tomo_scan.calculate_parameters(
self.tomo.parameters.start_pos,
self.tomo.parameters.end_pos - self.tomo.parameters.start_pos,
......@@ -1745,7 +1753,7 @@ class PcoTomo(FastTomo, TomoParameters):
self.parameters.noread,
self.parameters.start_turn,
self.tomo.tomo_scan.in_pars["sync_shut_angle"],
self.tomo.parameters.user_output,
self.parameters.user_output,
self.tomo.parameters.trigger_type,
title,
scan_info,
......@@ -1758,12 +1766,12 @@ class PcoTomo(FastTomo, TomoParameters):
proj_scan.add_preset(header_preset)
# add shutter preset
shutter_preset = PcoTomoShutterPreset(
self.tomo.shutter,
self.tomo.tomo_musst,
self.tomo.sequence_preset[0].mux,
)
proj_scan.add_preset(shutter_preset)
#shutter_preset = PcoTomoShutterPreset(
# self.tomo.shutter,
# self.tomo_musst,
# self.tomo.sequence_preset[0].mux,
#)
#proj_scan.add_preset(shutter_preset)
# add to scan sequence when requested
if scan_sequence != None:
......
......@@ -64,7 +64,7 @@ class TomoShutter(TomoParameters):
self.ccd_shutter = config.get("ccd_shutter", False)
self.ccd_shutter_time = config.get("ccd_shutter_time", None)
self.sync_shutter = config.get("sync_shutter", False)
self.sync_shutter_time = config.get("sync_shutter_time", None)
self.sync_shutter_time = config.get("sync_shutter_time", 0.0)
self.init()
......
......@@ -2,7 +2,7 @@ import bliss.controllers.lima
from .Tomo import Tomo,ScanType
from .TomoScan import TomoScan
from .TomoSequence import FastTomo,HalfTomo,ZSeries,Mtomo, Progressive, TopoTomo
from .TomoSequence import FastTomo,HalfTomo,ZSeries,Mtomo, Progressive, TopoTomo, PcoTomo
from .TomoCcd import TomoCcd
from .TomoSaving import TomoSaving
from .TomoShutter import TomoShutter
......
......@@ -81,7 +81,10 @@ class FixedOptic(TomoOptic):
self._magnification = config["magnification"]
super().__init__(name, config)
param_name = self.__name + ":parameters"
param_defaults = {}
super().__init__(name, config, param_name, param_defaults)
@property
def description(self):
......
......@@ -96,12 +96,15 @@ class PeterOptic(TomoOptic):
self.current_objective = None
self.current_eyepiece = None
param_name = self.__name + ":parameters"
param_defaults = {}
# Connect to the wago device
self.wago_proxy = PyTango.DeviceProxy(self.wago_device)
# Initialise the TomoOptic class
super().__init__(name, config)
super().__init__(name, config, param_name, param_defaults)
# self.magnification = 0.0
......
import sys
import gevent
import numpy as np
import time
import click
from bliss.setup_globals import *
from bliss.common import scans
from bliss.common.scans import ascan, pointscan
from bliss.common.cleanup import error_cleanup, capture_exceptions, axis as cleanup_axis
from bliss.scanning.scan_tools import peak, goto_peak
from bliss.controllers.lima.roi import Roi
from bliss.shell.standard import umv, mv, umvr, mvr, plotselect
from bliss.config.static import get_config
from nabu.preproc.alignment import CenterOfRotation
from nabu.preproc.alignment import DetectorTranslationAlongBeam
from nabu.preproc.alignment import CameraFocus
from nabu.preproc.alignment import CameraTilt
from bliss.common.plot import plot_image
class TomoAlign():
def __init__(self, name, config):
self.__name = name
self.__config = config
self.__tomo = config.get("tomo", None)
self.__paper = config.get("paper_motor", None)
self.__slits_vg = config.get("slits_vgap", None)
self.__slits_hg = config.get("slits_hgap", None)
self.__det_vtilt = config.get("detector_vtilt", None)
self.__det_htilt = config.get("detector_htilt", None)
@property
def name(self):
"""
A unique name for the Bliss object
"""
return self.__name
@property
def config(self):
"""
The configuration for Tomo alignment
"""
return self.__config
def __info__(self):
info_str = f"{self.name} info:\n"
if self.__tomo != None:
info_str += f" tomo = {self.__tomo.name} \n"
info_str += f" detector = {self.__tomo.tomo_ccd.detector.name}\n"
info_str += f" optic = {self.__tomo.optic.description}\n"
info_str += f" pixel size = {self._pixel_size()} \n"
info_str += f" exposure time = {self.__tomo.parameters.exposure_time} \n\n"
if self.__paper != None:
info_str += f" alignment paper= {self.__paper.name} \n"
if self.__slits_vg != None:
info_str += f" slits vgap = {self.__slits_vg.name} \n"
if self.__slits_hg != None:
info_str += f" slits hgap = {self.__slits_hg.name} \n"
if self.__det_vtilt != None:
info_str += f" detector htilt = {self.__det_vtilt.name} \n"
if self.__det_htilt != None:
info_str += f" detector htilt = {self.__det_htilt.name} \n"
return info_str
def _pixel_size(self):
# pixel size returned by tomo is in um
pixel_size = self.__tomo.tomo_ccd.calculate_image_pixel_size(self.__tomo.optic.magnification)
#print ("pixel_size in um = %f" % pixel_size)
# pixel size for Nabu caluculations must be in mm
pixel_size = pixel_size / 1000.0
return pixel_size
def _get_images(self, scan, detector):
# read back the scan images aquired
scan_images=[]
lima_data = scan.get_data()[detector.image]
npoints = lima_data.last_index
if npoints < lima_data.buffer_max_number:
for i in range(npoints):
scan_images.append(lima_data.get_image(i))
return scan_images
else:
ValueError("Cannot read images! Not enough images in the Lima image buffer")
#
# Detector focus alignment
#
def focus(self, save=False):
# prepare the focus scan parameters
scan_pars = __tomo.optic.focus_scan_parameters()
scan_range = scan_pars["focus_scan_range"]
scan_steps = scan_pars["focus_scan_steps"]
focus_type = scan_pars["focus_type"]
focus_motor = __tomo.optic.focus_motor()
if focus_type == "Rotation" and __tomo.optic.magnification < 0.7:
scan_range /= 2
scan_steps *= 2
start = focus_motor.position - scan_range
stop = focus_motor.position + scan_range
#pixel size in mm
pixel_size = _pixel_size()
# move in paper
print ("Move in paper")
__paper.IN
# Do the focus scan
focus_scan = self.focus_scan(focus_motor, start, stop, scan_steps,
__tomo.parameters.exposure_time ,
__tomo.tomo_ccd.detector, save=save)