Skip to content

Commit

Permalink
Merge branch 'v3a' into api-direct-movements-within-well
Browse files Browse the repository at this point in the history
  • Loading branch information
andySigler committed Feb 19, 2018
2 parents 76a1d0e + 73291cd commit 62575a2
Show file tree
Hide file tree
Showing 93 changed files with 5,430 additions and 509 deletions.
2 changes: 1 addition & 1 deletion api/opentrons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,4 @@ def _create_pipette_from_config(
containers = ContainersWrapper(robot)
labware = ContainersWrapper(robot)

__all__ = [containers, instruments, robot, reset, __version__]
__all__ = [containers, instruments, labware, robot, reset, __version__]
24 changes: 10 additions & 14 deletions api/opentrons/api/calibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def _set_state(self, state):

def tip_probe(self, instrument):
inst = instrument._instrument
log.debug('Probing tip with {}'.format(instrument.name))
log.info('Probing tip with {}'.format(instrument.name))
self._set_state('probing')

measured_center = calibration_functions.probe_instrument(
Expand All @@ -45,7 +45,7 @@ def tip_probe(self, instrument):
measured_center=measured_center
)

log.debug('New config: {0}'.format(config))
log.info('New config: {0}'.format(config))

calibration_functions.move_instrument_for_probing_prep(
inst, inst.robot
Expand All @@ -60,7 +60,7 @@ def pick_up_tip(self, instrument, container):
.format(type(container)))

inst = instrument._instrument
log.debug('Picking up tip from {} in {} with {}'.format(
log.info('Picking up tip from {} in {} with {}'.format(
container.name, container.slot, instrument.name))
self._set_state('moving')
inst.pick_up_tip(container._container[0])
Expand All @@ -73,22 +73,22 @@ def drop_tip(self, instrument, container):
.format(type(container)))

inst = instrument._instrument
log.debug('Dropping tip from {} in {} with {}'.format(
log.info('Dropping tip from {} in {} with {}'.format(
container.name, container.slot, instrument.name))
self._set_state('moving')
inst.drop_tip(container._container[0], home_after=True)
self._set_state('ready')

def return_tip(self, instrument):
inst = instrument._instrument
log.debug('Returning tip from {}'.format(instrument.name))
log.info('Returning tip from {}'.format(instrument.name))
self._set_state('moving')
inst.return_tip(home_after=True)
self._set_state('ready')

def move_to_front(self, instrument):
inst = instrument._instrument
log.debug('Moving {}'.format(instrument.name))
log.info('Moving {}'.format(instrument.name))
self._set_state('moving')
inst.robot.home()
calibration_functions.move_instrument_for_probing_prep(
Expand All @@ -97,22 +97,21 @@ def move_to_front(self, instrument):
self._set_state('ready')

def move_to(self, instrument, container):
# TODO (ben 20171115) Replace `isinstance` checks with typed params
if not isinstance(container, Container):
raise ValueError(
'Invalid object type {0}. Expected models.Container'
.format(type(container)))

inst = instrument._instrument
log.debug('Moving {} to {} in {}'.format(
log.info('Moving {} to {} in {}'.format(
instrument.name, container.name, container.slot))
self._set_state('moving')
inst.move_to(container._container[0])
self._set_state('ready')

def jog(self, instrument, distance, axis):
inst = instrument._instrument
log.debug('Jogging {} by {} in {}'.format(
log.info('Jogging {} by {} in {}'.format(
instrument.name, distance, axis))
self._set_state('moving')
calibration_functions.jog_instrument(
Expand All @@ -125,23 +124,20 @@ def jog(self, instrument, distance, axis):

def home(self, instrument):
inst = instrument._instrument
log.debug('Homing {}'.format(instrument.name))
log.info('Homing {}'.format(instrument.name))
self._set_state('moving')
inst.home()
self._set_state('ready')

def update_container_offset(self, container, instrument):
inst = instrument._instrument
log.debug('Updating {} in {}'.format(container.name, container.slot))
log.info('Updating {} in {}'.format(container.name, container.slot))
inst.robot.calibrate_container_with_instrument(
container=container._container,
instrument=inst,
save=True
)

# TODO (artyom, 20171003): along with session, consider extracting this
# into abstract base class or find any other way to keep notifications
# consistent across all managers
def _snapshot(self):
return {
'topic': CalibrationManager.TOPIC,
Expand Down
2 changes: 1 addition & 1 deletion api/opentrons/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, instrument, containers=None):
self.name = instrument.name
self.channels = instrument.channels
self.mount = instrument.mount
# TODO(artyom, 20171006): with axis removed from the instrument
# Although axis has been deprecated from the instrument
# we still need to pass it to the UI for now
# Warning: this does not correspond to the Smoothie axis!
self.axis = 'a' if self.mount == 'right' else 'b'
Expand Down
7 changes: 4 additions & 3 deletions api/opentrons/api/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from functools import reduce

from opentrons.broker import publish, subscribe
from opentrons.containers import get_container
from opentrons.containers import get_container, location_to_list
from opentrons.commands import tree, types
from opentrons import robot

Expand Down Expand Up @@ -199,7 +199,7 @@ def turn_off_rail_lights(self):
robot.turn_off_rail_lights()

def set_state(self, state):
log.info("State set to {}".format(state))
log.debug("State set to {}".format(state))
if state not in VALID_STATES:
raise ValueError(
'Invalid state: {0}. Valid states are: {1}'
Expand Down Expand Up @@ -275,8 +275,9 @@ def _get_labware(command):
containers.append(get_container(location))

if locations:
list_of_locations = location_to_list(locations)
containers.extend(
[get_container(location) for location in locations])
[get_container(location) for location in list_of_locations])

containers = [c for c in containers if c is not None]

Expand Down
46 changes: 14 additions & 32 deletions api/opentrons/commands/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
from ..broker import broker
import functools
import inspect
from opentrons.containers import Well, Container, Slot, WellSeries,\
unpack_location
from opentrons.containers import Well, Container, Slot, location_to_list


def stringify_location(location):
Expand All @@ -23,7 +22,7 @@ def get_slot(location):
if location is None:
return '?'

location = _location_to_list(location)
location = location_to_list(location)
multiple = len(location) > 1

return '{object_text}{suffix} {first}{last} in "{slot_text}"'.format(
Expand All @@ -35,32 +34,6 @@ def get_slot(location):
)


def _location_to_list(loc):
# might be a location tuple, or list of location tuples
# like what's returned from well.top()
if isinstance(loc, tuple):
loc = unpack_location(loc)[0]
elif isinstance(loc, list):
loc = [
unpack_location(l)[0]
for l in loc
]

if isinstance(loc, WellSeries):
# TODO(artyom, 20171107): this is to handle a case when
# container.rows('1', '2') returns a WellSeries of WellSeries
# the data structure should be fixed when WellSeries is phased out
if isinstance(loc[0], WellSeries):
loc = [well for series in loc for well in series]
else:
loc = list(loc)

# ensure it returns either list or tuple
if not (isinstance(loc, list) or isinstance(loc, tuple)):
loc = [loc]
return loc


def make_command(name, payload):
return {'name': name, 'payload': payload}

Expand Down Expand Up @@ -117,11 +90,14 @@ def consolidate(instrument, volume, source, dest):
source=stringify_location(source),
dest=stringify_location(dest)
)
# incase either source or dest is list of tuple location
# strip both down to simply lists of Placeables
locations = [] + location_to_list(source) + location_to_list(dest)
return make_command(
name=types.CONSOLIDATE,
payload={
'instrument': instrument,
'locations': [source, dest],
'locations': locations,
'volume': volume,
'source': source,
'dest': dest,
Expand All @@ -136,11 +112,14 @@ def distribute(instrument, volume, source, dest):
source=stringify_location(source),
dest=stringify_location(dest)
)
# incase either source or dest is list of tuple location
# strip both down to simply lists of Placeables
locations = [] + location_to_list(source) + location_to_list(dest)
return make_command(
name=types.DISTRIBUTE,
payload={
'instrument': instrument,
'locations': [source, dest],
'locations': locations,
'volume': volume,
'source': source,
'dest': dest,
Expand All @@ -155,11 +134,14 @@ def transfer(instrument, volume, source, dest):
source=stringify_location(source),
dest=stringify_location(dest)
)
# incase either source or dest is list of tuple location
# strip both down to simply lists of Placeables
locations = [] + location_to_list(source) + location_to_list(dest)
return make_command(
name=types.TRANSFER,
payload={
'instrument': instrument,
'locations': [source, dest],
'locations': locations,
'volume': volume,
'source': source,
'dest': dest,
Expand Down
2 changes: 2 additions & 0 deletions api/opentrons/containers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
Well,
WellSeries,
unpack_location,
location_to_list,
get_container
)
from opentrons.containers.calibrator import apply_calibration
Expand All @@ -24,6 +25,7 @@
Well,
WellSeries,
unpack_location,
location_to_list,
apply_calibration,
get_container]

Expand Down
29 changes: 29 additions & 0 deletions api/opentrons/containers/placeable.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,35 @@ def unpack_location(location):
return (placeable, Vector(coordinates))


def location_to_list(loc):
# might be a location tuple, or list of location tuples
# like what's returned from well.top()
if isinstance(loc, tuple):
loc = unpack_location(loc)[0]
if isinstance(loc, list):
if isinstance(loc[0], (WellSeries, list)):
loc = [well for series in loc for well in series]
else:
loc = [
unpack_location(l)[0]
for l in loc
]

if isinstance(loc, WellSeries):
# TODO(artyom, 20171107): this is to handle a case when
# container.rows('1', '2') returns a WellSeries of WellSeries
# the data structure should be fixed when WellSeries is phased out
if isinstance(loc[0], WellSeries):
loc = [well for series in loc for well in series]
else:
loc = list(loc)

# ensure it returns either list or tuple
if not (isinstance(loc, list) or isinstance(loc, tuple)):
loc = [loc]
return loc


def get_container(location):
obj, _ = unpack_location(location)

Expand Down
Loading

0 comments on commit 62575a2

Please sign in to comment.