diff --git a/pylabrobot/liquid_handling/liquid_handler.py b/pylabrobot/liquid_handling/liquid_handler.py index 0224803212..29971517a2 100644 --- a/pylabrobot/liquid_handling/liquid_handler.py +++ b/pylabrobot/liquid_handling/liquid_handler.py @@ -1813,7 +1813,7 @@ async def drop_resource( ) # get the location of the destination - if isinstance(destination, ResourceStack): + if isinstance(destination, ResourceStack) and not isinstance(resource, Lid): assert ( destination.direction == "z" ), "Only ResourceStacks with direction 'z' are currently supported" @@ -1835,13 +1835,26 @@ async def drop_resource( resource.rotated(z=resource_rotation_wrt_destination_wrt_local) ).rotated(destination.get_absolute_rotation()) to_location = destination.get_absolute_location() + adjusted_plate_anchor - elif isinstance(destination, Plate) and isinstance(resource, Lid): + # Automatically assign lid to plate as child when dropping a lid to a plate (on or off resource stack) + elif isinstance(destination, (Plate, ResourceStack)) and isinstance(resource, Lid): lid = resource - plate_location = destination.get_absolute_location() - child_wrt_parent = destination.get_lid_location( - lid.rotated(z=resource_rotation_wrt_destination_wrt_local) - ).rotated(destination.get_absolute_rotation()) - to_location = plate_location + child_wrt_parent + if isinstance(destination, ResourceStack): + if destination.direction != "z": + raise ValueError("Only ResourceStacks with direction 'z' are currently supported") + if len(destination.children) == 0: + to_location = destination.get_absolute_location(z="top") + else: + top_item = destination.get_top_item() + if isinstance(top_item, Plate): + destination = top_item + else: + to_location = destination.get_absolute_location(z="top") + if isinstance(destination, Plate): + plate_location = destination.get_absolute_location() + child_wrt_parent = destination.get_lid_location( + lid.rotated(z=resource_rotation_wrt_destination_wrt_local) + ).rotated(destination.get_absolute_rotation()) + to_location = plate_location + child_wrt_parent else: to_location = destination.get_absolute_location() diff --git a/pylabrobot/resources/carrier.py b/pylabrobot/resources/carrier.py index 6eabb1de3c..122c5ed218 100644 --- a/pylabrobot/resources/carrier.py +++ b/pylabrobot/resources/carrier.py @@ -234,8 +234,25 @@ def _update_resource_stack_location(self, resource: Resource): Args: resource: The Resource on the ResourceStack tht was assigned. """ - resource_stack = resource.parent - assert isinstance(resource_stack, ResourceStack) + + if isinstance(resource, Lid): + lid_parent = resource.parent + if lid_parent is None: + raise ValueError("Lid has no parent. ResourceStack not found for Lid") + if isinstance(lid_parent, ResourceStack): + resource_stack = lid_parent + elif isinstance(lid_parent.parent, ResourceStack): + resource_stack = lid_parent.parent + else: + raise ValueError("ResourceStack not found for Lid") + else: + if resource.parent is None: + raise ValueError("ResourceStack not found for resource") + if not isinstance(resource.parent, ResourceStack): + raise TypeError( + f"Resource {resource} is not a child of a ResourceStack, but of {type(resource.parent)}" + ) + resource_stack = resource.parent if resource_stack.children[0] == resource: resource_stack.location = self.get_default_child_location(resource)