Skip to content

Commit

Permalink
fix(app): creates required protocol deck config fixture utility
Browse files Browse the repository at this point in the history
creates utility getRequiredDeckConfig to generate list of required protocol deck config fixtures for
rendering in fixture lists. fixes a couple bugs rendering empty fixture tables. also removes
unnecessary getDeckDefFromRobotTypeV4
  • Loading branch information
brenthagen committed Nov 17, 2023
1 parent f73e925 commit d9d5cac
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 86 deletions.
9 changes: 7 additions & 2 deletions app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
import { Line } from '../../../atoms/structure'
import { StyledText } from '../../../atoms/text'
import { InfoMessage } from '../../../molecules/InfoMessage'
import { getSimplestDeckConfigForProtocolCommands } from '../../../resources/deck_configuration/utils'
import {
getRequiredDeckConfig,
getSimplestDeckConfigForProtocolCommands,
} from '../../../resources/deck_configuration/utils'
import {
useIsFlex,
useRobot,
Expand Down Expand Up @@ -121,7 +124,9 @@ export function ProtocolRunSetup({
protocolAnalysis?.commands ?? []
)

const hasFixtures = protocolDeckConfig.length > 0
const requiredDeckConfig = getRequiredDeckConfig(protocolDeckConfig)

const hasFixtures = requiredDeckConfig.length > 0

let moduleDescription: string = t(`${MODULE_SETUP_KEY}_description`, {
count: modules.length,
Expand Down
22 changes: 8 additions & 14 deletions app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import {
useHoverTooltip,
PrimaryButton,
} from '@opentrons/components'
import { FLEX_SINGLE_SLOT_ADDRESSABLE_AREAS } from '@opentrons/shared-data'

import { useToggleGroup } from '../../../../molecules/ToggleGroup/useToggleGroup'
import { useDeckConfigurationCompatibility } from '../../../../resources/deck_configuration/hooks'
import { getRequiredDeckConfig } from '../../../../resources/deck_configuration/utils'
import { Tooltip } from '../../../../atoms/Tooltip'
import {
useRunHasStarted,
Expand Down Expand Up @@ -57,16 +57,8 @@ export const SetupModuleAndDeck = ({
commands
)

const nonSingleSlotDeckConfigCompatibility = deckConfigCompatibility.filter(
({ requiredAddressableAreas }) =>
// required AA list includes a non-single-slot AA
!requiredAddressableAreas.every(aa =>
FLEX_SINGLE_SLOT_ADDRESSABLE_AREAS.includes(aa)
)
)
// fixture includes at least 1 required AA
const requiredDeckConfigCompatibility = nonSingleSlotDeckConfigCompatibility.filter(
fixture => fixture.requiredAddressableAreas.length > 0
const requiredDeckConfigCompatibility = getRequiredDeckConfig(
deckConfigCompatibility
)

return (
Expand All @@ -78,9 +70,11 @@ export const SetupModuleAndDeck = ({
{hasModules ? (
<SetupModulesList robotName={robotName} runId={runId} />
) : null}
<SetupFixtureList
deckConfigCompatibility={requiredDeckConfigCompatibility}
/>
{requiredDeckConfigCompatibility.length > 0 ? (
<SetupFixtureList
deckConfigCompatibility={requiredDeckConfigCompatibility}
/>
) : null}
</>
) : (
<SetupModulesMap runId={runId} />
Expand Down
102 changes: 54 additions & 48 deletions app/src/organisms/ProtocolSetupModulesAndDeck/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ export function ProtocolSetupModulesAndDeck({
protocolModulesInfo
)

const hasModules = attachedProtocolModuleMatches.length > 0

const {
missingModuleIds,
remainingAttachedModules,
Expand Down Expand Up @@ -421,56 +423,60 @@ export function ProtocolSetupModulesAndDeck({
/>
) : null}
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing32}>
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
<Flex
color={COLORS.darkBlack70}
fontSize={TYPOGRAPHY.fontSize22}
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
gridGap={SPACING.spacing24}
lineHeight={TYPOGRAPHY.lineHeight28}
paddingX={SPACING.spacing24}
>
<StyledText flex="4 0 0">{t('module')}</StyledText>
<StyledText flex="2 0 0">{t('location')}</StyledText>
<StyledText flex="3 0 0"> {t('status')}</StyledText>
</Flex>
{attachedProtocolModuleMatches.map(module => {
// check for duplicate module model in list of modules for protocol
const isDuplicateModuleModel = protocolModulesInfo
// filter out current module
.filter(otherModule => otherModule.moduleId !== module.moduleId)
// check for existence of another module of same model
.some(
otherModule =>
otherModule.moduleDef.model === module.moduleDef.model
)
{hasModules ? (
<Flex flexDirection={DIRECTION_COLUMN} gridGap={SPACING.spacing8}>
<Flex
color={COLORS.darkBlack70}
fontSize={TYPOGRAPHY.fontSize22}
fontWeight={TYPOGRAPHY.fontWeightSemiBold}
gridGap={SPACING.spacing24}
lineHeight={TYPOGRAPHY.lineHeight28}
paddingX={SPACING.spacing24}
>
<StyledText flex="4 0 0">{t('module')}</StyledText>
<StyledText flex="2 0 0">{t('location')}</StyledText>
<StyledText flex="3 0 0"> {t('status')}</StyledText>
</Flex>
{attachedProtocolModuleMatches.map(module => {
// check for duplicate module model in list of modules for protocol
const isDuplicateModuleModel = protocolModulesInfo
// filter out current module
.filter(
otherModule => otherModule.moduleId !== module.moduleId
)
// check for existence of another module of same model
.some(
otherModule =>
otherModule.moduleDef.model === module.moduleDef.model
)

const cutoutIdForSlotName = getCutoutIdForSlotName(
module.slotName,
deckDef
)
const cutoutIdForSlotName = getCutoutIdForSlotName(
module.slotName,
deckDef
)

return (
<RowModule
key={module.moduleId}
module={module}
isDuplicateModuleModel={isDuplicateModuleModel}
setShowMultipleModulesModal={setShowMultipleModulesModal}
calibrationStatus={calibrationStatus}
chainLiveCommands={chainLiveCommands}
isLoading={isCommandMutationLoading}
prepCommandErrorMessage={prepCommandErrorMessage}
setPrepCommandErrorMessage={setPrepCommandErrorMessage}
conflictedFixture={deckConfig?.find(
fixture =>
fixture.cutoutId === cutoutIdForSlotName &&
fixture.cutoutFixtureId != null &&
!SINGLE_SLOT_FIXTURES.includes(fixture.cutoutFixtureId)
)}
/>
)
})}
</Flex>
return (
<RowModule
key={module.moduleId}
module={module}
isDuplicateModuleModel={isDuplicateModuleModel}
setShowMultipleModulesModal={setShowMultipleModulesModal}
calibrationStatus={calibrationStatus}
chainLiveCommands={chainLiveCommands}
isLoading={isCommandMutationLoading}
prepCommandErrorMessage={prepCommandErrorMessage}
setPrepCommandErrorMessage={setPrepCommandErrorMessage}
conflictedFixture={deckConfig?.find(
fixture =>
fixture.cutoutId === cutoutIdForSlotName &&
fixture.cutoutFixtureId != null &&
!SINGLE_SLOT_FIXTURES.includes(fixture.cutoutFixtureId)
)}
/>
)
})}
</Flex>
) : null}
<FixtureTable
robotType={FLEX_ROBOT_TYPE}
mostRecentAnalysis={mostRecentAnalysis}
Expand Down
4 changes: 2 additions & 2 deletions app/src/resources/deck_configuration/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { parseAllAddressableAreas } from '@opentrons/api-client'
import { useDeckConfigurationQuery } from '@opentrons/react-api-client'
import {
FLEX_ROBOT_TYPE,
getDeckDefFromRobotTypeV4,
getDeckDefFromRobotType,
} from '@opentrons/shared-data'

import {
Expand All @@ -26,7 +26,7 @@ export function useDeckConfigurationCompatibility(
): CutoutConfigAndCompatibility[] {
const deckConfig = useDeckConfigurationQuery().data ?? []
if (robotType !== FLEX_ROBOT_TYPE) return []
const deckDef = getDeckDefFromRobotTypeV4(robotType)
const deckDef = getDeckDefFromRobotType(robotType)
const allAddressableAreas = parseAllAddressableAreas(protocolCommands)
return deckConfig.reduce<CutoutConfigAndCompatibility[]>(
(acc, { cutoutId, cutoutFixtureId }) => {
Expand Down
29 changes: 23 additions & 6 deletions app/src/resources/deck_configuration/utils.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
import { parseAllAddressableAreas } from '@opentrons/api-client'
import {
FLEX_ROBOT_TYPE,
FLEX_SINGLE_SLOT_ADDRESSABLE_AREAS,
getAddressableAreaFromSlotId,
getDeckDefFromRobotTypeV4,
getDeckDefFromRobotType,
} from '@opentrons/shared-data'

import type {
CutoutConfig,
CutoutId,
RunTimeCommand,
CutoutFixtureId,
CutoutFixture,
AddressableAreaName,
DeckDefinition,
} from '@opentrons/shared-data'

export interface CutoutConfigProtocolSpec {
cutoutId: CutoutId
cutoutFixtureId: CutoutFixtureId | null
export interface CutoutConfigProtocolSpec extends CutoutConfig {
requiredAddressableAreas: AddressableAreaName[]
}

Expand Down Expand Up @@ -87,7 +86,7 @@ export function getSimplestDeckConfigForProtocolCommands(
protocolAnalysisCommands: RunTimeCommand[]
): CutoutConfigProtocolSpec[] {
// TODO(BC, 2023-11-06): abstract out the robot type
const deckDef = getDeckDefFromRobotTypeV4(FLEX_ROBOT_TYPE)
const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE)

const addressableAreas = parseAllAddressableAreas(protocolAnalysisCommands)
const simplestDeckConfig = addressableAreas.reduce<
Expand Down Expand Up @@ -226,3 +225,21 @@ export function getSimplestFixtureForAddressableAreas(
)
return nextCompatibleCutoutFixtures?.[0] ?? null
}

export function getRequiredDeckConfig<T extends CutoutConfigProtocolSpec>(
deckConfigProtocolSpec: T[]
): T[] {
const nonSingleSlotDeckConfigCompatibility = deckConfigProtocolSpec.filter(
({ requiredAddressableAreas }) =>
// required AA list includes a non-single-slot AA
!requiredAddressableAreas.every(aa =>
FLEX_SINGLE_SLOT_ADDRESSABLE_AREAS.includes(aa)
)
)
// fixture includes at least 1 required AA
const requiredDeckConfigProtocolSpec = nonSingleSlotDeckConfigCompatibility.filter(
fixture => fixture.requiredAddressableAreas.length > 0
)

return requiredDeckConfigProtocolSpec
}
4 changes: 2 additions & 2 deletions protocol-designer/src/step-forms/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
PipetteName,
THERMOCYCLER_MODULE_TYPE,
WASTE_CHUTE_ADDRESSABLE_AREAS,
getDeckDefFromRobotTypeV4,
getDeckDefFromRobotType,
AddressableAreaName,
CutoutId,
} from '@opentrons/shared-data'
Expand Down Expand Up @@ -1331,7 +1331,7 @@ export const additionalEquipmentInvariantProperties = handleActions<NormalizedAd
): NormalizedAdditionalEquipmentById => {
const { file } = action.payload
const isFlex = file.robot.model === FLEX_ROBOT_TYPE
const deckDef = getDeckDefFromRobotTypeV4(FLEX_ROBOT_TYPE)
const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE)
const cutoutFixtures = deckDef.cutoutFixtures
const providesAddressableAreasForAddressableArea = cutoutFixtures.find(
cutoutFixture => cutoutFixture.id.includes('stagingAreaRightSlot')
Expand Down
4 changes: 2 additions & 2 deletions protocol-designer/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
WellSetHelpers,
makeWellSetHelpers,
AddressableAreaName,
getDeckDefFromRobotTypeV4,
getDeckDefFromRobotType,
FLEX_ROBOT_TYPE,
CutoutId,
STAGING_AREA_RIGHT_SLOT_FIXTURE,
Expand Down Expand Up @@ -145,7 +145,7 @@ export const getHas96Channel = (pipettes: PipetteEntities): boolean => {
export const getStagingAreaAddressableAreas = (
cutoutIds: CutoutId[]
): AddressableAreaName[] => {
const deckDef = getDeckDefFromRobotTypeV4(FLEX_ROBOT_TYPE)
const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE)
const cutoutFixtures = deckDef.cutoutFixtures

return cutoutIds
Expand Down
10 changes: 0 additions & 10 deletions shared-data/js/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,3 @@ export const getDeckDefFromRobotType = (
? standardFlexDeckDef
: standardOt2DeckDef
}

// TODO(bh, 2023-11-09): delete this function
export const getDeckDefFromRobotTypeV4 = (
robotType: RobotType
): DeckDefinition => {
// @ts-expect-error imported JSON not playing nice with TS. see https://github.com/microsoft/TypeScript/issues/32063
return robotType === 'OT-3 Standard'
? standardFlexDeckDef
: standardOt2DeckDef
}

0 comments on commit d9d5cac

Please sign in to comment.