From dc97d25939813aabea4f7890ae663aaa3b081ba0 Mon Sep 17 00:00:00 2001 From: Rick Wierenga Date: Wed, 18 Sep 2024 13:01:39 -0700 Subject: [PATCH] freeze the ops classes and remove doc strings --- .../liquid_handling/backends/hamilton/STAR.py | 13 +++--- .../backends/hamilton/vantage.py | 12 ++--- .../liquid_handling/backends/tecan/EVO.py | 15 +++---- .../backends/tecan/EVO_tests.py | 4 +- pylabrobot/liquid_handling/standard.py | 44 +++++-------------- 5 files changed, 31 insertions(+), 57 deletions(-) diff --git a/pylabrobot/liquid_handling/backends/hamilton/STAR.py b/pylabrobot/liquid_handling/backends/hamilton/STAR.py index 7f715cddf1..eb0e28ee72 100644 --- a/pylabrobot/liquid_handling/backends/hamilton/STAR.py +++ b/pylabrobot/liquid_handling/backends/hamilton/STAR.py @@ -1577,8 +1577,8 @@ async def aspirate( self._assert_valid_resources([op.resource for op in ops]) # correct volumes using the liquid class - for op, hlc in zip(ops, hamilton_liquid_classes): - op.volume = hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + volumes = [hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + for op, hlc in zip(ops, hamilton_liquid_classes)] well_bottoms = [op.resource.get_absolute_location().z + op.offset.z + \ op.resource.material_z_thickness for op in ops] @@ -1657,7 +1657,7 @@ async def aspirate( x_positions=x_positions, y_positions=y_positions, - aspiration_volumes=[round(op.volume * 10) for op in ops], + aspiration_volumes=[round(vol * 10) for vol in volumes], lld_search_height=[round(lsh * 10) for lsh in lld_search_height], clot_detection_height=[round(cd * 10) for cd in clot_detection_height], liquid_surface_no_lld=[round(ls * 10) for ls in liquid_surfaces_no_lld], @@ -1839,8 +1839,8 @@ async def dispense( )) # correct volumes using the liquid class - for op, hlc in zip(ops, hamilton_liquid_classes): - op.volume = hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + volumes = [hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + for op, hlc in zip(ops, hamilton_liquid_classes)] well_bottoms = [op.resource.get_absolute_location().z + op.offset.z + \ op.resource.material_z_thickness for op in ops] @@ -1858,7 +1858,6 @@ async def dispense( [_dispensing_mode_for_op(empty=empty[i], jet=jet[i], blow_out=blow_out[i]) for i in range(len(ops))] - dispense_volumes = [op.volume for op in ops] pull_out_distance_transport_air = _fill_in_defaults(pull_out_distance_transport_air, [10.0]*n) second_section_height = _fill_in_defaults(second_section_height, [3.2]*n) second_section_ratio = _fill_in_defaults(second_section_ratio, [618.0]*n) @@ -1907,7 +1906,7 @@ async def dispense( y_positions=y_positions, dispensing_mode=dispensing_modes, - dispense_volumes=[round(dv*10) for dv in dispense_volumes], + dispense_volumes=[round(vol*10) for vol in volumes], lld_search_height=[round(lsh*10) for lsh in lld_search_height], liquid_surface_no_lld=[round(ls*10) for ls in liquid_surfaces_no_lld], pull_out_distance_transport_air=[round(po*10) for po in pull_out_distance_transport_air], diff --git a/pylabrobot/liquid_handling/backends/hamilton/vantage.py b/pylabrobot/liquid_handling/backends/hamilton/vantage.py index db5a8074d1..c16a29bb71 100644 --- a/pylabrobot/liquid_handling/backends/hamilton/vantage.py +++ b/pylabrobot/liquid_handling/backends/hamilton/vantage.py @@ -620,8 +620,8 @@ async def aspirate( self._assert_valid_resources([op.resource for op in ops]) # correct volumes using the liquid class - for op, hlc in zip(ops, hlcs): - op.volume = hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + volumes = [hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + for op, hlc in zip(ops, hlcs)] well_bottoms = [op.resource.get_absolute_location().z + op.offset.z + \ op.resource.material_z_thickness for op in ops] @@ -663,7 +663,7 @@ async def aspirate( immersion_depth=[round(id_*10) for id_ in immersion_depth or [0]*len(ops)], surface_following_distance=[round(sfd*10) for sfd in surface_following_distance or [0]*len(ops)], - aspiration_volume=[round(op.volume*100) for op in ops], + aspiration_volume=[round(vol*100) for vol in volumes], aspiration_speed=[round(fr * 10) for fr in flow_rates], transport_air_volume=[round(tav*10) for tav in transport_air_volume or [hlc.aspiration_air_transport_volume if hlc is not None else 0 @@ -785,8 +785,8 @@ async def dispense( self._assert_valid_resources([op.resource for op in ops]) # correct volumes using the liquid class - for op, hlc in zip(ops, hlcs): - op.volume = hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + volumes = [hlc.compute_corrected_volume(op.volume) if hlc is not None else op.volume + for op, hlc in zip(ops, hlcs)] well_bottoms = [op.resource.get_absolute_location().z + op.offset.z + \ op.resource.material_z_thickness for op in ops] @@ -831,7 +831,7 @@ async def dispense( minimal_traverse_height_at_begin_of_command or [self._traversal_height]*len(ops)], minimal_height_at_command_end= [round(mh*10) for mh in minimal_height_at_command_end or [self._traversal_height]*len(ops)], - dispense_volume=[round(op.volume * 100) for op in ops], + dispense_volume=[round(vol*100) for vol in volumes], dispense_speed=[round(fr*10) for fr in flow_rates], cut_off_speed=[round(cs*10) for cs in cut_off_speed or [250]*len(ops)], stop_back_volume=[round(sbv*100) for sbv in stop_back_volume or [0]*len(ops)], diff --git a/pylabrobot/liquid_handling/backends/tecan/EVO.py b/pylabrobot/liquid_handling/backends/tecan/EVO.py index b5fe24da4e..74e147f13d 100644 --- a/pylabrobot/liquid_handling/backends/tecan/EVO.py +++ b/pylabrobot/liquid_handling/backends/tecan/EVO.py @@ -317,9 +317,6 @@ async def aspirate( tip_type=op.tip.tip_type ) if isinstance(op.tip, TecanTip) else None for op in ops] - for op, tlc in zip(ops, tecan_liquid_classes): - op.volume = tlc.compute_corrected_volume(op.volume) if tlc is not None else op.volume - ys = int(ops[0].resource.get_absolute_size_y() * 10) zadd: List[Optional[int]] = [0] * self.num_channels for i, channel in enumerate(use_channels): @@ -406,11 +403,6 @@ async def dispense( tip_type=op.tip.tip_type ) if isinstance(op.tip, TecanTip) else None for op in ops] - for op, tlc in zip(ops, tecan_liquid_classes): - op.volume = tlc.compute_corrected_volume(op.volume) + \ - tlc.aspirate_lag_volume + tlc.aspirate_tag_volume \ - if tlc is not None else op.volume - x, _ = self._first_valid(x_positions) y, yi = self._first_valid(y_positions) assert x is not None and y is not None @@ -724,7 +716,8 @@ def _aspirate_action( assert tlc is not None and z is not None sep[channel] = int(tlc.aspirate_speed * 12) # 6? ssz[channel] = round(z * tlc.aspirate_speed / ops[i].volume) - mtr[channel] = round(ops[i].volume * 6) # 3? + volume = tlc.compute_corrected_volume(ops[i].volume) + mtr[channel] = round(volume * 6) # 3? ssz_r[channel] = int(tlc.aspirate_retract_speed * 10) return ssz, sep, stz, mtr, ssz_r @@ -755,7 +748,9 @@ def _dispense_action( sep[channel] = int(tlc.dispense_speed * 12) # 6? spp[channel] = int(tlc.dispense_breakoff * 12) # 6? stz[channel] = 0 - mtr[channel] = -round(ops[i].volume * 6) # 3? + volume = tlc.compute_corrected_volume(ops[i].volume) + tlc.aspirate_lag_volume + \ + tlc.aspirate_tag_volume + mtr[channel] = -round(volume * 6) # 3? return sep, spp, stz, mtr diff --git a/pylabrobot/liquid_handling/backends/tecan/EVO_tests.py b/pylabrobot/liquid_handling/backends/tecan/EVO_tests.py index 072bb6f50b..25d902d46c 100644 --- a/pylabrobot/liquid_handling/backends/tecan/EVO_tests.py +++ b/pylabrobot/liquid_handling/backends/tecan/EVO_tests.py @@ -122,11 +122,11 @@ async def test_aspirate(self): call(module="C5", command="SML", params=[985, 2000, 2000, 2000, 2000, 2000, 2000, 2000]), call(module="C5", command="SBL", params=[20, None, None, None, None, None, None, None]), call(module="C5", command="SHZ", params=[1455, 1455, 1455, 1455, 1455, 1455, 1455, 1455]), - call(module="C5", command="MDT", params=[1, None, None, None, 31, 0, 0, 0, 0, 0, 0, 0]), + call(module="C5", command="MDT", params=[1, None, None, None, 30, 0, 0, 0, 0, 0, 0, 0]), call(module="C5", command="SHZ", params=[2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000]), call(module="C5", command="SSZ", params=[30, None, None, None, None, None, None, None]), call(module="C5", command="SEP", params=[1200, None, None, None, None, None, None, None]), - call(module="C5", command="STZ", params=[-31, None, None, None, None, None, None, None]), + call(module="C5", command="STZ", params=[-30, None, None, None, None, None, None, None]), call(module="C5", command="MTR", params=[626, None, None, None, None, None, None, None]), call(module="C5", command="SSZ", params=[200, None, None, None, None, None, None, None]), call(module="C5", command="MAZ", params=[1375, None, None, None, None, None, None, None]), diff --git a/pylabrobot/liquid_handling/standard.py b/pylabrobot/liquid_handling/standard.py index 51cf433262..b4f2acb7f9 100644 --- a/pylabrobot/liquid_handling/standard.py +++ b/pylabrobot/liquid_handling/standard.py @@ -14,42 +14,34 @@ from pylabrobot.resources.tip_rack import TipSpot -@dataclass +@dataclass(frozen=True) class Pickup: - """ A pickup operation. """ resource: TipSpot offset: Coordinate tip: Tip # TODO: perhaps we can remove this, because the tip spot has the tip? -@dataclass +@dataclass(frozen=True) class Drop: - """ A drop operation. """ resource: Resource offset: Coordinate tip: Tip -@dataclass +@dataclass(frozen=True) class PickupTipRack: - """ A pickup operation for an entire tip rack. """ - resource: TipRack offset: Coordinate -@dataclass +@dataclass(frozen=True) class DropTipRack: - """ A drop operation for an entire tip rack. """ - resource: Union[TipRack, Trash] offset: Coordinate -@dataclass +@dataclass(frozen=True) class Aspiration: - """ Aspiration contains information about an aspiration. """ - resource: Container offset: Coordinate tip: Tip @@ -60,10 +52,8 @@ class Aspiration: liquids: List[Tuple[Optional[Liquid], float]] -@dataclass +@dataclass(frozen=True) class Dispense: - """ Dispense contains information about an dispense. """ - resource: Container offset: Coordinate tip: Tip @@ -74,10 +64,8 @@ class Dispense: liquids: List[Tuple[Optional[Liquid], float]] -@dataclass +@dataclass(frozen=True) class AspirationPlate: - """ Contains information about an aspiration from a plate (in a single movement). """ - wells: List[Well] offset: Coordinate tips: List[Tip] @@ -88,10 +76,8 @@ class AspirationPlate: liquids: List[List[Tuple[Optional[Liquid], float]]] -@dataclass +@dataclass(frozen=True) class DispensePlate: - """ Contains information about an aspiration from a plate (in a single movement). """ - wells: List[Well] offset: Coordinate tips: List[Tip] @@ -101,10 +87,8 @@ class DispensePlate: blow_out_air_volume: Optional[float] liquids: List[List[Tuple[Optional[Liquid], float]]] -@dataclass +@dataclass(frozen=True) class AspirationContainer: - """ Contains information about an aspiration from a plate (in a single movement). """ - container: Container offset: Coordinate tips: List[Tip] @@ -115,10 +99,8 @@ class AspirationContainer: liquids: List[List[Tuple[Optional[Liquid], float]]] -@dataclass +@dataclass(frozen=True) class DispenseContainer: - """ Contains information about an aspiration from a plate (in a single movement). """ - container: Container offset: Coordinate tips: List[Tip] @@ -130,17 +112,15 @@ class DispenseContainer: class GripDirection(enum.Enum): - """ A direction from which to grab the resource. """ FRONT = enum.auto() BACK = enum.auto() LEFT = enum.auto() RIGHT = enum.auto() -@dataclass +@dataclass(frozen=True) class Move: - """ A move operation. - + """ Attributes: resource: The resource to move. destination: The destination of the move.