Skip to content

Commit

Permalink
fix(step-generation): update liquid state 96-channel and reservoir (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jerader authored Jun 17, 2024
1 parent 0f39310 commit 5172afc
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
2 changes: 2 additions & 0 deletions step-generation/src/__tests__/forAspirate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,6 @@ describe('8-channel trough', () => {
)

it.todo('aspirate from 384 plate starting from B row') // TODO

it.todo('aspirating from a full 96-channel and a reservoir labware')
})
51 changes: 51 additions & 0 deletions step-generation/src/getNextRobotStateAndWarnings/forAspirate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function forAspirate(
const nozzles = robotState.pipettes[pipetteId].nozzles
const pipetteSpec = invariantContext.pipetteEntities[pipetteId].spec
const labwareDef = invariantContext.labwareEntities[labwareId].def
const isReservoir = labwareDef.metadata.displayCategory === 'reservoir'
const channels = nozzles === COLUMN ? 8 : pipetteSpec.channels

const { allWellsShared, wellsForTips } = getWellsForTips(
Expand Down Expand Up @@ -81,6 +82,56 @@ export function forAspirate(
return
}

// all wells in the reservoir are being used in this case but 8 channels per well
if (channels === 96 && isReservoir) {
// for each well the 96 channels are aspirating into
wellsForTips.forEach(well => {
const sourceLiquidState = liquidState.labware[labwareId][well]
const isOveraspirate =
volume * 8 > getLocationTotalVolume(sourceLiquidState)

if (isEmpty(sourceLiquidState)) {
warnings.push(warningCreators.aspirateFromPristineWell())
} else if (isOveraspirate) {
warnings.push(warningCreators.aspirateMoreThanWellContents())
}

const volumePerTip = isOveraspirate
? getLocationTotalVolume(sourceLiquidState) / 8
: volume

// all tips get the same amount of the same liquid added to them, from the source well
const newLiquidFromWell = splitLiquid(volumePerTip, sourceLiquidState)
.dest

range(channels).forEach(tipIndex => {
const pipette = liquidState.pipettes[pipetteId]
const indexToString = tipIndex.toString()
const tipLiquidState = pipette[indexToString]

// since volumePerTip is being calculated to avoid splitting unevenly across tips,
// AIR needs to be added in here if it's an over-aspiration
const nextTipLiquidState = isOveraspirate
? mergeLiquid(tipLiquidState, {
...newLiquidFromWell,
[AIR]: {
volume: volume - volumePerTip,
},
})
: mergeLiquid(tipLiquidState, newLiquidFromWell)

pipette[indexToString] = nextTipLiquidState
})
// Remove liquid from source well
liquidState.labware[labwareId][well] = splitLiquid(
volumePerTip * 8,
liquidState.labware[labwareId][well]
).source
})

return
}

// general case (no common well shared across all tips)
range(channels).forEach(tipIndex => {
const indexToString = tipIndex.toString()
Expand Down

0 comments on commit 5172afc

Please sign in to comment.