Package to control Particulars TCT easily from Python.
The following line
pip3 install git+https://github.com/SengerM/PyticularsTCT
should be enough.
After installing PyUSB you may get the common permission error USBError: [Errno 13] Access denied (insufficient permissions)
. This solved the problem for me.
- First clone (or download) this repo in your favourite directory.
- Run
pip3 install -e C:\wherever\you\cloned\this\repo
- Install the file
vcredist_x64.exe
located inPyticularsTCT/PyticularsTCT/ximc/win64
. (You already downloaded it, just navigate within the repo to that file.)
Now it should work.
This package depends on others which you will have to install (you will discover when you first try to use this one). Most of them are easy but some, such as PyUSB, may be more tricky. However you should be able to make it work with help from Google.
This package was developed and tested only in our setup at UZH. It worked both on Linux (Ubuntu 20.04) and Windows (10).
Usage example:
import PyticularsTCT
from PyticularsTCT.find_ximc_stages import map_coordinates_to_serial_ports
import time
import numpy as np
stages_coordinates = { # This dictionary maps the serial number of each stage to a coordinate. To know the serial numbers you can use the function find_ximc_serial_devices defined in the file find_ximc_stages.py.
'00003A48': 'x',
'00003A57': 'y',
'000038CE': 'z',
}
ports_dict = map_coordinates_to_serial_ports(stages_coordinates) # You are not obliged to do this, you can just hardcode the serial ports in the line below. The advantage of this is that you don't need to change this each time the computer is restarted or the USB ports are disconnected.
tct = PyticularsTCT.TCT(x_stage_port=ports_dict['x'], y_stage_port=ports_dict['y'], z_stage_port=ports_dict['z'])
# Sweep laser intensity ---
tct.laser.on()
print(f'Laser is {tct.laser.status} at a frequency of {tct.laser.frequency} Hz.') # Should print 'Laser is on at a frequency of 1000 Hz'.
tct.laser.frequency = 2e3 # Change the frequency of the laser.
print(f'The frequency has been changed to {tct.laser.frequency} Hz.')
for DAC in np.linspace(0,1023,5):
tct.laser.DAC = int(DAC) # Change the intensity of the laser.
print(f'Laser DAC = {tct.laser.DAC}')
time.sleep(1)
# Sweep position using the mechanical stages ---
current_position = tct.stages.position # Store current position to go back in the end.
print(f'Start position: {current_position}') # Should print something like 'Start position: (0.23912637, 0.07196379, 0.5165688)' where each value is x,y,z.
tct.laser.DAC = 0 # This is the most intense setting.
tct.stages.move_rel(z=-555e-6) # Move 555 µm in the "-z" direction.
for kz in range(11):
tct.stages.move_rel(z=1111e-6/11) # Move in the "+z" direction.
print(f'Current position is {tct.stages.position}')
time.sleep(1)
print('Going back to start position...')
tct.stages.move_to(*current_position) # Go back to original position.
print(f'Current position is {tct.stages.position}')
print('Will turn off the laser now...')
tct.laser.off()
print(f'Laser status is {tct.laser.status}.')
print('Bye!')
Ideally you should use the TCT
class defined in the __init__.py
file that abstracts the whole setup. This is a very simple class which has a stages
artribute containing an instance of TCTStages
defined in stage.py
and an instance of ParticularsLaserController
defined in ParticularsLaserController.py
. The documentation is in the docstrings.
The X,Y,Z stages in the setup are controlled by 8SMC5-USB - Stepper & DC Motor Controller units. The programming interface is descripted here. PyticularsTCT is shipped with a hardcoded copy of the binaries for some operating systems together with a slightly modified version of the Python script that is provided by the original author of the ximc library (see PyticularsTCT/ximc
) in such a way that the control of the motors becomes easier. More information in the README.md
file located in PyticularsTCT/ximc
.
If you want control only the motors as a standalone package here there is an example:
from PyticularsTCT.stage import TCTStages
from PyticularsTCT.find_ximc_stages import map_coordinates_to_serial_ports
stages_coordinates = { # This is what I have in the lab, in your case it may be different.
'XIMC_XIMC_Motor_Controller_00003A48': 'x',
'XIMC_XIMC_Motor_Controller_00003A57': 'y',
'XIMC_XIMC_Motor_Controller_000038CE': 'z',
}
ports_dict = map_coordinates_to_serial_ports(stages_coordinates) # You are not obliged to do this, you can just hardcode the serial ports in the line below. The advantage of this is that you don't need to change this each time the computer is restarted or the USB ports are disconnected.
stages = TCTStages(x_stage_port=ports_dict['x'], y_stage_port=ports_dict['y'], z_stage_port=ports_dict['z'])
current_position = stages.position
print(f'Initial position: {current_position}') # Print (x,y,z) position.
stages.move_to(0,0,0) # Move to x=y=z=0.
print(stages.position)
stages.move_rel(z = 1e-2) # Move z 1 centimeter.
print(stages.position)
stages.move_rel(z = -.5e-2) # Move z -0.5 centimeter.
print(stages.position) # Position should be the initial position.
stages.move_rel(x = 1e-6, y = 2e-6) # Move 1 µm in x and 2 µm in y.
print(stages.position)
stages.move_to(*current_position) # Go back to previous position.
print(stages.position)
If, for some very weird reason, you want to control each of the motorized stages individually it is also possible, have a look at the source code of stage.py
.
The PyticularsLaserController is a pure Python module. If you want to use this module individually, here there is an example:
from PyticularsTCT.ParticularsLaserController import ParticularsLaserController
from time import sleep
laser = ParticularsLaserController() # Open connection to laser.
laser.on() # This is equivalent to `laser.status = 'on'`.
print(f'Current laser status is: {laser.status}') # This should print "on".
for frequency in [50,100,1e3,10e3,100e3]:
for DAC in [0,222,444,666,888,1023]:
print(f'Setting f = {frequency} Hz, DAC = {DAC}...')
laser.frequency = frequency # Change the frequency.
laser.DAC = DAC # Change the DAC, from 0 to 1023.
print(f'Current frequency = {laser.frequency} Hz') # This prints the current frequency.
print(f'Current DAC = {laser.DAC}') # This prints the current DAC value.
sleep(.5)
print('Will turn the laser off...')
laser.off() # This is equivalent to `laser.status = 'off'`.
print(f'Laser status is: {laser.status}')
A simple graphical interface is provided by PyticularsTCT to perform quick tests, laser alignment, etc. See the tct_graphic_interface.py
script. The graphical interface should be cross platform, though it has only been tested on Linux (Dec-2021).
- tct_scripts. Collection of scripts to perform scans.
- signals. Package to process TCT signals.
- landaupy. Landau (and Langauss) distribution(s) for Python.