Closed EvanKirshenbaum closed 7 months ago
This issue was referenced by the following commits before migration:
I'm starting to think that well gates should be pads (rather than well pads), complete with a location just off the main board.
Time to get my thoughts down. After playing with a couple of approaches, what I'm going to try now is a somewhat radical reimagining of how drops work, but (1) it will look the same most of the time, and (2) it should be able to be made to work right for the cases in which drops merge together with neighboring drops to make weirdly shaped chains (like the ones Corey is seeing). What I'm going to describe here only deals with fluid on the pads proper, but it can probably be made to work for fluid within the wells as well. The nice thing about having fluid motion inferred is that the model can change later without having to fix it in lots of places.
The big change is that Drop
s will no longer contain liquid themselves. Rather, they will indirect through Blob
s, which can involve multiple pads. I'm thinking of something like
class Drop:
blob: Blob
pad: Pad
@property def contents(self) -> Liquid:
return self.blob.contents
class Blob:
pads: Final[set[Pad]]
contents: Liquid # Final?
_stashed_drops: Final[dict[Pad, Drop]]
@property def singleton(self) -> bool:
return len(self.pads) == 1
@property def drops(self) -> Sequence[Drop]: ...
@property def neighbors(self) -> set[Pad]: ...
# Blobs also probably delegate reservation to their pads, so they all get reserved and unreserved together.
After fix-up:
The fix-up process will look something like this:
Thinking more about it, a few changes:
turned_on
and turned_off
). If a pad changes state, remove it from the old set (if it's there) or add it to the new one. (Ignore if new and old are the same.)
Journal based blobs appear to work, although I haven't tried actually running one of the protocols. (I've just been testing with mouse clicks and macro commands.) I haven't really integrated wells yet (a bit of code in the dispense sequence). What I'm going to try now is to refactor things a bit to abstract out the part of Pad
that holds blobs and drops and has neighbors and location as DropLoc
and extend it to WellPad
. Then I'll make blobs hold droplocs rather than pads. This will allow me to model motion in the well, as well. (I don't think I'm going to actually put drop monitors on the display for well pads, at least not for interior pads.)
The problem I see is that my current pull logic says that what gets pulled off an unpinned blob is a fraction of the volume of the blob, and this won't work for dispensing. So what I think I'm going to do is to say arbitrarily that
The combinatorial synthesis example protocol now works with inferred drop motion, so I'm going to declare this done.
While trying to add mirroring to the wombat platform (#60), it dawned on me that this would be a lot simpler if rather than trying to pretend we only had half the pads and have them show up on the monitor twice, we actually made separate pads that were ganged together (#61) In order for this to work correctly with drops, however, what we'd want to do is get rid of all of the explicit drop motion/merge/split/etc. code and have the board itself figure out what happens as part of the call to
finish_update()
for the board.This would have the additional benefit that the drop inference model can be updated as we get more understanding of what happens in real life.
Considerations:
add_monitor()
, but nobody actually seems to call that, so I may just get rid of that and work it in afterfinish_update()
.Migrated from internal repository. Originally created by @EvanKirshenbaum on Jan 09, 2022 at 6:30 PM PST. Closed on Feb 21, 2022 at 12:28 PM PST.