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

feat(hardware-testing): grav script on ot3 #12302

Merged
merged 114 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
e163f3e
moves gravimetric functionality into its own subfolder
andySigler Feb 9, 2023
10e4b09
move all ot2 functionality into gravimetric project
andySigler Feb 9, 2023
68929fe
wip
andySigler Feb 9, 2023
663ca5e
change tipracks to ot3 versions
andySigler Feb 10, 2023
16885de
can simulate on OT3
andySigler Feb 10, 2023
07c7bac
runs on ot3 without error
andySigler Feb 13, 2023
5ce3ed7
removes ProtocolContext from scale implementation
andySigler Feb 14, 2023
c48e0f3
push-plot-webpage-ot3 works
andySigler Feb 14, 2023
ff4647e
wip
andySigler Feb 14, 2023
f22e92d
DELETE THIS COMMIT
andySigler Feb 14, 2023
652a841
adds DVT pipettes to shared data
andySigler Feb 14, 2023
3898d90
ot3simulator small to change to allow simulation
andySigler Feb 17, 2023
4e710b2
local simulation working
andySigler Feb 17, 2023
598cd1e
use passed loop from ThreadManager when build OT3APIg
andySigler Feb 17, 2023
a07dfa8
use correct filepath for OT3 data files
andySigler Feb 17, 2023
df63cde
move execute to single file
andySigler Feb 17, 2023
3d1356d
placeholder for liquid-class defaults for OT3
andySigler Feb 17, 2023
13bcf9f
only read from scale when needed
andySigler Feb 21, 2023
9000b7f
remove pipette-timestamps
andySigler Feb 21, 2023
c387e16
merge in edge
andySigler Feb 24, 2023
86f8c08
integrates with scale; adds more volumes
andySigler Feb 24, 2023
558fc0f
wip
andySigler Feb 24, 2023
aa38634
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Feb 28, 2023
36174dc
remove hack from before revisioning update
andySigler Feb 28, 2023
4b8d5db
remove unnecessary v3.4 pipettes from shared-data
andySigler Feb 28, 2023
eb804da
fix merge conflicts
andySigler Mar 1, 2023
8b8361a
redo default liquid class settings for OT3 qc volumes
andySigler Mar 1, 2023
3cdffd2
deletes a lot of stuff
andySigler Mar 1, 2023
d9f3232
adds comments on reduced leading-air-gaps
andySigler Mar 1, 2023
c1cb774
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 2, 2023
e76ae4a
interpolate between liquid classes; move labware-def to static python…
andySigler Mar 2, 2023
3a3d735
increments test with cleared pipette ul-per-mm
andySigler Mar 2, 2023
26b706f
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 3, 2023
5e087a6
get labware-offsets; low_volume flag in config to filter <2uL
andySigler Mar 3, 2023
1df859f
linting
andySigler Mar 3, 2023
6ddd895
adds is_simulator to scale; reduce 50ul leading air-gaps to avoid SW bug
andySigler Mar 3, 2023
d13f398
adds blank measurements to find evaporation rate
andySigler Mar 3, 2023
9486901
add mix before aspirate
andySigler Mar 3, 2023
cdefdc8
remove aspirate after blow-out
andySigler Mar 3, 2023
c3f6ef2
change wording evaporation to blank
andySigler Mar 3, 2023
c2f1d3e
adds blowout with microliters to HW api
andySigler Mar 3, 2023
ae3dc1c
use HW api to run blow-out with microliters within grav script
andySigler Mar 3, 2023
948edc0
reorganizes pipetting sequence code; adds verbose comments
andySigler Mar 5, 2023
13b9289
wip: adding test report
andySigler Mar 6, 2023
bd77a01
wip: test-report is generated and format seems correct
andySigler Mar 6, 2023
ed1fec7
wip: most data stored, just need to calculate volumes
andySigler Mar 6, 2023
8d50021
wip: more cleaning up; store trial volumes
andySigler Mar 7, 2023
0a081eb
entire test report is filled out
andySigler Mar 7, 2023
610da18
calculate volumes using grams and environment data
andySigler Mar 7, 2023
404645f
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 7, 2023
725f8a3
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 8, 2023
0960a84
adds more args; adds fake protocol for calibrating tipracks
andySigler Mar 8, 2023
f90191b
merge in edge
andySigler Mar 8, 2023
a4bc98d
updates vial labware def
andySigler Mar 8, 2023
eb2529e
don't fail out if the rear-panel isn't found since EVT bots don't hav…
ryanthecoder Mar 8, 2023
2fb917d
put usb connected rear-panel behind a feature flag
ryanthecoder Mar 8, 2023
7315f5d
update robot server tests
ryanthecoder Mar 8, 2023
c34fdbc
few fixups from rebase
ryanthecoder Mar 8, 2023
52e127a
Merge branch 'evt_rear_panel_fix' into feat-hardware-testing-grav-scr…
andySigler Mar 9, 2023
1c9b29d
linting error from pipette qc script
andySigler Mar 9, 2023
b192654
slowing to 50mm/sec reduces noise on scale from moving air
andySigler Mar 9, 2023
38efdfa
use encoders after pick-up-tip
andySigler Mar 9, 2023
c2c586b
adds return tip option; multiple tip-racks
andySigler Mar 10, 2023
0506d50
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 10, 2023
3c805b7
add hard-coded vial offset to get around App bug
andySigler Mar 10, 2023
d38e15c
adds script for finding labware offset
andySigler Mar 10, 2023
443b645
option to skip blank readings
andySigler Mar 10, 2023
7712c41
correct decimal place on uL calculations
andySigler Mar 10, 2023
c7b4836
keep tip farther away from liquid during blank measurements
andySigler Mar 10, 2023
77e312c
also limit dispense volumes to 90% of pipette max
andySigler Mar 11, 2023
60bb06e
print final results at end
andySigler Mar 11, 2023
9dfacd2
fix(engine): subtract nominal overlap when calculating nominal tip le
andySigler Mar 11, 2023
f4df556
slow down acceleration/discontinuity; hard-code homing speeds to be f…
andySigler Mar 11, 2023
b6fee74
testing went well
andySigler Mar 11, 2023
1bba25f
linting
andySigler Mar 11, 2023
11d5618
adds inspect and skip-mix arguments
andySigler Mar 13, 2023
950580e
better printout during test run
andySigler Mar 13, 2023
ba66801
removing warnings about not having tip-length calibration on OT3
andySigler Mar 13, 2023
d5c1ff4
adds starting-tip
andySigler Mar 13, 2023
7dfda1f
use same submerge/retract distances for aspirate and dispense
andySigler Mar 13, 2023
a962f26
adds pipette temperature readings
andySigler Mar 13, 2023
7b67bb7
--inspect speeds all measurements up
andySigler Mar 13, 2023
c32cc56
use all of plunger
andySigler Mar 14, 2023
a0d122c
test more options in makefile
andySigler Mar 14, 2023
b788ba0
increase p1000-single pick-up-current from 0.15 to 0.25
andySigler Mar 14, 2023
f6250ca
fix bug where 1x trial would break CV calculations
andySigler Mar 14, 2023
aa05161
wip: tuning mix so droplets aren't created
andySigler Mar 14, 2023
bee277b
increase T50 leading-air-gaps
andySigler Mar 14, 2023
caf5f9c
update liquid-class settings to match tested values from Nick
andySigler Mar 14, 2023
74159e2
adds --user-volumes
andySigler Mar 14, 2023
7d278d5
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 14, 2023
b2b6478
merge in edge
andySigler Mar 14, 2023
f4c6c73
raise top plunger positions from 0.5 to 0.0
andySigler Mar 15, 2023
2d88a81
reduce amount of logs during measurement delay
andySigler Mar 15, 2023
051e4e2
load latest data 100ms after finishing previous data
andySigler Mar 16, 2023
a2c5e8d
different speeds for retract/submerge
andySigler Mar 16, 2023
88c032f
combine all stable samples into one segment to average; reduce delay …
andySigler Mar 16, 2023
cdddd49
reduct p1000 leading-air-gap from 32 to 16, so only one bubble is eje…
andySigler Mar 16, 2023
c1e3682
change skip-mix and skip-blank args to mix and blank
andySigler Mar 16, 2023
e2b71d3
linting!
andySigler Mar 16, 2023
a3cffa0
remove waiting for user to confirmware labware offsets
andySigler Mar 16, 2023
8434e0b
removes unnecessary changes to api
andySigler Mar 16, 2023
29c443f
remove reading temp-humidity within script
andySigler Mar 16, 2023
45de6e4
remove blow-out with volume from api
andySigler Mar 16, 2023
088a2aa
plate blow-out with micro-liters in hardware-testing script
andySigler Mar 16, 2023
c45f905
linting!
andySigler Mar 16, 2023
ac217b3
remove shared-data changes
andySigler Mar 16, 2023
21fa0b5
delete temp script for testing labware offsets
andySigler Mar 16, 2023
bc21c3d
Merge branch 'edge' into feat-hardware-testing-grav-script-on-ot3
andySigler Mar 16, 2023
71baa82
remove tip-overlap bug fix
andySigler Mar 16, 2023
67e3a03
fix broken test
andySigler Mar 16, 2023
088c503
fix makefile incorrectly calling gravimetric script
andySigler Mar 16, 2023
7a0d2c9
json uses 2-space indentation
andySigler Mar 16, 2023
3fd06ff
format-js
andySigler Mar 17, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ def _attached_pipette_to_mount(
raise RuntimeError(
f"mount {mount.name} requested a {expected_instr} which is not supported on the OT3"
)
if found_model and expected_instr and (expected_instr != found_model):
if found_model and expected_instr and (expected_instr not in found_model):
if self._strict_attached:
raise RuntimeError(
"mount {}: expected instrument {} but got {}".format(
Expand Down
60 changes: 32 additions & 28 deletions hardware-testing/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -71,43 +71,55 @@ test:
test-cov:
$(pytest) $(tests) $(test_opts) $(cov_opts)

.PHONY: test-integration
test-integration:
.PHONY: test-gravimetric
test-gravimetric:
$(python) -m hardware_testing.gravimetric --simulate --pipette 1000 --tip 1000 --trials 3 --starting-tip A1
$(python) -m hardware_testing.gravimetric --simulate --pipette 1000 --tip 200 --trials 3 --starting-tip A1
$(python) -m hardware_testing.gravimetric --simulate --pipette 1000 --tip 50 --trials 3 --starting-tip A1
$(python) -m hardware_testing.gravimetric --simulate --pipette 50 --tip 50 --trials 3 --starting-tip A1
$(python) -m hardware_testing.gravimetric --simulate --pipette 1000 --tip 1000 --trials 3 --starting-tip A1 --inspect
$(python) -m hardware_testing.gravimetric --simulate --pipette 1000 --tip 1000 --trials 3 --starting-tip A1 --increment

.PHONY: test-production-qc
test-production-qc:
$(python) -m hardware_testing.production_qc.pipette_assembly_qc_ot3 --operator test --simulate
$(python) -m hardware_testing.production_qc.robot_assembly_qc_ot3 --simulate
$(python) protocols/ot2_p300_single_channel_gravimetric.py --simulate
$(python) -m hardware_testing.examples.test_report

.PHONY: test-examples
test-examples:
$(python) -m hardware_testing.examples.csv_report
$(python) -m hardware_testing.examples.custom_axis_settings_ot3 --simulate
$(python) -m hardware_testing.examples.endstop_encoder_ot3 --simulate
$(python) -m hardware_testing.examples.pick_up_tip_ot3 --simulate
$(python) -m hardware_testing.examples.plunger_ot3 --simulate
$(python) -m hardware_testing.examples.capacitive_probe_ot3 --simulate

.PHONY: test-scripts
test-scripts:
$(python) -m hardware_testing.scripts.bowtie_ot3 --simulate

.PHONY: test-integration
test-integration: test-gravimetric test-production-qc test-examples test-scripts

.PHONY: lint
lint:
$(python) -m mypy hardware_testing tests protocols
$(python) -m black --check hardware_testing tests protocols setup.py
$(python) -m flake8 hardware_testing tests protocols setup.py
$(python) -m mypy hardware_testing tests
$(python) -m black --check hardware_testing tests setup.py
$(python) -m flake8 hardware_testing tests setup.py

.PHONY: format
format:
$(python) -m black hardware_testing tests protocols setup.py
$(python) -m black hardware_testing tests setup.py

define move-plot-webpage
define move-plot-webpage-ot3
ssh -i $(2) $(3) root@$(1) \
"function cleanup () { mount -o remount,ro / ; } ;\
mount -o remount,rw / &&\
mv /data/plot/index.html /usr/lib/python3.7/site-packages/hardware_testing/tools/plot &&\
mv /data/plot/index.js /usr/lib/python3.7/site-packages/hardware_testing/tools/plot &&\
mv /data/plot/index.html /opt/opentrons-robot-server/hardware_testing/tools/plot &&\
mv /data/plot/index.js /opt/opentrons-robot-server/hardware_testing/tools/plot &&\
rm -rf /data/plot &&\
cleanup || cleanup"
endef

.PHONY: push-plot-webpage
push-plot-webpage:
scp -r hardware_testing/tools/plot root@$(host):/data
$(call move-plot-webpage,$(host),$(br_ssh_key),$(ssh_opts))

.PHONY: push-plot-webpage-ot3
push-plot-webpage-ot3:
scp -r hardware_testing/tools/plot root@$(host):/data
Expand Down Expand Up @@ -135,19 +147,11 @@ push-no-restart-ot3: sdist Pipfile.lock
.PHONY: push-ot3
push-ot3: push-no-restart-ot3 restart-ot3

.PHONY: push-protocols
push-protocols:
scp -r protocols root@$(host):/data/user_storage/opentrons_data

.PHONY: push-protocols-ot3
push-protocols-ot3:
scp -r protocols root@$(host):/opt/opentrons-robot-server

.PHONY: push-all
push-all: clean wheel push-no-restart push-plot-webpage push-protocols
push-all: clean wheel push-no-restart push-plot-webpage

.PHONY: push-all-ot3
push-all: clean wheel push-no-restart-ot3 push-plot-webpage-ot3 push-protocols-ot3
push-all-ot3: push-ot3 push-plot-webpage-ot3

.PHONY: term
term:
Expand Down Expand Up @@ -197,7 +201,7 @@ sync-sw-ot3:
cd ../hardware && $(MAKE) push-no-restart-ot3 host=$(host)
cd ../api && $(MAKE) push-no-restart-ot3 host=$(host)
cd ../shared-data && $(MAKE) all push-no-restart-ot3 host=$(host)
cd ../hardware-testing && $(MAKE) push-no-restart-ot3 host=$(host)
cd ../hardware-testing && $(MAKE) push-all-ot3 host=$(host)

.PHONY: sync-fw-ot3
sync-fw-ot3:
Expand Down
36 changes: 26 additions & 10 deletions hardware-testing/hardware_testing/data/csv_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ def __str__(self) -> str:
_elapsed = round(self._elapsed_time, 1)
return f"{_elapsed},{full_str}"

@property
def data(self) -> List[Any]:
"""Data."""
return self._data

@property
def tag(self) -> str:
"""Line tag."""
Expand Down Expand Up @@ -268,18 +273,23 @@ def _generate_results_overview_section(tags: List[str]) -> CSVSection:
class CSVReport:
"""CSV Report."""

def __init__(self, script_path: str, sections: List[CSVSection]) -> None:
def __init__(
self,
test_name: str,
sections: List[CSVSection],
run_id: Optional[str] = None,
start_time: Optional[float] = None,
) -> None:
"""CSV Report init."""
self._script_path = script_path
self._test_name = data_io.create_test_name_from_file(script_path)
self._run_id = data_io.create_run_id()
self._test_name = test_name
self._run_id = run_id if run_id else data_io.create_run_id()
self._tag: Optional[str] = None
self._file_name: Optional[str] = None
_section_meta = _generate_meta_data_section()
_section_titles = [s.title for s in sections]
_section_results = _generate_results_overview_section(_section_titles)
self._sections = [_section_meta, _section_results] + sections
self._cache_start_time() # must happen before storing any data
self._cache_start_time(start_time) # must happen before storing any data
self(META_DATA_TITLE, META_DATA_TEST_NAME, [self._test_name])
self(META_DATA_TITLE, META_DATA_TEST_RUN_ID, [self._run_id])
_now = datetime.utcnow().strftime("%Y/%m/%d-%H:%M:%S")
Expand Down Expand Up @@ -343,23 +353,29 @@ def parent(self) -> Path:
"""Parent directory of this report file."""
return data_io.create_folder_for_test_data(self._test_name)

def _cache_start_time(self) -> None:
start_time = time()
@property
def tag(self) -> str:
"""Tag."""
return f"{self.__class__.__name__}-{self._tag}"

def _cache_start_time(self, start_time: Optional[float] = None) -> None:
checked_start_time = start_time if start_time else time()
for section in self._sections:
for line in section.lines:
if isinstance(line, CSVLineRepeating):
for i in range(len(line)):
line[i].cache_start_time(start_time)
line[i].cache_start_time(checked_start_time)
else:
line.cache_start_time(start_time)
line.cache_start_time(checked_start_time)

def set_tag(self, tag: str) -> None:
"""CSV Report set tag."""
self._tag = tag
self(META_DATA_TITLE, META_DATA_TEST_TAG, [self._tag])
self._file_name = data_io.create_file_name(
self._test_name, self._run_id, self._tag
self._test_name, self._run_id, self.tag
)
self.save_to_disk()

def set_operator(self, operator: str) -> None:
"""Set operator."""
Expand Down
16 changes: 14 additions & 2 deletions hardware-testing/hardware_testing/drivers/radwag/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from abc import ABC, abstractmethod
from typing import Tuple, Optional

from random import uniform
from serial import Serial # type: ignore[import]

from .commands import (
Expand Down Expand Up @@ -226,6 +225,15 @@ def read_mass(self) -> Tuple[float, bool]:
class SimRadwagScale(RadwagScaleBase):
"""Simulating Radwag Scale Driver."""

def __init__(self) -> None:
"""Constructor."""
self._mass: float = 0.0

@property
def sim_mass(self) -> float:
"""Simulation mass."""
return self._mass

def connect(self) -> None:
"""Connect."""
return
Expand Down Expand Up @@ -268,4 +276,8 @@ def set_tare(self, tare: float) -> None:

def read_mass(self) -> Tuple[float, bool]:
"""Read mass."""
return uniform(2.5, 2), True
return self._mass, True

def set_simulation_mass(self, mass: float) -> None:
"""Set simulation mass."""
self._mass = mass
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,8 @@

NUM_REPEATING_DATA = 30
EXAMPLE_REPORT = CSVReport(
script_path=__file__,
test_name="example-test-report",
sections=[
CSVSection(
title="TEST-INFO",
lines=[
CSVLine("software-version", [str]),
CSVLine("operator", [str]),
],
),
CSVSection(
title="PIPETTE-LEFT",
lines=[
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Pipette sensors OT3."""
import argparse
import asyncio
from time import sleep

from hardware_testing.opentrons_api import helpers_ot3
from hardware_testing.opentrons_api.types import OT3Mount


async def _main(is_simulating: bool) -> None:
api = await helpers_ot3.build_async_ot3_hardware_api(
is_simulating=is_simulating,
pipette_left="p1000_single_v3.3",
pipette_right="p1000_single_v3.3",
)
pip_mounts = [OT3Mount.from_mount(m) for m, p in api.hardware_pipettes.items() if p]
while True:
for mount in pip_mounts:
pascals = await helpers_ot3.get_pressure_ot3(api, mount)
pico_farads = await helpers_ot3.get_capacitance_ot3(api, mount)
celsius, humidity = await helpers_ot3.get_temperature_humidity_ot3(
api, mount
)
print(
f"-----\n"
f"{mount.name}:\n"
f"\tpascals={pascals}\n"
f"\tpico_farads={pico_farads}\n"
f"\tcelsius={celsius}\n"
f"\thumidity={humidity}"
)
sleep(0.2)


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--simulate", action="store_true")
args = parser.parse_args()
asyncio.run(_main(args.simulate))
18 changes: 0 additions & 18 deletions hardware-testing/hardware_testing/execute/README.md

This file was deleted.

4 changes: 0 additions & 4 deletions hardware-testing/hardware_testing/execute/__init__.py

This file was deleted.

Loading