Skip to content

Commit

Permalink
extend logic for custom labware
Browse files Browse the repository at this point in the history
  • Loading branch information
jerader committed Sep 25, 2023
1 parent 4379473 commit b3e972c
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 73 deletions.
5 changes: 2 additions & 3 deletions protocol-designer/src/components/DeckSetup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import { getDeckSetupForActiveItem } from '../../top-selectors/labware-locations
import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors'
import { TerminalItemId } from '../../steplist'
import { getSelectedTerminalItemId } from '../../ui/steps'
import { getHas96Channel } from '../../utils'
import { getRobotType } from '../../file-data/selectors'
import { BrowseLabwareModal } from '../labware'
import { SlotWarning } from './SlotWarning'
Expand Down Expand Up @@ -154,9 +155,7 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => {
robotType,
} = props
const pipettes = activeDeckSetup.pipettes
const has96Channel = Object.values(pipettes).some(
pip => pip.name === 'p1000_96'
)
const has96Channel = getHas96Channel(pipettes)

Check warning on line 158 in protocol-designer/src/components/DeckSetup/index.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/DeckSetup/index.tsx#L157-L158

Added lines #L157 - L158 were not covered by tests
const trashSlot = robotType === FLEX_ROBOT_TYPE ? FLEX_TRASH_SLOT : '12'
// NOTE: handling module<>labware compat when moving labware to empty module
// is handled by SlotControls.
Expand Down
16 changes: 9 additions & 7 deletions protocol-designer/src/components/LabwareSelectionModal/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ import {
selectors as labwareDefSelectors,
} from '../../labware-defs'
import { selectors as stepFormSelectors, ModuleOnDeck } from '../../step-forms'
import { BaseState, ThunkDispatch } from '../../types'
import { getHas96Channel } from '../../utils'
import { getPipetteEntities } from '../../step-forms/selectors'
import { adapter96ChannelDefUri } from '../modals/CreateFileWizard'
import type { BaseState, ThunkDispatch } from '../../types'
interface SP {
customLabwareDefs: LabwareSelectionModalProps['customLabwareDefs']
slot: LabwareSelectionModalProps['slot']
Expand All @@ -35,9 +36,7 @@ interface SP {
function mapStateToProps(state: BaseState): SP {
const slot = labwareIngredSelectors.selectedAddLabwareSlot(state) || null
const pipettes = getPipetteEntities(state)
const has96Channel = Object.values(pipettes).some(
pip => pip.name === 'p1000_96'
)
const has96Channel = getHas96Channel(pipettes)

Check warning on line 39 in protocol-designer/src/components/LabwareSelectionModal/index.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/LabwareSelectionModal/index.ts#L38-L39

Added lines #L38 - L39 were not covered by tests

// TODO: Ian 2019-10-29 needs revisit to support multiple manualIntervention steps
const modulesById = stepFormSelectors.getInitialDeckSetup(state).modules
Expand Down Expand Up @@ -86,10 +85,13 @@ function mergeProps(
dispatch(closeLabwareSelector())
},
onUploadLabware: fileChangeEvent =>
dispatch(labwareDefActions.createCustomLabwareDef(fileChangeEvent)),
dispatch(

Check warning on line 88 in protocol-designer/src/components/LabwareSelectionModal/index.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/LabwareSelectionModal/index.ts#L88

Added line #L88 was not covered by tests
labwareDefActions.createCustomLabwareDef(
fileChangeEvent,
stateProps.has96Channel
)
),
selectLabware: labwareDefURI => {
console.log(labwareDefURI)
console.log(stateProps.permittedTipracks)
if (stateProps.slot) {
dispatch(
createContainer({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
Btn,
JUSTIFY_END,
} from '@opentrons/components'
import { getPipetteNameSpecs } from '@opentrons/shared-data'
import { getPipetteNameSpecs, LEFT } from '@opentrons/shared-data'
import { i18n } from '../../../localization'
import { getLabwareDefsByURI } from '../../../labware-defs/selectors'
import { createCustomTiprackDef } from '../../../labware-defs/actions'
Expand Down Expand Up @@ -237,7 +237,14 @@ function PipetteTipsField(props: PipetteTipsFieldProps): JSX.Element | null {
</Flex>
<input
type="file"
onChange={e => dispatch(createCustomTiprackDef(e))}
onChange={e =>
dispatch(

Check warning on line 241 in protocol-designer/src/components/modals/CreateFileWizard/PipetteTipsTile.tsx

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/components/modals/CreateFileWizard/PipetteTipsTile.tsx#L241

Added line #L241 was not covered by tests
createCustomTiprackDef(
e,
values.pipettesByMount[LEFT].pipetteName === 'p1000_96'
)
)
}
/>
</OutlineButton>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,14 @@ export function PipetteFields(props: Props): JSX.Element {
{i18n.t('button.upload_custom_tip_rack')}
<input
type="file"
onChange={e => dispatch(createCustomTiprackDef(e))}
onChange={e =>
dispatch(
createCustomTiprackDef(
e,
values.left.pipetteName === 'p1000_96'
)
)
}
/>
</OutlineButton>
</div>
Expand Down
43 changes: 28 additions & 15 deletions protocol-designer/src/labware-defs/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
} from '@opentrons/shared-data'
import * as labwareDefSelectors from './selectors'
import { getAllWellSetsForLabware } from '../utils'
import { ThunkAction } from '../types'
import { LabwareUploadMessage } from './types'
import type { ThunkAction } from '../types'
import type { LabwareUploadMessage } from './types'
export interface LabwareUploadMessageAction {
type: 'LABWARE_UPLOAD_MESSAGE'
payload: LabwareUploadMessage
Expand Down Expand Up @@ -75,30 +75,32 @@ const _labwareDefsMatchingDisplayName = (

const getIsOverwriteMismatched = (
newDef: LabwareDefinition2,
overwrittenDef: LabwareDefinition2
overwrittenDef: LabwareDefinition2,
channel: 8 | 96
): boolean => {
const matchedWellOrdering = isEqual(newDef.ordering, overwrittenDef.ordering)
const matchedMultiUse =
matchedWellOrdering &&
isEqual(
getAllWellSetsForLabware(newDef, 8),
getAllWellSetsForLabware(overwrittenDef, 8)
getAllWellSetsForLabware(newDef, channel),
getAllWellSetsForLabware(overwrittenDef, channel)
)
return !(matchedWellOrdering && matchedMultiUse)
}

const _createCustomLabwareDef: (
onlyTiprack: boolean
) => (
event: React.SyntheticEvent<HTMLInputElement>
) => ThunkAction<any> = onlyTiprack => event => (dispatch, getState) => {
onlyTiprack: boolean,
has96Channel: boolean
) => (event: React.SyntheticEvent<HTMLInputElement>) => ThunkAction<any> = (
onlyTiprack,
has96Channel
) => event => (dispatch, getState) => {

Check warning on line 97 in protocol-designer/src/labware-defs/actions.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/labware-defs/actions.ts#L97

Added line #L97 was not covered by tests
const allLabwareDefs: LabwareDefinition2[] = values(
labwareDefSelectors.getLabwareDefsByURI(getState())
)
const customLabwareDefs: LabwareDefinition2[] = values(
labwareDefSelectors.getCustomLabwareDefsByURI(getState())
)

// @ts-expect-error(sa, 2021-6-20): null check
const file = event.currentTarget.files[0]
const reader = new FileReader()
Expand Down Expand Up @@ -199,7 +201,8 @@ const _createCustomLabwareDef: (
isOverwriteMismatched: getIsOverwriteMismatched(
// @ts-expect-error(sa, 2021-6-20): parsedLabwareDef might be nullsy
parsedLabwareDef,
matchingDefs[0]
matchingDefs[0],
has96Channel ? 96 : 8
),
})
)
Expand Down Expand Up @@ -242,11 +245,21 @@ const _createCustomLabwareDef: (
}

export const createCustomLabwareDef: (
event: React.SyntheticEvent<HTMLInputElement>
) => ThunkAction<any> = _createCustomLabwareDef(false)
event: React.SyntheticEvent<HTMLInputElement>,
has96Channel: boolean
) => (event: React.SyntheticEvent<HTMLInputElement>) => ThunkAction<any> = (
event,
has96Channel
) => _createCustomLabwareDef(false, has96Channel)

Check warning on line 253 in protocol-designer/src/labware-defs/actions.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/labware-defs/actions.ts#L253

Added line #L253 was not covered by tests

export const createCustomTiprackDef: (
event: React.SyntheticEvent<HTMLInputElement>
) => ThunkAction<any> = _createCustomLabwareDef(true)
event: React.SyntheticEvent<HTMLInputElement>,
has96Channel: boolean
) => (event: React.SyntheticEvent<HTMLInputElement>) => ThunkAction<any> = (
event,
has96Channel
) => _createCustomLabwareDef(true, has96Channel)

Check warning on line 261 in protocol-designer/src/labware-defs/actions.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/labware-defs/actions.ts#L261

Added line #L261 was not covered by tests

interface DismissLabwareUploadMessage {
type: 'DISMISS_LABWARE_UPLOAD_MESSAGE'
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ import {
getAllWellsFromPrimaryWells,
} from './utils'
import { getDefaultsForStepType } from '../getDefaultsForStepType'
import { LabwareEntities, PipetteEntities } from '@opentrons/step-generation'
import { FormData, StepFieldName } from '../../../form-types'
import { FormPatch } from '../../actions/types'
import type {
LabwareEntities,
PipetteEntities,
} from '@opentrons/step-generation'
import type { FormData, StepFieldName } from '../../../form-types'
import type { FormPatch } from '../../actions/types'

// TODO: Ian 2019-02-21 import this from a more central place - see #2926
const getDefaultFields = (...fields: StepFieldName[]): FormPatch =>
Expand Down Expand Up @@ -53,8 +56,10 @@ const updatePatchOnPipetteChannelChange = (
? getChannels(patch.pipette, pipetteEntities)
: null
const appliedPatch = { ...rawForm, ...patch }
const singleToMulti = prevChannels === 1 && nextChannels === 8
const multiToSingle = prevChannels === 8 && nextChannels === 1
const singleToMulti =
prevChannels === 1 && (nextChannels === 8 || nextChannels === 96)
const multiToSingle =
(prevChannels === 8 || prevChannels === 96) && nextChannels === 1

if (patch.pipette === null || singleToMulti) {
// reset all well selection
Expand All @@ -68,11 +73,19 @@ const updatePatchOnPipetteChannelChange = (
}),
}
} else if (multiToSingle) {
let channels: 8 | 96 = 8
if (prevChannels === 96) {
channels = 96

Check warning on line 78 in protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMix.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMix.ts#L78

Added line #L78 was not covered by tests
}
// multi-channel to single-channel: convert primary wells to all wells
const labwareId = appliedPatch.labware
const labwareDef = labwareEntities[labwareId].def
update = {
wells: getAllWellsFromPrimaryWells(appliedPatch.wells, labwareDef),
wells: getAllWellsFromPrimaryWells(
appliedPatch.wells,
labwareDef,
channels
),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,10 @@ const updatePatchOnPipetteChannelChange = (
: null
const { id, stepType, ...stepData } = rawForm
const appliedPatch = { ...(stepData as FormPatch), ...patch, id, stepType }
const singleToMulti = prevChannels === 1 && nextChannels === 8
const multiToSingle = prevChannels === 8 && nextChannels === 1
const singleToMulti =
prevChannels === 1 && (nextChannels === 8 || nextChannels === 96)
const multiToSingle =
(prevChannels === 8 || prevChannels === 96) && nextChannels === 1

if (patch.pipette === null || singleToMulti) {
// reset all well selection
Expand All @@ -475,6 +477,10 @@ const updatePatchOnPipetteChannelChange = (
}),
}
} else if (multiToSingle) {
let channels = 8

Check warning on line 480 in protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMoveLiquid.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMoveLiquid.ts#L480

Added line #L480 was not covered by tests
if (prevChannels === 96) {
channels = 96

Check warning on line 482 in protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMoveLiquid.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/steplist/formLevel/handleFormChange/dependentFieldsUpdateMoveLiquid.ts#L482

Added line #L482 was not covered by tests
}
// multi-channel to single-channel: convert primary wells to all wells
// @ts-expect-error(sa, 2021-06-14): appliedPatch.aspirate_labware is type ?unknown. Address in #3161
const sourceLabwareId: string = appliedPatch.aspirate_labware
Expand All @@ -488,12 +494,14 @@ const updatePatchOnPipetteChannelChange = (
aspirate_wells: getAllWellsFromPrimaryWells(
// @ts-expect-error(sa, 2021-06-14): appliedPatch.aspirate_wells is type ?unknown. Address in #3161
appliedPatch.aspirate_wells, // @ts-expect-error(sa, 2021-06-14): sourceLabwareDef is not typed properly. Address in #3161
sourceLabwareDef
sourceLabwareDef,
channels
),
dispense_wells: getAllWellsFromPrimaryWells(
// @ts-expect-error(sa, 2021-06-14): appliedPatch.dispense_wells is type ?unknown. Address in #3161
appliedPatch.dispense_wells, // @ts-expect-error(sa, 2021-06-14): destLabwareDef is not typed properly. Address in #3161
destLabwareDef
destLabwareDef,
channels
),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ export function chainPatchUpdaters(
// included in that set. Used to convert multi to single.
export function getAllWellsFromPrimaryWells(
primaryWells: string[],
labwareDef: LabwareDefinition2
labwareDef: LabwareDefinition2,
channels: 8 | 96
): string[] {
const allWells = primaryWells.reduce((acc: string[], well: string) => {
const nextWellSet = getWellSetForMultichannel(labwareDef, well, 8)
const nextWellSet = getWellSetForMultichannel(labwareDef, well, channels)

// filter out any nulls (but you shouldn't get any)
if (!nextWellSet) {
Expand Down
9 changes: 8 additions & 1 deletion protocol-designer/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { WellSetHelpers, makeWellSetHelpers } from '@opentrons/shared-data'
import { i18n } from '../localization'
import { WellGroup } from '@opentrons/components'
import { BoundingRect, GenericRect } from '../collision-types'
import type { LabwareEntities } from '@opentrons/step-generation'
import type {
LabwareEntities,
PipetteEntities,
} from '@opentrons/step-generation'

export const registerSelectors: (arg0: any) => void =
process.env.NODE_ENV === 'development'
Expand Down Expand Up @@ -116,3 +119,7 @@ export const getIsAdapter = (
labwareEntities[labwareId].def.allowedRoles?.includes('adapter') ?? false
)
}

export const getHas96Channel = (pipettes: PipetteEntities): boolean => {
return Object.values(pipettes).some(pip => pip.name === 'p1000_96')

Check warning on line 124 in protocol-designer/src/utils/index.ts

View check run for this annotation

Codecov / codecov/patch

protocol-designer/src/utils/index.ts#L124

Added line #L124 was not covered by tests
}
2 changes: 1 addition & 1 deletion shared-data/pipette/fixtures/name/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import _pipetteNameSpecFixtures from './pipetteNameSpecFixtures.json'
import type { PipetteName, PipetteNameSpecs } from '@opentrons/shared-data'
import type { PipetteName, PipetteNameSpecs } from '../../../js'

const pipetteNameSpecFixtures = _pipetteNameSpecFixtures as Record<
PipetteName,
Expand Down
34 changes: 3 additions & 31 deletions shared-data/pipette/fixtures/name/pipetteNameSpecFixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,46 +113,18 @@
},
"p1000_96": {
"displayName": "Flex 96-Channel 1000 μL",
"displayCategory": "GEN1",
"defaultAspirateFlowRate": {
"value": 7.85,
"min": 3,
"max": 812,
"valuesByApiLevel": {
"2.0": 7.85
}
"max": 812
},
"defaultDispenseFlowRate": {
"value": 7.85,
"min": 3,
"max": 812,
"valuesByApiLevel": {
"2.0": 7.85
}
},
"defaultBlowOutFlowRate": {
"value": 7.85,
"min": 3,
"max": 812,
"valuesByApiLevel": {
"2.0": 7.85
}
"max": 812
},
"channels": 96,
"minVolume": 5,
"maxVolume": 1000,
"smoothieConfigs": {
"stepsPerMM": 2133.33,
"homePosition": 230.15,
"travelDistance": 80
},
"defaultTipracks": [
"opentrons/opentrons_flex_96_tiprack_1000ul/1",
"opentrons/opentrons_flex_96_filtertiprack_1000ul/1",
"opentrons/opentrons_flex_96_tiprack_200ul/1",
"opentrons/opentrons_flex_96_filtertiprack_200ul/1",
"opentrons/opentrons_flex_96_tiprack_50ul/1",
"opentrons/opentrons_flex_96_filtertiprack_50ul/1"
]
"maxVolume": 1000
}
}

0 comments on commit b3e972c

Please sign in to comment.