Skip to content

Commit

Permalink
Removed utils.py file and added _getxyz() to :class: as a instead. Mo…
Browse files Browse the repository at this point in the history
…dified all .py files to reflect this change and consolidated module imports
  • Loading branch information
MariaPoliti committed Jan 19, 2024
1 parent 87de4f9 commit 3fa9501
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 174 deletions.
28 changes: 26 additions & 2 deletions science_jubilee/labware/Labware.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import os
import json

import numpy as np

from dataclasses import dataclass
from itertools import chain
from typing import List, Dict, Tuple, Union, Iterable, NamedTuple
import os
import json


@dataclass
Expand Down Expand Up @@ -509,6 +511,28 @@ def withWellOrder(self, order) -> list:

self.wells = ordered_wells

@staticmethod
def _getxyz(location: Union[Well, Tuple, 'Location']):
"""Helper function to extract the x, y, z coordinates of a location object.
:param location: The location object to extract the coordinates from. This can either be a
:class:`Well`, a :tuple: of x, y, z coordinates, or a :class:`Location` object
:type location: Union[Well, Tuple, Location]
:raises ValueError: If the location is not a :class:`Well`, a :class:`tuple`, or a :class:`Location` object
:return: The x, y, z coordinates of the location
:rtype: float, float, float
"""
if type(location) == Well:
x, y, z = location.x, location.y, location.z
elif type(location) == Tuple:
x, y, z = location
elif type(location)==Location:
x,y,z= location._point
else:
raise ValueError("Location should be of type Well or Tuple")

return x,y,z

## Adapted from Opentrons API opentrons.types##
class Point(NamedTuple):
"""A point in the Jubilee 3D coordinate system.
Expand Down
14 changes: 8 additions & 6 deletions science_jubilee/tools/Camera.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
from .Tool import Tool, ToolStateError, requires_active_tool
from science_jubilee.labware.Labware import Labware, Well
from typing import Tuple, Union
import cv2
import matplotlib
import platform
import time

import numpy as np

matplotlib.use("TkAgg")
from matplotlib import pyplot as plt
import numpy as np
import time
import platform
from science_jubilee.labware.Labware import Well
from science_jubilee.tools.Tool import Tool, requires_active_tool
from typing import Tuple


if platform.system() == "Linux":
import picamera # Note that this can only be installed on raspbery pi.
Expand Down
14 changes: 8 additions & 6 deletions science_jubilee/tools/Loop.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError, requires_active_tool
from science_jubilee.labware.Labware import Labware, Well
from typing import Tuple, Union
import warnings
import numpy as np
import os
import json
import os
import random
import warnings

import numpy as np

from science_jubilee.labware.Labware import Well
from science_jubilee.tools.Tool import Tool, requires_active_tool
from typing import Tuple


class Loop(Tool):
Expand Down
4 changes: 2 additions & 2 deletions science_jubilee/tools/PeristalticPumps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import logging
import os

from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError
from typing import Tuple, Union
from science_jubilee.tools.Tool import Tool
from typing import Union

class PeristalticPumps(Tool):
"""
Expand Down
17 changes: 8 additions & 9 deletions science_jubilee/tools/Pipette.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from science_jubilee.labware.Labware import Labware, Well, Location
from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError, requires_active_tool
from science_jubilee import utils
from typing import Tuple, Union


