Examples¶
Here you will find an in-depth example of using the Pycont library.
Pump Usage Example¶
This is an example of how to control a Tricontinent pump, using the Pycont library.
Below are samples of a .json configuration file which holds the parameters for the pump, and the python script which will control the pump.
JSON Configuration File (pump_setup_config.json)¶
This is the structure of a .json configuration file.
- io
This is the I/O port which will communicate with the pump from the host PC. Below is an example of communicating on a UNIX based system.
- baudrate
This is the communication baudrate for serial communication. This is usually set to 9600
- timeout
The default time to wait until the communication times out. (This is repeated several times)
- default
These are the default setting for all the pumps on the line. Here is where you set parameters, such as speed and volume.
- volume
The maximum volume available to pump
- micro_step_mode
This is the default microstep mode for the pumps. Mode 2 should suffice.
- top_velocity
This is the top speed for all the pumps.
- initialize_valve_position
The default position for the 3/4-way valve on top of the pump.
- groups
These are the collection of pumps connected on the line. Here, they are named after the chemicals which they hold.
- pumps
This is where we can set the individual settings for each pump. Each pump listed in the “group” section, must have it’s “switch” position initialised here.
- switch
The switch setting on the back of the pump. This identifies each pump on the line, hardware-wise.
JSON configuration file example:
{
"io":
{
"port": "/dev/ttyUSB0",
"baudrate": 9600,
"timeout": 1
},
"default":
{
"volume": 5,
"micro_step_mode": 2,
"top_velocity": 5000,
"initialize_valve_position": "I"
},
"groups":
{
"chemicals": ["acetone", "water"]
},
"pumps":
{
"acetone":
{
"switch": "0"
},
"water":
{
"switch": "1"
}
}
}
Python Script (pycont_test.py)¶
This is an example of a Python script which uses Pycont to control a set of pumps.
The steps are easy:
First, import the appropriate module. Here, it is: ‘pycont.controller’
Load the .json configuration file in a Controller object, e.g. ‘MultiPumpController’
Smart initialize the pumps with ‘smart_initialize()’ function.
The pumps are now initialized and ready for use!
The pumps can be accessed in two ways:
- ‘controller.pumps[‘pump_name’]’
- ‘controller.pump_name’
- These are personal preference, use whichever you like.
Have fun!
Python Script Example:
# simply import the module
import pycont.controller
# link to your config file
SETUP_CONFIG_FILE = './pump_setup_config.json'
# and load the config file in a MultiPumpController
controller = pycont.controller.MultiPumpController.from_configfile(SETUP_CONFIG_FILE)
# initialize the pumps in a smart way, if they are already initialized we do not want to reinitialize them because they got back to zero position
controller.smart_initialize()
# individual pumps can be accessed in two ways:
# - in the dict ```controller.pumps['pump_name']```
# - directly as an attribute ```controller.pump_name```
# the two above method link to the same pump instance
# we use the first convention because it highlight well the name of the pumps
# the second convention is certainly more convenient for online testing using ipython
# ask a pump to go to a specific position, calling it by its name
# the wait argument signifies if the command is blocking or non-blocking
# if wait=False (default), the function returns immediately and let you go on
# volumes are always in mL
controller.pumps['acetone'].go_to_volume(0.5, wait=False)
# if wait=True, the function returns only after the pump finished his move
controller.pumps['water'].go_to_volume(0.5, wait=True)
# of course you can pump and deliver volumes
controller.pumps['water'].pump(0.5, wait=True)
controller.pumps['water'].deliver(0.5, wait=True)
# and those function tells you is the action what feasible or not
succeed = controller.pumps['water'].pump(1000, wait=True)
if succeed:
print('How could you pump 1000 mL')
else:
print('You cannot pump 1000 mL!')
# the pump and deliver function respectively have a from_valve and to_valve argument
# if set, the valve position is set before the pump moves
controller.pumps['water'].pump(0.5, from_valve=pycont.controller.VALVE_INPUT, wait=True)
controller.pumps['water'].deliver(0.5, to_valve=pycont.controller.VALVE_OUTPUT, wait=True)
# you can also transfer volume from valve to valve
# the function is recusive so even of the volume is bigger than the syringe, it will iterate as many times as needed
controller.pumps['acetone'].transfer(7, pycont.controller.VALVE_INPUT, pycont.controller.VALVE_OUTPUT) # this function is blocking, no wait argument
# note that it pump from and to the position it is currently set to, made it easy to leave a small volume in the pump if needed
# you can also iterate on all the pumps
for _, pump in controller.pumps.items():
pump.go_to_volume(0) # here wait=False by default, all pumps move in parrallel
# wait until all pumps are ready to operate again
controller.wait_until_all_pumps_idle()
# you can apply command to all pumps in parrallel, in one command!
# this is the purpose of the controller.apply_command_to_all_pumps
# let's have the pumps go to their max volume
# the below function go through the list of pumps and run the 'go_to_max_volume' function without argument
controller.apply_command_to_all_pumps('go_to_max_volume')
while controller.are_pumps_busy():
# and record the volume in real time as the pumps are moving
print(controller.apply_command_to_all_pumps('get_volume'))
# and you set pump group in the config file and apply command to a group of pumps
# check the config file for group definition
# in this example 'chemicals' contains ['water', 'acetone']
controller.apply_command_to_group('chemicals', 'go_to_volume', 1)
controller.wait_until_all_pumps_idle()
# the two above function call the more generic apply_command_to_pumps function
# which take a list of pumps to apply the command to
controller.apply_command_to_pumps(['water', 'acetone'], 'go_to_volume', 1.5)
controller.wait_until_all_pumps_idle()
# So the three above way are different way to do the same things
# groups are a powerful way to automate initialization of your setup
time.sleep(1) # just to pause so that you can hear the sound of valve movements
# of course you can change valve position
# for this you should use the command set_valve_position(valve_position) using for valvle position the global variable define in pycont. They are VALVE_INPUT, VALVE_OUTPUT, VALVE_BYPASS, VALVE_EXTRA
controller.pumps['acetone'].set_valve_position(pycont.controller.VALVE_OUTPUT)
controller.pumps['water'].set_valve_position(pycont.controller.VALVE_OUTPUT)
time.sleep(1) # just to pause so that you can hear the sound of valve movements
# of course you can change all the valve position at once
# apply_command_to_all_pumps will forward all additional argument
controller.apply_command_to_all_pumps('set_valve_position', pycont.controller.VALVE_INPUT)
# get valve position
print(controller.pumps['water'].get_valve_position())
print(controller.apply_command_to_all_pumps('get_valve_position'))
# and compare it with global defined variable
if controller.pumps['water'].get_valve_position() == pycont.controller.VALVE_INPUT:
print('The valve for water is indeed in input position')
else:
print('Something went wrong when setting the valve position')
# finally there is some tools to track the status of the pumps
print(controller.pumps['water'].is_idle()) # is the pump ready?
print(controller.pumps['water'].is_busy()) # is the pump busy?
print(controller.pumps['water'].current_volume) # what volume is in the syringe, this is a direct reading from the pump position, we actually ask the pump!
print(controller.pumps['water'].remaining_volume) # what volume can still be pump
print(controller.pumps['water'].is_volume_pumpable(1)) # can I pump 1 ml?
print(controller.pumps['water'].is_volume_deliverable(1)) # can I deliver 1 ml?
# But note that the above tools are mostly encompassed in the higher level functions such as controller.wait_until_all_pumps_idle() which check is_idle() for all pumps
# Have fun!
Note
Insert more examples here!