Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pipette model offsets #838

Merged
merged 32 commits into from
Mar 7, 2018
Merged

Pipette model offsets #838

merged 32 commits into from
Mar 7, 2018

Conversation

andySigler
Copy link
Contributor

@andySigler andySigler commented Feb 14, 2018

overview

Fixes #817

This PR adds the property model_offset to pipette config, which is used to describe the dimensional differences between pipette. For example, a dimensional difference is that the P10_Single pipette is longer than the P300_Single

changelog

This PR refactors config.instrument_offset to store just the delta between what was expected vs what was found from tip-probe. Previously, config.instrument_offset described the entire offset of that instrument, including any offset from the pipette model's dimensions, so it could not be re-used between different models.

This PR also adds a version property to robot_config, to allow migrating from old configurations version to new ones.

Lastly, something that should be changed later on, is that the tip-length per pipette is saved in the robot config file. For example, if was using a P10_Single pipette, the generated config file would contain a tip_length key that looks like:

{
    "tip_length": {
        "p10_single": 40
    }
}

Later on, this tip_length should be a property of a tip-rack, not the pipette. This way, multiple pipettes can share the same tips without requiring a new tip-probe. Also, this way a single pipette can use multiple tips during a protocol run.

@andySigler andySigler added api Affects the `api` project WIP labels Feb 14, 2018
@codecov
Copy link

codecov bot commented Feb 14, 2018

Codecov Report

Merging #838 into edge will increase coverage by 0.15%.
The diff coverage is 98.27%.

Impacted file tree graph

@@            Coverage Diff             @@
##             edge     #838      +/-   ##
==========================================
+ Coverage   69.26%   69.42%   +0.15%     
==========================================
  Files         233      233              
  Lines        7181     7221      +40     
  Branches      312      312              
==========================================
+ Hits         4974     5013      +39     
- Misses       2118     2119       +1     
  Partials       89       89
Impacted Files Coverage Δ
api/opentrons/robot/robot_configs.py 100% <100%> (ø) ⬆️
api/opentrons/util/calibration_functions.py 98.73% <100%> (ø) ⬆️
api/opentrons/robot/robot.py 87.07% <100%> (+0.18%) ⬆️
api/opentrons/instruments/pipette_config.py 100% <100%> (ø) ⬆️
api/opentrons/instruments/pipette.py 96.53% <100%> (+0.01%) ⬆️
api/opentrons/deck_calibration/dc_main.py 34% <50%> (ø) ⬆️
api/opentrons/config/config.py 94.73% <0%> (-5.27%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 148d316...8a22960. Read the comment docs.

@andySigler andySigler force-pushed the api-pipette-model-offsets branch 4 times, most recently from 1958f72 to dfeec9b Compare February 21, 2018 22:32
btmorr
btmorr previously requested changes Feb 27, 2018
@@ -181,6 +186,11 @@ def __init__(
self.set_flow_rate(
aspirate=aspirate_flow_rate, dispense=dispense_flow_rate)

# TODO (andy): remove from pipette, move to tip-rack
self.robot.config.tip_length[self.name] = \
self.robot.config.tip_length.get(self.name, tip_length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the initialization parameter as the fallback here makes it such that if the tip length has previously been set in the config, whatever is specified in initialization would not be honored. I think the logic here should be reversed: if not tip_length, check config

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overwriting the length specified in initialization is intentional here. Pipettes are initialized before every protocol run, each with a default tip-length depending on the model. If the tip has already been probed, then we do not want to use that default length. Solving this confusion should probably be done in another PR by saving all tip-length measurements to the associated tip-rack labware

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the purpose of this parameter to serve as a fallback length perhaps renaming the parameter to fallback_tip_length or something similar would lessen the confusion until we are able to move tip length to labware definitions.

This strikes me as related to the problems we had when there was no split between a labware definition and labware calibration

# TODO (andy): remove from pipette, move to tip-rack
self.robot.config.tip_length[self.name] = \
self.robot.config.tip_length.get(self.name, tip_length)
robot_configs.save(self.robot.config)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should save here. In general, I'm not actually super confident in the logic of save, and I think using it more often adds risk around bad override values being stored

@btmorr btmorr changed the base branch from v3a to edge February 27, 2018 21:32
mcous
mcous previously requested changes Mar 5, 2018
Copy link
Contributor

@mcous mcous left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes for the datetime thing because lack of consistency in this area has caused problems before


if version in migration_functions:
# backup the loaded configuration json file
tag = datetime.now().isoformat().split('.')[0].replace(':', '-')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure how this logic is used, or if it's even part of this PR vs a copy-paste thing, but any datetimes should be formatted in ms since epoch (see #365 for context and discussion). Additionally, datetime.now().isoformat() is in local timezone, not UTC (not a problem with ms since epoch)

if version in migration_functions:
# backup the loaded configuration json file
tag = datetime.now().isoformat().split('.')[0].replace(':', '-')
tag += '-v{}'.format(version)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I'm already commenting on this stuff: this tag construction may be easier to understand as a single format call:

tag = '{}-v{}`.format(
    int(time.time() * 1000),
    version)

migrate_func = migration_functions[version]
config_json = migrate_func(config_json)
# recursively update the config
# until there are no more migration methods for it's version
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's vs its typo 😛

@@ -181,6 +186,11 @@ def __init__(
self.set_flow_rate(
aspirate=aspirate_flow_rate, dispense=dispense_flow_rate)

# TODO (andy): remove from pipette, move to tip-rack
self.robot.config.tip_length[self.name] = \
self.robot.config.tip_length.get(self.name, tip_length)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the purpose of this parameter to serve as a fallback length perhaps renaming the parameter to fallback_tip_length or something similar would lessen the confusion until we are able to move tip length to labware definitions.

This strikes me as related to the problems we had when there was no split between a labware definition and labware calibration

@Laura-Danielle Laura-Danielle dismissed stale reviews from btmorr and mcous March 7, 2018 00:51

Fixed by Andy

Copy link
Contributor

@Laura-Danielle Laura-Danielle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works with the following protocol:

from opentrons import containers, instruments, robot

rack1 = containers.load('tiprack-200ul', '3')
rack3 = containers.load('tiprack-200ul', '6')

plate = containers.load('96-flat', '1')


p300_single = instruments.P300_Single(
   mount='right',
   tip_racks=[rack1]
   )

p300_single_2 = instruments.P300_Single(
   mount='left',
   tip_racks=[rack1]
   )


p300_single.pick_up_tip()
p300_single.aspirate(30, plate.wells('A1'))
p300_single.dispense(30, plate.wells('B1'))
p300_single.move_to(plate.wells('B5'))
p300_single.drop_tip()

p300_single_2.pick_up_tip(rack1.wells('B1'))
p300_single_2.aspirate(5, plate.wells('A1'))
p300_single_2.dispense(5, plate.wells('A2'))
p300_single_2.move_to(plate.wells('A6')) 
p300_single_2.drop_tip()

Without calibrating the second model to the labware.

@andySigler andySigler merged commit f9b9c2a into edge Mar 7, 2018
@andySigler andySigler deleted the api-pipette-model-offsets branch March 7, 2018 16:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Affects the `api` project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants