PyHamilton Reference Guide
Author: Stefan Golas (Contact stefanmgolas@gmail.com)
Contents
- Intro
- Installation
- Your First PyHamilton Method
- How PyHamilton Works
- Expanding The API
Intro
PyHamilton is an open-source Python interface for programming Hamilton liquid-handling robots. PyHamilton is designed to be accessible while affording unlimited flexibility to the developer. We believe that an open-source community driven framework will accelerate discovery and enable a new generation of biological workflows.
Installation
-
Install and test the standard Hamilton software suite for your system.
-
Install 32-bit python <=3.9, preferably using the executable installer at Python Release Python 3.9.0 | Python.org. Python 3.10+ is known to cause an installation issue with some required pythonnet/pywin32 modules.
-
Make sure git is installed. Git - Downloading Package
-
Make sure you have .NET framework 4.0 or higher installed. https://www.microsoft.com/en-us/download/details.aspx?id=17851
-
Update your pip and setuptools.
> python -m pip install --upgrade pip > pip install --upgrade setuptools
-
Install pyhamilton.
pip install pyhamilton
-
Run the pyhamilton autoconfig tool from the command line.
pyhamilton-configure
-
Test your PyHamilton installation
The easiest way to test your PyHamilton installation is by running the following in your terminalmkdir new-project cd new-project pyhamilton-new-project py robot_method.py
Your First PyHamilton Method
Here is how to write your first PyHamilton method.
First, create a new directory called my-project
. Then, open the Hamilton Method Editor and create a new Layout file. Add 5 96-tip tip holders named “tips_1”, “tips_2”, etc. Then add 5 96-well plates named “plate_1”, “plate_2”, etc.
deck.lay
Next, create a file named robot_method.py
in your preferred text editor. Inside this file, paste this code chunk to import the necessary functions and classes from pyhamilton:
from pyhamilton import (HamiltonInterface, LayoutManager,
Plate96, Tip96, initialize, tip_pick_up, tip_eject,
aspirate, dispense, oemerr, resource_list_with_prefix)
Then, initialize your deck resources and declare a default liquid class. The LayoutManager class references the contents of a layfile to ensure that resource assignments in Python are consistent with the layfile.
lmgr = LayoutManager('deck.lay')
plates = resource_list_with_prefix(lmgr, 'plate_', Plate96, 5)
tips = resource_list_with_prefix(lmgr, 'tips', Tip96, 5)
liq_class = 'StandardVolumeFilter_Water_DispenseJet_Empty'
Make sure the liquid class in an aspiration step matches the tip type.
Now that your deck resources are initialized, let’s specify some aspiration and dispense patterns. These will convey the same information as sequences in Venus, but are lists of well indexes rather than static references to a predefined object. An aspiration pattern will be a list of 2-tuples where the first element is a Plate object and the second element is an integer. The length of this list is always 8, and positions in the aspiration pattern specify channels. Unused channels will have a None at that position in the list.
#Example aspiration pattern
#aspiration_poss = [(Plate96, 0), (Plate96, 1), (Plate96, 2), None, None, None, None, None]
#vols = [100, 100, 100, None, None, None, None, None]
aspiration_poss = [(plates[0], x) for x in range(8)]
dispense_poss = [(plates[0], x) for x in range(8,16)]
vols_list = [100]*8
List comprehensions are very convenient tools for specifying liquid-handling patterns. Let’s also specify which tips we’re going to use.
tips_poss = [(tips[0], x) for x in range(8)]
Now we are ready to enter the PyHamilton interface. We’re going to use simulation mode this time. The HamiltonInterface class spawns a subprocess which starts a server that communicates with the Venus universal method (STAR_OEM_noFan.hsl). We must instantiate this inside the if __name__ == '__main__'
guard.
if __name__ == '__main__':
with HamiltonInterface(simulate=True) as ham_int:
initialize(ham_int)
Finally, let’s add functions that run our aspiration and dispense patterns. aspirate
and dispense
functions take parallel lists of length 8 of aspiration patterns and volumes that specify the activity of each channel.
if __name__ == '__main__':
with HamiltonInterface(simulate=True) as ham_int:
initialize(ham_int)
tip_pick_up(ham_int, tips_poss)
aspirate(ham_int, aspiration_poss, vols_list, liquidClass = liq_class)
dispense(ham_int, dispense_poss, vols_list, liquidClass = liq_class)
tip_eject(ham_int, tips_poss)
Our robot_method.py
file should now look like this:
from pyhamilton import (HamiltonInterface, LayoutManager,
Plate96, Tip96, initialize, tip_pick_up, tip_eject,
aspirate, dispense, oemerr, resource_list_with_prefix)
liq_class = 'StandardVolumeFilter_Water_DispenseJet_Empty_with_transport_vol'
lmgr = LayoutManager('deck.lay')
plates = resource_list_with_prefix(lmgr, 'plate_', Plate96, 5)
tips = resource_list_with_prefix(lmgr, 'tips', Tip96, 5)
liq_class = 'StandardVolumeFilter_Water_DispenseJet_Empty'
aspiration_poss = [(plates[0], x) for x in range(8)]
dispense_poss = [(plates[0], x) for x in range(8,16)]
vols_list = [100]*8
tips_poss = [(tips[0], x) for x in range(8)]
if __name__ == '__main__':
with HamiltonInterface(simulate=True) as ham_int:
initialize(ham_int)
tip_pick_up(ham_int, tips_poss)
aspirate(ham_int, aspiration_poss, vols_list, liquidClass = liq_class)
dispense(ham_int, dispense_poss, vols_list, liquidClass = liq_class)
tip_eject(ham_int, tips_poss)
robot_method.py
my-project
│ deck.lay
│ robot_method.py
Project directory
Once your script looks like the one above, you can run it from the command line with py robot_method.py
.
Troubleshooting
-
If you encounter a “silent error” such as your initialization hanging, or your script crashing without a specific reason, or an unclear error code, try to run your script with HamiltonInterface(simulate=True). This will run PyHamilton with Run Control open in a window rather than in the background. From here you can turn simulate on or off in Run Control, and monitor the execution of your script. In rare cases, Run Control throws errors that are not visible at the Python level.
-
If you encounter an error relating to HxFan (i.e., your robot does not have a fan), open pyhamilton/star-oem/VENUS_Method/STAR_OEM_Test.med, navigate to the “HxFan” grouping, and delete all commands under this grouping.
-
If you would like to test your PyHamilton installation on a computer not connected to a Hamilton robot, use
HamiltonInterface(simulate=True)
to open your interface inside your robot script. -
If your initialization hangs (such as on initial_error_example.py), try these steps:
a. Make sure you don’t have any other program running which is communicating with the robot e.g. Venus run control
b. Make sure the .dlls referenced in__init__.py
are unblocked. See this StackOverflow thread for more details. -
Instrument configuration errors can arise right when you start a method, and can call PyHamilton to fail silently if not in “simulate” ie windowed mode. To fix this, make sure to reference a Layfile with the LayoutManager tool that you know works on your robot, before you instantiate the HamiltonInterface class. You can also manually copy this file into pyhamilton/pyhamilton/star-oem/VENUS_Method/STAR_OEM_Test.lay