Expand Down Expand Up @@ -139,7 +138,7 @@ def aspirate(self, vol: float, location : Union[Well, Tuple, Location], s:int =
:type s: int, optional
:raises ToolStateError: If the pipette does not have a tip attached
"""
x, y, z = utils.getxyz(location)
x, y, z = Labware._getxyz(location)

if type(location) == Well:
self.current_well = location
Expand Down Expand Up @@ -189,7 +188,7 @@ def dispense(self, vol: float, location :Union[Well, Tuple, Location], s:int = 2
:type s: int, optional
:raises ToolStateError: If the pipette does not have a tip attached
"""
x, y, z = utils.getxyz(location)
x, y, z = Labware._getxyz(location)

if type(location) == Well:
self.current_well = location
Expand Down Expand Up @@ -240,7 +239,7 @@ def transfer(self, vol: float, source_well: Union[Well, Tuple, Location],

vol_ = self.vol2move(vol)
# get locations
xs, ys, zs = utils.getxyz(source_well)
xs, ys, zs = Labware._getxyz(source_well)

if self.is_primed == True:
pass
Expand All @@ -253,7 +252,7 @@ def transfer(self, vol: float, source_well: Union[Well, Tuple, Location],

if isinstance(destination_well, list):
for well in destination_well:
xd, yd, zd = utils.getxyz(well)
xd, yd, zd = Labware._getxyz(well)

self._machine.safe_z_movement()
self._machine.move_to(x= xs, y=ys)
Expand Down Expand Up @@ -454,7 +453,7 @@ def pickup_tip(self, tip_ : Union[Well, Tuple] = None):
else:
tip = tip_

x, y, z = utils.getxyz(tip)
x, y, z = Labware._getxyz(tip)
self._machine.safe_z_movement()
self._machine.move_to(x=x, y=y)
self._pickup_tip(z)
Expand All @@ -475,9 +474,9 @@ def return_tip(self, location: Well = None):
:type location: :class:`Well`, optional
"""
if location is None:
x, y, z = utils.getxyz(self.first_available_tip)
x, y, z = Labware._getxyz(self.first_available_tip)
else:
x, y, z = utils.getxyz(location)
x, y, z = Labware._getxyz(location)
self._machine.safe_z_movement()
self._machine.move_to(x=x, y=y)
# z moves up/down to make sure tip actually makes it into rack
Expand Down Expand Up @@ -512,7 +511,7 @@ def drop_tip(self, location: Union[Well, Tuple]):
:param location: The location to drop the tip into
:type location: Union[:class:`Well`, tuple]
"""
x, y, z = utils.getxyz(location)
x, y, z = Labware._getxyz(location)

self._machine.safe_z_movement()
if x is not None or y is not None:
Expand Down
8 changes: 4 additions & 4 deletions science_jubilee/tools/PumpDispenser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import os

from science_jubilee.labware.Labware import Labware, Well, Location
from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError, requires_active_tool
from science_jubilee.tools.Tool import Tool
from typing import Tuple, Union
from science_jubilee import utils


class PumpDispenser(Tool):
"""
Expand Down Expand Up @@ -116,7 +116,7 @@ def dispense(self, vol: Union[float, int, list], location:Union[Well, Tuple, Loc


# calculate XY location for each dispense head
x, y, z = utils.getxyz(location)
x, y, z = Labware._getxyz(location)

if type(location) == Well:
if z == location.z:
Expand Down Expand Up @@ -171,7 +171,7 @@ def prime_lines(self, volume: Union[int, float] = None, location:Union[Well, Tup
location = self.waste

# calculate XY location for each dispense head
x, y, z = utils.getxyz(location)
x, y, z = Labware._getxyz(location)

if type(location) == Well:
if z == location.z:
Expand Down
14 changes: 6 additions & 8 deletions science_jubilee/tools/Sonicator.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import adafruit_mcp4725
import board
import busio
import digitalio
import json
import logging
import serial
import time
import digitalio
import board
import busio
import adafruit_mcp4725



from science_jubilee.labware.Labware import Labware, Well, Location
from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError, requires_active_tool
from science_jubilee import utils
from science_jubilee.tools.Tool import Tool, requires_active_tool
from typing import Tuple, Union


Expand Down Expand Up @@ -226,7 +224,7 @@ def sonicate_well(self, location:Union[Well, Tuple, Location],
raise ValueError("Error: plunge depth is too deep.")


x, y, z = utils._getxyz(location)
x, y, z = Labware.__getxyz(location)

self._machine.safe_z_movement()
self._machine.move_to(x=x,y=y) # Position over the well at safe z height.
Expand Down
109 changes: 21 additions & 88 deletions science_jubilee/tools/Syringe.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError, requires_active_tool
from science_jubilee.labware.Labware import Labware, Well
from typing import Tuple, Union
import json
import os
import warnings

import numpy as np
import os
import json

from science_jubilee.labware.Labware import Labware, Well, Location
from science_jubilee.tools.Tool import Tool, ToolStateError, ToolConfigurationError, requires_active_tool
from typing import Tuple, Union

class Syringe(Tool):
"""A class representation of a syringe.
Expand All @@ -26,7 +27,7 @@ def __init__(self, index, name, config):
self.load_config(config)

def load_config(self, config):
"""_summary_
"""Loads the confirguration file for the syringe tool
:param config: Name of the config file for your syringe. Expects the file to be in /tools/configs
:type config: str
Expand Down Expand Up @@ -108,36 +109,20 @@ def _dispense(self, vol, s: int = 2000):
def aspirate(
self,
vol: float,
s: int = 2000,
well: Well = None,
from_bottom: float = 5,
from_top: float = None,
location: Tuple[float] = None,
location :Union[Well, Tuple, Location],
s: int = 2000
):
"""Aspirate a certain volume from a given well.
:param vol: Volume to aspirate, in milliliters
:type vol: float
:param location: The location (e.g. a `Well` object) from where to aspirate the liquid from.
:type location: Union[Well, Tuple, Location]
:param s: Speed at which to aspirate in mm/min, defaults to 2000
:type s: int, optional
:param well: Well to aspirate from, defaults to None
:type well: Well, optional
:param from_bottom: Distance in z from the bottom of the well to aspirate from in mm, defaults to 5
:type from_bottom: float, optional
:param from_top: Distance in z from the top of the well to aspirate from in mm, can be used instead of from_bottom, defaults to None
:type from_top: float, optional
:param location: Explicit coordinates to aspirate from, can be specified instead of a Well, defaults to None
:type location: Tuple[float], optional
"""
x, y, z = self._get_xyz(well=well, location=location)
if well is not None:
top, bottom = self._get_top_bottom(well=well)
self.current_well = well

if from_bottom is not None and well is not None:
z = bottom + from_bottom
elif from_top is not None and well is not None:
z = top + from_top # TODO: this should be minus, if I'm understanding right?
x, y, z = Labware._getxyz(location)

self._machine.safe_z_movement()
self._machine.move_to(x=x, y=y)
self._machine.move_to(z=z)
Expand All @@ -147,38 +132,21 @@ def aspirate(
def dispense(
self,
vol: float,
s: int = 2000,
well: Well = None,
from_bottom: float = None,
from_top: float = 2,
location: Tuple[float] = None,
location :Union[Well, Tuple, Location],
s: int = 2000
):
"""Dispense a certain volume into a given well.
:param vol: Volume to dispense, in milliliters
:type vol: float
:param location: The location to dispense the liquid into.
:type location: Union[Well, Tuple, Location]
:param s: Speed at which to dispense in mm/min, defaults to 2000
:type s: int, optional
:param well: Well to dispense into, defaults to None, defaults to None
:type well: Well, optional
:param from_bottom: Distance in z from the bottom of the well to dispense from, in mm, defaults to None
:type from_bottom: float, optional
:param from_top: Distance in z from the top of the well to dispense from in mm, can be used instead of from_bottom, defaults to 2
:type from_top: float, optional
:param location: Explicit coordinates to dispense at, can be specified instead of a Well, defaults to None
:type location: Tuple[float], optional
"""
x, y, z = self._get_xyz(well=well, location=location)
if well is not None:
top, bottom = self._get_top_bottom(well=well)
self.current_well = well
"""
x, y, z = Labware._getxyz(location)

if from_bottom is not None and well is not None:
z = bottom + from_bottom
elif from_top is not None and well is not None:
z = top + from_top # TODO: This should be minus, if I understand right?
pass
self._machine.safe_z_movement()
self._machine.move_to(x=x, y=y)
self._machine.move_to(z=z)
Expand Down Expand Up @@ -237,8 +205,8 @@ def transfer(
source_destination_pairs = list(zip(source, destination))
for source_well, destination_well in source_destination_pairs:
# TODO: Large volume transfers which exceed tool capacity should be split up into several transfers
xs, ys, zs = self._get_xyz(well=source_well)
xd, yd, zd = self._get_xyz(well=destination_well)
xs, ys, zs =Labware._getxyz(source_well)
xd, yd, zd = Labware._getxyz(destination_well)

self._machine.safe_z_movement()
self._machine.move_to(x=xs, y=ys)
Expand All @@ -261,38 +229,3 @@ def transfer(
# self.mix(mix_after[0], mix_after[1])
# else:
# pass


@staticmethod
def _get_xyz(well: Well = None, location: Tuple[float] = None):
"""Get the (x,y,z) position of a well.
:param well: The well to fetch position of, defaults to None
:type well: :class:`Well`, optional
:param location: Directly specify an (x,y,z) location, defaults to None
:type location: Tuple[float], optional
:raises ValueError: Must specify either a well or a location
:return: The well location
:rtype: Tuple[float, float, float]
"""
if well is not None and location is not None:
raise ValueError("Specify only one of Well or x,y,z location")
elif well is not None:
x, y, z = well.x, well.y, well.z
else:
x, y, z = location
return x, y, z

@staticmethod
def _get_top_bottom(well: Well = None):
"""Get the top and bottom heights of a well.
:param well: The well to fetch position of, defaults to None
:type well: Well, optional
:return: The z-height of the top and bottom of the well
:rtype: Tuple[float, float]
"""
top = well.top
bottom = well.bottom
return top, bottom

Loading

0 comments on commit 3fa9501

Please sign in to comment.