diff --git a/src/pymicroscope/base/mapcontroller.py b/src/pymicroscope/base/mapcontroller.py new file mode 100644 index 0000000..1cde56e --- /dev/null +++ b/src/pymicroscope/base/mapcontroller.py @@ -0,0 +1,55 @@ +from mytk import * +import math +from typing import Tuple, Optional +from typing import Any + +class MapController(Bindable): + '''Giving all the position to create a map of all the sample''' + def __init__(self, device, *args, **kwargs): + super().__init__(*args, **kwargs) + self.device = device + + self.z_image_number = 1 + self.microstep_pixel = 0.16565 + self.z_range = 1 + self.x_dimension = 1000 + self.y_dimension = 500 + + self.parameters: dict[str, Optional[Tuple[int, int, int]]] = { + "Upper left corner": None, + "Upper right corner": None, + "Lower left corner": None, + "Lower right corner": None, + } + + def create_positions_for_map(self): + '''Giving all the deplacement position according to the x and y image dimension''' + positions_list = [] + + corner1 = self.parameters["Upper left corner"] + corner2 = self.parameters["Upper right corner"] + corner3 = self.parameters["Lower left corner"] + corner4 = self.parameters["Lower right corner"] + + x_image_dimension = self.x_dimension*self.microstep_pixel + y_image_dimension = self.y_dimension*self.microstep_pixel + z_image_dimension = self.z_range*self.microstep_pixel + + if all(x != (0.0, 0.0, 0.0) for x in self.parameters.values()): + number_of_x_image = math.ceil((corner2[0] - corner1[0]) / (0.9*x_image_dimension)) + number_of_y_image = math.ceil((corner2[1] - corner4[1])/ (0.9*y_image_dimension)) + else: + number_of_x_image = 1 + number_of_y_image = 1 + + + for z in range(self.z_image_number): + z_position = z*z_image_dimension + for y in range(number_of_y_image): + y_position = y*y_image_dimension*0.9 + for x in range(number_of_x_image): + x_position = x*x_image_dimension*0.9 + positions_list.append((x_position, y_position, z_position)) + + + return positions_list \ No newline at end of file diff --git a/src/pymicroscope/base/position_and_mapcontroller.py b/src/pymicroscope/base/position_and_mapcontroller.py deleted file mode 100644 index 4f5b3f3..0000000 --- a/src/pymicroscope/base/position_and_mapcontroller.py +++ /dev/null @@ -1,143 +0,0 @@ -from mytk import * -import math -from typing import Tuple, Optional -from typing import Any - -class MapController(Bindable): - def __init__(self, device, *args, **kwargs): - super().__init__(*args, **kwargs) - self.device = device - - self.z_image_number = 1 - self.microstep_pixel = 0.16565 - self.z_range = 1 - - self.parameters: dict[str, Optional[Tuple[int, int, int]]] = { - "Upper left corner": None, - "Upper right corner": None, - "Lower left corner": None, - "Lower right corner": None, - } - - def create_positions_for_map(self): - ## Faire le calcul pour vrai avec corner1m cprner2 corner3 corbner4... - # Utiliser self.parameters and self.z_imageNUmber, self.micvrostep...... - positions_list = [] - - corner1 = self.parameters["Upper left corner"] - corner2 = self.parameters["Upper right corner"] - corner3 = self.parameters["Lower left corner"] - corner4 = self.parameters["Lower right corner"] - #print(corner1, corner2, corner3, corner4) - - x_image_dimension = 1000*self.microstep_pixel - y_image_dimension = 500*self.microstep_pixel - z_image_dimension = self.z_range*self.microstep_pixel - - if all(x != (0.0, 0.0, 0.0) for x in self.parameters.values()): - number_of_x_image = math.ceil((corner2[0] - corner1[0]) / (0.9*x_image_dimension)) - number_of_y_image = math.ceil((corner2[1] - corner4[1])/ (0.9*y_image_dimension)) - else: - number_of_x_image = 1 - number_of_y_image = 1 - - - for z in range(self.z_image_number): - z_position = z*z_image_dimension - for y in range(number_of_y_image): - y_position = y*y_image_dimension*0.9 - for x in range(number_of_x_image): - x_position = x*x_image_dimension*0.9 - positions_list.append((x_position, y_position, z_position)) - - - return positions_list - - #return [(10, 0, 0), (100, 0, 0), (0, 100, 0), (100, 100, 0)] - #, (0,200,0), (100,0,0), (100, 100, 0 ), (100, 200, 0)] - - # def ajuste_map_imaging(self): - # if all(x is not None for x in self.parameters.values()): - # upper_left_corner = self.parameters["Upper left corner"] - # upper_right_corner = self.parameters["Upper right corner"] - # lower_left_corner = self.parameters["Lower left corner"] - # lower_right_corner = self.parameters["Lower right corner"] - - # # ajuste image for making a square - # if upper_left_corner[1] > upper_right_corner[1]: - # ajusted_position = ( - # upper_left_corner[0], - # upper_right_corner[1], - # upper_left_corner[2], - # ) - # self.parameters["Upper left corner"] = ajusted_position - - # if upper_left_corner[1] < upper_right_corner[1]: - # ajusted_position = ( - # upper_right_corner[0], - # upper_left_corner[1], - # upper_right_corner[2], - # ) - # self.parameters["Upper right corner"] = ajusted_position - - # if upper_right_corner[0] > lower_right_corner[0]: - # ajusted_position = ( - # lower_right_corner[0], - # upper_right_corner[1], - # upper_right_corner[2], - # ) - # self.parameters["Upper right corner"] = ajusted_position - - # if upper_right_corner[0] < lower_right_corner[0]: - # ajusted_position = ( - # upper_right_corner[0], - # lower_right_corner[1], - # lower_right_corner[2], - # ) - # self.parameters["Lower right corner"] = ajusted_position - - # if lower_left_corner[1] > lower_right_corner[1]: - # ajusted_position = ( - # lower_left_corner[0], - # lower_right_corner[1], - # lower_left_corner[2], - # ) - # self.parameters["Lower left corner"] = ajusted_position - - # if lower_left_corner[1] < lower_right_corner[1]: - # ajusted_position = ( - # lower_right_corner[0], - # lower_left_corner[1], - # lower_right_corner[2], - # ) - # self.parameters["Lower right corner"] = ajusted_position - - # if upper_left_corner[0] > lower_left_corner[0]: - # ajusted_position = ( - # upper_left_corner[0], - # lower_left_corner[1], - # lower_left_corner[2], - # ) - # self.parameters["Lower left corner"] = ajusted_position - - # if upper_left_corner[0] < lower_left_corner[0]: - # ajusted_position = ( - # lower_left_corner[0], - # upper_left_corner[1], - # upper_left_corner[2], - # ) - # self.parameters["Upper left corner"] = ajusted_position - - # for parameter, z in self.parameters: - # z_values_comparaison = z[2] - - # if len(set(z_values_comparaison)) != 1: - # ajusted_position = ( - # z[0], - # z[1], - # max(z_values_comparaison), - # ) - # self.parameters[parameter] = ajusted_position - - # else: - # raise ValueError("Some initial parameters are missing") \ No newline at end of file diff --git a/src/pymicroscope/experiment/actions.py b/src/pymicroscope/experiment/actions.py index 5a48866..0a1c9d5 100644 --- a/src/pymicroscope/experiment/actions.py +++ b/src/pymicroscope/experiment/actions.py @@ -150,6 +150,19 @@ def __init__( def do_perform(self, results=None) -> dict[str, Any] | None: self.device.moveInMicronsBy(self.d_position) return {"displacement": self.d_position} + +class ActionHome(Action): + def __init__( + self, + linear_motion_device: LinearMotionDevice, + *args, + **kwargs, + ): + super().__init__(*args, **kwargs) + self.device: LinearMotionDevice = linear_motion_device + + def do_perform(self, results=None) -> None: + self.device.home() class ActionFunctionCall(Action): @@ -296,10 +309,3 @@ def do_perform(self, results=None) -> dict[str, Any] | None: self.output = filepath - -class ActionClear(Action): - def __init__(self, filepath: Path, *args, **kwargs): - super().__init__(*args, **kwargs) - self.filepath = filepath - for file in self.filepath: - self.filepath[file] = None diff --git a/src/pymicroscope/hardware/kinesisdevice.py b/src/pymicroscope/hardware/kinesisdevice.py new file mode 100644 index 0000000..2b9ea8d --- /dev/null +++ b/src/pymicroscope/hardware/kinesisdevice.py @@ -0,0 +1,82 @@ +from hardwarelibrary.physicaldevice import * +from hardwarelibrary.motion.linearmotiondevice import * +from hardwarelibrary.communication.communicationport import * +from hardwarelibrary.communication.usbport import USBPort +from hardwarelibrary.communication.serialport import SerialPort +from hardwarelibrary.communication.commands import DataCommand +from hardwarelibrary.communication.debugport import DebugPort + +import time +from struct import * + +from pyftdi.ftdi import Ftdi #FIXME: should not be here. +from mytk import * +from pylablib.devices.Thorlabs import kinesis + +class KinesisDevice(LinearMotionDevice): + #SERIAL_NUMBER = "83849018" + + def __init__(self, serialNumber: str = None, channel: int = 1): + super().__init__(serialNumber=serialNumber, idVendor=self.classIdVendor, idProduct=self.classIdProduct) + self.thorlabs_device = None + self.channel =channel + self.nativeStepsPerMicrons = 128 + + + # All values are in native units (i.e. microsteps) + self.xMinLimit = 0 + self.xMaxLimit = 857599 + + def __del__(self): + try: + self.thorlabs_device.close() + except: + return + + def doInitializeDevice(self): + available_devices = kinesis.KinesisDevice.list_devices() + available_serial_numbers = [ device[0] for device in available_devices] + + if self.serialNumber not in available_serial_numbers: + raise RuntimeError("Kinesis Device with serial number {0} not found.".format(self.serialNumber)) + + '''Connect the right Kinesis Motor, open the port, set the channel and the reference position''' + self.thorlabs_device = kinesis.KinesisMotor(conn=self.serialNumber) + if self.thorlabs_device is None: + raise PhysicalDevice.UnableToInitialize("Cannot allocate port {0}".format(self.thorlabs_device)) + else: + self.thorlabs_device.open() + self.thorlabs_device.set_supported_channels(channels= self.channel) + self.thorlabs_device.set_position_reference() #set the initilal point + + def doShutdownDevice(self): + self.thorlabs_device.close() + self.thorlabs_device = None + + def position(self) -> int: # for 1D compatibility + position_tuple = super().position() + return position_tuple[0] + + def doGetPosition(self) -> tuple: + return (self.thorlabs_device.get_position(),) + + def doMoveTo(self, position): + self.thorlabs_device.move_to(position=position[0]) + if self.thorlabs_device.is_moving() is False: + raise Exception("unable to move the device.") + else: + self.thorlabs_device.wait_move() + + def doMoveBy(self, displacement): + self.thorlabs_device.move_by(distance=displacement[0]) + if self.thorlabs_device.is_moving() is False: + raise Exception("unable to move the device.") + else: + self.thorlabs_device.wait_move() + + def doHome(self): + self.thorlabs_device.move_to(position=0) + if self.thorlabs_device.is_moving() is False: + raise Exception("unable to move the device to home.") + else: + self.thorlabs_device.wait_for_stop() diff --git a/src/pymicroscope/microscope_app.py b/src/pymicroscope/microscope_app.py index 4f535c5..47dc3db 100644 --- a/src/pymicroscope/microscope_app.py +++ b/src/pymicroscope/microscope_app.py @@ -18,14 +18,17 @@ from PIL import Image as PILImage from pymicroscope.acquisition.imageprovider import DebugImageProvider, ImageProvider from pymicroscope.acquisition.cameraprovider import OpenCVImageProvider -from pymicroscope.base.position_and_mapcontroller import MapController +from pymicroscope.base.mapcontroller import MapController from pymicroscope.experiment.actions import * from pymicroscope.experiment.experiments import Experiment, ExperimentStep from pymicroscope.app_notifications import MicroscopeAppNotification from pymicroscope.base.save_history import SaveHistory from pymicroscope.utils.thread_utils import is_main_thread +from pymicroscope.plugins.delay_line import DelaysController +from hardwarelibrary.physicaldevice import PhysicalDevice from hardwarelibrary.motion import SutterDevice +from pymicroscope.hardware.kinesisdevice import KinesisDevice class MicroscopeApp(App): def __init__(self, *args, **kwargs): @@ -56,6 +59,17 @@ def __init__(self, *args, **kwargs): self.is_camera_running = False self.sample_position_device = SutterDevice(serialNumber="debug") + self.delay_device:LinearMotionDevice = KinesisDevice(serialNumber="83849018") + + try: + self.delay_device.initializeDevice() + self.delay_position = self.delay_device.position() + self.delay_device_is_ready = True + except PhysicalDevice.UnableToInitialize as e: + self.delay_position = None + self.delay_device_is_ready = False + + self.delay_controller = DelaysController() self.map_controller = MapController(self.sample_position_device) @@ -161,6 +175,7 @@ def build_interface(self): self.build_position_interface() self.build_start_stop_interface() self.build_cameras_menu() + self.build_delay_interface() def build_imageview_interface(self): assert is_main_thread() @@ -373,7 +388,7 @@ def user_changed_camera(self, popup, index): def build_position_interface(self): # assert is_main_thread() - self.position = Box(label="Position", width=500, height=250) + self.position = Box(label="Position", width=500, height=310) self.position.grid_into( self.window, column=1, row=2, pady=10, padx=10, sticky="nse" ) @@ -416,10 +431,54 @@ def build_position_interface(self): padx=10, sticky="w", ) + Label("Image Pixel Dimension:").grid_into( + self.position, + row=3, + column=0, + columnspan=2, + pady=10, + padx=10, + sticky="w", + ) + Label("x dimension:").grid_into( + self.position, + row=3, + column=2, + pady=10, + padx=10, + sticky="e", + ) + self.x_pixel_entry = IntEntry( + value=0, width=4 + ) + self.x_pixel_entry.grid_into( + self.position, row=3, column=3, pady=2, padx=2, sticky="nsw" + ) + self.map_controller.bind_properties( + "x_dimension", self.x_pixel_entry, "value_variable" + ) - Label("Facteur :").grid_into( + Label("y dimension:").grid_into( self.position, row=3, + column=4, + pady=10, + padx=10, + sticky="e", + ) + self.y_pixel_entry = IntEntry( + value=0, width=4 + ) + self.y_pixel_entry.grid_into( + self.position, row=3, column=5, pady=2, padx=2, sticky="nsw" + ) + self.map_controller.bind_properties( + "y_dimension", self.y_pixel_entry, "value_variable" + ) + + Label("Facteur :").grid_into( + self.position, + row=4, column=0, columnspan=2, pady=2, @@ -431,7 +490,7 @@ def build_position_interface(self): value=float(self.map_controller.microstep_pixel), width=5 ) self.microstep_pixel_entry.grid_into( - self.position, row=3, column=2, pady=2, padx=2, sticky="ns" + self.position, row=4, column=2, pady=2, padx=2, sticky="ns" ) self.map_controller.bind_properties( "microstep_pixel", self.microstep_pixel_entry, "value_variable" @@ -439,7 +498,7 @@ def build_position_interface(self): Label("um/px").grid_into( self.position, - row=3, + row=4, column=3, pady=2, padx=0, @@ -448,7 +507,7 @@ def build_position_interface(self): Label("Number of z images :").grid_into( self.position, - row=4, + row=5, column=0, columnspan=2, pady=2, @@ -459,7 +518,7 @@ def build_position_interface(self): value=self.map_controller.z_image_number, width=5 ) self.z_image_number_entry.grid_into( - self.position, row=4, column=2, pady=2, padx=2, sticky="ns" + self.position, row=5, column=2, pady=2, padx=2, sticky="ns" ) self.map_controller.bind_properties( "z_image_number", self.z_image_number_entry, "value_variable" @@ -467,8 +526,8 @@ def build_position_interface(self): Label("z step :").grid_into( self.position, - row=4, - column=4, + row=5, + column=3, pady=2, padx=2, sticky="nse", @@ -478,7 +537,7 @@ def build_position_interface(self): value=self.map_controller.z_range, width=5 ) self.z_range_entry.grid_into( - self.position, row=4, column=5, pady=2, padx=2, sticky="ns" + self.position, row=5, column=4, pady=2, padx=2, sticky="ns" ) self.map_controller.bind_properties( "z_range", self.z_range_entry, "value_variable" @@ -486,8 +545,8 @@ def build_position_interface(self): Label("um").grid_into( self.position, - row=4, - column=6, + row=5, + column=5, pady=2, padx=0, sticky="nsw", @@ -499,7 +558,7 @@ def build_position_interface(self): ) # want that when the button is push, the first value is memorised and we see the position at the button place self.apply_upper_left_button.grid_into( self.position, - row=5, + row=6, column=0, columnspan=2, pady=3, @@ -513,7 +572,7 @@ def build_position_interface(self): ) # want that when the button is push, the first value is memorised and we see the position at the button place self.apply_upper_right_button.grid_into( self.position, - row=5, + row=6, column=2, columnspan=2, pady=3, @@ -527,7 +586,7 @@ def build_position_interface(self): ) # want that when the button is push, the first value is memorised and we see the position at the button place self.apply_lower_right_button.grid_into( self.position, - row=6, + row=7, column=2, columnspan=2, pady=2, @@ -541,7 +600,7 @@ def build_position_interface(self): ) self.apply_lower_left_button.grid_into( self.position, - row=6, + row=7, column=0, columnspan=2, pady=2, @@ -555,12 +614,12 @@ def build_position_interface(self): ) self.start_map_aquisition.grid_into( self.position, - row=5, - column=5, + row=6, + column=4, columnspan=2, pady=2, padx=2, - sticky="nse", + sticky="ns", ) self.bind_properties( "can_start_map", self.start_map_aquisition, "is_enabled" @@ -572,17 +631,152 @@ def build_position_interface(self): ) self.clear_map_aquisition.grid_into( self.position, - row=6, - column=5, + row=7, + column=4, columnspan=2, pady=2, padx=2, - sticky="nse", + sticky="ns", ) self.bind_properties( "can_start_map", self.clear_map_aquisition, "is_enabled" ) + def build_delay_interface(self): + + self.delay_controls = Box( + label="Delay", width=370, height=250 + ) + + self.delay_controls.grid_into( + self.window, column=3, row=0, pady=10, padx=10, sticky="nse" + ) + self.delay_controls.widget.grid_propagate(False) + + Label("Position in encoder steps").grid_into( + self.delay_controls, row=1, column=0, columnspan=2, pady=4, padx=4, sticky="w" + ) + Label(self.delay_position).grid_into( + self.delay_controls, row=1, column=1, columnspan=2, pady=4, padx=4, sticky="e" + ) + Label("Tunable Wavelenght").grid_into( + self.delay_controls, row=2, column=0, pady=4, padx=4, sticky="w" + ) + self.wavelenght_entry = IntEntry( + value=0, width=5 + ) + self.wavelenght_entry.grid_into( + self.delay_controls, row=2, column=1, pady=4, padx=4, sticky="e" + ) + Label("nm").grid_into( + self.delay_controls, row=2, column=2, pady=4, padx=4, sticky="w" + ) + Label("Delay/Wavelenght relation:").grid_into( + self.delay_controls, row=3, column=0, columnspan=2, pady=4, padx=4, sticky="w" + ) + self.a_equation_entry = IntEntry( + value=self.delay_controller.a_value, width=5 + ) + self.a_equation_entry.grid_into( + self.delay_controls, row=3, column=1, pady=4, padx=4, sticky="e" + ) + self.delay_controller.bind_properties( + "a_value", self.a_equation_entry, "value_variable" + ) + + Label("x +").grid_into( + self.delay_controls, row=3, column=2, pady=4, padx=4, sticky="w" + ) + self.b_equation_entry = IntEntry( + value=self.delay_controller.b_value, width=3 + ) + self.b_equation_entry.grid_into( + self.delay_controls, row=3, column=3, pady=4, padx=4, sticky="w" + ) + self.delay_controller.bind_properties( + "b_value", self.b_equation_entry, "value_variable" + ) + + self.start_ajustement_placement = Button( + "Start wavelength Placement", + user_event_callback=self.user_clicked_ajustement_placement, + ) + self.start_ajustement_placement.grid_into( + self.delay_controls, + row=4, + column=0, + columnspan=3, + pady=4, + padx=4, + sticky="ns", + ) + + self.bind_properties( + "has_delay_device", self.start_ajustement_placement, "is_enabled" + ) + + self.start_move_left = Button( + "Left", + user_event_callback=self.user_clicked_left_direction, + ) + self.start_move_left.grid_into( + self.delay_controls, + row=5, + column=0, + pady=4, + padx=4, + sticky="ns", + ) + self.bind_properties( + "has_delay_device", self.start_move_left, "is_enabled" + ) + + self.start_move_right = Button( + "Right", + user_event_callback=self.user_clicked_right_direction, + ) + self.start_move_right.grid_into( + self.delay_controls, + row=5, + column=1, + pady=4, + padx=4, + sticky="nsw", + ) + + self.bind_properties( + "has_delay_device", self.start_move_right, "is_enabled" + ) + + self.start_homing = Button( + "Homing Placement", + user_event_callback=self.user_clicked_homing, + ) + self.start_homing.grid_into( + self.delay_controls, + row=6, + column=0, + pady=4, + padx=4, + sticky="nsw", + ) + self.bind_properties( + "has_delay_device", self.start_homing, "is_enabled" + ) + + def user_clicked_ajustement_placement(self, even, button): + delay_position = self.delay_controller.linear_relation_delays_and_wavelength(self.wavelenght_entry.value) #modifier l'équation de la relation en fct de la nouvelle implémentation + ActionMove(position=(delay_position,), linear_motion_device=self.delay_device).perform() + + def user_clicked_homing(self, even, button): + ActionHome(linear_motion_device=self.delay_device).do_perform() + + def user_clicked_left_direction(self, even, button): + ActionMoveBy(d_position=(5,), linear_motion_device=self.delay_device).do_perform() + + def user_clicked_right_direction(self, even, button): + ActionMoveBy(d_position=(-5,), linear_motion_device=self.delay_device).do_perform() + def user_clicked_saving_position(self, even, button): corner_label = button.label self.map_controller.parameters[ @@ -593,9 +787,9 @@ def user_clicked_saving_position(self, even, button): self.can_start_map = True def user_clicked_clear(self, even, button): - value_to_clear = self.map_controller.parameters - - ActionClear(value_to_clear) + for corner in self.map_controller.parameters: + self.map_controller.parameters[corner] = None + self.can_start_map = None def user_clicked_map_aquisition_image(self, event, button): @@ -625,6 +819,7 @@ def save_map_experience(self): exp.perform_in_background_thread() + def user_clicked_configure_button(self, event, button): restart_after = False @@ -749,6 +944,12 @@ def microscope_run_loop(self): self.after(20, self.microscope_run_loop) + def delay_return_home(self): + if self.delay_device.position() != 0: + ActionHome(linear_motion_device=self.delay_device).perform() + else: + pass + def about(self): Dialog.showinfo( title="About Microscope", @@ -763,6 +964,7 @@ def help(self): def quit(self): try: self.release_provider() + self.delay_return_home() except Exception as err: pass diff --git a/src/pymicroscope/plugins/delay_line.py b/src/pymicroscope/plugins/delay_line.py new file mode 100644 index 0000000..e5c5a6e --- /dev/null +++ b/src/pymicroscope/plugins/delay_line.py @@ -0,0 +1,17 @@ +from struct import * +from mytk import * + + +#for eventully automated +class DelaysController(Bindable): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.port = None + self.a_value = -0.302 + self.b_value = 285 + + def linear_relation_delays_and_wavelength(self, wavelength_value): + '''By the value setting at the interface, the linear relation delays and wavelength fonction return the delay position at a certain wavelenght''' + delay_position = (self.a_value)*wavelength_value + self.b_value + return delay_position + diff --git a/tests/test_delais.py b/tests/test_delais.py deleted file mode 100644 index 34039ca..0000000 --- a/tests/test_delais.py +++ /dev/null @@ -1,87 +0,0 @@ -import unittest -from mytk import * -import pylablib -import Thorpy -from pylablib.devices.Thorlabs import kinesis -from thorlabs_apt_device import APTDevice -from thorlabs_apt_device.devices import TDC001 -from thorlabs_apt_device.enums import EndPoint, LEDMode -import numpy as np -import serial -from serial.tools import list_ports -from hardwarelibrary.communication.usbport import USBPort - - - -CONTROLLER_SERIAL_PATH = "/dev/cu.wlan-debug" - -class TestDelais(unittest.TestCase): - def setUp(self): - self.init_thorlabs = APTDevice() - self.init_thorlabs.__init__() - self.port = serial.Serial(CONTROLLER_SERIAL_PATH, baudrate=19200, timeout=3) - self.port.reset_input_buffer() - self.port.reset_output_buffer() - self.thorpy = Thorpy() - - - def tearDown(self): - if self.init_thorlabs is not None: - self.init_thorlabs.close() - if self.port is not None: - self.port.close() - - @unittest.SkipTest - def test010_list_ports(self): - ports_list = serial.tools.list_ports.comports() - self.assertIsNotNone(ports_list) - - for port_info in ports_list: - print(f"Device:{port_info.device} vid:{port_info.vid} pid:{port_info.pid}") - - self.assertTrue(len(ports_list) > 0) - - @unittest.SkipTest - def test020_list_kinesis_device(self): - list = kinesis.list_kinesis_devices() - print(list) - - @unittest.SkipTest - def test000_init(self): - usb_port = USBPort() - self.assertTrue(usb_port) - devices = usb_port.allDevices() - print(devices) - - @unittest.SkipTest - def test001_port(self): - ports_list = serial.tools.list_ports.comports() - self.assertIsNotNone(ports_list) - print(ports_list) - - @unittest.SkipTest - def test002_find_device(self): - self.assertTrue(self.init_thorlabs) - print(self.init_thorlabs) - - @unittest.SkipTest - def test003_information_device(self): - print(self.init_thorlabs._log) - - print(self.init_thorlabs._port) - - print(self.init_thorlabs.controller, self.init_thorlabs.bays, self.init_thorlabs.channels) - - @unittest.SkipTest - def test004_commande(self): - self.init_thorlabs._write(LEDMode.MOVING) - - def test005_thorpy_methode(self): - - - - - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/test_kinesisdevice.py b/tests/test_kinesisdevice.py new file mode 100644 index 0000000..c70ed55 --- /dev/null +++ b/tests/test_kinesisdevice.py @@ -0,0 +1,114 @@ +import unittest +from mytk import * +from pylablib.devices.Thorlabs import kinesis +import platform + +SERIAL_NUMBER = "83849018" +class TestKinesisDevice(unittest.TestCase): + @classmethod + def setUpClass(cls): + if platform.system() == "Windows": + cls.port = kinesis.KinesisMotor(conn=SERIAL_NUMBER) + else: + raise RuntimeError("This test is only for Windows platform with a Thorlabs device connected.") + + super().setUpClass() + def setUp(self): + self.port = kinesis.KinesisMotor(conn=SERIAL_NUMBER) + + def tearDown(self): + self.port.close() + + @unittest.SkipTest + def test001_list_kinesis_device(self): + list = kinesis.list_kinesis_devices()[0] + print(list) + print(list[0]) + information = kinesis.BasicKinesisDevice(list[0]) + print(information) + + @unittest.SkipTest + def test002_get_information(self): + print(self.port) + self.assertTrue(self.port) + #self.port._home() + print(self.port.get_position(channel=[1])) + #print(self.port._get_position()) + #self.port._move_by() + #print(self.port._get_position()) + #setting = self.port.get_settings() #ensemble des paramètre setté pour les longueurs d'onde + #print(setting) + info = self.port.get_full_info() + print(info) + home_param = self.port.get_homing_parameters(channel=[1]) + #home_param = self.port._get_homing_parameters() + print(home_param) + limit_param = self.port.get_limit_switch_parameters() + #limit_param = self.port._get_limit_switch_parameters() + print(limit_param) + + #veloc_param = self.port._get_velocity_parameters(channel=[1]) + veloc_param = self.port.get_velocity_parameters(channel=[1]) + print(veloc_param) + + #jog_param = self.port._get_jog_parameters(channel=[1]) + jog_param = self.port.get_jog_parameters(channel=[1]) + print(jog_param) + + #movebeat_param = self.port._get_gen_move_parameters(channel=[1]) + movebeat_param = self.port.get_gen_move_parameters(channel=[1]) + print(movebeat_param) + + @unittest.SkipTest + def test003_send_comm(self): + #self.port.set_device_variable(key="associate_variable", value=3000) #pas réussi + self.port.send_comm_data(messageID=0x0448, data="4000", source=0x02) #bouge d'une distance de.. vers l'avant ps: pas de négatif!! + #self.port.send_comm_data(messageID=0x0453, data="2000") # va à la position nommé + print(self.port._get_position(channel=[1])) + #pas de stop point au jogging/ bien setter les paramètres initiales comme le point 0 + #pour une valeur data = 2000 la position est de 12333 + self.port.recv_comm() + + + @unittest.SkipTest + def test004_move_the_delais(self): + position1 = self.port._get_position(channel=[1]) + print(position1) + self.port._move_to(position=10, channel=[1]) + position2 = self.port._get_position(channel=[1]) + print(position2) + self.port._move_to(position=10000, channel=[1]) + position3 = self.port._get_position(channel=[1]) + print(position3) + #conclusion: les commande vont plus vite que le déplacement du délais. Il faut dont utiliser send_commande pour pouvoir faire un wait_move ou autre + + @unittest.SkipTest + def test005_home_movement(self): + self.port.home() + home_position = self.port.get_position(channel=[1]) + #self.port.wait_for_home(channel=[1]) + print(home_position) + + @unittest.SkipTest + def test006_complet_preparation_mouvement(self): + self.port.move_to(position=900000, channel=[1], scale=True) + #self.port.move_by(distance=-100, channel=[1]) # les moins pour reculer + does_move = self.port.is_moving(channel=[1]) + self.assertTrue(does_move) + self.port.wait_move(channel=[1]) + print(self.port.get_position(channel=[1])) + + #@unittest.SkipTest + def test007_fixe_position(self): + print(self.port.get_position(channel=[1])) + + @unittest.SkipTest #pas nécessaire ne fonctionne pas + def test008_setup_point_initial(self): + self.port.set_position_reference() + + #max distance [857599]mm + + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file