Skip to content

Commit

Permalink
refactor(app): split labware location from display location
Browse files Browse the repository at this point in the history
  • Loading branch information
mjhuff committed Oct 29, 2024
1 parent 4530e4e commit 5eab60c
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 152 deletions.
202 changes: 55 additions & 147 deletions app/src/local-resources/labware/utils/getLabwareDisplayLocation.ts
Original file line number Diff line number Diff line change
@@ -1,180 +1,88 @@
import {
getLabwareDefURI,
getLabwareDisplayName,
getModuleDisplayName,
getModuleType,
getOccludedSlotCountForModule,
} from '@opentrons/shared-data'

import {
getModuleModel,
getModuleDisplayLocation,
} from '/app/local-resources/modules'
import { getLabwareLocation } from './getLabwareLocation'

import type { TFunction } from 'i18next'
import type {
LabwareDefinition2,
LabwareLocation,
RobotType,
} from '@opentrons/shared-data'
import type { LoadedLabwares } from '/app/local-resources/labware'
import type { LoadedModules } from '/app/local-resources/modules'
LocationSlotOnlyParams,
LocationFullParams,
} from './getLabwareLocation'

interface LabwareDisplayLocationBaseParams {
location: LabwareLocation | null
loadedModules: LoadedModules
loadedLabwares: LoadedLabwares
robotType: RobotType
export interface DisplayLocationSlotOnlyParams extends LocationSlotOnlyParams {
t: TFunction
isOnDevice?: boolean
}

export interface LabwareDisplayLocationSlotOnly
extends LabwareDisplayLocationBaseParams {
detailLevel: 'slot-only'
}

export interface LabwareDisplayLocationFull
extends LabwareDisplayLocationBaseParams {
detailLevel?: 'full'
allRunDefs: LabwareDefinition2[]
export interface DisplayLocationFullParams extends LocationFullParams {
t: TFunction
isOnDevice?: boolean
}

export type LabwareDisplayLocationParams =
| LabwareDisplayLocationSlotOnly
| LabwareDisplayLocationFull
export type DisplayLocationParams =
| DisplayLocationSlotOnlyParams
| DisplayLocationFullParams

// detailLevel applies to nested labware. If 'full', return copy that includes the actual peripheral that nests the
// labware, ex, "in module XYZ in slot C1".
// If 'slot-only', return only the slot name, ex "in slot C1".
export function getLabwareDisplayLocation(
params: LabwareDisplayLocationParams
params: DisplayLocationParams
): string {
const {
loadedLabwares,
loadedModules,
location,
robotType,
t,
isOnDevice = false,
detailLevel = 'full',
} = params
const { t, isOnDevice = false } = params
const locationResult = getLabwareLocation(params)

if (location == null) {
console.error('Cannot get labware display location. No location provided.')
if (locationResult == null) {
return ''
} else if (location === 'offDeck') {
return t('off_deck')
} else if ('slotName' in location) {
return isOnDevice
? location.slotName
: t('slot', { slot_name: location.slotName })
} else if ('addressableAreaName' in location) {
return isOnDevice
? location.addressableAreaName
: t('slot', { slot_name: location.addressableAreaName })
} else if ('moduleId' in location) {
const moduleModel = getModuleModel(loadedModules, location.moduleId)
if (moduleModel == null) {
console.error('labware is located on an unknown module model')
return ''
}
const slotName = getModuleDisplayLocation(loadedModules, location.moduleId)
}

if (detailLevel === 'slot-only') {
return t('slot', { slot_name: slotName })
}
const { slotName, moduleModel, adapterName } = locationResult

return isOnDevice
? `${getModuleDisplayName(moduleModel)}, ${slotName}`
: t('module_in_slot', {
count: getOccludedSlotCountForModule(
getModuleType(moduleModel),
robotType
),
module: getModuleDisplayName(moduleModel),
slot_name: slotName,
})
} else if ('labwareId' in location) {
if (!Array.isArray(loadedLabwares)) {
console.error('Cannot get display location from loaded labwares object')
return ''
if (slotName === 'offDeck') {
return t('off_deck')
}
// Simple slot location
else if (moduleModel == null && adapterName == null) {
return isOnDevice ? slotName : t('slot', { slot_name: slotName })
}
// Module location without adapter
else if (moduleModel != null && adapterName == null) {
if (params.detailLevel === 'slot-only') {
return t('slot', { slot_name: slotName })
} else {
return isOnDevice
? `${getModuleDisplayName(moduleModel)}, ${slotName}`
: t('module_in_slot', {
count: getOccludedSlotCountForModule(
getModuleType(moduleModel),
params.robotType
),
module: getModuleDisplayName(moduleModel),
slot_name: slotName,
})
}
const adapter = loadedLabwares.find(lw => lw.id === location.labwareId)

if (adapter == null) {
console.error('labware is located on an unknown adapter')
return ''
} else if (detailLevel === 'slot-only') {
return getLabwareDisplayLocation({
...params,
location: adapter.location,
}
// Adapter locations
else if (adapterName != null) {
if (moduleModel == null) {
return t('adapter_in_slot', {
adapter: adapterName,
slot: slotName,
})
} else if (detailLevel === 'full') {
const { allRunDefs } = params as LabwareDisplayLocationFull
const adapterDef = allRunDefs.find(
def => getLabwareDefURI(def) === adapter?.definitionUri
)
const adapterDisplayName =
adapterDef != null ? getLabwareDisplayName(adapterDef) : ''

if (adapter.location === 'offDeck') {
return t('off_deck')
} else if (
'slotName' in adapter.location ||
'addressableAreaName' in adapter.location
) {
const slotName =
'slotName' in adapter.location
? adapter.location.slotName
: adapter.location.addressableAreaName
return t('adapter_in_slot', {
adapter: adapterDisplayName,
slot: slotName,
})
} else if ('moduleId' in adapter.location) {
const moduleIdUnderAdapter = adapter.location.moduleId

if (!Array.isArray(loadedModules)) {
console.error(
'Cannot get display location from loaded modules object'
)
return ''
}

const moduleModel = loadedModules.find(
module => module.id === moduleIdUnderAdapter
)?.model
if (moduleModel == null) {
console.error('labware is located on an adapter on an unknown module')
return ''
}
const slotName = getModuleDisplayLocation(
loadedModules,
adapter.location.moduleId
)

return t('adapter_in_mod_in_slot', {
count: getOccludedSlotCountForModule(
getModuleType(moduleModel),
robotType
),
module: getModuleDisplayName(moduleModel),
adapter: adapterDisplayName,
slot: slotName,
})
} else {
console.error(
'Unhandled adapter location for determining display location.'
)
return ''
}
} else {
console.error('Unhandled detail level for determining display location.')
return ''
return t('adapter_in_mod_in_slot', {
count: getOccludedSlotCountForModule(
getModuleType(moduleModel),
params.robotType
),
module: getModuleDisplayName(moduleModel),
adapter: adapterName,
slot: slotName,
})
}
} else {
console.error('display location could not be established: ', location)
return ''
}
}
147 changes: 147 additions & 0 deletions app/src/local-resources/labware/utils/getLabwareLocation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { getLabwareDefURI, getLabwareDisplayName } from '@opentrons/shared-data'

import {
getModuleDisplayLocation,
getModuleModel,
} from '/app/local-resources/modules'

import type {
LabwareDefinition2,
LabwareLocation,
ModuleModel,
RobotType,
} from '@opentrons/shared-data'
import type { LoadedLabwares } from '/app/local-resources/labware'
import type { LoadedModules } from '/app/local-resources/modules'

export interface LocationResult {
slotName: string
moduleModel?: ModuleModel
adapterName?: string
}

interface BaseParams {
location: LabwareLocation | null
loadedModules: LoadedModules
loadedLabwares: LoadedLabwares
robotType: RobotType
}

export interface LocationSlotOnlyParams extends BaseParams {
detailLevel: 'slot-only'
}

export interface LocationFullParams extends BaseParams {
allRunDefs: LabwareDefinition2[]
detailLevel?: 'full'
}

export type GetLabwareLocationParams =
| LocationSlotOnlyParams
| LocationFullParams

// detailLevel returns additional information about the module and adapter in the same location, if applicable.
// if 'slot-only', returns the underlying slot location.
export function getLabwareLocation(
params: GetLabwareLocationParams
): LocationResult | null {
const {
loadedLabwares,
loadedModules,
location,
detailLevel = 'full',
} = params

if (location == null) {
return null
} else if (location === 'offDeck') {
return { slotName: 'offDeck' }
} else if ('slotName' in location) {
return { slotName: location.slotName }
} else if ('addressableAreaName' in location) {
return { slotName: location.addressableAreaName }
} else if ('moduleId' in location) {
const moduleModel = getModuleModel(loadedModules, location.moduleId)
if (moduleModel == null) {
console.error('labware is located on an unknown module model')
return null
}
const slotName = getModuleDisplayLocation(loadedModules, location.moduleId)

return {
slotName,
moduleModel,
}
} else if ('labwareId' in location) {
if (!Array.isArray(loadedLabwares)) {
console.error('Cannot get location from loaded labwares object')
return null
}

const adapter = loadedLabwares.find(lw => lw.id === location.labwareId)

if (adapter == null) {
console.error('labware is located on an unknown adapter')
return null
} else if (detailLevel === 'slot-only') {
return getLabwareLocation({
...params,
location: adapter.location,
})
} else if (detailLevel === 'full') {
const { allRunDefs } = params as LocationFullParams
const adapterDef = allRunDefs.find(
def => getLabwareDefURI(def) === adapter?.definitionUri
)
const adapterName =
adapterDef != null ? getLabwareDisplayName(adapterDef) : ''

if (adapter.location === 'offDeck') {
return { slotName: 'offDeck', adapterName }
} else if (
'slotName' in adapter.location ||
'addressableAreaName' in adapter.location
) {
const slotName =
'slotName' in adapter.location
? adapter.location.slotName
: adapter.location.addressableAreaName
return { slotName, adapterName }
} else if ('moduleId' in adapter.location) {
const moduleIdUnderAdapter = adapter.location.moduleId

if (!Array.isArray(loadedModules)) {
console.error('Cannot get location from loaded modules object')
return null
}

const moduleModel = loadedModules.find(
module => module.id === moduleIdUnderAdapter
)?.model

if (moduleModel == null) {
console.error('labware is located on an adapter on an unknown module')
return null
}

const slotName = getModuleDisplayLocation(
loadedModules,
adapter.location.moduleId
)

return {
slotName,
moduleModel,
adapterName,
}
} else {
return null
}
} else {
console.error('Unhandled detailLevel.')
return null
}
} else {
return null
}
}
1 change: 1 addition & 0 deletions app/src/local-resources/labware/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './getLabwareDefinitionsFromCommands'
export * from './getLabwareName'
export * from './getLoadedLabware'
export * from './getLabwareDisplayLocation'
export * from './getLabwareLocation'
Loading

0 comments on commit 5eab60c

Please sign in to comment.