-
Notifications
You must be signed in to change notification settings - Fork 179
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app): Enable labware views for LPC Redesign (#17384)
Closes EXEC-1102 This commit refactors the LPC data layer to support labware for the redesign. For the Redesign, the geometric identity (the URI) of each labware drives the flow. That is, a user selects a geometric identity, and is then presented with the option to LPC the "default offset" or one of the "applied location offsets" that occurs in the run. Alternatively the user may just view labware offset information here. After selecting a specific offset for which the user wants to perform LPC, a singular "do LPC for only this offset" flow occurs. Because the robot actually does care about a labware instance for loading/unloading labware, we do keep track of one and only one labwareId for each uri, even if there are multiple labware with the same uri in the run.
- Loading branch information
Showing
68 changed files
with
1,685 additions
and
1,334 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { useLPCLabwareInfo } from './useLPCLabwareInfo' |
93 changes: 93 additions & 0 deletions
93
.../organisms/LabwarePositionCheck/LPCFlows/hooks/useLPCLabwareInfo/getLPCLabwareInfoFrom.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import isEqual from 'lodash/isEqual' | ||
|
||
import { getLabwareDisplayName, getLabwareDefURI } from '@opentrons/shared-data' | ||
|
||
import type { LabwareDefinition2 } from '@opentrons/shared-data' | ||
import type { LPCLabwareInfo, OffsetDetails } from '/app/redux/protocol-runs' | ||
import type { LabwareLocationCombo } from '/app/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos' | ||
import type { UseLPCLabwareInfoProps } from '.' | ||
|
||
interface GetLPCLabwareInfoParams { | ||
lwURIs: string[] | ||
currentOffsets: UseLPCLabwareInfoProps['currentOffsets'] | ||
lwLocationCombos: LabwareLocationCombo[] | ||
labwareDefs: UseLPCLabwareInfoProps['labwareDefs'] | ||
} | ||
|
||
export function getLPCLabwareInfoFrom( | ||
params: GetLPCLabwareInfoParams | ||
): LPCLabwareInfo { | ||
return { selectedLabware: null, labware: getLabwareInfoRecords(params) } | ||
} | ||
|
||
function getLabwareInfoRecords( | ||
params: GetLPCLabwareInfoParams | ||
): LPCLabwareInfo['labware'] { | ||
const labwareDetails: LPCLabwareInfo['labware'] = {} | ||
|
||
params.lwURIs.forEach(uri => { | ||
if (!(uri in labwareDetails)) { | ||
labwareDetails[uri] = { | ||
id: getALabwareIdFromUri({ ...params, uri }), | ||
displayName: getDisplayNameFromUri({ ...params, uri }), | ||
offsetDetails: getOffsetDetailsForLabware({ ...params, uri }), | ||
} | ||
} | ||
}) | ||
|
||
return labwareDetails | ||
} | ||
|
||
type GetLPCLabwareInfoForURI = Omit<GetLPCLabwareInfoParams, 'lwURIs'> & { | ||
uri: string | ||
} | ||
|
||
function getALabwareIdFromUri({ | ||
uri, | ||
lwLocationCombos, | ||
}: GetLPCLabwareInfoForURI): string { | ||
return ( | ||
lwLocationCombos.find(combo => combo.definitionUri === uri)?.labwareId ?? '' | ||
) | ||
} | ||
|
||
function getDisplayNameFromUri({ | ||
uri, | ||
labwareDefs, | ||
}: GetLPCLabwareInfoForURI): string { | ||
const matchedDef = labwareDefs?.find( | ||
def => getLabwareDefURI(def) === uri | ||
) as LabwareDefinition2 | ||
|
||
return getLabwareDisplayName(matchedDef) | ||
} | ||
|
||
// NOTE: A lot of the logic here acts as temporary adapter that resolves the app's current way of getting offset data (scraping the run record) | ||
// and the end goal of treating labware as first class citizens. | ||
function getOffsetDetailsForLabware({ | ||
currentOffsets, | ||
lwLocationCombos, | ||
uri, | ||
}: GetLPCLabwareInfoForURI): OffsetDetails[] { | ||
return lwLocationCombos.flatMap(comboInfo => { | ||
const { definitionUri, location, ...restInfo } = comboInfo | ||
|
||
const existingOffset = | ||
currentOffsets.find( | ||
offset => | ||
uri === offset.definitionUri && | ||
isEqual(offset.location, comboInfo.location) | ||
) ?? null | ||
|
||
return { | ||
existingOffset: existingOffset ?? null, | ||
workingOffset: null, | ||
locationDetails: { | ||
...location, | ||
...restInfo, | ||
definitionUri, | ||
kind: 'location-specific', | ||
}, | ||
} | ||
}) | ||
} |
56 changes: 56 additions & 0 deletions
56
...abwarePositionCheck/LPCFlows/hooks/useLPCLabwareInfo/getUniqueLabwareLocationComboInfo.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { isEqual } from 'lodash' | ||
|
||
import { getLabwareDefURI } from '@opentrons/shared-data' | ||
|
||
import { getLabwareLocationCombos } from '/app/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos' | ||
|
||
import type { | ||
CompletedProtocolAnalysis, | ||
LabwareDefinition2, | ||
} from '@opentrons/shared-data' | ||
import type { LabwareLocationCombo } from '/app/organisms/LegacyApplyHistoricOffsets/hooks/getLabwareLocationCombos' | ||
|
||
export interface GetUniqueLocationComboInfoParams { | ||
protocolData: CompletedProtocolAnalysis | null | ||
labwareDefs: LabwareDefinition2[] | null | ||
} | ||
|
||
export function getUniqueLabwareLocationComboInfo({ | ||
labwareDefs, | ||
protocolData, | ||
}: GetUniqueLocationComboInfoParams): LabwareLocationCombo[] { | ||
if (protocolData == null || labwareDefs == null) { | ||
return [] | ||
} | ||
|
||
const { commands, labware, modules = [] } = protocolData | ||
const labwareLocationCombos = getLabwareLocationCombos( | ||
commands, | ||
labware, | ||
modules | ||
) | ||
|
||
// Filter out duplicate labware and labware that is not LPC-able. | ||
return labwareLocationCombos.reduce<LabwareLocationCombo[]>( | ||
(acc, labwareLocationCombo) => { | ||
const labwareDef = labwareDefs.find( | ||
def => getLabwareDefURI(def) === labwareLocationCombo.definitionUri | ||
) | ||
if ( | ||
(labwareDef?.allowedRoles ?? []).includes('adapter') || | ||
(labwareDef?.allowedRoles ?? []).includes('lid') | ||
) { | ||
return acc | ||
} | ||
// remove duplicate definitionUri in same location | ||
const comboAlreadyExists = acc.some( | ||
accLocationCombo => | ||
labwareLocationCombo.definitionUri === | ||
accLocationCombo.definitionUri && | ||
isEqual(labwareLocationCombo.location, accLocationCombo.location) | ||
) | ||
return comboAlreadyExists ? acc : [...acc, labwareLocationCombo] | ||
}, | ||
[] | ||
) | ||
} |
50 changes: 50 additions & 0 deletions
50
app/src/organisms/LabwarePositionCheck/LPCFlows/hooks/useLPCLabwareInfo/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { useMemo } from 'react' | ||
|
||
import { getUniqueLabwareLocationComboInfo } from './getUniqueLabwareLocationComboInfo' | ||
import { getLPCLabwareInfoFrom } from './getLPCLabwareInfoFrom' | ||
|
||
import type { LabwareOffset } from '@opentrons/api-client' | ||
import type { LPCLabwareInfo } from '/app/redux/protocol-runs' | ||
import type { GetUniqueLocationComboInfoParams } from './getUniqueLabwareLocationComboInfo' | ||
|
||
export type UseLPCLabwareInfoProps = GetUniqueLocationComboInfoParams & { | ||
currentOffsets: LabwareOffset[] | ||
} | ||
|
||
// TODO(jh, 01-22-25): This interface will change substantially the switch to /labwareOffsets. | ||
|
||
// Structures LPC-able labware info for injection into LPC flows. | ||
export function useLPCLabwareInfo({ | ||
currentOffsets, | ||
labwareDefs, | ||
protocolData, | ||
}: UseLPCLabwareInfoProps): LPCLabwareInfo { | ||
// Analysis-derived data is the source of truth, because we must account for labware that has offsets AND account for labware | ||
// that does not have offsets. This will change with the LPC HTTP API refactors. | ||
const lwURIs = getLabwareURIsFromAnalysis(protocolData) | ||
const lwLocationCombos = useMemo( | ||
() => | ||
getUniqueLabwareLocationComboInfo({ | ||
labwareDefs, | ||
protocolData, | ||
}), | ||
[labwareDefs != null, protocolData != null] | ||
) | ||
|
||
return useMemo( | ||
() => | ||
getLPCLabwareInfoFrom({ | ||
lwURIs, | ||
currentOffsets, | ||
lwLocationCombos, | ||
labwareDefs, | ||
}), | ||
[lwURIs.length, currentOffsets.length, lwLocationCombos.length] | ||
) | ||
} | ||
|
||
function getLabwareURIsFromAnalysis( | ||
analysis: UseLPCLabwareInfoProps['protocolData'] | ||
): string[] { | ||
return analysis?.labware.map(lwInfo => lwInfo.definitionUri) ?? [] | ||
} |
Oops, something went wrong.