From 9e4b15c59d7f2fd917193de0e29461f1e1eb1413 Mon Sep 17 00:00:00 2001 From: Brian Cooper Date: Wed, 20 Mar 2024 17:18:39 -0400 Subject: [PATCH] module fixtures and AA's are versioned --- .../hardware-sim/DeckSlotLocation/index.tsx | 6 +- shared-data/deck/types/schemaV5.ts | 56 +++++++++++-------- shared-data/js/constants.ts | 10 ++-- shared-data/js/fixtures.ts | 50 ++++++++++------- .../helpers/getAddressableAreasInProtocol.ts | 19 +++++-- 5 files changed, 86 insertions(+), 55 deletions(-) diff --git a/components/src/hardware-sim/DeckSlotLocation/index.tsx b/components/src/hardware-sim/DeckSlotLocation/index.tsx index f40558219ec..fbe8431ea54 100644 --- a/components/src/hardware-sim/DeckSlotLocation/index.tsx +++ b/components/src/hardware-sim/DeckSlotLocation/index.tsx @@ -2,7 +2,7 @@ import * as React from 'react' import { getPositionFromSlotId, OT2_ROBOT_TYPE, - ot2DeckDefV4, + ot2DeckDefV5, } from '@opentrons/shared-data' import { SlotBase } from '../BaseDeck/SlotBase' @@ -40,7 +40,7 @@ export function LegacyDeckSlotLocation( if (robotType !== OT2_ROBOT_TYPE) return null - const slotDef = ot2DeckDefV4.locations.addressableAreas.find( + const slotDef = ot2DeckDefV5.locations.addressableAreas.find( s => s.id === slotName ) if (slotDef == null) { @@ -52,7 +52,7 @@ export function LegacyDeckSlotLocation( const slotPosition = getPositionFromSlotId( slotName, - (ot2DeckDefV4 as unknown) as DeckDefinition + (ot2DeckDefV5 as unknown) as DeckDefinition ) const isFixedTrash = slotName === 'fixedTrash' diff --git a/shared-data/deck/types/schemaV5.ts b/shared-data/deck/types/schemaV5.ts index df939dbb24b..7e2bb027088 100644 --- a/shared-data/deck/types/schemaV5.ts +++ b/shared-data/deck/types/schemaV5.ts @@ -27,23 +27,35 @@ export type FlexAddressableAreaName = | '8ChannelWasteChute' | '96ChannelWasteChute' | 'gripperWasteChute' - | 'thermocyclerModule' - | 'heaterShakerA1' - | 'heaterShakerB1' - | 'heaterShakerC1' - | 'heaterShakerD1' - | 'heaterShakerA3' - | 'heaterShakerB3' - | 'heaterShakerC3' - | 'heaterShakerD3' - | 'temperatureModuleA1' - | 'temperatureModuleB1' - | 'temperatureModuleC1' - | 'temperatureModuleD1' - | 'temperatureModuleA3' - | 'temperatureModuleB3' - | 'temperatureModuleC3' - | 'temperatureModuleD3' + | 'thermocyclerModuleV2' + | 'heaterShakerV1A1' + | 'heaterShakerV1B1' + | 'heaterShakerV1C1' + | 'heaterShakerV1D1' + | 'heaterShakerV1A3' + | 'heaterShakerV1B3' + | 'heaterShakerV1C3' + | 'heaterShakerV1D3' + | 'temperatureModuleV2A1' + | 'temperatureModuleV2B1' + | 'temperatureModuleV2C1' + | 'temperatureModuleV2D1' + | 'temperatureModuleV2A3' + | 'temperatureModuleV2B3' + | 'temperatureModuleV2C3' + | 'temperatureModuleV2D3' + | 'magneticBlockV1A1' + | 'magneticBlockV1B1' + | 'magneticBlockV1C1' + | 'magneticBlockV1D1' + | 'magneticBlockV1A2' + | 'magneticBlockV1B2' + | 'magneticBlockV1C2' + | 'magneticBlockV1D2' + | 'magneticBlockV1A3' + | 'magneticBlockV1B3' + | 'magneticBlockV1C3' + | 'magneticBlockV1D3' export type OT2AddressableAreaName = | '1' @@ -108,11 +120,11 @@ export type WasteChuteCutoutFixtureId = | 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' export type FlexModuleCutoutFixtureId = - | 'heaterShakerModule' - | 'temperatureModule' - | 'magneticBlockModule' - | 'thermocyclerModuleRear' - | 'thermocyclerModuleFront' + | 'heaterShakerModuleV1' + | 'temperatureModuleV2' + | 'magneticBlockModuleV1' + | 'thermocyclerModuleV2Rear' + | 'thermocyclerModuleV2Front' export type OT2SingleStandardSlot = 'singleStandardSlot' diff --git a/shared-data/js/constants.ts b/shared-data/js/constants.ts index ab28e628e18..d5216e27184 100644 --- a/shared-data/js/constants.ts +++ b/shared-data/js/constants.ts @@ -377,11 +377,11 @@ export const STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE: ' export const STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE: 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' = 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' -export const HEATERSHAKER_MODULE_V1_FIXTURE: 'heaterShakerModule' = 'heaterShakerModule' -export const TEMPERATURE_MODULE_V2_FIXTURE: 'temperatureModule' = 'temperatureModule' -export const MAGNETIC_BLOCK_V1_FIXTURE: 'magneticBlockModule' = 'magneticBlockModule' -export const THERMOCYCLER_V2_REAR_FIXTURE: 'thermocyclerModuleRear' = 'thermocyclerModuleRear' -export const THERMOCYCLER_V2_FRONT_FIXTURE: 'thermocyclerModuleFront' = 'thermocyclerModuleFront' +export const HEATERSHAKER_MODULE_V1_FIXTURE: 'heaterShakerModuleV1' = 'heaterShakerModuleV1' +export const TEMPERATURE_MODULE_V2_FIXTURE: 'temperatureModuleV2' = 'temperatureModuleV2' +export const MAGNETIC_BLOCK_V1_FIXTURE: 'magneticBlockModuleV1' = 'magneticBlockModuleV1' +export const THERMOCYCLER_V2_REAR_FIXTURE: 'thermocyclerModuleV2Rear' = 'thermocyclerModuleV2Rear' +export const THERMOCYCLER_V2_FRONT_FIXTURE: 'thermocyclerModuleV2Front' = 'thermocyclerModuleV2Front' export const MODULE_FIXTURES_BY_MODEL: {[moduleModel in ModuleModel]?: FlexModuleCutoutFixtureId[]} = { [HEATERSHAKER_MODULE_V1]: [HEATERSHAKER_MODULE_V1_FIXTURE], diff --git a/shared-data/js/fixtures.ts b/shared-data/js/fixtures.ts index 9730ed33356..44da5ccb56d 100644 --- a/shared-data/js/fixtures.ts +++ b/shared-data/js/fixtures.ts @@ -40,9 +40,9 @@ import { THERMOCYCLER_V2_FRONT_FIXTURE, MODULE_FIXTURES_BY_MODEL, } from './constants' -import type { CutoutFixtureId, CutoutId, FlexModuleCutoutFixtureId, OT2CutoutId } from '../deck' +import type { AddressableAreaName, CutoutFixtureId, CutoutId, FlexAddressableAreaName, FlexModuleCutoutFixtureId, OT2CutoutId } from '../deck' import type { AddressableArea, CoordinateTuple, DeckDefinition, ModuleModel } from './types' -import type { LoadModuleCreateCommand } from '../command' +import type { LoadModuleCreateCommand, ModuleLocation } from '../command' import { getModuleDisplayName } from './modules' export function getCutoutDisplayName(cutout: CutoutId): string { @@ -122,10 +122,10 @@ export function getPositionFromSlotId( const slotPosition: CoordinateTuple | null = cutoutPosition != null ? [ - cutoutPosition[0] + offsetFromCutoutFixture[0], - cutoutPosition[1] + offsetFromCutoutFixture[1], - cutoutPosition[2] + offsetFromCutoutFixture[2], - ] + cutoutPosition[0] + offsetFromCutoutFixture[0], + cutoutPosition[1] + offsetFromCutoutFixture[1], + cutoutPosition[2] + offsetFromCutoutFixture[2], + ] : null return slotPosition @@ -142,29 +142,41 @@ export function getAddressableAreaFromSlotId( ) } -export function getCutoutFixturesForModuleModel( +export function getCutoutFixtureIdsForModuleModel( moduleModel: ModuleModel ): FlexModuleCutoutFixtureId[] { const moduleFixtures = MODULE_FIXTURES_BY_MODEL[moduleModel] return moduleFixtures ?? [] } -export function getAddressableAreaFromLoadedModule( +export function getCutoutIdFromModuleLocation( + location: ModuleLocation, + deckDef: DeckDefinition +): CutoutId | null { + return deckDef.locations.cutouts.find( + cutout => cutout.id.includes(location.slotName) + )?.id ?? null +} + +export function getAddressableAreaNamesFromLoadedModule( params: LoadModuleCreateCommand['params'], deckDef: DeckDefinition -): AddressableArea | null { - const moduleFixtures = getCutoutFixturesForModuleModel(params.model) - return ( - deckDef.locations.addressableAreas.find( - addressableArea => addressableArea.id === slotId +): AddressableAreaName[] { + const moduleFixtureIds = getCutoutFixtureIdsForModuleModel(params.model) + const cutoutId = getCutoutIdFromModuleLocation(params.location, deckDef) + return moduleFixtureIds.reduce((acc, cutoutFixtureId) => { + const cutoutFixture = deckDef.cutoutFixtures.find( + cf => cf.id === cutoutFixtureId ) ?? null - ) + const providedAddressableAreas = cutoutId != null ?cutoutFixture?.providesAddressableAreas[cutoutId] ?? [] : [] + return [...acc, ...providedAddressableAreas] + }, []) } export function getFixtureDisplayName( cutoutFixtureId: CutoutFixtureId | null ): string { - switch(cutoutFixtureId) { + switch (cutoutFixtureId) { case STAGING_AREA_RIGHT_SLOT_FIXTURE: return 'Staging area slot' case TRASH_BIN_ADAPTER_FIXTURE: @@ -192,7 +204,7 @@ export function getFixtureDisplayName( } } -const STANDARD_OT2_SLOTS = [ +const STANDARD_OT2_SLOTS: AddressableAreaName[]= [ ADDRESSABLE_AREA_1, ADDRESSABLE_AREA_2, ADDRESSABLE_AREA_3, @@ -206,7 +218,7 @@ const STANDARD_OT2_SLOTS = [ ADDRESSABLE_AREA_11, ] -const STANDARD_FLEX_SLOTS = [ +const STANDARD_FLEX_SLOTS: AddressableAreaName[] = [ A1_ADDRESSABLE_AREA, A2_ADDRESSABLE_AREA, A3_ADDRESSABLE_AREA, @@ -222,10 +234,10 @@ const STANDARD_FLEX_SLOTS = [ ] export const isAddressableAreaStandardSlot = ( - addressableAreaId: string, + addressableAreaName: AddressableAreaName, deckDef: DeckDefinition ): boolean => (deckDef.robot.model === FLEX_ROBOT_TYPE ? STANDARD_FLEX_SLOTS : STANDARD_OT2_SLOTS - ).includes(addressableAreaId) + ).includes(addressableAreaName) diff --git a/shared-data/js/helpers/getAddressableAreasInProtocol.ts b/shared-data/js/helpers/getAddressableAreasInProtocol.ts index 902a9544c0e..82367c77a5a 100644 --- a/shared-data/js/helpers/getAddressableAreasInProtocol.ts +++ b/shared-data/js/helpers/getAddressableAreasInProtocol.ts @@ -1,5 +1,5 @@ import { MOVABLE_TRASH_A3_ADDRESSABLE_AREA } from '../constants' -import { getAddressableAreaFromSlotId } from '../fixtures' +import { getAddressableAreaNamesFromLoadedModule, getAddressableAreaFromSlotId } from '../fixtures' import type { AddressableAreaName } from '../../deck' import type { ProtocolAnalysisOutput } from '../../protocol' import type { CompletedProtocolAnalysis, DeckDefinition } from '../types' @@ -17,9 +17,7 @@ export function getAddressableAreasInProtocol( commandType === 'moveLabware' && params.newLocation !== 'offDeck' && 'slotName' in params.newLocation && - !acc.includes( - params.newLocation.slotName as AddressableAreaName - ) + !acc.includes(params.newLocation.slotName as AddressableAreaName) ) { const addressableAreaName = getAddressableAreaFromSlotId( params.newLocation.slotName, @@ -39,8 +37,7 @@ export function getAddressableAreasInProtocol( ) { return [...acc, params.newLocation.addressableAreaName] } else if ( - (commandType === 'loadLabware' || - commandType === 'loadModule') && + commandType === 'loadLabware' && params.location !== 'offDeck' && 'slotName' in params.location && !acc.includes(params.location.slotName as AddressableAreaName) @@ -60,6 +57,16 @@ export function getAddressableAreasInProtocol( } else { return [...acc, addressableAreaName] } + } else if ( + commandType === 'loadModule' && + !acc.includes(params.location.slotName as AddressableAreaName) + ) { + const addressableAreaNames = getAddressableAreaNamesFromLoadedModule( + params, + deckDef + ) + + return [...acc, ...addressableAreaNames] } else if ( commandType === 'loadLabware' && params.location !== 'offDeck' &&