From b57396061b0723137ab225db5ba33ad69a669011 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 7 Nov 2023 14:30:06 -0500 Subject: [PATCH 01/65] debug --- .../atomic/moveToAddressableArea.ts | 2 + .../src/commandCreators/atomic/replaceTip.ts | 44 ++++++++++++++----- .../src/utils/wasteChuteCommandsUtil.ts | 2 + 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts b/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts index f4eb1586005..0cd9c2b1aaf 100644 --- a/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts +++ b/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts @@ -12,6 +12,8 @@ export const moveToAddressableArea: CommandCreator = ) => { const { pipetteId, addressableAreaName } = args + console.log('MOVE TO ADDRESSABLE') + const commands = [ { commandType: 'moveToAddressableArea' as const, diff --git a/step-generation/src/commandCreators/atomic/replaceTip.ts b/step-generation/src/commandCreators/atomic/replaceTip.ts index cf59d1341d2..655b28e8a52 100644 --- a/step-generation/src/commandCreators/atomic/replaceTip.ts +++ b/step-generation/src/commandCreators/atomic/replaceTip.ts @@ -10,6 +10,7 @@ import { pipetteAdjacentHeaterShakerWhileShaking, getIsHeaterShakerEastWestWithLatchOpen, getIsHeaterShakerEastWestMultiChannelPipette, + wasteChuteCommandsUtil, } from '../../utils' import type { CommandCreatorError, @@ -98,6 +99,9 @@ export const replaceTip: CommandCreator = ( const labwareDef = invariantContext.labwareEntities[nextTiprack.tiprackId]?.def + const isWasteChute = + invariantContext.additionalEquipmentEntities[dropTipLocation] != null + console.log('🚀 ~ file: replaceTip.ts:103 ~ isWasteChute:', isWasteChute) if (!labwareDef) { return { errors: [ @@ -158,17 +162,35 @@ export const replaceTip: CommandCreator = ( } } - const commandCreators: CurriedCommandCreator[] = [ - curryCommandCreator(dropTip, { - pipette, - dropTipLocation, - }), - curryCommandCreator(_pickUpTip, { - pipette, - tiprack: nextTiprack.tiprackId, - well: nextTiprack.well, - }), - ] + const addressableAreaName = + pipetteSpec.channels === 96 + ? '96ChannelWasteChute' + : '1and8ChannelWasteChute' + + const commandCreators: CurriedCommandCreator[] = isWasteChute + ? [ + curryCommandCreator(wasteChuteCommandsUtil, { + type: 'dropTip', + pipetteId: pipette, + addressableAreaName, + }), + curryCommandCreator(_pickUpTip, { + pipette, + tiprack: nextTiprack.tiprackId, + well: nextTiprack.well, + }), + ] + : [ + curryCommandCreator(dropTip, { + pipette, + dropTipLocation, + }), + curryCommandCreator(_pickUpTip, { + pipette, + tiprack: nextTiprack.tiprackId, + well: nextTiprack.well, + }), + ] return reduceCommandCreators( commandCreators, diff --git a/step-generation/src/utils/wasteChuteCommandsUtil.ts b/step-generation/src/utils/wasteChuteCommandsUtil.ts index 29df4f550ca..4a5950b746d 100644 --- a/step-generation/src/utils/wasteChuteCommandsUtil.ts +++ b/step-generation/src/utils/wasteChuteCommandsUtil.ts @@ -108,6 +108,8 @@ export const wasteChuteCommandsUtil: CommandCreator = ( } } + console.log('🚀 ~ file: wasteChuteCommandsUtil.ts:64 ~ commands:', commands) + if (errors.length > 0) return { errors, From b9ef036337585c0cea9634ab341d2c08d4ac8722 Mon Sep 17 00:00:00 2001 From: Jethary Date: Tue, 7 Nov 2023 15:18:54 -0500 Subject: [PATCH 02/65] add check for tip attached in moveToAddressableArea --- .../src/utils/wasteChuteCommandsUtil.ts | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/step-generation/src/utils/wasteChuteCommandsUtil.ts b/step-generation/src/utils/wasteChuteCommandsUtil.ts index 4a5950b746d..99b4bd2090b 100644 --- a/step-generation/src/utils/wasteChuteCommandsUtil.ts +++ b/step-generation/src/utils/wasteChuteCommandsUtil.ts @@ -62,15 +62,18 @@ export const wasteChuteCommandsUtil: CommandCreator = ( let commands: CurriedCommandCreator[] = [] switch (type) { case 'dropTip': { - commands = [ - curryCommandCreator(moveToAddressableArea, { - pipetteId, - addressableAreaName, - }), - curryCommandCreator(dropTipInPlace, { - pipetteId, - }), - ] + commands = + prevRobotState.tipState.pipettes[pipetteId] != null + ? [ + curryCommandCreator(moveToAddressableArea, { + pipetteId, + addressableAreaName, + }), + curryCommandCreator(dropTipInPlace, { + pipetteId, + }), + ] + : [] break } case 'dispense': { From 736ca516c11b6dee598b671a74ff0decad81aae3 Mon Sep 17 00:00:00 2001 From: Jethary Date: Tue, 7 Nov 2023 15:30:53 -0500 Subject: [PATCH 03/65] fix ternary for no tip attached --- .../src/utils/wasteChuteCommandsUtil.ts | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/step-generation/src/utils/wasteChuteCommandsUtil.ts b/step-generation/src/utils/wasteChuteCommandsUtil.ts index 99b4bd2090b..0b1db88420f 100644 --- a/step-generation/src/utils/wasteChuteCommandsUtil.ts +++ b/step-generation/src/utils/wasteChuteCommandsUtil.ts @@ -62,18 +62,18 @@ export const wasteChuteCommandsUtil: CommandCreator = ( let commands: CurriedCommandCreator[] = [] switch (type) { case 'dropTip': { - commands = - prevRobotState.tipState.pipettes[pipetteId] != null - ? [ - curryCommandCreator(moveToAddressableArea, { - pipetteId, - addressableAreaName, - }), - curryCommandCreator(dropTipInPlace, { - pipetteId, - }), - ] - : [] + commands = !prevRobotState.tipState.pipettes[pipetteId] + ? [] + : [ + curryCommandCreator(moveToAddressableArea, { + pipetteId, + addressableAreaName, + }), + curryCommandCreator(dropTipInPlace, { + pipetteId, + }), + ] + break } case 'dispense': { From b0eb44221b1a72e86e93f01b8bb6676ada22cc97 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 7 Nov 2023 16:20:28 -0500 Subject: [PATCH 04/65] feat(protocol-designer): wire up drop drop tip in waste chute commands If we select the waste chute as our drop tip location, we need to generate different commands from dropping tips in other locations. For the waste chute, we generate moveToAddressableArea followed by dropTipInPlace commands. --- .../generateRobotStateTimeline.ts | 64 ++++++++++++++----- .../atomic/moveToAddressableArea.ts | 2 - .../src/commandCreators/atomic/replaceTip.ts | 2 +- .../src/utils/wasteChuteCommandsUtil.ts | 2 - 4 files changed, 50 insertions(+), 20 deletions(-) diff --git a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts index 72ff5301b8e..b2a2cbb28b9 100644 --- a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts +++ b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts @@ -2,6 +2,8 @@ import takeWhile from 'lodash/takeWhile' import * as StepGeneration from '@opentrons/step-generation' import { commandCreatorFromStepArgs } from '../file-data/selectors/commands' import type { StepArgsAndErrorsById } from '../steplist/types' +import { wasteChuteCommandsUtil } from '@opentrons/step-generation' +import { truncateSync } from 'fs-extra' export interface GenerateRobotStateTimelineArgs { allStepArgsAndErrors: StepArgsAndErrorsById orderedStepIds: string[] @@ -65,22 +67,54 @@ export const generateRobotStateTimeline = ( // @ts-expect-error(sa, 2021-6-20): not a valid type narrow, use in operator nextStepArgsForPipette.changeTip === 'never' + const isWasteChute = true + + const pipetteSpec = invariantContext.pipetteEntities[pipetteId]?.spec + + const addressableAreaName = + pipetteSpec.channels === 96 + ? '96ChannelWasteChute' + : '1and8ChannelWasteChute' + if (!willReuseTip) { - return [ - ...acc, - (_invariantContext, _prevRobotState) => - StepGeneration.reduceCommandCreators( - [ - curriedCommandCreator, - StepGeneration.curryCommandCreator(StepGeneration.dropTip, { - pipette: pipetteId, - dropTipLocation, - }), - ], - _invariantContext, - _prevRobotState - ), - ] + return isWasteChute + ? [ + ...acc, + (_invariantContext, _prevRobotState) => + StepGeneration.reduceCommandCreators( + [ + curriedCommandCreator, + StepGeneration.curryCommandCreator( + wasteChuteCommandsUtil, + { + type: 'dropTip', + pipetteId: pipetteId, + addressableAreaName, + } + ), + ], + _invariantContext, + _prevRobotState + ), + ] + : [ + ...acc, + (_invariantContext, _prevRobotState) => + StepGeneration.reduceCommandCreators( + [ + curriedCommandCreator, + StepGeneration.curryCommandCreator( + StepGeneration.dropTip, + { + pipette: pipetteId, + dropTipLocation, + } + ), + ], + _invariantContext, + _prevRobotState + ), + ] } } diff --git a/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts b/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts index 0cd9c2b1aaf..f4eb1586005 100644 --- a/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts +++ b/step-generation/src/commandCreators/atomic/moveToAddressableArea.ts @@ -12,8 +12,6 @@ export const moveToAddressableArea: CommandCreator = ) => { const { pipetteId, addressableAreaName } = args - console.log('MOVE TO ADDRESSABLE') - const commands = [ { commandType: 'moveToAddressableArea' as const, diff --git a/step-generation/src/commandCreators/atomic/replaceTip.ts b/step-generation/src/commandCreators/atomic/replaceTip.ts index 655b28e8a52..d469efdfb18 100644 --- a/step-generation/src/commandCreators/atomic/replaceTip.ts +++ b/step-generation/src/commandCreators/atomic/replaceTip.ts @@ -101,7 +101,7 @@ export const replaceTip: CommandCreator = ( const isWasteChute = invariantContext.additionalEquipmentEntities[dropTipLocation] != null - console.log('🚀 ~ file: replaceTip.ts:103 ~ isWasteChute:', isWasteChute) + if (!labwareDef) { return { errors: [ diff --git a/step-generation/src/utils/wasteChuteCommandsUtil.ts b/step-generation/src/utils/wasteChuteCommandsUtil.ts index 0b1db88420f..1473026450d 100644 --- a/step-generation/src/utils/wasteChuteCommandsUtil.ts +++ b/step-generation/src/utils/wasteChuteCommandsUtil.ts @@ -111,8 +111,6 @@ export const wasteChuteCommandsUtil: CommandCreator = ( } } - console.log('🚀 ~ file: wasteChuteCommandsUtil.ts:64 ~ commands:', commands) - if (errors.length > 0) return { errors, From fc2bcf702138d0d175711dee953f01de9b88751c Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 7 Nov 2023 16:30:24 -0500 Subject: [PATCH 05/65] check for wasteChute --- .../src/timelineMiddleware/generateRobotStateTimeline.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts index b2a2cbb28b9..7419d0ce4e4 100644 --- a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts +++ b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts @@ -67,7 +67,8 @@ export const generateRobotStateTimeline = ( // @ts-expect-error(sa, 2021-6-20): not a valid type narrow, use in operator nextStepArgsForPipette.changeTip === 'never' - const isWasteChute = true + const isWasteChute = + invariantContext.additionalEquipmentEntities[dropTipLocation] != null const pipetteSpec = invariantContext.pipetteEntities[pipetteId]?.spec From 77b8e966a36fb2c0d30ce72465a48ec957884a8f Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Wed, 8 Nov 2023 15:45:30 -0500 Subject: [PATCH 06/65] update tip state after dropTipInPlace, add test for replaceTip in wasteChute --- .../src/__tests__/replaceTip.test.ts | 41 +++++++++++++++++++ .../src/fixtures/commandFixtures.ts | 22 ++++++++++ .../inPlaceCommandUpdates.ts | 4 +- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/step-generation/src/__tests__/replaceTip.test.ts b/step-generation/src/__tests__/replaceTip.test.ts index c97bc008eb8..27af7db7c96 100644 --- a/step-generation/src/__tests__/replaceTip.test.ts +++ b/step-generation/src/__tests__/replaceTip.test.ts @@ -7,6 +7,8 @@ import { getSuccessResult, pickUpTipHelper, dropTipHelper, + dropTipInPlaceHelper, + moveToAddressableAreaHelper, DEFAULT_PIPETTE, } from '../fixtures' import { FIXED_TRASH_ID } from '..' @@ -17,6 +19,7 @@ const tiprack1Id = 'tiprack1Id' const tiprack2Id = 'tiprack2Id' const p300SingleId = DEFAULT_PIPETTE const p300MultiId = 'p300MultiId' +const wasteChuteId = 'wasteChuteId' describe('replaceTip', () => { let invariantContext: InvariantContext let initialRobotState: RobotState @@ -132,6 +135,44 @@ describe('replaceTip', () => { }), ]) }) + it('Single-channel: dropping tips in waste chute', () => { + invariantContext = { + ...invariantContext, + additionalEquipmentEntities: { + wasteChuteId: { + name: 'wasteChute', + id: wasteChuteId, + location: 'D3', + }, + }, + } + const initialTestRobotState = merge({}, initialRobotState, { + tipState: { + tipracks: { + [tiprack1Id]: { + A1: false, + }, + }, + pipettes: { + p300SingleId: true, + }, + }, + }) + const result = replaceTip( + { + pipette: p300SingleId, + dropTipLocation: 'wasteChuteId', + }, + invariantContext, + initialTestRobotState + ) + const res = getSuccessResult(result) + expect(res.commands).toEqual([ + moveToAddressableAreaHelper(), + dropTipInPlaceHelper(), + pickUpTipHelper('B1'), + ]) + }) }) describe('replaceTip: multi-channel', () => { it('multi-channel, all tipracks have tips', () => { diff --git a/step-generation/src/fixtures/commandFixtures.ts b/step-generation/src/fixtures/commandFixtures.ts index b3e881fa5e9..77029e9264c 100644 --- a/step-generation/src/fixtures/commandFixtures.ts +++ b/step-generation/src/fixtures/commandFixtures.ts @@ -310,3 +310,25 @@ export const pickUpTipHelper = ( wellName: typeof tip === 'string' ? tip : tiprackWellNamesFlat[tip], }, }) +export const dropTipInPlaceHelper = (params?: { + pipetteId?: string +}): CreateCommand => ({ + commandType: 'dropTipInPlace', + key: expect.any(String), + params: { + pipetteId: DEFAULT_PIPETTE, + ...params, + }, +}) +export const moveToAddressableAreaHelper = (params?: { + pipetteId?: string + addressableAreaName: string +}): CreateCommand => ({ + commandType: 'moveToAddressableArea', + key: expect.any(String), + params: { + pipetteId: DEFAULT_PIPETTE, + addressableAreaName: '1and8ChannelWasteChute', + ...params, + }, +}) diff --git a/step-generation/src/getNextRobotStateAndWarnings/inPlaceCommandUpdates.ts b/step-generation/src/getNextRobotStateAndWarnings/inPlaceCommandUpdates.ts index 19a20c04db3..19028db007f 100644 --- a/step-generation/src/getNextRobotStateAndWarnings/inPlaceCommandUpdates.ts +++ b/step-generation/src/getNextRobotStateAndWarnings/inPlaceCommandUpdates.ts @@ -24,5 +24,7 @@ export const forDropTipInPlace = ( invariantContext: InvariantContext, robotStateAndWarnings: RobotStateAndWarnings ): void => { - // TODO(jr, 11/6/23): update state + const { pipetteId } = params + const { robotState } = robotStateAndWarnings + robotState.tipState.pipettes[pipetteId] = false } From 92c77602519ccd5f3b7d4d813cd05a4db73d6f8a Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Wed, 8 Nov 2023 15:58:03 -0500 Subject: [PATCH 07/65] lint --- .../src/timelineMiddleware/generateRobotStateTimeline.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts index 7419d0ce4e4..00f41a879c5 100644 --- a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts +++ b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts @@ -3,7 +3,7 @@ import * as StepGeneration from '@opentrons/step-generation' import { commandCreatorFromStepArgs } from '../file-data/selectors/commands' import type { StepArgsAndErrorsById } from '../steplist/types' import { wasteChuteCommandsUtil } from '@opentrons/step-generation' -import { truncateSync } from 'fs-extra' + export interface GenerateRobotStateTimelineArgs { allStepArgsAndErrors: StepArgsAndErrorsById orderedStepIds: string[] From 8d65cd79560a264f52480d49ba18b5b5722f8f88 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Wed, 8 Nov 2023 17:58:12 -0500 Subject: [PATCH 08/65] feat(app): add command text for new commands adds command text with requisite params for dropTipInPlace, dispenseInPlace, blowOutInPlace, and moveToAddressableArea --- .../en/protocol_command_text.json | 4 ++ .../CommandText/PipettingCommandText.tsx | 44 +++++++++---------- app/src/organisms/CommandText/index.tsx | 43 +++++++++++++++++- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/app/src/assets/localization/en/protocol_command_text.json b/app/src/assets/localization/en/protocol_command_text.json index 8d84b9e341f..167b64c08ed 100644 --- a/app/src/assets/localization/en/protocol_command_text.json +++ b/app/src/assets/localization/en/protocol_command_text.json @@ -3,6 +3,7 @@ "adapter_in_slot": "{{adapter}} in {{slot}}", "aspirate": "Aspirating {{volume}} µL from well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", "blowout": "Blowing out at well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "blowout_in_place": "Blowing out in place at {{flow_rate}} µL/sec", "closing_tc_lid": "Closing Thermocycler lid", "comment": "Comment", "configure_for_volume": "Configure {{pipette}} to aspirate {{volume}} µL", @@ -16,7 +17,9 @@ "disengaging_magnetic_module": "Disengaging Magnetic Module", "dispense_push_out": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec and pushing out {{push_out_volume}} µL", "dispense": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "dispense_in_place": "Dispensing {{volume}} µL in place at {{flow_rate}} µL/sec", "drop_tip": "Dropping tip in {{well_name}} of {{labware}}", + "drop_tip_in_place": "Dropping tip in place", "engaging_magnetic_module": "Engaging Magnetic Module", "fixed_trash": "Fixed Trash", "home_gantry": "Homing all gantry, pipette, and plunger axes", @@ -31,6 +34,7 @@ "move_to_coordinates": "Moving to (X: {{x}}, Y: {{y}}, Z: {{z}})", "move_to_slot": "Moving to Slot {{slot_name}}", "move_to_well": "Moving to well {{well_name}} of {{labware}} in {{labware_location}}", + "move_to_addressable_area": "Moving to {{addressable_area}} at {{speed}} mm/s at {{height}} mm high", "notes": "notes", "off_deck": "off deck", "offdeck": "offdeck", diff --git a/app/src/organisms/CommandText/PipettingCommandText.tsx b/app/src/organisms/CommandText/PipettingCommandText.tsx index 8aff25b4da3..fba1d96d67d 100644 --- a/app/src/organisms/CommandText/PipettingCommandText.tsx +++ b/app/src/organisms/CommandText/PipettingCommandText.tsx @@ -1,15 +1,10 @@ import { useTranslation } from 'react-i18next' import { CompletedProtocolAnalysis, - AspirateRunTimeCommand, - DispenseRunTimeCommand, - BlowoutRunTimeCommand, - MoveToWellRunTimeCommand, - DropTipRunTimeCommand, - PickUpTipRunTimeCommand, getLabwareDefURI, RobotType, } from '@opentrons/shared-data' +import type { PipettingRunTimeCommand } from '@opentrons/shared-data' import { getLabwareDefinitionsFromCommands } from '../LabwarePositionCheck/utils/labware' import { getLoadedLabware } from './utils/accessors' import { @@ -18,15 +13,8 @@ import { getFinalLabwareLocation, } from './utils' -type PipettingRunTimeCommmand = - | AspirateRunTimeCommand - | DispenseRunTimeCommand - | BlowoutRunTimeCommand - | MoveToWellRunTimeCommand - | DropTipRunTimeCommand - | PickUpTipRunTimeCommand interface PipettingCommandTextProps { - command: PipettingRunTimeCommmand + command: PipettingRunTimeCommand robotSideAnalysis: CompletedProtocolAnalysis robotType: RobotType } @@ -38,7 +26,15 @@ export const PipettingCommandText = ({ }: PipettingCommandTextProps): JSX.Element | null => { const { t } = useTranslation('protocol_command_text') - const { labwareId, wellName } = command.params + let labwareId = '' + let wellName = '' + if ('labwareId' in command.params) { + labwareId = command.params.labwareId + } + if ('wellName' in command.params) { + wellName = command.params.wellName + } + const allPreviousCommands = robotSideAnalysis.commands.slice( 0, robotSideAnalysis.commands.findIndex(c => c.id === command.id) @@ -95,13 +91,6 @@ export const PipettingCommandText = ({ flow_rate: flowRate, }) } - case 'moveToWell': { - return t('move_to_well', { - well_name: wellName, - labware: getLabwareName(robotSideAnalysis, labwareId), - labware_location: displayLocation, - }) - } case 'dropTip': { const loadedLabware = getLoadedLabware(robotSideAnalysis, labwareId) const labwareDefinitions = getLabwareDefinitionsFromCommands( @@ -128,6 +117,17 @@ export const PipettingCommandText = ({ labware_location: displayLocation, }) } + case 'dropTipInPlace': { + return t('drop_tip_in_place') + } + case 'dispenseInPlace': { + const { volume, flowRate } = command.params + return t('dispense_in_place', { volume: volume, flow_rate: flowRate }) + } + case 'blowOutInPlace': { + const { flowRate } = command.params + return t('blowout_in_place', { flow_rate: flowRate }) + } default: { console.warn( 'PipettingCommandText encountered a command with an unrecognized commandType: ', diff --git a/app/src/organisms/CommandText/index.tsx b/app/src/organisms/CommandText/index.tsx index 67e76526ab1..a1aadd54bc2 100644 --- a/app/src/organisms/CommandText/index.tsx +++ b/app/src/organisms/CommandText/index.tsx @@ -3,6 +3,11 @@ import { useTranslation } from 'react-i18next' import { Flex, DIRECTION_COLUMN, SPACING } from '@opentrons/components' import { getPipetteNameSpecs, RunTimeCommand } from '@opentrons/shared-data' +import { + getLabwareName, + getLabwareDisplayLocation, + getFinalLabwareLocation, +} from './utils' import { StyledText } from '../../atoms/text' import { LoadCommandText } from './LoadCommandText' import { PipettingCommandText } from './PipettingCommandText' @@ -51,7 +56,6 @@ export function CommandText(props: Props): JSX.Element | null { case 'aspirate': case 'dispense': case 'blowout': - case 'moveToWell': case 'dropTip': case 'pickUpTip': { return ( @@ -138,6 +142,31 @@ export function CommandText(props: Props): JSX.Element | null { ) } + case 'moveToWell': { + const { wellName, labwareId } = command.params + const allPreviousCommands = robotSideAnalysis.commands.slice( + 0, + robotSideAnalysis.commands.findIndex(c => c.id === command.id) + ) + const labwareLocation = getFinalLabwareLocation( + labwareId, + allPreviousCommands + ) + const displayLocation = + labwareLocation != null + ? getLabwareDisplayLocation( + robotSideAnalysis, + labwareLocation, + t, + robotType + ) + : '' + return t('move_to_well', { + well_name: wellName, + labware: getLabwareName(robotSideAnalysis, labwareId), + labware_location: displayLocation, + }) + } case 'moveLabware': { return ( @@ -182,6 +211,18 @@ export function CommandText(props: Props): JSX.Element | null { ) } + case 'moveToAddressableArea': { + const { addressableAreaName, speed, minimumZHeight } = command.params + return ( + + {t('move_to_addressable_area', { + addressable_area: addressableAreaName, + speed: speed, + height: minimumZHeight, + })} + + ) + } case 'touchTip': case 'home': case 'savePosition': From 86cc37415c1dd8b9a6b4d83df22146ba89b3f77c Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 09:48:52 -0500 Subject: [PATCH 09/65] initial tests --- .../CommandText/PipettingCommandText.tsx | 12 +++--------- .../__tests__/CommandText.test.tsx | 19 +++++++++++++++++++ app/src/organisms/CommandText/index.tsx | 1 + 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/app/src/organisms/CommandText/PipettingCommandText.tsx b/app/src/organisms/CommandText/PipettingCommandText.tsx index fba1d96d67d..3ace803dfac 100644 --- a/app/src/organisms/CommandText/PipettingCommandText.tsx +++ b/app/src/organisms/CommandText/PipettingCommandText.tsx @@ -26,14 +26,8 @@ export const PipettingCommandText = ({ }: PipettingCommandTextProps): JSX.Element | null => { const { t } = useTranslation('protocol_command_text') - let labwareId = '' - let wellName = '' - if ('labwareId' in command.params) { - labwareId = command.params.labwareId - } - if ('wellName' in command.params) { - wellName = command.params.wellName - } + const labwareId = command.params.labwareId ?? null + const wellName = command.params.wellId ?? null const allPreviousCommands = robotSideAnalysis.commands.slice( 0, @@ -57,7 +51,7 @@ export const PipettingCommandText = ({ const { volume, flowRate } = command.params return t('aspirate', { well_name: wellName, - labware: getLabwareName(robotSideAnalysis, labwareId), + labware: getLabwareName(robotSideAnalysis, labwareId ?? ''), labware_location: displayLocation, volume: volume, flow_rate: flowRate, diff --git a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx index 28ef08f940f..11b7a161362 100644 --- a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx +++ b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx @@ -1,6 +1,7 @@ import * as React from 'react' import { renderWithProviders } from '@opentrons/components' import { + DropTipInPlaceRunTimeCommand, FLEX_ROBOT_TYPE, PrepareToAspirateRunTimeCommand, } from '@opentrons/shared-data' @@ -204,6 +205,24 @@ describe('CommandText', () => { )[0] getByText('Returning tip to A1 of Opentrons 96 Tip Rack 300 µL in Slot 9') }) + it('renders correct text for dropTipInPlace', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Dropping tip in place') + }) it('renders correct text for pickUpTip', () => { const command = mockRobotSideAnalysis.commands.find( c => c.commandType === 'pickUpTip' diff --git a/app/src/organisms/CommandText/index.tsx b/app/src/organisms/CommandText/index.tsx index a1aadd54bc2..e66584bc3ce 100644 --- a/app/src/organisms/CommandText/index.tsx +++ b/app/src/organisms/CommandText/index.tsx @@ -57,6 +57,7 @@ export function CommandText(props: Props): JSX.Element | null { case 'dispense': case 'blowout': case 'dropTip': + case 'dropTipInPlace': case 'pickUpTip': { return ( From 7606b196a103ff3b7336162d92c86d13a5abb396 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 10:17:04 -0500 Subject: [PATCH 10/65] add tests for all inPlace + moveToAddressableArea commands --- .../CommandText/PipettingCommandText.tsx | 10 ++- .../__tests__/CommandText.test.tsx | 63 +++++++++++++++++++ app/src/organisms/CommandText/index.tsx | 2 + 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/app/src/organisms/CommandText/PipettingCommandText.tsx b/app/src/organisms/CommandText/PipettingCommandText.tsx index 3ace803dfac..9abc69df107 100644 --- a/app/src/organisms/CommandText/PipettingCommandText.tsx +++ b/app/src/organisms/CommandText/PipettingCommandText.tsx @@ -26,8 +26,14 @@ export const PipettingCommandText = ({ }: PipettingCommandTextProps): JSX.Element | null => { const { t } = useTranslation('protocol_command_text') - const labwareId = command.params.labwareId ?? null - const wellName = command.params.wellId ?? null + let labwareId = '' + let wellName = '' + if ('labwareId' in command.params) { + labwareId = command.params.labwareId + } + if ('wellName' in command.params) { + wellName = command.params.wellName + } const allPreviousCommands = robotSideAnalysis.commands.slice( 0, diff --git a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx index 11b7a161362..242c6939eb4 100644 --- a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx +++ b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx @@ -1,8 +1,11 @@ import * as React from 'react' import { renderWithProviders } from '@opentrons/components' import { + BlowoutInPlaceRunTimeCommand, + DispenseInPlaceRunTimeCommand, DropTipInPlaceRunTimeCommand, FLEX_ROBOT_TYPE, + MoveToAddressableAreaRunTimeCommand, PrepareToAspirateRunTimeCommand, } from '@opentrons/shared-data' import { i18n } from '../../../i18n' @@ -86,6 +89,26 @@ describe('CommandText', () => { ) } }) + it('renders correct text for dispenseInPlace', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Dispensing 50 µL in place at 300 µL/sec') + }) it('renders correct text for blowout', () => { const dispenseCommand = mockRobotSideAnalysis.commands.find( c => c.commandType === 'dispense' @@ -109,6 +132,25 @@ describe('CommandText', () => { ) } }) + it('renders correct text for blowOutInPlace', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Blowing out in place at 300 µL/sec') + }) it('renders correct text for moveToWell', () => { const dispenseCommand = mockRobotSideAnalysis.commands.find( c => c.commandType === 'aspirate' @@ -130,6 +172,27 @@ describe('CommandText', () => { getByText('Moving to well A1 of NEST 1 Well Reservoir 195 mL in Slot 5') } }) + it('renders correct text for moveToAddressableArea', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Moving to D3 at 200 mm/s at 100 mm high') + }) it('renders correct text for configureForVolume', () => { const command = { commandType: 'configureForVolume', diff --git a/app/src/organisms/CommandText/index.tsx b/app/src/organisms/CommandText/index.tsx index e66584bc3ce..00e9bca5808 100644 --- a/app/src/organisms/CommandText/index.tsx +++ b/app/src/organisms/CommandText/index.tsx @@ -55,7 +55,9 @@ export function CommandText(props: Props): JSX.Element | null { switch (command.commandType) { case 'aspirate': case 'dispense': + case 'dispenseInPlace': case 'blowout': + case 'blowOutInPlace': case 'dropTip': case 'dropTipInPlace': case 'pickUpTip': { From 4e8de519e046abbe2d7843319d479e34dd76de3d Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 11:25:09 -0500 Subject: [PATCH 11/65] factor PipettingRunTimeCommand type into AtLocation and InPlace --- shared-data/command/types/pipetting.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/shared-data/command/types/pipetting.ts b/shared-data/command/types/pipetting.ts index fe54ed1cf81..192c4d71345 100644 --- a/shared-data/command/types/pipetting.ts +++ b/shared-data/command/types/pipetting.ts @@ -1,17 +1,23 @@ import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' export type PipettingRunTimeCommand = + | PipettingAtLocationRunTimeCommand + | PipettingInPlaceRunTimeCommand + +export type PipettingAtLocationRunTimeCommand = | AspirateRunTimeCommand - | BlowoutInPlaceRunTimeCommand | BlowoutRunTimeCommand - | ConfigureForVolumeRunTimeCommand - | DispenseInPlaceRunTimeCommand | DispenseRunTimeCommand - | DropTipInPlaceRunTimeCommand | DropTipRunTimeCommand | PickUpTipRunTimeCommand - | PrepareToAspirateRunTimeCommand | TouchTipRunTimeCommand +export type PipettingInPlaceRunTimeCommand = + | BlowoutInPlaceRunTimeCommand + | ConfigureForVolumeRunTimeCommand + | DispenseInPlaceRunTimeCommand + | DropTipInPlaceRunTimeCommand + | PrepareToAspirateRunTimeCommand + export type PipettingCreateCommand = | AspirateCreateCommand | BlowoutCreateCommand From a21e3401ae1c7e0b47e10dfadc72a220c8e2b3a6 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 12:22:21 -0500 Subject: [PATCH 12/65] reset unintended files out of scope of this PR --- .../en/protocol_command_text.json | 4 - .../CommandText/PipettingCommandText.tsx | 46 +++++------ .../__tests__/CommandText.test.tsx | 82 ------------------- app/src/organisms/CommandText/index.tsx | 46 +---------- shared-data/command/types/pipetting.ts | 44 ++-------- 5 files changed, 33 insertions(+), 189 deletions(-) diff --git a/app/src/assets/localization/en/protocol_command_text.json b/app/src/assets/localization/en/protocol_command_text.json index 167b64c08ed..8d84b9e341f 100644 --- a/app/src/assets/localization/en/protocol_command_text.json +++ b/app/src/assets/localization/en/protocol_command_text.json @@ -3,7 +3,6 @@ "adapter_in_slot": "{{adapter}} in {{slot}}", "aspirate": "Aspirating {{volume}} µL from well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", "blowout": "Blowing out at well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", - "blowout_in_place": "Blowing out in place at {{flow_rate}} µL/sec", "closing_tc_lid": "Closing Thermocycler lid", "comment": "Comment", "configure_for_volume": "Configure {{pipette}} to aspirate {{volume}} µL", @@ -17,9 +16,7 @@ "disengaging_magnetic_module": "Disengaging Magnetic Module", "dispense_push_out": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec and pushing out {{push_out_volume}} µL", "dispense": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", - "dispense_in_place": "Dispensing {{volume}} µL in place at {{flow_rate}} µL/sec", "drop_tip": "Dropping tip in {{well_name}} of {{labware}}", - "drop_tip_in_place": "Dropping tip in place", "engaging_magnetic_module": "Engaging Magnetic Module", "fixed_trash": "Fixed Trash", "home_gantry": "Homing all gantry, pipette, and plunger axes", @@ -34,7 +31,6 @@ "move_to_coordinates": "Moving to (X: {{x}}, Y: {{y}}, Z: {{z}})", "move_to_slot": "Moving to Slot {{slot_name}}", "move_to_well": "Moving to well {{well_name}} of {{labware}} in {{labware_location}}", - "move_to_addressable_area": "Moving to {{addressable_area}} at {{speed}} mm/s at {{height}} mm high", "notes": "notes", "off_deck": "off deck", "offdeck": "offdeck", diff --git a/app/src/organisms/CommandText/PipettingCommandText.tsx b/app/src/organisms/CommandText/PipettingCommandText.tsx index 9abc69df107..8aff25b4da3 100644 --- a/app/src/organisms/CommandText/PipettingCommandText.tsx +++ b/app/src/organisms/CommandText/PipettingCommandText.tsx @@ -1,10 +1,15 @@ import { useTranslation } from 'react-i18next' import { CompletedProtocolAnalysis, + AspirateRunTimeCommand, + DispenseRunTimeCommand, + BlowoutRunTimeCommand, + MoveToWellRunTimeCommand, + DropTipRunTimeCommand, + PickUpTipRunTimeCommand, getLabwareDefURI, RobotType, } from '@opentrons/shared-data' -import type { PipettingRunTimeCommand } from '@opentrons/shared-data' import { getLabwareDefinitionsFromCommands } from '../LabwarePositionCheck/utils/labware' import { getLoadedLabware } from './utils/accessors' import { @@ -13,8 +18,15 @@ import { getFinalLabwareLocation, } from './utils' +type PipettingRunTimeCommmand = + | AspirateRunTimeCommand + | DispenseRunTimeCommand + | BlowoutRunTimeCommand + | MoveToWellRunTimeCommand + | DropTipRunTimeCommand + | PickUpTipRunTimeCommand interface PipettingCommandTextProps { - command: PipettingRunTimeCommand + command: PipettingRunTimeCommmand robotSideAnalysis: CompletedProtocolAnalysis robotType: RobotType } @@ -26,15 +38,7 @@ export const PipettingCommandText = ({ }: PipettingCommandTextProps): JSX.Element | null => { const { t } = useTranslation('protocol_command_text') - let labwareId = '' - let wellName = '' - if ('labwareId' in command.params) { - labwareId = command.params.labwareId - } - if ('wellName' in command.params) { - wellName = command.params.wellName - } - + const { labwareId, wellName } = command.params const allPreviousCommands = robotSideAnalysis.commands.slice( 0, robotSideAnalysis.commands.findIndex(c => c.id === command.id) @@ -57,7 +61,7 @@ export const PipettingCommandText = ({ const { volume, flowRate } = command.params return t('aspirate', { well_name: wellName, - labware: getLabwareName(robotSideAnalysis, labwareId ?? ''), + labware: getLabwareName(robotSideAnalysis, labwareId), labware_location: displayLocation, volume: volume, flow_rate: flowRate, @@ -91,6 +95,13 @@ export const PipettingCommandText = ({ flow_rate: flowRate, }) } + case 'moveToWell': { + return t('move_to_well', { + well_name: wellName, + labware: getLabwareName(robotSideAnalysis, labwareId), + labware_location: displayLocation, + }) + } case 'dropTip': { const loadedLabware = getLoadedLabware(robotSideAnalysis, labwareId) const labwareDefinitions = getLabwareDefinitionsFromCommands( @@ -117,17 +128,6 @@ export const PipettingCommandText = ({ labware_location: displayLocation, }) } - case 'dropTipInPlace': { - return t('drop_tip_in_place') - } - case 'dispenseInPlace': { - const { volume, flowRate } = command.params - return t('dispense_in_place', { volume: volume, flow_rate: flowRate }) - } - case 'blowOutInPlace': { - const { flowRate } = command.params - return t('blowout_in_place', { flow_rate: flowRate }) - } default: { console.warn( 'PipettingCommandText encountered a command with an unrecognized commandType: ', diff --git a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx index 242c6939eb4..28ef08f940f 100644 --- a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx +++ b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx @@ -1,11 +1,7 @@ import * as React from 'react' import { renderWithProviders } from '@opentrons/components' import { - BlowoutInPlaceRunTimeCommand, - DispenseInPlaceRunTimeCommand, - DropTipInPlaceRunTimeCommand, FLEX_ROBOT_TYPE, - MoveToAddressableAreaRunTimeCommand, PrepareToAspirateRunTimeCommand, } from '@opentrons/shared-data' import { i18n } from '../../../i18n' @@ -89,26 +85,6 @@ describe('CommandText', () => { ) } }) - it('renders correct text for dispenseInPlace', () => { - const { getByText } = renderWithProviders( - , - { i18nInstance: i18n } - )[0] - getByText('Dispensing 50 µL in place at 300 µL/sec') - }) it('renders correct text for blowout', () => { const dispenseCommand = mockRobotSideAnalysis.commands.find( c => c.commandType === 'dispense' @@ -132,25 +108,6 @@ describe('CommandText', () => { ) } }) - it('renders correct text for blowOutInPlace', () => { - const { getByText } = renderWithProviders( - , - { i18nInstance: i18n } - )[0] - getByText('Blowing out in place at 300 µL/sec') - }) it('renders correct text for moveToWell', () => { const dispenseCommand = mockRobotSideAnalysis.commands.find( c => c.commandType === 'aspirate' @@ -172,27 +129,6 @@ describe('CommandText', () => { getByText('Moving to well A1 of NEST 1 Well Reservoir 195 mL in Slot 5') } }) - it('renders correct text for moveToAddressableArea', () => { - const { getByText } = renderWithProviders( - , - { i18nInstance: i18n } - )[0] - getByText('Moving to D3 at 200 mm/s at 100 mm high') - }) it('renders correct text for configureForVolume', () => { const command = { commandType: 'configureForVolume', @@ -268,24 +204,6 @@ describe('CommandText', () => { )[0] getByText('Returning tip to A1 of Opentrons 96 Tip Rack 300 µL in Slot 9') }) - it('renders correct text for dropTipInPlace', () => { - const { getByText } = renderWithProviders( - , - { i18nInstance: i18n } - )[0] - getByText('Dropping tip in place') - }) it('renders correct text for pickUpTip', () => { const command = mockRobotSideAnalysis.commands.find( c => c.commandType === 'pickUpTip' diff --git a/app/src/organisms/CommandText/index.tsx b/app/src/organisms/CommandText/index.tsx index 00e9bca5808..67e76526ab1 100644 --- a/app/src/organisms/CommandText/index.tsx +++ b/app/src/organisms/CommandText/index.tsx @@ -3,11 +3,6 @@ import { useTranslation } from 'react-i18next' import { Flex, DIRECTION_COLUMN, SPACING } from '@opentrons/components' import { getPipetteNameSpecs, RunTimeCommand } from '@opentrons/shared-data' -import { - getLabwareName, - getLabwareDisplayLocation, - getFinalLabwareLocation, -} from './utils' import { StyledText } from '../../atoms/text' import { LoadCommandText } from './LoadCommandText' import { PipettingCommandText } from './PipettingCommandText' @@ -55,11 +50,9 @@ export function CommandText(props: Props): JSX.Element | null { switch (command.commandType) { case 'aspirate': case 'dispense': - case 'dispenseInPlace': case 'blowout': - case 'blowOutInPlace': + case 'moveToWell': case 'dropTip': - case 'dropTipInPlace': case 'pickUpTip': { return ( @@ -145,31 +138,6 @@ export function CommandText(props: Props): JSX.Element | null { ) } - case 'moveToWell': { - const { wellName, labwareId } = command.params - const allPreviousCommands = robotSideAnalysis.commands.slice( - 0, - robotSideAnalysis.commands.findIndex(c => c.id === command.id) - ) - const labwareLocation = getFinalLabwareLocation( - labwareId, - allPreviousCommands - ) - const displayLocation = - labwareLocation != null - ? getLabwareDisplayLocation( - robotSideAnalysis, - labwareLocation, - t, - robotType - ) - : '' - return t('move_to_well', { - well_name: wellName, - labware: getLabwareName(robotSideAnalysis, labwareId), - labware_location: displayLocation, - }) - } case 'moveLabware': { return ( @@ -214,18 +182,6 @@ export function CommandText(props: Props): JSX.Element | null { ) } - case 'moveToAddressableArea': { - const { addressableAreaName, speed, minimumZHeight } = command.params - return ( - - {t('move_to_addressable_area', { - addressable_area: addressableAreaName, - speed: speed, - height: minimumZHeight, - })} - - ) - } case 'touchTip': case 'home': case 'savePosition': diff --git a/shared-data/command/types/pipetting.ts b/shared-data/command/types/pipetting.ts index 192c4d71345..1a0c0dd36c8 100644 --- a/shared-data/command/types/pipetting.ts +++ b/shared-data/command/types/pipetting.ts @@ -1,35 +1,27 @@ import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' export type PipettingRunTimeCommand = - | PipettingAtLocationRunTimeCommand - | PipettingInPlaceRunTimeCommand - -export type PipettingAtLocationRunTimeCommand = | AspirateRunTimeCommand - | BlowoutRunTimeCommand | DispenseRunTimeCommand - | DropTipRunTimeCommand - | PickUpTipRunTimeCommand - | TouchTipRunTimeCommand - -export type PipettingInPlaceRunTimeCommand = + | BlowoutRunTimeCommand | BlowoutInPlaceRunTimeCommand - | ConfigureForVolumeRunTimeCommand - | DispenseInPlaceRunTimeCommand + | TouchTipRunTimeCommand + | PickUpTipRunTimeCommand + | DropTipRunTimeCommand | DropTipInPlaceRunTimeCommand + | ConfigureForVolumeRunTimeCommand | PrepareToAspirateRunTimeCommand export type PipettingCreateCommand = | AspirateCreateCommand + | DispenseCreateCommand | BlowoutCreateCommand | BlowoutInPlaceCreateCommand - | ConfigureForVolumeCreateCommand - | DispenseCreateCommand - | DispenseInPlaceCreateCommand + | TouchTipCreateCommand + | PickUpTipCreateCommand | DropTipCreateCommand | DropTipInPlaceCreateCommand - | PickUpTipCreateCommand + | ConfigureForVolumeCreateCommand | PrepareToAspirateCreateCommand - | TouchTipCreateCommand export interface ConfigureForVolumeCreateCommand extends CommonCommandCreateInfo { @@ -66,17 +58,6 @@ export interface DispenseRunTimeCommand DispenseCreateCommand { result?: BasicLiquidHandlingResult } - -export interface DispenseInPlaceCreateCommand extends CommonCommandCreateInfo { - commandType: 'dispenseInPlace' - params: DispenseInPlaceParams -} -export interface DispenseInPlaceRunTimeCommand - extends CommonCommandRunTimeInfo, - DispenseInPlaceCreateCommand { - result?: BasicLiquidHandlingResult -} - export interface BlowoutCreateCommand extends CommonCommandCreateInfo { commandType: 'blowout' params: BlowoutParams @@ -173,13 +154,6 @@ export interface BlowoutInPlaceParams { flowRate: number // µL/s } -export interface DispenseInPlaceParams { - pipetteId: string - volume: number - flowRate: number // µL/s - pushOut?: number -} - interface FlowRateParams { flowRate: number // µL/s } From 424f001bd583e96325d40b6b38170db5c4fd8768 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 12:27:30 -0500 Subject: [PATCH 13/65] reset pipetting types for now --- shared-data/command/types/pipetting.ts | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/shared-data/command/types/pipetting.ts b/shared-data/command/types/pipetting.ts index 1a0c0dd36c8..fe54ed1cf81 100644 --- a/shared-data/command/types/pipetting.ts +++ b/shared-data/command/types/pipetting.ts @@ -1,27 +1,29 @@ import type { CommonCommandRunTimeInfo, CommonCommandCreateInfo } from '.' export type PipettingRunTimeCommand = | AspirateRunTimeCommand - | DispenseRunTimeCommand - | BlowoutRunTimeCommand | BlowoutInPlaceRunTimeCommand - | TouchTipRunTimeCommand - | PickUpTipRunTimeCommand - | DropTipRunTimeCommand - | DropTipInPlaceRunTimeCommand + | BlowoutRunTimeCommand | ConfigureForVolumeRunTimeCommand + | DispenseInPlaceRunTimeCommand + | DispenseRunTimeCommand + | DropTipInPlaceRunTimeCommand + | DropTipRunTimeCommand + | PickUpTipRunTimeCommand | PrepareToAspirateRunTimeCommand + | TouchTipRunTimeCommand export type PipettingCreateCommand = | AspirateCreateCommand - | DispenseCreateCommand | BlowoutCreateCommand | BlowoutInPlaceCreateCommand - | TouchTipCreateCommand - | PickUpTipCreateCommand + | ConfigureForVolumeCreateCommand + | DispenseCreateCommand + | DispenseInPlaceCreateCommand | DropTipCreateCommand | DropTipInPlaceCreateCommand - | ConfigureForVolumeCreateCommand + | PickUpTipCreateCommand | PrepareToAspirateCreateCommand + | TouchTipCreateCommand export interface ConfigureForVolumeCreateCommand extends CommonCommandCreateInfo { @@ -58,6 +60,17 @@ export interface DispenseRunTimeCommand DispenseCreateCommand { result?: BasicLiquidHandlingResult } + +export interface DispenseInPlaceCreateCommand extends CommonCommandCreateInfo { + commandType: 'dispenseInPlace' + params: DispenseInPlaceParams +} +export interface DispenseInPlaceRunTimeCommand + extends CommonCommandRunTimeInfo, + DispenseInPlaceCreateCommand { + result?: BasicLiquidHandlingResult +} + export interface BlowoutCreateCommand extends CommonCommandCreateInfo { commandType: 'blowout' params: BlowoutParams @@ -154,6 +167,13 @@ export interface BlowoutInPlaceParams { flowRate: number // µL/s } +export interface DispenseInPlaceParams { + pipetteId: string + volume: number + flowRate: number // µL/s + pushOut?: number +} + interface FlowRateParams { flowRate: number // µL/s } From c561d3730ad7cc5b06fd3d3f7605015fb77a439c Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 15:09:54 -0500 Subject: [PATCH 14/65] stash fixture files --- .../2/fixture_flex_96_tiprack_adapter | 43 + .../2/fixture_flex_tiprack_1000_ul.json | 1026 +++++++++++++++++ shared-data/pipette/fixtures/name/index.ts | 1 + .../src/__tests__/replaceTip.test.ts | 3 + .../src/fixtures/commandFixtures.ts | 1 + .../src/fixtures/robotStateFixtures.ts | 29 +- 6 files changed, 1101 insertions(+), 2 deletions(-) create mode 100644 shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter create mode 100644 shared-data/labware/fixtures/2/fixture_flex_tiprack_1000_ul.json diff --git a/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter b/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter new file mode 100644 index 00000000000..43f22feddc1 --- /dev/null +++ b/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter @@ -0,0 +1,43 @@ +{ + "ordering": [], + "brand": { + "brand": "Fixture", + "brandId": [] + }, + "metadata": { + "displayName": "Fixture Flex 96 Tip Rack Adapter", + "displayCategory": "adapter", + "displayVolumeUnits": "µL", + "tags": [] + }, + "dimensions": { + "xDimension": 156.5, + "yDimension": 93, + "zDimension": 132 + }, + "wells": {}, + "groups": [ + { + "metadata": {}, + "wells": [] + } + ], + "parameters": { + "format": "96Standard", + "quirks": [], + "isTiprack": false, + "isMagneticModuleCompatible": false, + "loadName": "fixture_flex_96_tiprack_adapter" + }, + "namespace": "fixture", + "version": 1, + "schemaVersion": 2, + "allowedRoles": [ + "adapter" + ], + "cornerOffsetFromSlot": { + "x": -14.25, + "y": -3.5, + "z": 0 + } +} diff --git a/shared-data/labware/fixtures/2/fixture_flex_tiprack_1000_ul.json b/shared-data/labware/fixtures/2/fixture_flex_tiprack_1000_ul.json new file mode 100644 index 00000000000..5eaa01f9440 --- /dev/null +++ b/shared-data/labware/fixtures/2/fixture_flex_tiprack_1000_ul.json @@ -0,0 +1,1026 @@ +{ + "ordering": [ + ["A1", "B1", "C1", "D1", "E1", "F1", "G1", "H1"], + ["A2", "B2", "C2", "D2", "E2", "F2", "G2", "H2"], + ["A3", "B3", "C3", "D3", "E3", "F3", "G3", "H3"], + ["A4", "B4", "C4", "D4", "E4", "F4", "G4", "H4"], + ["A5", "B5", "C5", "D5", "E5", "F5", "G5", "H5"], + ["A6", "B6", "C6", "D6", "E6", "F6", "G6", "H6"], + ["A7", "B7", "C7", "D7", "E7", "F7", "G7", "H7"], + ["A8", "B8", "C8", "D8", "E8", "F8", "G8", "H8"], + ["A9", "B9", "C9", "D9", "E9", "F9", "G9", "H9"], + ["A10", "B10", "C10", "D10", "E10", "F10", "G10", "H10"], + ["A11", "B11", "C11", "D11", "E11", "F11", "G11", "H11"], + ["A12", "B12", "C12", "D12", "E12", "F12", "G12", "H12"] + ], + "brand": { + "brand": "Fixture", + "brandId": [] + }, + "metadata": { + "displayName": "Fixture Flex Tiprack 1000 uL", + "displayCategory": "tipRack", + "displayVolumeUnits": "µL", + "tags": [] + }, + "dimensions": { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99 + }, + "gripForce": 16, + "gripHeightFromLabwareBottom": 23.9, + "wells": { + "A1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5 + }, + "B1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5 + }, + "C1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5 + }, + "D1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5 + }, + "E1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5 + }, + "F1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5 + }, + "G1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5 + }, + "H1": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5 + }, + "A2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5 + }, + "B2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5 + }, + "C2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5 + }, + "D2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5 + }, + "E2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5 + }, + "F2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5 + }, + "G2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5 + }, + "H2": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5 + }, + "A3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5 + }, + "B3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5 + }, + "C3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5 + }, + "D3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5 + }, + "E3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5 + }, + "F3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5 + }, + "G3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5 + }, + "H3": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5 + }, + "A4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5 + }, + "B4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5 + }, + "C4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5 + }, + "D4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5 + }, + "E4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5 + }, + "F4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5 + }, + "G4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5 + }, + "H4": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5 + }, + "A5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5 + }, + "B5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5 + }, + "C5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5 + }, + "D5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5 + }, + "E5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5 + }, + "F5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5 + }, + "G5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5 + }, + "H5": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5 + }, + "A6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5 + }, + "B6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5 + }, + "C6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5 + }, + "D6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5 + }, + "E6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5 + }, + "F6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5 + }, + "G6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5 + }, + "H6": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5 + }, + "A7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5 + }, + "B7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5 + }, + "C7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5 + }, + "D7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5 + }, + "E7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5 + }, + "F7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5 + }, + "G7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5 + }, + "H7": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5 + }, + "A8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5 + }, + "B8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5 + }, + "C8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5 + }, + "D8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5 + }, + "E8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5 + }, + "F8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5 + }, + "G8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5 + }, + "H8": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5 + }, + "A9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5 + }, + "B9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5 + }, + "C9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5 + }, + "D9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5 + }, + "E9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5 + }, + "F9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5 + }, + "G9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5 + }, + "H9": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5 + }, + "A10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5 + }, + "B10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5 + }, + "C10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5 + }, + "D10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5 + }, + "E10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5 + }, + "F10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5 + }, + "G10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5 + }, + "H10": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5 + }, + "A11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5 + }, + "B11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5 + }, + "C11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5 + }, + "D11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5 + }, + "E11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5 + }, + "F11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5 + }, + "G11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5 + }, + "H11": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5 + }, + "A12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5 + }, + "B12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5 + }, + "C12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5 + }, + "D12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5 + }, + "E12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5 + }, + "F12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5 + }, + "G12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5 + }, + "H12": { + "depth": 97.5, + "shape": "circular", + "diameter": 5.47, + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5 + } + }, + "groups": [ + { + "metadata": {}, + "wells": [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12" + ] + } + ], + "parameters": { + "format": "96Standard", + "quirks": [], + "isTiprack": true, + "tipLength": 95.6, + "tipOverlap": 10.5, + "isMagneticModuleCompatible": false, + "loadName": "fixture_flex_96_tiprack_1000ul" + }, + "namespace": "fixture", + "version": 1, + "schemaVersion": 2, + "cornerOffsetFromSlot": { + "x": 0, + "y": 0, + "z": 0 + }, + "stackingOffsetWithLabware": { + "opentrons_flex_96_tiprack_adapter": { + "x": 0, + "y": 0, + "z": 121 + } + } +} diff --git a/shared-data/pipette/fixtures/name/index.ts b/shared-data/pipette/fixtures/name/index.ts index 1625636981e..0831ffc7fdd 100644 --- a/shared-data/pipette/fixtures/name/index.ts +++ b/shared-data/pipette/fixtures/name/index.ts @@ -16,3 +16,4 @@ export const fixtureP300Multi: PipetteNameSpecs = pipetteNameSpecFixtures.p300_multi export const fixtureP1000Single: PipetteNameSpecs = pipetteNameSpecFixtures.p1000_single +export const fixtureP100096: PipetteNameSpecs = pipetteNameSpecFixtures.p1000_96 diff --git a/step-generation/src/__tests__/replaceTip.test.ts b/step-generation/src/__tests__/replaceTip.test.ts index 27af7db7c96..5a6d744fef4 100644 --- a/step-generation/src/__tests__/replaceTip.test.ts +++ b/step-generation/src/__tests__/replaceTip.test.ts @@ -17,8 +17,11 @@ import type { InvariantContext, RobotState } from '../types' const tiprack1Id = 'tiprack1Id' const tiprack2Id = 'tiprack2Id' +const tiprack4Id = 'tiprack4Id' +const tiprack5Id = 'tiprack5Id' const p300SingleId = DEFAULT_PIPETTE const p300MultiId = 'p300MultiId' +const p100096Id = 'p100096Id' const wasteChuteId = 'wasteChuteId' describe('replaceTip', () => { let invariantContext: InvariantContext diff --git a/step-generation/src/fixtures/commandFixtures.ts b/step-generation/src/fixtures/commandFixtures.ts index 77029e9264c..2261323f430 100644 --- a/step-generation/src/fixtures/commandFixtures.ts +++ b/step-generation/src/fixtures/commandFixtures.ts @@ -90,6 +90,7 @@ export const getFlowRateAndOffsetParamsMix = (): FlowRateAndOffsetParamsMix => ( // ================= export const DEFAULT_PIPETTE = 'p300SingleId' export const MULTI_PIPETTE = 'p300MultiId' +export const PIPETTE_96 = 'p100096Id' export const SOURCE_LABWARE = 'sourcePlateId' export const DEST_LABWARE = 'destPlateId' export const TROUGH_LABWARE = 'troughId' diff --git a/step-generation/src/fixtures/robotStateFixtures.ts b/step-generation/src/fixtures/robotStateFixtures.ts index aa44e110dd3..adc06c10c09 100644 --- a/step-generation/src/fixtures/robotStateFixtures.ts +++ b/step-generation/src/fixtures/robotStateFixtures.ts @@ -10,12 +10,14 @@ import { fixtureP10Multi as _fixtureP10Multi, fixtureP300Single as _fixtureP300Single, fixtureP300Multi as _fixtureP300Multi, + fixtureP100096 as _fixtureP100096, } from '@opentrons/shared-data/pipette/fixtures/name' import _fixtureTrash from '@opentrons/shared-data/labware/fixtures/2/fixture_trash.json' import _fixture96Plate from '@opentrons/shared-data/labware/fixtures/2/fixture_96_plate.json' import _fixture12Trough from '@opentrons/shared-data/labware/fixtures/2/fixture_12_trough.json' import _fixtureTiprack10ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_10_ul.json' import _fixtureTiprack300ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_300_ul.json' +import _fixtureTiprack1000ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_1000_ul.json' import { TEMPERATURE_APPROACHING_TARGET, TEMPERATURE_AT_TARGET, @@ -26,15 +28,16 @@ import { import { DEFAULT_PIPETTE, MULTI_PIPETTE, + PIPETTE_96, SOURCE_LABWARE, DEST_LABWARE, TROUGH_LABWARE, } from './commandFixtures' import { makeInitialRobotState } from '../utils' import { tiprackWellNamesFlat } from './data' -import type { LabwareDefinition2 } from '@opentrons/shared-data' +imPIPETTE_96 type { LabwareDefinition2 } from '@opentrons/shared-data' import type { AdditionalEquipmentEntities } from '../types' -import type { +import typePIPETTE_96 { Config, InvariantContext, ModuleEntities, @@ -47,12 +50,14 @@ const fixtureP10Single = _fixtureP10Single const fixtureP10Multi = _fixtureP10Multi const fixtureP300Single = _fixtureP300Single const fixtureP300Multi = _fixtureP300Multi +const fixtureP100096 = _fixtureP100096 const fixtureTrash = _fixtureTrash as LabwareDefinition2 const fixture96Plate = _fixture96Plate as LabwareDefinition2 const fixture12Trough = _fixture12Trough as LabwareDefinition2 const fixtureTiprack10ul = _fixtureTiprack10ul as LabwareDefinition2 const fixtureTiprack300ul = _fixtureTiprack300ul as LabwareDefinition2 +const fixtureTiprack1000ul = _fixtureTiprack1000ul as LabwareDefinition2 export const DEFAULT_CONFIG: Config = { OT_PD_DISABLE_MODULE_RESTRICTIONS: false, @@ -120,6 +125,18 @@ export function makeContext(): InvariantContext { labwareDefURI: getLabwareDefURI(fixtureTiprack300ul), def: fixtureTiprack300ul, }, + tiprack4Id: { + id: 'tiprack4Id', + + labwareDefURI: getLabwareDefURI(fixtureTiprack1000ul), + def: fixtureTiprack1000ul, + }, + tiprack5Id: { + id: 'tiprack5Id', + + labwareDefURI: getLabwareDefURI(fixtureTiprack1000ul), + def: fixtureTiprack1000ul, + }, } const moduleEntities: ModuleEntities = {} const additionalEquipmentEntities: AdditionalEquipmentEntities = {} @@ -152,6 +169,14 @@ export function makeContext(): InvariantContext { name: 'p300_multi', id: MULTI_PIPETTE, + tiprackDefURI: getLabwareDefURI(fixtureTiprack300ul), + tiprackLabwareDef: fixtureTiprack300ul, + spec: fixtureP300Multi, + }, + [PIPETTE_96]: { + name: 'p1000_96', + id: PIPETTE_96, + tiprackDefURI: getLabwareDefURI(fixtureTiprack300ul), tiprackLabwareDef: fixtureTiprack300ul, spec: fixtureP300Multi, From 96c7905e52a6aed2c2cfced723e05e01ac378174 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Mon, 13 Nov 2023 09:39:59 -0500 Subject: [PATCH 15/65] clean up dropTip command logic --- .../generateRobotStateTimeline.ts | 62 +++++++------------ 1 file changed, 23 insertions(+), 39 deletions(-) diff --git a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts index 00f41a879c5..544a14dca10 100644 --- a/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts +++ b/protocol-designer/src/timelineMiddleware/generateRobotStateTimeline.ts @@ -2,7 +2,6 @@ import takeWhile from 'lodash/takeWhile' import * as StepGeneration from '@opentrons/step-generation' import { commandCreatorFromStepArgs } from '../file-data/selectors/commands' import type { StepArgsAndErrorsById } from '../steplist/types' -import { wasteChuteCommandsUtil } from '@opentrons/step-generation' export interface GenerateRobotStateTimelineArgs { allStepArgsAndErrors: StepArgsAndErrorsById @@ -77,45 +76,30 @@ export const generateRobotStateTimeline = ( ? '96ChannelWasteChute' : '1and8ChannelWasteChute' + const dropTipCommand = isWasteChute + ? StepGeneration.curryCommandCreator( + StepGeneration.wasteChuteCommandsUtil, + { + type: 'dropTip', + pipetteId: pipetteId, + addressableAreaName, + } + ) + : StepGeneration.curryCommandCreator(StepGeneration.dropTip, { + pipette: pipetteId, + dropTipLocation, + }) + if (!willReuseTip) { - return isWasteChute - ? [ - ...acc, - (_invariantContext, _prevRobotState) => - StepGeneration.reduceCommandCreators( - [ - curriedCommandCreator, - StepGeneration.curryCommandCreator( - wasteChuteCommandsUtil, - { - type: 'dropTip', - pipetteId: pipetteId, - addressableAreaName, - } - ), - ], - _invariantContext, - _prevRobotState - ), - ] - : [ - ...acc, - (_invariantContext, _prevRobotState) => - StepGeneration.reduceCommandCreators( - [ - curriedCommandCreator, - StepGeneration.curryCommandCreator( - StepGeneration.dropTip, - { - pipette: pipetteId, - dropTipLocation, - } - ), - ], - _invariantContext, - _prevRobotState - ), - ] + return [ + ...acc, + (_invariantContext, _prevRobotState) => + StepGeneration.reduceCommandCreators( + [curriedCommandCreator, dropTipCommand], + _invariantContext, + _prevRobotState + ), + ] } } From c7b53e72d07579ce34caeb315053423da77e4c80 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 14 Nov 2023 12:26:49 -0500 Subject: [PATCH 16/65] add fixtures for 1000ul tiprack and 96-channel adapter --- ...x_tiprack_1000_ul.json => fixture_flex_96_tiprack_1000ul.json} | 0 ...ex_96_tiprack_adapter => fixture_flex_96_tiprack_adapter.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename shared-data/labware/fixtures/2/{fixture_flex_tiprack_1000_ul.json => fixture_flex_96_tiprack_1000ul.json} (100%) rename shared-data/labware/fixtures/2/{fixture_flex_96_tiprack_adapter => fixture_flex_96_tiprack_adapter.json} (100%) diff --git a/shared-data/labware/fixtures/2/fixture_flex_tiprack_1000_ul.json b/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_1000ul.json similarity index 100% rename from shared-data/labware/fixtures/2/fixture_flex_tiprack_1000_ul.json rename to shared-data/labware/fixtures/2/fixture_flex_96_tiprack_1000ul.json diff --git a/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter b/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json similarity index 100% rename from shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter rename to shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json From d28cab5f680559607d2445f81efd7f2a493df47e Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 14 Nov 2023 12:27:35 -0500 Subject: [PATCH 17/65] update replaceTip tests for 96-channel in waste chute --- .../src/__tests__/replaceTip.test.ts | 45 +++++++++++++++++++ .../src/fixtures/robotStateFixtures.ts | 38 +++++++++++++--- 2 files changed, 77 insertions(+), 6 deletions(-) diff --git a/step-generation/src/__tests__/replaceTip.test.ts b/step-generation/src/__tests__/replaceTip.test.ts index 5a6d744fef4..6dfc0978583 100644 --- a/step-generation/src/__tests__/replaceTip.test.ts +++ b/step-generation/src/__tests__/replaceTip.test.ts @@ -249,4 +249,49 @@ describe('replaceTip', () => { ]) }) }) + describe('replaceTip: 96-channel', () => { + it('96-channel, dropping tips in waste chute', () => { + invariantContext = { + ...invariantContext, + additionalEquipmentEntities: { + wasteChuteId: { + name: 'wasteChute', + id: wasteChuteId, + location: 'D3', + }, + }, + } + const initialTestRobotState = merge({}, initialRobotState, { + tipState: { + tipracks: { + [tiprack4Id]: getTiprackTipstate(false), + [tiprack5Id]: getTiprackTipstate(true), + }, + pipettes: { + p100096Id: true, + }, + }, + }) + const result = replaceTip( + { + pipette: p100096Id, + dropTipLocation: 'wasteChuteId', + }, + invariantContext, + initialTestRobotState + ) + const res = getSuccessResult(result) + expect(res.commands).toEqual([ + moveToAddressableAreaHelper({ + pipetteId: p100096Id, + addressableAreaName: '96ChannelWasteChute', + }), + dropTipInPlaceHelper({ pipetteId: p100096Id }), + pickUpTipHelper('A1', { + pipetteId: p100096Id, + labwareId: tiprack5Id, + }), + ]) + }) + }) }) diff --git a/step-generation/src/fixtures/robotStateFixtures.ts b/step-generation/src/fixtures/robotStateFixtures.ts index adc06c10c09..42b1fa7fa58 100644 --- a/step-generation/src/fixtures/robotStateFixtures.ts +++ b/step-generation/src/fixtures/robotStateFixtures.ts @@ -17,7 +17,8 @@ import _fixture96Plate from '@opentrons/shared-data/labware/fixtures/2/fixture_9 import _fixture12Trough from '@opentrons/shared-data/labware/fixtures/2/fixture_12_trough.json' import _fixtureTiprack10ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_10_ul.json' import _fixtureTiprack300ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_300_ul.json' -import _fixtureTiprack1000ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_1000_ul.json' +import _fixtureTiprack1000ul from '@opentrons/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_1000ul.json' +import _fixtureTiprackAdapter from '@opentrons/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json' import { TEMPERATURE_APPROACHING_TARGET, TEMPERATURE_AT_TARGET, @@ -35,9 +36,9 @@ import { } from './commandFixtures' import { makeInitialRobotState } from '../utils' import { tiprackWellNamesFlat } from './data' -imPIPETTE_96 type { LabwareDefinition2 } from '@opentrons/shared-data' +import type { LabwareDefinition2 } from '@opentrons/shared-data' import type { AdditionalEquipmentEntities } from '../types' -import typePIPETTE_96 { +import type { Config, InvariantContext, ModuleEntities, @@ -58,6 +59,7 @@ const fixture12Trough = _fixture12Trough as LabwareDefinition2 const fixtureTiprack10ul = _fixtureTiprack10ul as LabwareDefinition2 const fixtureTiprack300ul = _fixtureTiprack300ul as LabwareDefinition2 const fixtureTiprack1000ul = _fixtureTiprack1000ul as LabwareDefinition2 +const fixtureTiprackAdapter = _fixtureTiprackAdapter as LabwareDefinition2 export const DEFAULT_CONFIG: Config = { OT_PD_DISABLE_MODULE_RESTRICTIONS: false, @@ -125,6 +127,18 @@ export function makeContext(): InvariantContext { labwareDefURI: getLabwareDefURI(fixtureTiprack300ul), def: fixtureTiprack300ul, }, + tiprack4AdapterId: { + id: 'tiprack4AdapterId', + + labwareDefURI: getLabwareDefURI(fixtureTiprackAdapter), + def: fixtureTiprackAdapter, + }, + tiprack5AdapterId: { + id: 'tiprack5AdapterId', + + labwareDefURI: getLabwareDefURI(fixtureTiprackAdapter), + def: fixtureTiprackAdapter, + }, tiprack4Id: { id: 'tiprack4Id', @@ -177,9 +191,9 @@ export function makeContext(): InvariantContext { name: 'p1000_96', id: PIPETTE_96, - tiprackDefURI: getLabwareDefURI(fixtureTiprack300ul), - tiprackLabwareDef: fixtureTiprack300ul, - spec: fixtureP300Multi, + tiprackDefURI: getLabwareDefURI(fixtureTiprack1000ul), + tiprackLabwareDef: fixtureTiprack1000ul, + spec: fixtureP100096, }, } return { @@ -238,6 +252,18 @@ export const makeStateArgsStandard = (): StandardMakeStateArgs => ({ tiprack2Id: { slot: '5', }, + tiprack4AdapterId: { + slot: '7', + }, + tiprack5AdapterId: { + slot: '8', + }, + tiprack4Id: { + slot: 'tiprack4AdapterId', + }, + tiprack5Id: { + slot: 'tiprack5AdapterId', + }, sourcePlateId: { slot: '2', }, From b19a928f4546d3a0234a790a029ebdb25f6d24ed Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 14 Nov 2023 12:28:04 -0500 Subject: [PATCH 18/65] update fixture tests to reflect 1000ul tiprack and adapter --- .../__snapshots__/LabwareList.test.tsx.snap | 1187 +++++ .../FilterCategory.test.tsx.snap | 11 + .../fixtureGeneration.test.ts.snap | 4449 ++++++++++++++++- .../src/__tests__/fixtureGeneration.test.ts | 12 + 4 files changed, 5499 insertions(+), 160 deletions(-) diff --git a/labware-library/src/components/LabwareList/__tests__/__snapshots__/LabwareList.test.tsx.snap b/labware-library/src/components/LabwareList/__tests__/__snapshots__/LabwareList.test.tsx.snap index 4fc515c877c..aeb4b5c916d 100644 --- a/labware-library/src/components/LabwareList/__tests__/__snapshots__/LabwareList.test.tsx.snap +++ b/labware-library/src/components/LabwareList/__tests__/__snapshots__/LabwareList.test.tsx.snap @@ -6258,6 +6258,1193 @@ exports[`LabwareList component renders 1`] = ` } key="fixture/fixture_96_plate/1" /> + + +
  • + + Adapter + +
  • `; diff --git a/step-generation/src/__tests__/__snapshots__/fixtureGeneration.test.ts.snap b/step-generation/src/__tests__/__snapshots__/fixtureGeneration.test.ts.snap index 496ad3aed3c..e8e545df2b3 100644 --- a/step-generation/src/__tests__/__snapshots__/fixtureGeneration.test.ts.snap +++ b/step-generation/src/__tests__/__snapshots__/fixtureGeneration.test.ts.snap @@ -496,6 +496,204 @@ Object { "H8": Object {}, "H9": Object {}, }, + "tiprack4AdapterId": Object {}, + "tiprack4Id": Object { + "A1": Object {}, + "A10": Object {}, + "A11": Object {}, + "A12": Object {}, + "A2": Object {}, + "A3": Object {}, + "A4": Object {}, + "A5": Object {}, + "A6": Object {}, + "A7": Object {}, + "A8": Object {}, + "A9": Object {}, + "B1": Object {}, + "B10": Object {}, + "B11": Object {}, + "B12": Object {}, + "B2": Object {}, + "B3": Object {}, + "B4": Object {}, + "B5": Object {}, + "B6": Object {}, + "B7": Object {}, + "B8": Object {}, + "B9": Object {}, + "C1": Object {}, + "C10": Object {}, + "C11": Object {}, + "C12": Object {}, + "C2": Object {}, + "C3": Object {}, + "C4": Object {}, + "C5": Object {}, + "C6": Object {}, + "C7": Object {}, + "C8": Object {}, + "C9": Object {}, + "D1": Object {}, + "D10": Object {}, + "D11": Object {}, + "D12": Object {}, + "D2": Object {}, + "D3": Object {}, + "D4": Object {}, + "D5": Object {}, + "D6": Object {}, + "D7": Object {}, + "D8": Object {}, + "D9": Object {}, + "E1": Object {}, + "E10": Object {}, + "E11": Object {}, + "E12": Object {}, + "E2": Object {}, + "E3": Object {}, + "E4": Object {}, + "E5": Object {}, + "E6": Object {}, + "E7": Object {}, + "E8": Object {}, + "E9": Object {}, + "F1": Object {}, + "F10": Object {}, + "F11": Object {}, + "F12": Object {}, + "F2": Object {}, + "F3": Object {}, + "F4": Object {}, + "F5": Object {}, + "F6": Object {}, + "F7": Object {}, + "F8": Object {}, + "F9": Object {}, + "G1": Object {}, + "G10": Object {}, + "G11": Object {}, + "G12": Object {}, + "G2": Object {}, + "G3": Object {}, + "G4": Object {}, + "G5": Object {}, + "G6": Object {}, + "G7": Object {}, + "G8": Object {}, + "G9": Object {}, + "H1": Object {}, + "H10": Object {}, + "H11": Object {}, + "H12": Object {}, + "H2": Object {}, + "H3": Object {}, + "H4": Object {}, + "H5": Object {}, + "H6": Object {}, + "H7": Object {}, + "H8": Object {}, + "H9": Object {}, + }, + "tiprack5AdapterId": Object {}, + "tiprack5Id": Object { + "A1": Object {}, + "A10": Object {}, + "A11": Object {}, + "A12": Object {}, + "A2": Object {}, + "A3": Object {}, + "A4": Object {}, + "A5": Object {}, + "A6": Object {}, + "A7": Object {}, + "A8": Object {}, + "A9": Object {}, + "B1": Object {}, + "B10": Object {}, + "B11": Object {}, + "B12": Object {}, + "B2": Object {}, + "B3": Object {}, + "B4": Object {}, + "B5": Object {}, + "B6": Object {}, + "B7": Object {}, + "B8": Object {}, + "B9": Object {}, + "C1": Object {}, + "C10": Object {}, + "C11": Object {}, + "C12": Object {}, + "C2": Object {}, + "C3": Object {}, + "C4": Object {}, + "C5": Object {}, + "C6": Object {}, + "C7": Object {}, + "C8": Object {}, + "C9": Object {}, + "D1": Object {}, + "D10": Object {}, + "D11": Object {}, + "D12": Object {}, + "D2": Object {}, + "D3": Object {}, + "D4": Object {}, + "D5": Object {}, + "D6": Object {}, + "D7": Object {}, + "D8": Object {}, + "D9": Object {}, + "E1": Object {}, + "E10": Object {}, + "E11": Object {}, + "E12": Object {}, + "E2": Object {}, + "E3": Object {}, + "E4": Object {}, + "E5": Object {}, + "E6": Object {}, + "E7": Object {}, + "E8": Object {}, + "E9": Object {}, + "F1": Object {}, + "F10": Object {}, + "F11": Object {}, + "F12": Object {}, + "F2": Object {}, + "F3": Object {}, + "F4": Object {}, + "F5": Object {}, + "F6": Object {}, + "F7": Object {}, + "F8": Object {}, + "F9": Object {}, + "G1": Object {}, + "G10": Object {}, + "G11": Object {}, + "G12": Object {}, + "G2": Object {}, + "G3": Object {}, + "G4": Object {}, + "G5": Object {}, + "G6": Object {}, + "G7": Object {}, + "G8": Object {}, + "G9": Object {}, + "H1": Object {}, + "H10": Object {}, + "H11": Object {}, + "H12": Object {}, + "H2": Object {}, + "H3": Object {}, + "H4": Object {}, + "H5": Object {}, + "H6": Object {}, + "H7": Object {}, + "H8": Object {}, + "H9": Object {}, + }, "troughId": Object { "A1": Object {}, "A10": Object {}, @@ -512,6 +710,104 @@ Object { }, }, "pipettes": Object { + "p100096Id": Object { + "0": Object {}, + "1": Object {}, + "10": Object {}, + "11": Object {}, + "12": Object {}, + "13": Object {}, + "14": Object {}, + "15": Object {}, + "16": Object {}, + "17": Object {}, + "18": Object {}, + "19": Object {}, + "2": Object {}, + "20": Object {}, + "21": Object {}, + "22": Object {}, + "23": Object {}, + "24": Object {}, + "25": Object {}, + "26": Object {}, + "27": Object {}, + "28": Object {}, + "29": Object {}, + "3": Object {}, + "30": Object {}, + "31": Object {}, + "32": Object {}, + "33": Object {}, + "34": Object {}, + "35": Object {}, + "36": Object {}, + "37": Object {}, + "38": Object {}, + "39": Object {}, + "4": Object {}, + "40": Object {}, + "41": Object {}, + "42": Object {}, + "43": Object {}, + "44": Object {}, + "45": Object {}, + "46": Object {}, + "47": Object {}, + "48": Object {}, + "49": Object {}, + "5": Object {}, + "50": Object {}, + "51": Object {}, + "52": Object {}, + "53": Object {}, + "54": Object {}, + "55": Object {}, + "56": Object {}, + "57": Object {}, + "58": Object {}, + "59": Object {}, + "6": Object {}, + "60": Object {}, + "61": Object {}, + "62": Object {}, + "63": Object {}, + "64": Object {}, + "65": Object {}, + "66": Object {}, + "67": Object {}, + "68": Object {}, + "69": Object {}, + "7": Object {}, + "70": Object {}, + "71": Object {}, + "72": Object {}, + "73": Object {}, + "74": Object {}, + "75": Object {}, + "76": Object {}, + "77": Object {}, + "78": Object {}, + "79": Object {}, + "8": Object {}, + "80": Object {}, + "81": Object {}, + "82": Object {}, + "83": Object {}, + "84": Object {}, + "85": Object {}, + "86": Object {}, + "87": Object {}, + "88": Object {}, + "89": Object {}, + "9": Object {}, + "90": Object {}, + "91": Object {}, + "92": Object {}, + "93": Object {}, + "94": Object {}, + "95": Object {}, + }, "p10MultiId": Object { "0": Object {}, "1": Object {}, @@ -6261,230 +6557,3755 @@ Object { "id": "tiprack3Id", "labwareDefURI": "fixture/fixture_tiprack_300_ul/1", }, - "troughId": Object { + "tiprack4AdapterId": Object { "def": Object { + "allowedRoles": Array [ + "adapter", + ], "brand": Object { - "brand": "USA Scientific", - "brandId": Array [ - "1061-8150", - ], + "brand": "Fixture", + "brandId": Array [], }, "cornerOffsetFromSlot": Object { - "x": 0, - "y": 0, + "x": -14.25, + "y": -3.5, "z": 0, }, "dimensions": Object { - "xDimension": 127.76, - "yDimension": 85.8, - "zDimension": 44.45, + "xDimension": 156.5, + "yDimension": 93, + "zDimension": 132, }, "groups": Array [ Object { - "metadata": Object { - "wellBottomShape": "v", - }, - "wells": Array [ - "A1", - "A2", - "A3", - "A4", - "A5", - "A6", - "A7", - "A8", - "A9", - "A10", - "A11", - "A12", - ], + "metadata": Object {}, + "wells": Array [], }, ], "metadata": Object { - "displayCategory": "reservoir", - "displayName": "12 Channel Trough", - "displayVolumeUnits": "mL", + "displayCategory": "adapter", + "displayName": "Fixture Flex 96 Tip Rack Adapter", + "displayVolumeUnits": "µL", + "tags": Array [], }, "namespace": "fixture", - "ordering": Array [ - Array [ - "A1", - ], - Array [ - "A2", - ], - Array [ - "A3", - ], - Array [ - "A4", - ], - Array [ - "A5", - ], - Array [ - "A6", - ], + "ordering": Array [], + "parameters": Object { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "fixture_flex_96_tiprack_adapter", + "quirks": Array [], + }, + "schemaVersion": 2, + "version": 1, + "wells": Object {}, + }, + "id": "tiprack4AdapterId", + "labwareDefURI": "fixture/fixture_flex_96_tiprack_adapter/1", + }, + "tiprack4Id": Object { + "def": Object { + "brand": Object { + "brand": "Fixture", + "brandId": Array [], + }, + "cornerOffsetFromSlot": Object { + "x": 0, + "y": 0, + "z": 0, + }, + "dimensions": Object { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99, + }, + "gripForce": 16, + "gripHeightFromLabwareBottom": 23.9, + "groups": Array [ + Object { + "metadata": Object {}, + "wells": Array [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12", + ], + }, + ], + "metadata": Object { + "displayCategory": "tipRack", + "displayName": "Fixture Flex Tiprack 1000 uL", + "displayVolumeUnits": "µL", + "tags": Array [], + }, + "namespace": "fixture", + "ordering": Array [ + Array [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + ], + Array [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + ], + Array [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + ], + Array [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + ], + Array [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + ], + Array [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + ], Array [ "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", ], Array [ "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", ], Array [ "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", ], Array [ "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", ], Array [ "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", ], Array [ "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12", ], ], "parameters": Object { - "format": "trough", + "format": "96Standard", "isMagneticModuleCompatible": false, - "isTiprack": false, - "loadName": "fixture_12_trough", - "quirks": Array [ - "centerMultichannelOnWells", - "touchTipDisabled", - ], + "isTiprack": true, + "loadName": "fixture_flex_96_tiprack_1000ul", + "quirks": Array [], + "tipLength": 95.6, + "tipOverlap": 10.5, }, "schemaVersion": 2, + "stackingOffsetWithLabware": Object { + "opentrons_flex_96_tiprack_adapter": Object { + "x": 0, + "y": 0, + "z": 121, + }, + }, "version": 1, "wells": Object { "A1": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 13.94, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5, }, "A10": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 95.75, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5, }, "A11": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 104.84, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5, }, "A12": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 113.93, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5, }, "A2": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 23.03, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5, }, "A3": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 32.12, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5, }, "A4": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 41.21, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5, }, "A5": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 50.3, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5, }, "A6": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 59.39, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5, + }, + "A7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5, + }, + "A8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5, + }, + "A9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5, + }, + "B1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5, + }, + "B10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5, + }, + "B11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5, + }, + "B12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5, + }, + "B2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5, + }, + "B3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5, + }, + "B4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5, + }, + "B5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5, + }, + "B6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5, + }, + "B7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5, + }, + "B8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5, + }, + "B9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5, + }, + "C1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5, + }, + "C10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5, + }, + "C11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5, + }, + "C12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5, + }, + "C2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5, + }, + "C3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5, + }, + "C4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5, + }, + "C5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5, + }, + "C6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5, + }, + "C7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5, + }, + "C8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5, + }, + "C9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5, + }, + "D1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5, + }, + "D10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5, + }, + "D11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5, + }, + "D12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5, + }, + "D2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5, + }, + "D3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5, + }, + "D4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5, + }, + "D5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5, + }, + "D6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5, + }, + "D7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5, + }, + "D8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5, + }, + "D9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5, + }, + "E1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5, + }, + "E10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5, + }, + "E11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5, + }, + "E12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5, + }, + "E2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5, + }, + "E3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5, + }, + "E4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5, + }, + "E5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5, + }, + "E6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5, + }, + "E7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5, + }, + "E8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5, + }, + "E9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5, + }, + "F1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5, + }, + "F10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5, + }, + "F11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5, + }, + "F12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5, + }, + "F2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5, + }, + "F3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5, + }, + "F4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5, + }, + "F5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5, + }, + "F6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5, + }, + "F7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5, + }, + "F8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5, + }, + "F9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5, + }, + "G1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5, + }, + "G10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5, + }, + "G11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5, + }, + "G12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5, + }, + "G2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5, + }, + "G3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5, + }, + "G4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5, + }, + "G5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5, + }, + "G6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5, + }, + "G7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5, + }, + "G8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5, + }, + "G9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5, + }, + "H1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5, + }, + "H10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5, + }, + "H11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5, + }, + "H12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5, + }, + "H2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5, + }, + "H3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5, + }, + "H4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5, + }, + "H5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5, + }, + "H6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5, + }, + "H7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5, + }, + "H8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5, + }, + "H9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5, + }, + }, + }, + "id": "tiprack4Id", + "labwareDefURI": "fixture/fixture_flex_96_tiprack_1000ul/1", + }, + "tiprack5AdapterId": Object { + "def": Object { + "allowedRoles": Array [ + "adapter", + ], + "brand": Object { + "brand": "Fixture", + "brandId": Array [], + }, + "cornerOffsetFromSlot": Object { + "x": -14.25, + "y": -3.5, + "z": 0, + }, + "dimensions": Object { + "xDimension": 156.5, + "yDimension": 93, + "zDimension": 132, + }, + "groups": Array [ + Object { + "metadata": Object {}, + "wells": Array [], + }, + ], + "metadata": Object { + "displayCategory": "adapter", + "displayName": "Fixture Flex 96 Tip Rack Adapter", + "displayVolumeUnits": "µL", + "tags": Array [], + }, + "namespace": "fixture", + "ordering": Array [], + "parameters": Object { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "fixture_flex_96_tiprack_adapter", + "quirks": Array [], + }, + "schemaVersion": 2, + "version": 1, + "wells": Object {}, + }, + "id": "tiprack5AdapterId", + "labwareDefURI": "fixture/fixture_flex_96_tiprack_adapter/1", + }, + "tiprack5Id": Object { + "def": Object { + "brand": Object { + "brand": "Fixture", + "brandId": Array [], + }, + "cornerOffsetFromSlot": Object { + "x": 0, + "y": 0, + "z": 0, + }, + "dimensions": Object { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99, + }, + "gripForce": 16, + "gripHeightFromLabwareBottom": 23.9, + "groups": Array [ + Object { + "metadata": Object {}, + "wells": Array [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12", + ], + }, + ], + "metadata": Object { + "displayCategory": "tipRack", + "displayName": "Fixture Flex Tiprack 1000 uL", + "displayVolumeUnits": "µL", + "tags": Array [], + }, + "namespace": "fixture", + "ordering": Array [ + Array [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + ], + Array [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + ], + Array [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + ], + Array [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + ], + Array [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + ], + Array [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + ], + Array [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + ], + Array [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + ], + Array [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + ], + Array [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + ], + Array [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + ], + Array [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12", + ], + ], + "parameters": Object { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": true, + "loadName": "fixture_flex_96_tiprack_1000ul", + "quirks": Array [], + "tipLength": 95.6, + "tipOverlap": 10.5, + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": Object { + "opentrons_flex_96_tiprack_adapter": Object { + "x": 0, + "y": 0, + "z": 121, + }, + }, + "version": 1, + "wells": Object { + "A1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5, + }, + "A10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5, + }, + "A11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5, + }, + "A12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5, + }, + "A2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5, + }, + "A3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5, + }, + "A4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5, + }, + "A5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5, + }, + "A6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5, + }, + "A7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5, + }, + "A8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5, + }, + "A9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5, + }, + "B1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5, + }, + "B10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5, + }, + "B11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5, + }, + "B12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5, + }, + "B2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5, + }, + "B3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5, + }, + "B4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5, + }, + "B5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5, + }, + "B6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5, + }, + "B7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5, + }, + "B8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5, + }, + "B9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5, + }, + "C1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5, + }, + "C10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5, + }, + "C11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5, + }, + "C12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5, + }, + "C2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5, + }, + "C3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5, + }, + "C4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5, + }, + "C5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5, + }, + "C6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5, + }, + "C7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5, + }, + "C8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5, + }, + "C9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5, + }, + "D1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5, + }, + "D10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5, + }, + "D11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5, + }, + "D12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5, + }, + "D2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5, + }, + "D3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5, + }, + "D4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5, + }, + "D5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5, + }, + "D6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5, + }, + "D7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5, + }, + "D8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5, + }, + "D9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5, + }, + "E1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5, + }, + "E10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5, + }, + "E11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5, + }, + "E12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5, + }, + "E2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5, + }, + "E3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5, + }, + "E4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5, + }, + "E5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5, + }, + "E6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5, + }, + "E7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5, + }, + "E8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5, + }, + "E9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5, + }, + "F1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5, + }, + "F10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5, + }, + "F11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5, + }, + "F12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5, + }, + "F2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5, + }, + "F3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5, + }, + "F4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5, + }, + "F5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5, + }, + "F6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5, + }, + "F7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5, + }, + "F8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5, + }, + "F9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5, + }, + "G1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5, + }, + "G10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5, + }, + "G11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5, + }, + "G12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5, + }, + "G2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5, + }, + "G3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5, + }, + "G4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5, + }, + "G5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5, + }, + "G6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5, + }, + "G7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5, + }, + "G8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5, + }, + "G9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5, + }, + "H1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5, + }, + "H10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5, + }, + "H11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5, + }, + "H12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5, + }, + "H2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5, + }, + "H3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5, + }, + "H4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5, + }, + "H5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5, + }, + "H6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5, + }, + "H7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5, + }, + "H8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5, + }, + "H9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5, + }, + }, + }, + "id": "tiprack5Id", + "labwareDefURI": "fixture/fixture_flex_96_tiprack_1000ul/1", + }, + "troughId": Object { + "def": Object { + "brand": Object { + "brand": "USA Scientific", + "brandId": Array [ + "1061-8150", + ], + }, + "cornerOffsetFromSlot": Object { + "x": 0, + "y": 0, + "z": 0, + }, + "dimensions": Object { + "xDimension": 127.76, + "yDimension": 85.8, + "zDimension": 44.45, + }, + "groups": Array [ + Object { + "metadata": Object { + "wellBottomShape": "v", + }, + "wells": Array [ + "A1", + "A2", + "A3", + "A4", + "A5", + "A6", + "A7", + "A8", + "A9", + "A10", + "A11", + "A12", + ], + }, + ], + "metadata": Object { + "displayCategory": "reservoir", + "displayName": "12 Channel Trough", + "displayVolumeUnits": "mL", + }, + "namespace": "fixture", + "ordering": Array [ + Array [ + "A1", + ], + Array [ + "A2", + ], + Array [ + "A3", + ], + Array [ + "A4", + ], + Array [ + "A5", + ], + Array [ + "A6", + ], + Array [ + "A7", + ], + Array [ + "A8", + ], + Array [ + "A9", + ], + Array [ + "A10", + ], + Array [ + "A11", + ], + Array [ + "A12", + ], + ], + "parameters": Object { + "format": "trough", + "isMagneticModuleCompatible": false, + "isTiprack": false, + "loadName": "fixture_12_trough", + "quirks": Array [ + "centerMultichannelOnWells", + "touchTipDisabled", + ], + }, + "schemaVersion": 2, + "version": 1, + "wells": Object { + "A1": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 13.94, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A10": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 95.75, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A11": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 104.84, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A12": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 113.93, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A2": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 23.03, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A3": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 32.12, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A4": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 41.21, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A5": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 50.3, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A6": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 59.39, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A7": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 68.48, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A8": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 77.57, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + "A9": Object { + "depth": 42.16, + "shape": "rectangular", + "totalLiquidVolume": 22000, + "x": 86.66, + "xDimension": 8.33, + "y": 42.9, + "yDimension": 71.88, + "z": 2.29, + }, + }, + }, + "id": "troughId", + "labwareDefURI": "fixture/fixture_12_trough/1", + }, + }, + "moduleEntities": Object {}, + "pipetteEntities": Object { + "p100096Id": Object { + "id": "p100096Id", + "name": "p1000_96", + "spec": Object { + "channels": 96, + "defaultAspirateFlowRate": Object { + "max": 812, + "min": 3, + "value": 7.85, + }, + "defaultDispenseFlowRate": Object { + "max": 812, + "min": 3, + "value": 7.85, + }, + "displayName": "Flex 96-Channel 1000 μL", + "maxVolume": 1000, + "minVolume": 5, + }, + "tiprackDefURI": "fixture/fixture_flex_96_tiprack_1000ul/1", + "tiprackLabwareDef": Object { + "brand": Object { + "brand": "Fixture", + "brandId": Array [], + }, + "cornerOffsetFromSlot": Object { + "x": 0, + "y": 0, + "z": 0, + }, + "dimensions": Object { + "xDimension": 127.75, + "yDimension": 85.75, + "zDimension": 99, + }, + "gripForce": 16, + "gripHeightFromLabwareBottom": 23.9, + "groups": Array [ + Object { + "metadata": Object {}, + "wells": Array [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12", + ], + }, + ], + "metadata": Object { + "displayCategory": "tipRack", + "displayName": "Fixture Flex Tiprack 1000 uL", + "displayVolumeUnits": "µL", + "tags": Array [], + }, + "namespace": "fixture", + "ordering": Array [ + Array [ + "A1", + "B1", + "C1", + "D1", + "E1", + "F1", + "G1", + "H1", + ], + Array [ + "A2", + "B2", + "C2", + "D2", + "E2", + "F2", + "G2", + "H2", + ], + Array [ + "A3", + "B3", + "C3", + "D3", + "E3", + "F3", + "G3", + "H3", + ], + Array [ + "A4", + "B4", + "C4", + "D4", + "E4", + "F4", + "G4", + "H4", + ], + Array [ + "A5", + "B5", + "C5", + "D5", + "E5", + "F5", + "G5", + "H5", + ], + Array [ + "A6", + "B6", + "C6", + "D6", + "E6", + "F6", + "G6", + "H6", + ], + Array [ + "A7", + "B7", + "C7", + "D7", + "E7", + "F7", + "G7", + "H7", + ], + Array [ + "A8", + "B8", + "C8", + "D8", + "E8", + "F8", + "G8", + "H8", + ], + Array [ + "A9", + "B9", + "C9", + "D9", + "E9", + "F9", + "G9", + "H9", + ], + Array [ + "A10", + "B10", + "C10", + "D10", + "E10", + "F10", + "G10", + "H10", + ], + Array [ + "A11", + "B11", + "C11", + "D11", + "E11", + "F11", + "G11", + "H11", + ], + Array [ + "A12", + "B12", + "C12", + "D12", + "E12", + "F12", + "G12", + "H12", + ], + ], + "parameters": Object { + "format": "96Standard", + "isMagneticModuleCompatible": false, + "isTiprack": true, + "loadName": "fixture_flex_96_tiprack_1000ul", + "quirks": Array [], + "tipLength": 95.6, + "tipOverlap": 10.5, + }, + "schemaVersion": 2, + "stackingOffsetWithLabware": Object { + "opentrons_flex_96_tiprack_adapter": Object { + "x": 0, + "y": 0, + "z": 121, + }, + }, + "version": 1, + "wells": Object { + "A1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 74.38, + "z": 1.5, + }, + "A10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 74.38, + "z": 1.5, + }, + "A11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 74.38, + "z": 1.5, + }, + "A12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 74.38, + "z": 1.5, + }, + "A2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 74.38, + "z": 1.5, + }, + "A3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 74.38, + "z": 1.5, + }, + "A4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 74.38, + "z": 1.5, + }, + "A5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 74.38, + "z": 1.5, + }, + "A6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 74.38, + "z": 1.5, + }, + "A7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 74.38, + "z": 1.5, + }, + "A8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 74.38, + "z": 1.5, + }, + "A9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 74.38, + "z": 1.5, + }, + "B1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 65.38, + "z": 1.5, + }, + "B10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 65.38, + "z": 1.5, + }, + "B11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 65.38, + "z": 1.5, + }, + "B12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 65.38, + "z": 1.5, + }, + "B2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 65.38, + "z": 1.5, + }, + "B3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 65.38, + "z": 1.5, + }, + "B4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 65.38, + "z": 1.5, + }, + "B5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 65.38, + "z": 1.5, + }, + "B6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 65.38, + "z": 1.5, + }, + "B7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 65.38, + "z": 1.5, + }, + "B8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 65.38, + "z": 1.5, + }, + "B9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 65.38, + "z": 1.5, + }, + "C1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 56.38, + "z": 1.5, + }, + "C10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 56.38, + "z": 1.5, + }, + "C11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 56.38, + "z": 1.5, + }, + "C12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 56.38, + "z": 1.5, + }, + "C2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 56.38, + "z": 1.5, + }, + "C3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 56.38, + "z": 1.5, + }, + "C4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 56.38, + "z": 1.5, + }, + "C5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 56.38, + "z": 1.5, + }, + "C6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 56.38, + "z": 1.5, + }, + "C7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 56.38, + "z": 1.5, + }, + "C8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 56.38, + "z": 1.5, + }, + "C9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 56.38, + "z": 1.5, + }, + "D1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 47.38, + "z": 1.5, + }, + "D10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 47.38, + "z": 1.5, + }, + "D11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 47.38, + "z": 1.5, + }, + "D12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 47.38, + "z": 1.5, + }, + "D2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 47.38, + "z": 1.5, + }, + "D3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 47.38, + "z": 1.5, + }, + "D4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 47.38, + "z": 1.5, + }, + "D5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 47.38, + "z": 1.5, + }, + "D6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 47.38, + "z": 1.5, + }, + "D7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 47.38, + "z": 1.5, + }, + "D8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 47.38, + "z": 1.5, + }, + "D9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 47.38, + "z": 1.5, + }, + "E1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 38.38, + "z": 1.5, + }, + "E10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 38.38, + "z": 1.5, + }, + "E11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 38.38, + "z": 1.5, + }, + "E12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 38.38, + "z": 1.5, + }, + "E2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 38.38, + "z": 1.5, + }, + "E3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 38.38, + "z": 1.5, + }, + "E4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 38.38, + "z": 1.5, + }, + "E5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 38.38, + "z": 1.5, + }, + "E6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 38.38, + "z": 1.5, + }, + "E7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 38.38, + "z": 1.5, + }, + "E8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 38.38, + "z": 1.5, + }, + "E9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 38.38, + "z": 1.5, + }, + "F1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 29.38, + "z": 1.5, + }, + "F10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 29.38, + "z": 1.5, + }, + "F11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 29.38, + "z": 1.5, + }, + "F12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 29.38, + "z": 1.5, + }, + "F2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 29.38, + "z": 1.5, + }, + "F3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 29.38, + "z": 1.5, + }, + "F4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 29.38, + "z": 1.5, + }, + "F5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 29.38, + "z": 1.5, + }, + "F6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 29.38, + "z": 1.5, + }, + "F7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 29.38, + "z": 1.5, + }, + "F8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 29.38, + "z": 1.5, + }, + "F9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 29.38, + "z": 1.5, + }, + "G1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 20.38, + "z": 1.5, + }, + "G10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 20.38, + "z": 1.5, + }, + "G11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 20.38, + "z": 1.5, + }, + "G12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 20.38, + "z": 1.5, + }, + "G2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 20.38, + "z": 1.5, + }, + "G3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 20.38, + "z": 1.5, + }, + "G4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 20.38, + "z": 1.5, + }, + "G5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 20.38, + "z": 1.5, + }, + "G6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 20.38, + "z": 1.5, + }, + "G7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 20.38, + "z": 1.5, + }, + "G8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 20.38, + "z": 1.5, + }, + "G9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 20.38, + "z": 1.5, + }, + "H1": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 14.38, + "y": 11.38, + "z": 1.5, + }, + "H10": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 95.38, + "y": 11.38, + "z": 1.5, + }, + "H11": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 104.38, + "y": 11.38, + "z": 1.5, + }, + "H12": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 113.38, + "y": 11.38, + "z": 1.5, + }, + "H2": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 23.38, + "y": 11.38, + "z": 1.5, + }, + "H3": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 32.38, + "y": 11.38, + "z": 1.5, + }, + "H4": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 41.38, + "y": 11.38, + "z": 1.5, }, - "A7": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 68.48, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "H5": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 50.38, + "y": 11.38, + "z": 1.5, }, - "A8": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 77.57, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "H6": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 59.38, + "y": 11.38, + "z": 1.5, }, - "A9": Object { - "depth": 42.16, - "shape": "rectangular", - "totalLiquidVolume": 22000, - "x": 86.66, - "xDimension": 8.33, - "y": 42.9, - "yDimension": 71.88, - "z": 2.29, + "H7": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 68.38, + "y": 11.38, + "z": 1.5, + }, + "H8": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 77.38, + "y": 11.38, + "z": 1.5, + }, + "H9": Object { + "depth": 97.5, + "diameter": 5.47, + "shape": "circular", + "totalLiquidVolume": 1000, + "x": 86.38, + "y": 11.38, + "z": 1.5, }, }, }, - "id": "troughId", - "labwareDefURI": "fixture/fixture_12_trough/1", }, - }, - "moduleEntities": Object {}, - "pipetteEntities": Object { "p10MultiId": Object { "id": "p10MultiId", "name": "p10_multi", @@ -11088,6 +14909,18 @@ Object { "tiprack2Id": Object { "slot": "2", }, + "tiprack4AdapterId": Object { + "slot": "7", + }, + "tiprack4Id": Object { + "slot": "tiprack4AdapterId", + }, + "tiprack5AdapterId": Object { + "slot": "8", + }, + "tiprack5Id": Object { + "slot": "tiprack5AdapterId", + }, }, "liquidState": Object { "labware": Object { @@ -11584,6 +15417,204 @@ Object { "H8": Object {}, "H9": Object {}, }, + "tiprack4AdapterId": Object {}, + "tiprack4Id": Object { + "A1": Object {}, + "A10": Object {}, + "A11": Object {}, + "A12": Object {}, + "A2": Object {}, + "A3": Object {}, + "A4": Object {}, + "A5": Object {}, + "A6": Object {}, + "A7": Object {}, + "A8": Object {}, + "A9": Object {}, + "B1": Object {}, + "B10": Object {}, + "B11": Object {}, + "B12": Object {}, + "B2": Object {}, + "B3": Object {}, + "B4": Object {}, + "B5": Object {}, + "B6": Object {}, + "B7": Object {}, + "B8": Object {}, + "B9": Object {}, + "C1": Object {}, + "C10": Object {}, + "C11": Object {}, + "C12": Object {}, + "C2": Object {}, + "C3": Object {}, + "C4": Object {}, + "C5": Object {}, + "C6": Object {}, + "C7": Object {}, + "C8": Object {}, + "C9": Object {}, + "D1": Object {}, + "D10": Object {}, + "D11": Object {}, + "D12": Object {}, + "D2": Object {}, + "D3": Object {}, + "D4": Object {}, + "D5": Object {}, + "D6": Object {}, + "D7": Object {}, + "D8": Object {}, + "D9": Object {}, + "E1": Object {}, + "E10": Object {}, + "E11": Object {}, + "E12": Object {}, + "E2": Object {}, + "E3": Object {}, + "E4": Object {}, + "E5": Object {}, + "E6": Object {}, + "E7": Object {}, + "E8": Object {}, + "E9": Object {}, + "F1": Object {}, + "F10": Object {}, + "F11": Object {}, + "F12": Object {}, + "F2": Object {}, + "F3": Object {}, + "F4": Object {}, + "F5": Object {}, + "F6": Object {}, + "F7": Object {}, + "F8": Object {}, + "F9": Object {}, + "G1": Object {}, + "G10": Object {}, + "G11": Object {}, + "G12": Object {}, + "G2": Object {}, + "G3": Object {}, + "G4": Object {}, + "G5": Object {}, + "G6": Object {}, + "G7": Object {}, + "G8": Object {}, + "G9": Object {}, + "H1": Object {}, + "H10": Object {}, + "H11": Object {}, + "H12": Object {}, + "H2": Object {}, + "H3": Object {}, + "H4": Object {}, + "H5": Object {}, + "H6": Object {}, + "H7": Object {}, + "H8": Object {}, + "H9": Object {}, + }, + "tiprack5AdapterId": Object {}, + "tiprack5Id": Object { + "A1": Object {}, + "A10": Object {}, + "A11": Object {}, + "A12": Object {}, + "A2": Object {}, + "A3": Object {}, + "A4": Object {}, + "A5": Object {}, + "A6": Object {}, + "A7": Object {}, + "A8": Object {}, + "A9": Object {}, + "B1": Object {}, + "B10": Object {}, + "B11": Object {}, + "B12": Object {}, + "B2": Object {}, + "B3": Object {}, + "B4": Object {}, + "B5": Object {}, + "B6": Object {}, + "B7": Object {}, + "B8": Object {}, + "B9": Object {}, + "C1": Object {}, + "C10": Object {}, + "C11": Object {}, + "C12": Object {}, + "C2": Object {}, + "C3": Object {}, + "C4": Object {}, + "C5": Object {}, + "C6": Object {}, + "C7": Object {}, + "C8": Object {}, + "C9": Object {}, + "D1": Object {}, + "D10": Object {}, + "D11": Object {}, + "D12": Object {}, + "D2": Object {}, + "D3": Object {}, + "D4": Object {}, + "D5": Object {}, + "D6": Object {}, + "D7": Object {}, + "D8": Object {}, + "D9": Object {}, + "E1": Object {}, + "E10": Object {}, + "E11": Object {}, + "E12": Object {}, + "E2": Object {}, + "E3": Object {}, + "E4": Object {}, + "E5": Object {}, + "E6": Object {}, + "E7": Object {}, + "E8": Object {}, + "E9": Object {}, + "F1": Object {}, + "F10": Object {}, + "F11": Object {}, + "F12": Object {}, + "F2": Object {}, + "F3": Object {}, + "F4": Object {}, + "F5": Object {}, + "F6": Object {}, + "F7": Object {}, + "F8": Object {}, + "F9": Object {}, + "G1": Object {}, + "G10": Object {}, + "G11": Object {}, + "G12": Object {}, + "G2": Object {}, + "G3": Object {}, + "G4": Object {}, + "G5": Object {}, + "G6": Object {}, + "G7": Object {}, + "G8": Object {}, + "G9": Object {}, + "H1": Object {}, + "H10": Object {}, + "H11": Object {}, + "H12": Object {}, + "H2": Object {}, + "H3": Object {}, + "H4": Object {}, + "H5": Object {}, + "H6": Object {}, + "H7": Object {}, + "H8": Object {}, + "H9": Object {}, + }, "troughId": Object { "A1": Object {}, "A10": Object {}, @@ -11600,6 +15631,104 @@ Object { }, }, "pipettes": Object { + "p100096Id": Object { + "0": Object {}, + "1": Object {}, + "10": Object {}, + "11": Object {}, + "12": Object {}, + "13": Object {}, + "14": Object {}, + "15": Object {}, + "16": Object {}, + "17": Object {}, + "18": Object {}, + "19": Object {}, + "2": Object {}, + "20": Object {}, + "21": Object {}, + "22": Object {}, + "23": Object {}, + "24": Object {}, + "25": Object {}, + "26": Object {}, + "27": Object {}, + "28": Object {}, + "29": Object {}, + "3": Object {}, + "30": Object {}, + "31": Object {}, + "32": Object {}, + "33": Object {}, + "34": Object {}, + "35": Object {}, + "36": Object {}, + "37": Object {}, + "38": Object {}, + "39": Object {}, + "4": Object {}, + "40": Object {}, + "41": Object {}, + "42": Object {}, + "43": Object {}, + "44": Object {}, + "45": Object {}, + "46": Object {}, + "47": Object {}, + "48": Object {}, + "49": Object {}, + "5": Object {}, + "50": Object {}, + "51": Object {}, + "52": Object {}, + "53": Object {}, + "54": Object {}, + "55": Object {}, + "56": Object {}, + "57": Object {}, + "58": Object {}, + "59": Object {}, + "6": Object {}, + "60": Object {}, + "61": Object {}, + "62": Object {}, + "63": Object {}, + "64": Object {}, + "65": Object {}, + "66": Object {}, + "67": Object {}, + "68": Object {}, + "69": Object {}, + "7": Object {}, + "70": Object {}, + "71": Object {}, + "72": Object {}, + "73": Object {}, + "74": Object {}, + "75": Object {}, + "76": Object {}, + "77": Object {}, + "78": Object {}, + "79": Object {}, + "8": Object {}, + "80": Object {}, + "81": Object {}, + "82": Object {}, + "83": Object {}, + "84": Object {}, + "85": Object {}, + "86": Object {}, + "87": Object {}, + "88": Object {}, + "89": Object {}, + "9": Object {}, + "90": Object {}, + "91": Object {}, + "92": Object {}, + "93": Object {}, + "94": Object {}, + "95": Object {}, + }, "p10MultiId": Object { "0": Object {}, "1": Object {}, diff --git a/step-generation/src/__tests__/fixtureGeneration.test.ts b/step-generation/src/__tests__/fixtureGeneration.test.ts index 5f14449b473..158f0cfb6ed 100644 --- a/step-generation/src/__tests__/fixtureGeneration.test.ts +++ b/step-generation/src/__tests__/fixtureGeneration.test.ts @@ -18,6 +18,18 @@ describe('snapshot tests', () => { sourcePlateId: { slot: '4', }, + tiprack4AdapterId: { + slot: '7', + }, + tiprack5AdapterId: { + slot: '8', + }, + tiprack4Id: { + slot: 'tiprack4AdapterId', + }, + tiprack5Id: { + slot: 'tiprack5AdapterId', + }, fixedTrash: { slot: '12', }, From 574a1bb73fd557e274a9b0b2a0a8c8ea320a6ff6 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 14 Nov 2023 12:41:01 -0500 Subject: [PATCH 19/65] fix json formatting --- .../labware/fixtures/2/fixture_flex_96_tiprack_adapter.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json b/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json index 43f22feddc1..a97b50810f5 100644 --- a/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json +++ b/shared-data/labware/fixtures/2/fixture_flex_96_tiprack_adapter.json @@ -32,9 +32,7 @@ "namespace": "fixture", "version": 1, "schemaVersion": 2, - "allowedRoles": [ - "adapter" - ], + "allowedRoles": ["adapter"], "cornerOffsetFromSlot": { "x": -14.25, "y": -3.5, From fe12f92086fd0b9a0666e89f99f7a0f6a8e619c4 Mon Sep 17 00:00:00 2001 From: Alise Au <20424172+ahiuchingau@users.noreply.github.com> Date: Tue, 7 Nov 2023 14:04:42 -0500 Subject: [PATCH 20/65] we need to make sure positions are updated after fast home failure(#13934) --- api/src/opentrons/hardware_control/ot3api.py | 1 + 1 file changed, 1 insertion(+) diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index 7a87c7aae5e..d106308055c 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -1460,6 +1460,7 @@ async def _home_axis(self, axis: Axis) -> None: self._log.warning( f"Stall on {axis} during fast home, encoder may have missed an overflow" ) + await self.refresh_positions() await self._backend.home([axis], self.gantry_load) else: From 6575b5825290d86fc54ac113fe5bebff2b5ce80a Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 7 Nov 2023 15:43:02 -0500 Subject: [PATCH 21/65] feat(app): add robot is busy banner to device details (#13932) * feat(app): add robot is busy banner to device details --- .../localization/en/device_details.json | 3 +- .../DeviceDetailsDeckConfiguration.test.tsx | 47 +++++++++++++++++-- .../DeviceDetailsDeckConfiguration/index.tsx | 22 +++++++-- 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/app/src/assets/localization/en/device_details.json b/app/src/assets/localization/en/device_details.json index 7dfdc46a6a6..517b24894f0 100644 --- a/app/src/assets/localization/en/device_details.json +++ b/app/src/assets/localization/en/device_details.json @@ -33,7 +33,8 @@ "current_temp": "Current: {{temp}} °C", "current_version": "Current Version", "deck_cal_missing": "Pipette Offset calibration missing. Calibrate deck first.", - "deck_configuration_is_not_available": "Deck configuration is not available when run is in progress", + "deck_configuration_is_not_available_when_run_is_in_progress": "Deck configuration is not available when run is in progress", + "deck_configuration_is_not_available_when_robot_is_busy": "Deck configuration is not available when the robot is busy", "deck_configuration": "deck configuration", "deck_fixture_setup_instructions": "Deck fixture setup instructions", "deck_fixture_setup_modal_bottom_description_desktop": "For detailed instructions for different types of fixtures, scan the QR code or go to the link below.", diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx index 162db0ab1fe..3965297c1a3 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/DeviceDetailsDeckConfiguration.test.tsx @@ -1,14 +1,24 @@ import * as React from 'react' -import { DeckConfigurator, renderWithProviders } from '@opentrons/components' +import { when, resetAllWhenMocks } from 'jest-when' + +import { + DeckConfigurator, + partialComponentPropsMatcher, + renderWithProviders, +} from '@opentrons/components' import { + useCurrentMaintenanceRun, useDeckConfigurationQuery, useUpdateDeckConfigurationMutation, } from '@opentrons/react-api-client' + import { i18n } from '../../../i18n' import { useRunStatuses } from '../../Devices/hooks' import { DeckFixtureSetupInstructionsModal } from '../DeckFixtureSetupInstructionsModal' import { DeviceDetailsDeckConfiguration } from '../' +import type { MaintenanceRun } from '@opentrons/api-client' + jest.mock('@opentrons/components/src/hardware-sim/DeckConfigurator/index') jest.mock('@opentrons/react-api-client') jest.mock('../DeckFixtureSetupInstructionsModal') @@ -22,6 +32,9 @@ const RUN_STATUSES = { isRunTerminal: false, isRunIdle: false, } +const mockCurrnetMaintenanceRun = { + data: { id: 'mockMaintenanceRunId' }, +} as MaintenanceRun const mockUseDeckConfigurationQuery = useDeckConfigurationQuery as jest.MockedFunction< typeof useDeckConfigurationQuery @@ -38,6 +51,9 @@ const mockDeckConfigurator = DeckConfigurator as jest.MockedFunction< const mockUseRunStatuses = useRunStatuses as jest.MockedFunction< typeof useRunStatuses > +const mockUseCurrentMaintenanceRun = useCurrentMaintenanceRun as jest.MockedFunction< + typeof useCurrentMaintenanceRun +> const render = ( props: React.ComponentProps @@ -61,8 +77,15 @@ describe('DeviceDetailsDeckConfiguration', () => { mockDeckFixtureSetupInstructionsModal.mockReturnValue(
    mock DeckFixtureSetupInstructionsModal
    ) - mockDeckConfigurator.mockReturnValue(
    mock DeckConfigurator
    ) + when(mockDeckConfigurator).mockReturnValue(
    mock DeckConfigurator
    ) mockUseRunStatuses.mockReturnValue(RUN_STATUSES) + mockUseCurrentMaintenanceRun.mockReturnValue({ + data: {}, + } as any) + }) + + afterEach(() => { + resetAllWhenMocks() }) it('should render text and button', () => { @@ -83,9 +106,23 @@ describe('DeviceDetailsDeckConfiguration', () => { it('should render banner and make deck configurator disabled when running', () => { RUN_STATUSES.isRunRunning = true mockUseRunStatuses.mockReturnValue(RUN_STATUSES) - const [{ getByText, queryAllByRole }] = render(props) + when(mockDeckConfigurator) + .calledWith(partialComponentPropsMatcher({ readOnly: true })) + .mockReturnValue(
    disabled mock DeckConfigurator
    ) + const [{ getByText }] = render(props) getByText('Deck configuration is not available when run is in progress') - // Note (kk:10/27/2023) detects Setup Instructions buttons - expect(queryAllByRole('button').length).toBe(1) + getByText('disabled mock DeckConfigurator') + }) + + it('should render banner and make deck configurator disabled when a maintenance run exists', () => { + mockUseCurrentMaintenanceRun.mockReturnValue({ + data: mockCurrnetMaintenanceRun, + } as any) + when(mockDeckConfigurator) + .calledWith(partialComponentPropsMatcher({ readOnly: true })) + .mockReturnValue(
    disabled mock DeckConfigurator
    ) + const [{ getByText }] = render(props) + getByText('Deck configuration is not available when the robot is busy') + getByText('disabled mock DeckConfigurator') }) }) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index 4bc2c582557..69206f577db 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -17,6 +17,7 @@ import { TYPOGRAPHY, } from '@opentrons/components' import { + useCurrentMaintenanceRun, useDeckConfigurationQuery, useUpdateDeckConfigurationMutation, } from '@opentrons/react-api-client' @@ -33,6 +34,8 @@ import { useRunStatuses } from '../Devices/hooks' import type { Cutout } from '@opentrons/shared-data' +const RUN_REFETCH_INTERVAL = 5000 + interface DeviceDetailsDeckConfigurationProps { robotName: string } @@ -56,6 +59,10 @@ export function DeviceDetailsDeckConfiguration({ const deckConfig = useDeckConfigurationQuery().data ?? [] const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() const { isRunRunning } = useRunStatuses() + const { data: maintenanceRunData } = useCurrentMaintenanceRun({ + refetchInterval: RUN_REFETCH_INTERVAL, + }) + const isMaintenanceRunExisting = maintenanceRunData?.data?.id != null const handleClickAdd = (fixtureLocation: Cutout): void => { setTargetFixtureLocation(fixtureLocation) @@ -124,13 +131,22 @@ export function DeviceDetailsDeckConfiguration({ gridGap={SPACING.spacing16} paddingX={SPACING.spacing16} paddingBottom={SPACING.spacing32} - paddingTop={isRunRunning ? undefined : SPACING.spacing32} + paddingTop={ + isRunRunning || isMaintenanceRunExisting + ? undefined + : SPACING.spacing32 + } width="100%" flexDirection={DIRECTION_COLUMN} > {isRunRunning ? ( - {t('deck_configuration_is_not_available')} + {t('deck_configuration_is_not_available_when_run_is_in_progress')} + + ) : null} + {isMaintenanceRunExisting ? ( + + {t('deck_configuration_is_not_available_when_robot_is_busy')} ) : null} @@ -142,7 +158,7 @@ export function DeviceDetailsDeckConfiguration({ flexDirection={DIRECTION_COLUMN} > Date: Tue, 7 Nov 2023 15:46:02 -0500 Subject: [PATCH 22/65] feat(api): Partial tip configuration (#13936) Adds partial-tip configurations for all multichannel pipettes (8-channel and 96-channel). The idea here is that you can tell the system to use only a subset of a pipette's tips. This will really help with things like tip usage, and enable using high-throughput pipettes to interact with labware that would not support the geometry of multiple tips. --------- Co-authored-by: Laura Cox <31892318+Laura-Danielle@users.noreply.github.com> Co-authored-by: Carlos Co-authored-by: Laura Cox --- api/src/opentrons/hardware_control/api.py | 32 ++ .../opentrons/hardware_control/dev_types.py | 2 + .../instruments/ot2/pipette.py | 84 ++--- .../instruments/ot2/pipette_handler.py | 23 +- .../instruments/ot3/pipette.py | 109 +++---- .../instruments/ot3/pipette_handler.py | 23 +- .../hardware_control/nozzle_manager.py | 298 ++++++++++++++++++ api/src/opentrons/hardware_control/ot3api.py | 44 ++- .../protocols/liquid_handler.py | 24 ++ api/src/opentrons/protocol_api/__init__.py | 6 + .../opentrons/protocol_api/_nozzle_layout.py | 27 ++ .../protocol_api/core/engine/instrument.py | 45 ++- .../opentrons/protocol_api/core/instrument.py | 16 + .../core/legacy/legacy_instrument_core.py | 10 + .../legacy_instrument_core.py | 10 + .../protocol_api/instrument_context.py | 55 ++++ api/src/opentrons/protocol_engine/__init__.py | 10 + .../protocol_engine/clients/sync_client.py | 15 + .../protocol_engine/commands/__init__.py | 14 + .../commands/command_unions.py | 19 +- .../commands/configure_nozzle_layout.py | 111 +++++++ .../commands/configuring_common.py | 15 + .../protocol_engine/execution/equipment.py | 50 +++ .../protocol_engine/execution/tip_handler.py | 112 ++++++- .../resources/pipette_data_provider.py | 56 +++- .../protocol_engine/state/pipettes.py | 28 +- api/src/opentrons/protocol_engine/types.py | 64 ++++ api/src/opentrons/types.py | 1 + .../instruments/test_nozzle_manager.py | 199 ++++++++++++ .../hardware_control/test_ot3_api.py | 14 +- .../hardware_control/test_pipette.py | 2 +- .../hardware_control/test_pipette_handler.py | 4 +- .../core/engine/test_instrument_core.py | 52 ++- .../protocol_api/test_instrument_context.py | 24 ++ .../protocol_engine/commands/conftest.py | 7 + .../commands/test_configure_nozzle_layout.py | 212 +++++++++++++ .../execution/test_tip_handler.py | 96 +++++- .../resources/test_pipette_data_provider.py | 15 + .../state/test_pipette_store.py | 1 + .../state/test_pipette_view.py | 3 + shared-data/command/schemas/8.json | 165 ++++++++++ shared-data/errors/definitions/1/errors.json | 4 + .../2/general/eight_channel/p10/1_0.json | 13 +- .../2/general/eight_channel/p10/1_3.json | 13 +- .../2/general/eight_channel/p10/1_4.json | 13 +- .../2/general/eight_channel/p10/1_5.json | 13 +- .../2/general/eight_channel/p10/1_6.json | 13 +- .../2/general/eight_channel/p1000/1_0.json | 15 +- .../2/general/eight_channel/p1000/3_0.json | 13 +- .../2/general/eight_channel/p1000/3_3.json | 13 +- .../2/general/eight_channel/p1000/3_4.json | 13 +- .../2/general/eight_channel/p1000/3_5.json | 13 +- .../2/general/eight_channel/p20/2_0.json | 13 +- .../2/general/eight_channel/p20/2_1.json | 13 +- .../2/general/eight_channel/p300/1_0.json | 13 +- .../2/general/eight_channel/p300/1_3.json | 13 +- .../2/general/eight_channel/p300/1_4.json | 13 +- .../2/general/eight_channel/p300/1_5.json | 13 +- .../2/general/eight_channel/p300/2_0.json | 13 +- .../2/general/eight_channel/p300/2_1.json | 13 +- .../2/general/eight_channel/p50/1_0.json | 13 +- .../2/general/eight_channel/p50/1_3.json | 13 +- .../2/general/eight_channel/p50/1_4.json | 13 +- .../2/general/eight_channel/p50/1_5.json | 13 +- .../2/general/eight_channel/p50/3_0.json | 13 +- .../2/general/eight_channel/p50/3_3.json | 13 +- .../2/general/eight_channel/p50/3_4.json | 13 +- .../2/general/eight_channel/p50/3_5.json | 13 +- .../general/ninety_six_channel/p1000/1_0.json | 18 +- .../general/ninety_six_channel/p1000/3_0.json | 18 +- .../general/ninety_six_channel/p1000/3_3.json | 18 +- .../general/ninety_six_channel/p1000/3_4.json | 18 +- .../general/ninety_six_channel/p1000/3_5.json | 18 +- .../2/general/single_channel/p10/1_0.json | 6 +- .../2/general/single_channel/p10/1_3.json | 6 +- .../2/general/single_channel/p10/1_4.json | 6 +- .../2/general/single_channel/p10/1_5.json | 6 +- .../2/general/single_channel/p1000/1_0.json | 6 +- .../2/general/single_channel/p1000/1_3.json | 6 +- .../2/general/single_channel/p1000/1_4.json | 6 +- .../2/general/single_channel/p1000/1_5.json | 6 +- .../2/general/single_channel/p1000/2_0.json | 6 +- .../2/general/single_channel/p1000/2_1.json | 6 +- .../2/general/single_channel/p1000/2_2.json | 6 +- .../2/general/single_channel/p1000/3_0.json | 6 +- .../2/general/single_channel/p1000/3_3.json | 6 +- .../2/general/single_channel/p1000/3_4.json | 6 +- .../2/general/single_channel/p1000/3_5.json | 6 +- .../2/general/single_channel/p20/2_0.json | 6 +- .../2/general/single_channel/p20/2_1.json | 6 +- .../2/general/single_channel/p20/2_2.json | 6 +- .../2/general/single_channel/p300/1_0.json | 6 +- .../2/general/single_channel/p300/1_3.json | 6 +- .../2/general/single_channel/p300/1_4.json | 6 +- .../2/general/single_channel/p300/1_5.json | 6 +- .../2/general/single_channel/p300/2_0.json | 6 +- .../2/general/single_channel/p300/2_1.json | 6 +- .../2/general/single_channel/p50/1_0.json | 6 +- .../2/general/single_channel/p50/1_3.json | 6 +- .../2/general/single_channel/p50/1_4.json | 6 +- .../2/general/single_channel/p50/1_5.json | 8 +- .../2/general/single_channel/p50/3_0.json | 6 +- .../2/general/single_channel/p50/3_3.json | 6 +- .../2/general/single_channel/p50/3_4.json | 6 +- .../2/general/single_channel/p50/3_5.json | 6 +- .../2/geometry/eight_channel/p10/1_0.json | 14 +- .../2/geometry/eight_channel/p10/1_3.json | 14 +- .../2/geometry/eight_channel/p10/1_4.json | 14 +- .../2/geometry/eight_channel/p10/1_5.json | 14 +- .../2/geometry/eight_channel/p10/1_6.json | 14 +- .../2/geometry/eight_channel/p1000/1_0.json | 14 +- .../2/geometry/eight_channel/p1000/3_0.json | 14 +- .../2/geometry/eight_channel/p1000/3_3.json | 14 +- .../2/geometry/eight_channel/p1000/3_4.json | 14 +- .../2/geometry/eight_channel/p1000/3_5.json | 14 +- .../2/geometry/eight_channel/p20/2_0.json | 14 +- .../2/geometry/eight_channel/p20/2_1.json | 14 +- .../2/geometry/eight_channel/p300/1_0.json | 14 +- .../2/geometry/eight_channel/p300/1_3.json | 14 +- .../2/geometry/eight_channel/p300/1_4.json | 14 +- .../2/geometry/eight_channel/p300/1_5.json | 14 +- .../2/geometry/eight_channel/p300/2_0.json | 14 +- .../2/geometry/eight_channel/p300/2_1.json | 14 +- .../2/geometry/eight_channel/p50/1_0.json | 14 +- .../2/geometry/eight_channel/p50/1_3.json | 14 +- .../2/geometry/eight_channel/p50/1_4.json | 14 +- .../2/geometry/eight_channel/p50/1_5.json | 14 +- .../2/geometry/eight_channel/p50/3_0.json | 14 +- .../2/geometry/eight_channel/p50/3_3.json | 14 +- .../2/geometry/eight_channel/p50/3_4.json | 14 +- .../2/geometry/eight_channel/p50/3_5.json | 14 +- .../ninety_six_channel/p1000/1_0.json | 190 +++++------ .../ninety_six_channel/p1000/3_0.json | 190 +++++------ .../ninety_six_channel/p1000/3_3.json | 190 +++++------ .../ninety_six_channel/p1000/3_4.json | 190 +++++------ .../ninety_six_channel/p1000/3_5.json | 190 +++++------ .../opentrons_shared_data/errors/codes.py | 1 + .../pipette/model_constants.py | 4 +- .../pipette/mutable_configurations.py | 14 +- .../pipette/pipette_definition.py | 8 +- .../pipette/scripts/build_json_script.py | 10 +- .../scripts/update_configuration_files.py | 9 +- 142 files changed, 3166 insertions(+), 919 deletions(-) create mode 100644 api/src/opentrons/hardware_control/nozzle_manager.py create mode 100644 api/src/opentrons/protocol_api/_nozzle_layout.py create mode 100644 api/src/opentrons/protocol_engine/commands/configure_nozzle_layout.py create mode 100644 api/tests/opentrons/hardware_control/instruments/test_nozzle_manager.py create mode 100644 api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py diff --git a/api/src/opentrons/hardware_control/api.py b/api/src/opentrons/hardware_control/api.py index 3aa91eaae5e..75d0bd65226 100644 --- a/api/src/opentrons/hardware_control/api.py +++ b/api/src/opentrons/hardware_control/api.py @@ -1084,6 +1084,38 @@ async def blow_out( blowout_spec.instr.set_current_volume(0) blowout_spec.instr.ready_to_aspirate = False + async def update_nozzle_configuration_for_mount( + self, + mount: top_types.Mount, + back_left_nozzle: Optional[str], + front_right_nozzle: Optional[str], + starting_nozzle: Optional[str] = None, + ) -> None: + """ + Update a nozzle configuration for a given pipette. + + The expectation of this function is that the back_left_nozzle/front_right_nozzle are the two corners + of a rectangle of nozzles. A call to this function that does not follow that schema will result + in an error. + + :param mount: A robot mount that the instrument is on. + :param back_left_nozzle: A string representing a nozzle name of the form such as 'A1'. + :param front_right_nozzle: A string representing a nozzle name of the form such as 'A1'. + :param starting_nozzle: A string representing the starting nozzle which will be used as the critical point + of the pipette nozzle configuration. By default, the back left nozzle will be the starting nozzle if + none is provided. + :return: None. + + If none of the nozzle parameters are provided, the nozzle configuration will be reset to default. + """ + if not back_left_nozzle and not front_right_nozzle and not starting_nozzle: + await self.reset_nozzle_configuration(mount) + else: + assert back_left_nozzle and front_right_nozzle + await self.update_nozzle_configuration( + mount, back_left_nozzle, front_right_nozzle, starting_nozzle + ) + async def pick_up_tip( self, mount: top_types.Mount, diff --git a/api/src/opentrons/hardware_control/dev_types.py b/api/src/opentrons/hardware_control/dev_types.py index 915761245e8..0c4e5ae4ef7 100644 --- a/api/src/opentrons/hardware_control/dev_types.py +++ b/api/src/opentrons/hardware_control/dev_types.py @@ -28,6 +28,7 @@ from opentrons.drivers.types import MoveSplit from opentrons.types import Mount from opentrons.hardware_control.types import GripperJawState +from opentrons.hardware_control.nozzle_manager import NozzleMap class InstrumentSpec(TypedDict): @@ -94,6 +95,7 @@ class PipetteDict(InstrumentDict): has_tip: bool default_push_out_volume: Optional[float] supported_tips: Dict[PipetteTipType, SupportedTipsDefinition] + current_nozzle_map: Optional[NozzleMap] class PipetteStateDict(TypedDict): diff --git a/api/src/opentrons/hardware_control/instruments/ot2/pipette.py b/api/src/opentrons/hardware_control/instruments/ot2/pipette.py index 5185fce9f3e..f5b9aa3fd29 100644 --- a/api/src/opentrons/hardware_control/instruments/ot2/pipette.py +++ b/api/src/opentrons/hardware_control/instruments/ot2/pipette.py @@ -5,7 +5,7 @@ """ Classes and functions for pipette state tracking """ import logging -from typing import Any, Dict, Optional, Set, Tuple, Union, cast, List +from typing import Any, Dict, Optional, Set, Tuple, Union, cast from opentrons_shared_data.pipette.pipette_definition import ( PipetteConfigurations, @@ -46,6 +46,7 @@ BoardRevision, ) from opentrons.hardware_control.errors import InvalidCriticalPoint +from opentrons.hardware_control import nozzle_manager from opentrons_shared_data.pipette.dev_types import ( @@ -54,7 +55,6 @@ PipetteModel, ) from opentrons.hardware_control.dev_types import InstrumentHardwareConfigs -from typing_extensions import Final RECONFIG_KEYS = {"quirks"} @@ -62,8 +62,6 @@ mod_log = logging.getLogger(__name__) -INTERNOZZLE_SPACING_MM: Final[float] = 9 - # TODO (lc 11-1-2022) Once we unify calibration loading # for the hardware controller, we will be able to # unify the pipette classes again. @@ -92,6 +90,7 @@ def __init__( self._pipette_version = self._config.version self._max_channels = self._config.channels self._backlash_distance = config.backlash_distance + self._pick_up_configurations = config.pick_up_tip_configurations self._liquid_class_name = pip_types.LiquidClasses.default self._liquid_class = self._config.liquid_properties[self._liquid_class_name] @@ -109,6 +108,12 @@ def __init__( pipette_version=config.version, ) self._nozzle_offset = self._config.nozzle_offset + self._nozzle_manager = ( + nozzle_manager.NozzleConfigurationManager.build_from_nozzlemap( + self._config.nozzle_map, + self._config.partial_tip_configurations.per_tip_pickup_current, + ) + ) self._current_volume = 0.0 self._working_volume = float(self._liquid_class.max_volume) self._current_tip_length = 0.0 @@ -197,8 +202,12 @@ def liquid_class_name(self) -> pip_types.LiquidClasses: return self._liquid_class_name @property - def nozzle_offset(self) -> List[float]: - return self._nozzle_offset + def nozzle_offset(self) -> Point: + return self._nozzle_manager.starting_nozzle_offset + + @property + def nozzle_manager(self) -> nozzle_manager.NozzleConfigurationManager: + return self._nozzle_manager @property def pipette_offset(self) -> PipetteOffsetByPipetteMount: @@ -282,6 +291,12 @@ def reset_state(self) -> None: ) self._tip_overlap_lookup = self.liquid_class.tip_overlap_dictionary + self._nozzle_manager = ( + nozzle_manager.NozzleConfigurationManager.build_from_nozzlemap( + self._config.nozzle_map, + self._config.partial_tip_configurations.per_tip_pickup_current, + ) + ) def reset_pipette_offset(self, mount: Mount, to_default: bool) -> None: """Reset the pipette offset to system defaults.""" @@ -323,8 +338,6 @@ def critical_point(self, cp_override: Optional[CriticalPoint] = None) -> Point: we have a tip, or :py:attr:`CriticalPoint.XY_CENTER` - the specified critical point will be used. """ - instr = Point(*self._pipette_offset.offset) - offsets = self.nozzle_offset if cp_override in [ CriticalPoint.GRIPPER_JAW_CENTER, @@ -333,42 +346,22 @@ def critical_point(self, cp_override: Optional[CriticalPoint] = None) -> Point: ]: raise InvalidCriticalPoint(cp_override.name, "pipette") - if not self.has_tip or cp_override == CriticalPoint.NOZZLE: - cp_type = CriticalPoint.NOZZLE - tip_length = 0.0 - else: - cp_type = CriticalPoint.TIP - tip_length = self.current_tip_length - if cp_override == CriticalPoint.XY_CENTER: - mod_offset_xy = [ - offsets[0], - offsets[1] - (INTERNOZZLE_SPACING_MM * (self._config.channels - 1) / 2), - offsets[2], - ] - cp_type = CriticalPoint.XY_CENTER - elif cp_override == CriticalPoint.FRONT_NOZZLE: - mod_offset_xy = [ - 0, - (offsets[1] - INTERNOZZLE_SPACING_MM * (self._config.channels - 1)), - offsets[2], - ] - cp_type = CriticalPoint.FRONT_NOZZLE - else: - mod_offset_xy = list(offsets) - mod_and_tip = Point( - mod_offset_xy[0], mod_offset_xy[1], mod_offset_xy[2] - tip_length + instr = Point(*self._pipette_offset.offset) + cp_with_tip_length = self._nozzle_manager.critical_point_with_tip_length( + cp_override, + self.current_tip_length if cp_override != CriticalPoint.NOZZLE else 0.0, ) - cp = mod_and_tip + instr + cp = cp_with_tip_length + instr if self._log.isEnabledFor(logging.DEBUG): info_str = "cp: {}{}: {} (from: ".format( - cp_type, " (from override)" if cp_override else "", cp + cp_override, " (from override)" if cp_override else "", cp ) info_str += "model offset: {} + instrument offset: {}".format( - mod_offset_xy, instr + cp_with_tip_length, instr ) - info_str += " - tip_length: {}".format(tip_length) + info_str += " - tip_length: {}".format(self.current_tip_length) info_str += ")" self._log.debug(info_str) @@ -485,6 +478,25 @@ def ok_to_push_out(self, push_out_dist_mm: float) -> bool: self.plunger_positions.bottom - self.plunger_positions.blow_out ) + def update_nozzle_configuration( + self, + back_left_nozzle: str, + front_right_nozzle: str, + starting_nozzle: Optional[str] = None, + ) -> None: + """ + Update nozzle configuration manager. + """ + self._nozzle_manager.update_nozzle_configuration( + back_left_nozzle, front_right_nozzle, starting_nozzle + ) + + def reset_nozzle_configuration(self) -> None: + """ + Reset nozzle configuration manager. + """ + self._nozzle_manager.reset_to_default_configuration() + def add_tip(self, tip_length: float) -> None: """ Add a tip to the pipette for position tracking and validation diff --git a/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py b/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py index dba4e253da6..43d4e1518b4 100644 --- a/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py +++ b/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py @@ -226,6 +226,7 @@ def get_attached_instrument(self, mount: MountType) -> PipetteDict: # this dict newly every time? Any why only a few items are being updated? for key in configs: result[key] = instr_dict[key] + result["current_nozzle_map"] = instr.nozzle_manager.current_configuration result["min_volume"] = instr.liquid_class.min_volume result["max_volume"] = instr.liquid_class.max_volume result["channels"] = instr.channels @@ -392,6 +393,24 @@ async def reset(self) -> None: k: None for k in self._attached_instruments.keys() } + async def update_nozzle_configuration( + self, + mount: MountType, + back_left_nozzle: str, + front_right_nozzle: str, + starting_nozzle: Optional[str] = None, + ) -> None: + instr = self._attached_instruments[mount] + if instr: + instr.update_nozzle_configuration( + back_left_nozzle, front_right_nozzle, starting_nozzle + ) + + async def reset_nozzle_configuration(self, mount: MountType) -> None: + instr = self._attached_instruments[mount] + if instr: + instr.reset_nozzle_configuration() + async def add_tip(self, mount: MountType, tip_length: float) -> None: instr = self._attached_instruments[mount] attached = self.attached_instruments @@ -789,7 +808,7 @@ def add_tip_to_instr() -> None: current={ Axis.by_mount( mount - ): instrument.pick_up_configurations.current + ): instrument.nozzle_manager.get_tip_configuration_current() }, speed=pick_up_speed, relative_down=top_types.Point(0, 0, press_dist), @@ -818,7 +837,7 @@ def add_tip_to_instr() -> None: current={ Axis.by_mount( mount - ): instrument.pick_up_configurations.current + ): instrument.nozzle_manager.get_tip_configuration_current() }, speed=pick_up_speed, relative_down=top_types.Point(0, 0, press_dist), diff --git a/api/src/opentrons/hardware_control/instruments/ot3/pipette.py b/api/src/opentrons/hardware_control/instruments/ot3/pipette.py index 272a1dd97ec..89f99416726 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/pipette.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/pipette.py @@ -1,8 +1,7 @@ import logging import functools -from typing import Any, List, Dict, Optional, Set, Tuple, Union, cast -from typing_extensions import Final +from typing import Any, Dict, Optional, Set, Tuple, Union, cast from opentrons.types import Point @@ -46,12 +45,10 @@ ) from opentrons.hardware_control.types import CriticalPoint, OT3Mount from opentrons.hardware_control.errors import InvalidCriticalPoint +from opentrons.hardware_control import nozzle_manager mod_log = logging.getLogger(__name__) -# TODO (lc 12-2-2022) We should move this to the geometry configurations -INTERNOZZLE_SPACING_MM: Final[float] = 9 - class Pipette(AbstractInstrument[PipetteConfigurations]): """A class to gather and track pipette state and configs. @@ -97,6 +94,12 @@ def __init__( pipette_version=config.version, ) self._nozzle_offset = self._config.nozzle_offset + self._nozzle_manager = ( + nozzle_manager.NozzleConfigurationManager.build_from_nozzlemap( + self._config.nozzle_map, + self._config.partial_tip_configurations.per_tip_pickup_current, + ) + ) self._current_volume = 0.0 self._working_volume = float(self._liquid_class.max_volume) self._current_tip_length = 0.0 @@ -162,8 +165,12 @@ def tip_overlap(self) -> Dict[str, float]: return self._tip_overlap_lookup @property - def nozzle_offset(self) -> List[float]: - return self._nozzle_offset + def nozzle_offset(self) -> Point: + return self._nozzle_manager.starting_nozzle_offset + + @property + def nozzle_manager(self) -> nozzle_manager.NozzleConfigurationManager: + return self._nozzle_manager @property def pipette_offset(self) -> PipetteOffsetByPipetteMount: @@ -250,6 +257,12 @@ def reset_state(self) -> None: self._flow_acceleration = self._active_tip_settings.default_flow_acceleration self._tip_overlap_lookup = self.liquid_class.tip_overlap_dictionary + self._nozzle_manager = ( + nozzle_manager.NozzleConfigurationManager.build_from_nozzlemap( + self._config.nozzle_map, + self._config.partial_tip_configurations.per_tip_pickup_current, + ) + ) def reset_pipette_offset(self, mount: OT3Mount, to_default: bool) -> None: """Reset the pipette offset to system defaults.""" @@ -293,73 +306,28 @@ def critical_point(self, cp_override: Optional[CriticalPoint] = None) -> Point: we have a tip, or :py:attr:`CriticalPoint.XY_CENTER` - the specified critical point will be used. """ - instr = Point(*self._pipette_offset.offset) - offsets = self.nozzle_offset - # Temporary solution for the 96 channel critical point locations. - # We should instead record every channel "critical point" in - # the pipette configurations. - X_DIRECTION_VALUE = 1 - Y_DIVISION = 2 - if self.channels == 96: - NUM_ROWS = 12 - NUM_COLS = 8 - X_DIRECTION_VALUE = -1 - elif self.channels == 8: - NUM_ROWS = 1 - NUM_COLS = 8 - else: - NUM_ROWS = 1 - NUM_COLS = 1 - - x_offset_to_right_nozzle = ( - X_DIRECTION_VALUE * INTERNOZZLE_SPACING_MM * (NUM_ROWS - 1) - ) - y_offset_to_front_nozzle = INTERNOZZLE_SPACING_MM * (NUM_COLS - 1) - if cp_override in [ CriticalPoint.GRIPPER_JAW_CENTER, CriticalPoint.GRIPPER_FRONT_CALIBRATION_PIN, CriticalPoint.GRIPPER_REAR_CALIBRATION_PIN, ]: raise InvalidCriticalPoint(cp_override.name, "pipette") - if not self.has_tip_length or cp_override == CriticalPoint.NOZZLE: - cp_type = CriticalPoint.NOZZLE - tip_length = 0.0 - else: - cp_type = CriticalPoint.TIP - tip_length = self.current_tip_length - if cp_override == CriticalPoint.XY_CENTER: - mod_offset_xy = [ - offsets[0] - x_offset_to_right_nozzle / 2, - offsets[1] - y_offset_to_front_nozzle / Y_DIVISION, - offsets[2], - ] - cp_type = CriticalPoint.XY_CENTER - elif cp_override == CriticalPoint.FRONT_NOZZLE: - # front left nozzle of the 96 channel and - # front nozzle of the 8 channel - mod_offset_xy = [ - offsets[0], - offsets[1] - y_offset_to_front_nozzle, - offsets[2], - ] - cp_type = CriticalPoint.FRONT_NOZZLE - else: - mod_offset_xy = list(offsets) - mod_and_tip = Point( - mod_offset_xy[0], mod_offset_xy[1], mod_offset_xy[2] - tip_length - ) - cp = mod_and_tip + instr + instr = Point(*self._pipette_offset.offset) + cp_with_tip_length = self._nozzle_manager.critical_point_with_tip_length( + cp_override, + self.current_tip_length if cp_override != CriticalPoint.NOZZLE else 0.0, + ) + cp = cp_with_tip_length + instr if self._log.isEnabledFor(logging.DEBUG): info_str = "cp: {}{}: {} (from: ".format( - cp_type, " (from override)" if cp_override else "", cp + cp_override, " (from override)" if cp_override else "", cp ) info_str += "model offset: {} + instrument offset: {}".format( - mod_offset_xy, instr + cp_with_tip_length, instr ) - info_str += " - tip_length: {}".format(tip_length) + info_str += " - tip_length: {}".format(self.current_tip_length) info_str += ")" self._log.debug(info_str) @@ -483,6 +451,25 @@ def ok_to_push_out(self, push_out_dist_mm: float) -> bool: self.plunger_positions.blow_out - self.plunger_positions.bottom ) + def update_nozzle_configuration( + self, + back_left_nozzle: str, + front_right_nozzle: str, + starting_nozzle: Optional[str] = None, + ) -> None: + """ + Update nozzle configuration manager. + """ + self._nozzle_manager.update_nozzle_configuration( + back_left_nozzle, front_right_nozzle, starting_nozzle + ) + + def reset_nozzle_configuration(self) -> None: + """ + Reset nozzle configuration manager. + """ + self._nozzle_manager.reset_to_default_configuration() + def add_tip(self, tip_length: float) -> None: """ Add a tip to the pipette for position tracking and validation diff --git a/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py b/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py index ff8fbc64122..8b00f6f7aeb 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py @@ -241,6 +241,7 @@ def get_attached_instrument(self, mount: OT3Mount) -> PipetteDict: for key in configs: result[key] = instr_dict[key] + result["current_nozzle_map"] = instr.nozzle_manager.current_configuration result["min_volume"] = instr.liquid_class.min_volume result["max_volume"] = instr.liquid_class.max_volume result["channels"] = instr._max_channels @@ -398,6 +399,24 @@ async def reset(self) -> None: k: None for k in self._attached_instruments.keys() } + async def update_nozzle_configuration( + self, + mount: MountType, + back_left_nozzle: str, + front_right_nozzle: str, + starting_nozzle: Optional[str] = None, + ) -> None: + instr = self._attached_instruments[OT3Mount.from_mount(mount)] + if instr: + instr.update_nozzle_configuration( + back_left_nozzle, front_right_nozzle, starting_nozzle + ) + + async def reset_nozzle_configuration(self, mount: OT3Mount) -> None: + instr = self._attached_instruments[OT3Mount.from_mount(mount)] + if instr: + instr.reset_nozzle_configuration() + async def add_tip(self, mount: OT3Mount, tip_length: float) -> None: instr = self._attached_instruments[mount] attached = self.attached_instruments @@ -724,7 +743,7 @@ def plan_ht_pick_up_tip(self) -> TipActionSpec: prep_move_speed=instrument.pick_up_configurations.prep_move_speed, clamp_move_speed=instrument.pick_up_configurations.speed, plunger_current=instrument.plunger_motor_current.run, - tip_motor_current=instrument.pick_up_configurations.current, + tip_motor_current=instrument.nozzle_manager.get_tip_configuration_current(), ) return TipActionSpec( @@ -775,7 +794,7 @@ def build_presses() -> List[TipActionMoveSpec]: currents={ Axis.by_mount( mount - ): instrument.pick_up_configurations.current + ): instrument.nozzle_manager.get_tip_configuration_current() }, ) ) diff --git a/api/src/opentrons/hardware_control/nozzle_manager.py b/api/src/opentrons/hardware_control/nozzle_manager.py new file mode 100644 index 00000000000..781d2c55bc8 --- /dev/null +++ b/api/src/opentrons/hardware_control/nozzle_manager.py @@ -0,0 +1,298 @@ +from typing import Dict, List, Optional, Any, Sequence +from typing_extensions import Final +from dataclasses import dataclass +from collections import OrderedDict +from enum import Enum + +from opentrons.hardware_control.types import CriticalPoint +from opentrons.types import Point +from opentrons_shared_data.errors import ( + ErrorCodes, + GeneralError, +) + +INTERNOZZLE_SPACING = 9 + + +class NozzleConfigurationType(Enum): + """ + Nozzle Configuration Type. + + Represents the current nozzle + configuration stored in NozzleMap + """ + + COLUMN = "COLUMN" + ROW = "ROW" + QUADRANT = "QUADRANT" + SINGLE = "SINGLE" + FULL = "FULL" + + @classmethod + def determine_nozzle_configuration( + cls, + nozzle_difference: Point, + physical_nozzlemap_length: int, + current_nozzlemap_length: int, + ) -> "NozzleConfigurationType": + """ + Determine the nozzle configuration based on the starting and + ending nozzle. + + :param nozzle_difference: the difference between the back + left and front right nozzle + :param physical_nozzlemap_length: integer representing the + length of the default physical configuration of the pipette. + :param current_nozzlemap_length: integer representing the + length of the current physical configuration of the pipette. + :return : nozzle configuration type + """ + if physical_nozzlemap_length == current_nozzlemap_length: + return NozzleConfigurationType.FULL + + if nozzle_difference == Point(0, 0, 0): + return NozzleConfigurationType.SINGLE + elif nozzle_difference[0] == 0: + return NozzleConfigurationType.COLUMN + elif nozzle_difference[1] == 0: + return NozzleConfigurationType.ROW + else: + return NozzleConfigurationType.QUADRANT + + +@dataclass +class NozzleMap: + """ + Nozzle Map. + + A data store class that can build + and store nozzle configurations + based on the physical default + nozzle map of the pipette and + the requested starting/ending tips. + """ + + back_left: str + front_right: str + starting_nozzle: str + map_store: Dict[str, Point] + configuration: NozzleConfigurationType + + def __str__(self) -> str: + return f"back_left_nozzle: {self.back_left} front_right_nozzle: {self.front_right} configuration: {self.configuration}" + + @property + def starting_nozzle_offset(self) -> Point: + return self.map_store[self.starting_nozzle] + + @property + def xy_center_offset(self) -> Point: + difference = self.map_store[self.front_right] - self.map_store[self.back_left] + return self.map_store[self.back_left] + Point( + difference[0] / 2, difference[1] / 2, 0 + ) + + @property + def front_nozzle_offset(self) -> Point: + # front left-most nozzle of the 96 channel in a given configuration + # and front nozzle of the 8 channel + if self.starting_nozzle == self.front_right: + return self.map_store[self.front_right] + map_store_list = list(self.map_store.values()) + starting_idx = map_store_list.index(self.map_store[self.back_left]) + difference = self.map_store[self.back_left] - self.map_store[self.front_right] + y_rows_length = int(difference[1] // INTERNOZZLE_SPACING) + return map_store_list[starting_idx + y_rows_length] + + @property + def tip_count(self) -> int: + return len(self.map_store) + + @classmethod + def build( + cls, + physical_nozzle_map: Dict[str, Point], + starting_nozzle: str, + back_left_nozzle: str, + front_right_nozzle: str, + origin_nozzle: Optional[str] = None, + ) -> "NozzleMap": + difference = ( + physical_nozzle_map[front_right_nozzle] + - physical_nozzle_map[back_left_nozzle] + ) + x_columns_length = int(abs(difference[0] // INTERNOZZLE_SPACING)) + 1 + y_rows_length = int(abs(difference[1] // INTERNOZZLE_SPACING)) + 1 + + map_store_list = list(physical_nozzle_map.items()) + + if origin_nozzle: + origin_difference = ( + physical_nozzle_map[back_left_nozzle] + - physical_nozzle_map[origin_nozzle] + ) + starting_col = int(abs(origin_difference[0] // INTERNOZZLE_SPACING)) + else: + starting_col = 0 + map_store = OrderedDict( + { + k: v + for i in range(x_columns_length) + for k, v in map_store_list[ + (i + starting_col) * 8 : y_rows_length * ((i + starting_col) + 1) + ] + } + ) + return cls( + back_left=back_left_nozzle, + front_right=front_right_nozzle, + starting_nozzle=starting_nozzle, + map_store=map_store, + configuration=NozzleConfigurationType.determine_nozzle_configuration( + difference, len(physical_nozzle_map), len(map_store) + ), + ) + + @staticmethod + def validate_nozzle_configuration( + back_left_nozzle: str, + front_right_nozzle: str, + default_configuration: "NozzleMap", + current_configuration: Optional["NozzleMap"] = None, + ) -> None: + """ + Validate nozzle configuration. + """ + if back_left_nozzle > front_right_nozzle: + raise IncompatibleNozzleConfiguration( + message=f"Back left nozzle {back_left_nozzle} provided is not to the back or left of {front_right_nozzle}.", + detail={ + "current_nozzle_configuration": current_configuration, + "requested_back_left_nozzle": back_left_nozzle, + "requested_front_right_nozzle": front_right_nozzle, + }, + ) + if not default_configuration.map_store.get(back_left_nozzle): + raise IncompatibleNozzleConfiguration( + message=f"Starting nozzle {back_left_nozzle} does not exist in the nozzle map.", + detail={ + "current_nozzle_configuration": current_configuration, + "requested_back_left_nozzle": back_left_nozzle, + "requested_front_right_nozzle": front_right_nozzle, + }, + ) + + if not default_configuration.map_store.get(front_right_nozzle): + raise IncompatibleNozzleConfiguration( + message=f"Ending nozzle {front_right_nozzle} does not exist in the nozzle map.", + detail={ + "current_nozzle_configuration": current_configuration, + "requested_back_left_nozzle": back_left_nozzle, + "requested_front_right_nozzle": front_right_nozzle, + }, + ) + + +class IncompatibleNozzleConfiguration(GeneralError): + """Error raised if nozzle configuration is incompatible with the currently loaded pipette.""" + + def __init__( + self, + message: Optional[str] = None, + detail: Optional[Dict[str, Any]] = None, + wrapping: Optional[Sequence[GeneralError]] = None, + ) -> None: + """Build a IncompatibleNozzleConfiguration error.""" + super().__init__( + code=ErrorCodes.API_MISCONFIGURATION, + message=message, + detail=detail, + wrapping=wrapping, + ) + + +class NozzleConfigurationManager: + def __init__( + self, + nozzle_map: NozzleMap, + pick_up_current_map: Dict[int, float], + ) -> None: + self._physical_nozzle_map = nozzle_map + self._current_nozzle_configuration = nozzle_map + self._pick_up_current_map: Final[Dict[int, float]] = pick_up_current_map + + @classmethod + def build_from_nozzlemap( + cls, + nozzle_map: Dict[str, List[float]], + pick_up_current_map: Dict[int, float], + ) -> "NozzleConfigurationManager": + + sorted_nozzlemap = list(nozzle_map.keys()) + sorted_nozzlemap.sort(key=lambda x: int(x[1::])) + nozzle_map_ordereddict: Dict[str, Point] = OrderedDict( + {k: Point(*nozzle_map[k]) for k in sorted_nozzlemap} + ) + first_nozzle = next(iter(list(nozzle_map_ordereddict.keys()))) + last_nozzle = next(reversed(list(nozzle_map_ordereddict.keys()))) + starting_nozzle_config = NozzleMap.build( + nozzle_map_ordereddict, + starting_nozzle=first_nozzle, + back_left_nozzle=first_nozzle, + front_right_nozzle=last_nozzle, + ) + return cls(starting_nozzle_config, pick_up_current_map) + + @property + def starting_nozzle_offset(self) -> Point: + return self._current_nozzle_configuration.starting_nozzle_offset + + @property + def current_configuration(self) -> NozzleMap: + return self._current_nozzle_configuration + + def reset_to_default_configuration(self) -> None: + self._current_nozzle_configuration = self._physical_nozzle_map + + def update_nozzle_configuration( + self, + back_left_nozzle: str, + front_right_nozzle: str, + starting_nozzle: Optional[str] = None, + ) -> None: + if ( + back_left_nozzle == self._physical_nozzle_map.back_left + and front_right_nozzle == self._physical_nozzle_map.front_right + ): + self._current_nozzle_configuration = self._physical_nozzle_map + else: + NozzleMap.validate_nozzle_configuration( + back_left_nozzle, + front_right_nozzle, + self._physical_nozzle_map, + self._current_nozzle_configuration, + ) + + self._current_nozzle_configuration = NozzleMap.build( + self._physical_nozzle_map.map_store, + starting_nozzle=starting_nozzle or back_left_nozzle, + back_left_nozzle=back_left_nozzle, + front_right_nozzle=front_right_nozzle, + origin_nozzle=self._physical_nozzle_map.starting_nozzle, + ) + + def get_tip_configuration_current(self) -> float: + return self._pick_up_current_map[self._current_nozzle_configuration.tip_count] + + def critical_point_with_tip_length( + self, + cp_override: Optional[CriticalPoint], + tip_length: float = 0.0, + ) -> Point: + if cp_override == CriticalPoint.XY_CENTER: + current_nozzle = self._current_nozzle_configuration.xy_center_offset + elif cp_override == CriticalPoint.FRONT_NOZZLE: + current_nozzle = self._current_nozzle_configuration.front_nozzle_offset + else: + current_nozzle = self.starting_nozzle_offset + return current_nozzle - Point(0, 0, tip_length) diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index d106308055c..1a2eb65e8a6 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -54,7 +54,7 @@ MoveTarget, ZeroLengthMoveError, ) - +from opentrons.hardware_control.nozzle_manager import NozzleConfigurationType from opentrons_hardware.hardware_control.motion import MoveStopCondition from opentrons_shared_data.errors.exceptions import ( EnumeratedError, @@ -2044,8 +2044,11 @@ def add_tip_to_instr() -> None: instrument.set_current_volume(0) await self._move_to_plunger_bottom(realmount, rate=1.0) - - if self.gantry_load == GantryLoad.HIGH_THROUGHPUT: + if ( + self.gantry_load == GantryLoad.HIGH_THROUGHPUT + and instrument.nozzle_manager.current_configuration.configuration + == NozzleConfigurationType.FULL + ): spec = self._pipette_handler.plan_ht_pick_up_tip() if spec.z_distance_to_tiprack: await self.move_rel( @@ -2365,6 +2368,41 @@ def get_instrument_max_height( return pos_at_home[Axis.by_mount(mount)] - self._config.z_retract_distance + async def update_nozzle_configuration_for_mount( + self, + mount: Union[top_types.Mount, OT3Mount], + back_left_nozzle: Optional[str] = None, + front_right_nozzle: Optional[str] = None, + starting_nozzle: Optional[str] = None, + ) -> None: + """ + The expectation of this function is that the back_left_nozzle/front_right_nozzle are the two corners + of a rectangle of nozzles. A call to this function that does not follow that schema will result + in an error. + + :param mount: A robot mount that the instrument is on. + :param back_left_nozzle: A string representing a nozzle name of the form such as 'A1'. + :param front_right_nozzle: A string representing a nozzle name of the form such as 'A1'. + :param starting_nozzle: A string representing the starting nozzle which will be used as the critical point + of the pipette nozzle configuration. By default, the back left nozzle will be the starting nozzle if + none is provided. + :return: None. + + If none of the nozzle parameters are provided, the nozzle configuration will be reset to default. + """ + if not back_left_nozzle and not front_right_nozzle and not starting_nozzle: + await self._pipette_handler.reset_nozzle_configuration( + OT3Mount.from_mount(mount) + ) + else: + assert back_left_nozzle and front_right_nozzle + await self._pipette_handler.update_nozzle_configuration( + OT3Mount.from_mount(mount), + back_left_nozzle, + front_right_nozzle, + starting_nozzle, + ) + async def add_tip( self, mount: Union[top_types.Mount, OT3Mount], tip_length: float ) -> None: diff --git a/api/src/opentrons/hardware_control/protocols/liquid_handler.py b/api/src/opentrons/hardware_control/protocols/liquid_handler.py index e25a25299ce..e46cea2fdc2 100644 --- a/api/src/opentrons/hardware_control/protocols/liquid_handler.py +++ b/api/src/opentrons/hardware_control/protocols/liquid_handler.py @@ -16,6 +16,30 @@ class LiquidHandler( Calibratable[CalibrationType], Protocol[CalibrationType], ): + async def update_nozzle_configuration_for_mount( + self, + mount: Mount, + back_left_nozzle: Optional[str], + front_right_nozzle: Optional[str], + starting_nozzle: Optional[str] = None, + ) -> None: + """ + The expectation of this function is that the back_left_nozzle/front_right_nozzle are the two corners + of a rectangle of nozzles. A call to this function that does not follow that schema will result + in an error. + + :param mount: A robot mount that the instrument is on. + :param back_left_nozzle: A string representing a nozzle name of the form such as 'A1'. + :param front_right_nozzle: A string representing a nozzle name of the form such as 'A1'. + :param starting_nozzle: A string representing the starting nozzle which will be used as the critical point + of the pipette nozzle configuration. By default, the back left nozzle will be the starting nozzle if + none is provided. + + If none of the nozzle parameters are provided, the nozzle configuration will be reset to default. + :return: None. + """ + ... + async def configure_for_volume(self, mount: Mount, volume: float) -> None: """ Configure a pipette to handle the specified volume. diff --git a/api/src/opentrons/protocol_api/__init__.py b/api/src/opentrons/protocol_api/__init__.py index c96fefba360..0d518bbf5c0 100644 --- a/api/src/opentrons/protocol_api/__init__.py +++ b/api/src/opentrons/protocol_api/__init__.py @@ -25,6 +25,10 @@ from ._liquid import Liquid from ._types import OFF_DECK from ._waste_chute import WasteChute +from ._nozzle_layout import ( + COLUMN, + EMPTY, +) from .create_protocol_context import ( create_protocol_context, @@ -48,6 +52,8 @@ "WasteChute", "Well", "Liquid", + "COLUMN", + "EMPTY", "OFF_DECK", # For internal Opentrons use only: "create_protocol_context", diff --git a/api/src/opentrons/protocol_api/_nozzle_layout.py b/api/src/opentrons/protocol_api/_nozzle_layout.py new file mode 100644 index 00000000000..45cabb24af6 --- /dev/null +++ b/api/src/opentrons/protocol_api/_nozzle_layout.py @@ -0,0 +1,27 @@ +from typing_extensions import Final +import enum + + +class NozzleLayout(enum.Enum): + COLUMN = "COLUMN" + SINGLE = "SINGLE" + ROW = "ROW" + QUADRANT = "QUADRANT" + EMPTY = "EMPTY" + + +COLUMN: Final = NozzleLayout.COLUMN +EMPTY: Final = NozzleLayout.EMPTY + +# Set __doc__ manually as a workaround. When this docstring is written the normal way, right after +# the constant definition, Sphinx has trouble picking it up. +COLUMN.__doc__ = """\ +A special nozzle configuration type indicating a full single column pick up. Predominantly meant for the 96 channel. + +See for details on using ``COLUMN`` with :py:obj:`InstrumentContext.configure_nozzle_layout()`. +""" +EMPTY.__doc__ = """\ +A special nozzle configuration type indicating a reset back to default where the pipette will pick up its max capacity of tips. + +See for details on using ``RESET`` with :py:obj:`InstrumentContext.configure_nozzle_layout()`. +""" diff --git a/api/src/opentrons/protocol_api/core/engine/instrument.py b/api/src/opentrons/protocol_api/core/engine/instrument.py index 79773c98264..0c762358c14 100644 --- a/api/src/opentrons/protocol_api/core/engine/instrument.py +++ b/api/src/opentrons/protocol_api/core/engine/instrument.py @@ -1,7 +1,7 @@ """ProtocolEngine-based InstrumentContext core implementation.""" from __future__ import annotations -from typing import Optional, TYPE_CHECKING +from typing import Optional, TYPE_CHECKING, cast from opentrons.types import Location, Mount from opentrons.hardware_control import SyncHardwareAPI @@ -14,6 +14,15 @@ WellLocation, WellOrigin, WellOffset, + EmptyNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + RowNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, +) +from opentrons.protocol_engine.types import ( + PRIMARY_NOZZLE_LITERAL, + NozzleLayoutConfigurationType, ) from opentrons.protocol_engine.errors.exceptions import TipNotAttachedError from opentrons.protocol_engine.clients import SyncClient as EngineClient @@ -21,6 +30,7 @@ from opentrons.types import Point, DeckSlotName from opentrons_shared_data.pipette.dev_types import PipetteNameType +from opentrons.protocol_api._nozzle_layout import NozzleLayout from ..instrument import AbstractInstrument from .well import WellCore @@ -587,3 +597,36 @@ def configure_for_volume(self, volume: float) -> None: def prepare_to_aspirate(self) -> None: self._engine_client.prepare_to_aspirate(pipette_id=self._pipette_id) + + def configure_nozzle_layout( + self, + style: NozzleLayout, + primary_nozzle: Optional[str], + front_right_nozzle: Optional[str], + ) -> None: + + if style == NozzleLayout.COLUMN: + configuration_model: NozzleLayoutConfigurationType = ( + ColumnNozzleLayoutConfiguration( + primary_nozzle=cast(PRIMARY_NOZZLE_LITERAL, primary_nozzle) + ) + ) + elif style == NozzleLayout.ROW: + configuration_model = RowNozzleLayoutConfiguration( + primary_nozzle=cast(PRIMARY_NOZZLE_LITERAL, primary_nozzle) + ) + elif style == NozzleLayout.QUADRANT: + assert front_right_nozzle is not None + configuration_model = QuadrantNozzleLayoutConfiguration( + primary_nozzle=cast(PRIMARY_NOZZLE_LITERAL, primary_nozzle), + front_right_nozzle=front_right_nozzle, + ) + elif style == NozzleLayout.SINGLE: + configuration_model = SingleNozzleLayoutConfiguration( + primary_nozzle=cast(PRIMARY_NOZZLE_LITERAL, primary_nozzle) + ) + else: + configuration_model = EmptyNozzleLayoutConfiguration() + self._engine_client.configure_nozzle_layout( + pipette_id=self._pipette_id, configuration_params=configuration_model + ) diff --git a/api/src/opentrons/protocol_api/core/instrument.py b/api/src/opentrons/protocol_api/core/instrument.py index bcec7f9c0f6..6429e253c2e 100644 --- a/api/src/opentrons/protocol_api/core/instrument.py +++ b/api/src/opentrons/protocol_api/core/instrument.py @@ -8,6 +8,7 @@ from opentrons import types from opentrons.hardware_control.dev_types import PipetteDict from opentrons.protocols.api_support.util import FlowRates +from opentrons.protocol_api._nozzle_layout import NozzleLayout from .._waste_chute import WasteChute from .well import WellCoreType @@ -247,5 +248,20 @@ def prepare_to_aspirate(self) -> None: """Prepare the pipette to aspirate.""" ... + def configure_nozzle_layout( + self, + style: NozzleLayout, + primary_nozzle: Optional[str], + front_right_nozzle: Optional[str], + ) -> None: + """Configure the pipette to a specific nozzle layout. + + Args: + style: The type of configuration you wish to build. + primary_nozzle: The nozzle that will determine a pipettes critical point. + front_right_nozzle: The front right most nozzle in the requested layout. + """ + ... + InstrumentCoreType = TypeVar("InstrumentCoreType", bound=AbstractInstrument[Any]) diff --git a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py index b9e661a9fce..5ce5fd595c9 100644 --- a/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy/legacy_instrument_core.py @@ -17,6 +17,7 @@ APIVersionError, ) from opentrons.protocols.geometry import planning +from opentrons.protocol_api._nozzle_layout import NozzleLayout from ..._waste_chute import WasteChute from ..instrument import AbstractInstrument @@ -519,3 +520,12 @@ def flag_unsafe_move(self, location: types.Location) -> None: def configure_for_volume(self, volume: float) -> None: """This will never be called because it was added in API 2.15.""" pass + + def configure_nozzle_layout( + self, + style: NozzleLayout, + primary_nozzle: Optional[str], + front_right_nozzle: Optional[str], + ) -> None: + """This will never be called because it was added in API 2.15.""" + pass diff --git a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py index ab90676c27e..27ed2a5d438 100644 --- a/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py +++ b/api/src/opentrons/protocol_api/core/legacy_simulator/legacy_instrument_core.py @@ -22,6 +22,7 @@ ) from ..._waste_chute import WasteChute +from opentrons.protocol_api._nozzle_layout import NozzleLayout from ..instrument import AbstractInstrument @@ -435,3 +436,12 @@ def _raise_if_tip(self, action: str) -> None: def configure_for_volume(self, volume: float) -> None: """This will never be called because it was added in API 2.15.""" pass + + def configure_nozzle_layout( + self, + style: NozzleLayout, + primary_nozzle: Optional[str], + front_right_nozzle: Optional[str], + ) -> None: + """This will never be called because it was added in API 2.15.""" + pass diff --git a/api/src/opentrons/protocol_api/instrument_context.py b/api/src/opentrons/protocol_api/instrument_context.py index 9f03645f69d..64cef355d7f 100644 --- a/api/src/opentrons/protocol_api/instrument_context.py +++ b/api/src/opentrons/protocol_api/instrument_context.py @@ -33,6 +33,7 @@ from .core.legacy.legacy_instrument_core import LegacyInstrumentCore from .config import Clearances from ._waste_chute import WasteChute +from ._nozzle_layout import NozzleLayout from . import labware, validation @@ -1658,3 +1659,57 @@ def prepare_to_aspirate(self) -> None: message=f"Cannot prepare {str(self)} for aspirate while it contains liquid." ) self._core.prepare_to_aspirate() + + def configure_nozzle_layout( + self, + style: NozzleLayout, + start: Optional[str] = None, + front_right: Optional[str] = None, + ) -> None: + """Configure a pipette to pick up less than the maximum tip capacity. The pipette + will remain in its partial state until this function is called again without any inputs. All subsequent + pipetting calls will execute with the new nozzle layout meaning that the pipette will perform + robot moves in the set nozzle layout. + + :param style: The requested nozzle layout should specify the shape that you + wish to configure your pipette to. Certain pipettes are restricted to a subset of `NozzleLayout` + types. See the note below on the different `NozzleLayout` types. + :type requested_nozzle_layout: `NozzleLayout.COLUMN`, `NozzleLayout.EMPTY` or None. + :param start: Signifies the nozzle that the robot will use to determine how to perform moves to different locations on the deck. + :type start: string or None. + :param front_right: Signifies the ending nozzle in your partial configuration. It is not required for NozzleLayout.COLUMN, NozzleLayout.ROW, or NozzleLayout.SINGLE + configurations. + :type front_right: string or None. + + .. note:: + Your `start` and `front_right` strings should be formatted similarly to a well, so in the format of . + The pipette nozzles are mapped in the same format as a 96 well standard plate starting from the back left-most nozzle + to the front right-most nozzle. + + .. code-block:: python + + from opentrons.protocol_api import COLUMN, EMPTY + + # Sets a pipette to a full single column pickup using "A1" as the primary nozzle. Implicitly, "H1" is the ending nozzle. + instr.configure_nozzle_layout(style=COLUMN, start="A1") + + # Resets the pipette configuration to default + instr.configure_nozzle_layout(style=EMPTY) + """ + if style != NozzleLayout.EMPTY: + if start is None: + raise ValueError( + f"Cannot configure a nozzle layout of style {style.value} without a starting nozzle." + ) + if start not in types.ALLOWED_PRIMARY_NOZZLES: + raise ValueError( + f"Starting nozzle specified is not of {types.ALLOWED_PRIMARY_NOZZLES}" + ) + if style == NozzleLayout.QUADRANT: + if front_right is None: + raise ValueError( + "Cannot configure a QUADRANT layout without a front right nozzle." + ) + self._core.configure_nozzle_layout( + style, primary_nozzle=start, front_right_nozzle=front_right + ) diff --git a/api/src/opentrons/protocol_engine/__init__.py b/api/src/opentrons/protocol_engine/__init__.py index a975b497332..253e88dc33f 100644 --- a/api/src/opentrons/protocol_engine/__init__.py +++ b/api/src/opentrons/protocol_engine/__init__.py @@ -52,6 +52,11 @@ ModuleModel, ModuleDefinition, Liquid, + EmptyNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + RowNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, ) @@ -105,6 +110,11 @@ "ModuleModel", "ModuleDefinition", "Liquid", + "EmptyNozzleLayoutConfiguration", + "SingleNozzleLayoutConfiguration", + "RowNozzleLayoutConfiguration", + "ColumnNozzleLayoutConfiguration", + "QuadrantNozzleLayoutConfiguration", # plugins "AbstractPlugin", ] diff --git a/api/src/opentrons/protocol_engine/clients/sync_client.py b/api/src/opentrons/protocol_engine/clients/sync_client.py index cfef710a5ce..1982ad66fa1 100644 --- a/api/src/opentrons/protocol_engine/clients/sync_client.py +++ b/api/src/opentrons/protocol_engine/clients/sync_client.py @@ -23,6 +23,7 @@ LabwareOffsetVector, MotorAxis, Liquid, + NozzleLayoutConfigurationType, ) from .transports import ChildThreadTransport @@ -292,6 +293,20 @@ def prepare_to_aspirate(self, pipette_id: str) -> commands.PrepareToAspirateResu result = self._transport.execute_command(request=request) return cast(commands.PrepareToAspirateResult, result) + def configure_nozzle_layout( + self, + pipette_id: str, + configuration_params: NozzleLayoutConfigurationType, + ) -> commands.ConfigureNozzleLayoutResult: + """Execute a ConfigureForVolume command.""" + request = commands.ConfigureNozzleLayoutCreate( + params=commands.ConfigureNozzleLayoutParams( + pipetteId=pipette_id, configuration_params=configuration_params + ) + ) + result = self._transport.execute_command(request=request) + return cast(commands.ConfigureNozzleLayoutResult, result) + def aspirate( self, pipette_id: str, diff --git a/api/src/opentrons/protocol_engine/commands/__init__.py b/api/src/opentrons/protocol_engine/commands/__init__.py index 85b25046479..60c5e8350ea 100644 --- a/api/src/opentrons/protocol_engine/commands/__init__.py +++ b/api/src/opentrons/protocol_engine/commands/__init__.py @@ -274,6 +274,14 @@ PrepareToAspirateCommandType, ) +from .configure_nozzle_layout import ( + ConfigureNozzleLayout, + ConfigureNozzleLayoutCreate, + ConfigureNozzleLayoutParams, + ConfigureNozzleLayoutResult, + ConfigureNozzleLayoutCommandType, +) + __all__ = [ # command type unions "Command", @@ -477,4 +485,10 @@ "PrepareToAspirateParams", "PrepareToAspirateResult", "PrepareToAspirateCommandType", + # configure nozzle layout command bundle + "ConfigureNozzleLayout", + "ConfigureNozzleLayoutCreate", + "ConfigureNozzleLayoutParams", + "ConfigureNozzleLayoutResult", + "ConfigureNozzleLayoutCommandType", ] diff --git a/api/src/opentrons/protocol_engine/commands/command_unions.py b/api/src/opentrons/protocol_engine/commands/command_unions.py index bf9ff6b7768..4387a9178ec 100644 --- a/api/src/opentrons/protocol_engine/commands/command_unions.py +++ b/api/src/opentrons/protocol_engine/commands/command_unions.py @@ -243,6 +243,15 @@ PrepareToAspirateCommandType, ) +from .configure_nozzle_layout import ( + ConfigureNozzleLayout, + ConfigureNozzleLayoutCreate, + ConfigureNozzleLayoutParams, + ConfigureNozzleLayoutResult, + ConfigureNozzleLayoutCommandType, + ConfigureNozzleLayoutPrivateResult, +) + Command = Union[ Aspirate, AspirateInPlace, @@ -253,6 +262,7 @@ BlowOut, BlowOutInPlace, ConfigureForVolume, + ConfigureNozzleLayout, DropTip, DropTipInPlace, Home, @@ -305,6 +315,7 @@ AspirateInPlaceParams, CommentParams, ConfigureForVolumeParams, + ConfigureNozzleLayoutParams, CustomParams, DispenseParams, DispenseInPlaceParams, @@ -363,6 +374,7 @@ AspirateInPlaceCommandType, CommentCommandType, ConfigureForVolumeCommandType, + ConfigureNozzleLayoutCommandType, CustomCommandType, DispenseCommandType, DispenseInPlaceCommandType, @@ -420,6 +432,7 @@ AspirateInPlaceCreate, CommentCreate, ConfigureForVolumeCreate, + ConfigureNozzleLayoutCreate, CustomCreate, DispenseCreate, DispenseInPlaceCreate, @@ -477,6 +490,7 @@ AspirateInPlaceResult, CommentResult, ConfigureForVolumeResult, + ConfigureNozzleLayoutResult, CustomResult, DispenseResult, DispenseInPlaceResult, @@ -530,5 +544,8 @@ ] CommandPrivateResult = Union[ - None, LoadPipettePrivateResult, ConfigureForVolumePrivateResult + None, + LoadPipettePrivateResult, + ConfigureForVolumePrivateResult, + ConfigureNozzleLayoutPrivateResult, ] diff --git a/api/src/opentrons/protocol_engine/commands/configure_nozzle_layout.py b/api/src/opentrons/protocol_engine/commands/configure_nozzle_layout.py new file mode 100644 index 00000000000..2ad5f38a9a5 --- /dev/null +++ b/api/src/opentrons/protocol_engine/commands/configure_nozzle_layout.py @@ -0,0 +1,111 @@ +"""Configure nozzle layout command request, result, and implementation models.""" +from __future__ import annotations +from pydantic import BaseModel +from typing import TYPE_CHECKING, Optional, Type, Tuple, Union +from typing_extensions import Literal + +from .pipetting_common import ( + PipetteIdMixin, +) +from .command import ( + AbstractCommandWithPrivateResultImpl, + BaseCommand, + BaseCommandCreate, +) +from .configuring_common import ( + PipetteNozzleLayoutResultMixin, +) +from ..types import ( + EmptyNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + RowNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, +) + +if TYPE_CHECKING: + from ..execution import EquipmentHandler, TipHandler + + +ConfigureNozzleLayoutCommandType = Literal["configureNozzleLayout"] + + +class ConfigureNozzleLayoutParams(PipetteIdMixin): + """Parameters required to configure the nozzle layout for a specific pipette.""" + + configuration_params: Union[ + EmptyNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + RowNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, + ] + + +class ConfigureNozzleLayoutPrivateResult(PipetteNozzleLayoutResultMixin): + """Result sent to the store but not serialized.""" + + pass + + +class ConfigureNozzleLayoutResult(BaseModel): + """Result data from execution of an configureNozzleLayout command.""" + + pass + + +class ConfigureNozzleLayoutImplementation( + AbstractCommandWithPrivateResultImpl[ + ConfigureNozzleLayoutParams, + ConfigureNozzleLayoutResult, + ConfigureNozzleLayoutPrivateResult, + ] +): + """Configure nozzle layout command implementation.""" + + def __init__( + self, equipment: EquipmentHandler, tip_handler: TipHandler, **kwargs: object + ) -> None: + self._equipment = equipment + self._tip_handler = tip_handler + + async def execute( + self, params: ConfigureNozzleLayoutParams + ) -> Tuple[ConfigureNozzleLayoutResult, ConfigureNozzleLayoutPrivateResult]: + """Check that requested pipette can support the requested nozzle layout.""" + nozzle_params = await self._tip_handler.available_for_nozzle_layout( + pipette_id=params.pipetteId, **params.configuration_params.dict() + ) + + nozzle_map = await self._equipment.configure_nozzle_layout( + pipette_id=params.pipetteId, + **nozzle_params, + ) + + return ConfigureNozzleLayoutResult(), ConfigureNozzleLayoutPrivateResult( + pipette_id=params.pipetteId, + nozzle_map=nozzle_map, + ) + + +class ConfigureNozzleLayout( + BaseCommand[ConfigureNozzleLayoutParams, ConfigureNozzleLayoutResult] +): + """Configure nozzle layout command model.""" + + commandType: ConfigureNozzleLayoutCommandType = "configureNozzleLayout" + params: ConfigureNozzleLayoutParams + result: Optional[ConfigureNozzleLayoutResult] + + _ImplementationCls: Type[ + ConfigureNozzleLayoutImplementation + ] = ConfigureNozzleLayoutImplementation + + +class ConfigureNozzleLayoutCreate(BaseCommandCreate[ConfigureNozzleLayoutParams]): + """Configure nozzle layout creation request model.""" + + commandType: ConfigureNozzleLayoutCommandType = "configureNozzleLayout" + params: ConfigureNozzleLayoutParams + + _CommandCls: Type[ConfigureNozzleLayout] = ConfigureNozzleLayout diff --git a/api/src/opentrons/protocol_engine/commands/configuring_common.py b/api/src/opentrons/protocol_engine/commands/configuring_common.py index a4ff8917310..ec5917d9931 100644 --- a/api/src/opentrons/protocol_engine/commands/configuring_common.py +++ b/api/src/opentrons/protocol_engine/commands/configuring_common.py @@ -1,6 +1,11 @@ """Common configuration command base models.""" +from pydantic import BaseModel, Field +from typing import Optional from dataclasses import dataclass +from opentrons.hardware_control.nozzle_manager import ( + NozzleMap, +) from ..resources import pipette_data_provider @@ -11,3 +16,13 @@ class PipetteConfigUpdateResultMixin: pipette_id: str serial_number: str config: pipette_data_provider.LoadedStaticPipetteData + + +class PipetteNozzleLayoutResultMixin(BaseModel): + """A nozzle layout result for updating the pipette state.""" + + pipette_id: str + nozzle_map: Optional[NozzleMap] = Field( + default=None, + description="A dataclass object holding information about the current nozzle configuration.", + ) diff --git a/api/src/opentrons/protocol_engine/execution/equipment.py b/api/src/opentrons/protocol_engine/execution/equipment.py index d15e2ec7e17..b3361510ec2 100644 --- a/api/src/opentrons/protocol_engine/execution/equipment.py +++ b/api/src/opentrons/protocol_engine/execution/equipment.py @@ -15,6 +15,7 @@ TempDeck, Thermocycler, ) +from opentrons.hardware_control.nozzle_manager import NozzleMap from opentrons.protocol_engine.state.module_substates import ( MagneticModuleId, HeaterShakerModuleId, @@ -387,6 +388,55 @@ async def configure_for_volume( static_config=static_pipette_config, ) + async def configure_nozzle_layout( + self, + pipette_id: str, + primary_nozzle: Optional[str] = None, + front_right_nozzle: Optional[str] = None, + back_left_nozzle: Optional[str] = None, + ) -> Optional[NozzleMap]: + """Ensure the requested nozzle layout is compatible with the current pipette. + + Args: + pipette_id: The identifier for the pipette. + primary_nozzle: The nozzle which will be used as the + front_right_nozzle + back_left_nozzle + + Returns: + A NozzleMap object or None. + """ + use_virtual_pipettes = self._state_store.config.use_virtual_pipettes + + if not use_virtual_pipettes: + mount = self._state_store.pipettes.get_mount(pipette_id).to_hw_mount() + + await self._hardware_api.update_nozzle_configuration_for_mount( + mount, + back_left_nozzle if back_left_nozzle else primary_nozzle, + front_right_nozzle if front_right_nozzle else primary_nozzle, + primary_nozzle if back_left_nozzle else None, + ) + pipette_dict = self._hardware_api.get_attached_instrument(mount) + nozzle_map = pipette_dict["current_nozzle_map"] + + else: + model = self._state_store.pipettes.get_model_name(pipette_id) + self._virtual_pipette_data_provider.configure_virtual_pipette_nozzle_layout( + pipette_id, + model, + back_left_nozzle if back_left_nozzle else primary_nozzle, + front_right_nozzle if front_right_nozzle else primary_nozzle, + primary_nozzle if back_left_nozzle else None, + ) + nozzle_map = ( + self._virtual_pipette_data_provider.get_nozzle_layout_for_pipette( + pipette_id + ) + ) + + return nozzle_map + @overload def get_module_hardware_api( self, diff --git a/api/src/opentrons/protocol_engine/execution/tip_handler.py b/api/src/opentrons/protocol_engine/execution/tip_handler.py index b007545edd2..4ea54df86fa 100644 --- a/api/src/opentrons/protocol_engine/execution/tip_handler.py +++ b/api/src/opentrons/protocol_engine/execution/tip_handler.py @@ -1,17 +1,43 @@ """Tip pickup and drop procedures.""" -from typing import Optional +from typing import Optional, Dict from typing_extensions import Protocol as TypingProtocol from opentrons.hardware_control import HardwareControlAPI +from opentrons_shared_data.errors.exceptions import ( + CommandPreconditionViolated, + CommandParameterLimitViolated, +) from ..resources import LabwareDataProvider from ..state import StateView from ..types import TipGeometry +PRIMARY_NOZZLE_TO_ENDING_NOZZLE_MAP = { + "A1": {"COLUMN": "H1", "ROW": "A12"}, + "H1": {"COLUMN": "A1", "ROW": "H12"}, + "A12": {"COLUMN": "H12", "ROW": "A1"}, + "H12": {"COLUMN": "A12", "ROW": "H1"}, +} + + class TipHandler(TypingProtocol): """Pick up and drop tips.""" + async def available_for_nozzle_layout( + self, + pipette_id: str, + style: str, + primary_nozzle: Optional[str] = None, + front_right_nozzle: Optional[str] = None, + ) -> Dict[str, str]: + """Check nozzle layout is compatible with the pipette. + + Returns: + A dict of nozzles used to configure the pipette. + """ + ... + async def pick_up_tip( self, pipette_id: str, @@ -50,6 +76,48 @@ def __init__( self._hardware_api = hardware_api self._labware_data_provider = labware_data_provider or LabwareDataProvider() + async def available_for_nozzle_layout( + self, + pipette_id: str, + style: str, + primary_nozzle: Optional[str] = None, + front_right_nozzle: Optional[str] = None, + ) -> Dict[str, str]: + """Check nozzle layout is compatible with the pipette.""" + if self._state_view.pipettes.get_attached_tip(pipette_id): + raise CommandPreconditionViolated( + message=f"Cannot configure nozzle layout of {str(self)} while it has tips attached." + ) + channels = self._state_view.pipettes.get_channels(pipette_id) + if channels == 1: + raise CommandPreconditionViolated( + message=f"Cannot configure nozzle layout with a {channels} channel pipette." + ) + if style == "EMPTY": + return {} + if style == "ROW" and channels == 8: + raise CommandParameterLimitViolated( + command_name="configure_nozzle_layout", + parameter_name="RowNozzleLayout", + limit_statement="RowNozzleLayout is incompatible with {channels} channel pipettes.", + actual_value=str(primary_nozzle), + ) + if not primary_nozzle: + return {"primary_nozzle": "A1"} + if style == "SINGLE": + return {"primary_nozzle": primary_nozzle} + if not front_right_nozzle: + return { + "primary_nozzle": primary_nozzle, + "front_right_nozzle": PRIMARY_NOZZLE_TO_ENDING_NOZZLE_MAP[ + primary_nozzle + ][style], + } + return { + "primary_nozzle": primary_nozzle, + "front_right_nozzle": front_right_nozzle, + } + async def pick_up_tip( self, pipette_id: str, @@ -128,6 +196,48 @@ class VirtualTipHandler(TipHandler): def __init__(self, state_view: StateView) -> None: self._state_view = state_view + async def available_for_nozzle_layout( + self, + pipette_id: str, + style: str, + primary_nozzle: Optional[str] = None, + front_right_nozzle: Optional[str] = None, + ) -> Dict[str, str]: + """Check nozzle layout is compatible with the pipette.""" + if self._state_view.pipettes.get_attached_tip(pipette_id): + raise CommandPreconditionViolated( + message=f"Cannot configure nozzle layout of {str(self)} while it has tips attached." + ) + channels = self._state_view.pipettes.get_channels(pipette_id) + if channels == 1: + raise CommandPreconditionViolated( + message=f"Cannot configure nozzle layout with a {channels} channel pipette." + ) + if style == "EMPTY": + return {} + if style == "ROW" and channels == 8: + raise CommandParameterLimitViolated( + command_name="configure_nozzle_layout", + parameter_name="RowNozzleLayout", + limit_statement="RowNozzleLayout is incompatible with {channels} channel pipettes.", + actual_value=str(primary_nozzle), + ) + if not primary_nozzle: + return {"primary_nozzle": "A1"} + if style == "SINGLE": + return {"primary_nozzle": primary_nozzle} + if not front_right_nozzle: + return { + "primary_nozzle": primary_nozzle, + "front_right_nozzle": PRIMARY_NOZZLE_TO_ENDING_NOZZLE_MAP[ + primary_nozzle + ][style], + } + return { + "primary_nozzle": primary_nozzle, + "front_right_nozzle": front_right_nozzle, + } + async def pick_up_tip( self, pipette_id: str, diff --git a/api/src/opentrons/protocol_engine/resources/pipette_data_provider.py b/api/src/opentrons/protocol_engine/resources/pipette_data_provider.py index 086c670fb5d..818566e3691 100644 --- a/api/src/opentrons/protocol_engine/resources/pipette_data_provider.py +++ b/api/src/opentrons/protocol_engine/resources/pipette_data_provider.py @@ -1,6 +1,6 @@ """Pipette config data providers.""" from dataclasses import dataclass -from typing import Dict +from typing import Dict, Optional from opentrons_shared_data.pipette.dev_types import PipetteName, PipetteModel from opentrons_shared_data.pipette import ( @@ -12,6 +12,10 @@ from opentrons.hardware_control.dev_types import PipetteDict +from opentrons.hardware_control.nozzle_manager import ( + NozzleConfigurationManager, + NozzleMap, +) from ..types import FlowRates @@ -40,6 +44,39 @@ class VirtualPipetteDataProvider: def __init__(self) -> None: """Build a VirtualPipetteDataProvider.""" self._liquid_class_by_id: Dict[str, pip_types.LiquidClasses] = {} + self._nozzle_manager_layout_by_id: Dict[str, NozzleConfigurationManager] = {} + + def configure_virtual_pipette_nozzle_layout( + self, + pipette_id: str, + pipette_model_string: str, + back_left_nozzle: Optional[str] = None, + front_right_nozzle: Optional[str] = None, + starting_nozzle: Optional[str] = None, + ) -> None: + """Emulate update_nozzle_configuration_for_mount.""" + if pipette_id not in self._nozzle_manager_layout_by_id: + config = self._get_virtual_pipette_full_config_by_model_string( + pipette_model_string + ) + new_nozzle_manager = NozzleConfigurationManager.build_from_nozzlemap( + config.nozzle_map, + config.partial_tip_configurations.per_tip_pickup_current, + ) + if back_left_nozzle and front_right_nozzle and starting_nozzle: + new_nozzle_manager.update_nozzle_configuration( + back_left_nozzle, front_right_nozzle, starting_nozzle + ) + self._nozzle_manager_layout_by_id[pipette_id] = new_nozzle_manager + elif back_left_nozzle and front_right_nozzle and starting_nozzle: + # Need to make sure that we pass all the right nozzles here. + self._nozzle_manager_layout_by_id[pipette_id].update_nozzle_configuration( + back_left_nozzle, front_right_nozzle, starting_nozzle + ) + else: + self._nozzle_manager_layout_by_id[ + pipette_id + ].reset_to_default_configuration() def configure_virtual_pipette_for_volume( self, pipette_id: str, volume: float, pipette_model_string: str @@ -61,6 +98,10 @@ def configure_virtual_pipette_for_volume( ) self._liquid_class_by_id[pipette_id] = liquid_class + def get_nozzle_layout_for_pipette(self, pipette_id: str) -> NozzleMap: + """Get the current nozzle layout stored for a virtual pipette.""" + return self._nozzle_manager_layout_by_id[pipette_id].current_configuration + def get_virtual_pipette_static_config_by_model_string( self, pipette_model_string: str, pipette_id: str ) -> LoadedStaticPipetteData: @@ -72,6 +113,19 @@ def get_virtual_pipette_static_config_by_model_string( pipette_model, pipette_id ) + def _get_virtual_pipette_full_config_by_model_string( + self, pipette_model_string: str + ) -> pipette_definition.PipetteConfigurations: + """Get the full pipette config from a model string.""" + pipette_model = pipette_load_name.convert_pipette_model( + PipetteModel(pipette_model_string) + ) + return load_pipette_data.load_definition( + pipette_model.pipette_type, + pipette_model.pipette_channels, + pipette_model.pipette_version, + ) + def _get_virtual_pipette_static_config_by_model( self, pipette_model: pipette_definition.PipetteModelVersionType, pipette_id: str ) -> LoadedStaticPipetteData: diff --git a/api/src/opentrons/protocol_engine/state/pipettes.py b/api/src/opentrons/protocol_engine/state/pipettes.py index 8c8d7a366cb..4d1f7278971 100644 --- a/api/src/opentrons/protocol_engine/state/pipettes.py +++ b/api/src/opentrons/protocol_engine/state/pipettes.py @@ -6,6 +6,10 @@ from opentrons_shared_data.pipette import pipette_definition from opentrons.config.defaults_ot2 import Z_RETRACT_DISTANCE from opentrons.hardware_control.dev_types import PipetteDict +from opentrons.hardware_control.nozzle_manager import ( + NozzleConfigurationType, + NozzleMap, +) from opentrons.types import MountType, Mount as HwMount from .. import errors @@ -39,7 +43,10 @@ CommandPrivateResult, PrepareToAspirateResult, ) -from ..commands.configuring_common import PipetteConfigUpdateResultMixin +from ..commands.configuring_common import ( + PipetteConfigUpdateResultMixin, + PipetteNozzleLayoutResultMixin, +) from ..actions import ( Action, SetPipetteMovementSpeedAction, @@ -94,6 +101,7 @@ class PipetteState: movement_speed_by_id: Dict[str, Optional[float]] static_config_by_id: Dict[str, StaticPipetteConfig] flow_rates_by_id: Dict[str, FlowRates] + nozzle_configuration_by_id: Dict[str, Optional[NozzleMap]] class PipetteStore(HasState[PipetteState], HandlesActions): @@ -112,6 +120,7 @@ def __init__(self) -> None: movement_speed_by_id={}, static_config_by_id={}, flow_rates_by_id={}, + nozzle_configuration_by_id={}, ) def handle_action(self, action: Action) -> None: @@ -144,6 +153,10 @@ def _handle_command( # noqa: C901 nozzle_offset_z=config.nozzle_offset_z, ) self._state.flow_rates_by_id[private_result.pipette_id] = config.flow_rates + elif isinstance(private_result, PipetteNozzleLayoutResultMixin): + self._state.nozzle_configuration_by_id[ + private_result.pipette_id + ] = private_result.nozzle_map if isinstance(command.result, LoadPipetteResult): pipette_id = command.result.pipetteId @@ -156,6 +169,7 @@ def _handle_command( # noqa: C901 self._state.aspirated_volume_by_id[pipette_id] = None self._state.movement_speed_by_id[pipette_id] = None self._state.attached_tip_by_id[pipette_id] = None + self._state.nozzle_configuration_by_id[pipette_id] = None elif isinstance(command.result, AspirateResult): pipette_id = command.params.pipetteId @@ -535,6 +549,10 @@ def get_serial_number(self, pipette_id: str) -> str: """Get the serial number of the pipette.""" return self.get_config(pipette_id).serial_number + def get_channels(self, pipette_id: str) -> int: + """Return the max channels of the pipette.""" + return self.get_config(pipette_id).channels + def get_minimum_volume(self, pipette_id: str) -> float: """Return the given pipette's minimum volume.""" return self.get_config(pipette_id).min_volume @@ -597,3 +615,11 @@ def get_plunger_axis(self, pipette_id: str) -> MotorAxis: if mount == MountType.LEFT else MotorAxis.RIGHT_PLUNGER ) + + def get_nozzle_layout_type(self, pipette_id: str) -> NozzleConfigurationType: + """Get the current set nozzle layout configuration.""" + nozzle_map_for_pipette = self._state.nozzle_configuration_by_id.get(pipette_id) + if nozzle_map_for_pipette: + return nozzle_map_for_pipette.configuration + else: + return NozzleConfigurationType.FULL diff --git a/api/src/opentrons/protocol_engine/types.py b/api/src/opentrons/protocol_engine/types.py index 228cb066aaf..b00e8ee1af6 100644 --- a/api/src/opentrons/protocol_engine/types.py +++ b/api/src/opentrons/protocol_engine/types.py @@ -662,3 +662,67 @@ class PostRunHardwareState(Enum): HOME_THEN_DISENGAGE = "homeThenDisengage" STAY_ENGAGED_IN_PLACE = "stayEngagedInPlace" DISENGAGE_IN_PLACE = "disengageInPlace" + + +NOZZLE_NAME_REGEX = "[A-Z][0-100]" +PRIMARY_NOZZLE_LITERAL = Literal["A1", "H1", "A12", "H12"] + + +class EmptyNozzleLayoutConfiguration(BaseModel): + """Empty basemodel to represent a reset to the nozzle configuration. Sending no parameters resets to default.""" + + style: Literal["EMPTY"] = "EMPTY" + + +class SingleNozzleLayoutConfiguration(BaseModel): + """Minimum information required for a new nozzle configuration.""" + + style: Literal["SINGLE"] = "SINGLE" + primary_nozzle: PRIMARY_NOZZLE_LITERAL = Field( + ..., + description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + ) + + +class RowNozzleLayoutConfiguration(BaseModel): + """Minimum information required for a new nozzle configuration.""" + + style: Literal["ROW"] = "ROW" + primary_nozzle: PRIMARY_NOZZLE_LITERAL = Field( + ..., + description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + ) + + +class ColumnNozzleLayoutConfiguration(BaseModel): + """Information required for nozzle configurations of type ROW and COLUMN.""" + + style: Literal["COLUMN"] = "COLUMN" + primary_nozzle: PRIMARY_NOZZLE_LITERAL = Field( + ..., + description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + ) + + +class QuadrantNozzleLayoutConfiguration(BaseModel): + """Information required for nozzle configurations of type QUADRANT.""" + + style: Literal["QUADRANT"] = "QUADRANT" + primary_nozzle: PRIMARY_NOZZLE_LITERAL = Field( + ..., + description="The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + ) + front_right_nozzle: str = Field( + ..., + regex=NOZZLE_NAME_REGEX, + description="The front right nozzle in your configuration.", + ) + + +NozzleLayoutConfigurationType = Union[ + EmptyNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + RowNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, +] diff --git a/api/src/opentrons/types.py b/api/src/opentrons/types.py index fbfe2dab403..6c8eb06f027 100644 --- a/api/src/opentrons/types.py +++ b/api/src/opentrons/types.py @@ -364,3 +364,4 @@ class TransferTipPolicy(enum.Enum): DeckLocation = Union[int, str] +ALLOWED_PRIMARY_NOZZLES = ["A1", "H1", "A12", "H12"] diff --git a/api/tests/opentrons/hardware_control/instruments/test_nozzle_manager.py b/api/tests/opentrons/hardware_control/instruments/test_nozzle_manager.py new file mode 100644 index 00000000000..1761e59a6ec --- /dev/null +++ b/api/tests/opentrons/hardware_control/instruments/test_nozzle_manager.py @@ -0,0 +1,199 @@ +import pytest +from typing import Dict, List, ContextManager, Tuple + +from contextlib import nullcontext as does_not_raise +from opentrons.hardware_control import nozzle_manager + +from opentrons.types import Point +from opentrons.hardware_control.types import CriticalPoint + + +def build_nozzle_manger( + nozzle_map: Dict[str, List[float]] +) -> nozzle_manager.NozzleConfigurationManager: + return nozzle_manager.NozzleConfigurationManager.build_from_nozzlemap( + nozzle_map, pick_up_current_map={1: 0.1} + ) + + +NINETY_SIX_CHANNEL_MAP = { + "A1": [-36.0, -25.5, -259.15], + "A2": [-27.0, -25.5, -259.15], + "A3": [-18.0, -25.5, -259.15], + "A4": [-9.0, -25.5, -259.15], + "A5": [0.0, -25.5, -259.15], + "A6": [9.0, -25.5, -259.15], + "A7": [18.0, -25.5, -259.15], + "A8": [27.0, -25.5, -259.15], + "A9": [36.0, -25.5, -259.15], + "A10": [45.0, -25.5, -259.15], + "A11": [54.0, -25.5, -259.15], + "A12": [63.0, -25.5, -259.15], + "B1": [-36.0, -34.5, -259.15], + "B2": [-27.0, -34.5, -259.15], + "B3": [-18.0, -34.5, -259.15], + "B4": [-9.0, -34.5, -259.15], + "B5": [0.0, -34.5, -259.15], + "B6": [9.0, -34.5, -259.15], + "B7": [18.0, -34.5, -259.15], + "B8": [27.0, -34.5, -259.15], + "B9": [36.0, -34.5, -259.15], + "B10": [45.0, -34.5, -259.15], + "B11": [54.0, -34.5, -259.15], + "B12": [63.0, -34.5, -259.15], + "C1": [-36.0, -43.5, -259.15], + "C2": [-27.0, -43.5, -259.15], + "C3": [-18.0, -43.5, -259.15], + "C4": [-9.0, -43.5, -259.15], + "C5": [0.0, -43.5, -259.15], + "C6": [9.0, -43.5, -259.15], + "C7": [18.0, -43.5, -259.15], + "C8": [27.0, -43.5, -259.15], + "C9": [36.0, -43.5, -259.15], + "C10": [45.0, -43.5, -259.15], + "C11": [54.0, -43.5, -259.15], + "C12": [63.0, -43.5, -259.15], + "D1": [-36.0, -52.5, -259.15], + "D2": [-27.0, -52.5, -259.15], + "D3": [-18.0, -52.5, -259.15], + "D4": [-9.0, -52.5, -259.15], + "D5": [0.0, -52.5, -259.15], + "D6": [9.0, -52.5, -259.15], + "D7": [18.0, -52.5, -259.15], + "D8": [27.0, -52.5, -259.15], + "D9": [36.0, -52.5, -259.15], + "D10": [45.0, -52.5, -259.15], + "D11": [54.0, -52.5, -259.15], + "D12": [63.0, -52.5, -259.15], + "E1": [-36.0, -61.5, -259.15], + "E2": [-27.0, -61.5, -259.15], + "E3": [-18.0, -61.5, -259.15], + "E4": [-9.0, -61.5, -259.15], + "E5": [0.0, -61.5, -259.15], + "E6": [9.0, -61.5, -259.15], + "E7": [18.0, -61.5, -259.15], + "E8": [27.0, -61.5, -259.15], + "E9": [36.0, -61.5, -259.15], + "E10": [45.0, -61.5, -259.15], + "E11": [54.0, -61.5, -259.15], + "E12": [63.0, -61.5, -259.15], + "F1": [-36.0, -70.5, -259.15], + "F2": [-27.0, -70.5, -259.15], + "F3": [-18.0, -70.5, -259.15], + "F4": [-9.0, -70.5, -259.15], + "F5": [0.0, -70.5, -259.15], + "F6": [9.0, -70.5, -259.15], + "F7": [18.0, -70.5, -259.15], + "F8": [27.0, -70.5, -259.15], + "F9": [36.0, -70.5, -259.15], + "F10": [45.0, -70.5, -259.15], + "F11": [54.0, -70.5, -259.15], + "F12": [63.0, -70.5, -259.15], + "G1": [-36.0, -79.5, -259.15], + "G2": [-27.0, -79.5, -259.15], + "G3": [-18.0, -79.5, -259.15], + "G4": [-9.0, -79.5, -259.15], + "G5": [0.0, -79.5, -259.15], + "G6": [9.0, -79.5, -259.15], + "G7": [18.0, -79.5, -259.15], + "G8": [27.0, -79.5, -259.15], + "G9": [36.0, -79.5, -259.15], + "G10": [45.0, -79.5, -259.15], + "G11": [54.0, -79.5, -259.15], + "G12": [63.0, -79.5, -259.15], + "H1": [-36.0, -88.5, -259.15], + "H2": [-27.0, -88.5, -259.15], + "H3": [-18.0, -88.5, -259.15], + "H4": [-9.0, -88.5, -259.15], + "H5": [0.0, -88.5, -259.15], + "H6": [9.0, -88.5, -259.15], + "H7": [18.0, -88.5, -259.15], + "H8": [27.0, -88.5, -259.15], + "H9": [36.0, -88.5, -259.15], + "H10": [45.0, -88.5, -259.15], + "H11": [54.0, -88.5, -259.15], + "H12": [63.0, -88.5, -259.15], +} + + +@pytest.mark.parametrize( + argnames=["nozzle_map", "critical_point_configuration", "expected"], + argvalues=[ + [ + { + "A1": [-8.0, -16.0, -259.15], + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15], + }, + CriticalPoint.XY_CENTER, + Point(-8.0, -47.5, -259.15), + ], + [ + NINETY_SIX_CHANNEL_MAP, + CriticalPoint.XY_CENTER, + Point(13.5, -57.0, -259.15), + ], + [ + {"A1": [1, 1, 1]}, + CriticalPoint.FRONT_NOZZLE, + Point(1, 1, 1), + ], + ], +) +def test_update_nozzles_with_critical_points( + nozzle_map: Dict[str, List[float]], + critical_point_configuration: CriticalPoint, + expected: List[float], +) -> None: + subject = build_nozzle_manger(nozzle_map) + new_cp = subject.critical_point_with_tip_length(critical_point_configuration) + assert new_cp == expected + + +@pytest.mark.parametrize( + argnames=["nozzle_map", "updated_nozzle_configuration", "exception", "expected_cp"], + argvalues=[ + [ + { + "A1": [0.0, 31.5, 0.8], + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8], + }, + ("D1", "H1"), + does_not_raise(), + Point(0.0, 4.5, 0.8), + ], + [ + {"A1": [1, 1, 1]}, + ("A1", "D1"), + pytest.raises(nozzle_manager.IncompatibleNozzleConfiguration), + Point(1, 1, 1), + ], + [ + NINETY_SIX_CHANNEL_MAP, + ("A12", "H12"), + does_not_raise(), + Point(x=63.0, y=-25.5, z=-259.15), + ], + ], +) +def test_update_nozzle_configuration( + nozzle_map: Dict[str, List[float]], + updated_nozzle_configuration: Tuple[str, str], + exception: ContextManager[None], + expected_cp: List[float], +) -> None: + subject = build_nozzle_manger(nozzle_map) + with exception: + subject.update_nozzle_configuration(*updated_nozzle_configuration) + assert subject.starting_nozzle_offset == expected_cp diff --git a/api/tests/opentrons/hardware_control/test_ot3_api.py b/api/tests/opentrons/hardware_control/test_ot3_api.py index cd6f383c2cd..9c92d5b936f 100644 --- a/api/tests/opentrons/hardware_control/test_ot3_api.py +++ b/api/tests/opentrons/hardware_control/test_ot3_api.py @@ -30,6 +30,7 @@ TipActionSpec, TipActionMoveSpec, ) +from opentrons.hardware_control.instruments.ot3.pipette import Pipette from opentrons.hardware_control.types import ( OT3Mount, Axis, @@ -44,6 +45,7 @@ EstopStateNotification, TipStateType, ) +from opentrons.hardware_control.nozzle_manager import NozzleConfigurationType from opentrons.hardware_control.errors import InvalidCriticalPoint from opentrons.hardware_control.ot3api import OT3API from opentrons.hardware_control import ThreadManager @@ -531,7 +533,9 @@ async def test_pickup_moves( gantry_load = GantryLoad.LOW_THROUGHPUT await ot3_hardware.set_gantry_load(gantry_load) - + pipette_handler.get_pipette( + OT3Mount.LEFT + ).nozzle_manager.current_configuration.configuration = NozzleConfigurationType.FULL z_tiprack_distance = 8.0 end_z_retract_dist = 9.0 move_plan_return_val = TipActionSpec( @@ -1457,6 +1461,7 @@ async def test_save_instrument_offset( ) +@pytest.mark.xfail() async def test_pick_up_tip_full_tiprack( ot3_hardware: ThreadManager[OT3API], mock_instrument_handlers: Tuple[Mock], @@ -1469,11 +1474,16 @@ async def test_pick_up_tip_full_tiprack( await ot3_hardware.home() _, pipette_handler = mock_instrument_handlers backend = ot3_hardware.managed_obj._backend - + instr_mock = AsyncMock(spec=Pipette) + instr_mock.nozzle_manager.current_configruation.configuration.return_value = ( + NozzleConfigurationType.FULL + ) with patch.object( backend, "tip_action", AsyncMock(spec=backend.tip_action) ) as tip_action: backend._gear_motor_position = {NodeId: 0} + pipette_handler.get_pipette.return_value = instr_mock + pipette_handler.plan_ht_pick_up_tip.return_value = TipActionSpec( shake_off_moves=[], tip_action_moves=[ diff --git a/api/tests/opentrons/hardware_control/test_pipette.py b/api/tests/opentrons/hardware_control/test_pipette.py index 582e95b589e..c6b298c51c8 100644 --- a/api/tests/opentrons/hardware_control/test_pipette.py +++ b/api/tests/opentrons/hardware_control/test_pipette.py @@ -166,7 +166,7 @@ def test_critical_points_pipette_offset( ) -> None: hw_pipette = pipette_builder(model, calibration) # pipette offset + nozzle offset to determine critical point - offsets = calibration.offset + Point(*hw_pipette.nozzle_offset) + offsets = calibration.offset + hw_pipette.nozzle_offset assert hw_pipette.critical_point() == offsets assert hw_pipette.critical_point(types.CriticalPoint.NOZZLE) == offsets assert hw_pipette.critical_point(types.CriticalPoint.TIP) == offsets diff --git a/api/tests/opentrons/hardware_control/test_pipette_handler.py b/api/tests/opentrons/hardware_control/test_pipette_handler.py index 8da45e68b8f..c962fc592c5 100644 --- a/api/tests/opentrons/hardware_control/test_pipette_handler.py +++ b/api/tests/opentrons/hardware_control/test_pipette_handler.py @@ -151,7 +151,9 @@ def test_plan_check_pick_up_tip_with_presses_argument_ot3( decoy.when(mock_pipette_ot3.pick_up_configurations.increment).then_return(increment) decoy.when(mock_pipette_ot3.pick_up_configurations.speed).then_return(5.5) decoy.when(mock_pipette_ot3.pick_up_configurations.distance).then_return(10) - decoy.when(mock_pipette_ot3.pick_up_configurations.current).then_return(1) + decoy.when( + mock_pipette_ot3.nozzle_manager.get_tip_configuration_current() + ).then_return(1) decoy.when(mock_pipette_ot3.plunger_motor_current.run).then_return(1) decoy.when(mock_pipette_ot3.config.quirks).then_return([]) decoy.when(mock_pipette_ot3.channels).then_return(channels) diff --git a/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py b/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py index b53fa674ef1..333c39e0bfd 100644 --- a/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py +++ b/api/tests/opentrons/protocol_api/core/engine/test_instrument_core.py @@ -1,5 +1,5 @@ """Test for the ProtocolEngine-based instrument API core.""" -from typing import cast +from typing import cast, Optional import pytest from decoy import Decoy @@ -20,7 +20,15 @@ ) from opentrons.protocol_engine.errors.exceptions import TipNotAttachedError from opentrons.protocol_engine.clients import SyncClient as EngineClient -from opentrons.protocol_engine.types import FlowRates, TipGeometry +from opentrons.protocol_engine.types import ( + FlowRates, + TipGeometry, + NozzleLayoutConfigurationType, + RowNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, +) +from opentrons.protocol_api._nozzle_layout import NozzleLayout from opentrons.protocol_api.core.engine import InstrumentCore, WellCore, ProtocolCore from opentrons.types import Location, Mount, MountType, Point @@ -874,3 +882,43 @@ def test_has_tip( ).then_return(TipGeometry(length=1, diameter=2, volume=3)) assert subject.has_tip() is True + + +@pytest.mark.parametrize( + argnames=["style", "primary_nozzle", "front_right_nozzle", "expected_model"], + argvalues=[ + [ + NozzleLayout.COLUMN, + "A1", + "H1", + ColumnNozzleLayoutConfiguration(primary_nozzle="A1"), + ], + [ + NozzleLayout.SINGLE, + "H12", + None, + SingleNozzleLayoutConfiguration(primary_nozzle="H12"), + ], + [ + NozzleLayout.ROW, + "A12", + None, + RowNozzleLayoutConfiguration(primary_nozzle="A12"), + ], + ], +) +def test_configure_nozzle_layout( + decoy: Decoy, + mock_engine_client: EngineClient, + subject: InstrumentCore, + style: NozzleLayout, + primary_nozzle: Optional[str], + front_right_nozzle: Optional[str], + expected_model: NozzleLayoutConfigurationType, +) -> None: + """The correct model is passed to the engine client.""" + subject.configure_nozzle_layout(style, primary_nozzle, front_right_nozzle) + + decoy.verify( + mock_engine_client.configure_nozzle_layout(subject._pipette_id, expected_model) + ) diff --git a/api/tests/opentrons/protocol_api/test_instrument_context.py b/api/tests/opentrons/protocol_api/test_instrument_context.py index 9a38dfef87b..c181add69f5 100644 --- a/api/tests/opentrons/protocol_api/test_instrument_context.py +++ b/api/tests/opentrons/protocol_api/test_instrument_context.py @@ -6,6 +6,9 @@ from decoy import Decoy from opentrons.legacy_broker import LegacyBroker +from typing import ContextManager, Optional +from contextlib import nullcontext as does_not_raise + from opentrons.protocols.api_support import instrument as mock_instrument_support from opentrons.protocols.api_support.types import APIVersion from opentrons.protocols.api_support.util import ( @@ -26,6 +29,7 @@ from opentrons.protocol_api.core.legacy.legacy_instrument_core import ( LegacyInstrumentCore, ) +from opentrons.protocol_api._nozzle_layout import NozzleLayout from opentrons.types import Location, Mount, Point from opentrons_shared_data.errors.exceptions import ( @@ -934,3 +938,23 @@ def test_prepare_to_aspirate_checks_volume( decoy.when(mock_instrument_core.get_current_volume()).then_return(10) with pytest.raises(CommandPreconditionViolated): subject.prepare_to_aspirate() + + +@pytest.mark.parametrize( + argnames=["style", "primary_nozzle", "front_right_nozzle", "exception"], + argvalues=[ + [NozzleLayout.COLUMN, "A1", "H1", does_not_raise()], + [NozzleLayout.SINGLE, None, None, pytest.raises(ValueError)], + [NozzleLayout.ROW, "E1", None, pytest.raises(ValueError)], + ], +) +def test_configure_nozzle_layout( + subject: InstrumentContext, + style: NozzleLayout, + primary_nozzle: Optional[str], + front_right_nozzle: Optional[str], + exception: ContextManager[None], +) -> None: + """The correct model is passed to the engine client.""" + with exception: + subject.configure_nozzle_layout(style, primary_nozzle, front_right_nozzle) diff --git a/api/tests/opentrons/protocol_engine/commands/conftest.py b/api/tests/opentrons/protocol_engine/commands/conftest.py index f9275b0d1e1..aad3cf21d4a 100644 --- a/api/tests/opentrons/protocol_engine/commands/conftest.py +++ b/api/tests/opentrons/protocol_engine/commands/conftest.py @@ -12,6 +12,7 @@ RailLightsHandler, LabwareMovementHandler, StatusBarHandler, + TipHandler, ) from opentrons.protocol_engine.state import StateView @@ -46,6 +47,12 @@ def pipetting(decoy: Decoy) -> PipettingHandler: return decoy.mock(cls=PipettingHandler) +@pytest.fixture +def tip_handler(decoy: Decoy) -> TipHandler: + """Get a mocked out EquipmentHandler.""" + return decoy.mock(cls=TipHandler) + + @pytest.fixture def run_control(decoy: Decoy) -> RunControlHandler: """Get a mocked out RunControlHandler.""" diff --git a/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py b/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py new file mode 100644 index 00000000000..44fc10530e5 --- /dev/null +++ b/api/tests/opentrons/protocol_engine/commands/test_configure_nozzle_layout.py @@ -0,0 +1,212 @@ +"""Test configure nozzle layout commands.""" +import pytest +from decoy import Decoy +from typing import Union, Optional, Dict + +from opentrons.protocol_engine.execution import ( + EquipmentHandler, + TipHandler, +) +from opentrons.types import Point +from opentrons.hardware_control.nozzle_manager import NozzleMap + + +from opentrons.protocol_engine.commands.configure_nozzle_layout import ( + ConfigureNozzleLayoutParams, + ConfigureNozzleLayoutResult, + ConfigureNozzleLayoutPrivateResult, + ConfigureNozzleLayoutImplementation, +) + +from opentrons.protocol_engine.types import ( + EmptyNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, +) + + +NINETY_SIX_MAP = { + "A1": Point(-36.0, -25.5, -259.15), + "A2": Point(-27.0, -25.5, -259.15), + "A3": Point(-18.0, -25.5, -259.15), + "A4": Point(-9.0, -25.5, -259.15), + "A5": Point(0.0, -25.5, -259.15), + "A6": Point(9.0, -25.5, -259.15), + "A7": Point(18.0, -25.5, -259.15), + "A8": Point(27.0, -25.5, -259.15), + "A9": Point(36.0, -25.5, -259.15), + "A10": Point(45.0, -25.5, -259.15), + "A11": Point(54.0, -25.5, -259.15), + "A12": Point(63.0, -25.5, -259.15), + "B1": Point(-36.0, -34.5, -259.15), + "B2": Point(-27.0, -34.5, -259.15), + "B3": Point(-18.0, -34.5, -259.15), + "B4": Point(-9.0, -34.5, -259.15), + "B5": Point(0.0, -34.5, -259.15), + "B6": Point(9.0, -34.5, -259.15), + "B7": Point(18.0, -34.5, -259.15), + "B8": Point(27.0, -34.5, -259.15), + "B9": Point(36.0, -34.5, -259.15), + "B10": Point(45.0, -34.5, -259.15), + "B11": Point(54.0, -34.5, -259.15), + "B12": Point(63.0, -34.5, -259.15), + "C1": Point(-36.0, -43.5, -259.15), + "C2": Point(-27.0, -43.5, -259.15), + "C3": Point(-18.0, -43.5, -259.15), + "C4": Point(-9.0, -43.5, -259.15), + "C5": Point(0.0, -43.5, -259.15), + "C6": Point(9.0, -43.5, -259.15), + "C7": Point(18.0, -43.5, -259.15), + "C8": Point(27.0, -43.5, -259.15), + "C9": Point(36.0, -43.5, -259.15), + "C10": Point(45.0, -43.5, -259.15), + "C11": Point(54.0, -43.5, -259.15), + "C12": Point(63.0, -43.5, -259.15), + "D1": Point(-36.0, -52.5, -259.15), + "D2": Point(-27.0, -52.5, -259.15), + "D3": Point(-18.0, -52.5, -259.15), + "D4": Point(-9.0, -52.5, -259.15), + "D5": Point(0.0, -52.5, -259.15), + "D6": Point(9.0, -52.5, -259.15), + "D7": Point(18.0, -52.5, -259.15), + "D8": Point(27.0, -52.5, -259.15), + "D9": Point(36.0, -52.5, -259.15), + "D10": Point(45.0, -52.5, -259.15), + "D11": Point(54.0, -52.5, -259.15), + "D12": Point(63.0, -52.5, -259.15), + "E1": Point(-36.0, -61.5, -259.15), + "E2": Point(-27.0, -61.5, -259.15), + "E3": Point(-18.0, -61.5, -259.15), + "E4": Point(-9.0, -61.5, -259.15), + "E5": Point(0.0, -61.5, -259.15), + "E6": Point(9.0, -61.5, -259.15), + "E7": Point(18.0, -61.5, -259.15), + "E8": Point(27.0, -61.5, -259.15), + "E9": Point(36.0, -61.5, -259.15), + "E10": Point(45.0, -61.5, -259.15), + "E11": Point(54.0, -61.5, -259.15), + "E12": Point(63.0, -61.5, -259.15), + "F1": Point(-36.0, -70.5, -259.15), + "F2": Point(-27.0, -70.5, -259.15), + "F3": Point(-18.0, -70.5, -259.15), + "F4": Point(-9.0, -70.5, -259.15), + "F5": Point(0.0, -70.5, -259.15), + "F6": Point(9.0, -70.5, -259.15), + "F7": Point(18.0, -70.5, -259.15), + "F8": Point(27.0, -70.5, -259.15), + "F9": Point(36.0, -70.5, -259.15), + "F10": Point(45.0, -70.5, -259.15), + "F11": Point(54.0, -70.5, -259.15), + "F12": Point(63.0, -70.5, -259.15), + "G1": Point(-36.0, -79.5, -259.15), + "G2": Point(-27.0, -79.5, -259.15), + "G3": Point(-18.0, -79.5, -259.15), + "G4": Point(-9.0, -79.5, -259.15), + "G5": Point(0.0, -79.5, -259.15), + "G6": Point(9.0, -79.5, -259.15), + "G7": Point(18.0, -79.5, -259.15), + "G8": Point(27.0, -79.5, -259.15), + "G9": Point(36.0, -79.5, -259.15), + "G10": Point(45.0, -79.5, -259.15), + "G11": Point(54.0, -79.5, -259.15), + "G12": Point(63.0, -79.5, -259.15), + "H1": Point(-36.0, -88.5, -259.15), + "H2": Point(-27.0, -88.5, -259.15), + "H3": Point(-18.0, -88.5, -259.15), + "H4": Point(-9.0, -88.5, -259.15), + "H5": Point(0.0, -88.5, -259.15), + "H6": Point(9.0, -88.5, -259.15), + "H7": Point(18.0, -88.5, -259.15), + "H8": Point(27.0, -88.5, -259.15), + "H9": Point(36.0, -88.5, -259.15), + "H10": Point(45.0, -88.5, -259.15), + "H11": Point(54.0, -88.5, -259.15), + "H12": Point(63.0, -88.5, -259.15), +} + + +@pytest.mark.parametrize( + argnames=["request_model", "expected_nozzlemap", "nozzle_params"], + argvalues=[ + [ + SingleNozzleLayoutConfiguration(primary_nozzle="A1"), + NozzleMap.build( + physical_nozzle_map={"A1": Point(0, 0, 0)}, + starting_nozzle="A1", + back_left_nozzle="A1", + front_right_nozzle="A1", + ), + {"primary_nozzle": "A1"}, + ], + [ + ColumnNozzleLayoutConfiguration(primary_nozzle="A1"), + NozzleMap.build( + physical_nozzle_map=NINETY_SIX_MAP, + starting_nozzle="A1", + back_left_nozzle="A1", + front_right_nozzle="H1", + ), + {"primary_nozzle": "A1", "front_right_nozzle": "H1"}, + ], + [ + QuadrantNozzleLayoutConfiguration( + primary_nozzle="A1", front_right_nozzle="E1" + ), + NozzleMap.build( + physical_nozzle_map=NINETY_SIX_MAP, + starting_nozzle="A1", + back_left_nozzle="A1", + front_right_nozzle="E1", + ), + {"primary_nozzle": "A1", "front_right_nozzle": "E1"}, + ], + [ + EmptyNozzleLayoutConfiguration(), + None, + {}, + ], + ], +) +async def test_configure_nozzle_layout_implementation( + decoy: Decoy, + equipment: EquipmentHandler, + tip_handler: TipHandler, + request_model: Union[ + EmptyNozzleLayoutConfiguration, + ColumnNozzleLayoutConfiguration, + QuadrantNozzleLayoutConfiguration, + SingleNozzleLayoutConfiguration, + ], + expected_nozzlemap: Optional[NozzleMap], + nozzle_params: Dict[str, str], +) -> None: + """A ConfigureForVolume command should have an execution implementation.""" + subject = ConfigureNozzleLayoutImplementation( + equipment=equipment, tip_handler=tip_handler + ) + + requested_nozzle_layout = ConfigureNozzleLayoutParams( + pipetteId="pipette-id", + configuration_params=request_model, + ) + + decoy.when( + await tip_handler.available_for_nozzle_layout( + "pipette-id", **request_model.dict() + ) + ).then_return(nozzle_params) + + decoy.when( + await equipment.configure_nozzle_layout( + pipette_id="pipette-id", + **nozzle_params, + ) + ).then_return(expected_nozzlemap) + + result, private_result = await subject.execute(requested_nozzle_layout) + + assert result == ConfigureNozzleLayoutResult() + assert private_result == ConfigureNozzleLayoutPrivateResult( + pipette_id="pipette-id", nozzle_map=expected_nozzlemap + ) diff --git a/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py b/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py index c8ce23e4756..d9052872cff 100644 --- a/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py +++ b/api/tests/opentrons/protocol_engine/execution/test_tip_handler.py @@ -2,6 +2,9 @@ import pytest from decoy import Decoy +from typing import Dict, ContextManager, Optional +from contextlib import nullcontext as does_not_raise + from opentrons.types import Mount, MountType from opentrons.hardware_control import API as HardwareAPI @@ -9,7 +12,10 @@ from opentrons.protocol_engine.state import StateView from opentrons.protocol_engine.types import TipGeometry from opentrons.protocol_engine.resources import LabwareDataProvider - +from opentrons_shared_data.errors.exceptions import ( + CommandPreconditionViolated, + CommandParameterLimitViolated, +) from opentrons.protocol_engine.execution.tip_handler import ( HardwareTipHandler, VirtualTipHandler, @@ -191,6 +197,94 @@ async def test_add_tip( ) +@pytest.mark.parametrize( + argnames=[ + "test_channels", + "style", + "primary_nozzle", + "front_nozzle", + "exception", + "expected_result", + "tip_result", + ], + argvalues=[ + [ + 8, + "COLUMN", + "A1", + None, + does_not_raise(), + {"primary_nozzle": "A1", "front_right_nozzle": "H1"}, + None, + ], + [ + 8, + "ROW", + "A1", + None, + pytest.raises(CommandParameterLimitViolated), + None, + None, + ], + [8, "SINGLE", "A1", None, does_not_raise(), {"primary_nozzle": "A1"}, None], + [ + 1, + "SINGLE", + "A1", + None, + pytest.raises(CommandPreconditionViolated), + None, + None, + ], + [ + 8, + "COLUMN", + "A1", + None, + pytest.raises(CommandPreconditionViolated), + None, + TipGeometry(length=50, diameter=5, volume=300), + ], + ], +) +async def test_available_nozzle_layout( + decoy: Decoy, + mock_state_view: StateView, + mock_hardware_api: HardwareAPI, + mock_labware_data_provider: LabwareDataProvider, + test_channels: int, + style: str, + primary_nozzle: Optional[str], + front_nozzle: Optional[str], + exception: ContextManager[None], + expected_result: Optional[Dict[str, str]], + tip_result: Optional[TipGeometry], +) -> None: + """The virtual and hardware pipettes should return the same data and error at the same time.""" + hw_subject = HardwareTipHandler( + state_view=mock_state_view, + hardware_api=mock_hardware_api, + labware_data_provider=mock_labware_data_provider, + ) + virtual_subject = VirtualTipHandler(state_view=mock_state_view) + decoy.when(mock_state_view.pipettes.get_channels("pipette-id")).then_return( + test_channels + ) + decoy.when(mock_state_view.pipettes.get_attached_tip("pipette-id")).then_return( + tip_result + ) + + with exception: + hw_result = await hw_subject.available_for_nozzle_layout( + "pipette-id", style, primary_nozzle, front_nozzle + ) + virtual_result = await virtual_subject.available_for_nozzle_layout( + "pipette-id", style, primary_nozzle, front_nozzle + ) + + assert hw_result == virtual_result == expected_result + + async def test_virtual_pick_up_tip( decoy: Decoy, mock_state_view: StateView, diff --git a/api/tests/opentrons/protocol_engine/resources/test_pipette_data_provider.py b/api/tests/opentrons/protocol_engine/resources/test_pipette_data_provider.py index 1eb3787a509..c3cf10449fc 100644 --- a/api/tests/opentrons/protocol_engine/resources/test_pipette_data_provider.py +++ b/api/tests/opentrons/protocol_engine/resources/test_pipette_data_provider.py @@ -125,6 +125,20 @@ def test_load_virtual_pipette_by_model_string( ) +def test_load_virtual_pipette_nozzle_layout( + subject_instance: VirtualPipetteDataProvider, +) -> None: + """It should return a NozzleMap object.""" + subject_instance.configure_virtual_pipette_nozzle_layout( + "my-pipette", "p300_multi_v2.1", "A1", "E1", "A1" + ) + result = subject_instance.get_nozzle_layout_for_pipette("my-pipette") + assert result.configuration.value == "COLUMN" + assert result.starting_nozzle == "A1" + assert result.front_right == "E1" + assert result.back_left == "A1" + + def test_get_pipette_static_config( supported_tip_fixture: pipette_definition.SupportedTipsDefinition, ) -> None: @@ -164,6 +178,7 @@ def test_get_pipette_static_config( "default_aspirate_speeds": {"2.0": 5.021202, "2.6": 10.042404}, "default_push_out_volume": 3, "supported_tips": {pip_types.PipetteTipType.t300: supported_tip_fixture}, + "current_nozzle_map": None, } result = subject.get_pipette_static_config(pipette_dict) diff --git a/api/tests/opentrons/protocol_engine/state/test_pipette_store.py b/api/tests/opentrons/protocol_engine/state/test_pipette_store.py index 25370a410fc..3f638991c95 100644 --- a/api/tests/opentrons/protocol_engine/state/test_pipette_store.py +++ b/api/tests/opentrons/protocol_engine/state/test_pipette_store.py @@ -69,6 +69,7 @@ def test_sets_initial_state(subject: PipetteStore) -> None: movement_speed_by_id={}, static_config_by_id={}, flow_rates_by_id={}, + nozzle_configuration_by_id={}, ) diff --git a/api/tests/opentrons/protocol_engine/state/test_pipette_view.py b/api/tests/opentrons/protocol_engine/state/test_pipette_view.py index b76ba20303f..5721beb5b18 100644 --- a/api/tests/opentrons/protocol_engine/state/test_pipette_view.py +++ b/api/tests/opentrons/protocol_engine/state/test_pipette_view.py @@ -24,6 +24,7 @@ HardwarePipette, StaticPipetteConfig, ) +from opentrons.hardware_control.nozzle_manager import NozzleMap from opentrons.protocol_engine.errors import TipNotAttachedError, PipetteNotLoadedError @@ -38,6 +39,7 @@ def get_pipette_view( movement_speed_by_id: Optional[Dict[str, Optional[float]]] = None, static_config_by_id: Optional[Dict[str, StaticPipetteConfig]] = None, flow_rates_by_id: Optional[Dict[str, FlowRates]] = None, + nozzle_layout_by_id: Optional[Dict[str, Optional[NozzleMap]]] = None, ) -> PipetteView: """Get a pipette view test subject with the specified state.""" state = PipetteState( @@ -49,6 +51,7 @@ def get_pipette_view( movement_speed_by_id=movement_speed_by_id or {}, static_config_by_id=static_config_by_id or {}, flow_rates_by_id=flow_rates_by_id or {}, + nozzle_configuration_by_id=nozzle_layout_by_id or {}, ) return PipetteView(state=state) diff --git a/shared-data/command/schemas/8.json b/shared-data/command/schemas/8.json index 81f1d37ca5f..2bfeee8e49c 100644 --- a/shared-data/command/schemas/8.json +++ b/shared-data/command/schemas/8.json @@ -14,6 +14,9 @@ { "$ref": "#/definitions/ConfigureForVolumeCreate" }, + { + "$ref": "#/definitions/ConfigureNozzleLayoutCreate" + }, { "$ref": "#/definitions/CustomCreate" }, @@ -439,6 +442,168 @@ }, "required": ["params"] }, + "EmptyNozzleLayoutConfiguration": { + "title": "EmptyNozzleLayoutConfiguration", + "description": "Empty basemodel to represent a reset to the nozzle configuration. Sending no parameters resets to default.", + "type": "object", + "properties": { + "style": { + "title": "Style", + "default": "EMPTY", + "enum": ["EMPTY"], + "type": "string" + } + } + }, + "SingleNozzleLayoutConfiguration": { + "title": "SingleNozzleLayoutConfiguration", + "description": "Minimum information required for a new nozzle configuration.", + "type": "object", + "properties": { + "style": { + "title": "Style", + "default": "SINGLE", + "enum": ["SINGLE"], + "type": "string" + }, + "primary_nozzle": { + "title": "Primary Nozzle", + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "type": "string" + } + }, + "required": ["primary_nozzle"] + }, + "RowNozzleLayoutConfiguration": { + "title": "RowNozzleLayoutConfiguration", + "description": "Minimum information required for a new nozzle configuration.", + "type": "object", + "properties": { + "style": { + "title": "Style", + "default": "ROW", + "enum": ["ROW"], + "type": "string" + }, + "primary_nozzle": { + "title": "Primary Nozzle", + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "type": "string" + } + }, + "required": ["primary_nozzle"] + }, + "ColumnNozzleLayoutConfiguration": { + "title": "ColumnNozzleLayoutConfiguration", + "description": "Information required for nozzle configurations of type ROW and COLUMN.", + "type": "object", + "properties": { + "style": { + "title": "Style", + "default": "COLUMN", + "enum": ["COLUMN"], + "type": "string" + }, + "primary_nozzle": { + "title": "Primary Nozzle", + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "type": "string" + } + }, + "required": ["primary_nozzle"] + }, + "QuadrantNozzleLayoutConfiguration": { + "title": "QuadrantNozzleLayoutConfiguration", + "description": "Information required for nozzle configurations of type QUADRANT.", + "type": "object", + "properties": { + "style": { + "title": "Style", + "default": "QUADRANT", + "enum": ["QUADRANT"], + "type": "string" + }, + "primary_nozzle": { + "title": "Primary Nozzle", + "description": "The primary nozzle to use in the layout configuration. This nozzle will update the critical point of the current pipette. For now, this is also the back left corner of your rectangle.", + "enum": ["A1", "H1", "A12", "H12"], + "type": "string" + }, + "front_right_nozzle": { + "title": "Front Right Nozzle", + "description": "The front right nozzle in your configuration.", + "pattern": "[A-Z][0-100]", + "type": "string" + } + }, + "required": ["primary_nozzle", "front_right_nozzle"] + }, + "ConfigureNozzleLayoutParams": { + "title": "ConfigureNozzleLayoutParams", + "description": "Parameters required to configure the nozzle layout for a specific pipette.", + "type": "object", + "properties": { + "pipetteId": { + "title": "Pipetteid", + "description": "Identifier of pipette to use for liquid handling.", + "type": "string" + }, + "configuration_params": { + "title": "Configuration Params", + "anyOf": [ + { + "$ref": "#/definitions/EmptyNozzleLayoutConfiguration" + }, + { + "$ref": "#/definitions/SingleNozzleLayoutConfiguration" + }, + { + "$ref": "#/definitions/RowNozzleLayoutConfiguration" + }, + { + "$ref": "#/definitions/ColumnNozzleLayoutConfiguration" + }, + { + "$ref": "#/definitions/QuadrantNozzleLayoutConfiguration" + } + ] + } + }, + "required": ["pipetteId", "configuration_params"] + }, + "ConfigureNozzleLayoutCreate": { + "title": "ConfigureNozzleLayoutCreate", + "description": "Configure nozzle layout creation request model.", + "type": "object", + "properties": { + "commandType": { + "title": "Commandtype", + "default": "configureNozzleLayout", + "enum": ["configureNozzleLayout"], + "type": "string" + }, + "params": { + "$ref": "#/definitions/ConfigureNozzleLayoutParams" + }, + "intent": { + "description": "The reason the command was added. If not specified or `protocol`, the command will be treated as part of the protocol run itself, and added to the end of the existing command queue.\n\nIf `setup`, the command will be treated as part of run setup. A setup command may only be enqueued if the run has not started.\n\nUse setup commands for activities like pre-run calibration checks and module setup, like pre-heating.", + "allOf": [ + { + "$ref": "#/definitions/CommandIntent" + } + ] + }, + "key": { + "title": "Key", + "description": "A key value, unique in this run, that can be used to track the same logical command across multiple runs of the same protocol. If a value is not provided, one will be generated.", + "type": "string" + } + }, + "required": ["params"] + }, "CustomParams": { "title": "CustomParams", "description": "Payload used by a custom command.", diff --git a/shared-data/errors/definitions/1/errors.json b/shared-data/errors/definitions/1/errors.json index 28caa98cb7a..1f31ac9af6e 100644 --- a/shared-data/errors/definitions/1/errors.json +++ b/shared-data/errors/definitions/1/errors.json @@ -213,6 +213,10 @@ "4006": { "detail": "Invalid Protocol Data", "category": "generalError" + }, + "4007": { + "detail": "API Command is misconfigured", + "category": "generalError" } } } diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_0.json index 4f353672189..a3a7a9a8fc4 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_0.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.4, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.1, + "3": 0.15, + "4": 0.2, + "5": 0.25, + "6": 0.3, + "7": 0.35, + "8": 0.4 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_3.json b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_3.json index 9090efaccb2..3f6700dc816 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_3.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_3.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.4, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.1, + "3": 0.15, + "4": 0.2, + "5": 0.25, + "6": 0.3, + "7": 0.35, + "8": 0.4 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_4.json b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_4.json index d7967eb7f8e..f183e7aab87 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_4.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_4.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.4, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.1, + "3": 0.15, + "4": 0.2, + "5": 0.25, + "6": 0.3, + "7": 0.35, + "8": 0.4 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_5.json b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_5.json index 9974fe1c989..ef35a1587c8 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_5.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_5.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.55, "speed": 30.0, "presses": 3, "increment": 3.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.14, + "3": 0.21, + "4": 0.28, + "5": 0.34, + "6": 0.41, + "7": 0.48, + "8": 0.55 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_6.json b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_6.json index 9974fe1c989..ef35a1587c8 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p10/1_6.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p10/1_6.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.55, "speed": 30.0, "presses": 3, "increment": 3.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.14, + "3": 0.21, + "4": 0.28, + "5": 0.34, + "6": 0.41, + "7": 0.48, + "8": 0.55 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p1000/1_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p1000/1_0.json index f8c2397938d..1d17191c93f 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p1000/1_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p1000/1_0.json @@ -1,10 +1,9 @@ { "$otSharedSchema": "#/pipette/schemas/2/pipettePropertiesSchema.json", - "displayName": "Flex 8-Channel 1000 μL", + "displayName": "Flex 8-Channel 1000 uL", "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.5, "presses": 1, "speed": 10, "increment": 0.0, @@ -40,7 +39,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.15, + "2": 0.13, + "3": 0.19, + "4": 0.25, + "5": 0.31, + "6": 0.38, + "7": 0.44, + "8": 0.5 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_0.json index 325e06edfc3..8bd59075ccc 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_0.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.5, "presses": 1, "speed": 10, "increment": 0.0, @@ -40,7 +39,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.15, + "2": 0.13, + "3": 0.19, + "4": 0.25, + "5": 0.31, + "6": 0.38, + "7": 0.44, + "8": 0.5 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_3.json b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_3.json index 325e06edfc3..8bd59075ccc 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_3.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_3.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.5, "presses": 1, "speed": 10, "increment": 0.0, @@ -40,7 +39,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.15, + "2": 0.13, + "3": 0.19, + "4": 0.25, + "5": 0.31, + "6": 0.38, + "7": 0.44, + "8": 0.5 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_4.json b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_4.json index 74ab62080fe..862266f22fe 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_4.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_4.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.55, "presses": 1, "speed": 10, "increment": 0.0, @@ -40,7 +39,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.2, + "2": 0.14, + "3": 0.21, + "4": 0.28, + "5": 0.34, + "6": 0.41, + "7": 0.48, + "8": 0.55 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_5.json b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_5.json index 74ab62080fe..862266f22fe 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_5.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p1000/3_5.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.55, "presses": 1, "speed": 10, "increment": 0.0, @@ -40,7 +39,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.2, + "2": 0.14, + "3": 0.21, + "4": 0.28, + "5": 0.34, + "6": 0.41, + "7": 0.48, + "8": 0.55 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p20/2_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p20/2_0.json index 5ff09279c1d..9530ac8428c 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p20/2_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p20/2_0.json @@ -4,7 +4,6 @@ "model": "p20", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.6, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.28, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p20/2_1.json b/shared-data/pipette/definitions/2/general/eight_channel/p20/2_1.json index 5ff09279c1d..9530ac8428c 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p20/2_1.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p20/2_1.json @@ -4,7 +4,6 @@ "model": "p20", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.6, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.28, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_0.json index fc8202bb490..0d1ed8808cc 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_0.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.6, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.3, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_3.json b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_3.json index 158246e8859..602bf5df703 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_3.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_3.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.6, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.3, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_4.json b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_4.json index 158246e8859..602bf5df703 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_4.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_4.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.6, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.3, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_5.json b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_5.json index 707f591d644..972cc766d78 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p300/1_5.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p300/1_5.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.9, "speed": 30.0, "presses": 3, "increment": 3.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.23, + "3": 0.34, + "4": 0.45, + "5": 0.56, + "6": 0.68, + "7": 0.79, + "8": 0.9 + } }, "channels": 8, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p300/2_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p300/2_0.json index faf79930bbf..412f0b9c90d 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p300/2_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p300/2_0.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.8, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.13, + "2": 0.2, + "3": 0.3, + "4": 0.4, + "5": 0.5, + "6": 0.6, + "7": 0.7, + "8": 0.8 + } }, "channels": 8, "shaftDiameter": 3.5, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p300/2_1.json b/shared-data/pipette/definitions/2/general/eight_channel/p300/2_1.json index faf79930bbf..412f0b9c90d 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p300/2_1.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p300/2_1.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.8, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.13, + "2": 0.2, + "3": 0.3, + "4": 0.4, + "5": 0.5, + "6": 0.6, + "7": 0.7, + "8": 0.8 + } }, "channels": 8, "shaftDiameter": 3.5, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_0.json index 3db295cf144..489a8a97191 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_0.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.6, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.3, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_3.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_3.json index a930751ec6c..2931fbd0351 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_3.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_3.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.6, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.3, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_4.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_4.json index 187dc21b9b0..d05487517e8 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_4.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_4.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.6, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.15, + "3": 0.23, + "4": 0.3, + "5": 0.38, + "6": 0.45, + "7": 0.53, + "8": 0.6 + } }, "channels": 8, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_5.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_5.json index c2249446a6b..6204217a21f 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/1_5.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/1_5.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.8, "speed": 30.0, "presses": 3, "increment": 3.0, @@ -34,7 +33,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.1, + "2": 0.2, + "3": 0.3, + "4": 0.4, + "5": 0.5, + "6": 0.6, + "7": 0.7, + "8": 0.8 + } }, "channels": 8, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_0.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_0.json index a6dceda8f18..4ea113546b3 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_0.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_0.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.5, "presses": 1, "speed": 10, "increment": 0.0, @@ -46,7 +45,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.15, + "2": 0.13, + "3": 0.19, + "4": 0.25, + "5": 0.31, + "6": 0.38, + "7": 0.44, + "8": 0.5 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_3.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_3.json index a6dceda8f18..4ea113546b3 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_3.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_3.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.5, "presses": 1, "speed": 10, "increment": 0.0, @@ -46,7 +45,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.15, + "2": 0.13, + "3": 0.19, + "4": 0.25, + "5": 0.31, + "6": 0.38, + "7": 0.44, + "8": 0.5 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_4.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_4.json index c7b005e1049..cffcc3d65e9 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_4.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_4.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.55, "presses": 1, "speed": 10, "increment": 0.0, @@ -46,7 +45,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.2, + "2": 0.14, + "3": 0.2, + "4": 0.28, + "5": 0.34, + "6": 0.41, + "7": 0.48, + "8": 0.55 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_5.json b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_5.json index c7b005e1049..cffcc3d65e9 100644 --- a/shared-data/pipette/definitions/2/general/eight_channel/p50/3_5.json +++ b/shared-data/pipette/definitions/2/general/eight_channel/p50/3_5.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.55, "presses": 1, "speed": 10, "increment": 0.0, @@ -46,7 +45,17 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8] + "availableConfigurations": [1, 2, 3, 4, 5, 6, 7, 8], + "perTipPickupCurrent": { + "1": 0.2, + "2": 0.14, + "3": 0.2, + "4": 0.28, + "5": 0.34, + "6": 0.41, + "7": 0.48, + "8": 0.55 + } }, "backCompatNames": [], "channels": 8, diff --git a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/1_0.json b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/1_0.json index be5a36fd7b2..2fa4e3e803a 100644 --- a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/1_0.json +++ b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/1_0.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 1.5, "presses": 0.0, "speed": 5.5, "increment": 0.0, @@ -45,7 +44,22 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 8, 12, 96] + "availableConfigurations": [1, 8, 12, 96], + "perTipPickupCurrent": { + "1": 0.02, + "2": 0.03, + "3": 0.05, + "4": 0.06, + "5": 0.08, + "6": 0.09, + "7": 0.11, + "8": 0.13, + "12": 0.19, + "16": 0.25, + "24": 0.38, + "48": 0.75, + "96": 1.5 + } }, "backCompatNames": [], "channels": 96, diff --git a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_0.json b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_0.json index ad470621884..bef06d53c03 100644 --- a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_0.json +++ b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_0.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 1.5, "presses": 0.0, "speed": 5.5, "increment": 0.0, @@ -45,7 +44,22 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 8, 12, 96] + "availableConfigurations": [1, 8, 12, 96], + "perTipPickupCurrent": { + "1": 0.02, + "2": 0.03, + "3": 0.05, + "4": 0.06, + "5": 0.08, + "6": 0.09, + "7": 0.11, + "8": 0.13, + "12": 0.19, + "16": 0.25, + "24": 0.38, + "48": 0.75, + "96": 1.5 + } }, "backCompatNames": [], "channels": 96, diff --git a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_3.json b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_3.json index ad470621884..bef06d53c03 100644 --- a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_3.json +++ b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_3.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 1.5, "presses": 0.0, "speed": 5.5, "increment": 0.0, @@ -45,7 +44,22 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 8, 12, 96] + "availableConfigurations": [1, 8, 12, 96], + "perTipPickupCurrent": { + "1": 0.02, + "2": 0.03, + "3": 0.05, + "4": 0.06, + "5": 0.08, + "6": 0.09, + "7": 0.11, + "8": 0.13, + "12": 0.19, + "16": 0.25, + "24": 0.38, + "48": 0.75, + "96": 1.5 + } }, "backCompatNames": [], "channels": 96, diff --git a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_4.json b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_4.json index 8ee7b54a538..4d7eaff5487 100644 --- a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_4.json +++ b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_4.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 1.5, "presses": 0.0, "speed": 5.5, "increment": 0.0, @@ -45,7 +44,22 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 8, 12, 96] + "availableConfigurations": [1, 8, 12, 96], + "perTipPickupCurrent": { + "1": 0.02, + "2": 0.03, + "3": 0.05, + "4": 0.06, + "5": 0.08, + "6": 0.09, + "7": 0.11, + "8": 0.13, + "12": 0.19, + "16": 0.25, + "24": 0.38, + "48": 0.75, + "96": 1.5 + } }, "backCompatNames": [], "channels": 96, diff --git a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_5.json b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_5.json index 5fe52525614..2494dfeccca 100644 --- a/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_5.json +++ b/shared-data/pipette/definitions/2/general/ninety_six_channel/p1000/3_5.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 1.5, "presses": 0.0, "speed": 5.5, "increment": 0.0, @@ -45,7 +44,22 @@ }, "partialTipConfigurations": { "partialTipSupported": true, - "availableConfigurations": [1, 8, 12, 96] + "availableConfigurations": [1, 8, 12, 16, 24, 48, 96], + "perTipPickupCurrent": { + "1": 0.02, + "2": 0.03, + "3": 0.05, + "4": 0.06, + "5": 0.08, + "6": 0.09, + "7": 0.11, + "8": 0.13, + "12": 0.19, + "16": 0.25, + "24": 0.38, + "48": 0.75, + "96": 1.5 + } }, "backCompatNames": [], "channels": 96, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p10/1_0.json b/shared-data/pipette/definitions/2/general/single_channel/p10/1_0.json index 87bc9d96d64..1d66d202d5f 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p10/1_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p10/1_0.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p10/1_3.json b/shared-data/pipette/definitions/2/general/single_channel/p10/1_3.json index 6ffa340a8b3..93bc4d1e0a2 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p10/1_3.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p10/1_3.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p10/1_4.json b/shared-data/pipette/definitions/2/general/single_channel/p10/1_4.json index abd69fc06d4..44fba8ac981 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p10/1_4.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p10/1_4.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p10/1_5.json b/shared-data/pipette/definitions/2/general/single_channel/p10/1_5.json index abd69fc06d4..44fba8ac981 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p10/1_5.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p10/1_5.json @@ -4,7 +4,6 @@ "model": "p10", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_0.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_0.json index fdd7421a49d..e2145b88696 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_0.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 9.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_3.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_3.json index bf9dbf3c137..2cfca4bd684 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_3.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_3.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 9.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_4.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_4.json index bf9dbf3c137..2cfca4bd684 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_4.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_4.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 9.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_5.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_5.json index cc2384deda6..4199255baf5 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/1_5.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/1_5.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.15, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.15 + } }, "channels": 1, "shaftDiameter": 9.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/2_0.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/2_0.json index 1faf7ce5e5f..90dca46ec79 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/2_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/2_0.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.17, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.17 + } }, "channels": 1, "shaftDiameter": 6.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/2_1.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/2_1.json index 0600d164c98..9ecf3e0909b 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/2_1.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/2_1.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.17, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.17 + } }, "channels": 1, "shaftDiameter": 6.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/2_2.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/2_2.json index 0600d164c98..9ecf3e0909b 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/2_2.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/2_2.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.17, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.17 + } }, "channels": 1, "shaftDiameter": 6.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_0.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_0.json index 1aa35765c0b..3475cb66bd4 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_0.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.15, "presses": 1, "speed": 5, "increment": 0.0, @@ -39,7 +38,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.15 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_3.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_3.json index 1aa35765c0b..3475cb66bd4 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_3.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_3.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.15, "presses": 1, "speed": 5, "increment": 0.0, @@ -39,7 +38,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.15 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_4.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_4.json index 9f88a64897d..1298625e578 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_4.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_4.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.2, "presses": 1, "speed": 10, "increment": 0.0, @@ -39,7 +38,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.2 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_5.json b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_5.json index 9f88a64897d..1298625e578 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p1000/3_5.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p1000/3_5.json @@ -4,7 +4,6 @@ "model": "p1000", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.2, "presses": 1, "speed": 10, "increment": 0.0, @@ -39,7 +38,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.2 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p20/2_0.json b/shared-data/pipette/definitions/2/general/single_channel/p20/2_0.json index 26e9a9c8f3f..1b5a8b392ae 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p20/2_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p20/2_0.json @@ -4,7 +4,6 @@ "model": "p20", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.1, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p20/2_1.json b/shared-data/pipette/definitions/2/general/single_channel/p20/2_1.json index 2a14e95d535..fd041576730 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p20/2_1.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p20/2_1.json @@ -4,7 +4,6 @@ "model": "p20", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.1, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p20/2_2.json b/shared-data/pipette/definitions/2/general/single_channel/p20/2_2.json index 2a14e95d535..fd041576730 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p20/2_2.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p20/2_2.json @@ -4,7 +4,6 @@ "model": "p20", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.1, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 1.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p300/1_0.json b/shared-data/pipette/definitions/2/general/single_channel/p300/1_0.json index 32b3a0c76cc..ebd868f0a03 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p300/1_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p300/1_0.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p300/1_3.json b/shared-data/pipette/definitions/2/general/single_channel/p300/1_3.json index eb334ea9835..426e391d012 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p300/1_3.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p300/1_3.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p300/1_4.json b/shared-data/pipette/definitions/2/general/single_channel/p300/1_4.json index 72c24e1ebdf..6d469c910ba 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p300/1_4.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p300/1_4.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p300/1_5.json b/shared-data/pipette/definitions/2/general/single_channel/p300/1_5.json index 72c24e1ebdf..6d469c910ba 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p300/1_5.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p300/1_5.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 5.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p300/2_0.json b/shared-data/pipette/definitions/2/general/single_channel/p300/2_0.json index 0d0e56e1368..d5aea0fa6cf 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p300/2_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p300/2_0.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.125, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.125 + } }, "channels": 1, "shaftDiameter": 3.5, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p300/2_1.json b/shared-data/pipette/definitions/2/general/single_channel/p300/2_1.json index 961c04a067d..d8c36634655 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p300/2_1.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p300/2_1.json @@ -4,7 +4,6 @@ "model": "p300", "displayCategory": "GEN2", "pickUpTipConfigurations": { - "current": 0.125, "speed": 10.0, "presses": 1, "increment": 0.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.125 + } }, "channels": 1, "shaftDiameter": 3.5, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/1_0.json b/shared-data/pipette/definitions/2/general/single_channel/p50/1_0.json index b413e7fc45f..f07934753bb 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/1_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/1_0.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/1_3.json b/shared-data/pipette/definitions/2/general/single_channel/p50/1_3.json index a355b7fa796..01bce6c8c90 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/1_3.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/1_3.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/1_4.json b/shared-data/pipette/definitions/2/general/single_channel/p50/1_4.json index 291b79b5751..a205e79cbc8 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/1_4.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/1_4.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "GEN1", "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -34,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/1_5.json b/shared-data/pipette/definitions/2/general/single_channel/p50/1_5.json index 96f0051da60..a205e79cbc8 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/1_5.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/1_5.json @@ -3,10 +3,7 @@ "displayName": "P50 Single-Channel GEN1", "model": "p50", "displayCategory": "GEN1", - "majorVersion": 1, - "minorVersion": 5, "pickUpTipConfigurations": { - "current": 0.1, "speed": 30.0, "presses": 3, "increment": 1.0, @@ -36,7 +33,10 @@ }, "partialTipConfigurations": { "partialTipSupported": false, - "availableConfigurations": null + "availableConfigurations": null, + "perTipPickupCurrent": { + "1": 0.1 + } }, "channels": 1, "shaftDiameter": 2.0, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/3_0.json b/shared-data/pipette/definitions/2/general/single_channel/p50/3_0.json index 7381b5fe52c..04aaedc093a 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/3_0.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/3_0.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.15, "presses": 1, "speed": 5, "increment": 0.0, @@ -45,7 +44,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.15 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/3_3.json b/shared-data/pipette/definitions/2/general/single_channel/p50/3_3.json index 7381b5fe52c..04aaedc093a 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/3_3.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/3_3.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.15, "presses": 1, "speed": 5, "increment": 0.0, @@ -45,7 +44,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.15 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/3_4.json b/shared-data/pipette/definitions/2/general/single_channel/p50/3_4.json index 7c606e35508..b46c3773f3c 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/3_4.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/3_4.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.2, "presses": 1, "speed": 10, "increment": 0.0, @@ -45,7 +44,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.2 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/general/single_channel/p50/3_5.json b/shared-data/pipette/definitions/2/general/single_channel/p50/3_5.json index 7c606e35508..b46c3773f3c 100644 --- a/shared-data/pipette/definitions/2/general/single_channel/p50/3_5.json +++ b/shared-data/pipette/definitions/2/general/single_channel/p50/3_5.json @@ -4,7 +4,6 @@ "model": "p50", "displayCategory": "FLEX", "pickUpTipConfigurations": { - "current": 0.2, "presses": 1, "speed": 10, "increment": 0.0, @@ -45,7 +44,10 @@ } }, "partialTipConfigurations": { - "partialTipSupported": false + "partialTipSupported": false, + "perTipPickupCurrent": { + "1": 0.2 + } }, "backCompatNames": [], "channels": 1, diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_0.json index 121ab9d8526..62ab42193de 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_0.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p10/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_3.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_3.json index 121ab9d8526..62ab42193de 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_3.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_3.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p10/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_4.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_4.json index 121ab9d8526..62ab42193de 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_4.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_4.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p10/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_5.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_5.json index 121ab9d8526..62ab42193de 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_5.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_5.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p10/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_6.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_6.json index 121ab9d8526..62ab42193de 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_6.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p10/1_6.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p10/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/1_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/1_0.json index 1000fbbc8d5..280d149c350 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/1_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/1_0.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_0.json index 1000fbbc8d5..280d149c350 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_0.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_3.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_3.json index 1000fbbc8d5..280d149c350 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_3.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_3.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_4.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_4.json index 1000fbbc8d5..280d149c350 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_4.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_4.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_5.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_5.json index 1000fbbc8d5..280d149c350 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_5.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p1000/3_5.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_0.json index 83a63481226..67fdef7b76b 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_0.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p20/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 19.4], - "B1": [0.0, 40.5, 19.4], - "C1": [0.0, 49.5, 19.4], - "D1": [0.0, 58.5, 19.4], - "E1": [0.0, 67.5, 19.4], - "F1": [0.0, 76.5, 19.4], - "G1": [0.0, 85.5, 19.4], - "H1": [0.0, 94.5, 19.4] + "B1": [0.0, 22.5, 19.4], + "C1": [0.0, 13.5, 19.4], + "D1": [0.0, 4.5, 19.4], + "E1": [0.0, -4.5, 19.4], + "F1": [0.0, -13.5, 19.4], + "G1": [0.0, -22.5, 19.4], + "H1": [0.0, -31.5, 19.4] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_1.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_1.json index 83a63481226..67fdef7b76b 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_1.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p20/2_1.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p20/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 19.4], - "B1": [0.0, 40.5, 19.4], - "C1": [0.0, 49.5, 19.4], - "D1": [0.0, 58.5, 19.4], - "E1": [0.0, 67.5, 19.4], - "F1": [0.0, 76.5, 19.4], - "G1": [0.0, 85.5, 19.4], - "H1": [0.0, 94.5, 19.4] + "B1": [0.0, 22.5, 19.4], + "C1": [0.0, 13.5, 19.4], + "D1": [0.0, 4.5, 19.4], + "E1": [0.0, -4.5, 19.4], + "F1": [0.0, -13.5, 19.4], + "G1": [0.0, -22.5, 19.4], + "H1": [0.0, -31.5, 19.4] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_0.json index 0575b8dca91..5a9430100c8 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_0.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p300/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_3.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_3.json index 0575b8dca91..5a9430100c8 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_3.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_3.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p300/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_4.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_4.json index 0575b8dca91..5a9430100c8 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_4.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_4.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p300/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_5.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_5.json index 0575b8dca91..5a9430100c8 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_5.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/1_5.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p300/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_0.json index d192e50d454..f79ca279af5 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_0.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p300/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 35.52], - "B1": [0.0, 40.5, 35.52], - "C1": [0.0, 49.5, 35.52], - "D1": [0.0, 58.5, 35.52], - "E1": [0.0, 67.5, 35.52], - "F1": [0.0, 76.5, 35.52], - "G1": [0.0, 85.5, 35.52], - "H1": [0.0, 94.5, 35.52] + "B1": [0.0, 22.5, 35.52], + "C1": [0.0, 13.5, 35.52], + "D1": [0.0, 4.5, 35.52], + "E1": [0.0, -4.5, 35.52], + "F1": [0.0, -13.5, 35.52], + "G1": [0.0, -22.5, 35.52], + "H1": [0.0, -31.5, 35.52] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_1.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_1.json index d192e50d454..f79ca279af5 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_1.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p300/2_1.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p300/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 35.52], - "B1": [0.0, 40.5, 35.52], - "C1": [0.0, 49.5, 35.52], - "D1": [0.0, 58.5, 35.52], - "E1": [0.0, 67.5, 35.52], - "F1": [0.0, 76.5, 35.52], - "G1": [0.0, 85.5, 35.52], - "H1": [0.0, 94.5, 35.52] + "B1": [0.0, 22.5, 35.52], + "C1": [0.0, 13.5, 35.52], + "D1": [0.0, 4.5, 35.52], + "E1": [0.0, -4.5, 35.52], + "F1": [0.0, -13.5, 35.52], + "G1": [0.0, -22.5, 35.52], + "H1": [0.0, -31.5, 35.52] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_0.json index e1e22f72c0c..167a0e0cf79 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_0.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p50/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_3.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_3.json index e1e22f72c0c..167a0e0cf79 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_3.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_3.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p50/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_4.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_4.json index e1e22f72c0c..167a0e0cf79 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_4.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_4.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p50/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_5.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_5.json index e1e22f72c0c..167a0e0cf79 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_5.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/1_5.json @@ -4,12 +4,12 @@ "pathTo3D": "pipette/definitions/2/geometry/eight_channel/p50/placeholder.gltf", "nozzleMap": { "A1": [0.0, 31.5, 0.8], - "B1": [0.0, 40.5, 0.8], - "C1": [0.0, 49.5, 0.8], - "D1": [0.0, 58.5, 0.8], - "E1": [0.0, 67.5, 0.8], - "F1": [0.0, 76.5, 0.8], - "G1": [0.0, 85.5, 0.8], - "H1": [0.0, 94.5, 0.8] + "B1": [0.0, 22.5, 0.8], + "C1": [0.0, 13.5, 0.8], + "D1": [0.0, 4.5, 0.8], + "E1": [0.0, -4.5, 0.8], + "F1": [0.0, -13.5, 0.8], + "G1": [0.0, -22.5, 0.8], + "H1": [0.0, -31.5, 0.8] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_0.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_0.json index 0e80b244be2..7fba327c671 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_0.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_0.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_3.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_3.json index 0e80b244be2..7fba327c671 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_3.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_3.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_4.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_4.json index 0e80b244be2..7fba327c671 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_4.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_4.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_5.json b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_5.json index 0e80b244be2..7fba327c671 100644 --- a/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_5.json +++ b/shared-data/pipette/definitions/2/geometry/eight_channel/p50/3_5.json @@ -4,12 +4,12 @@ "nozzleOffset": [-8.0, -16.0, -259.15], "nozzleMap": { "A1": [-8.0, -16.0, -259.15], - "B1": [-8.0, -7.0, -259.15], - "C1": [-8.0, 2.0, -259.15], - "D1": [-8.0, 11.0, -259.15], - "E1": [-8.0, 20.0, -259.15], - "F1": [-8.0, 29.0, -259.15], - "G1": [-8.0, 38.0, -259.15], - "H1": [-8.0, 47.0, -259.15] + "B1": [-8.0, -25.0, -259.15], + "C1": [-8.0, -34.0, -259.15], + "D1": [-8.0, -43.0, -259.15], + "E1": [-8.0, -52.0, -259.15], + "F1": [-8.0, -61.0, -259.15], + "G1": [-8.0, -70.0, -259.15], + "H1": [-8.0, -79.0, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/1_0.json b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/1_0.json index e65d6be1e6d..8924881092c 100644 --- a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/1_0.json +++ b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/1_0.json @@ -4,100 +4,100 @@ "nozzleOffset": [-36.0, -25.5, -259.15], "nozzleMap": { "A1": [-36.0, -25.5, -259.15], - "A2": [-45.0, -25.5, -259.15], - "A3": [-54.0, -25.5, -259.15], - "A4": [-63.0, -25.5, -259.15], - "A5": [-72.0, -25.5, -259.15], - "A6": [-81.0, -25.5, -259.15], - "A7": [-90.0, -25.5, -259.15], - "A8": [-99.0, -25.5, -259.15], - "A9": [-108.0, -25.5, -259.15], - "A10": [-117.0, -25.5, -259.15], - "A11": [-126.0, -25.5, -259.15], - "A12": [-135.0, -25.5, -259.15], - "B1": [-36.0, -16.5, -259.15], - "B2": [-45.0, -16.5, -259.15], - "B3": [-54.0, -16.5, -259.15], - "B4": [-63.0, -16.5, -259.15], - "B5": [-72.0, -16.5, -259.15], - "B6": [-81.0, -16.5, -259.15], - "B7": [-90.0, -16.5, -259.15], - "B8": [-99.0, -16.5, -259.15], - "B9": [-108.0, -16.5, -259.15], - "B10": [-117.0, -16.5, -259.15], - "B11": [-126.0, -16.5, -259.15], - "B12": [-135.0, -16.5, -259.15], - "C1": [-36.0, -7.5, -259.15], - "C2": [-45.0, -7.5, -259.15], - "C3": [-54.0, -7.5, -259.15], - "C4": [-63.0, -7.5, -259.15], - "C5": [-72.0, -7.5, -259.15], - "C6": [-81.0, -7.5, -259.15], - "C7": [-90.0, -7.5, -259.15], - "C8": [-99.0, -7.5, -259.15], - "C9": [-108.0, -7.5, -259.15], - "C10": [-117.0, -7.5, -259.15], - "C11": [-126.0, -7.5, -259.15], - "C12": [-135.0, -7.5, -259.15], - "D1": [-36.0, 1.5, -259.15], - "D2": [-45.0, 1.5, -259.15], - "D3": [-54.0, 1.5, -259.15], - "D4": [-63.0, 1.5, -259.15], - "D5": [-72.0, 1.5, -259.15], - "D6": [-81.0, 1.5, -259.15], - "D7": [-90.0, 1.5, -259.15], - "D8": [-99.0, 1.5, -259.15], - "D9": [-108.0, 1.5, -259.15], - "D10": [-117.0, 1.5, -259.15], - "D11": [-126.0, 1.5, -259.15], - "D12": [-135.0, 1.5, -259.15], - "E1": [-36.0, 10.5, -259.15], - "E2": [-45.0, 10.5, -259.15], - "E3": [-54.0, 10.5, -259.15], - "E4": [-63.0, 10.5, -259.15], - "E5": [-72.0, 10.5, -259.15], - "E6": [-81.0, 10.5, -259.15], - "E7": [-90.0, 10.5, -259.15], - "E8": [-99.0, 10.5, -259.15], - "E9": [-108.0, 10.5, -259.15], - "E10": [-117.0, 10.5, -259.15], - "E11": [-126.0, 10.5, -259.15], - "E12": [-135.0, 10.5, -259.15], - "F1": [-36.0, 19.5, -259.15], - "F2": [-45.0, 19.5, -259.15], - "F3": [-54.0, 19.5, -259.15], - "F4": [-63.0, 19.5, -259.15], - "F5": [-72.0, 19.5, -259.15], - "F6": [-81.0, 19.5, -259.15], - "F7": [-90.0, 19.5, -259.15], - "F8": [-99.0, 19.5, -259.15], - "F9": [-108.0, 19.5, -259.15], - "F10": [-117.0, 19.5, -259.15], - "F11": [-126.0, 19.5, -259.15], - "F12": [-135.0, 19.5, -259.15], - "G1": [-36.0, 28.5, -259.15], - "G2": [-45.0, 28.5, -259.15], - "G3": [-54.0, 28.5, -259.15], - "G4": [-63.0, 28.5, -259.15], - "G5": [-72.0, 28.5, -259.15], - "G6": [-81.0, 28.5, -259.15], - "G7": [-90.0, 28.5, -259.15], - "G8": [-99.0, 28.5, -259.15], - "G9": [-108.0, 28.5, -259.15], - "G10": [-117.0, 28.5, -259.15], - "G11": [-126.0, 28.5, -259.15], - "G12": [-135.0, 28.5, -259.15], - "H1": [-36.0, 37.5, -259.15], - "H2": [-45.0, 37.5, -259.15], - "H3": [-54.0, 37.5, -259.15], - "H4": [-63.0, 37.5, -259.15], - "H5": [-72.0, 37.5, -259.15], - "H6": [-81.0, 37.5, -259.15], - "H7": [-90.0, 37.5, -259.15], - "H8": [-99.0, 37.5, -259.15], - "H9": [-108.0, 37.5, -259.15], - "H10": [-117.0, 37.5, -259.15], - "H11": [-126.0, 37.5, -259.15], - "H12": [-135.0, 37.5, -259.15] + "A2": [-27.0, -25.5, -259.15], + "A3": [-18.0, -25.5, -259.15], + "A4": [-9.0, -25.5, -259.15], + "A5": [0.0, -25.5, -259.15], + "A6": [9.0, -25.5, -259.15], + "A7": [18.0, -25.5, -259.15], + "A8": [27.0, -25.5, -259.15], + "A9": [36.0, -25.5, -259.15], + "A10": [45.0, -25.5, -259.15], + "A11": [54.0, -25.5, -259.15], + "A12": [63.0, -25.5, -259.15], + "B1": [-36.0, -34.5, -259.15], + "B2": [-27.0, -34.5, -259.15], + "B3": [-18.0, -34.5, -259.15], + "B4": [-9.0, -34.5, -259.15], + "B5": [0.0, -34.5, -259.15], + "B6": [9.0, -34.5, -259.15], + "B7": [18.0, -34.5, -259.15], + "B8": [27.0, -34.5, -259.15], + "B9": [36.0, -34.5, -259.15], + "B10": [45.0, -34.5, -259.15], + "B11": [54.0, -34.5, -259.15], + "B12": [63.0, -34.5, -259.15], + "C1": [-36.0, -43.5, -259.15], + "C2": [-27.0, -43.5, -259.15], + "C3": [-18.0, -43.5, -259.15], + "C4": [-9.0, -43.5, -259.15], + "C5": [0.0, -43.5, -259.15], + "C6": [9.0, -43.5, -259.15], + "C7": [18.0, -43.5, -259.15], + "C8": [27.0, -43.5, -259.15], + "C9": [36.0, -43.5, -259.15], + "C10": [45.0, -43.5, -259.15], + "C11": [54.0, -43.5, -259.15], + "C12": [63.0, -43.5, -259.15], + "D1": [-36.0, -52.5, -259.15], + "D2": [-27.0, -52.5, -259.15], + "D3": [-18.0, -52.5, -259.15], + "D4": [-9.0, -52.5, -259.15], + "D5": [0.0, -52.5, -259.15], + "D6": [9.0, -52.5, -259.15], + "D7": [18.0, -52.5, -259.15], + "D8": [27.0, -52.5, -259.15], + "D9": [36.0, -52.5, -259.15], + "D10": [45.0, -52.5, -259.15], + "D11": [54.0, -52.5, -259.15], + "D12": [63.0, -52.5, -259.15], + "E1": [-36.0, -61.5, -259.15], + "E2": [-27.0, -61.5, -259.15], + "E3": [-18.0, -61.5, -259.15], + "E4": [-9.0, -61.5, -259.15], + "E5": [0.0, -61.5, -259.15], + "E6": [9.0, -61.5, -259.15], + "E7": [18.0, -61.5, -259.15], + "E8": [27.0, -61.5, -259.15], + "E9": [36.0, -61.5, -259.15], + "E10": [45.0, -61.5, -259.15], + "E11": [54.0, -61.5, -259.15], + "E12": [63.0, -61.5, -259.15], + "F1": [-36.0, -70.5, -259.15], + "F2": [-27.0, -70.5, -259.15], + "F3": [-18.0, -70.5, -259.15], + "F4": [-9.0, -70.5, -259.15], + "F5": [0.0, -70.5, -259.15], + "F6": [9.0, -70.5, -259.15], + "F7": [18.0, -70.5, -259.15], + "F8": [27.0, -70.5, -259.15], + "F9": [36.0, -70.5, -259.15], + "F10": [45.0, -70.5, -259.15], + "F11": [54.0, -70.5, -259.15], + "F12": [63.0, -70.5, -259.15], + "G1": [-36.0, -79.5, -259.15], + "G2": [-27.0, -79.5, -259.15], + "G3": [-18.0, -79.5, -259.15], + "G4": [-9.0, -79.5, -259.15], + "G5": [0.0, -79.5, -259.15], + "G6": [9.0, -79.5, -259.15], + "G7": [18.0, -79.5, -259.15], + "G8": [27.0, -79.5, -259.15], + "G9": [36.0, -79.5, -259.15], + "G10": [45.0, -79.5, -259.15], + "G11": [54.0, -79.5, -259.15], + "G12": [63.0, -79.5, -259.15], + "H1": [-36.0, -88.5, -259.15], + "H2": [-27.0, -88.5, -259.15], + "H3": [-18.0, -88.5, -259.15], + "H4": [-9.0, -88.5, -259.15], + "H5": [0.0, -88.5, -259.15], + "H6": [9.0, -88.5, -259.15], + "H7": [18.0, -88.5, -259.15], + "H8": [27.0, -88.5, -259.15], + "H9": [36.0, -88.5, -259.15], + "H10": [45.0, -88.5, -259.15], + "H11": [54.0, -88.5, -259.15], + "H12": [63.0, -88.5, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_0.json b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_0.json index e65d6be1e6d..8924881092c 100644 --- a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_0.json +++ b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_0.json @@ -4,100 +4,100 @@ "nozzleOffset": [-36.0, -25.5, -259.15], "nozzleMap": { "A1": [-36.0, -25.5, -259.15], - "A2": [-45.0, -25.5, -259.15], - "A3": [-54.0, -25.5, -259.15], - "A4": [-63.0, -25.5, -259.15], - "A5": [-72.0, -25.5, -259.15], - "A6": [-81.0, -25.5, -259.15], - "A7": [-90.0, -25.5, -259.15], - "A8": [-99.0, -25.5, -259.15], - "A9": [-108.0, -25.5, -259.15], - "A10": [-117.0, -25.5, -259.15], - "A11": [-126.0, -25.5, -259.15], - "A12": [-135.0, -25.5, -259.15], - "B1": [-36.0, -16.5, -259.15], - "B2": [-45.0, -16.5, -259.15], - "B3": [-54.0, -16.5, -259.15], - "B4": [-63.0, -16.5, -259.15], - "B5": [-72.0, -16.5, -259.15], - "B6": [-81.0, -16.5, -259.15], - "B7": [-90.0, -16.5, -259.15], - "B8": [-99.0, -16.5, -259.15], - "B9": [-108.0, -16.5, -259.15], - "B10": [-117.0, -16.5, -259.15], - "B11": [-126.0, -16.5, -259.15], - "B12": [-135.0, -16.5, -259.15], - "C1": [-36.0, -7.5, -259.15], - "C2": [-45.0, -7.5, -259.15], - "C3": [-54.0, -7.5, -259.15], - "C4": [-63.0, -7.5, -259.15], - "C5": [-72.0, -7.5, -259.15], - "C6": [-81.0, -7.5, -259.15], - "C7": [-90.0, -7.5, -259.15], - "C8": [-99.0, -7.5, -259.15], - "C9": [-108.0, -7.5, -259.15], - "C10": [-117.0, -7.5, -259.15], - "C11": [-126.0, -7.5, -259.15], - "C12": [-135.0, -7.5, -259.15], - "D1": [-36.0, 1.5, -259.15], - "D2": [-45.0, 1.5, -259.15], - "D3": [-54.0, 1.5, -259.15], - "D4": [-63.0, 1.5, -259.15], - "D5": [-72.0, 1.5, -259.15], - "D6": [-81.0, 1.5, -259.15], - "D7": [-90.0, 1.5, -259.15], - "D8": [-99.0, 1.5, -259.15], - "D9": [-108.0, 1.5, -259.15], - "D10": [-117.0, 1.5, -259.15], - "D11": [-126.0, 1.5, -259.15], - "D12": [-135.0, 1.5, -259.15], - "E1": [-36.0, 10.5, -259.15], - "E2": [-45.0, 10.5, -259.15], - "E3": [-54.0, 10.5, -259.15], - "E4": [-63.0, 10.5, -259.15], - "E5": [-72.0, 10.5, -259.15], - "E6": [-81.0, 10.5, -259.15], - "E7": [-90.0, 10.5, -259.15], - "E8": [-99.0, 10.5, -259.15], - "E9": [-108.0, 10.5, -259.15], - "E10": [-117.0, 10.5, -259.15], - "E11": [-126.0, 10.5, -259.15], - "E12": [-135.0, 10.5, -259.15], - "F1": [-36.0, 19.5, -259.15], - "F2": [-45.0, 19.5, -259.15], - "F3": [-54.0, 19.5, -259.15], - "F4": [-63.0, 19.5, -259.15], - "F5": [-72.0, 19.5, -259.15], - "F6": [-81.0, 19.5, -259.15], - "F7": [-90.0, 19.5, -259.15], - "F8": [-99.0, 19.5, -259.15], - "F9": [-108.0, 19.5, -259.15], - "F10": [-117.0, 19.5, -259.15], - "F11": [-126.0, 19.5, -259.15], - "F12": [-135.0, 19.5, -259.15], - "G1": [-36.0, 28.5, -259.15], - "G2": [-45.0, 28.5, -259.15], - "G3": [-54.0, 28.5, -259.15], - "G4": [-63.0, 28.5, -259.15], - "G5": [-72.0, 28.5, -259.15], - "G6": [-81.0, 28.5, -259.15], - "G7": [-90.0, 28.5, -259.15], - "G8": [-99.0, 28.5, -259.15], - "G9": [-108.0, 28.5, -259.15], - "G10": [-117.0, 28.5, -259.15], - "G11": [-126.0, 28.5, -259.15], - "G12": [-135.0, 28.5, -259.15], - "H1": [-36.0, 37.5, -259.15], - "H2": [-45.0, 37.5, -259.15], - "H3": [-54.0, 37.5, -259.15], - "H4": [-63.0, 37.5, -259.15], - "H5": [-72.0, 37.5, -259.15], - "H6": [-81.0, 37.5, -259.15], - "H7": [-90.0, 37.5, -259.15], - "H8": [-99.0, 37.5, -259.15], - "H9": [-108.0, 37.5, -259.15], - "H10": [-117.0, 37.5, -259.15], - "H11": [-126.0, 37.5, -259.15], - "H12": [-135.0, 37.5, -259.15] + "A2": [-27.0, -25.5, -259.15], + "A3": [-18.0, -25.5, -259.15], + "A4": [-9.0, -25.5, -259.15], + "A5": [0.0, -25.5, -259.15], + "A6": [9.0, -25.5, -259.15], + "A7": [18.0, -25.5, -259.15], + "A8": [27.0, -25.5, -259.15], + "A9": [36.0, -25.5, -259.15], + "A10": [45.0, -25.5, -259.15], + "A11": [54.0, -25.5, -259.15], + "A12": [63.0, -25.5, -259.15], + "B1": [-36.0, -34.5, -259.15], + "B2": [-27.0, -34.5, -259.15], + "B3": [-18.0, -34.5, -259.15], + "B4": [-9.0, -34.5, -259.15], + "B5": [0.0, -34.5, -259.15], + "B6": [9.0, -34.5, -259.15], + "B7": [18.0, -34.5, -259.15], + "B8": [27.0, -34.5, -259.15], + "B9": [36.0, -34.5, -259.15], + "B10": [45.0, -34.5, -259.15], + "B11": [54.0, -34.5, -259.15], + "B12": [63.0, -34.5, -259.15], + "C1": [-36.0, -43.5, -259.15], + "C2": [-27.0, -43.5, -259.15], + "C3": [-18.0, -43.5, -259.15], + "C4": [-9.0, -43.5, -259.15], + "C5": [0.0, -43.5, -259.15], + "C6": [9.0, -43.5, -259.15], + "C7": [18.0, -43.5, -259.15], + "C8": [27.0, -43.5, -259.15], + "C9": [36.0, -43.5, -259.15], + "C10": [45.0, -43.5, -259.15], + "C11": [54.0, -43.5, -259.15], + "C12": [63.0, -43.5, -259.15], + "D1": [-36.0, -52.5, -259.15], + "D2": [-27.0, -52.5, -259.15], + "D3": [-18.0, -52.5, -259.15], + "D4": [-9.0, -52.5, -259.15], + "D5": [0.0, -52.5, -259.15], + "D6": [9.0, -52.5, -259.15], + "D7": [18.0, -52.5, -259.15], + "D8": [27.0, -52.5, -259.15], + "D9": [36.0, -52.5, -259.15], + "D10": [45.0, -52.5, -259.15], + "D11": [54.0, -52.5, -259.15], + "D12": [63.0, -52.5, -259.15], + "E1": [-36.0, -61.5, -259.15], + "E2": [-27.0, -61.5, -259.15], + "E3": [-18.0, -61.5, -259.15], + "E4": [-9.0, -61.5, -259.15], + "E5": [0.0, -61.5, -259.15], + "E6": [9.0, -61.5, -259.15], + "E7": [18.0, -61.5, -259.15], + "E8": [27.0, -61.5, -259.15], + "E9": [36.0, -61.5, -259.15], + "E10": [45.0, -61.5, -259.15], + "E11": [54.0, -61.5, -259.15], + "E12": [63.0, -61.5, -259.15], + "F1": [-36.0, -70.5, -259.15], + "F2": [-27.0, -70.5, -259.15], + "F3": [-18.0, -70.5, -259.15], + "F4": [-9.0, -70.5, -259.15], + "F5": [0.0, -70.5, -259.15], + "F6": [9.0, -70.5, -259.15], + "F7": [18.0, -70.5, -259.15], + "F8": [27.0, -70.5, -259.15], + "F9": [36.0, -70.5, -259.15], + "F10": [45.0, -70.5, -259.15], + "F11": [54.0, -70.5, -259.15], + "F12": [63.0, -70.5, -259.15], + "G1": [-36.0, -79.5, -259.15], + "G2": [-27.0, -79.5, -259.15], + "G3": [-18.0, -79.5, -259.15], + "G4": [-9.0, -79.5, -259.15], + "G5": [0.0, -79.5, -259.15], + "G6": [9.0, -79.5, -259.15], + "G7": [18.0, -79.5, -259.15], + "G8": [27.0, -79.5, -259.15], + "G9": [36.0, -79.5, -259.15], + "G10": [45.0, -79.5, -259.15], + "G11": [54.0, -79.5, -259.15], + "G12": [63.0, -79.5, -259.15], + "H1": [-36.0, -88.5, -259.15], + "H2": [-27.0, -88.5, -259.15], + "H3": [-18.0, -88.5, -259.15], + "H4": [-9.0, -88.5, -259.15], + "H5": [0.0, -88.5, -259.15], + "H6": [9.0, -88.5, -259.15], + "H7": [18.0, -88.5, -259.15], + "H8": [27.0, -88.5, -259.15], + "H9": [36.0, -88.5, -259.15], + "H10": [45.0, -88.5, -259.15], + "H11": [54.0, -88.5, -259.15], + "H12": [63.0, -88.5, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_3.json b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_3.json index e65d6be1e6d..8924881092c 100644 --- a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_3.json +++ b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_3.json @@ -4,100 +4,100 @@ "nozzleOffset": [-36.0, -25.5, -259.15], "nozzleMap": { "A1": [-36.0, -25.5, -259.15], - "A2": [-45.0, -25.5, -259.15], - "A3": [-54.0, -25.5, -259.15], - "A4": [-63.0, -25.5, -259.15], - "A5": [-72.0, -25.5, -259.15], - "A6": [-81.0, -25.5, -259.15], - "A7": [-90.0, -25.5, -259.15], - "A8": [-99.0, -25.5, -259.15], - "A9": [-108.0, -25.5, -259.15], - "A10": [-117.0, -25.5, -259.15], - "A11": [-126.0, -25.5, -259.15], - "A12": [-135.0, -25.5, -259.15], - "B1": [-36.0, -16.5, -259.15], - "B2": [-45.0, -16.5, -259.15], - "B3": [-54.0, -16.5, -259.15], - "B4": [-63.0, -16.5, -259.15], - "B5": [-72.0, -16.5, -259.15], - "B6": [-81.0, -16.5, -259.15], - "B7": [-90.0, -16.5, -259.15], - "B8": [-99.0, -16.5, -259.15], - "B9": [-108.0, -16.5, -259.15], - "B10": [-117.0, -16.5, -259.15], - "B11": [-126.0, -16.5, -259.15], - "B12": [-135.0, -16.5, -259.15], - "C1": [-36.0, -7.5, -259.15], - "C2": [-45.0, -7.5, -259.15], - "C3": [-54.0, -7.5, -259.15], - "C4": [-63.0, -7.5, -259.15], - "C5": [-72.0, -7.5, -259.15], - "C6": [-81.0, -7.5, -259.15], - "C7": [-90.0, -7.5, -259.15], - "C8": [-99.0, -7.5, -259.15], - "C9": [-108.0, -7.5, -259.15], - "C10": [-117.0, -7.5, -259.15], - "C11": [-126.0, -7.5, -259.15], - "C12": [-135.0, -7.5, -259.15], - "D1": [-36.0, 1.5, -259.15], - "D2": [-45.0, 1.5, -259.15], - "D3": [-54.0, 1.5, -259.15], - "D4": [-63.0, 1.5, -259.15], - "D5": [-72.0, 1.5, -259.15], - "D6": [-81.0, 1.5, -259.15], - "D7": [-90.0, 1.5, -259.15], - "D8": [-99.0, 1.5, -259.15], - "D9": [-108.0, 1.5, -259.15], - "D10": [-117.0, 1.5, -259.15], - "D11": [-126.0, 1.5, -259.15], - "D12": [-135.0, 1.5, -259.15], - "E1": [-36.0, 10.5, -259.15], - "E2": [-45.0, 10.5, -259.15], - "E3": [-54.0, 10.5, -259.15], - "E4": [-63.0, 10.5, -259.15], - "E5": [-72.0, 10.5, -259.15], - "E6": [-81.0, 10.5, -259.15], - "E7": [-90.0, 10.5, -259.15], - "E8": [-99.0, 10.5, -259.15], - "E9": [-108.0, 10.5, -259.15], - "E10": [-117.0, 10.5, -259.15], - "E11": [-126.0, 10.5, -259.15], - "E12": [-135.0, 10.5, -259.15], - "F1": [-36.0, 19.5, -259.15], - "F2": [-45.0, 19.5, -259.15], - "F3": [-54.0, 19.5, -259.15], - "F4": [-63.0, 19.5, -259.15], - "F5": [-72.0, 19.5, -259.15], - "F6": [-81.0, 19.5, -259.15], - "F7": [-90.0, 19.5, -259.15], - "F8": [-99.0, 19.5, -259.15], - "F9": [-108.0, 19.5, -259.15], - "F10": [-117.0, 19.5, -259.15], - "F11": [-126.0, 19.5, -259.15], - "F12": [-135.0, 19.5, -259.15], - "G1": [-36.0, 28.5, -259.15], - "G2": [-45.0, 28.5, -259.15], - "G3": [-54.0, 28.5, -259.15], - "G4": [-63.0, 28.5, -259.15], - "G5": [-72.0, 28.5, -259.15], - "G6": [-81.0, 28.5, -259.15], - "G7": [-90.0, 28.5, -259.15], - "G8": [-99.0, 28.5, -259.15], - "G9": [-108.0, 28.5, -259.15], - "G10": [-117.0, 28.5, -259.15], - "G11": [-126.0, 28.5, -259.15], - "G12": [-135.0, 28.5, -259.15], - "H1": [-36.0, 37.5, -259.15], - "H2": [-45.0, 37.5, -259.15], - "H3": [-54.0, 37.5, -259.15], - "H4": [-63.0, 37.5, -259.15], - "H5": [-72.0, 37.5, -259.15], - "H6": [-81.0, 37.5, -259.15], - "H7": [-90.0, 37.5, -259.15], - "H8": [-99.0, 37.5, -259.15], - "H9": [-108.0, 37.5, -259.15], - "H10": [-117.0, 37.5, -259.15], - "H11": [-126.0, 37.5, -259.15], - "H12": [-135.0, 37.5, -259.15] + "A2": [-27.0, -25.5, -259.15], + "A3": [-18.0, -25.5, -259.15], + "A4": [-9.0, -25.5, -259.15], + "A5": [0.0, -25.5, -259.15], + "A6": [9.0, -25.5, -259.15], + "A7": [18.0, -25.5, -259.15], + "A8": [27.0, -25.5, -259.15], + "A9": [36.0, -25.5, -259.15], + "A10": [45.0, -25.5, -259.15], + "A11": [54.0, -25.5, -259.15], + "A12": [63.0, -25.5, -259.15], + "B1": [-36.0, -34.5, -259.15], + "B2": [-27.0, -34.5, -259.15], + "B3": [-18.0, -34.5, -259.15], + "B4": [-9.0, -34.5, -259.15], + "B5": [0.0, -34.5, -259.15], + "B6": [9.0, -34.5, -259.15], + "B7": [18.0, -34.5, -259.15], + "B8": [27.0, -34.5, -259.15], + "B9": [36.0, -34.5, -259.15], + "B10": [45.0, -34.5, -259.15], + "B11": [54.0, -34.5, -259.15], + "B12": [63.0, -34.5, -259.15], + "C1": [-36.0, -43.5, -259.15], + "C2": [-27.0, -43.5, -259.15], + "C3": [-18.0, -43.5, -259.15], + "C4": [-9.0, -43.5, -259.15], + "C5": [0.0, -43.5, -259.15], + "C6": [9.0, -43.5, -259.15], + "C7": [18.0, -43.5, -259.15], + "C8": [27.0, -43.5, -259.15], + "C9": [36.0, -43.5, -259.15], + "C10": [45.0, -43.5, -259.15], + "C11": [54.0, -43.5, -259.15], + "C12": [63.0, -43.5, -259.15], + "D1": [-36.0, -52.5, -259.15], + "D2": [-27.0, -52.5, -259.15], + "D3": [-18.0, -52.5, -259.15], + "D4": [-9.0, -52.5, -259.15], + "D5": [0.0, -52.5, -259.15], + "D6": [9.0, -52.5, -259.15], + "D7": [18.0, -52.5, -259.15], + "D8": [27.0, -52.5, -259.15], + "D9": [36.0, -52.5, -259.15], + "D10": [45.0, -52.5, -259.15], + "D11": [54.0, -52.5, -259.15], + "D12": [63.0, -52.5, -259.15], + "E1": [-36.0, -61.5, -259.15], + "E2": [-27.0, -61.5, -259.15], + "E3": [-18.0, -61.5, -259.15], + "E4": [-9.0, -61.5, -259.15], + "E5": [0.0, -61.5, -259.15], + "E6": [9.0, -61.5, -259.15], + "E7": [18.0, -61.5, -259.15], + "E8": [27.0, -61.5, -259.15], + "E9": [36.0, -61.5, -259.15], + "E10": [45.0, -61.5, -259.15], + "E11": [54.0, -61.5, -259.15], + "E12": [63.0, -61.5, -259.15], + "F1": [-36.0, -70.5, -259.15], + "F2": [-27.0, -70.5, -259.15], + "F3": [-18.0, -70.5, -259.15], + "F4": [-9.0, -70.5, -259.15], + "F5": [0.0, -70.5, -259.15], + "F6": [9.0, -70.5, -259.15], + "F7": [18.0, -70.5, -259.15], + "F8": [27.0, -70.5, -259.15], + "F9": [36.0, -70.5, -259.15], + "F10": [45.0, -70.5, -259.15], + "F11": [54.0, -70.5, -259.15], + "F12": [63.0, -70.5, -259.15], + "G1": [-36.0, -79.5, -259.15], + "G2": [-27.0, -79.5, -259.15], + "G3": [-18.0, -79.5, -259.15], + "G4": [-9.0, -79.5, -259.15], + "G5": [0.0, -79.5, -259.15], + "G6": [9.0, -79.5, -259.15], + "G7": [18.0, -79.5, -259.15], + "G8": [27.0, -79.5, -259.15], + "G9": [36.0, -79.5, -259.15], + "G10": [45.0, -79.5, -259.15], + "G11": [54.0, -79.5, -259.15], + "G12": [63.0, -79.5, -259.15], + "H1": [-36.0, -88.5, -259.15], + "H2": [-27.0, -88.5, -259.15], + "H3": [-18.0, -88.5, -259.15], + "H4": [-9.0, -88.5, -259.15], + "H5": [0.0, -88.5, -259.15], + "H6": [9.0, -88.5, -259.15], + "H7": [18.0, -88.5, -259.15], + "H8": [27.0, -88.5, -259.15], + "H9": [36.0, -88.5, -259.15], + "H10": [45.0, -88.5, -259.15], + "H11": [54.0, -88.5, -259.15], + "H12": [63.0, -88.5, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_4.json b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_4.json index e65d6be1e6d..8924881092c 100644 --- a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_4.json +++ b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_4.json @@ -4,100 +4,100 @@ "nozzleOffset": [-36.0, -25.5, -259.15], "nozzleMap": { "A1": [-36.0, -25.5, -259.15], - "A2": [-45.0, -25.5, -259.15], - "A3": [-54.0, -25.5, -259.15], - "A4": [-63.0, -25.5, -259.15], - "A5": [-72.0, -25.5, -259.15], - "A6": [-81.0, -25.5, -259.15], - "A7": [-90.0, -25.5, -259.15], - "A8": [-99.0, -25.5, -259.15], - "A9": [-108.0, -25.5, -259.15], - "A10": [-117.0, -25.5, -259.15], - "A11": [-126.0, -25.5, -259.15], - "A12": [-135.0, -25.5, -259.15], - "B1": [-36.0, -16.5, -259.15], - "B2": [-45.0, -16.5, -259.15], - "B3": [-54.0, -16.5, -259.15], - "B4": [-63.0, -16.5, -259.15], - "B5": [-72.0, -16.5, -259.15], - "B6": [-81.0, -16.5, -259.15], - "B7": [-90.0, -16.5, -259.15], - "B8": [-99.0, -16.5, -259.15], - "B9": [-108.0, -16.5, -259.15], - "B10": [-117.0, -16.5, -259.15], - "B11": [-126.0, -16.5, -259.15], - "B12": [-135.0, -16.5, -259.15], - "C1": [-36.0, -7.5, -259.15], - "C2": [-45.0, -7.5, -259.15], - "C3": [-54.0, -7.5, -259.15], - "C4": [-63.0, -7.5, -259.15], - "C5": [-72.0, -7.5, -259.15], - "C6": [-81.0, -7.5, -259.15], - "C7": [-90.0, -7.5, -259.15], - "C8": [-99.0, -7.5, -259.15], - "C9": [-108.0, -7.5, -259.15], - "C10": [-117.0, -7.5, -259.15], - "C11": [-126.0, -7.5, -259.15], - "C12": [-135.0, -7.5, -259.15], - "D1": [-36.0, 1.5, -259.15], - "D2": [-45.0, 1.5, -259.15], - "D3": [-54.0, 1.5, -259.15], - "D4": [-63.0, 1.5, -259.15], - "D5": [-72.0, 1.5, -259.15], - "D6": [-81.0, 1.5, -259.15], - "D7": [-90.0, 1.5, -259.15], - "D8": [-99.0, 1.5, -259.15], - "D9": [-108.0, 1.5, -259.15], - "D10": [-117.0, 1.5, -259.15], - "D11": [-126.0, 1.5, -259.15], - "D12": [-135.0, 1.5, -259.15], - "E1": [-36.0, 10.5, -259.15], - "E2": [-45.0, 10.5, -259.15], - "E3": [-54.0, 10.5, -259.15], - "E4": [-63.0, 10.5, -259.15], - "E5": [-72.0, 10.5, -259.15], - "E6": [-81.0, 10.5, -259.15], - "E7": [-90.0, 10.5, -259.15], - "E8": [-99.0, 10.5, -259.15], - "E9": [-108.0, 10.5, -259.15], - "E10": [-117.0, 10.5, -259.15], - "E11": [-126.0, 10.5, -259.15], - "E12": [-135.0, 10.5, -259.15], - "F1": [-36.0, 19.5, -259.15], - "F2": [-45.0, 19.5, -259.15], - "F3": [-54.0, 19.5, -259.15], - "F4": [-63.0, 19.5, -259.15], - "F5": [-72.0, 19.5, -259.15], - "F6": [-81.0, 19.5, -259.15], - "F7": [-90.0, 19.5, -259.15], - "F8": [-99.0, 19.5, -259.15], - "F9": [-108.0, 19.5, -259.15], - "F10": [-117.0, 19.5, -259.15], - "F11": [-126.0, 19.5, -259.15], - "F12": [-135.0, 19.5, -259.15], - "G1": [-36.0, 28.5, -259.15], - "G2": [-45.0, 28.5, -259.15], - "G3": [-54.0, 28.5, -259.15], - "G4": [-63.0, 28.5, -259.15], - "G5": [-72.0, 28.5, -259.15], - "G6": [-81.0, 28.5, -259.15], - "G7": [-90.0, 28.5, -259.15], - "G8": [-99.0, 28.5, -259.15], - "G9": [-108.0, 28.5, -259.15], - "G10": [-117.0, 28.5, -259.15], - "G11": [-126.0, 28.5, -259.15], - "G12": [-135.0, 28.5, -259.15], - "H1": [-36.0, 37.5, -259.15], - "H2": [-45.0, 37.5, -259.15], - "H3": [-54.0, 37.5, -259.15], - "H4": [-63.0, 37.5, -259.15], - "H5": [-72.0, 37.5, -259.15], - "H6": [-81.0, 37.5, -259.15], - "H7": [-90.0, 37.5, -259.15], - "H8": [-99.0, 37.5, -259.15], - "H9": [-108.0, 37.5, -259.15], - "H10": [-117.0, 37.5, -259.15], - "H11": [-126.0, 37.5, -259.15], - "H12": [-135.0, 37.5, -259.15] + "A2": [-27.0, -25.5, -259.15], + "A3": [-18.0, -25.5, -259.15], + "A4": [-9.0, -25.5, -259.15], + "A5": [0.0, -25.5, -259.15], + "A6": [9.0, -25.5, -259.15], + "A7": [18.0, -25.5, -259.15], + "A8": [27.0, -25.5, -259.15], + "A9": [36.0, -25.5, -259.15], + "A10": [45.0, -25.5, -259.15], + "A11": [54.0, -25.5, -259.15], + "A12": [63.0, -25.5, -259.15], + "B1": [-36.0, -34.5, -259.15], + "B2": [-27.0, -34.5, -259.15], + "B3": [-18.0, -34.5, -259.15], + "B4": [-9.0, -34.5, -259.15], + "B5": [0.0, -34.5, -259.15], + "B6": [9.0, -34.5, -259.15], + "B7": [18.0, -34.5, -259.15], + "B8": [27.0, -34.5, -259.15], + "B9": [36.0, -34.5, -259.15], + "B10": [45.0, -34.5, -259.15], + "B11": [54.0, -34.5, -259.15], + "B12": [63.0, -34.5, -259.15], + "C1": [-36.0, -43.5, -259.15], + "C2": [-27.0, -43.5, -259.15], + "C3": [-18.0, -43.5, -259.15], + "C4": [-9.0, -43.5, -259.15], + "C5": [0.0, -43.5, -259.15], + "C6": [9.0, -43.5, -259.15], + "C7": [18.0, -43.5, -259.15], + "C8": [27.0, -43.5, -259.15], + "C9": [36.0, -43.5, -259.15], + "C10": [45.0, -43.5, -259.15], + "C11": [54.0, -43.5, -259.15], + "C12": [63.0, -43.5, -259.15], + "D1": [-36.0, -52.5, -259.15], + "D2": [-27.0, -52.5, -259.15], + "D3": [-18.0, -52.5, -259.15], + "D4": [-9.0, -52.5, -259.15], + "D5": [0.0, -52.5, -259.15], + "D6": [9.0, -52.5, -259.15], + "D7": [18.0, -52.5, -259.15], + "D8": [27.0, -52.5, -259.15], + "D9": [36.0, -52.5, -259.15], + "D10": [45.0, -52.5, -259.15], + "D11": [54.0, -52.5, -259.15], + "D12": [63.0, -52.5, -259.15], + "E1": [-36.0, -61.5, -259.15], + "E2": [-27.0, -61.5, -259.15], + "E3": [-18.0, -61.5, -259.15], + "E4": [-9.0, -61.5, -259.15], + "E5": [0.0, -61.5, -259.15], + "E6": [9.0, -61.5, -259.15], + "E7": [18.0, -61.5, -259.15], + "E8": [27.0, -61.5, -259.15], + "E9": [36.0, -61.5, -259.15], + "E10": [45.0, -61.5, -259.15], + "E11": [54.0, -61.5, -259.15], + "E12": [63.0, -61.5, -259.15], + "F1": [-36.0, -70.5, -259.15], + "F2": [-27.0, -70.5, -259.15], + "F3": [-18.0, -70.5, -259.15], + "F4": [-9.0, -70.5, -259.15], + "F5": [0.0, -70.5, -259.15], + "F6": [9.0, -70.5, -259.15], + "F7": [18.0, -70.5, -259.15], + "F8": [27.0, -70.5, -259.15], + "F9": [36.0, -70.5, -259.15], + "F10": [45.0, -70.5, -259.15], + "F11": [54.0, -70.5, -259.15], + "F12": [63.0, -70.5, -259.15], + "G1": [-36.0, -79.5, -259.15], + "G2": [-27.0, -79.5, -259.15], + "G3": [-18.0, -79.5, -259.15], + "G4": [-9.0, -79.5, -259.15], + "G5": [0.0, -79.5, -259.15], + "G6": [9.0, -79.5, -259.15], + "G7": [18.0, -79.5, -259.15], + "G8": [27.0, -79.5, -259.15], + "G9": [36.0, -79.5, -259.15], + "G10": [45.0, -79.5, -259.15], + "G11": [54.0, -79.5, -259.15], + "G12": [63.0, -79.5, -259.15], + "H1": [-36.0, -88.5, -259.15], + "H2": [-27.0, -88.5, -259.15], + "H3": [-18.0, -88.5, -259.15], + "H4": [-9.0, -88.5, -259.15], + "H5": [0.0, -88.5, -259.15], + "H6": [9.0, -88.5, -259.15], + "H7": [18.0, -88.5, -259.15], + "H8": [27.0, -88.5, -259.15], + "H9": [36.0, -88.5, -259.15], + "H10": [45.0, -88.5, -259.15], + "H11": [54.0, -88.5, -259.15], + "H12": [63.0, -88.5, -259.15] } } diff --git a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_5.json b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_5.json index e65d6be1e6d..8924881092c 100644 --- a/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_5.json +++ b/shared-data/pipette/definitions/2/geometry/ninety_six_channel/p1000/3_5.json @@ -4,100 +4,100 @@ "nozzleOffset": [-36.0, -25.5, -259.15], "nozzleMap": { "A1": [-36.0, -25.5, -259.15], - "A2": [-45.0, -25.5, -259.15], - "A3": [-54.0, -25.5, -259.15], - "A4": [-63.0, -25.5, -259.15], - "A5": [-72.0, -25.5, -259.15], - "A6": [-81.0, -25.5, -259.15], - "A7": [-90.0, -25.5, -259.15], - "A8": [-99.0, -25.5, -259.15], - "A9": [-108.0, -25.5, -259.15], - "A10": [-117.0, -25.5, -259.15], - "A11": [-126.0, -25.5, -259.15], - "A12": [-135.0, -25.5, -259.15], - "B1": [-36.0, -16.5, -259.15], - "B2": [-45.0, -16.5, -259.15], - "B3": [-54.0, -16.5, -259.15], - "B4": [-63.0, -16.5, -259.15], - "B5": [-72.0, -16.5, -259.15], - "B6": [-81.0, -16.5, -259.15], - "B7": [-90.0, -16.5, -259.15], - "B8": [-99.0, -16.5, -259.15], - "B9": [-108.0, -16.5, -259.15], - "B10": [-117.0, -16.5, -259.15], - "B11": [-126.0, -16.5, -259.15], - "B12": [-135.0, -16.5, -259.15], - "C1": [-36.0, -7.5, -259.15], - "C2": [-45.0, -7.5, -259.15], - "C3": [-54.0, -7.5, -259.15], - "C4": [-63.0, -7.5, -259.15], - "C5": [-72.0, -7.5, -259.15], - "C6": [-81.0, -7.5, -259.15], - "C7": [-90.0, -7.5, -259.15], - "C8": [-99.0, -7.5, -259.15], - "C9": [-108.0, -7.5, -259.15], - "C10": [-117.0, -7.5, -259.15], - "C11": [-126.0, -7.5, -259.15], - "C12": [-135.0, -7.5, -259.15], - "D1": [-36.0, 1.5, -259.15], - "D2": [-45.0, 1.5, -259.15], - "D3": [-54.0, 1.5, -259.15], - "D4": [-63.0, 1.5, -259.15], - "D5": [-72.0, 1.5, -259.15], - "D6": [-81.0, 1.5, -259.15], - "D7": [-90.0, 1.5, -259.15], - "D8": [-99.0, 1.5, -259.15], - "D9": [-108.0, 1.5, -259.15], - "D10": [-117.0, 1.5, -259.15], - "D11": [-126.0, 1.5, -259.15], - "D12": [-135.0, 1.5, -259.15], - "E1": [-36.0, 10.5, -259.15], - "E2": [-45.0, 10.5, -259.15], - "E3": [-54.0, 10.5, -259.15], - "E4": [-63.0, 10.5, -259.15], - "E5": [-72.0, 10.5, -259.15], - "E6": [-81.0, 10.5, -259.15], - "E7": [-90.0, 10.5, -259.15], - "E8": [-99.0, 10.5, -259.15], - "E9": [-108.0, 10.5, -259.15], - "E10": [-117.0, 10.5, -259.15], - "E11": [-126.0, 10.5, -259.15], - "E12": [-135.0, 10.5, -259.15], - "F1": [-36.0, 19.5, -259.15], - "F2": [-45.0, 19.5, -259.15], - "F3": [-54.0, 19.5, -259.15], - "F4": [-63.0, 19.5, -259.15], - "F5": [-72.0, 19.5, -259.15], - "F6": [-81.0, 19.5, -259.15], - "F7": [-90.0, 19.5, -259.15], - "F8": [-99.0, 19.5, -259.15], - "F9": [-108.0, 19.5, -259.15], - "F10": [-117.0, 19.5, -259.15], - "F11": [-126.0, 19.5, -259.15], - "F12": [-135.0, 19.5, -259.15], - "G1": [-36.0, 28.5, -259.15], - "G2": [-45.0, 28.5, -259.15], - "G3": [-54.0, 28.5, -259.15], - "G4": [-63.0, 28.5, -259.15], - "G5": [-72.0, 28.5, -259.15], - "G6": [-81.0, 28.5, -259.15], - "G7": [-90.0, 28.5, -259.15], - "G8": [-99.0, 28.5, -259.15], - "G9": [-108.0, 28.5, -259.15], - "G10": [-117.0, 28.5, -259.15], - "G11": [-126.0, 28.5, -259.15], - "G12": [-135.0, 28.5, -259.15], - "H1": [-36.0, 37.5, -259.15], - "H2": [-45.0, 37.5, -259.15], - "H3": [-54.0, 37.5, -259.15], - "H4": [-63.0, 37.5, -259.15], - "H5": [-72.0, 37.5, -259.15], - "H6": [-81.0, 37.5, -259.15], - "H7": [-90.0, 37.5, -259.15], - "H8": [-99.0, 37.5, -259.15], - "H9": [-108.0, 37.5, -259.15], - "H10": [-117.0, 37.5, -259.15], - "H11": [-126.0, 37.5, -259.15], - "H12": [-135.0, 37.5, -259.15] + "A2": [-27.0, -25.5, -259.15], + "A3": [-18.0, -25.5, -259.15], + "A4": [-9.0, -25.5, -259.15], + "A5": [0.0, -25.5, -259.15], + "A6": [9.0, -25.5, -259.15], + "A7": [18.0, -25.5, -259.15], + "A8": [27.0, -25.5, -259.15], + "A9": [36.0, -25.5, -259.15], + "A10": [45.0, -25.5, -259.15], + "A11": [54.0, -25.5, -259.15], + "A12": [63.0, -25.5, -259.15], + "B1": [-36.0, -34.5, -259.15], + "B2": [-27.0, -34.5, -259.15], + "B3": [-18.0, -34.5, -259.15], + "B4": [-9.0, -34.5, -259.15], + "B5": [0.0, -34.5, -259.15], + "B6": [9.0, -34.5, -259.15], + "B7": [18.0, -34.5, -259.15], + "B8": [27.0, -34.5, -259.15], + "B9": [36.0, -34.5, -259.15], + "B10": [45.0, -34.5, -259.15], + "B11": [54.0, -34.5, -259.15], + "B12": [63.0, -34.5, -259.15], + "C1": [-36.0, -43.5, -259.15], + "C2": [-27.0, -43.5, -259.15], + "C3": [-18.0, -43.5, -259.15], + "C4": [-9.0, -43.5, -259.15], + "C5": [0.0, -43.5, -259.15], + "C6": [9.0, -43.5, -259.15], + "C7": [18.0, -43.5, -259.15], + "C8": [27.0, -43.5, -259.15], + "C9": [36.0, -43.5, -259.15], + "C10": [45.0, -43.5, -259.15], + "C11": [54.0, -43.5, -259.15], + "C12": [63.0, -43.5, -259.15], + "D1": [-36.0, -52.5, -259.15], + "D2": [-27.0, -52.5, -259.15], + "D3": [-18.0, -52.5, -259.15], + "D4": [-9.0, -52.5, -259.15], + "D5": [0.0, -52.5, -259.15], + "D6": [9.0, -52.5, -259.15], + "D7": [18.0, -52.5, -259.15], + "D8": [27.0, -52.5, -259.15], + "D9": [36.0, -52.5, -259.15], + "D10": [45.0, -52.5, -259.15], + "D11": [54.0, -52.5, -259.15], + "D12": [63.0, -52.5, -259.15], + "E1": [-36.0, -61.5, -259.15], + "E2": [-27.0, -61.5, -259.15], + "E3": [-18.0, -61.5, -259.15], + "E4": [-9.0, -61.5, -259.15], + "E5": [0.0, -61.5, -259.15], + "E6": [9.0, -61.5, -259.15], + "E7": [18.0, -61.5, -259.15], + "E8": [27.0, -61.5, -259.15], + "E9": [36.0, -61.5, -259.15], + "E10": [45.0, -61.5, -259.15], + "E11": [54.0, -61.5, -259.15], + "E12": [63.0, -61.5, -259.15], + "F1": [-36.0, -70.5, -259.15], + "F2": [-27.0, -70.5, -259.15], + "F3": [-18.0, -70.5, -259.15], + "F4": [-9.0, -70.5, -259.15], + "F5": [0.0, -70.5, -259.15], + "F6": [9.0, -70.5, -259.15], + "F7": [18.0, -70.5, -259.15], + "F8": [27.0, -70.5, -259.15], + "F9": [36.0, -70.5, -259.15], + "F10": [45.0, -70.5, -259.15], + "F11": [54.0, -70.5, -259.15], + "F12": [63.0, -70.5, -259.15], + "G1": [-36.0, -79.5, -259.15], + "G2": [-27.0, -79.5, -259.15], + "G3": [-18.0, -79.5, -259.15], + "G4": [-9.0, -79.5, -259.15], + "G5": [0.0, -79.5, -259.15], + "G6": [9.0, -79.5, -259.15], + "G7": [18.0, -79.5, -259.15], + "G8": [27.0, -79.5, -259.15], + "G9": [36.0, -79.5, -259.15], + "G10": [45.0, -79.5, -259.15], + "G11": [54.0, -79.5, -259.15], + "G12": [63.0, -79.5, -259.15], + "H1": [-36.0, -88.5, -259.15], + "H2": [-27.0, -88.5, -259.15], + "H3": [-18.0, -88.5, -259.15], + "H4": [-9.0, -88.5, -259.15], + "H5": [0.0, -88.5, -259.15], + "H6": [9.0, -88.5, -259.15], + "H7": [18.0, -88.5, -259.15], + "H8": [27.0, -88.5, -259.15], + "H9": [36.0, -88.5, -259.15], + "H10": [45.0, -88.5, -259.15], + "H11": [54.0, -88.5, -259.15], + "H12": [63.0, -88.5, -259.15] } } diff --git a/shared-data/python/opentrons_shared_data/errors/codes.py b/shared-data/python/opentrons_shared_data/errors/codes.py index 1f104052cc8..ab79e03b06e 100644 --- a/shared-data/python/opentrons_shared_data/errors/codes.py +++ b/shared-data/python/opentrons_shared_data/errors/codes.py @@ -83,6 +83,7 @@ class ErrorCodes(Enum): COMMAND_PRECONDITION_VIOLATED = _code_from_dict_entry("4004") COMMAND_PARAMETER_LIMIT_VIOLATED = _code_from_dict_entry("4005") INVALID_PROTOCOL_DATA = _code_from_dict_entry("4006") + API_MISCONFIGURATION = _code_from_dict_entry("4007") @classmethod @lru_cache(25) diff --git a/shared-data/python/opentrons_shared_data/pipette/model_constants.py b/shared-data/python/opentrons_shared_data/pipette/model_constants.py index d57ffa587ab..00c577823d2 100644 --- a/shared-data/python/opentrons_shared_data/pipette/model_constants.py +++ b/shared-data/python/opentrons_shared_data/pipette/model_constants.py @@ -76,8 +76,8 @@ "liquid_class": "default", }, "pickUpCurrent": { - "top_level_name": "pickUpTipConfigurations", - "nested_name": "current", + "top_level_name": "partialTipConfigurations", + "nested_name": "perTipPickupCurrent", }, "pickUpDistance": { "top_level_name": "pickUpTipConfigurations", diff --git a/shared-data/python/opentrons_shared_data/pipette/mutable_configurations.py b/shared-data/python/opentrons_shared_data/pipette/mutable_configurations.py index d77af0620d8..2475353e12b 100644 --- a/shared-data/python/opentrons_shared_data/pipette/mutable_configurations.py +++ b/shared-data/python/opentrons_shared_data/pipette/mutable_configurations.py @@ -148,9 +148,14 @@ def _find_default(name: str, configs: Dict[str, Any]) -> MutableConfig: lookup_dict = _MAP_KEY_TO_V2[name] nested_name = lookup_dict["nested_name"] - min_max_dict = _MIN_MAX_LOOKUP[nested_name] - type_lookup = _TYPE_LOOKUP[nested_name] - units_lookup = _UNITS_LOOKUP[nested_name] + if name == "pickUpCurrent": + min_max_dict = _MIN_MAX_LOOKUP["current"] + type_lookup = _TYPE_LOOKUP["current"] + units_lookup = _UNITS_LOOKUP["current"] + else: + min_max_dict = _MIN_MAX_LOOKUP[nested_name] + type_lookup = _TYPE_LOOKUP[nested_name] + units_lookup = _UNITS_LOOKUP[nested_name] if name == "tipLength": # This is only a concern for OT-2 configs and I think we can # be less smart about handling multiple tip types. Instead, just @@ -164,6 +169,9 @@ def _find_default(name: str, configs: Dict[str, Any]) -> MutableConfig: default_value = configs["liquid_properties"][LIQUID_CLASS][ lookup_dict["top_level_name"] ][tip_list[-1]][nested_name] + elif name == "pickUpCurrent": + default_value_dict = configs[lookup_dict["top_level_name"]][nested_name] + default_value = default_value_dict[configs["channels"].value] elif lookup_dict.get("liquid_class"): _class = LiquidClasses[lookup_dict["liquid_class"]] default_value = configs[lookup_dict["top_level_name"]][_class][nested_name] diff --git a/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py b/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py index 7445baddbcc..2893d0c39fe 100644 --- a/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py +++ b/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py @@ -141,7 +141,7 @@ class PlungerPositions(BaseModel): class PlungerHomingConfigurations(BaseModel): current: float = Field( - ..., + default=0.0, description="Either the z motor current needed for picking up tip or the plunger motor current for dropping tip off the nozzle.", ) speed: float = Field( @@ -187,9 +187,9 @@ class PartialTipDefinition(BaseModel): description="A list of the types of partial tip configurations supported, listed by channel ints", alias="availableConfigurations", ) - per_tip_pickup_current: float = Field( - default=0.5, - description="A current scale for pick up tip in a partial tip configuration", + per_tip_pickup_current: Dict[int, float] = Field( + ..., + description="A current dictionary look-up by partial tip configuration.", alias="perTipPickupCurrent", ) diff --git a/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py b/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py index 54dfe3d1060..90c7757b6a7 100644 --- a/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py +++ b/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py @@ -111,14 +111,18 @@ def _build_motor_configurations( def _build_partial_tip_configurations(channels: int) -> PartialTipDefinition: if channels == 8: return PartialTipDefinition( - partialTipSupported=True, availableConfigurations=[1, 2, 3, 4, 5, 6, 7, 8] + partialTipSupported=True, + availableConfigurations=[1, 2, 3, 4, 5, 6, 7, 8], + perTipPickupCurrent={}, ) elif channels == 96: return PartialTipDefinition( - partialTipSupported=True, availableConfigurations=[1, 8, 12, 96] + partialTipSupported=True, + availableConfigurations=[1, 8, 12, 96], + perTipPickupCurrent={}, ) else: - return PartialTipDefinition(partialTipSupported=False) + return PartialTipDefinition(partialTipSupported=False, perTipPickupCurrent={}) def build_geometry_model_v2( diff --git a/shared-data/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py b/shared-data/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py index 16c434d9897..220214cd1e7 100644 --- a/shared-data/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py +++ b/shared-data/python/opentrons_shared_data/pipette/scripts/update_configuration_files.py @@ -145,7 +145,7 @@ def update( Recursively update the given dictionary to ensure no data is lost when updating. """ next_key = next(iter_of_configs, None) - if next_key and isinstance(dict_to_update[next_key], dict): + if next_key and isinstance(dict_to_update.get(next_key), dict): dict_to_update[next_key] = update( dict_to_update.get(next_key, {}), iter_of_configs, value_to_update ) @@ -157,8 +157,8 @@ def update( def build_nozzle_map( nozzle_offset: List[float], channels: PipetteChannelType ) -> Dict[str, List[float]]: - Y_OFFSET = 9 - X_OFFSET = -9 + Y_OFFSET = -9 + X_OFFSET = 9 if channels == PipetteChannelType.SINGLE_CHANNEL: return {"A1": nozzle_offset} elif channels == PipetteChannelType.EIGHT_CHANNEL: @@ -350,7 +350,7 @@ def _update_single_model(configuration_to_update: List[str]) -> None: def _update_all_models(configuration_to_update: List[str]) -> None: - paths_to_validate = ROOT / "liquid" + paths_to_validate = ROOT / "general" _channel_model_str = { "single_channel": "single", "ninety_six_channel": "96", @@ -378,7 +378,6 @@ def _update_all_models(configuration_to_update: List[str]) -> None: ) model_version = convert_pipette_model(built_model) - load_and_update_file_from_config( configuration_to_update, value_to_update, model_version ) From e4435a1e08df6c49b41330c9078a87aae32f4d78 Mon Sep 17 00:00:00 2001 From: Alise Au <20424172+ahiuchingau@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:31:22 -0500 Subject: [PATCH 23/65] listen to the right messages (#13937) --- hardware/opentrons_hardware/drivers/can_bus/can_messenger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py b/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py index 8803859d741..4044b491f0e 100644 --- a/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py +++ b/hardware/opentrons_hardware/drivers/can_bus/can_messenger.py @@ -126,7 +126,7 @@ def handle_ack(self, message: _AckResponses, arbitration_id: ArbitrationId) -> N """Add the ack to the queue if it matches the message_index of the sent message.""" if message.payload.message_index == self._message.payload.message_index: self._remove_response_node(arbitration_id.parts.originating_node_id) - self._ack_queue.put_nowait((arbitration_id, message)) + self._ack_queue.put_nowait((arbitration_id, message)) # If we've recieved all responses exit the listener if len(self._expected_nodes) == 0: self._event.set() From dd14c20b9af48e054b19b83d9a2d15bcf04b49a0 Mon Sep 17 00:00:00 2001 From: koji Date: Tue, 7 Nov 2023 16:33:36 -0500 Subject: [PATCH 24/65] refactor(app): replace RobotWorkSpace with BaseDeck in ProtocolSetup Liquids (#13918) * refactor(app): replace RobotWorkSpace with BaseDeck in ProtocolSetup Liquids --- app/src/molecules/DeckThumbnail/index.tsx | 10 +- .../Devices/ProtocolRun/ProtocolRunSetup.tsx | 1 + .../SetupLiquids/SetupLiquidsMap.tsx | 343 +++++++-------- .../__tests__/SetupLiquids.test.tsx | 7 +- .../__tests__/SetupLiquidsMap.test.tsx | 405 ++++++++++-------- .../ProtocolRun/SetupLiquids/index.tsx | 23 +- 6 files changed, 386 insertions(+), 403 deletions(-) diff --git a/app/src/molecules/DeckThumbnail/index.tsx b/app/src/molecules/DeckThumbnail/index.tsx index fed45696e55..a1d0fd06dc6 100644 --- a/app/src/molecules/DeckThumbnail/index.tsx +++ b/app/src/molecules/DeckThumbnail/index.tsx @@ -47,15 +47,9 @@ export function DeckThumbnail(props: DeckThumbnailProps): JSX.Element | null { protocolAnalysis.commands ) const liquids = protocolAnalysis.liquids + const labwareRenderInfo = getLabwareRenderInfo(protocolAnalysis, deckDef) + const protocolModulesInfo = getProtocolModulesInfo(protocolAnalysis, deckDef) - const labwareRenderInfo = - protocolAnalysis != null - ? getLabwareRenderInfo(protocolAnalysis, deckDef) - : {} - const protocolModulesInfo = - protocolAnalysis != null - ? getProtocolModulesInfo(protocolAnalysis, deckDef) - : [] const attachedProtocolModuleMatches = getAttachedProtocolModuleMatches( attachedModules, protocolModulesInfo diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx index ab5fdaffd3c..27ca12cdd7c 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx @@ -251,6 +251,7 @@ export function ProtocolRunSetup({ protocolRunHeaderRef={protocolRunHeaderRef} robotName={robotName} runId={runId} + protocolAnalysis={protocolData} /> ), description: hasLiquids diff --git a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx index 5bc7e4eb54f..d639664bdbb 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx @@ -2,244 +2,191 @@ import * as React from 'react' import map from 'lodash/map' import isEmpty from 'lodash/isEmpty' import { - parseLiquidsInLoadOrder, - parseLabwareInfoByLiquidId, parseInitialLoadedLabwareByAdapter, + parseLabwareInfoByLiquidId, + parseLiquidsInLoadOrder, } from '@opentrons/api-client' import { + ALIGN_CENTER, + BaseDeck, DIRECTION_COLUMN, Flex, - RobotWorkSpace, - SlotLabels, - LabwareRender, - Module, - ALIGN_CENTER, JUSTIFY_CENTER, + LabwareRender, } from '@opentrons/components' import { getDeckDefFromRobotType, - inferModuleOrientationFromXCoordinate, + getRobotTypeFromLoadedLabware, THERMOCYCLER_MODULE_V1, } from '@opentrons/shared-data' -import { - useLabwareRenderInfoForRunById, - useModuleRenderInfoForProtocolById, - useProtocolDetailsForRun, -} from '../../hooks' -import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis' +import { useAttachedModules } from '../../hooks' import { LabwareInfoOverlay } from '../LabwareInfoOverlay' -import { getStandardDeckViewLayerBlockList } from '../utils/getStandardDeckViewLayerBlockList' import { LiquidsLabwareDetailsModal } from './LiquidsLabwareDetailsModal' import { getWellFillFromLabwareId } from './utils' -import type { RobotType } from '@opentrons/shared-data' +import { getLabwareRenderInfo } from '../utils/getLabwareRenderInfo' +import { getDeckConfigFromProtocolCommands } from '../../../../resources/deck_configuration/utils' +import { getStandardDeckViewLayerBlockList } from '../utils/getStandardDeckViewLayerBlockList' +import { getAttachedProtocolModuleMatches } from '../../../ProtocolSetupModulesAndDeck/utils' +import { getProtocolModulesInfo } from '../utils/getProtocolModulesInfo' + +import type { + CompletedProtocolAnalysis, + ProtocolAnalysisOutput, +} from '@opentrons/shared-data' -const OT2_VIEWBOX = '-80 -40 550 500' -const OT3_VIEWBOX = '-144.31 -76.59 750 681.74' +const ATTACHED_MODULE_POLL_MS = 5000 -const getViewBox = (robotType: RobotType): string | null => { - switch (robotType) { - case 'OT-2 Standard': - return OT2_VIEWBOX - case 'OT-3 Standard': - return OT3_VIEWBOX - default: - return null - } -} interface SetupLiquidsMapProps { runId: string - robotName: string + protocolAnalysis: CompletedProtocolAnalysis | ProtocolAnalysisOutput | null } -export function SetupLiquidsMap(props: SetupLiquidsMapProps): JSX.Element { - const { runId, robotName } = props +export function SetupLiquidsMap( + props: SetupLiquidsMapProps +): JSX.Element | null { + const { runId, protocolAnalysis } = props const [hoverLabwareId, setHoverLabwareId] = React.useState('') + const [liquidDetailsLabwareId, setLiquidDetailsLabwareId] = React.useState< + string | null + >(null) + const attachedModules = + useAttachedModules({ + refetchInterval: ATTACHED_MODULE_POLL_MS, + }) ?? [] + + if (protocolAnalysis == null) return null - const moduleRenderInfoById = useModuleRenderInfoForProtocolById( - robotName, - runId - ) - const labwareRenderInfoById = useLabwareRenderInfoForRunById(runId) - const { robotType } = useProtocolDetailsForRun(runId) - const protocolData = useMostRecentCompletedAnalysis(runId) const liquids = parseLiquidsInLoadOrder( - protocolData?.liquids != null ? protocolData?.liquids : [], - protocolData?.commands ?? [] + protocolAnalysis.liquids != null ? protocolAnalysis.liquids : [], + protocolAnalysis.commands ?? [] ) const initialLoadedLabwareByAdapter = parseInitialLoadedLabwareByAdapter( - protocolData?.commands ?? [] + protocolAnalysis.commands ?? [] ) + const robotType = getRobotTypeFromLoadedLabware(protocolAnalysis.labware) const deckDef = getDeckDefFromRobotType(robotType) + const labwareRenderInfo = getLabwareRenderInfo(protocolAnalysis, deckDef) const labwareByLiquidId = parseLabwareInfoByLiquidId( - protocolData?.commands ?? [] + protocolAnalysis.commands ?? [] ) - const [liquidDetailsLabwareId, setLiquidDetailsLabwareId] = React.useState< - string | null - >(null) + const deckConfig = getDeckConfigFromProtocolCommands( + protocolAnalysis.commands + ) + const deckLayerBlocklist = getStandardDeckViewLayerBlockList(robotType) + + const protocolModulesInfo = getProtocolModulesInfo(protocolAnalysis, deckDef) + + const attachedProtocolModuleMatches = getAttachedProtocolModuleMatches( + attachedModules, + protocolModulesInfo + ) + + const moduleLocations = attachedProtocolModuleMatches.map(module => { + const labwareInAdapterInMod = + module.nestedLabwareId != null + ? initialLoadedLabwareByAdapter[module.nestedLabwareId] + : null + // only rendering the labware on top most layer so + // either the adapter or the labware are rendered but not both + const topLabwareDefinition = + labwareInAdapterInMod?.result?.definition ?? module.nestedLabwareDef + const topLabwareId = + labwareInAdapterInMod?.result?.labwareId ?? module.nestedLabwareId + const topLabwareDisplayName = + labwareInAdapterInMod?.params.displayName ?? + module.nestedLabwareDisplayName + + return { + moduleModel: module.moduleDef.model, + moduleLocation: { slotName: module.slotName }, + innerProps: + module.moduleDef.model === THERMOCYCLER_MODULE_V1 + ? { lidMotorState: 'open' } + : {}, + + nestedLabwareDef: topLabwareDefinition, + moduleChildren: ( + <> + {topLabwareDefinition != null && topLabwareId != null ? ( + + ) : null} + + ), + } + }) return ( - - {() => ( - <> - {map( - moduleRenderInfoById, - ({ - x, - y, - moduleDef, - nestedLabwareDef, - nestedLabwareId, - nestedLabwareDisplayName, - moduleId, - }) => { - const labwareInAdapterInMod = - nestedLabwareId != null - ? initialLoadedLabwareByAdapter[nestedLabwareId] - : null - // only rendering the labware on top most layer so - // either the adapter or the labware are rendered but not both - const topLabwareDefinition = - labwareInAdapterInMod?.result?.definition ?? nestedLabwareDef - const topLabwareId = - labwareInAdapterInMod?.result?.labwareId ?? nestedLabwareId - const topLabwareDisplayName = - labwareInAdapterInMod?.params.displayName ?? - nestedLabwareDisplayName - - const wellFill = getWellFillFromLabwareId( - topLabwareId ?? '', - liquids, - labwareByLiquidId - ) - const labwareHasLiquid = !isEmpty(wellFill) - - return ( - - {topLabwareDefinition != null && - topLabwareDisplayName != null && - topLabwareId != null ? ( - - setHoverLabwareId(topLabwareId)} - onMouseLeave={() => setHoverLabwareId('')} - onClick={() => - labwareHasLiquid - ? setLiquidDetailsLabwareId(topLabwareId) - : null - } - cursor={labwareHasLiquid ? 'pointer' : ''} - > - - - - - ) : null} - - ) - } - )} - {map( - labwareRenderInfoById, - ({ x, y, labwareDef, displayName }, labwareId) => { - const labwareInAdapter = - initialLoadedLabwareByAdapter[labwareId] - // only rendering the labware on top most layer so - // either the adapter or the labware are rendered but not both - const topLabwareDefinition = - labwareInAdapter?.result?.definition ?? labwareDef - const topLabwareId = - labwareInAdapter?.result?.labwareId ?? labwareId - const topLabwareDisplayName = - labwareInAdapter?.params.displayName ?? displayName - const wellFill = getWellFillFromLabwareId( - topLabwareId ?? '', - liquids, - labwareByLiquidId - ) - const labwareHasLiquid = !isEmpty(wellFill) - return ( - - setHoverLabwareId(topLabwareId)} - onMouseLeave={() => setHoverLabwareId('')} - onClick={() => - labwareHasLiquid - ? setLiquidDetailsLabwareId(topLabwareId) - : null - } - cursor={labwareHasLiquid ? 'pointer' : ''} - > - - - - - ) - } - )} - - + {map( + labwareRenderInfo, + ({ x, y, labwareDef, displayName }, labwareId) => { + const labwareInAdapter = initialLoadedLabwareByAdapter[labwareId] + // only rendering the labware on top most layer so + // either the adapter or the labware are rendered but not both + const topLabwareDefinition = + labwareInAdapter?.result?.definition ?? labwareDef + const topLabwareId = + labwareInAdapter?.result?.labwareId ?? labwareId + const topLabwareDisplayName = + labwareInAdapter?.params.displayName ?? displayName + const wellFill = getWellFillFromLabwareId( + topLabwareId ?? '', + liquids, + labwareByLiquidId + ) + const labwareHasLiquid = !isEmpty(wellFill) + return ( + + setHoverLabwareId(topLabwareId)} + onMouseLeave={() => setHoverLabwareId('')} + onClick={() => + labwareHasLiquid + ? setLiquidDetailsLabwareId(topLabwareId) + : null + } + cursor={labwareHasLiquid ? 'pointer' : ''} + > + + + + + ) + } )} - + {liquidDetailsLabwareId != null && ( ) => { return renderWithProviders( - , + , { i18nInstance: i18n, } diff --git a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/__tests__/SetupLiquidsMap.test.tsx b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/__tests__/SetupLiquidsMap.test.tsx index 51ded61559c..98e51b6ba4d 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/__tests__/SetupLiquidsMap.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/__tests__/SetupLiquidsMap.test.tsx @@ -2,88 +2,109 @@ import * as React from 'react' import { when, resetAllWhenMocks } from 'jest-when' import { i18n } from '../../../../../i18n' import { + BaseDeck, renderWithProviders, partialComponentPropsMatcher, - RobotWorkSpace, LabwareRender, - Module, + EXTENDED_DECK_CONFIG_FIXTURE, } from '@opentrons/components' + +import fixture_tiprack_300_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_300_ul.json' import { - inferModuleOrientationFromXCoordinate, - LabwareDefinition2, - ModuleModel, - ModuleType, + FLEX_ROBOT_TYPE, + getDeckDefFromRobotType, + getRobotTypeFromLoadedLabware, + OT2_ROBOT_TYPE, } from '@opentrons/shared-data' -import fixture_tiprack_300_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_300_ul.json' -import standardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot2_standard.json' import { - useLabwareRenderInfoForRunById, - useModuleRenderInfoForProtocolById, - useProtocolDetailsForRun, -} from '../../../hooks' -import { getWellFillFromLabwareId } from '../utils' -import { SetupLiquidsMap } from '../SetupLiquidsMap' + parseInitialLoadedLabwareByAdapter, + parseLabwareInfoByLiquidId, + parseLiquidsInLoadOrder, + simpleAnalysisFileFixture, +} from '@opentrons/api-client' +import ot2StandardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot2_standard.json' +import ot3StandardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot3_standard.json' + +import { useAttachedModules } from '../../../hooks' import { LabwareInfoOverlay } from '../../LabwareInfoOverlay' +import { getLabwareRenderInfo } from '../../utils/getLabwareRenderInfo' +import { getStandardDeckViewLayerBlockList } from '../../utils/getStandardDeckViewLayerBlockList' +import { getAttachedProtocolModuleMatches } from '../../../../ProtocolSetupModulesAndDeck/utils' +import { getProtocolModulesInfo } from '../../utils/getProtocolModulesInfo' +import { getDeckConfigFromProtocolCommands } from '../../../../../resources/deck_configuration/utils' +import { mockProtocolModuleInfo } from '../../../../ProtocolSetupLabware/__fixtures__' +import { mockFetchModulesSuccessActionPayloadModules } from '../../../../../redux/modules/__fixtures__' + +import { SetupLiquidsMap } from '../SetupLiquidsMap' + +import type { + ModuleModel, + ModuleType, + RunTimeCommand, + LabwareDefinition2, +} from '@opentrons/shared-data' jest.mock('@opentrons/components', () => { const actualComponents = jest.requireActual('@opentrons/components') return { ...actualComponents, - Module: jest.fn(() =>
    mock Module
    ), - RobotWorkSpace: jest.fn(() =>
    mock RobotWorkSpace
    ), LabwareRender: jest.fn(() =>
    mock LabwareRender
    ), } }) -jest.mock('@opentrons/shared-data', () => { - const actualSharedData = jest.requireActual('@opentrons/shared-data') - return { - ...actualSharedData, - inferModuleOrientationFromXCoordinate: jest.fn(), - } -}) + +jest.mock('@opentrons/components/src/hardware-sim/BaseDeck') +jest.mock('@opentrons/api-client') +jest.mock('@opentrons/shared-data/js/helpers') jest.mock('../../LabwareInfoOverlay') jest.mock('../../../hooks') jest.mock('../utils') +jest.mock('../../utils/getLabwareRenderInfo') +jest.mock('../../../../ProtocolSetupModulesAndDeck/utils') +jest.mock('../../utils/getProtocolModulesInfo') +jest.mock('../../../../../resources/deck_configuration/utils') -const mockUseProtocolDetailsForRun = useProtocolDetailsForRun as jest.MockedFunction< - typeof useProtocolDetailsForRun +const mockUseAttachedModules = useAttachedModules as jest.MockedFunction< + typeof useAttachedModules > const mockLabwareInfoOverlay = LabwareInfoOverlay as jest.MockedFunction< typeof LabwareInfoOverlay > -const mockModule = Module as jest.MockedFunction -const mockInferModuleOrientationFromXCoordinate = inferModuleOrientationFromXCoordinate as jest.MockedFunction< - typeof inferModuleOrientationFromXCoordinate -> -const mockRobotWorkSpace = RobotWorkSpace as jest.MockedFunction< - typeof RobotWorkSpace -> const mockLabwareRender = LabwareRender as jest.MockedFunction< typeof LabwareRender > -const mockUseLabwareRenderInfoForRunById = useLabwareRenderInfoForRunById as jest.MockedFunction< - typeof useLabwareRenderInfoForRunById +const mockBaseDeck = BaseDeck as jest.MockedFunction +const mockGetDeckDefFromRobotType = getDeckDefFromRobotType as jest.MockedFunction< + typeof getDeckDefFromRobotType > -const mockUseModuleRenderInfoForProtocolById = useModuleRenderInfoForProtocolById as jest.MockedFunction< - typeof useModuleRenderInfoForProtocolById +const mockGetRobotTypeFromLoadedLabware = getRobotTypeFromLoadedLabware as jest.MockedFunction< + typeof getRobotTypeFromLoadedLabware > -const mockGetWellFillFromLabwareId = getWellFillFromLabwareId as jest.MockedFunction< - typeof getWellFillFromLabwareId +const mockParseInitialLoadedLabwareByAdapter = parseInitialLoadedLabwareByAdapter as jest.MockedFunction< + typeof parseInitialLoadedLabwareByAdapter +> +const mockParseLabwareInfoByLiquidId = parseLabwareInfoByLiquidId as jest.MockedFunction< + typeof parseLabwareInfoByLiquidId +> +const mockParseLiquidsInLoadOrder = parseLiquidsInLoadOrder as jest.MockedFunction< + typeof parseLiquidsInLoadOrder +> +const mockGetLabwareRenderInfo = getLabwareRenderInfo as jest.MockedFunction< + typeof getLabwareRenderInfo +> +const mockGetAttachedProtocolModuleMatches = getAttachedProtocolModuleMatches as jest.MockedFunction< + typeof getAttachedProtocolModuleMatches +> +const mockGetProtocolModulesInfo = getProtocolModulesInfo as jest.MockedFunction< + typeof getProtocolModulesInfo +> +const mockGetDeckConfigFromProtocolCommands = getDeckConfigFromProtocolCommands as jest.MockedFunction< + typeof getDeckConfigFromProtocolCommands > -const MOCK_WELL_FILL = { C1: '#ff4888', C2: '#ff4888' } - -const deckSlotsById = standardDeckDef.locations.orderedSlots.reduce( - (acc, deckSlot) => ({ ...acc, [deckSlot.id]: deckSlot }), - {} -) - -const ROBOT_NAME = 'otie' const RUN_ID = '1' -const STUBBED_ORIENTATION_VALUE = 'left' const MOCK_300_UL_TIPRACK_ID = '300_ul_tiprack_id' const MOCK_MAGNETIC_MODULE_COORDS = [10, 20, 0] -const MOCK_TC_COORDS = [20, 30, 0] +const MOCK_SECOND_MAGNETIC_MODULE_COORDS = [100, 200, 0] const MOCK_300_UL_TIPRACK_COORDS = [30, 40, 0] const mockMagneticModule = { @@ -106,13 +127,6 @@ const mockMagneticModule = { quirks: [], } -const mockTCModule = { - labwareOffset: { x: 3, y: 3, z: 3 }, - moduleId: 'TCModuleId', - model: 'thermocyclerModuleV1' as ModuleModel, - type: 'thermocyclerModuleType' as ModuleType, -} - const render = (props: React.ComponentProps) => { return renderWithProviders(, { i18nInstance: i18n, @@ -122,10 +136,10 @@ const render = (props: React.ComponentProps) => { describe('SetupLiquidsMap', () => { let props: React.ComponentProps beforeEach(() => { - props = { runId: RUN_ID, robotName: ROBOT_NAME } - when(mockInferModuleOrientationFromXCoordinate) - .calledWith(expect.anything()) - .mockReturnValue(STUBBED_ORIENTATION_VALUE) + props = { + runId: RUN_ID, + protocolAnalysis: simpleAnalysisFileFixture as any, + } when(mockLabwareRender) .mockReturnValue(
    ) // this (default) empty div will be returned when LabwareRender isn't called with expected labware definition .calledWith( @@ -145,14 +159,30 @@ describe('SetupLiquidsMap', () => { }) ) .mockReturnValue(
    mock labware render with well fill
    ) - + when(mockUseAttachedModules).calledWith().mockReturnValue([]) + when(mockGetAttachedProtocolModuleMatches).mockReturnValue([]) + when(mockGetLabwareRenderInfo) + .calledWith(simpleAnalysisFileFixture as any, ot2StandardDeckDef as any) + .mockReturnValue({}) + when(mockGetDeckConfigFromProtocolCommands) + .calledWith(simpleAnalysisFileFixture.commands as RunTimeCommand[]) + .mockReturnValue(EXTENDED_DECK_CONFIG_FIXTURE) + when(mockGetRobotTypeFromLoadedLabware) + .calledWith(simpleAnalysisFileFixture.labware as any) + .mockReturnValue(FLEX_ROBOT_TYPE) + when(mockParseLiquidsInLoadOrder) + .calledWith( + simpleAnalysisFileFixture.liquids as any, + simpleAnalysisFileFixture.commands as any + ) + .mockReturnValue([]) + when(mockParseInitialLoadedLabwareByAdapter) + .calledWith(simpleAnalysisFileFixture.commands as any) + .mockReturnValue({}) when(mockLabwareInfoOverlay) .mockReturnValue(
    ) // this (default) empty div will be returned when LabwareInfoOverlay isn't called with expected props .calledWith( - partialComponentPropsMatcher({ - definition: fixture_tiprack_300_ul, - labwareHasLiquid: false, - }) + partialComponentPropsMatcher({ definition: fixture_tiprack_300_ul }) ) .mockReturnValue(
    @@ -160,94 +190,93 @@ describe('SetupLiquidsMap', () => { {fixture_tiprack_300_ul.metadata.displayName}
    ) - .calledWith(partialComponentPropsMatcher({ labwareHasLiquid: true })) - .mockReturnValue(
    mock labware overlay with liquid
    ) + }) - when(mockRobotWorkSpace) - .mockReturnValue(
    ) // this (default) empty div will be returned when RobotWorkSpace isn't called with expected props - .calledWith( - partialComponentPropsMatcher({ - deckDef: standardDeckDef, - children: expect.anything(), - }) - ) - .mockImplementation(({ children }) => ( - - {/* @ts-expect-error children won't be null since we checked for expect.anything() above */} - {children({ - deckSlotsById, - getRobotCoordsFromDOMCoords: {} as any, - })} - - )) - when(mockUseProtocolDetailsForRun) - .calledWith(RUN_ID) - .mockReturnValue({ - protocolData: { - pipettes: {}, - labware: {}, - modules: { - heatershaker_id: { - model: 'heaterShakerModuleV1', - }, - }, - liquids: [ - { - id: '1', - displayName: 'mock liquid', - description: '', - displayColor: '#FFFFFF', - }, - ], - labwareDefinitions: {}, - commands: [], - }, - } as any) + afterEach(() => { + jest.clearAllMocks() + resetAllWhenMocks() }) - afterEach(() => resetAllWhenMocks()) it('should render a deck WITHOUT labware and WITHOUT modules', () => { - when(mockUseLabwareRenderInfoForRunById) - .calledWith(RUN_ID) - .mockReturnValue({}) - when(mockUseModuleRenderInfoForProtocolById) - .calledWith(ROBOT_NAME, RUN_ID) - .mockReturnValue({}) - + props = { + ...props, + protocolAnalysis: null, + } render(props) - expect(mockModule).not.toHaveBeenCalled() expect(mockLabwareRender).not.toHaveBeenCalled() expect(mockLabwareInfoOverlay).not.toHaveBeenCalled() }) - it('should render a deck WITH labware and WITHOUT modules', () => { - when(mockUseLabwareRenderInfoForRunById) - .calledWith(RUN_ID) - .mockReturnValue({ - '300_ul_tiprack_id': { - labwareDef: fixture_tiprack_300_ul as LabwareDefinition2, - displayName: 'fresh tips', - x: MOCK_300_UL_TIPRACK_COORDS[0], - y: MOCK_300_UL_TIPRACK_COORDS[1], - z: MOCK_300_UL_TIPRACK_COORDS[2], - slotName: '1', - }, - }) - when(mockUseModuleRenderInfoForProtocolById) - .calledWith(ROBOT_NAME, RUN_ID) + it('should render base deck - robot type is OT-2', () => { + when(mockGetRobotTypeFromLoadedLabware) + .calledWith(simpleAnalysisFileFixture.labware as any) + .mockReturnValue(OT2_ROBOT_TYPE) + when(mockGetDeckDefFromRobotType) + .calledWith(OT2_ROBOT_TYPE) + .mockReturnValue(ot2StandardDeckDef as any) + when(mockParseLabwareInfoByLiquidId) + .calledWith(simpleAnalysisFileFixture.commands as any) .mockReturnValue({}) + mockUseAttachedModules.mockReturnValue( + mockFetchModulesSuccessActionPayloadModules + ) + when(mockGetLabwareRenderInfo).mockReturnValue({}) + when(mockGetProtocolModulesInfo) + .calledWith(simpleAnalysisFileFixture as any, ot2StandardDeckDef as any) + .mockReturnValue(mockProtocolModuleInfo) + when(mockGetAttachedProtocolModuleMatches) + .calledWith( + mockFetchModulesSuccessActionPayloadModules, + mockProtocolModuleInfo + ) + .mockReturnValue([ + { + moduleId: mockMagneticModule.moduleId, + x: MOCK_MAGNETIC_MODULE_COORDS[0], + y: MOCK_MAGNETIC_MODULE_COORDS[1], + z: MOCK_MAGNETIC_MODULE_COORDS[2], + moduleDef: mockMagneticModule as any, + nestedLabwareDef: null, + nestedLabwareDisplayName: null, + nestedLabwareId: null, + slotName: '1', + protocolLoadOrder: 1, + attachedModuleMatch: null, + }, + { + moduleId: mockMagneticModule.moduleId, + x: MOCK_SECOND_MAGNETIC_MODULE_COORDS[0], + y: MOCK_SECOND_MAGNETIC_MODULE_COORDS[1], + z: MOCK_SECOND_MAGNETIC_MODULE_COORDS[2], + moduleDef: mockMagneticModule as any, + nestedLabwareDef: null, + nestedLabwareDisplayName: null, + nestedLabwareId: null, + slotName: '2', + protocolLoadOrder: 0, + attachedModuleMatch: null, + }, + ]) + when(mockBaseDeck) + .calledWith( + partialComponentPropsMatcher({ + robotType: OT2_ROBOT_TYPE, + deckLayerBlocklist: getStandardDeckViewLayerBlockList(OT2_ROBOT_TYPE), + }) + ) + .mockReturnValue(
    mock BaseDeck
    ) const [{ getByText }] = render(props) - expect(mockModule).not.toHaveBeenCalled() - expect(mockLabwareRender).toHaveBeenCalled() - expect(mockLabwareInfoOverlay).toHaveBeenCalled() - getByText('mock labware render of 300ul Tiprack FIXTURE') - getByText('mock labware info overlay of 300ul Tiprack FIXTURE') + getByText('mock BaseDeck') }) - it('should render a deck WITH labware and WITH modules', () => { - when(mockUseLabwareRenderInfoForRunById) - .calledWith(RUN_ID) + it('should render base deck - robot type is Flex', () => { + when(mockGetDeckDefFromRobotType) + .calledWith(FLEX_ROBOT_TYPE) + .mockReturnValue(ot3StandardDeckDef as any) + + when(mockGetLabwareRenderInfo) + .calledWith(simpleAnalysisFileFixture as any, ot3StandardDeckDef as any) .mockReturnValue({ [MOCK_300_UL_TIPRACK_ID]: { labwareDef: fixture_tiprack_300_ul as LabwareDefinition2, @@ -255,79 +284,75 @@ describe('SetupLiquidsMap', () => { x: MOCK_300_UL_TIPRACK_COORDS[0], y: MOCK_300_UL_TIPRACK_COORDS[1], z: MOCK_300_UL_TIPRACK_COORDS[2], - slotName: '1', + slotName: 'C1', }, }) - when(mockUseModuleRenderInfoForProtocolById) - .calledWith(ROBOT_NAME, RUN_ID) - .mockReturnValue({ - [mockMagneticModule.moduleId]: { + when(mockParseLabwareInfoByLiquidId) + .calledWith(simpleAnalysisFileFixture.commands as any) + .mockReturnValue({}) + mockUseAttachedModules.mockReturnValue( + mockFetchModulesSuccessActionPayloadModules + ) + + when(mockGetProtocolModulesInfo) + .calledWith(simpleAnalysisFileFixture as any, ot3StandardDeckDef as any) + .mockReturnValue(mockProtocolModuleInfo) + when(mockGetAttachedProtocolModuleMatches) + .calledWith( + mockFetchModulesSuccessActionPayloadModules, + mockProtocolModuleInfo + ) + .mockReturnValue([ + { moduleId: mockMagneticModule.moduleId, x: MOCK_MAGNETIC_MODULE_COORDS[0], y: MOCK_MAGNETIC_MODULE_COORDS[1], z: MOCK_MAGNETIC_MODULE_COORDS[2], moduleDef: mockMagneticModule as any, nestedLabwareDef: null, + nestedLabwareDisplayName: null, nestedLabwareId: null, - protocolLoadOrder: 0, + slotName: 'C1', + protocolLoadOrder: 1, attachedModuleMatch: null, }, - [mockTCModule.moduleId]: { - moduleId: mockTCModule.moduleId, - x: MOCK_TC_COORDS[0], - y: MOCK_TC_COORDS[1], - z: MOCK_TC_COORDS[2], - moduleDef: mockTCModule, + { + moduleId: mockMagneticModule.moduleId, + x: MOCK_SECOND_MAGNETIC_MODULE_COORDS[0], + y: MOCK_SECOND_MAGNETIC_MODULE_COORDS[1], + z: MOCK_SECOND_MAGNETIC_MODULE_COORDS[2], + moduleDef: mockMagneticModule as any, nestedLabwareDef: null, + nestedLabwareDisplayName: null, nestedLabwareId: null, - protocolLoadOrder: 1, + slotName: 'B1', + protocolLoadOrder: 0, attachedModuleMatch: null, }, - } as any) - - when(mockModule) - .calledWith( - partialComponentPropsMatcher({ - def: mockMagneticModule, - x: MOCK_MAGNETIC_MODULE_COORDS[0], - y: MOCK_MAGNETIC_MODULE_COORDS[1], - }) - ) - .mockReturnValue(
    mock module viz {mockMagneticModule.type}
    ) + ]) - when(mockModule) + when(mockBaseDeck) .calledWith( partialComponentPropsMatcher({ - def: mockTCModule, - x: MOCK_TC_COORDS[0], - y: MOCK_TC_COORDS[1], + deckConfig: EXTENDED_DECK_CONFIG_FIXTURE, + deckLayerBlocklist: getStandardDeckViewLayerBlockList( + FLEX_ROBOT_TYPE + ), + robotType: FLEX_ROBOT_TYPE, + // ToDo (kk:11/03/2023) Update the following part later + labwareLocations: expect.anything(), + moduleLocations: expect.anything(), }) ) - .mockReturnValue(
    mock module viz {mockTCModule.type}
    ) - + .mockReturnValue(
    mock BaseDeck
    ) const [{ getByText }] = render(props) - getByText('mock module viz magneticModuleType') - getByText('mock module viz thermocyclerModuleType') - getByText('mock labware render of 300ul Tiprack FIXTURE') - getByText('mock labware info overlay of 300ul Tiprack FIXTURE') - }) - it('should render labware overlay and labware render with liquids', () => { - when(mockUseLabwareRenderInfoForRunById) - .calledWith(RUN_ID) - .mockReturnValue({ - '300_ul_tiprack_id': { - labwareDef: fixture_tiprack_300_ul as LabwareDefinition2, - displayName: 'fresh tips', - x: MOCK_300_UL_TIPRACK_COORDS[0], - y: MOCK_300_UL_TIPRACK_COORDS[1], - z: MOCK_300_UL_TIPRACK_COORDS[2], - slotName: '1', - }, - }) - mockGetWellFillFromLabwareId.mockReturnValue(MOCK_WELL_FILL) - const [{ getByText }] = render({ ...props }) - getByText('mock labware overlay with liquid') - getByText('mock labware render with well fill') + getByText('mock BaseDeck') }) + + // ToDo (kk:11/03/2023) + // The current component implementation is tough to test everything. + // I will do refactoring later and add tests to cover more cases. + // Probably I will replace BaseDeck's children with a new component and write test for that. + it.todo('should render labware overlay and labware render with liquids') }) diff --git a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/index.tsx b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/index.tsx index 85e2e2761fb..bb4de2d50ea 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/index.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/index.tsx @@ -13,13 +13,24 @@ import { BackToTopButton } from '../BackToTopButton' import { SetupLiquidsList } from './SetupLiquidsList' import { SetupLiquidsMap } from './SetupLiquidsMap' +import type { + CompletedProtocolAnalysis, + ProtocolAnalysisOutput, +} from '@opentrons/shared-data' + interface SetupLiquidsProps { protocolRunHeaderRef: React.RefObject | null robotName: string runId: string + protocolAnalysis: CompletedProtocolAnalysis | ProtocolAnalysisOutput | null } -export function SetupLiquids(props: SetupLiquidsProps): JSX.Element { +export function SetupLiquids({ + protocolRunHeaderRef, + robotName, + runId, + protocolAnalysis, +}: SetupLiquidsProps): JSX.Element { const { t } = useTranslation('protocol_setup') const [selectedValue, toggleGroup] = useToggleGroup( t('list_view'), @@ -35,15 +46,15 @@ export function SetupLiquids(props: SetupLiquidsProps): JSX.Element { > {toggleGroup} {selectedValue === t('list_view') ? ( - + ) : ( - + )} From 4a9a5021f472a2d118b44be157abae0c564b3355 Mon Sep 17 00:00:00 2001 From: Jamey H Date: Wed, 8 Nov 2023 07:46:48 -0500 Subject: [PATCH 25/65] feat(app, app-shell): add download progress to robot update flows (#13915) * feat(app): add download progress to robot update flows If the robot update cache files are still downloading, no longer is an error thrown. Instead, the update modal renders and a downloading stage of the update flow begins. Additionally, release files are downloaded and returned to the browser layer separately from system files, so users may see release notes as soon as they are downloaded. --- app-shell/src/http.ts | 23 ++- app-shell/src/robot-update/index.ts | 34 ++-- app-shell/src/robot-update/release-files.ts | 79 +++++++--- .../RobotUpdateProgressModal.tsx | 43 ++++-- .../RobotUpdateProgressModal.test.tsx | 16 +- .../__tests__/useRobotUpdateInfo.test.tsx | 146 +++++++++++++----- .../UpdateBuildroot/useRobotUpdateInfo.ts | 111 ++++++------- .../redux/robot-update/__tests__/epic.test.ts | 40 +++++ .../robot-update/__tests__/reducer.test.ts | 63 ++++++++ app/src/redux/robot-update/constants.ts | 7 + app/src/redux/robot-update/epic.ts | 17 +- app/src/redux/robot-update/hooks.ts | 1 + app/src/redux/robot-update/reducer.ts | 42 ++++- app/src/redux/robot-update/types.ts | 6 +- 14 files changed, 470 insertions(+), 158 deletions(-) diff --git a/app-shell/src/http.ts b/app-shell/src/http.ts index c4ce12d4aa6..02fe50da3e1 100644 --- a/app-shell/src/http.ts +++ b/app-shell/src/http.ts @@ -90,17 +90,22 @@ export function postFile( init?: RequestInit, progress?: (progress: number) => void ): Promise { - return createReadStream(source, progress ?? null).then(readStream => { - const body = new FormData() - body.append(name, readStream) - return fetch(input, { ...init, body, method: 'POST' }) + return new Promise((resolve, reject) => { + createReadStream(source, progress ?? null, reject).then(readStream => { + return new Promise(resolve => { + const body = new FormData() + body.append(name, readStream) + resolve(fetch(input, { ...init, body, method: 'POST' })) + }).then(resolve) + }) }) } function createReadStreamWithSize( source: string, size: number, - progress: ((progress: number) => void) | null + progress: ((progress: number) => void) | null, + onError: (error: unknown) => unknown ): Promise { return new Promise((resolve, reject) => { const readStream = fs.createReadStream(source) @@ -125,6 +130,7 @@ function createReadStreamWithSize( } readStream.once('error', handleError) + readStream.once('error', onError) function handleSuccess(): void { resolve(readStream) @@ -142,12 +148,13 @@ function createReadStreamWithSize( // create a read stream, handling errors that `fetch` is unable to catch function createReadStream( source: string, - progress: ((progress: number) => void) | null + progress: ((progress: number) => void) | null, + onError: (error: unknown) => unknown ): Promise { return fsPromises .stat(source) .then(filestats => - createReadStreamWithSize(source, filestats.size, progress) + createReadStreamWithSize(source, filestats.size, progress, onError) ) - .catch(() => createReadStreamWithSize(source, Infinity, progress)) + .catch(() => createReadStreamWithSize(source, Infinity, progress, onError)) } diff --git a/app-shell/src/robot-update/index.ts b/app-shell/src/robot-update/index.ts index b71eab6d44b..4f4d2bc8350 100644 --- a/app-shell/src/robot-update/index.ts +++ b/app-shell/src/robot-update/index.ts @@ -137,20 +137,28 @@ export function registerRobotUpdate(dispatch: Dispatch): Dispatch { case 'robotUpdate:READ_USER_FILE': { const { systemFile } = action.payload as { systemFile: string } - readFileAndDispatchInfo(dispatch, systemFile, true) - break + return readFileAndDispatchInfo(dispatch, systemFile, true) } case 'robotUpdate:READ_SYSTEM_FILE': { const { target } = action.payload const filename = updateSet[target]?.system + if (filename == null) { - return dispatch({ - type: 'robotUpdate:UNEXPECTED_ERROR', - payload: { message: 'Robot update file not downloaded' }, - }) + if (checkingForUpdates) { + dispatch({ + type: 'robotUpdate:CHECKING_FOR_UPDATE', + payload: target, + }) + } else { + // If the file was downloaded but deleted from robot-update-cache. + dispatch({ + type: 'robotUpdate:UNEXPECTED_ERROR', + payload: { message: 'Robot update file not downloaded' }, + }) + } } else { - readFileAndDispatchInfo(dispatch, filename) + return readFileAndDispatchInfo(dispatch, filename) } } } @@ -213,7 +221,7 @@ export function checkForRobotUpdate( const handleProgress = (progress: DownloadProgress): void => { const { downloaded, size } = progress if (size !== null) { - const percentDone = Math.round(downloaded / size) * 100 + const percentDone = Math.round((downloaded / size) * 100) if (percentDone - prevPercentDone > 0) { dispatch({ type: 'robotUpdate:DOWNLOAD_PROGRESS', @@ -227,7 +235,15 @@ export function checkForRobotUpdate( const targetDownloadDir = cacheDirForMachineFiles(target) return ensureDir(targetDownloadDir) - .then(() => getReleaseFiles(urls, targetDownloadDir, handleProgress)) + .then(() => + getReleaseFiles( + urls, + targetDownloadDir, + dispatch, + target, + handleProgress + ) + ) .then(filepaths => cacheUpdateSet(filepaths, target)) .then(updateInfo => dispatch({ type: 'robotUpdate:UPDATE_INFO', payload: updateInfo }) diff --git a/app-shell/src/robot-update/release-files.ts b/app-shell/src/robot-update/release-files.ts index d2d9d6b47cc..0c84634eb59 100644 --- a/app-shell/src/robot-update/release-files.ts +++ b/app-shell/src/robot-update/release-files.ts @@ -3,12 +3,17 @@ import assert from 'assert' import path from 'path' import { promisify } from 'util' import tempy from 'tempy' -import { move, readdir, remove } from 'fs-extra' +import { move, readdir, remove, readFile } from 'fs-extra' import StreamZip from 'node-stream-zip' import getStream from 'get-stream' +import { RobotUpdateTarget } from '@opentrons/app/src/redux/robot-update/types' + import { createLogger } from '../log' import { fetchToFile } from '../http' +import { Dispatch } from '../types' +import { CURRENT_VERSION } from '../update' + import type { DownloadProgress } from '../http' import type { ReleaseSetUrls, ReleaseSetFilepaths, UserFileInfo } from './types' @@ -23,6 +28,8 @@ const outPath = (dir: string, url: string): string => export function getReleaseFiles( urls: ReleaseSetUrls, directory: string, + dispatch: Dispatch, + target: RobotUpdateTarget, onProgress: (progress: DownloadProgress) => unknown ): Promise { return readdir(directory) @@ -44,41 +51,65 @@ export function getReleaseFiles( return { system, releaseNotes } } - return downloadReleaseFiles(urls, directory, onProgress) + return Promise.all([ + downloadAndNotify(true, urls.releaseNotes, directory, dispatch, target), + downloadAndNotify( + false, + urls.system, + directory, + dispatch, + target, + onProgress + ), + ]).then(([releaseNotes, system]) => ({ releaseNotes, system })) }) } -// downloads the entire release set to a temporary directory, and once they're -// all successfully downloaded, renames the directory to `directory` +// downloads robot update files to a temporary directory, and once +// successfully downloaded, renames the directory to `directory` // TODO(mc, 2019-07-09): DRY this up if/when more than 2 files are required -export function downloadReleaseFiles( - urls: ReleaseSetUrls, +export function downloadAndNotify( + isReleaseNotesDownload: boolean, + url: ReleaseSetUrls['releaseNotes' | 'system'], directory: string, + dispatch: Dispatch, + target: RobotUpdateTarget, // `onProgress` will be called with download progress as the files are read - onProgress: (progress: DownloadProgress) => unknown -): Promise { + onProgress?: (progress: DownloadProgress) => unknown +): Promise { const tempDir: string = tempy.directory() - const tempSystemPath = outPath(tempDir, urls.system) - const tempNotesPath = outPath(tempDir, urls.releaseNotes) + const tempPath = outPath(tempDir, url) + const path = outPath(directory, tempPath) + const logMessage = isReleaseNotesDownload ? 'release notes' : 'system files' - log.debug('directory created for robot update downloads', { tempDir }) + log.debug('directory created for ' + logMessage, { tempDir }) // downloads are streamed directly to the filesystem to avoid loading them // all into memory simultaneously - const systemReq = fetchToFile(urls.system, tempSystemPath, { onProgress }) - const notesReq = fetchToFile(urls.releaseNotes, tempNotesPath) - - return Promise.all([systemReq, notesReq]).then(results => { - const [systemTemp, releaseNotesTemp] = results - const systemPath = outPath(directory, systemTemp) - const notesPath = outPath(directory, releaseNotesTemp) - - log.debug('renaming directory', { from: tempDir, to: directory }) + const req = fetchToFile(url, tempPath, { + onProgress, + }) - return move(tempDir, directory, { overwrite: true }).then(() => ({ - system: systemPath, - releaseNotes: notesPath, - })) + return req.then(() => { + return move(tempPath, path, { overwrite: true }) + .then(() => { + if (isReleaseNotesDownload) { + return readFile(path, 'utf8').then(releaseNotes => + dispatch({ + type: 'robotUpdate:UPDATE_INFO', + payload: { releaseNotes, target, version: CURRENT_VERSION }, + }) + ) + } + // This action will only have an effect if the user is actively waiting for the download to complete. + else { + return dispatch({ + type: 'robotUpdate:DOWNLOAD_DONE', + payload: target, + }) + } + }) + .then(() => path) }) } diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx index a2a504629b9..94a31b77560 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/RobotUpdateProgressModal.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { useTranslation } from 'react-i18next' -import { useDispatch } from 'react-redux' +import { useDispatch, useSelector } from 'react-redux' import { css } from 'styled-components' import { @@ -23,11 +23,13 @@ import { FOOTER_BUTTON_STYLE } from './UpdateRobotModal' import { startRobotUpdate, clearRobotUpdateSession, + getRobotUpdateDownloadError, } from '../../../../redux/robot-update' import { useRobotUpdateInfo } from './useRobotUpdateInfo' import successIcon from '../../../../assets/images/icon_success.png' -import type { SetStatusBarCreateCommand } from '@opentrons/shared-data' +import type { State } from '../../../../redux/types' +import type { SetStatusBarCreateCommand } from '@opentrons/shared-data/protocol' import type { RobotUpdateSession } from '../../../../redux/robot-update/types' import type { UpdateStep } from './useRobotUpdateInfo' @@ -66,8 +68,15 @@ export function RobotUpdateProgressModal({ const completeRobotUpdateHandler = (): void => { if (closeUpdateBuildroot != null) closeUpdateBuildroot() } - const { error } = session || { error: null } - const { updateStep, progressPercent } = useRobotUpdateInfo(session) + + const { updateStep, progressPercent } = useRobotUpdateInfo(robotName, session) + + let { error } = session || { error: null } + const downloadError = useSelector((state: State) => + getRobotUpdateDownloadError(state, robotName) + ) + if (error == null && downloadError != null) error = downloadError + useStatusBarAnimation(error != null) useCleanupRobotUpdateSessionOnDismount() @@ -89,11 +98,27 @@ export function RobotUpdateProgressModal({ progressPercent ) - let modalBodyText = t('installing_update') + let modalBodyText = '' let subProgressBarText = t('do_not_turn_off') - if (updateStep === 'restart') modalBodyText = t('restarting_robot') - if (updateStep === 'restart' && letUserExitUpdate) { - subProgressBarText = t('restart_taking_too_long', { robotName }) + switch (updateStep) { + case 'initial': + case 'error': + modalBodyText = '' + break + case 'download': + modalBodyText = t('downloading_update') + break + case 'install': + modalBodyText = t('installing_update') + break + case 'restart': + modalBodyText = t('restarting_robot') + if (letUserExitUpdate) { + subProgressBarText = t('restart_taking_too_long', { robotName }) + } + break + default: + modalBodyText = t('installing_update') } return ( @@ -209,7 +234,7 @@ function SuccessOrError({ errorMessage }: SuccessOrErrorProps): JSX.Element { export const TIME_BEFORE_ALLOWING_EXIT_MS = 600000 // 10 mins function useAllowExitIfUpdateStalled( - updateStep: UpdateStep, + updateStep: UpdateStep | null, progressPercent: number ): boolean { const [letUserExitUpdate, setLetUserExitUpdate] = React.useState( diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/RobotUpdateProgressModal.test.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/RobotUpdateProgressModal.test.tsx index 45ae255f3c5..55793ef48dc 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/RobotUpdateProgressModal.test.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/RobotUpdateProgressModal.test.tsx @@ -8,7 +8,10 @@ import { TIME_BEFORE_ALLOWING_EXIT_MS, } from '../RobotUpdateProgressModal' import { useRobotUpdateInfo } from '../useRobotUpdateInfo' -import { getRobotSessionIsManualFile } from '../../../../../redux/robot-update' +import { + getRobotSessionIsManualFile, + getRobotUpdateDownloadError, +} from '../../../../../redux/robot-update' import { useDispatchStartRobotUpdate } from '../../../../../redux/robot-update/hooks' import type { SetStatusBarCreateCommand } from '@opentrons/shared-data' @@ -31,6 +34,9 @@ const mockGetRobotSessionIsManualFile = getRobotSessionIsManualFile as jest.Mock const mockUseDispatchStartRobotUpdate = useDispatchStartRobotUpdate as jest.MockedFunction< typeof useDispatchStartRobotUpdate > +const mockGetRobotUpdateDownloadError = getRobotUpdateDownloadError as jest.MockedFunction< + typeof getRobotUpdateDownloadError +> const render = ( props: React.ComponentProps @@ -71,12 +77,20 @@ describe('DownloadUpdateModal', () => { }) mockGetRobotSessionIsManualFile.mockReturnValue(false) mockUseDispatchStartRobotUpdate.mockReturnValue(jest.fn) + mockGetRobotUpdateDownloadError.mockReturnValue(null) }) afterEach(() => { jest.resetAllMocks() }) + it('renders robot update download errors', () => { + mockGetRobotUpdateDownloadError.mockReturnValue('test download error') + + const [{ getByText }] = render(props) + getByText('test download error') + }) + it('renders the robot name as a part of the header', () => { const [{ getByText }] = render(props) diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/useRobotUpdateInfo.test.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/useRobotUpdateInfo.test.tsx index 8b38bf9cde3..f1fd45669fc 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/useRobotUpdateInfo.test.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/useRobotUpdateInfo.test.tsx @@ -1,14 +1,34 @@ +import * as React from 'react' import { renderHook } from '@testing-library/react-hooks' +import { createStore } from 'redux' +import { I18nextProvider } from 'react-i18next' +import { Provider } from 'react-redux' + +import { i18n } from '../../../../../i18n' import { useRobotUpdateInfo } from '../useRobotUpdateInfo' +import { getRobotUpdateDownloadProgress } from '../../../../../redux/robot-update' + +import type { Store } from 'redux' +import { State } from '../../../../../redux/types' import type { RobotUpdateSession, UpdateSessionStep, UpdateSessionStage, } from '../../../../../redux/robot-update/types' +jest.mock('../../../../../redux/robot-update') + +const mockGetRobotUpdateDownloadProgress = getRobotUpdateDownloadProgress as jest.MockedFunction< + typeof getRobotUpdateDownloadProgress +> + describe('useRobotUpdateInfo', () => { + let store: Store + let wrapper: React.FunctionComponent<{}> + + const MOCK_ROBOT_NAME = 'testRobot' const mockRobotUpdateSession: RobotUpdateSession | null = { - robotName: 'testRobot', + robotName: MOCK_ROBOT_NAME, fileInfo: { isManualFile: true, systemFile: 'testFile', version: '1.0.0' }, token: null, pathPrefix: null, @@ -18,36 +38,79 @@ describe('useRobotUpdateInfo', () => { error: null, } - it('should return initial values when session is null', () => { - const { result } = renderHook(() => useRobotUpdateInfo(null)) + beforeEach(() => { + jest.useFakeTimers() + store = createStore(jest.fn(), {}) + store.dispatch = jest.fn() + wrapper = ({ children }) => ( + + {children} + + ) + mockGetRobotUpdateDownloadProgress.mockReturnValue(50) + }) - expect(result.current.updateStep).toBe('initial') + it('should return null when session is null', () => { + const { result } = renderHook( + () => useRobotUpdateInfo(MOCK_ROBOT_NAME, null), + { wrapper } + ) + + expect(result.current.updateStep).toBe(null) expect(result.current.progressPercent).toBe(0) }) it('should return initial values when there is no session step and stage', () => { - const { result } = renderHook(session => useRobotUpdateInfo(session), { - initialProps: { - ...mockRobotUpdateSession, - step: null, - stage: null, - }, - }) + const { result } = renderHook( + session => useRobotUpdateInfo(MOCK_ROBOT_NAME, session), + { + initialProps: { + ...mockRobotUpdateSession, + step: null, + stage: null, + } as any, + wrapper, + } + ) expect(result.current.updateStep).toBe('initial') expect(result.current.progressPercent).toBe(0) }) + it('should return download updateStep and appropriate percentages when the update is downloading', () => { + const { result, rerender } = renderHook( + session => useRobotUpdateInfo(MOCK_ROBOT_NAME, session), + { + initialProps: { + ...mockRobotUpdateSession, + step: 'downloadFile', + } as any, + wrapper, + } + ) + + expect(result.current.updateStep).toBe('download') + expect(Math.round(result.current.progressPercent)).toBe(17) + + rerender({ + ...mockRobotUpdateSession, + }) + + expect(result.current.updateStep).toBe('install') + expect(result.current.progressPercent).toBe(50) + }) + it('should update updateStep and progressPercent when session is provided', () => { const { result, rerender } = renderHook( - session => useRobotUpdateInfo(session), + session => useRobotUpdateInfo(MOCK_ROBOT_NAME, session), { - initialProps: mockRobotUpdateSession, + initialProps: mockRobotUpdateSession as any, + wrapper, } ) expect(result.current.updateStep).toBe('install') - expect(Math.round(result.current.progressPercent)).toBe(75) + expect(Math.round(result.current.progressPercent)).toBe(25) rerender({ ...mockRobotUpdateSession, @@ -63,14 +126,15 @@ describe('useRobotUpdateInfo', () => { it('should return correct updateStep and progressPercent values when there is an error', () => { const { result, rerender } = renderHook( - session => useRobotUpdateInfo(session), + session => useRobotUpdateInfo(MOCK_ROBOT_NAME, session), { - initialProps: mockRobotUpdateSession, + initialProps: mockRobotUpdateSession as any, + wrapper, } ) expect(result.current.updateStep).toBe('install') - expect(Math.round(result.current.progressPercent)).toBe(75) + expect(Math.round(result.current.progressPercent)).toBe(25) rerender({ ...mockRobotUpdateSession, @@ -78,34 +142,42 @@ describe('useRobotUpdateInfo', () => { }) expect(result.current.updateStep).toBe('error') - expect(Math.round(result.current.progressPercent)).toBe(75) + expect(Math.round(result.current.progressPercent)).toBe(25) }) it('should calculate correct progressPercent when the update is not manual', () => { - const { result } = renderHook(session => useRobotUpdateInfo(session), { - initialProps: { - ...mockRobotUpdateSession, - fileInfo: { - systemFile: 'downloadPath', - version: '1.0.0', - isManualFile: false, - }, - }, - }) + const { result } = renderHook( + session => useRobotUpdateInfo(MOCK_ROBOT_NAME, session), + { + initialProps: { + ...mockRobotUpdateSession, + fileInfo: { + systemFile: 'downloadPath', + version: '1.0.0', + isManualFile: false, + }, + } as any, + wrapper, + } + ) expect(result.current.updateStep).toBe('install') - expect(Math.round(result.current.progressPercent)).toBe(75) + expect(Math.round(result.current.progressPercent)).toBe(25) }) it('should ignore progressPercent reported by a step marked as ignored', () => { - const { result } = renderHook(session => useRobotUpdateInfo(session), { - initialProps: { - ...mockRobotUpdateSession, - step: 'processFile' as UpdateSessionStep, - stage: 'awaiting-file' as UpdateSessionStage, - progress: 100, - }, - }) + const { result } = renderHook( + session => useRobotUpdateInfo(MOCK_ROBOT_NAME, session), + { + initialProps: { + ...mockRobotUpdateSession, + step: 'processFile' as UpdateSessionStep, + stage: 'awaiting-file' as UpdateSessionStage, + progress: 100, + } as any, + wrapper, + } + ) expect(result.current.updateStep).toBe('install') expect(Math.round(result.current.progressPercent)).toBe(0) diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/useRobotUpdateInfo.ts b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/useRobotUpdateInfo.ts index 3e1b6e60a56..75c35746c9d 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/useRobotUpdateInfo.ts +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/useRobotUpdateInfo.ts @@ -1,16 +1,20 @@ import * as React from 'react' +import { useSelector } from 'react-redux' + +import { getRobotUpdateDownloadProgress } from '../../../../redux/robot-update' + import type { RobotUpdateSession } from '../../../../redux/robot-update/types' +import type { State } from '../../../../redux/types' export function useRobotUpdateInfo( + robotName: string, session: RobotUpdateSession | null -): { updateStep: UpdateStep; progressPercent: number } { - const progressPercent = useFindProgressPercentFrom(session) +): { updateStep: UpdateStep | null; progressPercent: number } { + const progressPercent = useFindProgressPercentFrom(robotName, session) - const shellReportedUpdateStep = React.useMemo( - () => getShellReportedUpdateStep(session), - [session] - ) - const updateStep = useTransitionUpdateStepFrom(shellReportedUpdateStep) + const updateStep = React.useMemo(() => determineUpdateStepFrom(session), [ + session, + ]) return { updateStep, @@ -19,22 +23,35 @@ export function useRobotUpdateInfo( } function useFindProgressPercentFrom( + robotName: string, session: RobotUpdateSession | null ): number { const [progressPercent, setProgressPercent] = React.useState(0) + const hasSeenDownloadFileStep = React.useRef(false) const prevSeenUpdateStep = React.useRef(null) const prevSeenStepProgress = React.useRef(0) const currentStepWithProgress = React.useRef(-1) - if (session == null) return progressPercent + const downloadProgress = useSelector((state: State) => + getRobotUpdateDownloadProgress(state, robotName) + ) + + if (session == null) { + if (progressPercent !== 0) { + setProgressPercent(0) + prevSeenStepProgress.current = 0 + hasSeenDownloadFileStep.current = false + } + return progressPercent + } - const { + let { step: sessionStep, stage: sessionStage, progress: stepProgress, } = session - if (sessionStep === 'getToken') { + if (sessionStep == null && sessionStage == null) { if (progressPercent !== 0) { setProgressPercent(0) prevSeenStepProgress.current = 0 @@ -46,27 +63,30 @@ function useFindProgressPercentFrom( prevSeenStepProgress.current = 100 } return progressPercent - } else if ( - sessionStage === 'error' || - sessionStage === null || - stepProgress == null || - sessionStep == null - ) { + } else if (sessionStage === 'error') { return progressPercent } const stepAndStage = `${sessionStep}-${sessionStage}` - // Ignored because 0-100 is too fast to be worth recording. + // Ignored because 0-100 is too fast to be worth recording or currently unsupported. const IGNORED_STEPS_AND_STAGES = [ 'processFile-awaiting-file', 'uploadFile-awaiting-file', ] + + if (sessionStep === 'downloadFile') { + hasSeenDownloadFileStep.current = true + stepProgress = downloadProgress + } + + stepProgress = stepProgress ?? 0 + // Each stepAndStage is an equal fraction of the total steps. - const TOTAL_STEPS_WITH_PROGRESS = 2 + const TOTAL_STEPS_WITH_PROGRESS = hasSeenDownloadFileStep.current ? 3 : 2 const isNewStateWithProgress = prevSeenUpdateStep.current !== stepAndStage && - stepProgress > 0 && // Accomodate for shell progress oddities. + stepProgress > 0 && // Accommodate for shell progress oddities. stepProgress < 100 // Proceed to next fraction of progress bar. @@ -79,7 +99,7 @@ function useFindProgressPercentFrom( (100 * currentStepWithProgress.current) / TOTAL_STEPS_WITH_PROGRESS prevSeenStepProgress.current = 0 prevSeenUpdateStep.current = stepAndStage - setProgressPercent(completedStepsWithProgress + stepProgress) + setProgressPercent(completedStepsWithProgress) } // Proceed with current fraction of progress bar. else if ( @@ -87,12 +107,13 @@ function useFindProgressPercentFrom( !IGNORED_STEPS_AND_STAGES.includes(stepAndStage) ) { const currentStepProgress = - progressPercent + (stepProgress - prevSeenStepProgress.current) / TOTAL_STEPS_WITH_PROGRESS + const nonBacktrackedProgressPercent = Math.max( progressPercent, - currentStepProgress + currentStepProgress + progressPercent ) + prevSeenStepProgress.current = stepProgress setProgressPercent(nonBacktrackedProgressPercent) } @@ -108,18 +129,19 @@ export type UpdateStep = | 'finished' | 'error' -function getShellReportedUpdateStep( +function determineUpdateStepFrom( session: RobotUpdateSession | null ): UpdateStep | null { if (session == null) return null const { step: sessionStep, stage: sessionStage, error } = session - // TODO(jh, 09-14-2023: add download logic to app-shell/redux/progress bar. let reportedUpdateStep: UpdateStep if (error != null) { reportedUpdateStep = 'error' } else if (sessionStep == null && sessionStage == null) { reportedUpdateStep = 'initial' + } else if (sessionStep === 'downloadFile') { + reportedUpdateStep = 'download' } else if (sessionStep === 'finished') { reportedUpdateStep = 'finished' } else if ( @@ -134,44 +156,3 @@ function getShellReportedUpdateStep( return reportedUpdateStep } - -// Shell steps have the potential to backtrack, so use guarded transitions. -function useTransitionUpdateStepFrom( - reportedUpdateStep: UpdateStep | null -): UpdateStep { - const [updateStep, setUpdateStep] = React.useState('initial') - const prevUpdateStep = React.useRef(null) - - switch (reportedUpdateStep) { - case 'initial': - if (updateStep !== 'initial') { - setUpdateStep('initial') - prevUpdateStep.current = null - } - break - case 'error': - if (updateStep !== 'error') { - setUpdateStep('error') - } - break - case 'install': - if (updateStep === 'initial' && prevUpdateStep.current == null) { - setUpdateStep('install') - prevUpdateStep.current = 'initial' - } - break - case 'restart': - if (updateStep === 'install' && prevUpdateStep.current === 'initial') { - setUpdateStep('restart') - prevUpdateStep.current = 'install' - } - break - case 'finished': - if (updateStep === 'restart' && prevUpdateStep.current === 'install') { - setUpdateStep('finished') - prevUpdateStep.current = 'restart' - } - break - } - return updateStep -} diff --git a/app/src/redux/robot-update/__tests__/epic.test.ts b/app/src/redux/robot-update/__tests__/epic.test.ts index 92172ec3852..91141fa75ab 100644 --- a/app/src/redux/robot-update/__tests__/epic.test.ts +++ b/app/src/redux/robot-update/__tests__/epic.test.ts @@ -386,6 +386,46 @@ describe('robot update epics', () => { }) }) + describe('startUpdateAfterFileDownload', () => { + it('should start the update after file download if the robot is a flex', () => { + testScheduler.run(({ hot, cold, expectObservable }) => { + const session: ReturnType = { + stage: 'done', + step: 'downloadFile', + } as any + + getRobotUpdateRobot.mockReturnValue(brRobotFlex) + getRobotUpdateSession.mockReturnValue(session) + + const state$ = hot('-a', { a: state }) + const output$ = epics.startUpdateAfterFileDownload(null as any, state$) + + expectObservable(output$).toBe('-a', { + a: actions.readSystemRobotUpdateFile('flex'), + }) + }) + }) + + it('should start the update after file download if the robot is a ot-2', () => { + testScheduler.run(({ hot, cold, expectObservable }) => { + const session: ReturnType = { + stage: 'done', + step: 'downloadFile', + } as any + + getRobotUpdateRobot.mockReturnValue(brRobotOt2) + getRobotUpdateSession.mockReturnValue(session) + + const state$ = hot('-a', { a: state }) + const output$ = epics.startUpdateAfterFileDownload(null as any, state$) + + expectObservable(output$).toBe('-a', { + a: actions.readSystemRobotUpdateFile('ot2'), + }) + }) + }) + }) + it('retryAfterPremigrationEpic', () => { testScheduler.run(({ hot, expectObservable }) => { getRobotUpdateRobot.mockReturnValueOnce(brReadyRobot) diff --git a/app/src/redux/robot-update/__tests__/reducer.test.ts b/app/src/redux/robot-update/__tests__/reducer.test.ts index 05a38d7b303..f681706c2b6 100644 --- a/app/src/redux/robot-update/__tests__/reducer.test.ts +++ b/app/src/redux/robot-update/__tests__/reducer.test.ts @@ -137,6 +137,69 @@ describe('robot update reducer', () => { }, }, }, + { + name: 'handles robotUpdate:CHECKING_FOR_UPDATE', + action: { + type: 'robotUpdate:CHECKING_FOR_UPDATE', + payload: 'ot2', + }, + initialState: { ...INITIAL_STATE, session: null }, + expected: { + ...INITIAL_STATE, + session: { + step: 'downloadFile', + stage: 'writing', + target: 'ot2', + }, + }, + }, + { + name: + 'handles robotUpdate:DOWNLOAD_DONE when the target matches the robot type', + action: { + type: 'robotUpdate:DOWNLOAD_DONE', + payload: 'ot2', + }, + initialState: { + ...INITIAL_STATE, + session: { + step: 'downloadFile', + stage: 'writing', + target: 'ot2', + }, + }, + expected: { + ...INITIAL_STATE, + session: { + step: 'downloadFile', + stage: 'done', + }, + }, + }, + { + name: + 'handles robotUpdate:DOWNLOAD_DONE when the target does not match the robot type', + action: { + type: 'robotUpdate:DOWNLOAD_DONE', + payload: 'ot2', + }, + initialState: { + ...INITIAL_STATE, + session: { + step: 'downloadFile', + stage: 'writing', + target: 'flex', + }, + }, + expected: { + ...INITIAL_STATE, + session: { + step: 'downloadFile', + stage: 'writing', + target: 'flex', + }, + }, + }, { name: 'handles robotUpdate:FILE_INFO', action: { diff --git a/app/src/redux/robot-update/constants.ts b/app/src/redux/robot-update/constants.ts index 2c0e625f892..cff9ed795ca 100644 --- a/app/src/redux/robot-update/constants.ts +++ b/app/src/redux/robot-update/constants.ts @@ -2,6 +2,7 @@ export const PREMIGRATION: 'premigration' = 'premigration' export const PREMIGRATION_RESTART: 'premigrationRestart' = 'premigrationRestart' +export const DOWNLOAD_FILE: 'downloadFile' = 'downloadFile' export const GET_TOKEN: 'getToken' = 'getToken' export const UPLOAD_FILE: 'uploadFile' = 'uploadFile' export const PROCESS_FILE: 'processFile' = 'processFile' @@ -32,6 +33,9 @@ export const REINSTALL: 'reinstall' = 'reinstall' // action types +export const ROBOTUPDATE_CHECKING_FOR_UPDATE: 'robotUpdate:CHECKING_FOR_UPDATE' = + 'robotUpdate:CHECKING_FOR_UPDATE' + export const ROBOTUPDATE_UPDATE_VERSION: 'robotUpdate:UPDATE_VERSION' = 'robotUpdate:UPDATE_VERSION' @@ -47,6 +51,9 @@ export const ROBOTUPDATE_DOWNLOAD_PROGRESS: 'robotUpdate:DOWNLOAD_PROGRESS' = export const ROBOTUPDATE_DOWNLOAD_ERROR: 'robotUpdate:DOWNLOAD_ERROR' = 'robotUpdate:DOWNLOAD_ERROR' +export const ROBOTUPDATE_DOWNLOAD_DONE: 'robotUpdate:DOWNLOAD_DONE' = + 'robotUpdate:DOWNLOAD_DONE' + export const ROBOTUPDATE_SET_UPDATE_SEEN: 'robotUpdate:SET_UPDATE_SEEN' = 'robotUpdate:SET_UPDATE_SEEN' diff --git a/app/src/redux/robot-update/epic.ts b/app/src/redux/robot-update/epic.ts index 07c22e03555..f3ec8fcfacf 100644 --- a/app/src/redux/robot-update/epic.ts +++ b/app/src/redux/robot-update/epic.ts @@ -62,6 +62,7 @@ import { ROBOTUPDATE_FILE_INFO, ROBOTUPDATE_CREATE_SESSION, ROBOTUPDATE_CREATE_SESSION_SUCCESS, + DOWNLOAD_FILE, } from './constants' import type { Observable } from 'rxjs' @@ -144,6 +145,19 @@ export const startUpdateEpic: Epic = (action$, state$) => }) ) +export const startUpdateAfterFileDownload: Epic = (_, state$) => { + return state$.pipe( + filter(passActiveSession({ step: DOWNLOAD_FILE, stage: DONE })), + switchMap(stateWithSession => { + const host: ViewableRobot = getRobotUpdateRobot(stateWithSession) as any + const robotModel = + host?.serverHealth?.robotModel === 'OT-3 Standard' ? 'flex' : 'ot2' + + return of(readSystemRobotUpdateFile(robotModel)) + }) + ) +} + // listen for a the active robot to come back with capabilities after premigration export const retryAfterPremigrationEpic: Epic = (_, state$) => { return state$.pipe( @@ -284,8 +298,6 @@ const passActiveSession = (props: Partial) => ( return ( robot !== null && !session?.error && - typeof session?.pathPrefix === 'string' && - typeof session?.token === 'string' && every( props, (value, key) => session?.[key as keyof RobotUpdateSession] === value @@ -449,6 +461,7 @@ export const removeMigratedRobotsEpic: Epic = (_, state$) => { export const robotUpdateEpic = combineEpics( startUpdateEpic, + startUpdateAfterFileDownload, retryAfterPremigrationEpic, startSessionAfterFileInfoEpic, createSessionEpic, diff --git a/app/src/redux/robot-update/hooks.ts b/app/src/redux/robot-update/hooks.ts index 840349ef331..9316e87ab35 100644 --- a/app/src/redux/robot-update/hooks.ts +++ b/app/src/redux/robot-update/hooks.ts @@ -7,6 +7,7 @@ type DispatchStartRobotUpdate = ( systemFile?: string | undefined ) => void +// Safely start a robot update. export function useDispatchStartRobotUpdate(): DispatchStartRobotUpdate { const dispatch = useDispatch<(a: Action) => void>() diff --git a/app/src/redux/robot-update/reducer.ts b/app/src/redux/robot-update/reducer.ts index fecebc4ee77..50c00c411e2 100644 --- a/app/src/redux/robot-update/reducer.ts +++ b/app/src/redux/robot-update/reducer.ts @@ -23,7 +23,7 @@ export const INITIAL_STATE: RobotUpdateState = { } export const initialSession = ( - robotName: string, + robotName: string | null, session: RobotUpdateSession | null ): RobotUpdateSession => ({ robotName, @@ -67,6 +67,21 @@ export const robotUpdateReducer: Reducer = ( } } + case Constants.ROBOTUPDATE_CHECKING_FOR_UPDATE: { + const session = state.session as RobotUpdateSession + const target = action.payload + + return { + ...state, + session: { + ...session, + step: Constants.DOWNLOAD_FILE, + stage: Constants.WRITING, + target, + }, + } + } + case Constants.ROBOTUPDATE_DOWNLOAD_PROGRESS: { return { ...state, @@ -79,6 +94,24 @@ export const robotUpdateReducer: Reducer = ( } } + case Constants.ROBOTUPDATE_DOWNLOAD_DONE: { + if (!state.session) return state + + const { target, ...session } = state.session + const isThisRobotDownloadDone = + session?.step === Constants.DOWNLOAD_FILE && target === action.payload + + return isThisRobotDownloadDone + ? { + ...state, + session: { + ...session, + stage: Constants.DONE, + }, + } + : state + } + case Constants.ROBOTUPDATE_DOWNLOAD_ERROR: { return { ...state, @@ -104,7 +137,12 @@ export const robotUpdateReducer: Reducer = ( return { ...state, - session: { ...session, step: Constants.GET_TOKEN }, + session: { + ...session, + robotName: host.name, + step: Constants.GET_TOKEN, + stage: null, + }, } } diff --git a/app/src/redux/robot-update/types.ts b/app/src/redux/robot-update/types.ts index c3fbe2193d0..81f43a7e571 100644 --- a/app/src/redux/robot-update/types.ts +++ b/app/src/redux/robot-update/types.ts @@ -39,6 +39,7 @@ export type UpdateSessionStage = export type UpdateSessionStep = | 'premigration' | 'premigrationRestart' + | 'downloadFile' | 'getToken' | 'uploadFile' | 'processFile' @@ -48,7 +49,7 @@ export type UpdateSessionStep = | 'finished' export interface RobotUpdateSession { - robotName: string + robotName: string | null fileInfo: RobotUpdateFileInfo | null token: string | null pathPrefix: string | null @@ -56,6 +57,7 @@ export interface RobotUpdateSession { stage: UpdateSessionStage | null progress: number | null error: string | null + target?: RobotUpdateTarget } export interface PerTargetRobotUpdateState { @@ -181,3 +183,5 @@ export type RobotUpdateAction = | { type: 'robotUpdate:CLEAR_SESSION' } | { type: 'robotUpdate:SET_UPDATE_SEEN'; meta: { robotName: string } } | { type: 'robotUpdate:FILE_UPLOAD_PROGRESS'; payload: number } + | { type: 'robotUpdate:CHECKING_FOR_UPDATE'; payload: RobotUpdateTarget } + | { type: 'robotUpdate:DOWNLOAD_DONE'; payload: RobotUpdateTarget } From d631fc198a9308fdac8f2d0818d84096f233a5b8 Mon Sep 17 00:00:00 2001 From: Ryan Howard Date: Wed, 8 Nov 2023 10:03:58 -0500 Subject: [PATCH 26/65] chore(api): fix push-ot3 for some versions of linux that can't use the multifile scp command (#13911) --- api/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/Makefile b/api/Makefile index adff7704fd9..c6e78d04939 100755 --- a/api/Makefile +++ b/api/Makefile @@ -184,7 +184,8 @@ push-no-restart-ot3: sdist echo $(sdist_file) $(call push-python-sdist,$(host),$(ssh_key),$(ssh_opts),$(sdist_file),/opt/opentrons-robot-server,opentrons,src,,$(version_file)) ssh $(ssh_helper) root@$(host) "mount -o remount,rw / && mkdir -p /usr/local/bin" - scp $(ssh_helper) ./src/opentrons/hardware_control/scripts/{ot3repl,ot3gripper} root@$(host):/usr/local/bin/ + scp $(ssh_helper) ./src/opentrons/hardware_control/scripts/ot3repl root@$(host):/usr/local/bin/ + scp $(ssh_helper) ./src/opentrons/hardware_control/scripts/ot3gripper root@$(host):/usr/local/bin/ ssh $(ssh_helper) root@$(host) "mount -o remount,ro /" .PHONY: push-ot3 From 9d5418f84bf68f7df71b74914e3aee944e1a1615 Mon Sep 17 00:00:00 2001 From: Frank Sinapi Date: Wed, 8 Nov 2023 10:28:14 -0500 Subject: [PATCH 27/65] fix(api, shared-data, robot-server): stringify all error info in run log (#13942) * fix(shared-data, api): stringify exception details dict to prevent runlog pydantic validation errors * Add protection for run store to return None if pydantic validation of a state summary fails * Log run store errors when they happen --- api/src/opentrons/hardware_control/api.py | 12 +-- .../backends/ot3controller.py | 2 +- api/src/opentrons/hardware_control/errors.py | 2 +- .../instruments/ot2/pipette_handler.py | 2 +- .../instruments/ot3/gripper.py | 8 +- .../instruments/ot3/gripper_handler.py | 2 +- .../instruments/ot3/pipette.py | 2 +- .../instruments/ot3/pipette_handler.py | 2 +- api/src/opentrons/hardware_control/ot3api.py | 2 +- .../protocol_runner/json_file_reader.py | 6 +- robot-server/robot_server/runs/run_store.py | 19 ++-- robot-server/tests/runs/test_run_store.py | 56 +++++++++++ .../errors/exceptions.py | 96 +++++++++---------- 13 files changed, 138 insertions(+), 73 deletions(-) diff --git a/api/src/opentrons/hardware_control/api.py b/api/src/opentrons/hardware_control/api.py index 75d0bd65226..f3f70c16b9a 100644 --- a/api/src/opentrons/hardware_control/api.py +++ b/api/src/opentrons/hardware_control/api.py @@ -618,7 +618,7 @@ async def home(self, axes: Optional[List[Axis]] = None) -> None: if any(unsupported): raise UnsupportedHardwareCommand( message=f"At least one axis in {axes} is not supported on the OT2.", - detail={"unsupported_axes": unsupported}, + detail={"unsupported_axes": str(unsupported)}, ) self._reset_last_mount() # Initialize/update current_position @@ -661,14 +661,14 @@ async def current_position( raise PositionUnknownError( message=f"Current position of {str(mount)} pipette is unknown," " please home.", - detail={"mount": str(mount), "missing_axes": position_axes}, + detail={"mount": str(mount), "missing_axes": str(position_axes)}, ) axes_str = [ot2_axis_to_string(a) for a in position_axes] if not self._backend.is_homed(axes_str): unhomed = self._backend._unhomed_axes(axes_str) raise PositionUnknownError( message=f"{str(mount)} pipette axes ({unhomed}) must be homed.", - detail={"mount": str(mount), "unhomed_axes": unhomed}, + detail={"mount": str(mount), "unhomed_axes": str(unhomed)}, ) elif not self._current_position and not refresh: raise PositionUnknownError( @@ -755,7 +755,7 @@ async def move_axes( """ raise UnsupportedHardwareCommand( message="move_axes is not supported on the OT-2.", - detail={"axes_commanded": list(position.keys())}, + detail={"axes_commanded": str(list(position.keys()))}, ) async def move_rel( @@ -781,7 +781,7 @@ async def move_rel( " is unknown.", detail={ "mount": str(mount), - "fail_on_not_homed": fail_on_not_homed, + "fail_on_not_homed": str(fail_on_not_homed), }, ) else: @@ -797,7 +797,7 @@ async def move_rel( unhomed = self._backend._unhomed_axes(axes_str) raise PositionUnknownError( message=f"{str(mount)} pipette axes ({unhomed}) must be homed.", - detail={"mount": str(mount), "unhomed_axes": unhomed}, + detail={"mount": str(mount), "unhomed_axes": str(unhomed)}, ) await self._cache_and_maybe_retract_mount(mount) diff --git a/api/src/opentrons/hardware_control/backends/ot3controller.py b/api/src/opentrons/hardware_control/backends/ot3controller.py index 7c4ce56ac4f..9718e298dfd 100644 --- a/api/src/opentrons/hardware_control/backends/ot3controller.py +++ b/api/src/opentrons/hardware_control/backends/ot3controller.py @@ -1166,7 +1166,7 @@ def _pop_queue() -> Optional[Tuple[NodeId, ErrorCode]]: mount = Axis.to_ot3_mount(node_to_axis(q_msg[0])) raise PipetteOverpressureError( message=msg.format(str(mount)), - detail={"mount": mount}, + detail={"mount": str(mount)}, ) else: yield diff --git a/api/src/opentrons/hardware_control/errors.py b/api/src/opentrons/hardware_control/errors.py index f678167cf28..6cde3fa076b 100644 --- a/api/src/opentrons/hardware_control/errors.py +++ b/api/src/opentrons/hardware_control/errors.py @@ -25,7 +25,7 @@ class InvalidPipetteName(InvalidInstrumentData): def __init__(self, name: int, mount: str) -> None: super().__init__( message=f"Invalid pipette name key {name} on mount {mount}", - detail={"mount": mount, "name": name}, + detail={"mount": mount, "name": str(name)}, ) diff --git a/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py b/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py index 43d4e1518b4..67596cea790 100644 --- a/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py +++ b/api/src/opentrons/hardware_control/instruments/ot2/pipette_handler.py @@ -638,7 +638,7 @@ def plan_check_dispense( # type: ignore[no-untyped-def] message="Cannot push_out on a dispense that does not leave the pipette empty", detail={ "command": "dispense", - "remaining-volume": instrument.current_volume - disp_vol, + "remaining-volume": str(instrument.current_volume - disp_vol), }, ) push_out_ul = 0 diff --git a/api/src/opentrons/hardware_control/instruments/ot3/gripper.py b/api/src/opentrons/hardware_control/instruments/ot3/gripper.py index 7eb757fd333..3eb3c863522 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/gripper.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/gripper.py @@ -183,16 +183,16 @@ def check_calibration_pin_location_is_accurate(self) -> None: raise CommandPreconditionViolated( "Cannot calibrate gripper without attaching a calibration probe", detail={ - "probe": self._attached_probe, - "jaw_state": self.state, + "probe": str(self._attached_probe), + "jaw_state": str(self.state), }, ) if self.state != GripperJawState.GRIPPING: raise CommandPreconditionViolated( "Cannot calibrate gripper if jaw is not in gripping state", detail={ - "probe": self._attached_probe, - "jaw_state": self.state, + "probe": str(self._attached_probe), + "jaw_state": str(self.state), }, ) diff --git a/api/src/opentrons/hardware_control/instruments/ot3/gripper_handler.py b/api/src/opentrons/hardware_control/instruments/ot3/gripper_handler.py index 51778b08b92..cf2ba55e23d 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/gripper_handler.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/gripper_handler.py @@ -133,7 +133,7 @@ def check_ready_for_jaw_move(self, command: str) -> None: message=f"Cannot {command} gripper jaw before homing", detail={ "command": command, - "jaw_state": gripper.state, + "jaw_state": str(gripper.state), }, ) diff --git a/api/src/opentrons/hardware_control/instruments/ot3/pipette.py b/api/src/opentrons/hardware_control/instruments/ot3/pipette.py index 89f99416726..1f6dd0b4b59 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/pipette.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/pipette.py @@ -597,7 +597,7 @@ def set_liquid_class_by_name(self, class_name: str) -> None: message=f"Liquid class {class_name} is not valid for {self._config.display_name}", detail={ "requested-class-name": class_name, - "pipette-model": self._pipette_model, + "pipette-model": str(self._pipette_model), }, ) if ( diff --git a/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py b/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py index 8b00f6f7aeb..36b41e3e816 100644 --- a/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py +++ b/api/src/opentrons/hardware_control/instruments/ot3/pipette_handler.py @@ -613,7 +613,7 @@ def plan_check_dispense( message="Cannot push_out on a dispense that does not leave the pipette empty", detail={ "command": "dispense", - "remaining-volume": instrument.current_volume - disp_vol, + "remaining-volume": str(instrument.current_volume - disp_vol), }, ) push_out_ul = 0 diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index 1a2eb65e8a6..11b9682805c 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -945,7 +945,7 @@ async def current_position_ot3( raise PositionUnknownError( message=f"Motor positions for {str(mount)} mount are missing (" f"{mount_axes}); must first home motors.", - detail={"mount": str(mount), "missing_axes": mount_axes}, + detail={"mount": str(mount), "missing_axes": str(mount_axes)}, ) self._assert_motor_ok(mount_axes) diff --git a/api/src/opentrons/protocol_runner/json_file_reader.py b/api/src/opentrons/protocol_runner/json_file_reader.py index 17f82ec8cee..488c28d273b 100644 --- a/api/src/opentrons/protocol_runner/json_file_reader.py +++ b/api/src/opentrons/protocol_runner/json_file_reader.py @@ -25,7 +25,7 @@ def read( message=f"Cannot execute {name} as a JSON protocol", detail={ "kind": "non-json-file-in-json-file-reader", - "metadata-name": protocol_source.metadata.get("name"), + "metadata-name": str(protocol_source.metadata.get("name")), "file-name": protocol_source.main_file.name, }, ) @@ -40,7 +40,9 @@ def read( message=f"{name} is a JSON protocol v{protocol_source.config.schema_version} which this robot cannot execute", detail={ "kind": "schema-version-unknown", - "requested-schema-version": protocol_source.config.schema_version, + "requested-schema-version": str( + protocol_source.config.schema_version + ), "minimum-handled-schema-version": "6", "maximum-handled-shcema-version": "8", }, diff --git a/robot-server/robot_server/runs/run_store.py b/robot-server/robot_server/runs/run_store.py index 32f2eca3251..88471787da3 100644 --- a/robot-server/robot_server/runs/run_store.py +++ b/robot-server/robot_server/runs/run_store.py @@ -1,4 +1,5 @@ """Runs' on-db store.""" +import logging from collections import defaultdict from dataclasses import dataclass from datetime import datetime @@ -6,7 +7,7 @@ from typing import Any, Dict, List, Optional, cast import sqlalchemy -from pydantic import parse_obj_as +from pydantic import parse_obj_as, ValidationError from opentrons.util.helpers import utc_now from opentrons.protocol_engine import StateSummary, CommandSlice @@ -18,6 +19,8 @@ from .action_models import RunAction, RunActionType from .run_models import RunNotFoundError +log = logging.getLogger(__name__) + _CACHE_ENTRIES = 32 @@ -256,11 +259,15 @@ def get_state_summary(self, run_id: str) -> Optional[StateSummary]: with self._sql_engine.begin() as transaction: row = transaction.execute(select_run_data).one() - return ( - StateSummary.parse_obj(row.state_summary) - if row.state_summary is not None - else None - ) + try: + return ( + StateSummary.parse_obj(row.state_summary) + if row.state_summary is not None + else None + ) + except ValidationError as e: + log.warn(f"Error retrieving state summary for {run_id}: {e}") + return None @lru_cache(maxsize=_CACHE_ENTRIES) def _get_all_unparsed_commands(self, run_id: str) -> List[Dict[str, Any]]: diff --git a/robot-server/tests/runs/test_run_store.py b/robot-server/tests/runs/test_run_store.py index 3350a290d13..c805b944714 100644 --- a/robot-server/tests/runs/test_run_store.py +++ b/robot-server/tests/runs/test_run_store.py @@ -104,6 +104,46 @@ def state_summary() -> StateSummary: ) +@pytest.fixture +def invalid_state_summary() -> StateSummary: + """Should fail pydantic validation.""" + analysis_error = pe_errors.ErrorOccurrence.construct( + id="error-id", + # Invalid value here should fail analysis + createdAt=MountType.LEFT, # type: ignore + errorType="BadError", + detail="oh no", + ) + + analysis_labware = pe_types.LoadedLabware( + id="labware-id", + loadName="load-name", + definitionUri="namespace/load-name/42", + location=pe_types.DeckSlotLocation(slotName=DeckSlotName.SLOT_1), + offsetId=None, + ) + + analysis_pipette = pe_types.LoadedPipette( + id="pipette-id", + pipetteName=PipetteNameType.P300_SINGLE, + mount=MountType.LEFT, + ) + + liquids = [Liquid(id="some-id", displayName="water", description="water desc")] + + return StateSummary( + errors=[analysis_error], + labware=[analysis_labware], + pipettes=[analysis_pipette], + # TODO(mc, 2022-02-14): evaluate usage of modules in the analysis resp. + modules=[], + # TODO (tz 22-4-19): added the field to class. make sure what to initialize + labwareOffsets=[], + status=EngineStatus.IDLE, + liquids=liquids, + ) + + def test_update_run_state( subject: RunStore, state_summary: StateSummary, @@ -367,6 +407,22 @@ def test_get_state_summary(subject: RunStore, state_summary: StateSummary) -> No assert result == state_summary +def test_get_state_summary_failure( + subject: RunStore, invalid_state_summary: StateSummary +) -> None: + """It should return None.""" + subject.insert( + run_id="run-id", + protocol_id=None, + created_at=datetime(year=2021, month=1, day=1, tzinfo=timezone.utc), + ) + subject.update_run_state( + run_id="run-id", summary=invalid_state_summary, commands=[] + ) + result = subject.get_state_summary(run_id="run-id") + assert result is None + + def test_get_state_summary_none(subject: RunStore) -> None: """It should return None if no state data stored.""" subject.insert( diff --git a/shared-data/python/opentrons_shared_data/errors/exceptions.py b/shared-data/python/opentrons_shared_data/errors/exceptions.py index fa784e5fb90..9483b404965 100644 --- a/shared-data/python/opentrons_shared_data/errors/exceptions.py +++ b/shared-data/python/opentrons_shared_data/errors/exceptions.py @@ -19,7 +19,7 @@ def __init__( self, code: ErrorCodes, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence["EnumeratedError"]] = None, ) -> None: """Build an EnumeratedError.""" @@ -61,7 +61,7 @@ def __init__( self, code: Optional[ErrorCodes] = None, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CommunicationError.""" @@ -88,7 +88,7 @@ def __init__( self, code: Optional[ErrorCodes] = None, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a RoboticsControlError.""" @@ -116,7 +116,7 @@ def __init__( self, code: Optional[ErrorCodes] = None, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a RoboticsInteractionError.""" @@ -144,7 +144,7 @@ def __init__( self, code: Optional[ErrorCodes] = None, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[Union[EnumeratedError, BaseException]]] = None, ) -> None: """Build a GeneralError.""" @@ -220,7 +220,7 @@ class RobotInUseError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CanbusCommunicationError.""" @@ -233,7 +233,7 @@ class CanbusCommunicationError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CanbusCommunicationError.""" @@ -248,7 +248,7 @@ class InternalUSBCommunicationError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an InternalUSBCommunicationError.""" @@ -263,7 +263,7 @@ class ModuleCommunicationError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CanbusCommunicationError.""" @@ -278,7 +278,7 @@ class CommandTimedOutError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CommandTimedOutError.""" @@ -291,7 +291,7 @@ class FirmwareUpdateFailedError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a FirmwareUpdateFailedError.""" @@ -304,7 +304,7 @@ class InternalMessageFormatError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an InternalMesasgeFormatError.""" @@ -319,7 +319,7 @@ class CANBusConfigurationError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CANBus Configuration Error.""" @@ -334,7 +334,7 @@ class CANBusBusError(CommunicationError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CANBus Bus Error.""" @@ -347,7 +347,7 @@ class MotionFailedError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a MotionFailedError.""" @@ -360,7 +360,7 @@ class HomingFailedError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a HomingFailedError.""" @@ -373,7 +373,7 @@ class StallOrCollisionDetectedError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a StallOrCollisionDetectedError.""" @@ -388,7 +388,7 @@ class MotionPlanningFailureError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a MotionPlanningFailureError.""" @@ -401,7 +401,7 @@ class PositionEstimationInvalidError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a PositionEstimationFailedError.""" @@ -416,7 +416,7 @@ class MoveConditionNotMetError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a MoveConditionNotMetError.""" @@ -435,7 +435,7 @@ def __init__( self, structure_height: float, lower_limit: float, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CalibrationStructureNotFoundError.""" @@ -454,7 +454,7 @@ def __init__( self, edge_name: str, stride: float, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a EdgeNotFoundError.""" @@ -473,7 +473,7 @@ def __init__( self, found: float, nominal: float, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a EarlyCapacitiveSenseTrigger.""" @@ -492,7 +492,7 @@ def __init__( self, found: float, nominal: float, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a InaccurateNonContactSweepError.""" @@ -513,7 +513,7 @@ class MisalignedGantryError(RoboticsControlError): def __init__( self, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a MisalignedGantryError.""" @@ -534,7 +534,7 @@ class UnmatchedTipPresenceStates(RoboticsControlError): def __init__( self, states: Dict[int, int], - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an UnmatchedTipPresenceStatesError.""" @@ -562,7 +562,7 @@ class PositionUnknownError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a PositionUnknownError.""" @@ -575,7 +575,7 @@ class ExecutionCancelledError(RoboticsControlError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a ExecutionCancelledError.""" @@ -588,7 +588,7 @@ class LabwareDroppedError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a LabwareDroppedError.""" @@ -601,7 +601,7 @@ class TipPickupFailedError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a TipPickupFailedError.""" @@ -614,7 +614,7 @@ class TipDropFailedError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a TipPickupFailedError.""" @@ -629,7 +629,7 @@ def __init__( action: str, pipette_name: str, mount: str, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an UnexpectedTipRemovalError.""" @@ -651,7 +651,7 @@ def __init__( pipette_name: str, mount: str, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an UnexpectedTipAttachError.""" @@ -670,7 +670,7 @@ def __init__( action: str, subsystems_to_update: List[Any], message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a FirmwareUpdateRequiredError.""" @@ -687,7 +687,7 @@ class PipetteOverpressureError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an PipetteOverpressureError.""" @@ -700,7 +700,7 @@ class EStopActivatedError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an EStopActivatedError.""" @@ -713,7 +713,7 @@ class EStopNotPresentError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an EStopNotPresentError.""" @@ -726,7 +726,7 @@ class PipetteNotPresentError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an PipetteNotPresentError.""" @@ -739,7 +739,7 @@ class GripperNotPresentError(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a GripperNotPresentError.""" @@ -752,7 +752,7 @@ class InvalidActuator(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an InvalidActuator.""" @@ -766,7 +766,7 @@ def __init__( self, identifier: str, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a ModuleNotPresentError.""" @@ -784,7 +784,7 @@ class InvalidInstrumentData(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an InvalidInstrumentData.""" @@ -797,7 +797,7 @@ class InvalidLiquidClassName(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an InvalidLiquidClassName.""" @@ -812,7 +812,7 @@ class TipDetectorNotFound(RoboticsInteractionError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a TipDetectorNotFound.""" @@ -827,7 +827,7 @@ def __init__( api_element: str, since_version: str, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an APIRemoved error.""" @@ -849,7 +849,7 @@ class CommandPreconditionViolated(GeneralError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build a CommandPreconditionViolated instance.""" @@ -893,7 +893,7 @@ class UnsupportedHardwareCommand(GeneralError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an UnsupportedHardwareCommand.""" @@ -908,7 +908,7 @@ class InvalidProtocolData(GeneralError): def __init__( self, message: Optional[str] = None, - detail: Optional[Dict[str, Any]] = None, + detail: Optional[Dict[str, str]] = None, wrapping: Optional[Sequence[EnumeratedError]] = None, ) -> None: """Build an InvalidProtocolData.""" From 566027a3a719d4e29f14bc7991653adf1b60144d Mon Sep 17 00:00:00 2001 From: Shlok Amin Date: Wed, 8 Nov 2023 11:17:28 -0500 Subject: [PATCH 28/65] refactor(app): only show ODD runs loading screen when server returns 503 (#13940) --- .../Devices/__tests__/RecentProtocolRuns.test.tsx | 5 +++-- .../Devices/hooks/__tests__/useIsRobotBusy.test.ts | 3 ++- .../pages/OnDeviceDisplay/RobotDashboard/index.tsx | 2 +- react-api-client/src/runs/useAllRunsQuery.ts | 12 +++++++++--- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/app/src/organisms/Devices/__tests__/RecentProtocolRuns.test.tsx b/app/src/organisms/Devices/__tests__/RecentProtocolRuns.test.tsx index 570da04652d..2cfb460f4a7 100644 --- a/app/src/organisms/Devices/__tests__/RecentProtocolRuns.test.tsx +++ b/app/src/organisms/Devices/__tests__/RecentProtocolRuns.test.tsx @@ -8,6 +8,7 @@ import { RecentProtocolRuns } from '../RecentProtocolRuns' import { HistoricalProtocolRun } from '../HistoricalProtocolRun' import type { Runs } from '@opentrons/api-client' +import type { AxiosError } from 'axios' jest.mock('@opentrons/react-api-client') jest.mock('../hooks') @@ -57,7 +58,7 @@ describe('RecentProtocolRuns', () => { mockUseIsRobotViewable.mockReturnValue(true) mockUseAllRunsQuery.mockReturnValue({ data: {}, - } as UseQueryResult) + } as UseQueryResult) const [{ getByText }] = render() getByText('No protocol runs yet!') @@ -76,7 +77,7 @@ describe('RecentProtocolRuns', () => { }, ], }, - } as UseQueryResult) + } as UseQueryResult) const [{ getByText }] = render() getByText('Recent Protocol Runs') getByText('Run') diff --git a/app/src/organisms/Devices/hooks/__tests__/useIsRobotBusy.test.ts b/app/src/organisms/Devices/hooks/__tests__/useIsRobotBusy.test.ts index 559ea98da67..fd6a466c5e8 100644 --- a/app/src/organisms/Devices/hooks/__tests__/useIsRobotBusy.test.ts +++ b/app/src/organisms/Devices/hooks/__tests__/useIsRobotBusy.test.ts @@ -14,6 +14,7 @@ import { useIsRobotBusy } from '../useIsRobotBusy' import { useIsFlex } from '../useIsFlex' import type { Sessions, Runs } from '@opentrons/api-client' +import type { AxiosError } from 'axios' jest.mock('@opentrons/react-api-client') jest.mock('../../../ProtocolUpload/hooks') @@ -49,7 +50,7 @@ describe('useIsRobotBusy', () => { current: {}, }, }, - } as UseQueryResult) + } as UseQueryResult) mockUseEstopQuery.mockReturnValue({ data: mockEstopStatus } as any) mockUseIsFlex.mockReturnValue(false) }) diff --git a/app/src/pages/OnDeviceDisplay/RobotDashboard/index.tsx b/app/src/pages/OnDeviceDisplay/RobotDashboard/index.tsx index f2d861b6a13..a4609200d86 100644 --- a/app/src/pages/OnDeviceDisplay/RobotDashboard/index.tsx +++ b/app/src/pages/OnDeviceDisplay/RobotDashboard/index.tsx @@ -58,7 +58,7 @@ export function RobotDashboard(): JSX.Element { // GET runs query will error with 503 if database is initializing // this should be momentary, and the type of error to come from this endpoint // so, all errors will be mapped to an initializing spinner - if (allRunsQueryError != null) { + if (allRunsQueryError?.code === '503') { contents = } else if (recentRunsOfUniqueProtocols.length > 0) { contents = ( diff --git a/react-api-client/src/runs/useAllRunsQuery.ts b/react-api-client/src/runs/useAllRunsQuery.ts index a1e3665860f..35bc910c67b 100644 --- a/react-api-client/src/runs/useAllRunsQuery.ts +++ b/react-api-client/src/runs/useAllRunsQuery.ts @@ -3,10 +3,11 @@ import { useQuery } from 'react-query' import { useHost } from '../api' import type { UseQueryOptions, UseQueryResult } from 'react-query' +import type { AxiosError } from 'axios' export type UseAllRunsQueryOptions = UseQueryOptions< Runs, - Error, + AxiosError, Runs, Array > @@ -15,7 +16,7 @@ export function useAllRunsQuery( params: GetRunsParams = {}, options: UseAllRunsQueryOptions = {}, hostOverride?: HostConfig | null -): UseQueryResult { +): UseQueryResult { const contextHost = useHost() const host = hostOverride != null ? { ...contextHost, ...hostOverride } : contextHost @@ -25,7 +26,12 @@ export function useAllRunsQuery( } const query = useQuery( queryKey, - () => getRuns(host as HostConfig, params).then(response => response.data), + () => + getRuns(host as HostConfig, params) + .then(response => response.data) + .catch((e: AxiosError) => { + throw e + }), { enabled: host !== null, ...options } ) From 8c55cb17621d97d5b13d6182f37bdd1fd2bd821b Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Wed, 8 Nov 2023 11:24:05 -0500 Subject: [PATCH 29/65] fix(app): update video assets for attach and detach 96-channel pipette (#13929) closes RQA-1863 Update video assets for attach/detach 96-channel pipette due to stroke issue in existing animations --- .../Pipette_Attach_96.webm | Bin 234222 -> 228876 bytes .../Pipette_Detach_96.webm | Bin 220217 -> 209640 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/app/src/assets/videos/pipette-wizard-flows/Pipette_Attach_96.webm b/app/src/assets/videos/pipette-wizard-flows/Pipette_Attach_96.webm index 3f219813708e815f12e9d70bc9038cc0dbde3c14..d3486a97089f426fdc1902b22ba3d7460e4e5ed2 100644 GIT binary patch literal 228876 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�exoV=#q0;XJ6ep!PA}84 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
  • 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 literal 234222 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�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 v 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

    Lp|K9yomil`9I}AcKCuZXW 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

    )(2=DwNNTSU4 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ƟvD*6hCop_r>^ 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 literal 220217 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 D=Fp?C From a14bfe39fc8c08052b986bb46ab57ffa33886bfb Mon Sep 17 00:00:00 2001 From: Andy Sigler Date: Wed, 8 Nov 2023 11:44:02 -0500 Subject: [PATCH 30/65] fix(hardware-testing): Improvements to daily-setup process after more testing (#13899) --- .eslintignore | 1 + hardware-testing/Makefile | 3 + .../hardware_testing/gravimetric/__main__.py | 44 ++++++++++++- .../gravimetric/daily_setup.py | 43 +++++++----- .../hardware_testing/gravimetric/helpers.py | 13 ++-- .../hardware_testing/gravimetric/trial.py | 2 +- .../hardware_testing/tools/plot/index.html | 2 +- .../hardware_testing/tools/plot/index.js | 4 +- .../tools/plot/plotly-2.12.1.min.js | 65 +++++++++++++++++++ .../hardware_testing/tools/plot/server.py | 6 +- 10 files changed, 155 insertions(+), 28 deletions(-) create mode 100644 hardware-testing/hardware_testing/tools/plot/plotly-2.12.1.min.js diff --git a/.eslintignore b/.eslintignore index 27885c64ce6..1444a777aa1 100644 --- a/.eslintignore +++ b/.eslintignore @@ -27,6 +27,7 @@ update-server/** robot-server/** notify-server/** shared-data/python/** +hardware-testing/** # app-testing don't format the json protocols app-testing/files diff --git a/hardware-testing/Makefile b/hardware-testing/Makefile index 1206e24b175..d8af8fcca85 100755 --- a/hardware-testing/Makefile +++ b/hardware-testing/Makefile @@ -130,6 +130,7 @@ test-gravimetric-96: test-gravimetric: -$(MAKE) apply-patches-gravimetric $(python) -m hardware_testing.gravimetric.daily_setup --simulate + $(python) -m hardware_testing.gravimetric.daily_setup --simulate --calibrate $(MAKE) test-gravimetric-single $(MAKE) test-gravimetric-multi $(MAKE) test-gravimetric-96 @@ -181,6 +182,8 @@ ssh $(ssh_helper_ot3) root@$(1) \ mount -o remount,rw / &&\ mv /data/plot/index.html /opt/opentrons-robot-server/hardware_testing/tools/plot &&\ mv /data/plot/index.js /opt/opentrons-robot-server/hardware_testing/tools/plot &&\ +mv /data/plot/plotly-2.12.1.min.js /opt/opentrons-robot-server/hardware_testing/tools/plot &&\ +mv /data/plot/favicon.png /opt/opentrons-robot-server/hardware_testing/tools/plot &&\ rm -rf /data/plot &&\ cleanup || cleanup" endef diff --git a/hardware-testing/hardware_testing/gravimetric/__main__.py b/hardware-testing/hardware_testing/gravimetric/__main__.py index 2d790535445..4c54bb3a71e 100644 --- a/hardware-testing/hardware_testing/gravimetric/__main__.py +++ b/hardware-testing/hardware_testing/gravimetric/__main__.py @@ -2,8 +2,10 @@ from json import load as json_load from pathlib import Path import argparse +from time import time from typing import List, Union, Dict, Optional, Any, Tuple from dataclasses import dataclass +from opentrons.hardware_control.types import OT3Mount from opentrons.protocol_api import ProtocolContext from . import report import subprocess @@ -40,6 +42,7 @@ from .measurement.record import GravimetricRecorder from .measurement import DELAY_FOR_MEASUREMENT from .measurement.scale import Scale +from .measurement.environment import read_environment_data from .trial import TestResources, _change_pipettes from .tips import get_tips from hardware_testing.drivers import asair_sensor @@ -570,6 +573,7 @@ def _main( parser.add_argument( "--mode", type=str, choices=["", "default", "lowVolumeDefault"], default="" ) + parser.add_argument("--pre-heat", action="store_true") args = parser.parse_args() run_args = RunArgs.build_run_args(args) if not run_args.ctx.is_simulating(): @@ -580,14 +584,50 @@ def _main( shell=True, ) sleep(1) + hw = run_args.ctx._core.get_hardware() try: if not run_args.ctx.is_simulating() and not args.photometric: ui.get_user_ready("CLOSE the door, and MOVE AWAY from machine") ui.print_info("homing...") run_args.ctx.home() + + if args.pre_heat: + ui.print_header("PRE-HEAT") + mnt = OT3Mount.LEFT + hw.add_tip(mnt, 1) + hw.prepare_for_aspirate(mnt) + env_data = read_environment_data( + mnt.name.lower(), hw.is_simulator, run_args.environment_sensor + ) + start_temp = env_data.celsius_pipette + temp_limit = min(start_temp + 3.0, 28.0) + max_pre_heat_seconds = 60 * 10 + now = time() + start_time = now + while ( + now - start_time < max_pre_heat_seconds + and env_data.celsius_pipette < temp_limit + ): + ui.print_info( + f"pre-heat {int(now - start_time)} seconds " + f"({max_pre_heat_seconds} limit): " + f"{round(env_data.celsius_pipette, 2)} C " + f"({round(temp_limit, 2)} C limit)" + ) + # NOTE: moving slowly helps make sure full current is sent to coils + hw.aspirate(mnt, rate=0.1) + hw.dispense(mnt, rate=0.1, push_out=0) + env_data = read_environment_data( + mnt.name.lower(), hw.is_simulator, run_args.environment_sensor + ) + if run_args.ctx.is_simulating(): + now += 1 + else: + now = time() + hw.remove_tip(mnt) + for tip, volumes in run_args.volumes: if args.channels == 96 and not run_args.ctx.is_simulating(): - hw = run_args.ctx._core.get_hardware() ui.alert_user_ready(f"prepare the {tip}ul tipracks", hw) _main(args, run_args, tip, volumes) finally: @@ -598,5 +638,5 @@ def _main( _change_pipettes(run_args.ctx, run_args.pipette) if not run_args.ctx.is_simulating(): serial_logger.terminate() - del run_args.ctx._core.get_hardware()._backend.eeprom_driver._gpio + del hw._backend.eeprom_driver._gpio print("done\n\n") diff --git a/hardware-testing/hardware_testing/gravimetric/daily_setup.py b/hardware-testing/hardware_testing/gravimetric/daily_setup.py index 4e3eb26ba0d..bc13dc9d0bf 100644 --- a/hardware-testing/hardware_testing/gravimetric/daily_setup.py +++ b/hardware-testing/hardware_testing/gravimetric/daily_setup.py @@ -102,7 +102,6 @@ def _check_unstable_count(tag: str) -> None: OT3Mount.LEFT, Point(x=MOVE_X_MM, y=MOVE_Y_MM), speed=GANTRY_MAX_SPEED ) _check_unstable_count(tag) - hw.set_status_bar_state(COLOR_STATES["idle"]) # WALKING @@ -114,13 +113,12 @@ def _check_unstable_count(tag: str) -> None: if not hw.is_simulator: ui.get_user_ready("prepare to WALK") tag = "WALKING" + hw.set_status_bar_state(COLOR_STATES["walking"]) with recorder.samples_of_tag(tag): - num_disco_cycles = int(WALKING_SECONDS / 5) - for _ in range(num_disco_cycles): - hw.set_status_bar_state(COLOR_STATES["walking"]) - if not hw.is_simulator: - sleep(5) + if not hw.is_simulator: + sleep(WALKING_SECONDS) _check_unstable_count(tag) + hw.set_status_bar_state(COLOR_STATES["idle"]) def _wait_for_stability( @@ -155,7 +153,10 @@ def _wait_for_stability( def _run( - hw_api: SyncHardwareAPI, recorder: GravimetricRecorder, skip_stability: bool + hw_api: SyncHardwareAPI, + recorder: GravimetricRecorder, + skip_stability: bool, + calibrate: bool = False, ) -> None: ui.print_title("GRAVIMETRIC DAILY SETUP") ui.print_info(f"Scale: {recorder.max_capacity}g (SN:{recorder.serial_number})") @@ -185,13 +186,15 @@ def _calibrate() -> None: _record() hw_api.set_status_bar_state(COLOR_STATES["interact"]) if not hw_api.is_simulator: - ui.get_user_ready("INSTALL Radwag's default weighing pan") + if calibrate: + ui.get_user_ready("INSTALL Radwag's default weighing pan") ui.get_user_ready("REMOVE all weights, vials, and labware from scale") ui.get_user_ready("CLOSE door and step away from fixture") hw_api.set_status_bar_state(COLOR_STATES["idle"]) ui.print_header("TEST STABILITY") if not skip_stability: + print("homing...") hw_api.home() _wait_for_stability(recorder, hw_api, tag="stability") _test_stability(recorder, hw_api) @@ -204,12 +207,13 @@ def _calibrate() -> None: _wait_for_stability(recorder, hw_api, tag="zero") _zero() - ui.print_header("CALIBRATE SCALE") - if hw_api.is_simulator or ui.get_user_answer("calibrate (ADJUST) this scale"): - if not hw_api.is_simulator: - ui.get_user_ready("about to CALIBRATE the scale:") - _wait_for_stability(recorder, hw_api, tag="calibrate") - _calibrate() + if calibrate: + ui.print_header("CALIBRATE SCALE") + if hw_api.is_simulator or ui.get_user_answer("calibrate (ADJUST) this scale"): + if not hw_api.is_simulator: + ui.get_user_ready("about to CALIBRATE the scale:") + _wait_for_stability(recorder, hw_api, tag="calibrate") + _calibrate() ui.print_header("TEST ACCURACY") if hw_api.is_simulator: @@ -242,6 +246,7 @@ def _calibrate() -> None: if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--simulate", action="store_true") + parser.add_argument("--calibrate", action="store_true") parser.add_argument("--skip-stability", action="store_true") args = parser.parse_args() _ctx = helpers.get_api_context( @@ -263,15 +268,19 @@ def _calibrate() -> None: simulate=_hw.is_simulator, ) try: - _run(_hw, _rec, args.skip_stability) + _run(_hw, _rec, args.skip_stability, args.calibrate) _hw.set_status_bar_state(COLOR_STATES["pass"]) ui.print_header("Result: PASS") + if not args.simulate: + ui.get_user_ready("test done") + except KeyboardInterrupt: + ui.print_header("Result: EXITED EARLY") except Exception as e: _hw.set_status_bar_state(COLOR_STATES["fail"]) ui.print_header("Result: FAIL") - raise e - finally: if not args.simulate: ui.get_user_ready("test done") + raise e + finally: _rec.stop() _hw.set_status_bar_state(COLOR_STATES["idle"]) diff --git a/hardware-testing/hardware_testing/gravimetric/helpers.py b/hardware-testing/hardware_testing/gravimetric/helpers.py index cc891234616..7836e069218 100644 --- a/hardware-testing/hardware_testing/gravimetric/helpers.py +++ b/hardware-testing/hardware_testing/gravimetric/helpers.py @@ -1,5 +1,6 @@ """Opentrons helper methods.""" import asyncio +from random import random, randint from types import MethodType from typing import Any, List, Dict, Optional, Tuple from statistics import stdev @@ -320,10 +321,14 @@ def _get_volumes( test_volumes = get_volume_increments( pipette_channels, pipette_volume, tip_volume, mode=mode ) - elif user_volumes and not ctx.is_simulating(): - _inp = input( - f'Enter desired volumes for tip{tip_volume}, comma separated (eg: "10,100,1000") :' - ) + elif user_volumes: + if ctx.is_simulating(): + rand_vols = [round(random() * tip_volume, 1) for _ in range(randint(1, 3))] + _inp = ",".join([str(r) for r in rand_vols]) + else: + _inp = input( + f'Enter desired volumes for tip{tip_volume}, comma separated (eg: "10,100,1000") :' + ) test_volumes = [ float(vol_str) for vol_str in _inp.strip().split(",") if vol_str ] diff --git a/hardware-testing/hardware_testing/gravimetric/trial.py b/hardware-testing/hardware_testing/gravimetric/trial.py index 72d370930c2..9c410b5d1eb 100644 --- a/hardware-testing/hardware_testing/gravimetric/trial.py +++ b/hardware-testing/hardware_testing/gravimetric/trial.py @@ -146,7 +146,7 @@ def build_gravimetric_trials( for trial in range(cfg.trials): d: Optional[float] = None cv: Optional[float] = None - if not cfg.increment: + if not cfg.increment and not cfg.user_volumes: d, cv = config.QC_TEST_MIN_REQUIREMENTS[cfg.pipette_channels][ cfg.pipette_volume ][cfg.tip_volume][volume] diff --git a/hardware-testing/hardware_testing/tools/plot/index.html b/hardware-testing/hardware_testing/tools/plot/index.html index 6b8389645be..124607b6a1b 100644 --- a/hardware-testing/hardware_testing/tools/plot/index.html +++ b/hardware-testing/hardware_testing/tools/plot/index.html @@ -5,7 +5,7 @@ Hardware-Testing: Plot - + plotly-logomark"}}},{}],483:[function(t,e,r){"use strict";r.isLeftAnchor=function(t){return"left"===t.xanchor||"auto"===t.xanchor&&t.x<=1/3},r.isCenterAnchor=function(t){return"center"===t.xanchor||"auto"===t.xanchor&&t.x>1/3&&t.x<2/3},r.isRightAnchor=function(t){return"right"===t.xanchor||"auto"===t.xanchor&&t.x>=2/3},r.isTopAnchor=function(t){return"top"===t.yanchor||"auto"===t.yanchor&&t.y>=2/3},r.isMiddleAnchor=function(t){return"middle"===t.yanchor||"auto"===t.yanchor&&t.y>1/3&&t.y<2/3},r.isBottomAnchor=function(t){return"bottom"===t.yanchor||"auto"===t.yanchor&&t.y<=1/3}},{}],484:[function(t,e,r){"use strict";var n=t("./mod"),i=n.mod,a=n.modHalf,o=Math.PI,s=2*o;function l(t){return Math.abs(t[1]-t[0])>s-1e-14}function c(t,e){return a(e-t,s)}function u(t,e){if(l(e))return!0;var r,n;e[0](n=i(n,s))&&(n+=s);var a=i(t,s),o=a+s;return a>=r&&a<=n||o>=r&&o<=n}function f(t,e,r,n,i,a,c){i=i||0,a=a||0;var u,f,h,p,d,m=l([r,n]);function g(t,e){return[t*Math.cos(e)+i,a-t*Math.sin(e)]}m?(u=0,f=o,h=s):r=i&&t<=a);var i,a},pathArc:function(t,e,r,n,i){return f(null,t,e,r,n,i,0)},pathSector:function(t,e,r,n,i){return f(null,t,e,r,n,i,1)},pathAnnulus:function(t,e,r,n,i,a){return f(t,e,r,n,i,a,1)}}},{"./mod":510}],485:[function(t,e,r){"use strict";var n=Array.isArray,i=ArrayBuffer,a=DataView;function o(t){return i.isView(t)&&!(t instanceof a)}function s(t){return n(t)||o(t)}function l(t,e,r){if(s(t)){if(s(t[0])){for(var n=r,i=0;ii.max?e.set(r):e.set(+t)}},integer:{coerceFunction:function(t,e,r,i){t%1||!n(t)||void 0!==i.min&&ti.max?e.set(r):e.set(+t)}},string:{coerceFunction:function(t,e,r,n){if("string"!=typeof t){var i="number"==typeof t;!0!==n.strict&&i?e.set(String(t)):e.set(r)}else n.noBlank&&!t?e.set(r):e.set(t)}},color:{coerceFunction:function(t,e,r){i(t).isValid()?e.set(t):e.set(r)}},colorlist:{coerceFunction:function(t,e,r){Array.isArray(t)&&t.length&&t.every((function(t){return i(t).isValid()}))?e.set(t):e.set(r)}},colorscale:{coerceFunction:function(t,e,r){e.set(o.get(t,r))}},angle:{coerceFunction:function(t,e,r){"auto"===t?e.set("auto"):n(t)?e.set(f(+t,360)):e.set(r)}},subplotid:{coerceFunction:function(t,e,r,n){var i=n.regex||u(r);"string"==typeof t&&i.test(t)?e.set(t):e.set(r)},validateFunction:function(t,e){var r=e.dflt;return t===r||"string"==typeof t&&!!u(r).test(t)}},flaglist:{coerceFunction:function(t,e,r,n){if("string"==typeof t)if(-1===(n.extras||[]).indexOf(t)){for(var i=t.split("+"),a=0;a=n&&t<=i?t:u}if("string"!=typeof t&&"number"!=typeof t)return u;t=String(t);var c=_(e),v=t.charAt(0);!c||"G"!==v&&"g"!==v||(t=t.substr(1),e="");var w=c&&"chinese"===e.substr(0,7),T=t.match(w?x:y);if(!T)return u;var k=T[1],A=T[3]||"1",M=Number(T[5]||1),S=Number(T[7]||0),E=Number(T[9]||0),L=Number(T[11]||0);if(c){if(2===k.length)return u;var C;k=Number(k);try{var P=g.getComponentMethod("calendars","getCal")(e);if(w){var I="i"===A.charAt(A.length-1);A=parseInt(A,10),C=P.newDate(k,P.toMonthIndex(k,A,I),M)}else C=P.newDate(k,Number(A),M)}catch(t){return u}return C?(C.toJD()-m)*f+S*h+E*p+L*d:u}k=2===k.length?(Number(k)+2e3-b)%100+b:Number(k),A-=1;var O=new Date(Date.UTC(2e3,A,M,S,E));return O.setUTCFullYear(k),O.getUTCMonth()!==A||O.getUTCDate()!==M?u:O.getTime()+L*d},n=r.MIN_MS=r.dateTime2ms("-9999"),i=r.MAX_MS=r.dateTime2ms("9999-12-31 23:59:59.9999"),r.isDateTime=function(t,e){return r.dateTime2ms(t,e)!==u};var T=90*f,k=3*h,A=5*p;function M(t,e,r,n,i){if((e||r||n||i)&&(t+=" "+w(e,2)+":"+w(r,2),(n||i)&&(t+=":"+w(n,2),i))){for(var a=4;i%10==0;)a-=1,i/=10;t+="."+w(i,a)}return t}r.ms2DateTime=function(t,e,r){if("number"!=typeof t||!(t>=n&&t<=i))return u;e||(e=0);var a,o,s,c,y,x,b=Math.floor(10*l(t+.05,1)),w=Math.round(t-b/10);if(_(r)){var S=Math.floor(w/f)+m,E=Math.floor(l(t,f));try{a=g.getComponentMethod("calendars","getCal")(r).fromJD(S).formatDate("yyyy-mm-dd")}catch(t){a=v("G%Y-%m-%d")(new Date(w))}if("-"===a.charAt(0))for(;a.length<11;)a="-0"+a.substr(1);else for(;a.length<10;)a="0"+a;o=e=n+f&&t<=i-f))return u;var e=Math.floor(10*l(t+.05,1)),r=new Date(Math.round(t-e/10));return M(a("%Y-%m-%d")(r),r.getHours(),r.getMinutes(),r.getSeconds(),10*r.getUTCMilliseconds()+e)},r.cleanDate=function(t,e,n){if(t===u)return e;if(r.isJSDate(t)||"number"==typeof t&&isFinite(t)){if(_(n))return s.error("JS Dates and milliseconds are incompatible with world calendars",t),e;if(!(t=r.ms2DateTimeLocal(+t))&&void 0!==e)return e}else if(!r.isDateTime(t,n))return s.error("unrecognized date",t),e;return t};var S=/%\d?f/g,E=/%h/g,L={1:"1",2:"1",3:"2",4:"2"};function C(t,e,r,n){t=t.replace(S,(function(t){var r=Math.min(+t.charAt(1)||6,6);return(e/1e3%1+2).toFixed(r).substr(2).replace(/0+$/,"")||"0"}));var i=new Date(Math.floor(e+.05));if(t=t.replace(E,(function(){return L[r("%q")(i)]})),_(n))try{t=g.getComponentMethod("calendars","worldCalFmt")(t,e,n)}catch(t){return"Invalid"}return r(t)(i)}var P=[59,59.9,59.99,59.999,59.9999];r.formatDate=function(t,e,r,n,i,a){if(i=_(i)&&i,!e)if("y"===r)e=a.year;else if("m"===r)e=a.month;else{if("d"!==r)return function(t,e){var r=l(t+.05,f),n=w(Math.floor(r/h),2)+":"+w(l(Math.floor(r/p),60),2);if("M"!==e){o(e)||(e=0);var i=(100+Math.min(l(t/d,60),P[e])).toFixed(e).substr(1);e>0&&(i=i.replace(/0+$/,"").replace(/[\.]$/,"")),n+=":"+i}return n}(t,r)+"\n"+C(a.dayMonthYear,t,n,i);e=a.dayMonth+"\n"+a.year}return C(e,t,n,i)};var I=3*f;r.incrementMonth=function(t,e,r){r=_(r)&&r;var n=l(t,f);if(t=Math.round(t-n),r)try{var i=Math.round(t/f)+m,a=g.getComponentMethod("calendars","getCal")(r),o=a.fromJD(i);return e%12?a.add(o,e,"m"):a.add(o,e/12,"y"),(o.toJD()-m)*f+n}catch(e){s.error("invalid ms "+t+" in calendar "+r)}var c=new Date(t+I);return c.setUTCMonth(c.getUTCMonth()+e)+n-I},r.findExactDates=function(t,e){for(var r,n,i=0,a=0,s=0,l=0,c=_(e)&&g.getComponentMethod("calendars","getCal")(e),u=0;u0&&t[e+1][0]<0)return e;return null}switch(e="RUS"===s||"FJI"===s?function(t){var e;if(null===c(t))e=t;else for(e=new Array(t.length),i=0;ie?r[n++]=[t[i][0]+360,t[i][1]]:i===e?(r[n++]=t[i],r[n++]=[t[i][0],-90]):r[n++]=t[i];var a=h.tester(r);a.pts.pop(),l.push(a)}:function(t){l.push(h.tester(t))},a.type){case"MultiPolygon":for(r=0;ri&&(i=c,e=l)}else e=r;return o.default(e).geometry.coordinates}(u),n.fIn=t,n.fOut=u,s.push(u)}else c.log(["Location",n.loc,"does not have a valid GeoJSON geometry.","Traces with locationmode *geojson-id* only support","*Polygon* and *MultiPolygon* geometries."].join(" "))}delete i[r]}switch(r.type){case"FeatureCollection":var h=r.features;for(n=0;n100?(clearInterval(a),n("Unexpected error while fetching from "+t)):void i++}),50)}))}for(var o=0;o0&&(r.push(i),i=[])}return i.length>0&&r.push(i),r},r.makeLine=function(t){return 1===t.length?{type:"LineString",coordinates:t[0]}:{type:"MultiLineString",coordinates:t}},r.makePolygon=function(t){if(1===t.length)return{type:"Polygon",coordinates:t};for(var e=new Array(t.length),r=0;r1||m<0||m>1?null:{x:t+l*m,y:e+f*m}}function l(t,e,r,n,i){var a=n*t+i*e;if(a<0)return n*n+i*i;if(a>r){var o=n-t,s=i-e;return o*o+s*s}var l=n*e-i*t;return l*l/r}r.segmentsIntersect=s,r.segmentDistance=function(t,e,r,n,i,a,o,c){if(s(t,e,r,n,i,a,o,c))return 0;var u=r-t,f=n-e,h=o-i,p=c-a,d=u*u+f*f,m=h*h+p*p,g=Math.min(l(u,f,d,i-t,a-e),l(u,f,d,o-t,c-e),l(h,p,m,t-i,e-a),l(h,p,m,r-i,n-a));return Math.sqrt(g)},r.getTextLocation=function(t,e,r,s){if(t===i&&s===a||(n={},i=t,a=s),n[r])return n[r];var l=t.getPointAtLength(o(r-s/2,e)),c=t.getPointAtLength(o(r+s/2,e)),u=Math.atan((c.y-l.y)/(c.x-l.x)),f=t.getPointAtLength(o(r,e)),h={x:(4*f.x+l.x+c.x)/6,y:(4*f.y+l.y+c.y)/6,theta:u};return n[r]=h,h},r.clearLocationCache=function(){i=null},r.getVisibleSegment=function(t,e,r){var n,i,a=e.left,o=e.right,s=e.top,l=e.bottom,c=0,u=t.getTotalLength(),f=u;function h(e){var r=t.getPointAtLength(e);0===e?n=r:e===u&&(i=r);var c=r.xo?r.x-o:0,f=r.yl?r.y-l:0;return Math.sqrt(c*c+f*f)}for(var p=h(c);p;){if((c+=p+r)>f)return;p=h(c)}for(p=h(f);p;){if(c>(f-=p+r))return;p=h(f)}return{min:c,max:f,len:f-c,total:u,isClosed:0===c&&f===u&&Math.abs(n.x-i.x)<.1&&Math.abs(n.y-i.y)<.1}},r.findPointOnPath=function(t,e,r,n){for(var i,a,o,s=(n=n||{}).pathLength||t.getTotalLength(),l=n.tolerance||.001,c=n.iterationLimit||30,u=t.getPointAtLength(0)[r]>t.getPointAtLength(s)[r]?-1:1,f=0,h=0,p=s;f0?p=i:h=i,f++}return a}},{"./mod":510}],499:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("tinycolor2"),a=t("color-normalize"),o=t("../components/colorscale"),s=t("../components/color/attributes").defaultLine,l=t("./array").isArrayOrTypedArray,c=a(s);function u(t,e){var r=t;return r[3]*=e,r}function f(t){if(n(t))return c;var e=a(t);return e.length?e:c}function h(t){return n(t)?t:1}e.exports={formatColor:function(t,e,r){var n,i,s,p,d,m=t.color,g=l(m),v=l(e),y=o.extractOpts(t),x=[];if(n=void 0!==y.colorscale?o.makeColorScaleFuncFromTrace(t):f,i=g?function(t,e){return void 0===t[e]?c:a(n(t[e]))}:f,s=v?function(t,e){return void 0===t[e]?1:h(t[e])}:h,g||v)for(var b=0;b1?(r*t+r*e)/r:t+e,i=String(n).length;if(i>16){var a=String(e).length;if(i>=String(t).length+a){var o=parseFloat(n).toPrecision(12);-1===o.indexOf("e+")&&(n=+o)}}return n}},{}],503:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("d3-time-format").utcFormat,a=t("d3-format").format,o=t("fast-isnumeric"),s=t("../constants/numerical"),l=s.FP_SAFE,c=-l,u=s.BADNUM,f=e.exports={};f.adjustFormat=function(t){return!t||/^\d[.]\df/.test(t)||/[.]\d%/.test(t)?t:"0.f"===t?"~f":/^\d%/.test(t)?"~%":/^\ds/.test(t)?"~s":!/^[~,.0$]/.test(t)&&/[&fps]/.test(t)?"~"+t:t};var h={};f.warnBadFormat=function(t){var e=String(t);h[e]||(h[e]=1,f.warn('encountered bad format: "'+e+'"'))},f.noFormat=function(t){return String(t)},f.numberFormat=function(t){var e;try{e=a(f.adjustFormat(t))}catch(e){return f.warnBadFormat(t),f.noFormat}return e},f.nestedProperty=t("./nested_property"),f.keyedContainer=t("./keyed_container"),f.relativeAttr=t("./relative_attr"),f.isPlainObject=t("./is_plain_object"),f.toLogRange=t("./to_log_range"),f.relinkPrivateKeys=t("./relink_private");var p=t("./array");f.isTypedArray=p.isTypedArray,f.isArrayOrTypedArray=p.isArrayOrTypedArray,f.isArray1D=p.isArray1D,f.ensureArray=p.ensureArray,f.concat=p.concat,f.maxRowLength=p.maxRowLength,f.minRowLength=p.minRowLength;var d=t("./mod");f.mod=d.mod,f.modHalf=d.modHalf;var m=t("./coerce");f.valObjectMeta=m.valObjectMeta,f.coerce=m.coerce,f.coerce2=m.coerce2,f.coerceFont=m.coerceFont,f.coercePattern=m.coercePattern,f.coerceHoverinfo=m.coerceHoverinfo,f.coerceSelectionMarkerOpacity=m.coerceSelectionMarkerOpacity,f.validate=m.validate;var g=t("./dates");f.dateTime2ms=g.dateTime2ms,f.isDateTime=g.isDateTime,f.ms2DateTime=g.ms2DateTime,f.ms2DateTimeLocal=g.ms2DateTimeLocal,f.cleanDate=g.cleanDate,f.isJSDate=g.isJSDate,f.formatDate=g.formatDate,f.incrementMonth=g.incrementMonth,f.dateTick0=g.dateTick0,f.dfltRange=g.dfltRange,f.findExactDates=g.findExactDates,f.MIN_MS=g.MIN_MS,f.MAX_MS=g.MAX_MS;var v=t("./search");f.findBin=v.findBin,f.sorterAsc=v.sorterAsc,f.sorterDes=v.sorterDes,f.distinctVals=v.distinctVals,f.roundUp=v.roundUp,f.sort=v.sort,f.findIndexOfMin=v.findIndexOfMin,f.sortObjectKeys=t("./sort_object_keys");var y=t("./stats");f.aggNums=y.aggNums,f.len=y.len,f.mean=y.mean,f.median=y.median,f.midRange=y.midRange,f.variance=y.variance,f.stdev=y.stdev,f.interp=y.interp;var x=t("./matrix");f.init2dArray=x.init2dArray,f.transposeRagged=x.transposeRagged,f.dot=x.dot,f.translationMatrix=x.translationMatrix,f.rotationMatrix=x.rotationMatrix,f.rotationXYMatrix=x.rotationXYMatrix,f.apply3DTransform=x.apply3DTransform,f.apply2DTransform=x.apply2DTransform,f.apply2DTransform2=x.apply2DTransform2,f.convertCssMatrix=x.convertCssMatrix,f.inverseTransformMatrix=x.inverseTransformMatrix;var b=t("./angles");f.deg2rad=b.deg2rad,f.rad2deg=b.rad2deg,f.angleDelta=b.angleDelta,f.angleDist=b.angleDist,f.isFullCircle=b.isFullCircle,f.isAngleInsideSector=b.isAngleInsideSector,f.isPtInsideSector=b.isPtInsideSector,f.pathArc=b.pathArc,f.pathSector=b.pathSector,f.pathAnnulus=b.pathAnnulus;var _=t("./anchor_utils");f.isLeftAnchor=_.isLeftAnchor,f.isCenterAnchor=_.isCenterAnchor,f.isRightAnchor=_.isRightAnchor,f.isTopAnchor=_.isTopAnchor,f.isMiddleAnchor=_.isMiddleAnchor,f.isBottomAnchor=_.isBottomAnchor;var w=t("./geometry2d");f.segmentsIntersect=w.segmentsIntersect,f.segmentDistance=w.segmentDistance,f.getTextLocation=w.getTextLocation,f.clearLocationCache=w.clearLocationCache,f.getVisibleSegment=w.getVisibleSegment,f.findPointOnPath=w.findPointOnPath;var T=t("./extend");f.extendFlat=T.extendFlat,f.extendDeep=T.extendDeep,f.extendDeepAll=T.extendDeepAll,f.extendDeepNoArrays=T.extendDeepNoArrays;var k=t("./loggers");f.log=k.log,f.warn=k.warn,f.error=k.error;var A=t("./regex");f.counterRegex=A.counter;var M=t("./throttle");f.throttle=M.throttle,f.throttleDone=M.done,f.clearThrottle=M.clear;var S=t("./dom");function E(t){var e={};for(var r in t)for(var n=t[r],i=0;il||t=e)&&(o(t)&&t>=0&&t%1==0)},f.noop=t("./noop"),f.identity=t("./identity"),f.repeat=function(t,e){for(var r=new Array(e),n=0;nr?Math.max(r,Math.min(e,t)):Math.max(e,Math.min(r,t))},f.bBoxIntersect=function(t,e,r){return r=r||0,t.left<=e.right+r&&e.left<=t.right+r&&t.top<=e.bottom+r&&e.top<=t.bottom+r},f.simpleMap=function(t,e,r,n,i){for(var a=t.length,o=new Array(a),s=0;s=Math.pow(2,r)?i>10?(f.warn("randstr failed uniqueness"),l):t(e,r,n,(i||0)+1):l},f.OptionControl=function(t,e){t||(t={}),e||(e="opt");var r={optionList:[],_newoption:function(n){n[e]=t,r[n.name]=n,r.optionList.push(n)}};return r["_"+e]=t,r},f.smooth=function(t,e){if((e=Math.round(e)||0)<2)return t;var r,n,i,a,o=t.length,s=2*o,l=2*e-1,c=new Array(l),u=new Array(o);for(r=0;r=s&&(i-=s*Math.floor(i/s)),i<0?i=-1-i:i>=o&&(i=s-1-i),a+=t[i]*c[n];u[r]=a}return u},f.syncOrAsync=function(t,e,r){var n;function i(){return f.syncOrAsync(t,e,r)}for(;t.length;)if((n=(0,t.splice(0,1)[0])(e))&&n.then)return n.then(i);return r&&r(e)},f.stripTrailingSlash=function(t){return"/"===t.substr(-1)?t.substr(0,t.length-1):t},f.noneOrAll=function(t,e,r){if(t){var n,i=!1,a=!0;for(n=0;n0?e:0}))},f.fillArray=function(t,e,r,n){if(n=n||f.identity,f.isArrayOrTypedArray(t))for(var i=0;i1?i+o[1]:"";if(a&&(o.length>1||s.length>4||r))for(;n.test(s);)s=s.replace(n,"$1"+a+"$2");return s+l},f.TEMPLATE_STRING_REGEX=/%{([^\s%{}:]*)([:|\|][^}]*)?}/g;var z=/^\w*$/;f.templateString=function(t,e){var r={};return t.replace(f.TEMPLATE_STRING_REGEX,(function(t,n){var i;return z.test(n)?i=e[n]:(r[n]=r[n]||f.nestedProperty(e,n).get,i=r[n]()),f.isValidTextValue(i)?i:""}))};var D={max:10,count:0,name:"hovertemplate"};f.hovertemplateString=function(){return B.apply(D,arguments)};var R={max:10,count:0,name:"texttemplate"};f.texttemplateString=function(){return B.apply(R,arguments)};var F=/^[:|\|]/;function B(t,e,r){var n=this,a=arguments;e||(e={});var o={};return t.replace(f.TEMPLATE_STRING_REGEX,(function(t,s,l){var c,u,h,p="_xother"===s||"_yother"===s,d="_xother_"===s||"_yother_"===s,m="xother_"===s||"yother_"===s,g="xother"===s||"yother"===s||p||m||d,v=s;if((p||d)&&(v=v.substring(1)),(m||d)&&(v=v.substring(0,v.length-1)),g){if(void 0===(c=e[v]))return""}else for(h=3;h=48&&o<=57,c=s>=48&&s<=57;if(l&&(n=10*n+o-48),c&&(i=10*i+s-48),!l||!c){if(n!==i)return n-i;if(o!==s)return o-s}}return i-n};var N=2e9;f.seedPseudoRandom=function(){N=2e9},f.pseudoRandom=function(){var t=N;return N=(69069*N+1)%4294967296,Math.abs(N-t)<429496729?f.pseudoRandom():N/4294967296},f.fillText=function(t,e,r){var n=Array.isArray(r)?function(t){r.push(t)}:function(t){r.text=t},i=f.extractOption(t,e,"htx","hovertext");if(f.isValidTextValue(i))return n(i);var a=f.extractOption(t,e,"tx","text");return f.isValidTextValue(a)?n(a):void 0},f.isValidTextValue=function(t){return t||0===t},f.formatPercent=function(t,e){e=e||0;for(var r=(Math.round(100*t*Math.pow(10,e))*Math.pow(.1,e)).toFixed(e)+"%",n=0;n1&&(c=1):c=0,f.strTranslate(i-c*(r+o),a-c*(n+s))+f.strScale(c)+(l?"rotate("+l+(e?"":" "+r+" "+n)+")":"")},f.ensureUniformFontSize=function(t,e){var r=f.extendFlat({},e);return r.size=Math.max(e.size,t._fullLayout.uniformtext.minsize||0),r},f.join2=function(t,e,r){var n=t.length;return n>1?t.slice(0,-1).join(e)+r+t[n-1]:t.join(e)},f.bigFont=function(t){return Math.round(1.2*t)};var j=f.getFirefoxVersion(),U=null!==j&&j<86;f.getPositionFromD3Event=function(){return U?[n.event.layerX,n.event.layerY]:[n.event.offsetX,n.event.offsetY]}},{"../constants/numerical":479,"./anchor_utils":483,"./angles":484,"./array":485,"./clean_number":486,"./clear_responsive":488,"./coerce":489,"./dates":490,"./dom":491,"./extend":493,"./filter_unique":494,"./filter_visible":495,"./geometry2d":498,"./identity":501,"./increment":502,"./is_plain_object":504,"./keyed_container":505,"./localize":506,"./loggers":507,"./make_trace_groups":508,"./matrix":509,"./mod":510,"./nested_property":511,"./noop":512,"./notifier":513,"./preserve_drawing_buffer":517,"./push_unique":518,"./regex":520,"./relative_attr":521,"./relink_private":522,"./search":523,"./sort_object_keys":526,"./stats":527,"./throttle":530,"./to_log_range":531,"@plotly/d3":58,"d3-format":112,"d3-time-format":120,"fast-isnumeric":190}],504:[function(t,e,r){"use strict";e.exports=function(t){return window&&window.process&&window.process.versions?"[object Object]"===Object.prototype.toString.call(t):"[object Object]"===Object.prototype.toString.call(t)&&Object.getPrototypeOf(t).hasOwnProperty("hasOwnProperty")}},{}],505:[function(t,e,r){"use strict";var n=t("./nested_property"),i=/^\w*$/;e.exports=function(t,e,r,a){var o,s,l;r=r||"name",a=a||"value";var c={};e&&e.length?(l=n(t,e),s=l.get()):s=t,e=e||"";var u={};if(s)for(o=0;o2)return c[e]=2|c[e],h.set(t,null);if(f){for(o=e;o1){var e=["LOG:"];for(t=0;t1){var r=[];for(t=0;t"),"long")}},a.warn=function(){var t;if(n.logging>0){var e=["WARN:"];for(t=0;t0){var r=[];for(t=0;t"),"stick")}},a.error=function(){var t;if(n.logging>0){var e=["ERROR:"];for(t=0;t0){var r=[];for(t=0;t"),"stick")}}},{"../plot_api/plot_config":541,"./notifier":513}],508:[function(t,e,r){"use strict";var n=t("@plotly/d3");e.exports=function(t,e,r){var i=t.selectAll("g."+r.replace(/\s/g,".")).data(e,(function(t){return t[0].trace.uid}));i.exit().remove(),i.enter().append("g").attr("class",r),i.order();var a=t.classed("rangeplot")?"nodeRangePlot3":"node3";return i.each((function(t){t[0][a]=n.select(this)})),i}},{"@plotly/d3":58}],509:[function(t,e,r){"use strict";var n=t("gl-mat4");r.init2dArray=function(t,e){for(var r=new Array(t),n=0;ne/2?t-Math.round(t/e)*e:t}}},{}],511:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("./array").isArrayOrTypedArray;function a(t,e){return function(){var r,n,o,s,l,c=t;for(s=0;s/g),l=0;la||c===i||cs)&&(!e||!l(t))}:function(t,e){var l=t[0],c=t[1];if(l===i||la||c===i||cs)return!1;var u,f,h,p,d,m=r.length,g=r[0][0],v=r[0][1],y=0;for(u=1;uMath.max(f,g)||c>Math.max(h,v)))if(cu||Math.abs(n(o,h))>i)return!0;return!1},a.filter=function(t,e){var r=[t[0]],n=0,i=0;function o(o){t.push(o);var s=r.length,l=n;r.splice(i+1);for(var c=l+1;c1&&o(t.pop());return{addPt:o,raw:t,filtered:r}}},{"../constants/numerical":479,"./matrix":509}],516:[function(t,e,r){(function(r){(function(){"use strict";var n=t("./show_no_webgl_msg"),i=t("regl");e.exports=function(t,e,a){var o=t._fullLayout,s=!0;return o._glcanvas.each((function(n){if(n.regl)n.regl.preloadCachedCode(a);else if(!n.pick||o._has("parcoords")){try{n.regl=i({canvas:this,attributes:{antialias:!n.pick,preserveDrawingBuffer:!0},pixelRatio:t._context.plotGlPixelRatio||r.devicePixelRatio,extensions:e||[],cachedCode:a||{}})}catch(t){s=!1}n.regl||(s=!1),s&&this.addEventListener("webglcontextlost",(function(e){t&&t.emit&&t.emit("plotly_webglcontextlost",{event:e,layer:n.key})}),!1)}})),s||n({container:o._glcontainer.node()}),s}}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./show_no_webgl_msg":525,regl:283}],517:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("is-mobile");e.exports=function(t){var e;if("string"!=typeof(e=t&&t.hasOwnProperty("userAgent")?t.userAgent:function(){var t;"undefined"!=typeof navigator&&(t=navigator.userAgent);t&&t.headers&&"string"==typeof t.headers["user-agent"]&&(t=t.headers["user-agent"]);return t}()))return!0;var r=i({ua:{headers:{"user-agent":e}},tablet:!0,featureDetect:!1});if(!r)for(var a=e.split(" "),o=1;o-1;s--){var l=a[s];if("Version/"===l.substr(0,8)){var c=l.substr(8).split(".")[0];if(n(c)&&(c=+c),c>=13)return!0}}}return r}},{"fast-isnumeric":190,"is-mobile":234}],518:[function(t,e,r){"use strict";e.exports=function(t,e){if(e instanceof RegExp){for(var r=e.toString(),n=0;ni.queueLength&&(t.undoQueue.queue.shift(),t.undoQueue.index--))},startSequence:function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!0,t.undoQueue.beginSequence=!0},stopSequence:function(t){t.undoQueue=t.undoQueue||{index:0,queue:[],sequence:!1},t.undoQueue.sequence=!1,t.undoQueue.beginSequence=!1},undo:function(t){var e,r;if(!(void 0===t.undoQueue||isNaN(t.undoQueue.index)||t.undoQueue.index<=0)){for(t.undoQueue.index--,e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;r=t.undoQueue.queue.length)){for(e=t.undoQueue.queue[t.undoQueue.index],t.undoQueue.inSequence=!0,r=0;re}function u(t,e){return t>=e}r.findBin=function(t,e,r){if(n(e.start))return r?Math.ceil((t-e.start)/e.size-1e-9)-1:Math.floor((t-e.start)/e.size+1e-9);var a,o,f=0,h=e.length,p=0,d=h>1?(e[h-1]-e[0])/(h-1):1;for(o=d>=0?r?s:l:r?u:c,t+=1e-9*d*(r?-1:1)*(d>=0?1:-1);f90&&i.log("Long binary search..."),f-1},r.sorterAsc=function(t,e){return t-e},r.sorterDes=function(t,e){return e-t},r.distinctVals=function(t){var e,n=t.slice();for(n.sort(r.sorterAsc),e=n.length-1;e>-1&&n[e]===o;e--);for(var i,a=n[e]-n[0]||1,s=a/(e||1)/1e4,l=[],c=0;c<=e;c++){var u=n[c],f=u-i;void 0===i?(l.push(u),i=u):f>s&&(a=Math.min(a,f),l.push(u),i=u)}return{vals:l,minDiff:a}},r.roundUp=function(t,e,r){for(var n,i=0,a=e.length-1,o=0,s=r?0:1,l=r?1:0,c=r?Math.ceil:Math.floor;i0&&(n=1),r&&n)return t.sort(e)}return n?t:t.reverse()},r.findIndexOfMin=function(t,e){e=e||a;for(var r,n=1/0,i=0;ia.length)&&(o=a.length),n(e)||(e=!1),i(a[0])){for(l=new Array(o),s=0;st.length-1)return t[t.length-1];var r=e%1;return r*t[Math.ceil(e)]+(1-r)*t[Math.floor(e)]}},{"./array":485,"fast-isnumeric":190}],528:[function(t,e,r){"use strict";var n=t("color-normalize");e.exports=function(t){return t?n(t):[0,0,0,1]}},{"color-normalize":89}],529:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../lib"),a=i.strTranslate,o=t("../constants/xmlns_namespaces"),s=t("../constants/alignment").LINE_SPACING,l=/([^$]*)([$]+[^$]*[$]+)([^$]*)/;r.convertToTspans=function(t,e,m){var M=t.text(),S=!t.attr("data-notex")&&e&&e._context.typesetMath&&"undefined"!=typeof MathJax&&M.match(l),C=n.select(t.node().parentNode);if(!C.empty()){var P=t.attr("class")?t.attr("class").split(" ")[0]:"text";return P+="-math",C.selectAll("svg."+P).remove(),C.selectAll("g."+P+"-group").remove(),t.style("display",null).attr({"data-unformatted":M,"data-math":"N"}),S?(e&&e._promises||[]).push(new Promise((function(e){t.style("display","none");var r=parseInt(t.node().style.fontSize,10),o={fontSize:r};!function(t,e,r){var a,o,s,l,h=parseInt((MathJax.version||"").split(".")[0]);if(2!==h&&3!==h)return void i.warn("No MathJax version:",MathJax.version);var p=function(){var r="math-output-"+i.randstr({},64),a=(l=n.select("body").append("div").attr({id:r}).style({visibility:"hidden",position:"absolute","font-size":e.fontSize+"px"}).text(t.replace(c,"\\lt ").replace(u,"\\gt "))).node();return 2===h?MathJax.Hub.Typeset(a):MathJax.typeset([a])},d=function(){var e=l.select(2===h?".MathJax_SVG":".MathJax"),a=!e.empty()&&l.select("svg").node();if(a){var o,s=a.getBoundingClientRect();o=2===h?n.select("body").select("#MathJax_SVG_glyphs"):e.select("defs"),r(e,o,s)}else i.log("There was an error in the tex syntax.",t),r();l.remove()};2===h?MathJax.Hub.Queue((function(){return o=i.extendDeepAll({},MathJax.Hub.config),s=MathJax.Hub.processSectionDelay,void 0!==MathJax.Hub.processSectionDelay&&(MathJax.Hub.processSectionDelay=0),MathJax.Hub.Config({messageStyle:"none",tex2jax:{inlineMath:f},displayAlign:"left"})}),(function(){if("SVG"!==(a=MathJax.Hub.config.menuSettings.renderer))return MathJax.Hub.setRenderer("SVG")}),p,d,(function(){if("SVG"!==a)return MathJax.Hub.setRenderer(a)}),(function(){return void 0!==s&&(MathJax.Hub.processSectionDelay=s),MathJax.Hub.Config(o)})):3===h&&(o=i.extendDeepAll({},MathJax.config),MathJax.config.tex||(MathJax.config.tex={}),MathJax.config.tex.inlineMath=f,"svg"!==(a=MathJax.config.startup.output)&&(MathJax.config.startup.output="svg"),MathJax.startup.defaultReady(),MathJax.startup.promise.then((function(){p(),d(),"svg"!==a&&(MathJax.config.startup.output=a),MathJax.config=o})))}(S[2],o,(function(n,i,o){C.selectAll("svg."+P).remove(),C.selectAll("g."+P+"-group").remove();var s=n&&n.select("svg");if(!s||!s.node())return I(),void e();var l=C.append("g").classed(P+"-group",!0).attr({"pointer-events":"none","data-unformatted":M,"data-math":"Y"});l.node().appendChild(s.node()),i&&i.node()&&s.node().insertBefore(i.node().cloneNode(!0),s.node().firstChild);var c=o.width,u=o.height;s.attr({class:P,height:u,preserveAspectRatio:"xMinYMin meet"}).style({overflow:"visible","pointer-events":"none"});var f=t.node().style.fill||"black",h=s.select("g");h.attr({fill:f,stroke:f});var p=h.node().getBoundingClientRect(),d=p.width,g=p.height;(d>c||g>u)&&(s.style("overflow","hidden"),d=(p=s.node().getBoundingClientRect()).width,g=p.height);var v=+t.attr("x"),y=+t.attr("y"),x=-(r||t.node().getBoundingClientRect().height)/4;if("y"===P[0])l.attr({transform:"rotate("+[-90,v,y]+")"+a(-d/2,x-g/2)});else if("l"===P[0])y=x-g/2;else if("a"===P[0]&&0!==P.indexOf("atitle"))v=0,y=x;else{var b=t.attr("text-anchor");v-=d*("middle"===b?.5:"end"===b?1:0),y=y+x-g/2}s.attr({x:v,y:y}),m&&m.call(t,l),e(l)}))}))):I(),t}function I(){C.empty()||(P=t.attr("class")+"-math",C.select("svg."+P).remove()),t.text("").style("white-space","pre"),function(t,e){e=e.replace(g," ");var r,a=!1,l=[],c=-1;function u(){c++;var e=document.createElementNS(o.svg,"tspan");n.select(e).attr({class:"line",dy:c*s+"em"}),t.appendChild(e),r=e;var i=l;if(l=[{node:e}],i.length>1)for(var a=1;a doesnt match end tag <"+t+">. Pretending it did match.",e),r=l[l.length-1].node}else i.log("Ignoring unexpected end tag .",e)}x.test(e)?u():(r=t,l=[{node:t}]);for(var S=e.split(v),C=0;C|>|>)/g;var f=[["$","$"],["\\(","\\)"]];var h={sup:"font-size:70%",sub:"font-size:70%",b:"font-weight:bold",i:"font-style:italic",a:"cursor:pointer",span:"",em:"font-style:italic;font-weight:bold"},p={sub:"0.3em",sup:"-0.6em"},d={sub:"-0.21em",sup:"0.42em"},m=["http:","https:","mailto:","",void 0,":"],g=r.NEWLINES=/(\r\n?|\n)/g,v=/(<[^<>]*>)/,y=/<(\/?)([^ >]*)(\s+(.*))?>/i,x=//i;r.BR_TAG_ALL=//gi;var b=/(^|[\s"'])style\s*=\s*("([^"]*);?"|'([^']*);?')/i,_=/(^|[\s"'])href\s*=\s*("([^"]*)"|'([^']*)')/i,w=/(^|[\s"'])target\s*=\s*("([^"\s]*)"|'([^'\s]*)')/i,T=/(^|[\s"'])popup\s*=\s*("([\w=,]*)"|'([\w=,]*)')/i;function k(t,e){if(!t)return null;var r=t.match(e),n=r&&(r[3]||r[4]);return n&&E(n)}var A=/(^|;)\s*color:/;r.plainText=function(t,e){for(var r=void 0!==(e=e||{}).len&&-1!==e.len?e.len:1/0,n=void 0!==e.allowedTags?e.allowedTags:["br"],i="...".length,a=t.split(v),o=[],s="",l=0,c=0;ci?o.push(u.substr(0,d-i)+"..."):o.push(u.substr(0,d));break}s=""}}return o.join("")};var M={mu:"\u03bc",amp:"&",lt:"<",gt:">",nbsp:"\xa0",times:"\xd7",plusmn:"\xb1",deg:"\xb0"},S=/&(#\d+|#x[\da-fA-F]+|[a-z]+);/g;function E(t){return t.replace(S,(function(t,e){return("#"===e.charAt(0)?function(t){if(t>1114111)return;var e=String.fromCodePoint;if(e)return e(t);var r=String.fromCharCode;return t<=65535?r(t):r(55232+(t>>10),t%1024+56320)}("x"===e.charAt(1)?parseInt(e.substr(2),16):parseInt(e.substr(1),10)):M[e])||t}))}function L(t){var e=encodeURI(decodeURI(t)),r=document.createElement("a"),n=document.createElement("a");r.href=t,n.href=e;var i=r.protocol,a=n.protocol;return-1!==m.indexOf(i)&&-1!==m.indexOf(a)?e:""}function C(t,e,r){var n,a,o,s=r.horizontalAlign,l=r.verticalAlign||"top",c=t.node().getBoundingClientRect(),u=e.node().getBoundingClientRect();return a="bottom"===l?function(){return c.bottom-n.height}:"middle"===l?function(){return c.top+(c.height-n.height)/2}:function(){return c.top},o="right"===s?function(){return c.right-n.width}:"center"===s?function(){return c.left+(c.width-n.width)/2}:function(){return c.left},function(){n=this.node().getBoundingClientRect();var t=o()-u.left,e=a()-u.top,s=r.gd||{};if(r.gd){s._fullLayout._calcInverseTransform(s);var l=i.apply3DTransform(s._fullLayout._invTransform)(t,e);t=l[0],e=l[1]}return this.style({top:e+"px",left:t+"px","z-index":1e3}),this}}r.convertEntities=E,r.sanitizeHTML=function(t){t=t.replace(g," ");for(var e=document.createElement("p"),r=e,i=[],a=t.split(v),o=0;oa.ts+e?l():a.timer=setTimeout((function(){l(),a.timer=null}),e)},r.done=function(t){var e=n[t];return e&&e.timer?new Promise((function(t){var r=e.onDone;e.onDone=function(){r&&r(),t(),e.onDone=null}})):Promise.resolve()},r.clear=function(t){if(t)i(n[t]),delete n[t];else for(var e in n)r.clear(e)}},{}],531:[function(t,e,r){"use strict";var n=t("fast-isnumeric");e.exports=function(t,e){if(t>0)return Math.log(t)/Math.LN10;var r=Math.log(Math.min(e[0],e[1]))/Math.LN10;return n(r)||(r=Math.log(Math.max(e[0],e[1]))/Math.LN10-6),r}},{"fast-isnumeric":190}],532:[function(t,e,r){"use strict";var n=e.exports={},i=t("../plots/geo/constants").locationmodeToLayer,a=t("topojson-client").feature;n.getTopojsonName=function(t){return[t.scope.replace(/ /g,"-"),"_",t.resolution.toString(),"m"].join("")},n.getTopojsonPath=function(t,e){return t+e+".json"},n.getTopojsonFeatures=function(t,e){var r=i[t.locationmode],n=e.objects[r];return a(e,n).features}},{"../plots/geo/constants":587,"topojson-client":315}],533:[function(t,e,r){"use strict";e.exports={moduleType:"locale",name:"en-US",dictionary:{"Click to enter Colorscale title":"Click to enter Colorscale title"},format:{date:"%m/%d/%Y"}}},{}],534:[function(t,e,r){"use strict";e.exports={moduleType:"locale",name:"en",dictionary:{"Click to enter Colorscale title":"Click to enter Colourscale title"},format:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],periods:["AM","PM"],dateTime:"%a %b %e %X %Y",date:"%d/%m/%Y",time:"%H:%M:%S",decimal:".",thousands:",",grouping:[3],currency:["$",""],year:"%Y",month:"%b %Y",dayMonth:"%b %-d",dayMonthYear:"%b %-d, %Y"}}},{}],535:[function(t,e,r){"use strict";var n=t("../registry");e.exports=function(t){for(var e,r,i=n.layoutArrayContainers,a=n.layoutArrayRegexes,o=t.split("[")[0],s=0;s0&&o.log("Clearing previous rejected promises from queue."),t._promises=[]},r.cleanLayout=function(t){var e,n;t||(t={}),t.xaxis1&&(t.xaxis||(t.xaxis=t.xaxis1),delete t.xaxis1),t.yaxis1&&(t.yaxis||(t.yaxis=t.yaxis1),delete t.yaxis1),t.scene1&&(t.scene||(t.scene=t.scene1),delete t.scene1);var a=(s.subplotsRegistry.cartesian||{}).attrRegex,l=(s.subplotsRegistry.polar||{}).attrRegex,f=(s.subplotsRegistry.ternary||{}).attrRegex,h=(s.subplotsRegistry.gl3d||{}).attrRegex,m=Object.keys(t);for(e=0;e3?(O.x=1.02,O.xanchor="left"):O.x<-2&&(O.x=-.02,O.xanchor="right"),O.y>3?(O.y=1.02,O.yanchor="bottom"):O.y<-2&&(O.y=-.02,O.yanchor="top")),d(t),"rotate"===t.dragmode&&(t.dragmode="orbit"),c.clean(t),t.template&&t.template.layout&&r.cleanLayout(t.template.layout),t},r.cleanData=function(t){for(var e=0;e0)return t.substr(0,e)}r.hasParent=function(t,e){for(var r=b(e);r;){if(r in t)return!0;r=b(r)}return!1};var _=["x","y","z"];r.clearAxisTypes=function(t,e,r){for(var n=0;n1&&a.warn("Full array edits are incompatible with other edits",f);var y=r[""][""];if(c(y))e.set(null);else{if(!Array.isArray(y))return a.warn("Unrecognized full array edit value",f,y),!0;e.set(y)}return!m&&(h(g,v),p(t),!0)}var x,b,_,w,T,k,A,M,S=Object.keys(r).map(Number).sort(o),E=e.get(),L=E||[],C=u(v,f).get(),P=[],I=-1,O=L.length;for(x=0;xL.length-(A?0:1))a.warn("index out of range",f,_);else if(void 0!==k)T.length>1&&a.warn("Insertion & removal are incompatible with edits to the same index.",f,_),c(k)?P.push(_):A?("add"===k&&(k={}),L.splice(_,0,k),C&&C.splice(_,0,{})):a.warn("Unrecognized full object edit value",f,_,k),-1===I&&(I=_);else for(b=0;b=0;x--)L.splice(P[x],1),C&&C.splice(P[x],1);if(L.length?E||e.set(L):e.set(null),m)return!1;if(h(g,v),d!==i){var z;if(-1===I)z=S;else{for(O=Math.max(L.length,O),z=[],x=0;x=I);x++)z.push(_);for(x=I;x=t.data.length||i<-t.data.length)throw new Error(r+" must be valid indices for gd.data.");if(e.indexOf(i,n+1)>-1||i>=0&&e.indexOf(-t.data.length+i)>-1||i<0&&e.indexOf(t.data.length+i)>-1)throw new Error("each index in "+r+" must be unique.")}}function I(t,e,r){if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if(void 0===e)throw new Error("currentIndices is a required argument.");if(Array.isArray(e)||(e=[e]),P(t,e,"currentIndices"),void 0===r||Array.isArray(r)||(r=[r]),void 0!==r&&P(t,r,"newIndices"),void 0!==r&&e.length!==r.length)throw new Error("current and new indices must be of equal length.")}function O(t,e,r,n,a){!function(t,e,r,n){var i=o.isPlainObject(n);if(!Array.isArray(t.data))throw new Error("gd.data must be an array");if(!o.isPlainObject(e))throw new Error("update must be a key:value object");if(void 0===r)throw new Error("indices must be an integer or array of integers");for(var a in P(t,r,"indices"),e){if(!Array.isArray(e[a])||e[a].length!==r.length)throw new Error("attribute "+a+" must be an array of length equal to indices array length");if(i&&(!(a in n)||!Array.isArray(n[a])||n[a].length!==e[a].length))throw new Error("when maxPoints is set as a key:value object it must contain a 1:1 corrispondence with the keys and number of traces in the update object")}}(t,e,r,n);for(var l=function(t,e,r,n){var a,l,c,u,f,h=o.isPlainObject(n),p=[];for(var d in Array.isArray(r)||(r=[r]),r=C(r,t.data.length-1),e)for(var m=0;m-1&&-1===r.indexOf("grouptitlefont")?l(r,r.replace("titlefont","title.font")):r.indexOf("titleposition")>-1?l(r,r.replace("titleposition","title.position")):r.indexOf("titleside")>-1?l(r,r.replace("titleside","title.side")):r.indexOf("titleoffset")>-1&&l(r,r.replace("titleoffset","title.offset")):l(r,r.replace("title","title.text"));function l(e,r){t[r]=t[e],delete t[e]}}function U(t,e,r){t=o.getGraphDiv(t),_.clearPromiseQueue(t);var n={};if("string"==typeof e)n[e]=r;else{if(!o.isPlainObject(e))return o.warn("Relayout fail.",e,r),Promise.reject();n=o.extendFlat({},e)}Object.keys(n).length&&(t.changed=!0);var i=W(t,n),a=i.flags;a.calc&&(t.calcdata=void 0);var s=[h.previousPromises];a.layoutReplot?s.push(w.layoutReplot):Object.keys(n).length&&(V(t,a,i)||h.supplyDefaults(t),a.legend&&s.push(w.doLegend),a.layoutstyle&&s.push(w.layoutStyles),a.axrange&&H(s,i.rangesAltered),a.ticks&&s.push(w.doTicksRelayout),a.modebar&&s.push(w.doModeBar),a.camera&&s.push(w.doCamera),a.colorbars&&s.push(w.doColorBars),s.push(M)),s.push(h.rehover,h.redrag),c.add(t,U,[t,i.undoit],U,[t,i.redoit]);var l=o.syncOrAsync(s,t);return l&&l.then||(l=Promise.resolve(t)),l.then((function(){return t.emit("plotly_relayout",i.eventData),t}))}function V(t,e,r){var n=t._fullLayout;if(!e.axrange)return!1;for(var i in e)if("axrange"!==i&&e[i])return!1;for(var a in r.rangesAltered){var o=p.id2name(a),s=t.layout[o],l=n[o];if(l.autorange=s.autorange,s.range&&(l.range=s.range.slice()),l.cleanRange(),l._matchGroup)for(var c in l._matchGroup)if(c!==a){var u=n[p.id2name(c)];u.autorange=l.autorange,u.range=l.range.slice(),u._input.range=l.range.slice()}}return!0}function H(t,e){var r=e?function(t){var r=[],n=!0;for(var i in e){var a=p.getFromId(t,i);if(r.push(i),-1!==(a.ticklabelposition||"").indexOf("inside")&&a._anchorAxis&&r.push(a._anchorAxis._id),a._matchGroup)for(var o in a._matchGroup)e[o]||r.push(o);a.automargin&&(n=!1)}return p.draw(t,r,{skipTitle:n})}:function(t){return p.draw(t,"redraw")};t.push(y,w.doAutoRangeAndConstraints,r,w.drawData,w.finalDraw)}var q=/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/,G=/^[xyz]axis[0-9]*\.autorange$/,Y=/^[xyz]axis[0-9]*\.domain(\[[0|1]\])?$/;function W(t,e){var r,n,i,a=t.layout,l=t._fullLayout,c=l._guiEditing,h=F(l._preGUI,c),d=Object.keys(e),m=p.list(t),g=o.extendDeepAll({},e),v={};for(j(e),d=Object.keys(e),n=0;n0&&"string"!=typeof O.parts[D];)D--;var B=O.parts[D],N=O.parts[D-1]+"."+B,U=O.parts.slice(0,D).join("."),V=s(t.layout,U).get(),H=s(l,U).get(),W=O.get();if(void 0!==z){M[I]=z,S[I]="reverse"===B?z:R(W);var Z=f.getLayoutValObject(l,O.parts);if(Z&&Z.impliedEdits&&null!==z)for(var J in Z.impliedEdits)E(o.relativeAttr(I,J),Z.impliedEdits[J]);if(-1!==["width","height"].indexOf(I))if(z){E("autosize",null);var K="height"===I?"width":"height";E(K,l[K])}else l[I]=t._initialAutoSize[I];else if("autosize"===I)E("width",z?null:l.width),E("height",z?null:l.height);else if(N.match(q))P(N),s(l,U+"._inputRange").set(null);else if(N.match(G)){P(N),s(l,U+"._inputRange").set(null);var Q=s(l,U).get();Q._inputDomain&&(Q._input.domain=Q._inputDomain.slice())}else N.match(Y)&&s(l,U+"._inputDomain").set(null);if("type"===B){L=V;var $="linear"===H.type&&"log"===z,tt="log"===H.type&&"linear"===z;if($||tt){if(L&&L.range)if(H.autorange)$&&(L.range=L.range[1]>L.range[0]?[1,2]:[2,1]);else{var et=L.range[0],rt=L.range[1];$?(et<=0&&rt<=0&&E(U+".autorange",!0),et<=0?et=rt/1e6:rt<=0&&(rt=et/1e6),E(U+".range[0]",Math.log(et)/Math.LN10),E(U+".range[1]",Math.log(rt)/Math.LN10)):(E(U+".range[0]",Math.pow(10,et)),E(U+".range[1]",Math.pow(10,rt)))}else E(U+".autorange",!0);Array.isArray(l._subplots.polar)&&l._subplots.polar.length&&l[O.parts[0]]&&"radialaxis"===O.parts[1]&&delete l[O.parts[0]]._subplot.viewInitial["radialaxis.range"],u.getComponentMethod("annotations","convertCoords")(t,H,z,E),u.getComponentMethod("images","convertCoords")(t,H,z,E)}else E(U+".autorange",!0),E(U+".range",null);s(l,U+"._inputRange").set(null)}else if(B.match(k)){var nt=s(l,I).get(),it=(z||{}).type;it&&"-"!==it||(it="linear"),u.getComponentMethod("annotations","convertCoords")(t,nt,it,E),u.getComponentMethod("images","convertCoords")(t,nt,it,E)}var at=b.containerArrayMatch(I);if(at){r=at.array,n=at.index;var ot=at.property,st=Z||{editType:"calc"};""!==n&&""===ot&&(b.isAddVal(z)?S[I]=null:b.isRemoveVal(z)?S[I]=(s(a,r).get()||[])[n]:o.warn("unrecognized full object value",e)),T.update(A,st),v[r]||(v[r]={});var lt=v[r][n];lt||(lt=v[r][n]={}),lt[ot]=z,delete e[I]}else"reverse"===B?(V.range?V.range.reverse():(E(U+".autorange",!0),V.range=[1,0]),H.autorange?A.calc=!0:A.plot=!0):("dragmode"===I&&(!1===z&&!1!==W||!1!==z&&!1===W)||l._has("scatter-like")&&l._has("regl")&&"dragmode"===I&&("lasso"===z||"select"===z)&&"lasso"!==W&&"select"!==W||l._has("gl2d")?A.plot=!0:Z?T.update(A,Z):A.calc=!0,O.set(z))}}for(r in v){b.applyContainerArrayChanges(t,h(a,r),v[r],A,h)||(A.plot=!0)}for(var ct in C){var ut=(L=p.getFromId(t,ct))&&L._constraintGroup;if(ut)for(var ft in A.calc=!0,ut)C[ft]||(p.getFromId(t,ft)._constraintShrinkable=!0)}return(X(t)||e.height||e.width)&&(A.plot=!0),(A.plot||A.calc)&&(A.layoutReplot=!0),{flags:A,rangesAltered:C,undoit:S,redoit:M,eventData:g}}function X(t){var e=t._fullLayout,r=e.width,n=e.height;return t.layout.autosize&&h.plotAutoSize(t,t.layout,e),e.width!==r||e.height!==n}function Z(t,e,n,i){t=o.getGraphDiv(t),_.clearPromiseQueue(t),o.isPlainObject(e)||(e={}),o.isPlainObject(n)||(n={}),Object.keys(e).length&&(t.changed=!0),Object.keys(n).length&&(t.changed=!0);var a=_.coerceTraceIndices(t,i),s=N(t,o.extendFlat({},e),a),l=s.flags,u=W(t,o.extendFlat({},n)),f=u.flags;(l.calc||f.calc)&&(t.calcdata=void 0),l.clearAxisTypes&&_.clearAxisTypes(t,a,n);var p=[];f.layoutReplot?p.push(w.layoutReplot):l.fullReplot?p.push(r._doPlot):(p.push(h.previousPromises),V(t,f,u)||h.supplyDefaults(t),l.style&&p.push(w.doTraceStyle),(l.colorbars||f.colorbars)&&p.push(w.doColorBars),f.legend&&p.push(w.doLegend),f.layoutstyle&&p.push(w.layoutStyles),f.axrange&&H(p,u.rangesAltered),f.ticks&&p.push(w.doTicksRelayout),f.modebar&&p.push(w.doModeBar),f.camera&&p.push(w.doCamera),p.push(M)),p.push(h.rehover,h.redrag),c.add(t,Z,[t,s.undoit,u.undoit,s.traces],Z,[t,s.redoit,u.redoit,s.traces]);var d=o.syncOrAsync(p,t);return d&&d.then||(d=Promise.resolve(t)),d.then((function(){return t.emit("plotly_update",{data:s.eventData,layout:u.eventData}),t}))}function J(t){return function(e){e._fullLayout._guiEditing=!0;var r=t.apply(null,arguments);return e._fullLayout._guiEditing=!1,r}}var K=[{pattern:/^hiddenlabels/,attr:"legend.uirevision"},{pattern:/^((x|y)axis\d*)\.((auto)?range|title\.text)/},{pattern:/axis\d*\.showspikes$/,attr:"modebar.uirevision"},{pattern:/(hover|drag)mode$/,attr:"modebar.uirevision"},{pattern:/^(scene\d*)\.camera/},{pattern:/^(geo\d*)\.(projection|center|fitbounds)/},{pattern:/^(ternary\d*\.[abc]axis)\.(min|title\.text)$/},{pattern:/^(polar\d*\.radialaxis)\.((auto)?range|angle|title\.text)/},{pattern:/^(polar\d*\.angularaxis)\.rotation/},{pattern:/^(mapbox\d*)\.(center|zoom|bearing|pitch)/},{pattern:/^legend\.(x|y)$/,attr:"editrevision"},{pattern:/^(shapes|annotations)/,attr:"editrevision"},{pattern:/^title\.text$/,attr:"editrevision"}],Q=[{pattern:/^selectedpoints$/,attr:"selectionrevision"},{pattern:/(^|value\.)visible$/,attr:"legend.uirevision"},{pattern:/^dimensions\[\d+\]\.constraintrange/},{pattern:/^node\.(x|y|groups)/},{pattern:/^level$/},{pattern:/(^|value\.)name$/},{pattern:/colorbar\.title\.text$/},{pattern:/colorbar\.(x|y)$/,attr:"editrevision"}];function $(t,e){for(var r=0;r1;)if(n.pop(),void 0!==(r=s(e,n.join(".")+".uirevision").get()))return r;return e.uirevision}function et(t,e){for(var r=0;r=i.length?i[0]:i[t]:i}function l(t){return Array.isArray(a)?t>=a.length?a[0]:a[t]:a}function c(t,e){var r=0;return function(){if(t&&++r===e)return t()}}return void 0===n._frameWaitingCnt&&(n._frameWaitingCnt=0),new Promise((function(a,u){function f(){n._currentFrame&&n._currentFrame.onComplete&&n._currentFrame.onComplete();var e=n._currentFrame=n._frameQueue.shift();if(e){var r=e.name?e.name.toString():null;t._fullLayout._currentFrame=r,n._lastFrameAt=Date.now(),n._timeToNext=e.frameOpts.duration,h.transition(t,e.frame.data,e.frame.layout,_.coerceTraceIndices(t,e.frame.traces),e.frameOpts,e.transitionOpts).then((function(){e.onComplete&&e.onComplete()})),t.emit("plotly_animatingframe",{name:r,frame:e.frame,animation:{frame:e.frameOpts,transition:e.transitionOpts}})}else t.emit("plotly_animated"),window.cancelAnimationFrame(n._animationRaf),n._animationRaf=null}function p(){t.emit("plotly_animating"),n._lastFrameAt=-1/0,n._timeToNext=0,n._runningTransitions=0,n._currentFrame=null;var e=function(){n._animationRaf=window.requestAnimationFrame(e),Date.now()-n._lastFrameAt>n._timeToNext&&f()};e()}var d,m,g=0;function v(t){return Array.isArray(i)?g>=i.length?t.transitionOpts=i[g]:t.transitionOpts=i[0]:t.transitionOpts=i,g++,t}var y=[],x=null==e,b=Array.isArray(e);if(!x&&!b&&o.isPlainObject(e))y.push({type:"object",data:v(o.extendFlat({},e))});else if(x||-1!==["string","number"].indexOf(typeof e))for(d=0;d0&&kk)&&A.push(m);y=A}}y.length>0?function(e){if(0!==e.length){for(var i=0;i=0;n--)if(o.isPlainObject(e[n])){var m=e[n].name,g=(u[m]||d[m]||{}).name,v=e[n].name,y=u[g]||d[g];g&&v&&"number"==typeof v&&y&&A<5&&(A++,o.warn('addFrames: overwriting frame "'+(u[g]||d[g]).name+'" with a frame whose name of type "number" also equates to "'+g+'". This is valid but may potentially lead to unexpected behavior since all plotly.js frame names are stored internally as strings.'),5===A&&o.warn("addFrames: This API call has yielded too many of these warnings. For the rest of this call, further warnings about numeric frame names will be suppressed.")),d[m]={name:m},p.push({frame:h.supplyFrameDefaults(e[n]),index:r&&void 0!==r[n]&&null!==r[n]?r[n]:f+n})}p.sort((function(t,e){return t.index>e.index?-1:t.index=0;n--){if("number"==typeof(i=p[n].frame).name&&o.warn("Warning: addFrames accepts frames with numeric names, but the numbers areimplicitly cast to strings"),!i.name)for(;u[i.name="frame "+t._transitionData._counter++];);if(u[i.name]){for(a=0;a=0;r--)n=e[r],a.push({type:"delete",index:n}),s.unshift({type:"insert",index:n,value:i[n]});var l=h.modifyFrames,u=h.modifyFrames,f=[t,s],p=[t,a];return c&&c.add(t,l,f,u,p),h.modifyFrames(t,a)},r.addTraces=function t(e,n,i){e=o.getGraphDiv(e);var a,s,l=[],u=r.deleteTraces,f=t,h=[e,l],p=[e,n];for(function(t,e,r){var n,i;if(!Array.isArray(t.data))throw new Error("gd.data must be an array.");if(void 0===e)throw new Error("traces must be defined.");for(Array.isArray(e)||(e=[e]),n=0;n=0&&r=0&&r=a.length)return!1;if(2===t.dimensions){if(r++,e.length===r)return t;var o=e[r];if(!y(o))return!1;t=a[i][o]}else t=a[i]}else t=a}}return t}function y(t){return t===Math.round(t)&&t>=0}function x(){var t,e,r={};for(t in f(r,o),n.subplotsRegistry){if((e=n.subplotsRegistry[t]).layoutAttributes)if(Array.isArray(e.attr))for(var i=0;i=l.length)return!1;i=(r=(n.transformsRegistry[l[c].type]||{}).attributes)&&r[e[2]],s=3}else{var u=t._module;if(u||(u=(n.modules[t.type||a.type.dflt]||{})._module),!u)return!1;if(!(i=(r=u.attributes)&&r[o])){var f=u.basePlotModule;f&&f.attributes&&(i=f.attributes[o])}i||(i=a[o])}return v(i,e,s)},r.getLayoutValObject=function(t,e){return v(function(t,e){var r,i,a,s,l=t._basePlotModules;if(l){var c;for(r=0;r=i&&(r._input||{})._templateitemname;o&&(a=i);var s,l=e+"["+a+"]";function c(){s={},o&&(s[l]={},s[l].templateitemname=o)}function u(t,e){o?n.nestedProperty(s[l],t).set(e):s[l+"."+t]=e}function f(){var t=s;return c(),t}return c(),{modifyBase:function(t,e){s[t]=e},modifyItem:u,getUpdateObj:f,applyUpdate:function(e,r){e&&u(e,r);var i=f();for(var a in i)n.nestedProperty(t,a).set(i[a])}}}},{"../lib":503,"../plots/attributes":550}],544:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../registry"),a=t("../plots/plots"),o=t("../lib"),s=t("../lib/clear_gl_canvases"),l=t("../components/color"),c=t("../components/drawing"),u=t("../components/titles"),f=t("../components/modebar"),h=t("../plots/cartesian/axes"),p=t("../constants/alignment"),d=t("../plots/cartesian/constraints"),m=d.enforce,g=d.clean,v=t("../plots/cartesian/autorange").doAutoRange;function y(t,e,r){for(var n=0;n=t[1]||i[1]<=t[0])&&(a[0]e[0]))return!0}return!1}function x(t){var e,i,s,u,d,m,g=t._fullLayout,v=g._size,x=v.p,_=h.list(t,"",!0);if(g._paperdiv.style({width:t._context.responsive&&g.autosize&&!t._context._hasZeroWidth&&!t.layout.width?"100%":g.width+"px",height:t._context.responsive&&g.autosize&&!t._context._hasZeroHeight&&!t.layout.height?"100%":g.height+"px"}).selectAll(".main-svg").call(c.setSize,g.width,g.height),t._context.setBackground(t,g.paper_bgcolor),r.drawMainTitle(t),f.manage(t),!g._has("cartesian"))return a.previousPromises(t);function T(t,e,r){var n=t._lw/2;return"x"===t._id.charAt(0)?e?"top"===r?e._offset-x-n:e._offset+e._length+x+n:v.t+v.h*(1-(t.position||0))+n%1:e?"right"===r?e._offset+e._length+x+n:e._offset-x-n:v.l+v.w*(t.position||0)+n%1}for(e=0;e<_.length;e++){var k=(u=_[e])._anchorAxis;u._linepositions={},u._lw=c.crispRound(t,u.linewidth,1),u._mainLinePosition=T(u,k,u.side),u._mainMirrorPosition=u.mirror&&k?T(u,k,p.OPPOSITE_SIDE[u.side]):null}var A=[],M=[],S=[],E=1===l.opacity(g.paper_bgcolor)&&1===l.opacity(g.plot_bgcolor)&&g.paper_bgcolor===g.plot_bgcolor;for(i in g._plots)if((s=g._plots[i]).mainplot)s.bg&&s.bg.remove(),s.bg=void 0;else{var L=s.xaxis.domain,C=s.yaxis.domain,P=s.plotgroup;if(y(L,C,S)){var I=P.node(),O=s.bg=o.ensureSingle(P,"rect","bg");I.insertBefore(O.node(),I.childNodes[0]),M.push(i)}else P.select("rect.bg").remove(),S.push([L,C]),E||(A.push(i),M.push(i))}var z,D,R,F,B,N,j,U,V,H,q,G,Y,W=g._bgLayer.selectAll(".bg").data(A);for(W.enter().append("rect").classed("bg",!0),W.exit().remove(),W.each((function(t){g._plots[t].bg=n.select(this)})),e=0;eT?u.push({code:"unused",traceType:y,templateCount:w,dataCount:T}):T>w&&u.push({code:"reused",traceType:y,templateCount:w,dataCount:T})}}else u.push({code:"data"});if(function t(e,r){for(var n in e)if("_"!==n.charAt(0)){var a=e[n],o=m(e,n,r);i(a)?(Array.isArray(e)&&!1===a._template&&a.templateitemname&&u.push({code:"missing",path:o,templateitemname:a.templateitemname}),t(a,o)):Array.isArray(a)&&g(a)&&t(a,o)}}({data:p,layout:h},""),u.length)return u.map(v)}},{"../lib":503,"../plots/attributes":550,"../plots/plots":619,"./plot_config":541,"./plot_schema":542,"./plot_template":543}],546:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("./plot_api"),a=t("../plots/plots"),o=t("../lib"),s=t("../snapshot/helpers"),l=t("../snapshot/tosvg"),c=t("../snapshot/svgtoimg"),u=t("../version").version,f={format:{valType:"enumerated",values:["png","jpeg","webp","svg","full-json"],dflt:"png"},width:{valType:"number",min:1},height:{valType:"number",min:1},scale:{valType:"number",min:0,dflt:1},setBackground:{valType:"any",dflt:!1},imageDataOnly:{valType:"boolean",dflt:!1}};e.exports=function(t,e){var r,h,p,d;function m(t){return!(t in e)||o.validate(e[t],f[t])}if(e=e||{},o.isPlainObject(t)?(r=t.data||[],h=t.layout||{},p=t.config||{},d={}):(t=o.getGraphDiv(t),r=o.extendDeep([],t.data),h=o.extendDeep({},t.layout),p=t._context,d=t._fullLayout||{}),!m("width")&&null!==e.width||!m("height")&&null!==e.height)throw new Error("Height and width should be pixel values.");if(!m("format"))throw new Error("Export format is not "+o.join2(f.format.values,", "," or ")+".");var g={};function v(t,r){return o.coerce(e,g,f,t,r)}var y=v("format"),x=v("width"),b=v("height"),_=v("scale"),w=v("setBackground"),T=v("imageDataOnly"),k=document.createElement("div");k.style.position="absolute",k.style.left="-5000px",document.body.appendChild(k);var A=o.extendFlat({},h);x?A.width=x:null===e.width&&n(d.width)&&(A.width=d.width),b?A.height=b:null===e.height&&n(d.height)&&(A.height=d.height);var M=o.extendFlat({},p,{_exportedPlot:!0,staticPlot:!0,setBackground:w}),S=s.getRedrawFunc(k);function E(){return new Promise((function(t){setTimeout(t,s.getDelay(k._fullLayout))}))}function L(){return new Promise((function(t,e){var r=l(k,y,_),n=k._fullLayout.width,f=k._fullLayout.height;function h(){i.purge(k),document.body.removeChild(k)}if("full-json"===y){var p=a.graphJson(k,!1,"keepdata","object",!0,!0);return p.version=u,p=JSON.stringify(p),h(),t(T?p:s.encodeJSON(p))}if(h(),"svg"===y)return t(T?r:s.encodeSVG(r));var d=document.createElement("canvas");d.id=o.randstr(),c({format:y,width:n,height:f,scale:_,canvas:d,svg:r,promise:!0}).then(t).catch(e)}))}return new Promise((function(t,e){i.newPlot(k,r,A,M).then(S).then(E).then(L).then((function(e){t(function(t){return T?t.replace(s.IMAGE_URL_PREFIX,""):t}(e))})).catch((function(t){e(t)}))}))}},{"../lib":503,"../plots/plots":619,"../snapshot/helpers":642,"../snapshot/svgtoimg":644,"../snapshot/tosvg":646,"../version":1123,"./plot_api":540,"fast-isnumeric":190}],547:[function(t,e,r){"use strict";var n=t("../lib"),i=t("../plots/plots"),a=t("./plot_schema"),o=t("./plot_config").dfltConfig,s=n.isPlainObject,l=Array.isArray,c=n.isArrayOrTypedArray;function u(t,e,r,i,a,o){o=o||[];for(var f=Object.keys(t),h=0;hx.length&&i.push(d("unused",a,v.concat(x.length)));var A,M,S,E,L,C=x.length,P=Array.isArray(k);if(P&&(C=Math.min(C,k.length)),2===b.dimensions)for(M=0;Mx[M].length&&i.push(d("unused",a,v.concat(M,x[M].length)));var I=x[M].length;for(A=0;A<(P?Math.min(I,k[M].length):I);A++)S=P?k[M][A]:k,E=y[M][A],L=x[M][A],n.validate(E,S)?L!==E&&L!==+E&&i.push(d("dynamic",a,v.concat(M,A),E,L)):i.push(d("value",a,v.concat(M,A),E))}else i.push(d("array",a,v.concat(M),y[M]));else for(M=0;M1&&p.push(d("object","layout"))),i.supplyDefaults(m);for(var g=m._fullData,v=r.length,y=0;y0&&Math.round(f)===f))return{vals:i};c=f}for(var h=e.calendar,p="start"===l,d="end"===l,m=t[r+"period0"],g=a(m,h)||0,v=[],y=[],x=[],b=i.length,_=0;_A;)k=o(k,-c,h);for(;k<=A;)k=o(k,c,h);T=o(k,-c,h)}else{for(k=g+(w=Math.round((A-g)/u))*u;k>A;)k-=u;for(;k<=A;)k+=u;T=k-u}v[_]=p?T:d?k:(T+k)/2,y[_]=T,x[_]=k}return{vals:v,starts:y,ends:x}}},{"../../constants/numerical":479,"../../lib":503,"fast-isnumeric":190}],552:[function(t,e,r){"use strict";e.exports={xaxis:{valType:"subplotid",dflt:"x",editType:"calc+clearAxisTypes"},yaxis:{valType:"subplotid",dflt:"y",editType:"calc+clearAxisTypes"}}},{}],553:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("fast-isnumeric"),a=t("../../lib"),o=t("../../constants/numerical").FP_SAFE,s=t("../../registry"),l=t("../../components/drawing"),c=t("./axis_ids"),u=c.getFromId,f=c.isLinked;function h(t,e){var r,n,i=[],o=t._fullLayout,s=d(o,e,0),l=d(o,e,1),c=m(t,e),u=c.min,f=c.max;if(0===u.length||0===f.length)return a.simpleMap(e.range,e.r2l);var h=u[0].val,g=f[0].val;for(r=1;r0&&((T=E-s(x)-l(b))>L?k/T>C&&(_=x,w=b,C=k/T):k/E>C&&(_={val:x.val,nopad:1},w={val:b.val,nopad:1},C=k/E));if(h===g){var P=h-1,I=h+1;if(M)if(0===h)i=[0,1];else{var O=(h>0?f:u).reduce((function(t,e){return Math.max(t,l(e))}),0),z=h/(1-Math.min(.5,O/E));i=h>0?[0,z]:[z,0]}else i=S?[Math.max(0,P),Math.max(1,I)]:[P,I]}else M?(_.val>=0&&(_={val:0,nopad:1}),w.val<=0&&(w={val:0,nopad:1})):S&&(_.val-C*s(_)<0&&(_={val:0,nopad:1}),w.val<=0&&(w={val:1,nopad:1})),C=(w.val-_.val-p(e,x.val,b.val))/(E-s(_)-l(w)),i=[_.val-C*s(_),w.val+C*l(w)];return v&&i.reverse(),a.simpleMap(i,e.l2r||Number)}function p(t,e,r){var n=0;if(t.rangebreaks)for(var i=t.locateBreaks(e,r),a=0;a0?r.ppadplus:r.ppadminus)||r.ppad||0),S=A((t._m>0?r.ppadminus:r.ppadplus)||r.ppad||0),E=A(r.vpadplus||r.vpad),L=A(r.vpadminus||r.vpad);if(!T){if(h=1/0,p=-1/0,w)for(n=0;n0&&(h=a),a>p&&a-o&&(h=a),a>p&&a=I;n--)P(n);return{min:d,max:m,opts:r}},concatExtremes:m};function m(t,e,r){var n,i,a,o=e._id,s=t._fullData,l=t._fullLayout,c=[],f=[];function h(t,e){for(n=0;n=r&&(c.extrapad||!o)){s=!1;break}i(e,c.val)&&c.pad<=r&&(o||!c.extrapad)&&(t.splice(l,1),l--)}if(s){var u=a&&0===e;t.push({val:e,pad:u?0:r,extrapad:!u&&o})}}function x(t){return i(t)&&Math.abs(t)=e}},{"../../components/drawing":388,"../../constants/numerical":479,"../../lib":503,"../../registry":638,"./axis_ids":558,"@plotly/d3":58,"fast-isnumeric":190}],554:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("fast-isnumeric"),a=t("../../plots/plots"),o=t("../../registry"),s=t("../../lib"),l=s.strTranslate,c=t("../../lib/svg_text_utils"),u=t("../../components/titles"),f=t("../../components/color"),h=t("../../components/drawing"),p=t("./layout_attributes"),d=t("./clean_ticks"),m=t("../../constants/numerical"),g=m.ONEMAXYEAR,v=m.ONEAVGYEAR,y=m.ONEMINYEAR,x=m.ONEMAXQUARTER,b=m.ONEAVGQUARTER,_=m.ONEMINQUARTER,w=m.ONEMAXMONTH,T=m.ONEAVGMONTH,k=m.ONEMINMONTH,A=m.ONEWEEK,M=m.ONEDAY,S=M/2,E=m.ONEHOUR,L=m.ONEMIN,C=m.ONESEC,P=m.MINUS_SIGN,I=m.BADNUM,O={K:"zeroline"},z={K:"gridline",L:"path"},D={K:"minor-gridline",L:"path"},R={K:"tick",L:"path"},F={K:"tick",L:"text"},B=t("../../constants/alignment"),N=B.MID_SHIFT,j=B.CAP_SHIFT,U=B.LINE_SPACING,V=B.OPPOSITE_SIDE,H=e.exports={};H.setConvert=t("./set_convert");var q=t("./axis_autotype"),G=t("./axis_ids"),Y=G.idSort,W=G.isLinked;H.id2name=G.id2name,H.name2id=G.name2id,H.cleanId=G.cleanId,H.list=G.list,H.listIds=G.listIds,H.getFromId=G.getFromId,H.getFromTrace=G.getFromTrace;var X=t("./autorange");H.getAutoRange=X.getAutoRange,H.findExtremes=X.findExtremes;function Z(t){var e=1e-4*(t[1]-t[0]);return[t[0]-e,t[1]+e]}H.coerceRef=function(t,e,r,n,i,a){var o=n.charAt(n.length-1),l=r._fullLayout._subplots[o+"axis"],c=n+"ref",u={};return i||(i=l[0]||("string"==typeof a?a:a[0])),a||(a=i),l=l.concat(l.map((function(t){return t+" domain"}))),u[c]={valType:"enumerated",values:l.concat(a?"string"==typeof a?[a]:a:[]),dflt:i},s.coerce(t,e,u,c)},H.getRefType=function(t){return void 0===t?t:"paper"===t?"paper":"pixel"===t?"pixel":/( domain)$/.test(t)?"domain":"range"},H.coercePosition=function(t,e,r,n,i,a){var o,l;if("range"!==H.getRefType(n))o=s.ensureNumber,l=r(i,a);else{var c=H.getFromId(e,n);l=r(i,a=c.fraction2r(a)),o=c.cleanPos}t[i]=o(l)},H.cleanPosition=function(t,e,r){return("paper"===r||"pixel"===r?s.ensureNumber:H.getFromId(e,r).cleanPos)(t)},H.redrawComponents=function(t,e){e=e||H.listIds(t);var r=t._fullLayout;function n(n,i,a,s){for(var l=o.getComponentMethod(n,i),c={},u=0;ur&&f2e-6||((r-t._forceTick0)/t._minDtick%1+1.000001)%1>2e-6)&&(t._minDtick=0)):t._minDtick=0},H.saveRangeInitial=function(t,e){for(var r=H.list(t,"",!0),n=!1,i=0;i.3*h||u(n)||u(a))){var p=r.dtick/2;t+=t+p.8){var o=Number(r.substr(1));a.exactYears>.8&&o%12==0?t=H.tickIncrement(t,"M6","reverse")+1.5*M:a.exactMonths>.8?t=H.tickIncrement(t,"M1","reverse")+15.5*M:t-=S;var l=H.tickIncrement(t,r);if(l<=n)return l}return t}(y,t,v,c,a)),g=y,0;g<=u;)g=H.tickIncrement(g,v,!1,a);return{start:e.c2r(y,0,a),end:e.c2r(g,0,a),size:v,_dataSpan:u-c}},H.prepMinorTicks=function(t,e,r){if(!e.minor.dtick){delete t.dtick;var n,a=e.dtick&&i(e._tmin);if(a){var o=H.tickIncrement(e._tmin,e.dtick,!0);n=[e._tmin,.99*o+.01*e._tmin]}else{var l=s.simpleMap(e.range,e.r2l);n=[l[0],.8*l[0]+.2*l[1]]}if(t.range=s.simpleMap(n,e.l2r),t._isMinor=!0,H.prepTicks(t,r),a){var c=i(e.dtick),u=i(t.dtick),f=c?e.dtick:+e.dtick.substring(1),h=u?t.dtick:+t.dtick.substring(1);c&&u?$(f,h)?f===2*A&&h===2*M&&(t.dtick=A):f===2*A&&h===3*M?t.dtick=A:f!==A||(e._input.minor||{}).nticks?tt(f/h,2.5)?t.dtick=f/2:t.dtick=f:t.dtick=M:"M"===String(e.dtick).charAt(0)?u?t.dtick="M1":$(f,h)?f>=12&&2===h&&(t.dtick="M3"):t.dtick=e.dtick:"L"===String(t.dtick).charAt(0)?"L"===String(e.dtick).charAt(0)?$(f,h)||(t.dtick=tt(f/h,2.5)?e.dtick/2:e.dtick):t.dtick="D1":"D2"===t.dtick&&+e.dtick>1&&(t.dtick=1)}t.range=e.range}void 0===e.minor._tick0Init&&(t.tick0=e.tick0)},H.prepTicks=function(t,e){var r=s.simpleMap(t.range,t.r2l,void 0,void 0,e);if("auto"===t.tickmode||!t.dtick){var n,a=t.nticks;a||("category"===t.type||"multicategory"===t.type?(n=t.tickfont?s.bigFont(t.tickfont.size||12):15,a=t._length/n):(n="y"===t._id.charAt(0)?40:80,a=s.constrain(t._length/n,4,9)+1),"radialaxis"===t._name&&(a*=2)),t.minor&&"array"!==t.minor.tickmode||"array"===t.tickmode&&(a*=100),t._roughDTick=Math.abs(r[1]-r[0])/a,H.autoTicks(t,t._roughDTick),t._minDtick>0&&t.dtick<2*t._minDtick&&(t.dtick=t._minDtick,t.tick0=t.l2r(t._forceTick0))}"period"===t.ticklabelmode&&function(t){var e;function r(){return!(i(t.dtick)||"M"!==t.dtick.charAt(0))}var n=r(),a=H.getTickFormat(t);if(a){var o=t._dtickInit!==t.dtick;/%[fLQsSMX]/.test(a)||(/%[HI]/.test(a)?(e=E,o&&!n&&t.dtick=(O?0:1);z--){var D=!z;z?(t._dtickInit=t.dtick,t._tick0Init=t.tick0):(t.minor._dtickInit=t.minor.dtick,t.minor._tick0Init=t.minor.tick0);var R=z?t:s.extendFlat({},t,t.minor);if(D?H.prepMinorTicks(R,t,e):H.prepTicks(R,e),"array"!==R.tickmode){var F=Z(u),B=F[0],N=F[1],j=i(R.dtick),U="log"===a&&!(j||"L"===R.dtick.charAt(0)),V=H.tickFirst(R,e);if(z){if(t._tmin=V,V=N:W<=N;W=H.tickIncrement(W,X,f,o)){if(z&&q++,R.rangebreaks&&!f){if(W=p)break}if(C.length>d||W===Y)break;Y=W;var J={value:W};z?(U&&W!==(0|W)&&(J.simpleLabel=!0),l>1&&q%l&&(J.skipLabel=!0),C.push(J)):(J.minor=!0,P.push(J))}}else z?(C=[],m=rt(t)):(P=[],L=rt(t))}if(O&&!("inside"===t.minor.ticks&&"outside"===t.ticks||"outside"===t.minor.ticks&&"inside"===t.ticks)){for(var K=C.map((function(t){return t.value})),Q=[],$=0;$0?(a=n-1,o=n):(a=n,o=n);var s,l=t[a].value,c=t[o].value,u=Math.abs(c-l),f=r||u,h=0;f>=y?h=u>=y&&u<=g?u:v:r===b&&f>=_?h=u>=_&&u<=x?u:b:f>=k?h=u>=k&&u<=w?u:T:r===A&&f>=A?h=A:f>=M?h=M:r===S&&f>=S?h=S:r===E&&f>=E&&(h=E),h>=u&&(h=u,s=!0);var p=i+h;if(e.rangebreaks&&h>0){for(var d=0,m=0;m<84;m++){var L=(m+.5)/84;e.maskBreaks(i*(1-L)+L*p)!==I&&d++}(h*=d/84)||(t[n].drop=!0),s&&u>A&&(h=u)}(h>0||0===n)&&(t[n].periodX=i+h/2)}}(C,t,t._definedDelta),t.rangebreaks){var at="y"===t._id.charAt(0),ot=1;"auto"===t.tickmode&&(ot=t.tickfont?t.tickfont.size:12);var st=NaN;for(r=C.length-1;r>-1;r--)if(C[r].drop)C.splice(r,1);else{C[r].value=Ct(C[r].value,t);var lt=t.c2p(C[r].value);(at?st>lt-ot:stp||utp&&(ct.periodX=p),ut10||"01-01"!==n.substr(5)?t._tickround="d":t._tickround=+e.substr(1)%12==0?"y":"m";else if(e>=M&&a<=10||e>=15*M)t._tickround="d";else if(e>=L&&a<=16||e>=E)t._tickround="M";else if(e>=C&&a<=19||e>=L)t._tickround="S";else{var o=t.l2r(r+e).replace(/^-/,"").length;t._tickround=Math.max(a,o)-20,t._tickround<0&&(t._tickround=4)}}else if(i(e)||"L"===e.charAt(0)){var s=t.range.map(t.r2d||Number);i(e)||(e=Number(e.substr(1))),t._tickround=2-Math.floor(Math.log(e)/Math.LN10+.01);var l=Math.max(Math.abs(s[0]),Math.abs(s[1])),c=Math.floor(Math.log(l)/Math.LN10+.01),u=void 0===t.minexponent?3:t.minexponent;Math.abs(c)>u&&(dt(t.exponentformat)&&!mt(c)?t._tickexponent=3*Math.round((c-1)/3):t._tickexponent=c)}else t._tickround=null}function ht(t,e,r){var n=t.tickfont||{};return{x:e,dx:0,dy:0,text:r||"",fontSize:n.size,font:n.family,fontColor:n.color}}H.autoTicks=function(t,e,r){var n;function a(t){return Math.pow(t,Math.floor(Math.log(e)/Math.LN10))}if("date"===t.type){t.tick0=s.dateTick0(t.calendar,0);var o=2*e;if(o>v)e/=v,n=a(10),t.dtick="M"+12*ut(e,n,nt);else if(o>T)e/=T,t.dtick="M"+ut(e,1,it);else if(o>M){if(t.dtick=ut(e,M,t._hasDayOfWeekBreaks?[1,2,7,14]:ot),!r){var l=H.getTickFormat(t),c="period"===t.ticklabelmode;c&&(t._rawTick0=t.tick0),/%[uVW]/.test(l)?t.tick0=s.dateTick0(t.calendar,2):t.tick0=s.dateTick0(t.calendar,1),c&&(t._dowTick0=t.tick0)}}else o>E?t.dtick=ut(e,E,it):o>L?t.dtick=ut(e,L,at):o>C?t.dtick=ut(e,C,at):(n=a(10),t.dtick=ut(e,n,nt))}else if("log"===t.type){t.tick0=0;var u=s.simpleMap(t.range,t.r2l);if(t._isMinor&&(e*=1.5),e>.7)t.dtick=Math.ceil(e);else if(Math.abs(u[1]-u[0])<1){var f=1.5*Math.abs((u[1]-u[0])/e);e=Math.abs(Math.pow(10,u[1])-Math.pow(10,u[0]))/f,n=a(10),t.dtick="L"+ut(e,n,nt)}else t.dtick=e>.3?"D2":"D1"}else"category"===t.type||"multicategory"===t.type?(t.tick0=0,t.dtick=Math.ceil(Math.max(e,1))):Lt(t)?(t.tick0=0,n=1,t.dtick=ut(e,n,ct)):(t.tick0=0,n=a(10),t.dtick=ut(e,n,nt));if(0===t.dtick&&(t.dtick=1),!i(t.dtick)&&"string"!=typeof t.dtick){var h=t.dtick;throw t.dtick=1,"ax.dtick error: "+String(h)}},H.tickIncrement=function(t,e,r,a){var o=r?-1:1;if(i(e))return s.increment(t,o*e);var l=e.charAt(0),c=o*Number(e.substr(1));if("M"===l)return s.incrementMonth(t,c,a);if("L"===l)return Math.log(Math.pow(10,t)+c)/Math.LN10;if("D"===l){var u="D2"===e?lt:st,f=t+.01*o,h=s.roundUp(s.mod(f,1),u,r);return Math.floor(f)+Math.log(n.round(Math.pow(10,h),1))/Math.LN10}throw"unrecognized dtick "+String(e)},H.tickFirst=function(t,e){var r=t.r2l||Number,a=s.simpleMap(t.range,r,void 0,void 0,e),o=a[1] ")}else t._prevDateHead=l,c+="
    "+l;e.text=c}(t,o,r,c):"log"===u?function(t,e,r,n,a){var o=t.dtick,l=e.x,c=t.tickformat,u="string"==typeof o&&o.charAt(0);"never"===a&&(a="");n&&"L"!==u&&(o="L3",u="L");if(c||"L"===u)e.text=gt(Math.pow(10,l),t,a,n);else if(i(o)||"D"===u&&s.mod(l+.01,1)<.1){var f=Math.round(l),h=Math.abs(f),p=t.exponentformat;"power"===p||dt(p)&&mt(f)?(e.text=0===f?1:1===f?"10":"10"+(f>1?"":P)+h+"",e.fontSize*=1.25):("e"===p||"E"===p)&&h>2?e.text="1"+p+(f>0?"+":P)+h:(e.text=gt(Math.pow(10,l),t,"","fakehover"),"D1"===o&&"y"===t._id.charAt(0)&&(e.dy-=e.fontSize/6))}else{if("D"!==u)throw"unrecognized dtick "+String(o);e.text=String(Math.round(Math.pow(10,s.mod(l,1)))),e.fontSize*=.75}if("D1"===t.dtick){var d=String(e.text).charAt(0);"0"!==d&&"1"!==d||("y"===t._id.charAt(0)?e.dx-=e.fontSize/4:(e.dy+=e.fontSize/2,e.dx+=(t.range[1]>t.range[0]?1:-1)*e.fontSize*(l<0?.5:.25)))}}(t,o,0,c,m):"category"===u?function(t,e){var r=t._categories[Math.round(e.x)];void 0===r&&(r="");e.text=String(r)}(t,o):"multicategory"===u?function(t,e,r){var n=Math.round(e.x),i=t._categories[n]||[],a=void 0===i[1]?"":String(i[1]),o=void 0===i[0]?"":String(i[0]);r?e.text=o+" - "+a:(e.text=a,e.text2=o)}(t,o,r):Lt(t)?function(t,e,r,n,i){if("radians"!==t.thetaunit||r)e.text=gt(e.x,t,i,n);else{var a=e.x/180;if(0===a)e.text="0";else{var o=function(t){function e(t,e){return Math.abs(t-e)<=1e-6}var r=function(t){for(var r=1;!e(Math.round(t*r)/r,t);)r*=10;return r}(t),n=t*r,i=Math.abs(function t(r,n){return e(n,0)?r:t(n,r%n)}(n,r));return[Math.round(n/i),Math.round(r/i)]}(a);if(o[1]>=100)e.text=gt(s.deg2rad(e.x),t,i,n);else{var l=e.x<0;1===o[1]?1===o[0]?e.text="\u03c0":e.text=o[0]+"\u03c0":e.text=["",o[0],"","\u2044","",o[1],"","\u03c0"].join(""),l&&(e.text=P+e.text)}}}}(t,o,r,c,m):function(t,e,r,n,i){"never"===i?i="":"all"===t.showexponent&&Math.abs(e.x/t.dtick)<1e-6&&(i="hide");e.text=gt(e.x,t,i,n)}(t,o,0,c,m),n||(t.tickprefix&&!d(t.showtickprefix)&&(o.text=t.tickprefix+o.text),t.ticksuffix&&!d(t.showticksuffix)&&(o.text+=t.ticksuffix)),"boundaries"===t.tickson||t.showdividers){var g=function(e){var r=t.l2p(e);return r>=0&&r<=t._length?e:null};o.xbnd=[g(o.x-.5),g(o.x+t.dtick-.5)]}return o},H.hoverLabelText=function(t,e,r){r&&(t=s.extendFlat({},t,{hoverformat:r}));var n=Array.isArray(e)?e[0]:e,i=Array.isArray(e)?e[1]:void 0;if(void 0!==i&&i!==n)return H.hoverLabelText(t,n,r)+" - "+H.hoverLabelText(t,i,r);var a="log"===t.type&&n<=0,o=H.tickText(t,t.c2l(a?-n:n),"hover").text;return a?0===n?"0":P+o:o};var pt=["f","p","n","\u03bc","m","","k","M","G","T"];function dt(t){return"SI"===t||"B"===t}function mt(t){return t>14||t<-15}function gt(t,e,r,n){var a=t<0,o=e._tickround,l=r||e.exponentformat||"B",c=e._tickexponent,u=H.getTickFormat(e),f=e.separatethousands;if(n){var h={exponentformat:l,minexponent:e.minexponent,dtick:"none"===e.showexponent?e.dtick:i(t)&&Math.abs(t)||1,range:"none"===e.showexponent?e.range.map(e.r2d):[0,t||1]};ft(h),o=(Number(h._tickround)||0)+4,c=h._tickexponent,e.hoverformat&&(u=e.hoverformat)}if(u)return e._numFormat(u)(t).replace(/-/g,P);var p,d=Math.pow(10,-o)/2;if("none"===l&&(c=0),(t=Math.abs(t))"+p+"":"B"===l&&9===c?t+="B":dt(l)&&(t+=pt[c/3+5]));return a?P+t:t}function vt(t,e){for(var r=[],n={},i=0;i1&&r=i.min&&t=0,a=u(t,e[1])<=0;return(r||i)&&(n||a)}if(t.tickformatstops&&t.tickformatstops.length>0)switch(t.type){case"date":case"linear":for(e=0;e=o(i)))){r=n;break}break;case"log":for(e=0;e0?r.bottom-f:0,h)))),e.automargin){n={x:0,y:0,r:0,l:0,t:0,b:0};var p=[0,1];if("x"===d){if("b"===l?n[l]=e._depth:(n[l]=e._depth=Math.max(r.width>0?f-r.top:0,h),p.reverse()),r.width>0){var g=r.right-(e._offset+e._length);g>0&&(n.xr=1,n.r=g);var v=e._offset-r.left;v>0&&(n.xl=0,n.l=v)}}else if("l"===l?n[l]=e._depth=Math.max(r.height>0?f-r.left:0,h):(n[l]=e._depth=Math.max(r.height>0?r.right-f:0,h),p.reverse()),r.height>0){var y=r.bottom-(e._offset+e._length);y>0&&(n.yb=0,n.b=y);var x=e._offset-r.top;x>0&&(n.yt=1,n.t=x)}n[m]="free"===e.anchor?e.position:e._anchorAxis.domain[p[0]],e.title.text!==c._dfltTitle[d]&&(n[l]+=bt(e)+(e.title.standoff||0)),e.mirror&&"free"!==e.anchor&&((i={x:0,y:0,r:0,l:0,t:0,b:0})[u]=e.linewidth,e.mirror&&!0!==e.mirror&&(i[u]+=h),!0===e.mirror||"ticks"===e.mirror?i[m]=e._anchorAxis.domain[p[1]]:"all"!==e.mirror&&"allticks"!==e.mirror||(i[m]=[e._counterDomainMin,e._counterDomainMax][p[1]]))}it&&(s=o.getComponentMethod("rangeslider","autoMarginOpts")(t,e)),a.autoMargin(t,Tt(e),n),a.autoMargin(t,kt(e),i),a.autoMargin(t,At(e),s)})),r.skipTitle||it&&"bottom"===e.side||rt.push((function(){return function(t,e){var r,n=t._fullLayout,i=e._id,a=i.charAt(0),o=e.title.font.size;if(e.title.hasOwnProperty("standoff"))r=e._depth+e.title.standoff+bt(e);else{var s=Pt(e);if("multicategory"===e.type)r=e._depth;else{var l=1.5*o;s&&(l=.5*o,"outside"===e.ticks&&(l+=e.ticklen)),r=10+l+(e.linewidth?e.linewidth-1:0)}s||(r+="x"===a?"top"===e.side?o*(e.showticklabels?1:0):o*(e.showticklabels?1.5:.5):"right"===e.side?o*(e.showticklabels?1:.5):o*(e.showticklabels?.5:0))}var c,f,p,d,m=H.getPxPosition(t,e);"x"===a?(f=e._offset+e._length/2,p="top"===e.side?m-r:m+r):(p=e._offset+e._length/2,f="right"===e.side?m+r:m-r,c={rotate:"-90",offset:0});if("multicategory"!==e.type){var g=e._selections[e._id+"tick"];if(d={selection:g,side:e.side},g&&g.node()&&g.node().parentNode){var v=h.getTranslate(g.node().parentNode);d.offsetLeft=v.x,d.offsetTop=v.y}e.title.hasOwnProperty("standoff")&&(d.pad=0)}return u.draw(t,i+"title",{propContainer:e,propName:e._name+".title.text",placeholder:n._dfltTitle[a],avoid:d,transform:c,attributes:{x:f,y:p,"text-anchor":"middle"}})}(t,e)})),s.syncOrAsync(rt)}}function at(t){var r=p+(t||"tick");return w[r]||(w[r]=function(t,e){var r,n,i,a;t._selections[e].size()?(r=1/0,n=-1/0,i=1/0,a=-1/0,t._selections[e].each((function(){var t=wt(this),e=h.bBox(t.node().parentNode);r=Math.min(r,e.top),n=Math.max(n,e.bottom),i=Math.min(i,e.left),a=Math.max(a,e.right)}))):(r=0,n=0,i=0,a=0);return{top:r,bottom:n,left:i,right:a,height:n-r,width:a-i}}(e,r)),w[r]}},H.getTickSigns=function(t,e){var r=t._id.charAt(0),n={x:"top",y:"right"}[r],i=t.side===n?1:-1,a=[-1,1,i,-i];return"inside"!==(e?(t.minor||{}).ticks:t.ticks)==("x"===r)&&(a=a.map((function(t){return-t}))),t.side&&a.push({l:-1,t:-1,r:1,b:1}[t.side.charAt(0)]),a},H.makeTransTickFn=function(t){return"x"===t._id.charAt(0)?function(e){return l(t._offset+t.l2p(e.x),0)}:function(e){return l(0,t._offset+t.l2p(e.x))}},H.makeTransTickLabelFn=function(t){var e=function(t){var e=t.ticklabelposition||"",r=function(t){return-1!==e.indexOf(t)},n=r("top"),i=r("left"),a=r("right"),o=r("bottom"),s=r("inside"),l=o||i||n||a;if(!l&&!s)return[0,0];var c=t.side,u=l?(t.tickwidth||0)/2:0,f=3,h=t.tickfont?t.tickfont.size:12;(o||n)&&(u+=h*j,f+=(t.linewidth||0)/2);(i||a)&&(u+=(t.linewidth||0)/2,f+=3);s&&"top"===c&&(f-=h*(1-j));(i||n)&&(u=-u);"bottom"!==c&&"right"!==c||(f=-f);return[l?u:0,s?f:0]}(t),r=e[0],n=e[1];return"x"===t._id.charAt(0)?function(e){return l(r+t._offset+t.l2p(yt(e)),n)}:function(e){return l(n,r+t._offset+t.l2p(yt(e)))}},H.makeTickPath=function(t,e,r,n){n||(n={});var i=n.minor;if(i&&!t.minor)return"";var a=void 0!==n.len?n.len:i?t.minor.ticklen:t.ticklen,o=t._id.charAt(0),s=(t.linewidth||1)/2;return"x"===o?"M0,"+(e+s*r)+"v"+a*r:"M"+(e+s*r)+",0h"+a*r},H.makeLabelFns=function(t,e,r){var n=t.ticklabelposition||"",a=function(t){return-1!==n.indexOf(t)},o=a("top"),l=a("left"),c=a("right"),u=a("bottom")||l||o||c,f=a("inside"),h="inside"===n&&"inside"===t.ticks||!f&&"outside"===t.ticks&&"boundaries"!==t.tickson,p=0,d=0,m=h?t.ticklen:0;if(f?m*=-1:u&&(m=0),h&&(p+=m,r)){var g=s.deg2rad(r);p=m*Math.cos(g)+1,d=m*Math.sin(g)}t.showticklabels&&(h||t.showline)&&(p+=.2*t.tickfont.size);var v,y,x,b,_,w={labelStandoff:p+=(t.linewidth||1)/2*(f?-1:1),labelShift:d},T=0,k=t.side,A=t._id.charAt(0),M=t.tickangle;if("x"===A)b=(_=!f&&"bottom"===k||f&&"top"===k)?1:-1,f&&(b*=-1),v=d*b,y=e+p*b,x=_?1:-.2,90===Math.abs(M)&&(f?x+=N:x=-90===M&&"bottom"===k?j:90===M&&"top"===k?N:.5,T=N/2*(M/90)),w.xFn=function(t){return t.dx+v+T*t.fontSize},w.yFn=function(t){return t.dy+y+t.fontSize*x},w.anchorFn=function(t,e){if(u){if(l)return"end";if(c)return"start"}return i(e)&&0!==e&&180!==e?e*b<0!==f?"end":"start":"middle"},w.heightFn=function(e,r,n){return r<-60||r>60?-.5*n:"top"===t.side!==f?-n:0};else if("y"===A){if(b=(_=!f&&"left"===k||f&&"right"===k)?1:-1,f&&(b*=-1),v=p,y=d*b,x=0,f||90!==Math.abs(M)||(x=-90===M&&"left"===k||90===M&&"right"===k?j:.5),f){var S=i(M)?+M:0;if(0!==S){var E=s.deg2rad(S);T=Math.abs(Math.sin(E))*j*b,x=0}}w.xFn=function(t){return t.dx+e-(v+t.fontSize*x)*b+T*t.fontSize},w.yFn=function(t){return t.dy+y+t.fontSize*N},w.anchorFn=function(t,e){return i(e)&&90===Math.abs(e)?"middle":_?"end":"start"},w.heightFn=function(e,r,n){return"right"===t.side&&(r*=-1),r<-30?-n:r<30?-.5*n:0}}return w},H.drawTicks=function(t,e,r){r=r||{};var i=e._id+"tick",a=[].concat(e.minor&&e.minor.ticks?r.vals.filter((function(t){return t.minor&&!t.noTick})):[]).concat(e.ticks?r.vals.filter((function(t){return!t.minor&&!t.noTick})):[]),o=r.layer.selectAll("path."+i).data(a,xt);o.exit().remove(),o.enter().append("path").classed(i,1).classed("ticks",1).classed("crisp",!1!==r.crisp).each((function(t){return f.stroke(n.select(this),t.minor?e.minor.tickcolor:e.tickcolor)})).style("stroke-width",(function(r){return h.crispRound(t,r.minor?e.minor.tickwidth:e.tickwidth,1)+"px"})).attr("d",r.path).style("display",null),It(e,[R]),o.attr("transform",r.transFn)},H.drawGrid=function(t,e,r){r=r||{};var i=e._id+"grid",a=e.minor&&e.minor.showgrid,o=a?r.vals.filter((function(t){return t.minor})):[],s=e.showgrid?r.vals.filter((function(t){return!t.minor})):[],l=r.counterAxis;if(l&&H.shouldShowZeroLine(t,e,l))for(var c="array"===e.tickmode,u=0;u=0;v--){var y=v?m:g;if(y){var x=y.selectAll("path."+i).data(v?s:o,xt);x.exit().remove(),x.enter().append("path").classed(i,1).classed("crisp",!1!==r.crisp),x.attr("transform",r.transFn).attr("d",r.path).each((function(t){return f.stroke(n.select(this),t.minor?e.minor.gridcolor:e.gridcolor||"#ddd")})).style("stroke-dasharray",(function(t){return h.dashStyle(t.minor?e.minor.griddash:e.griddash,t.minor?e.minor.gridwidth:e.gridwidth)})).style("stroke-width",(function(t){return(t.minor?d:e._gw)+"px"})).style("display",null),"function"==typeof r.path&&x.attr("d",r.path)}}It(e,[z,D])},H.drawZeroLine=function(t,e,r){r=r||r;var n=e._id+"zl",i=H.shouldShowZeroLine(t,e,r.counterAxis),a=r.layer.selectAll("path."+n).data(i?[{x:0,id:e._id}]:[]);a.exit().remove(),a.enter().append("path").classed(n,1).classed("zl",1).classed("crisp",!1!==r.crisp).each((function(){r.layer.selectAll("path").sort((function(t,e){return Y(t.id,e.id)}))})),a.attr("transform",r.transFn).attr("d",r.path).call(f.stroke,e.zerolinecolor||f.defaultLine).style("stroke-width",h.crispRound(t,e.zerolinewidth,e._gw||1)+"px").style("display",null),It(e,[O])},H.drawLabels=function(t,e,r){r=r||{};var a=t._fullLayout,o=e._id,u=o.charAt(0),f=r.cls||o+"tick",p=r.vals.filter((function(t){return t.text})),d=r.labelFns,m=r.secondary?0:e.tickangle,g=(e._prevTickAngles||{})[f],v=r.layer.selectAll("g."+f).data(e.showticklabels?p:[],xt),y=[];function x(t,a){t.each((function(t){var o=n.select(this),s=o.select(".text-math-group"),u=d.anchorFn(t,a),f=r.transFn.call(o.node(),t)+(i(a)&&0!=+a?" rotate("+a+","+d.xFn(t)+","+(d.yFn(t)-t.fontSize/2)+")":""),p=c.lineCount(o),m=U*t.fontSize,g=d.heightFn(t,i(a)?+a:0,(p-1)*m);if(g&&(f+=l(0,g)),s.empty()){var v=o.select("text");v.attr({transform:f,"text-anchor":u}),v.style("opacity",1),e._adjustTickLabelsOverflow&&e._adjustTickLabelsOverflow()}else{var y=h.bBox(s.node()).width*{end:-.5,start:.5}[u];s.attr("transform",f+l(y,0))}}))}v.enter().append("g").classed(f,1).append("text").attr("text-anchor","middle").each((function(e){var r=n.select(this),i=t._promises.length;r.call(c.positionText,d.xFn(e),d.yFn(e)).call(h.font,e.font,e.fontSize,e.fontColor).text(e.text).call(c.convertToTspans,t),t._promises[i]?y.push(t._promises.pop().then((function(){x(r,m)}))):x(r,m)})),It(e,[F]),v.exit().remove(),r.repositionOnUpdate&&v.each((function(t){n.select(this).select("text").call(c.positionText,d.xFn(t),d.yFn(t))})),e._adjustTickLabelsOverflow=function(){var r=e.ticklabeloverflow;if(r&&"allow"!==r){var i=-1!==r.indexOf("hide"),o="x"===e._id.charAt(0),l=0,c=o?t._fullLayout.width:t._fullLayout.height;if(-1!==r.indexOf("domain")){var u=s.simpleMap(e.range,e.r2l);l=e.l2p(u[0])+e._offset,c=e.l2p(u[1])+e._offset}var f=Math.min(l,c),p=Math.max(l,c),d=e.side,m=1/0,g=-1/0;for(var y in v.each((function(t){var r=n.select(this);if(r.select(".text-math-group").empty()){var a=h.bBox(r.node()),s=0;o?(a.right>p||a.leftp||a.top+(e.tickangle?0:t.fontSize/4)e["_visibleLabelMin_"+r._id]?l.style("display","none"):"tick"!==t.K||i||l.style("display",null)}))}))}))}))},x(v,g+1?g:m);var b=null;e._selections&&(e._selections[f]=v);var _=[function(){return y.length&&Promise.all(y)}];e.automargin&&a._redrawFromAutoMarginCount&&90===g?(b=90,_.push((function(){x(v,g)}))):_.push((function(){if(x(v,m),p.length&&"x"===u&&!i(m)&&("log"!==e.type||"D"!==String(e.dtick).charAt(0))){b=0;var t,n=0,a=[];if(v.each((function(t){n=Math.max(n,t.fontSize);var r=e.l2p(t.x),i=wt(this),o=h.bBox(i.node());a.push({top:0,bottom:10,height:10,left:r-o.width/2,right:r+o.width/2+2,width:o.width+2})})),"boundaries"!==e.tickson&&!e.showdividers||r.secondary){var o=p.length,l=Math.abs((p[o-1].x-p[0].x)*e._m)/(o-1),c=e.ticklabelposition||"",f=function(t){return-1!==c.indexOf(t)},d=f("top"),g=f("left"),y=f("right"),_=f("bottom")||g||d||y?(e.tickwidth||0)+6:0,w=l<2.5*n||"multicategory"===e.type||"realaxis"===e._name;for(t=0;t1)for(n=1;n2*o}(i,e))return"date";var g="strict"!==r.autotypenumbers;return function(t,e){for(var r=t.length,n=f(r),i=0,o=0,s={},u=0;u2*i}(i,g)?"category":function(t,e){for(var r=t.length,n=0;n=2){var s,c,u="";if(2===o.length)for(s=0;s<2;s++)if(c=b(o[s])){u=g;break}var f=i("pattern",u);if(f===g)for(s=0;s<2;s++)(c=b(o[s]))&&(e.bounds[s]=o[s]=c-1);if(f)for(s=0;s<2;s++)switch(c=o[s],f){case g:if(!n(c))return void(e.enabled=!1);if((c=+c)!==Math.floor(c)||c<0||c>=7)return void(e.enabled=!1);e.bounds[s]=o[s]=c;break;case v:if(!n(c))return void(e.enabled=!1);if((c=+c)<0||c>24)return void(e.enabled=!1);e.bounds[s]=o[s]=c}if(!1===r.autorange){var h=r.range;if(h[0]h[1])return void(e.enabled=!1)}else if(o[0]>h[0]&&o[1]n?1:-1:+(t.substr(1)||1)-+(e.substr(1)||1)},r.ref2id=function(t){return!!/^[xyz]/.test(t)&&t.split(" ")[0]},r.isLinked=function(t,e){return a(e,t._axisMatchGroups)||a(e,t._axisConstraintGroups)}},{"../../registry":638,"./constants":561}],559:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){if("category"===e.type){var i,a=t.categoryarray,o=Array.isArray(a)&&a.length>0;o&&(i="array");var s,l=r("categoryorder",i);"array"===l&&(s=r("categoryarray")),o||"array"!==l||(l=e.categoryorder="trace"),"trace"===l?e._initialCategories=[]:"array"===l?e._initialCategories=s.slice():(s=function(t,e){var r,n,i,a=e.dataAttr||t._id.charAt(0),o={};if(e.axData)r=e.axData;else for(r=[],n=0;nn?i.substr(n):a.substr(r))+o:i+a+t*e:o}function g(t,e){for(var r=e._size,n=r.h/r.w,i={},a=Object.keys(t),o=0;oc*x)||T)for(r=0;rO&&FP&&(P=F);h/=(P-C)/(2*I),C=l.l2r(C),P=l.l2r(P),l.range=l._input.range=S=0?Math.min(t,.9):1/(1/Math.max(t,-.3)+3.222))}function N(t,e,r,n,i){return t.append("path").attr("class","zoombox").style({fill:e>.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("transform",c(r,n)).attr("d",i+"Z")}function j(t,e,r){return t.append("path").attr("class","zoombox-corners").style({fill:f.background,stroke:f.defaultLine,"stroke-width":1,opacity:0}).attr("transform",c(e,r)).attr("d","M0,0Z")}function U(t,e,r,n,i,a){t.attr("d",n+"M"+r.l+","+r.t+"v"+r.h+"h"+r.w+"v-"+r.h+"h-"+r.w+"Z"),V(t,e,i,a)}function V(t,e,r,n){r||(t.transition().style("fill",n>.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),e.transition().style("opacity",1).duration(200))}function H(t){n.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}function q(t){I&&t.data&&t._context.showTips&&(i.notifier(i._(t,"Double-click to zoom back out"),"long"),I=!1)}function G(t){var e=Math.floor(Math.min(t.b-t.t,t.r-t.l,P)/2);return"M"+(t.l-3.5)+","+(t.t-.5+e)+"h3v"+-e+"h"+e+"v-3h-"+(e+3)+"ZM"+(t.r+3.5)+","+(t.t-.5+e)+"h-3v"+-e+"h"+-e+"v-3h"+(e+3)+"ZM"+(t.r+3.5)+","+(t.b+.5-e)+"h-3v"+e+"h"+-e+"v3h"+(e+3)+"ZM"+(t.l-3.5)+","+(t.b+.5-e)+"h3v"+e+"h"+e+"v3h-"+(e+3)+"Z"}function Y(t,e,r,n,a){for(var o,s,l,c,u=!1,f={},h={},p=(a||{}).xaHash,d=(a||{}).yaHash,m=0;m=0)i._fullLayout._deactivateShape(i);else{var o=i._fullLayout.clickmode;if(H(i),2!==t||vt||qt(),gt)o.indexOf("select")>-1&&S(r,i,J,K,e.id,Pt),o.indexOf("event")>-1&&p.click(i,r,e.id);else if(1===t&&vt){var s=m?O:I,c="s"===m||"w"===v?0:1,f=s._name+".range["+c+"]",h=function(t,e){var r,n=t.range[e],i=Math.abs(n-t.range[1-e]);return"date"===t.type?n:"log"===t.type?(r=Math.ceil(Math.max(0,-Math.log(i)/Math.LN10))+3,a("."+r+"g")(Math.pow(10,n))):(r=Math.floor(Math.log(Math.abs(n))/Math.LN10)-Math.floor(Math.log(i)/Math.LN10)+4,a("."+String(r)+"g")(n))}(s,c),d="left",g="middle";if(s.fixedrange)return;m?(g="n"===m?"top":"bottom","right"===s.side&&(d="right")):"e"===v&&(d="right"),i._context.showAxisRangeEntryBoxes&&n.select(bt).call(u.makeEditable,{gd:i,immediate:!0,background:i._fullLayout.paper_bgcolor,text:String(h),fill:s.tickfont?s.tickfont.color:"#444",horizontalAlign:d,verticalAlign:g}).on("edit",(function(t){var e=s.d2r(t);void 0!==e&&l.call("_guiRelayout",i,f,e)}))}}}function zt(e,r){if(t._transitioningWithDuration)return!1;var n=Math.max(0,Math.min(tt,pt*e+_t)),i=Math.max(0,Math.min(et,dt*r+wt)),a=Math.abs(n-_t),o=Math.abs(i-wt);function s(){St="",Tt.r=Tt.l,Tt.t=Tt.b,Lt.attr("d","M0,0Z")}if(Tt.l=Math.min(_t,n),Tt.r=Math.max(_t,n),Tt.t=Math.min(wt,i),Tt.b=Math.max(wt,i),rt.isSubplotConstrained)a>P||o>P?(St="xy",a/tt>o/et?(o=a*et/tt,wt>i?Tt.t=wt-o:Tt.b=wt+o):(a=o*tt/et,_t>n?Tt.l=_t-a:Tt.r=_t+a),Lt.attr("d",G(Tt))):s();else if(nt.isSubplotConstrained)if(a>P||o>P){St="xy";var l=Math.min(Tt.l/tt,(et-Tt.b)/et),c=Math.max(Tt.r/tt,(et-Tt.t)/et);Tt.l=l*tt,Tt.r=c*tt,Tt.b=(1-l)*et,Tt.t=(1-c)*et,Lt.attr("d",G(Tt))}else s();else!at||o0){var u;if(nt.isSubplotConstrained||!it&&1===at.length){for(u=0;um[1]-1/4096&&(e.domain=s),i.noneOrAll(t.domain,e.domain,s)}return r("layer"),e}},{"../../lib":503,"fast-isnumeric":190}],573:[function(t,e,r){"use strict";var n=t("./show_dflt");e.exports=function(t,e,r,i,a){a||(a={});var o=a.tickSuffixDflt,s=n(t);r("tickprefix")&&r("showtickprefix",s),r("ticksuffix",o)&&r("showticksuffix",s)}},{"./show_dflt":577}],574:[function(t,e,r){"use strict";var n=t("../../constants/alignment").FROM_BL;e.exports=function(t,e,r){void 0===r&&(r=n[t.constraintoward||"center"]);var i=[t.r2l(t.range[0]),t.r2l(t.range[1])],a=i[0]+(i[1]-i[0])*r;t.range=t._input.range=[t.l2r(a+(i[0]-a)*e),t.l2r(a+(i[1]-a)*e)],t.setScale()}},{"../../constants/alignment":471}],575:[function(t,e,r){"use strict";var n=t("polybooljs"),i=t("../../registry"),a=t("../../components/drawing").dashStyle,o=t("../../components/color"),s=t("../../components/fx"),l=t("../../components/fx/helpers").makeEventData,c=t("../../components/dragelement/helpers"),u=c.freeMode,f=c.rectMode,h=c.drawMode,p=c.openMode,d=c.selectMode,m=t("../../components/shapes/draw_newshape/display_outlines"),g=t("../../components/shapes/draw_newshape/helpers").handleEllipse,v=t("../../components/shapes/draw_newshape/newshapes"),y=t("../../lib"),x=t("../../lib/polygon"),b=t("../../lib/throttle"),_=t("./axis_ids").getFromId,w=t("../../lib/clear_gl_canvases"),T=t("../../plot_api/subroutines").redrawReglTraces,k=t("./constants"),A=k.MINSELECT,M=x.filter,S=x.tester,E=t("./handle_outline").clearSelect,L=t("./helpers"),C=L.p2r,P=L.axValue,I=L.getTransform;function O(t,e,r,n,i,a,o){var s,l,c,u,f,h,d,g,v,y=e._hoverdata,x=e._fullLayout.clickmode.indexOf("event")>-1,b=[];if(function(t){return t&&Array.isArray(t)&&!0!==t[0].hoverOnBox}(y)){F(t,e,a);var _=function(t,e){var r,n,i=t[0],a=-1,o=[];for(n=0;n0?function(t,e){var r,n,i,a=[];for(i=0;i0&&a.push(r);if(1===a.length&&a[0]===e.searchInfo&&(n=e.searchInfo.cd[0].trace).selectedpoints.length===e.pointNumbers.length){for(i=0;i1)return!1;if((i+=r.selectedpoints.length)>1)return!1}return 1===i}(s)&&(h=j(_))){for(o&&o.remove(),v=0;v=0&&n._fullLayout._deactivateShape(n),h(e)){var a=n._fullLayout._zoomlayer.selectAll(".select-outline-"+r.id);if(a&&n._fullLayout._drawing){var o=v(a,t);o&&i.call("_guiRelayout",n,{shapes:o}),n._fullLayout._drawing=!1}}r.selection={},r.selection.selectionDefs=t.selectionDefs=[],r.selection.mergedPolygons=t.mergedPolygons=[]}function N(t,e,r,n){var i,a,o,s=[],l=e.map((function(t){return t._id})),c=r.map((function(t){return t._id}));for(o=0;o0?n[0]:r;return!!e.selectedpoints&&e.selectedpoints.indexOf(i)>-1}function U(t,e,r){var n,a,o,s;for(n=0;n=0)L._fullLayout._deactivateShape(L);else if(!_){var r=z.clickmode;b.done(mt).then((function(){if(b.clear(mt),2===t){for(ft.remove(),$=0;$-1&&O(e,L,i.xaxes,i.yaxes,i.subplot,i,ft),"event"===r&&L.emit("plotly_selected",void 0);s.click(L,e)})).catch(y.error)}},i.doneFn=function(){dt.remove(),b.done(mt).then((function(){b.clear(mt),i.gd.emit("plotly_selected",et),Q&&i.selectionDefs&&(Q.subtract=ut,i.selectionDefs.push(Q),i.mergedPolygons.length=0,[].push.apply(i.mergedPolygons,K)),i.doneFnCompleted&&i.doneFnCompleted(gt)})).catch(y.error),_&&B(i)}},clearSelect:E,clearSelectionsCache:B,selectOnClick:O}},{"../../components/color":366,"../../components/dragelement/helpers":384,"../../components/drawing":388,"../../components/fx":406,"../../components/fx/helpers":402,"../../components/shapes/draw_newshape/display_outlines":454,"../../components/shapes/draw_newshape/helpers":455,"../../components/shapes/draw_newshape/newshapes":456,"../../lib":503,"../../lib/clear_gl_canvases":487,"../../lib/polygon":515,"../../lib/throttle":530,"../../plot_api/subroutines":544,"../../registry":638,"./axis_ids":558,"./constants":561,"./handle_outline":565,"./helpers":566,polybooljs:254}],576:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("d3-time-format").utcFormat,a=t("../../lib"),o=a.numberFormat,s=t("fast-isnumeric"),l=a.cleanNumber,c=a.ms2DateTime,u=a.dateTime2ms,f=a.ensureNumber,h=a.isArrayOrTypedArray,p=t("../../constants/numerical"),d=p.FP_SAFE,m=p.BADNUM,g=p.LOG_CLIP,v=p.ONEWEEK,y=p.ONEDAY,x=p.ONEHOUR,b=p.ONEMIN,_=p.ONESEC,w=t("./axis_ids"),T=t("./constants"),k=T.HOUR_PATTERN,A=T.WEEKDAY_PATTERN;function M(t){return Math.pow(10,t)}function S(t){return null!=t}e.exports=function(t,e){e=e||{};var r=t._id||"x",p=r.charAt(0);function E(e,r){if(e>0)return Math.log(e)/Math.LN10;if(e<=0&&r&&t.range&&2===t.range.length){var n=t.range[0],i=t.range[1];return.5*(n+i-2*g*Math.abs(n-i))}return m}function L(e,r,n,i){if((i||{}).msUTC&&s(e))return+e;var o=u(e,n||t.calendar);if(o===m){if(!s(e))return m;e=+e;var l=Math.floor(10*a.mod(e+.05,1)),c=Math.round(e-l/10);o=u(new Date(c))+l/10}return o}function C(e,r,n){return c(e,r,n||t.calendar)}function P(e){return t._categories[Math.round(e)]}function I(e){if(S(e)){if(void 0===t._categoriesMap&&(t._categoriesMap={}),void 0!==t._categoriesMap[e])return t._categoriesMap[e];t._categories.push("number"==typeof e?String(e):e);var r=t._categories.length-1;return t._categoriesMap[e]=r,r}return m}function O(e){if(t._categoriesMap)return t._categoriesMap[e]}function z(t){var e=O(t);return void 0!==e?e:s(t)?+t:void 0}function D(t){return s(t)?+t:O(t)}function R(t,e,r){return n.round(r+e*t,2)}function F(t,e,r){return(t-r)/e}var B=function(e){return s(e)?R(e,t._m,t._b):m},N=function(e){return F(e,t._m,t._b)};if(t.rangebreaks){var j="y"===p;B=function(e){if(!s(e))return m;var r=t._rangebreaks.length;if(!r)return R(e,t._m,t._b);var n=j;t.range[0]>t.range[1]&&(n=!n);for(var i=n?-1:1,a=i*e,o=0,l=0;lu)){o=a<(c+u)/2?l:l+1;break}o=l+1}var f=t._B[o]||0;return isFinite(f)?R(e,t._m2,f):0},N=function(e){var r=t._rangebreaks.length;if(!r)return F(e,t._m,t._b);for(var n=0,i=0;it._rangebreaks[i].pmax&&(n=i+1);return F(e,t._m2,t._B[n])}}t.c2l="log"===t.type?E:f,t.l2c="log"===t.type?M:f,t.l2p=B,t.p2l=N,t.c2p="log"===t.type?function(t,e){return B(E(t,e))}:B,t.p2c="log"===t.type?function(t){return M(N(t))}:N,-1!==["linear","-"].indexOf(t.type)?(t.d2r=t.r2d=t.d2c=t.r2c=t.d2l=t.r2l=l,t.c2d=t.c2r=t.l2d=t.l2r=f,t.d2p=t.r2p=function(e){return t.l2p(l(e))},t.p2d=t.p2r=N,t.cleanPos=f):"log"===t.type?(t.d2r=t.d2l=function(t,e){return E(l(t),e)},t.r2d=t.r2c=function(t){return M(l(t))},t.d2c=t.r2l=l,t.c2d=t.l2r=f,t.c2r=E,t.l2d=M,t.d2p=function(e,r){return t.l2p(t.d2r(e,r))},t.p2d=function(t){return M(N(t))},t.r2p=function(e){return t.l2p(l(e))},t.p2r=N,t.cleanPos=f):"date"===t.type?(t.d2r=t.r2d=a.identity,t.d2c=t.r2c=t.d2l=t.r2l=L,t.c2d=t.c2r=t.l2d=t.l2r=C,t.d2p=t.r2p=function(e,r,n){return t.l2p(L(e,0,n))},t.p2d=t.p2r=function(t,e,r){return C(N(t),e,r)},t.cleanPos=function(e){return a.cleanDate(e,m,t.calendar)}):"category"===t.type?(t.d2c=t.d2l=I,t.r2d=t.c2d=t.l2d=P,t.d2r=t.d2l_noadd=z,t.r2c=function(e){var r=D(e);return void 0!==r?r:t.fraction2r(.5)},t.l2r=t.c2r=f,t.r2l=D,t.d2p=function(e){return t.l2p(t.r2c(e))},t.p2d=function(t){return P(N(t))},t.r2p=t.d2p,t.p2r=N,t.cleanPos=function(t){return"string"==typeof t&&""!==t?t:f(t)}):"multicategory"===t.type&&(t.r2d=t.c2d=t.l2d=P,t.d2r=t.d2l_noadd=z,t.r2c=function(e){var r=z(e);return void 0!==r?r:t.fraction2r(.5)},t.r2c_just_indices=O,t.l2r=t.c2r=f,t.r2l=z,t.d2p=function(e){return t.l2p(t.r2c(e))},t.p2d=function(t){return P(N(t))},t.r2p=t.d2p,t.p2r=N,t.cleanPos=function(t){return Array.isArray(t)||"string"==typeof t&&""!==t?t:f(t)},t.setupMultiCategory=function(n){var i,o,s=t._traceIndices,l=t._matchGroup;if(l&&0===t._categories.length)for(var c in l)if(c!==r){var u=e[w.id2name(c)];s=s.concat(u._traceIndices)}var f=[[0,{}],[0,{}]],d=[];for(i=0;id&&(o[n]=d),o[0]===o[1]){var c=Math.max(1,Math.abs(1e-6*o[0]));o[0]-=c,o[1]+=c}}else a.nestedProperty(t,e).set(i)},t.setScale=function(r){var n=e._size;if(t.overlaying){var i=w.getFromId({_fullLayout:e},t.overlaying);t.domain=i.domain}var a=r&&t._r?"_r":"range",o=t.calendar;t.cleanRange(a);var s,l,c=t.r2l(t[a][0],o),u=t.r2l(t[a][1],o),f="y"===p;if((f?(t._offset=n.t+(1-t.domain[1])*n.h,t._length=n.h*(t.domain[1]-t.domain[0]),t._m=t._length/(c-u),t._b=-t._m*u):(t._offset=n.l+t.domain[0]*n.w,t._length=n.w*(t.domain[1]-t.domain[0]),t._m=t._length/(u-c),t._b=-t._m*c),t._rangebreaks=[],t._lBreaks=0,t._m2=0,t._B=[],t.rangebreaks)&&(t._rangebreaks=t.locateBreaks(Math.min(c,u),Math.max(c,u)),t._rangebreaks.length)){for(s=0;su&&(h=!h),h&&t._rangebreaks.reverse();var d=h?-1:1;for(t._m2=d*t._length/(Math.abs(u-c)-t._lBreaks),t._B.push(-t._m2*(f?u:c)),s=0;si&&(i+=7,oi&&(i+=24,o=n&&o=n&&e=s.min&&(ts.max&&(s.max=n),i=!1)}i&&c.push({min:t,max:n})}};for(n=0;nr.duration?(!function(){for(var r={},n=0;n rect").call(o.setTranslate,0,0).call(o.setScale,1,1),t.plot.call(o.setTranslate,e._offset,r._offset).call(o.setScale,1,1);var n=t.plot.selectAll(".scatterlayer .trace");n.selectAll(".point").call(o.setPointGroupScale,1,1),n.selectAll(".textpoint").call(o.setTextPointsScale,1,1),n.call(o.hideOutsideRangePoints,t)}function g(e,r){var n=e.plotinfo,i=n.xaxis,l=n.yaxis,c=i._length,u=l._length,f=!!e.xr1,h=!!e.yr1,p=[];if(f){var d=a.simpleMap(e.xr0,i.r2l),m=a.simpleMap(e.xr1,i.r2l),g=d[1]-d[0],v=m[1]-m[0];p[0]=(d[0]*(1-r)+r*m[0]-d[0])/(d[1]-d[0])*c,p[2]=c*(1-r+r*v/g),i.range[0]=i.l2r(d[0]*(1-r)+r*m[0]),i.range[1]=i.l2r(d[1]*(1-r)+r*m[1])}else p[0]=0,p[2]=c;if(h){var y=a.simpleMap(e.yr0,l.r2l),x=a.simpleMap(e.yr1,l.r2l),b=y[1]-y[0],_=x[1]-x[0];p[1]=(y[1]*(1-r)+r*x[1]-y[1])/(y[0]-y[1])*u,p[3]=u*(1-r+r*_/b),l.range[0]=i.l2r(y[0]*(1-r)+r*x[0]),l.range[1]=l.l2r(y[1]*(1-r)+r*x[1])}else p[1]=0,p[3]=u;s.drawOne(t,i,{skipTitle:!0}),s.drawOne(t,l,{skipTitle:!0}),s.redrawComponents(t,[i._id,l._id]);var w=f?c/p[2]:1,T=h?u/p[3]:1,k=f?p[0]:0,A=h?p[1]:0,M=f?p[0]/p[2]*c:0,S=h?p[1]/p[3]*u:0,E=i._offset-M,L=l._offset-S;n.clipRect.call(o.setTranslate,k,A).call(o.setScale,1/w,1/T),n.plot.call(o.setTranslate,E,L).call(o.setScale,w,T),o.setPointGroupScale(n.zoomScalePts,1/w,1/T),o.setTextPointsScale(n.zoomScaleTxt,1/w,1/T)}s.redrawComponents(t)}},{"../../components/drawing":388,"../../lib":503,"../../registry":638,"./axes":554,"@plotly/d3":58}],582:[function(t,e,r){"use strict";var n=t("../../registry").traceIs,i=t("./axis_autotype");function a(t){return{v:"x",h:"y"}[t.orientation||"v"]}function o(t,e){var r=a(t),i=n(t,"box-violin"),o=n(t._fullInput||{},"candlestick");return i&&!o&&e===r&&void 0===t[r]&&void 0===t[r+"0"]}e.exports=function(t,e,r,s){r("autotypenumbers",s.autotypenumbersDflt),"-"===r("type",(s.splomStash||{}).type)&&(!function(t,e){if("-"!==t.type)return;var r,s=t._id,l=s.charAt(0);-1!==s.indexOf("scene")&&(s=l);var c=function(t,e,r){for(var n=0;n0&&(i["_"+r+"axes"]||{})[e])return i;if((i[r+"axis"]||r)===e){if(o(i,r))return i;if((i[r]||[]).length||i[r+"0"])return i}}}(e,s,l);if(!c)return;if("histogram"===c.type&&l==={v:"y",h:"x"}[c.orientation||"v"])return void(t.type="linear");var u=l+"calendar",f=c[u],h={noMultiCategory:!n(c,"cartesian")||n(c,"noMultiCategory")};"box"===c.type&&c._hasPreCompStats&&l==={h:"x",v:"y"}[c.orientation||"v"]&&(h.noMultiCategory=!0);if(h.autotypenumbers=t.autotypenumbers,o(c,l)){var p=a(c),d=[];for(r=0;r0?".":"")+a;i.isPlainObject(o)?l(o,e,s,n+1):e(s,a,o)}}))}r.manageCommandObserver=function(t,e,n,o){var s={},l=!0;e&&e._commandObserver&&(s=e._commandObserver),s.cache||(s.cache={}),s.lookupTable={};var c=r.hasSimpleAPICommandBindings(t,n,s.lookupTable);if(e&&e._commandObserver){if(c)return s;if(e._commandObserver.remove)return e._commandObserver.remove(),e._commandObserver=null,s}if(c){a(t,c,s.cache),s.check=function(){if(l){var e=a(t,c,s.cache);return e.changed&&o&&void 0!==s.lookupTable[e.value]&&(s.disable(),Promise.resolve(o({value:e.value,type:c.type,prop:c.prop,traces:c.traces,index:s.lookupTable[e.value]})).then(s.enable,s.enable)),e.changed}};for(var u=["plotly_relayout","plotly_redraw","plotly_restyle","plotly_update","plotly_animatingframe","plotly_afterplot"],f=0;f0&&i<0&&(i+=360);var s=(i-n)/4;return{type:"Polygon",coordinates:[[[n,a],[n,o],[n+s,o],[n+2*s,o],[n+3*s,o],[i,o],[i,a],[i-s,a],[i-2*s,a],[i-3*s,a],[n,a]]]}}e.exports=function(t){return new M(t)},S.plot=function(t,e,r){var n=this,i=e[this.id],a=[],o=!1;for(var s in w.layerNameToAdjective)if("frame"!==s&&i["show"+s]){o=!0;break}for(var l=0;l0&&a._module.calcGeoJSON(i,e)}if(!this.updateProjection(t,e)){this.viewInitial&&this.scope===r.scope||this.saveViewInitial(r),this.scope=r.scope,this.updateBaseLayers(e,r),this.updateDims(e,r),this.updateFx(e,r),d.generalUpdatePerTraceModule(this.graphDiv,this,t,r);var o=this.layers.frontplot.select(".scatterlayer");this.dataPoints.point=o.selectAll(".point"),this.dataPoints.text=o.selectAll("text"),this.dataPaths.line=o.selectAll(".js-line");var s=this.layers.backplot.select(".choroplethlayer");this.dataPaths.choropleth=s.selectAll("path"),this.render()}},S.updateProjection=function(t,e){var r=this.graphDiv,n=e[this.id],l=e._size,u=n.domain,f=n.projection,h=n.lonaxis,p=n.lataxis,d=h._ax,m=p._ax,v=this.projection=function(t){var e=t.projection,r=e.type,n=w.projNames[r];n="geo"+c.titleCase(n);for(var l=(i[n]||s[n])(),u=t._isSatellite?180*Math.acos(1/e.distance)/Math.PI:t._isClipped?w.lonaxisSpan[r]/2:null,f=["center","rotate","parallels","clipExtent"],h=function(t){return t?l:[]},p=0;pu*Math.PI/180}return!1},l.getPath=function(){return a().projection(l)},l.getBounds=function(t){return l.getPath().bounds(t)},l.precision(w.precision),t._isSatellite&&l.tilt(e.tilt).distance(e.distance);u&&l.clipAngle(u-w.clipPad);return l}(n),y=[[l.l+l.w*u.x[0],l.t+l.h*(1-u.y[1])],[l.l+l.w*u.x[1],l.t+l.h*(1-u.y[0])]],x=n.center||{},b=f.rotation||{},_=h.range||[],T=p.range||[];if(n.fitbounds){d._length=y[1][0]-y[0][0],m._length=y[1][1]-y[0][1],d.range=g(r,d),m.range=g(r,m);var k=(d.range[0]+d.range[1])/2,A=(m.range[0]+m.range[1])/2;if(n._isScoped)x={lon:k,lat:A};else if(n._isClipped){x={lon:k,lat:A},b={lon:k,lat:A,roll:b.roll};var M=f.type,S=w.lonaxisSpan[M]/2||180,L=w.lataxisSpan[M]/2||90;_=[k-S,k+S],T=[A-L,A+L]}else x={lon:k,lat:A},b={lon:k,lat:b.lat,roll:b.roll}}v.center([x.lon-b.lon,x.lat-b.lat]).rotate([-b.lon,-b.lat,b.roll]).parallels(f.parallels);var C=E(_,T);v.fitExtent(y,C);var P=this.bounds=v.getBounds(C),I=this.fitScale=v.scale(),O=v.translate();if(n.fitbounds){var z=v.getBounds(E(d.range,m.range)),D=Math.min((P[1][0]-P[0][0])/(z[1][0]-z[0][0]),(P[1][1]-P[0][1])/(z[1][1]-z[0][1]));isFinite(D)?v.scale(D*I):c.warn("Something went wrong during"+this.id+"fitbounds computations.")}else v.scale(f.scale*I);var R=this.midPt=[(P[0][0]+P[1][0])/2,(P[0][1]+P[1][1])/2];if(v.translate([O[0]+(R[0]-O[0]),O[1]+(R[1]-O[1])]).clipExtent(P),n._isAlbersUsa){var F=v([x.lon,x.lat]),B=v.translate();v.translate([B[0]-(F[0]-B[0]),B[1]-(F[1]-B[1])])}},S.updateBaseLayers=function(t,e){var r=this,i=r.topojson,a=r.layers,o=r.basePaths;function s(t){return"lonaxis"===t||"lataxis"===t}function l(t){return Boolean(w.lineLayers[t])}function c(t){return Boolean(w.fillLayers[t])}var u=(this.hasChoropleth?w.layersForChoropleth:w.layers).filter((function(t){return l(t)||c(t)?e["show"+t]:!s(t)||e[t].showgrid})),p=r.framework.selectAll(".layer").data(u,String);p.exit().each((function(t){delete a[t],delete o[t],n.select(this).remove()})),p.enter().append("g").attr("class",(function(t){return"layer "+t})).each((function(t){var e=a[t]=n.select(this);"bg"===t?r.bgRect=e.append("rect").style("pointer-events","all"):s(t)?o[t]=e.append("path").style("fill","none"):"backplot"===t?e.append("g").classed("choroplethlayer",!0):"frontplot"===t?e.append("g").classed("scatterlayer",!0):l(t)?o[t]=e.append("path").style("fill","none").style("stroke-miterlimit",2):c(t)&&(o[t]=e.append("path").style("stroke","none"))})),p.order(),p.each((function(r){var n=o[r],a=w.layerNameToAdjective[r];"frame"===r?n.datum(w.sphereSVG):l(r)||c(r)?n.datum(A(i,i.objects[r])):s(r)&&n.datum(function(t,e,r){var n,i,a,o=e[t],s=w.scopeDefaults[e.scope];"lonaxis"===t?(n=s.lonaxisRange,i=s.lataxisRange,a=function(t,e){return[t,e]}):"lataxis"===t&&(n=s.lataxisRange,i=s.lonaxisRange,a=function(t,e){return[e,t]});var l={type:"linear",range:[n[0],n[1]-1e-6],tick0:o.tick0,dtick:o.dtick};m.setConvert(l,r);var c=m.calcTicks(l);e.isScoped||"lonaxis"!==t||c.pop();for(var u=c.length,f=new Array(u),h=0;h-1&&b(n.event,i,[r.xaxis],[r.yaxis],r.id,f),s.indexOf("event")>-1&&p.click(i,n.event))}))}function h(t){return r.projection.invert([t[0]+r.xaxis._offset,t[1]+r.yaxis._offset])}},S.makeFramework=function(){var t=this,e=t.graphDiv,r=e._fullLayout,i="clip"+r._uid+t.id;t.clipDef=r._clips.append("clipPath").attr("id",i),t.clipRect=t.clipDef.append("rect"),t.framework=n.select(t.container).append("g").attr("class","geo "+t.id).call(h.setClipUrl,i,e),t.project=function(e){var r=t.projection(e);return r?[r[0]-t.xaxis._offset,r[1]-t.yaxis._offset]:[null,null]},t.xaxis={_id:"x",c2p:function(e){return t.project(e)[0]}},t.yaxis={_id:"y",c2p:function(e){return t.project(e)[1]}},t.mockAxis={type:"linear",showexponent:"all",exponentformat:"B"},m.setConvert(t.mockAxis,r)},S.saveViewInitial=function(t){var e,r=t.center||{},n=t.projection,i=n.rotation||{};this.viewInitial={fitbounds:t.fitbounds,"projection.scale":n.scale},e=t._isScoped?{"center.lon":r.lon,"center.lat":r.lat}:t._isClipped?{"projection.rotation.lon":i.lon,"projection.rotation.lat":i.lat}:{"center.lon":r.lon,"center.lat":r.lat,"projection.rotation.lon":i.lon},c.extendFlat(this.viewInitial,e)},S.render=function(){var t,e=this.projection,r=e.getPath();function n(t){var r=e(t.lonlat);return r?u(r[0],r[1]):null}function i(t){return e.isLonLatOverEdges(t.lonlat)?"none":null}for(t in this.basePaths)this.basePaths[t].attr("d",r);for(t in this.dataPaths)this.dataPaths[t].attr("d",(function(t){return r(t.geojson)}));for(t in this.dataPoints)this.dataPoints[t].attr("display",i).attr("transform",n)}},{"../../components/color":366,"../../components/dragelement":385,"../../components/drawing":388,"../../components/fx":406,"../../lib":503,"../../lib/geo_location_utils":496,"../../lib/topojson_utils":532,"../../registry":638,"../cartesian/autorange":553,"../cartesian/axes":554,"../cartesian/select":575,"../plots":619,"./constants":587,"./zoom":592,"@plotly/d3":58,"d3-geo":114,"d3-geo-projection":113,"topojson-client":315}],589:[function(t,e,r){"use strict";var n=t("../../plots/get_data").getSubplotCalcData,i=t("../../lib").counterRegex,a=t("./geo"),o="geo",s=i(o),l={};l.geo={valType:"subplotid",dflt:o,editType:"calc"},e.exports={attr:o,name:o,idRoot:o,idRegex:s,attrRegex:s,attributes:l,layoutAttributes:t("./layout_attributes"),supplyLayoutDefaults:t("./layout_defaults"),plot:function(t){for(var e=t._fullLayout,r=t.calcdata,i=e._subplots.geo,s=0;s0&&P<0&&(P+=360);var I,O,z,D=(C+P)/2;if(!p){var R=d?f.projRotate:[D,0,0];I=r("projection.rotation.lon",R[0]),r("projection.rotation.lat",R[1]),r("projection.rotation.roll",R[2]),r("showcoastlines",!d&&x)&&(r("coastlinecolor"),r("coastlinewidth")),r("showocean",!!x&&void 0)&&r("oceancolor")}(p?(O=-96.6,z=38.7):(O=d?D:I,z=(L[0]+L[1])/2),r("center.lon",O),r("center.lat",z),m&&(r("projection.tilt"),r("projection.distance")),g)&&r("projection.parallels",f.projParallels||[0,60]);r("projection.scale"),r("showland",!!x&&void 0)&&r("landcolor"),r("showlakes",!!x&&void 0)&&r("lakecolor"),r("showrivers",!!x&&void 0)&&(r("rivercolor"),r("riverwidth")),r("showcountries",d&&"usa"!==u&&x)&&(r("countrycolor"),r("countrywidth")),("usa"===u||"north america"===u&&50===c)&&(r("showsubunits",x),r("subunitcolor"),r("subunitwidth")),d||r("showframe",x)&&(r("framecolor"),r("framewidth")),r("bgcolor"),r("fitbounds")&&(delete e.projection.scale,d?(delete e.center.lon,delete e.center.lat):v?(delete e.center.lon,delete e.center.lat,delete e.projection.rotation.lon,delete e.projection.rotation.lat,delete e.lonaxis.range,delete e.lataxis.range):(delete e.center.lon,delete e.center.lat,delete e.projection.rotation.lon))}e.exports=function(t,e,r){i(t,e,r,{type:"geo",attributes:s,handleDefaults:c,fullData:r,partition:"y"})}},{"../../lib":503,"../get_data":593,"../subplot_defaults":632,"./constants":587,"./layout_attributes":590}],592:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=t("../../registry"),o=Math.PI/180,s=180/Math.PI,l={cursor:"pointer"},c={cursor:"auto"};function u(t,e){return n.behavior.zoom().translate(e.translate()).scale(e.scale())}function f(t,e,r){var n=t.id,o=t.graphDiv,s=o.layout,l=s[n],c=o._fullLayout,u=c[n],f={},h={};function p(t,e){f[n+"."+t]=i.nestedProperty(l,t).get(),a.call("_storeDirectGUIEdit",s,c._preGUI,f);var r=i.nestedProperty(u,t);r.get()!==e&&(r.set(e),i.nestedProperty(l,t).set(e),h[n+"."+t]=e)}r(p),p("projection.scale",e.scale()/t.fitScale),p("fitbounds",!1),o.emit("plotly_relayout",h)}function h(t,e){var r=u(0,e);function i(r){var n=e.invert(t.midPt);r("center.lon",n[0]),r("center.lat",n[1])}return r.on("zoomstart",(function(){n.select(this).style(l)})).on("zoom",(function(){e.scale(n.event.scale).translate(n.event.translate),t.render();var r=e.invert(t.midPt);t.graphDiv.emit("plotly_relayouting",{"geo.projection.scale":e.scale()/t.fitScale,"geo.center.lon":r[0],"geo.center.lat":r[1]})})).on("zoomend",(function(){n.select(this).style(c),f(t,e,i)})),r}function p(t,e){var r,i,a,o,s,h,p,d,m,g=u(0,e);function v(t){return e.invert(t)}function y(r){var n=e.rotate(),i=e.invert(t.midPt);r("projection.rotation.lon",-n[0]),r("center.lon",i[0]),r("center.lat",i[1])}return g.on("zoomstart",(function(){n.select(this).style(l),r=n.mouse(this),i=e.rotate(),a=e.translate(),o=i,s=v(r)})).on("zoom",(function(){if(h=n.mouse(this),function(t){var r=v(t);if(!r)return!0;var n=e(r);return Math.abs(n[0]-t[0])>2||Math.abs(n[1]-t[1])>2}(r))return g.scale(e.scale()),void g.translate(e.translate());e.scale(n.event.scale),e.translate([a[0],n.event.translate[1]]),s?v(h)&&(d=v(h),p=[o[0]+(d[0]-s[0]),i[1],i[2]],e.rotate(p),o=p):s=v(r=h),m=!0,t.render();var l=e.rotate(),c=e.invert(t.midPt);t.graphDiv.emit("plotly_relayouting",{"geo.projection.scale":e.scale()/t.fitScale,"geo.center.lon":c[0],"geo.center.lat":c[1],"geo.projection.rotation.lon":-l[0]})})).on("zoomend",(function(){n.select(this).style(c),m&&f(t,e,y)})),g}function d(t,e){var r,i={r:e.rotate(),k:e.scale()},a=u(0,e),o=function(t){var e=0,r=arguments.length,i=[];for(;++ed?(a=(f>0?90:-90)-p,i=0):(a=Math.asin(f/d)*s-p,i=Math.sqrt(d*d-f*f));var m=180-a-2*p,g=(Math.atan2(h,u)-Math.atan2(c,i))*s,v=(Math.atan2(h,u)-Math.atan2(c,-i))*s;return b(r[0],r[1],a,g)<=b(r[0],r[1],m,v)?[a,g,r[2]]:[m,v,r[2]]}function b(t,e,r,n){var i=_(r-t),a=_(n-e);return Math.sqrt(i*i+a*a)}function _(t){return(t%360+540)%360-180}function w(t,e,r){var n=r*o,i=t.slice(),a=0===e?1:0,s=2===e?1:2,l=Math.cos(n),c=Math.sin(n);return i[a]=t[a]*l-t[s]*c,i[s]=t[s]*l+t[a]*c,i}function T(t){return[Math.atan2(2*(t[0]*t[1]+t[2]*t[3]),1-2*(t[1]*t[1]+t[2]*t[2]))*s,Math.asin(Math.max(-1,Math.min(1,2*(t[0]*t[2]-t[3]*t[1]))))*s,Math.atan2(2*(t[0]*t[3]+t[1]*t[2]),1-2*(t[2]*t[2]+t[3]*t[3]))*s]}function k(t,e){for(var r=0,n=0,i=t.length;nMath.abs(s)?(c.boxEnd[1]=c.boxStart[1]+Math.abs(a)*_*(s>=0?1:-1),c.boxEnd[1]l[3]&&(c.boxEnd[1]=l[3],c.boxEnd[0]=c.boxStart[0]+(l[3]-c.boxStart[1])/Math.abs(_))):(c.boxEnd[0]=c.boxStart[0]+Math.abs(s)/_*(a>=0?1:-1),c.boxEnd[0]l[2]&&(c.boxEnd[0]=l[2],c.boxEnd[1]=c.boxStart[1]+(l[2]-c.boxStart[0])*Math.abs(_)))}}else c.boxEnabled?(a=c.boxStart[0]!==c.boxEnd[0],s=c.boxStart[1]!==c.boxEnd[1],a||s?(a&&(g(0,c.boxStart[0],c.boxEnd[0]),t.xaxis.autorange=!1),s&&(g(1,c.boxStart[1],c.boxEnd[1]),t.yaxis.autorange=!1),t.relayoutCallback()):t.glplot.setDirty(),c.boxEnabled=!1,c.boxInited=!1):c.boxInited&&(c.boxInited=!1);break;case"pan":c.boxEnabled=!1,c.boxInited=!1,e?(c.panning||(c.dragStart[0]=n,c.dragStart[1]=i),Math.abs(c.dragStart[0]-n).999&&(m="turntable"):m="turntable")}else m="turntable";r("dragmode",m),r("hovermode",n.getDfltFromLayout("hovermode"))}e.exports=function(t,e,r){var i=e._basePlotModules.length>1;o(t,e,r,{type:"gl3d",attributes:l,handleDefaults:u,fullLayout:e,font:e.font,fullData:r,getDfltFromLayout:function(e){if(!i)return n.validate(t[e],l[e])?t[e]:void 0},autotypenumbersDflt:e.autotypenumbers,paper_bgcolor:e.paper_bgcolor,calendar:e.calendar})}},{"../../../components/color":366,"../../../lib":503,"../../../registry":638,"../../get_data":593,"../../subplot_defaults":632,"./axis_defaults":601,"./layout_attributes":604}],604:[function(t,e,r){"use strict";var n=t("./axis_attributes"),i=t("../../domain").attributes,a=t("../../../lib/extend").extendFlat,o=t("../../../lib").counterRegex;function s(t,e,r){return{x:{valType:"number",dflt:t,editType:"camera"},y:{valType:"number",dflt:e,editType:"camera"},z:{valType:"number",dflt:r,editType:"camera"},editType:"camera"}}e.exports={_arrayAttrRegexps:[o("scene",".annotations",!0)],bgcolor:{valType:"color",dflt:"rgba(0,0,0,0)",editType:"plot"},camera:{up:a(s(0,0,1),{}),center:a(s(0,0,0),{}),eye:a(s(1.25,1.25,1.25),{}),projection:{type:{valType:"enumerated",values:["perspective","orthographic"],dflt:"perspective",editType:"calc"},editType:"calc"},editType:"camera"},domain:i({name:"scene",editType:"plot"}),aspectmode:{valType:"enumerated",values:["auto","cube","data","manual"],dflt:"auto",editType:"plot",impliedEdits:{"aspectratio.x":void 0,"aspectratio.y":void 0,"aspectratio.z":void 0}},aspectratio:{x:{valType:"number",min:0,editType:"plot",impliedEdits:{"^aspectmode":"manual"}},y:{valType:"number",min:0,editType:"plot",impliedEdits:{"^aspectmode":"manual"}},z:{valType:"number",min:0,editType:"plot",impliedEdits:{"^aspectmode":"manual"}},editType:"plot",impliedEdits:{aspectmode:"manual"}},xaxis:n,yaxis:n,zaxis:n,dragmode:{valType:"enumerated",values:["orbit","turntable","zoom","pan",!1],editType:"plot"},hovermode:{valType:"enumerated",values:["closest",!1],dflt:"closest",editType:"modebar"},uirevision:{valType:"any",editType:"none"},editType:"plot",_deprecated:{cameraposition:{valType:"info_array",editType:"camera"}}}},{"../../../lib":503,"../../../lib/extend":493,"../../domain":584,"./axis_attributes":600}],605:[function(t,e,r){"use strict";var n=t("../../../lib/str2rgbarray"),i=["xaxis","yaxis","zaxis"];function a(){this.enabled=[!0,!0,!0],this.colors=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.drawSides=[!0,!0,!0],this.lineWidth=[1,1,1]}a.prototype.merge=function(t){for(var e=0;e<3;++e){var r=t[i[e]];r.visible?(this.enabled[e]=r.showspikes,this.colors[e]=n(r.spikecolor),this.drawSides[e]=r.spikesides,this.lineWidth[e]=r.spikethickness):(this.enabled[e]=!1,this.drawSides[e]=!1)}},e.exports=function(t){var e=new a;return e.merge(t),e}},{"../../../lib/str2rgbarray":528}],606:[function(t,e,r){"use strict";e.exports=function(t){for(var e=t.axesOptions,r=t.glplot.axesPixels,s=t.fullSceneLayout,l=[[],[],[]],c=0;c<3;++c){var u=s[a[c]];if(u._length=(r[c].hi-r[c].lo)*r[c].pixelsPerDataUnit/t.dataScale[c],Math.abs(u._length)===1/0||isNaN(u._length))l[c]=[];else{u._input_range=u.range.slice(),u.range[0]=r[c].lo/t.dataScale[c],u.range[1]=r[c].hi/t.dataScale[c],u._m=1/(t.dataScale[c]*r[c].pixelsPerDataUnit),u.range[0]===u.range[1]&&(u.range[0]-=1,u.range[1]+=1);var f=u.tickmode;if("auto"===u.tickmode){u.tickmode="linear";var h=u.nticks||i.constrain(u._length/40,4,9);n.autoTicks(u,Math.abs(u.range[1]-u.range[0])/h)}for(var p=n.calcTicks(u,{msUTC:!0}),d=0;d/g," "));l[c]=p,u.tickmode=f}}e.ticks=l;for(c=0;c<3;++c){o[c]=.5*(t.glplot.bounds[0][c]+t.glplot.bounds[1][c]);for(d=0;d<2;++d)e.bounds[d][c]=t.glplot.bounds[d][c]}t.contourLevels=function(t){for(var e=new Array(3),r=0;r<3;++r){for(var n=t[r],i=new Array(n.length),a=0;ar.deltaY?1.1:1/1.1,a=t.glplot.getAspectratio();t.glplot.setAspectratio({x:n*a.x,y:n*a.y,z:n*a.z})}i(t)}}),!!c&&{passive:!1}),t.glplot.canvas.addEventListener("mousemove",(function(){if(!1!==t.fullSceneLayout.dragmode&&0!==t.camera.mouseListener.buttons){var e=n();t.graphDiv.emit("plotly_relayouting",e)}})),t.staticMode||t.glplot.canvas.addEventListener("webglcontextlost",(function(r){e&&e.emit&&e.emit("plotly_webglcontextlost",{event:r,layer:t.id})}),!1)),t.glplot.oncontextloss=function(){t.recoverContext()},t.glplot.onrender=function(){t.render()},!0},w.render=function(){var t,e=this,r=e.graphDiv,n=e.svgContainer,i=e.container.getBoundingClientRect();r._fullLayout._calcInverseTransform(r);var a=r._fullLayout._invScaleX,o=r._fullLayout._invScaleY,s=i.width*a,l=i.height*o;n.setAttributeNS(null,"viewBox","0 0 "+s+" "+l),n.setAttributeNS(null,"width",s),n.setAttributeNS(null,"height",l),b(e),e.glplot.axes.update(e.axesOptions);for(var c=Object.keys(e.traces),u=null,h=e.glplot.selection,m=0;m")):"isosurface"===t.type||"volume"===t.type?(T.valueLabel=p.hoverLabelText(e._mockAxis,e._mockAxis.d2l(h.traceCoordinate[3]),t.valuehoverformat),S.push("value: "+T.valueLabel),h.textLabel&&S.push(h.textLabel),x=S.join("
    ")):x=h.textLabel;var E={x:h.traceCoordinate[0],y:h.traceCoordinate[1],z:h.traceCoordinate[2],data:_._input,fullData:_,curveNumber:_.index,pointNumber:w};d.appendArrayPointValue(E,_,w),t._module.eventData&&(E=_._module.eventData(E,h,_,{},w));var L={points:[E]};if(e.fullSceneLayout.hovermode){var C=[];d.loneHover({trace:_,x:(.5+.5*y[0]/y[3])*s,y:(.5-.5*y[1]/y[3])*l,xLabel:T.xLabel,yLabel:T.yLabel,zLabel:T.zLabel,text:x,name:u.name,color:d.castHoverOption(_,w,"bgcolor")||u.color,borderColor:d.castHoverOption(_,w,"bordercolor"),fontFamily:d.castHoverOption(_,w,"font.family"),fontSize:d.castHoverOption(_,w,"font.size"),fontColor:d.castHoverOption(_,w,"font.color"),nameLength:d.castHoverOption(_,w,"namelength"),textAlign:d.castHoverOption(_,w,"align"),hovertemplate:f.castOption(_,w,"hovertemplate"),hovertemplateLabels:f.extendFlat({},E,T),eventData:[E]},{container:n,gd:r,inOut_bbox:C}),E.bbox=C[0]}h.buttons&&h.distance<5?r.emit("plotly_click",L):r.emit("plotly_hover",L),this.oldEventData=L}else d.loneUnhover(n),this.oldEventData&&r.emit("plotly_unhover",this.oldEventData),this.oldEventData=void 0;e.drawAnnotations(e)},w.recoverContext=function(){var t=this;t.glplot.dispose();var e=function(){t.glplot.gl.isContextLost()?requestAnimationFrame(e):t.initializeGLPlot()?t.plot.apply(t,t.plotArgs):f.error("Catastrophic and unrecoverable WebGL error. Context lost.")};requestAnimationFrame(e)};var k=["xaxis","yaxis","zaxis"];function A(t,e,r){for(var n=t.fullSceneLayout,i=0;i<3;i++){var a=k[i],o=a.charAt(0),s=n[a],l=e[o],c=e[o+"calendar"],u=e["_"+o+"length"];if(f.isArrayOrTypedArray(l))for(var h,p=0;p<(u||l.length);p++)if(f.isArrayOrTypedArray(l[p]))for(var d=0;dg[1][a])g[0][a]=-1,g[1][a]=1;else{var L=g[1][a]-g[0][a];g[0][a]-=L/32,g[1][a]+=L/32}if("reversed"===s.autorange){var C=g[0][a];g[0][a]=g[1][a],g[1][a]=C}}else{var P=s.range;g[0][a]=s.r2l(P[0]),g[1][a]=s.r2l(P[1])}g[0][a]===g[1][a]&&(g[0][a]-=1,g[1][a]+=1),v[a]=g[1][a]-g[0][a],this.glplot.setBounds(a,{min:g[0][a]*h[a],max:g[1][a]*h[a]})}var I=c.aspectmode;if("cube"===I)d=[1,1,1];else if("manual"===I){var O=c.aspectratio;d=[O.x,O.y,O.z]}else{if("auto"!==I&&"data"!==I)throw new Error("scene.js aspectRatio was not one of the enumerated types");var z=[1,1,1];for(a=0;a<3;++a){var D=y[l=(s=c[k[a]]).type];z[a]=Math.pow(D.acc,1/D.count)/h[a]}d="data"===I||Math.max.apply(null,z)/Math.min.apply(null,z)<=4?z:[1,1,1]}c.aspectratio.x=u.aspectratio.x=d[0],c.aspectratio.y=u.aspectratio.y=d[1],c.aspectratio.z=u.aspectratio.z=d[2],this.glplot.setAspectratio(c.aspectratio),this.viewInitial.aspectratio||(this.viewInitial.aspectratio={x:c.aspectratio.x,y:c.aspectratio.y,z:c.aspectratio.z}),this.viewInitial.aspectmode||(this.viewInitial.aspectmode=c.aspectmode);var R=c.domain||null,F=e._size||null;if(R&&F){var B=this.container.style;B.position="absolute",B.left=F.l+R.x[0]*F.w+"px",B.top=F.t+(1-R.y[1])*F.h+"px",B.width=F.w*(R.x[1]-R.x[0])+"px",B.height=F.h*(R.y[1]-R.y[0])+"px"}this.glplot.redraw()}},w.destroy=function(){this.glplot&&(this.camera.mouseListener.enabled=!1,this.container.removeEventListener("wheel",this.camera.wheelListener),this.camera=null,this.glplot.dispose(),this.container.parentNode.removeChild(this.container),this.glplot=null)},w.getCamera=function(){var t;return this.camera.view.recalcMatrix(this.camera.view.lastT()),{up:{x:(t=this.camera).up[0],y:t.up[1],z:t.up[2]},center:{x:t.center[0],y:t.center[1],z:t.center[2]},eye:{x:t.eye[0],y:t.eye[1],z:t.eye[2]},projection:{type:!0===t._ortho?"orthographic":"perspective"}}},w.setViewport=function(t){var e,r=t.camera;this.camera.lookAt.apply(this,[[(e=r).eye.x,e.eye.y,e.eye.z],[e.center.x,e.center.y,e.center.z],[e.up.x,e.up.y,e.up.z]]),this.glplot.setAspectratio(t.aspectratio),"orthographic"===r.projection.type!==this.camera._ortho&&(this.glplot.redraw(),this.glplot.clearRGBA(),this.glplot.dispose(),this.initializeGLPlot())},w.isCameraChanged=function(t){var e=this.getCamera(),r=f.nestedProperty(t,this.id+".camera").get();function n(t,e,r,n){var i=["up","center","eye"],a=["x","y","z"];return e[i[r]]&&t[i[r]][a[n]]===e[i[r]][a[n]]}var i=!1;if(void 0===r)i=!0;else{for(var a=0;a<3;a++)for(var o=0;o<3;o++)if(!n(e,r,a,o)){i=!0;break}(!r.projection||e.projection&&e.projection.type!==r.projection.type)&&(i=!0)}return i},w.isAspectChanged=function(t){var e=this.glplot.getAspectratio(),r=f.nestedProperty(t,this.id+".aspectratio").get();return void 0===r||r.x!==e.x||r.y!==e.y||r.z!==e.z},w.saveLayout=function(t){var e,r,n,i,a,o,s=this.fullLayout,l=this.isCameraChanged(t),c=this.isAspectChanged(t),h=l||c;if(h){var p={};if(l&&(e=this.getCamera(),n=(r=f.nestedProperty(t,this.id+".camera")).get(),p[this.id+".camera"]=n),c&&(i=this.glplot.getAspectratio(),o=(a=f.nestedProperty(t,this.id+".aspectratio")).get(),p[this.id+".aspectratio"]=o),u.call("_storeDirectGUIEdit",t,s._preGUI,p),l)r.set(e),f.nestedProperty(s,this.id+".camera").set(e);if(c)a.set(i),f.nestedProperty(s,this.id+".aspectratio").set(i),this.glplot.redraw()}return h},w.updateFx=function(t,e){var r=this.camera;if(r)if("orbit"===t)r.mode="orbit",r.keyBindingMode="rotate";else if("turntable"===t){r.up=[0,0,1],r.mode="turntable",r.keyBindingMode="rotate";var n=this.graphDiv,i=n._fullLayout,a=this.fullSceneLayout.camera,o=a.up.x,s=a.up.y,l=a.up.z;if(l/Math.sqrt(o*o+s*s+l*l)<.999){var c=this.id+".camera.up",h={x:0,y:0,z:1},p={};p[c]=h;var d=n.layout;u.call("_storeDirectGUIEdit",d,i._preGUI,p),a.up=h,f.nestedProperty(d,c).set(h)}}else r.keyBindingMode=t;this.fullSceneLayout.hovermode=e},w.toImage=function(t){t||(t="png"),this.staticMode&&this.container.appendChild(n),this.glplot.redraw();var e=this.glplot.gl,r=e.drawingBufferWidth,i=e.drawingBufferHeight;e.bindFramebuffer(e.FRAMEBUFFER,null);var a=new Uint8Array(r*i*4);e.readPixels(0,0,r,i,e.RGBA,e.UNSIGNED_BYTE,a),function(t,e,r){for(var n=0,i=r-1;n0)for(var s=255/o,l=0;l<3;++l)t[a+l]=Math.min(s*t[a+l],255)}}(a,r,i);var o=document.createElement("canvas");o.width=r,o.height=i;var s,l=o.getContext("2d",{willReadFrequently:!0}),c=l.createImageData(r,i);switch(c.data.set(a),l.putImageData(c,0,0),t){case"jpeg":s=o.toDataURL("image/jpeg");break;case"webp":s=o.toDataURL("image/webp");break;default:s=o.toDataURL("image/png")}return this.staticMode&&this.container.removeChild(n),s},w.setConvert=function(){for(var t=0;t<3;t++){var e=this.fullSceneLayout[k[t]];p.setConvert(e,this.fullLayout),e.setScale=f.noop}},w.make4thDimension=function(){var t=this.graphDiv._fullLayout;this._mockAxis={type:"linear",showexponent:"all",exponentformat:"B"},p.setConvert(this._mockAxis,t)},e.exports=_},{"../../../stackgl_modules":1124,"../../components/fx":406,"../../lib":503,"../../lib/show_no_webgl_msg":525,"../../lib/str2rgbarray":528,"../../plots/cartesian/axes":554,"../../registry":638,"./layout/convert":602,"./layout/spikes":605,"./layout/tick_marks":606,"./project":607,"has-passive-events":229,"webgl-context":331}],609:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){n=n||t.length;for(var i=new Array(n),a=0;aOpenStreetMap
    contributors',a=['\xa9 Carto',i].join(" "),o=['Map tiles by Stamen Design','under CC BY 3.0',"|",'Data by OpenStreetMap contributors','under ODbL'].join(" "),s={"open-street-map":{id:"osm",version:8,sources:{"plotly-osm-tiles":{type:"raster",attribution:i,tiles:["https://a.tile.openstreetmap.org/{z}/{x}/{y}.png","https://b.tile.openstreetmap.org/{z}/{x}/{y}.png"],tileSize:256}},layers:[{id:"plotly-osm-tiles",type:"raster",source:"plotly-osm-tiles",minzoom:0,maxzoom:22}]},"white-bg":{id:"white-bg",version:8,sources:{},layers:[{id:"white-bg",type:"background",paint:{"background-color":"#FFFFFF"},minzoom:0,maxzoom:22}]},"carto-positron":{id:"carto-positron",version:8,sources:{"plotly-carto-positron":{type:"raster",attribution:a,tiles:["https://cartodb-basemaps-c.global.ssl.fastly.net/light_all/{z}/{x}/{y}.png"],tileSize:256}},layers:[{id:"plotly-carto-positron",type:"raster",source:"plotly-carto-positron",minzoom:0,maxzoom:22}]},"carto-darkmatter":{id:"carto-darkmatter",version:8,sources:{"plotly-carto-darkmatter":{type:"raster",attribution:a,tiles:["https://cartodb-basemaps-c.global.ssl.fastly.net/dark_all/{z}/{x}/{y}.png"],tileSize:256}},layers:[{id:"plotly-carto-darkmatter",type:"raster",source:"plotly-carto-darkmatter",minzoom:0,maxzoom:22}]},"stamen-terrain":{id:"stamen-terrain",version:8,sources:{"plotly-stamen-terrain":{type:"raster",attribution:o,tiles:["https://stamen-tiles.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png"],tileSize:256}},layers:[{id:"plotly-stamen-terrain",type:"raster",source:"plotly-stamen-terrain",minzoom:0,maxzoom:22}]},"stamen-toner":{id:"stamen-toner",version:8,sources:{"plotly-stamen-toner":{type:"raster",attribution:o,tiles:["https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png"],tileSize:256}},layers:[{id:"plotly-stamen-toner",type:"raster",source:"plotly-stamen-toner",minzoom:0,maxzoom:22}]},"stamen-watercolor":{id:"stamen-watercolor",version:8,sources:{"plotly-stamen-watercolor":{type:"raster",attribution:['Map tiles by Stamen Design','under CC BY 3.0',"|",'Data by OpenStreetMap contributors','under CC BY SA'].join(" "),tiles:["https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.png"],tileSize:256}},layers:[{id:"plotly-stamen-watercolor",type:"raster",source:"plotly-stamen-watercolor",minzoom:0,maxzoom:22}]}},l=n(s);e.exports={requiredVersion:"1.10.1",styleUrlPrefix:"mapbox://styles/mapbox/",styleUrlSuffix:"v9",styleValuesMapbox:["basic","streets","outdoors","light","dark","satellite","satellite-streets"],styleValueDflt:"basic",stylesNonMapbox:s,styleValuesNonMapbox:l,traceLayerPrefix:"plotly-trace-layer-",layoutLayerPrefix:"plotly-layout-layer-",wrongVersionErrorMsg:["Your custom plotly.js bundle is not using the correct mapbox-gl version","Please install mapbox-gl@1.10.1."].join("\n"),noAccessTokenErrorMsg:["Missing Mapbox access token.","Mapbox trace type require a Mapbox access token to be registered.","For example:"," Plotly.newPlot(gd, data, layout, { mapboxAccessToken: 'my-access-token' });","More info here: https://www.mapbox.com/help/define-access-token/"].join("\n"),missingStyleErrorMsg:["No valid mapbox style found, please set `mapbox.style` to one of:",l.join(", "),"or register a Mapbox access token to use a Mapbox-served style."].join("\n"),multipleTokensErrorMsg:["Set multiple mapbox access token across different mapbox subplot,","using first token found as mapbox-gl does not allow multipleaccess tokens on the same page."].join("\n"),mapOnErrorMsg:"Mapbox error.",mapboxLogo:{path0:"m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z",path1:"M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z",path2:"M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z",polygon:"11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34"},styleRules:{map:"overflow:hidden;position:relative;","missing-css":"display:none;",canary:"background-color:salmon;","ctrl-bottom-left":"position: absolute; pointer-events: none; z-index: 2; bottom: 0; left: 0;","ctrl-bottom-right":"position: absolute; pointer-events: none; z-index: 2; right: 0; bottom: 0;",ctrl:"clear: both; pointer-events: auto; transform: translate(0, 0);","ctrl-attrib.mapboxgl-compact .mapboxgl-ctrl-attrib-inner":"display: none;","ctrl-attrib.mapboxgl-compact:hover .mapboxgl-ctrl-attrib-inner":"display: block; margin-top:2px","ctrl-attrib.mapboxgl-compact:hover":"padding: 2px 24px 2px 4px; visibility: visible; margin-top: 6px;","ctrl-attrib.mapboxgl-compact::after":'content: ""; cursor: pointer; position: absolute; background-image: url(\'data:image/svg+xml;charset=utf-8,%3Csvg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"%3E %3Cpath fill="%23333333" fill-rule="evenodd" d="M4,10a6,6 0 1,0 12,0a6,6 0 1,0 -12,0 M9,7a1,1 0 1,0 2,0a1,1 0 1,0 -2,0 M9,10a1,1 0 1,1 2,0l0,3a1,1 0 1,1 -2,0"/%3E %3C/svg%3E\'); background-color: rgba(255, 255, 255, 0.5); width: 24px; height: 24px; box-sizing: border-box; border-radius: 12px;',"ctrl-attrib.mapboxgl-compact":"min-height: 20px; padding: 0; margin: 10px; position: relative; background-color: #fff; border-radius: 3px 12px 12px 3px;","ctrl-bottom-right > .mapboxgl-ctrl-attrib.mapboxgl-compact::after":"bottom: 0; right: 0","ctrl-bottom-left > .mapboxgl-ctrl-attrib.mapboxgl-compact::after":"bottom: 0; left: 0","ctrl-bottom-left .mapboxgl-ctrl":"margin: 0 0 10px 10px; float: left;","ctrl-bottom-right .mapboxgl-ctrl":"margin: 0 10px 10px 0; float: right;","ctrl-attrib":"color: rgba(0, 0, 0, 0.75); text-decoration: none; font-size: 12px","ctrl-attrib a":"color: rgba(0, 0, 0, 0.75); text-decoration: none; font-size: 12px","ctrl-attrib a:hover":"color: inherit; text-decoration: underline;","ctrl-attrib .mapbox-improve-map":"font-weight: bold; margin-left: 2px;","attrib-empty":"display: none;","ctrl-logo":'display:block; width: 21px; height: 21px; background-image: url(\'data:image/svg+xml;charset=utf-8,%3C?xml version="1.0" encoding="utf-8"?%3E %3Csvg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 21 21" style="enable-background:new 0 0 21 21;" xml:space="preserve"%3E%3Cg transform="translate(0,0.01)"%3E%3Cpath d="m 10.5,1.24 c -5.11,0 -9.25,4.15 -9.25,9.25 0,5.1 4.15,9.25 9.25,9.25 5.1,0 9.25,-4.15 9.25,-9.25 0,-5.11 -4.14,-9.25 -9.25,-9.25 z m 4.39,11.53 c -1.93,1.93 -4.78,2.31 -6.7,2.31 -0.7,0 -1.41,-0.05 -2.1,-0.16 0,0 -1.02,-5.64 2.14,-8.81 0.83,-0.83 1.95,-1.28 3.13,-1.28 1.27,0 2.49,0.51 3.39,1.42 1.84,1.84 1.89,4.75 0.14,6.52 z" style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3Cpath d="M 10.5,-0.01 C 4.7,-0.01 0,4.7 0,10.49 c 0,5.79 4.7,10.5 10.5,10.5 5.8,0 10.5,-4.7 10.5,-10.5 C 20.99,4.7 16.3,-0.01 10.5,-0.01 Z m 0,19.75 c -5.11,0 -9.25,-4.15 -9.25,-9.25 0,-5.1 4.14,-9.26 9.25,-9.26 5.11,0 9.25,4.15 9.25,9.25 0,5.13 -4.14,9.26 -9.25,9.26 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpath d="M 14.74,6.25 C 12.9,4.41 9.98,4.35 8.23,6.1 5.07,9.27 6.09,14.91 6.09,14.91 c 0,0 5.64,1.02 8.81,-2.14 C 16.64,11 16.59,8.09 14.74,6.25 Z m -2.27,4.09 -0.91,1.87 -0.9,-1.87 -1.86,-0.91 1.86,-0.9 0.9,-1.87 0.91,1.87 1.86,0.9 z" style="opacity:0.35;enable-background:new" class="st1"/%3E%3Cpolygon points="11.56,12.21 10.66,10.34 8.8,9.43 10.66,8.53 11.56,6.66 12.47,8.53 14.33,9.43 12.47,10.34 " style="opacity:0.9;fill:%23ffffff;enable-background:new" class="st0"/%3E%3C/g%3E%3C/svg%3E\')'}}},{"../../lib/sort_object_keys":526}],612:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e){var r=t.split(" "),i=r[0],a=r[1],o=n.isArrayOrTypedArray(e)?n.mean(e):e,s=.5+o/100,l=1.5+o/100,c=["",""],u=[0,0];switch(i){case"top":c[0]="top",u[1]=-l;break;case"bottom":c[0]="bottom",u[1]=l}switch(a){case"left":c[1]="right",u[0]=-s;break;case"right":c[1]="left",u[0]=s}return{anchor:c[0]&&c[1]?c.join("-"):c[0]?c[0]:c[1]?c[1]:"center",offset:u}}},{"../../lib":503}],613:[function(t,e,r){"use strict";var n=t("mapbox-gl/dist/mapbox-gl-unminified"),i=t("../../lib"),a=i.strTranslate,o=i.strScale,s=t("../../plots/get_data").getSubplotCalcData,l=t("../../constants/xmlns_namespaces"),c=t("@plotly/d3"),u=t("../../components/drawing"),f=t("../../lib/svg_text_utils"),h=t("./mapbox"),p=r.constants=t("./constants");function d(t){return"string"==typeof t&&(-1!==p.styleValuesMapbox.indexOf(t)||0===t.indexOf("mapbox://"))}r.name="mapbox",r.attr="subplot",r.idRoot="mapbox",r.idRegex=r.attrRegex=i.counterRegex("mapbox"),r.attributes={subplot:{valType:"subplotid",dflt:"mapbox",editType:"calc"}},r.layoutAttributes=t("./layout_attributes"),r.supplyLayoutDefaults=t("./layout_defaults"),r.plot=function(t){var e=t._fullLayout,r=t.calcdata,a=e._subplots.mapbox;if(n.version!==p.requiredVersion)throw new Error(p.wrongVersionErrorMsg);var o=function(t,e){var r=t._fullLayout;if(""===t._context.mapboxAccessToken)return"";for(var n=[],a=[],o=!1,s=!1,l=0;l1&&i.warn(p.multipleTokensErrorMsg),n[0]):(a.length&&i.log(["Listed mapbox access token(s)",a.join(","),"but did not use a Mapbox map style, ignoring token(s)."].join(" ")),"")}(t,a);n.accessToken=o;for(var l=0;l_/2){var w=v.split("|").join("
    ");x.text(w).attr("data-unformatted",w).call(f.convertToTspans,t),b=u.bBox(x.node())}x.attr("transform",a(-3,8-b.height)),y.insert("rect",".static-attribution").attr({x:-b.width-6,y:-b.height-3,width:b.width+6,height:b.height+3,fill:"rgba(255, 255, 255, 0.75)"});var T=1;b.width+6>_&&(T=_/(b.width+6));var k=[n.l+n.w*h.x[1],n.t+n.h*(1-h.y[0])];y.attr("transform",a(k[0],k[1])+o(T))}},r.updateFx=function(t){for(var e=t._fullLayout,r=e._subplots.mapbox,n=0;n0){for(var r=0;r0}function u(t){var e={},r={};switch(t.type){case"circle":n.extendFlat(r,{"circle-radius":t.circle.radius,"circle-color":t.color,"circle-opacity":t.opacity});break;case"line":n.extendFlat(r,{"line-width":t.line.width,"line-color":t.color,"line-opacity":t.opacity,"line-dasharray":t.line.dash});break;case"fill":n.extendFlat(r,{"fill-color":t.color,"fill-outline-color":t.fill.outlinecolor,"fill-opacity":t.opacity});break;case"symbol":var i=t.symbol,o=a(i.textposition,i.iconsize);n.extendFlat(e,{"icon-image":i.icon+"-15","icon-size":i.iconsize/10,"text-field":i.text,"text-size":i.textfont.size,"text-anchor":o.anchor,"text-offset":o.offset,"symbol-placement":i.placement}),n.extendFlat(r,{"icon-color":t.color,"text-color":i.textfont.color,"text-opacity":t.opacity});break;case"raster":n.extendFlat(r,{"raster-fade-duration":0,"raster-opacity":t.opacity})}return{layout:e,paint:r}}l.update=function(t){this.visible?this.needsNewImage(t)?this.updateImage(t):this.needsNewSource(t)?(this.removeLayer(),this.updateSource(t),this.updateLayer(t)):this.needsNewLayer(t)?this.updateLayer(t):this.updateStyle(t):(this.updateSource(t),this.updateLayer(t)),this.visible=c(t)},l.needsNewImage=function(t){return this.subplot.map.getSource(this.idSource)&&"image"===this.sourceType&&"image"===t.sourcetype&&(this.source!==t.source||JSON.stringify(this.coordinates)!==JSON.stringify(t.coordinates))},l.needsNewSource=function(t){return this.sourceType!==t.sourcetype||JSON.stringify(this.source)!==JSON.stringify(t.source)||this.layerType!==t.type},l.needsNewLayer=function(t){return this.layerType!==t.type||this.below!==this.subplot.belowLookup["layout-"+this.index]},l.lookupBelow=function(){return this.subplot.belowLookup["layout-"+this.index]},l.updateImage=function(t){this.subplot.map.getSource(this.idSource).updateImage({url:t.source,coordinates:t.coordinates});var e=this.findFollowingMapboxLayerId(this.lookupBelow());null!==e&&this.subplot.map.moveLayer(this.idLayer,e)},l.updateSource=function(t){var e=this.subplot.map;if(e.getSource(this.idSource)&&e.removeSource(this.idSource),this.sourceType=t.sourcetype,this.source=t.source,c(t)){var r=function(t){var e,r=t.sourcetype,n=t.source,a={type:r};"geojson"===r?e="data":"vector"===r?e="string"==typeof n?"url":"tiles":"raster"===r?(e="tiles",a.tileSize=256):"image"===r&&(e="url",a.coordinates=t.coordinates);a[e]=n,t.sourceattribution&&(a.attribution=i(t.sourceattribution));return a}(t);e.addSource(this.idSource,r)}},l.findFollowingMapboxLayerId=function(t){if("traces"===t)for(var e=this.subplot.getMapLayers(),r=0;r1)for(r=0;r-1&&v(e.originalEvent,n,[r.xaxis],[r.yaxis],r.id,t),i.indexOf("event")>-1&&c.click(n,e.originalEvent)}}},_.updateFx=function(t){var e=this,r=e.map,n=e.gd;if(!e.isStatic){var a,o=t.dragmode;a=f(o)?function(t,r){(t.range={})[e.id]=[c([r.xmin,r.ymin]),c([r.xmax,r.ymax])]}:function(t,r,n){(t.lassoPoints={})[e.id]=n.filtered.map(c)};var s=e.dragOptions;e.dragOptions=i.extendDeep(s||{},{dragmode:t.dragmode,element:e.div,gd:n,plotinfo:{id:e.id,domain:t[e.id].domain,xaxis:e.xaxis,yaxis:e.yaxis,fillRangeItems:a},xaxes:[e.xaxis],yaxes:[e.yaxis],subplot:e.id}),r.off("click",e.onClickInPanHandler),p(o)||h(o)?(r.dragPan.disable(),r.on("zoomstart",e.clearSelect),e.dragOptions.prepFn=function(t,r,n){d(t,r,n,e.dragOptions,o)},l.init(e.dragOptions)):(r.dragPan.enable(),r.off("zoomstart",e.clearSelect),e.div.onmousedown=null,e.onClickInPanHandler=e.onClickInPanFn(e.dragOptions),r.on("click",e.onClickInPanHandler))}function c(t){var r=e.map.unproject(t);return[r.lng,r.lat]}},_.updateFramework=function(t){var e=t[this.id].domain,r=t._size,n=this.div.style;n.width=r.w*(e.x[1]-e.x[0])+"px",n.height=r.h*(e.y[1]-e.y[0])+"px",n.left=r.l+e.x[0]*r.w+"px",n.top=r.t+(1-e.y[1])*r.h+"px",this.xaxis._offset=r.l+e.x[0]*r.w,this.xaxis._length=r.w*(e.x[1]-e.x[0]),this.yaxis._offset=r.t+(1-e.y[1])*r.h,this.yaxis._length=r.h*(e.y[1]-e.y[0])},_.updateLayers=function(t){var e,r=t[this.id].layers,n=this.layerList;if(r.length!==n.length){for(e=0;e=e.width-20?(a["text-anchor"]="start",a.x=5):(a["text-anchor"]="end",a.x=e._paper.attr("width")-7),r.attr(a);var o=r.select(".js-link-to-tool"),s=r.select(".js-link-spacer"),l=r.select(".js-sourcelinks");t._context.showSources&&t._context.showSources(t),t._context.showLink&&function(t,e){e.text("");var r=e.append("a").attr({"xlink:xlink:href":"#",class:"link--impt link--embedview","font-weight":"bold"}).text(t._context.linkText+" "+String.fromCharCode(187));if(t._context.sendData)r.on("click",(function(){b.sendDataToCloud(t)}));else{var n=window.location.pathname.split("/"),i=window.location.search;r.attr({"xlink:xlink:show":"new","xlink:xlink:href":"/"+n[2].split(".")[0]+"/"+n[1]+i})}}(t,o),s.text(o.text()&&l.text()?" - ":"")}},b.sendDataToCloud=function(t){var e=(window.PLOTLYENV||{}).BASE_URL||t._context.plotlyServerURL;if(e){t.emit("plotly_beforeexport");var r=n.select(t).append("div").attr("id","hiddenform").style("display","none"),i=r.append("form").attr({action:e+"/external",method:"post",target:"_blank"});return i.append("input").attr({type:"text",name:"data"}).node().value=b.graphJson(t,!1,"keepdata"),i.node().submit(),r.remove(),t.emit("plotly_afterexport"),!1}};var T=["days","shortDays","months","shortMonths","periods","dateTime","date","time","decimal","thousands","grouping","currency"],k=["year","month","dayMonth","dayMonthYear"];function A(t,e){var r=t._context.locale;r||(r="en-US");var n=!1,i={};function a(t){for(var r=!0,a=0;a1&&z.length>1){for(s.getComponentMethod("grid","sizeDefaults")(c,l),o=0;o15&&z.length>15&&0===l.shapes.length&&0===l.images.length,b.linkSubplots(h,l,f,n),b.cleanPlot(h,l,f,n);var N=!(!n._has||!n._has("gl2d")),j=!(!l._has||!l._has("gl2d")),U=!(!n._has||!n._has("cartesian"))||N,V=!(!l._has||!l._has("cartesian"))||j;U&&!V?n._bgLayer.remove():V&&!U&&(l._shouldCreateBgLayer=!0),n._zoomlayer&&!t._dragging&&d({_fullLayout:n}),function(t,e){var r,n=[];e.meta&&(r=e._meta={meta:e.meta,layout:{meta:e.meta}});for(var i=0;i0){var f=1-2*s;n=Math.round(f*n),i=Math.round(f*i)}}var h=b.layoutAttributes.width.min,p=b.layoutAttributes.height.min;n1,m=!e.height&&Math.abs(r.height-i)>1;(m||d)&&(d&&(r.width=n),m&&(r.height=i)),t._initialAutoSize||(t._initialAutoSize={width:n,height:i}),b.sanitizeMargins(r)},b.supplyLayoutModuleDefaults=function(t,e,r,n){var i,a,o,l=s.componentsRegistry,c=e._basePlotModules,f=s.subplotsRegistry.cartesian;for(i in l)(o=l[i]).includeBasePlot&&o.includeBasePlot(t,e);for(var h in c.length||c.push(f),e._has("cartesian")&&(s.getComponentMethod("grid","contentDefaults")(t,e),f.finalizeSubplots(t,e)),e._subplots)e._subplots[h].sort(u.subplotSort);for(a=0;a1&&(r.l/=m,r.r/=m)}if(f){var g=(r.t+r.b)/f;g>1&&(r.t/=g,r.b/=g)}var v=void 0!==r.xl?r.xl:r.x,y=void 0!==r.xr?r.xr:r.x,x=void 0!==r.yt?r.yt:r.y,_=void 0!==r.yb?r.yb:r.y;h[e]={l:{val:v,size:r.l+d},r:{val:y,size:r.r+d},b:{val:_,size:r.b+d},t:{val:x,size:r.t+d}},p[e]=1}else delete h[e],delete p[e];if(!n._replotting)return b.doAutoMargin(t)}},b.doAutoMargin=function(t){var e=t._fullLayout,r=e.width,n=e.height;e._size||(e._size={}),C(e);var i=e._size,a=e.margin,l=u.extendFlat({},i),c=a.l,f=a.r,h=a.t,d=a.b,m=e._pushmargin,g=e._pushmarginIds;if(!1!==e.margin.autoexpand){for(var v in m)g[v]||delete m[v];for(var y in m.base={l:{val:0,size:c},r:{val:1,size:f},t:{val:1,size:h},b:{val:0,size:d}},m){var x=m[y].l||{},_=m[y].b||{},w=x.val,T=x.size,k=_.val,A=_.size;for(var M in m){if(o(T)&&m[M].r){var S=m[M].r.val,E=m[M].r.size;if(S>w){var L=(T*S+(E-r)*w)/(S-w),P=(E*(1-w)+(T-r)*(1-S))/(S-w);L+P>c+f&&(c=L,f=P)}}if(o(A)&&m[M].t){var I=m[M].t.val,O=m[M].t.size;if(I>k){var z=(A*I+(O-n)*k)/(I-k),D=(O*(1-k)+(A-n)*(1-I))/(I-k);z+D>d+h&&(d=z,h=D)}}}}}var R=u.constrain(r-a.l-a.r,2,64),F=u.constrain(n-a.t-a.b,2,64),B=Math.max(0,r-R),N=Math.max(0,n-F);if(B){var j=(c+f)/B;j>1&&(c/=j,f/=j)}if(N){var U=(d+h)/N;U>1&&(d/=U,h/=U)}if(i.l=Math.round(c),i.r=Math.round(f),i.t=Math.round(h),i.b=Math.round(d),i.p=Math.round(a.pad),i.w=Math.round(r)-i.l-i.r,i.h=Math.round(n)-i.t-i.b,!e._replotting&&b.didMarginChange(l,i)){"_redrawFromAutoMarginCount"in e?e._redrawFromAutoMarginCount++:e._redrawFromAutoMarginCount=1;var V=3*(1+Object.keys(g).length);if(e._redrawFromAutoMarginCount0&&(t._transitioningWithDuration=!0),t._transitionData._interruptCallbacks.push((function(){n=!0})),r.redraw&&t._transitionData._interruptCallbacks.push((function(){return s.call("redraw",t)})),t._transitionData._interruptCallbacks.push((function(){t.emit("plotly_transitioninterrupted",[])}));var a=0,o=0;function l(){return a++,function(){o++,n||o!==a||function(e){if(!t._transitionData)return;(function(t){if(t)for(;t.length;)t.shift()})(t._transitionData._interruptCallbacks),Promise.resolve().then((function(){if(r.redraw)return s.call("redraw",t)})).then((function(){t._transitioning=!1,t._transitioningWithDuration=!1,t.emit("plotly_transitioned",[])})).then(e)}(i)}}r.runFn(l),setTimeout(l())}))}],a=u.syncOrAsync(i,t);return a&&a.then||(a=Promise.resolve()),a.then((function(){return t}))}b.didMarginChange=function(t,e){for(var r=0;r1)return!0}return!1},b.graphJson=function(t,e,r,n,i,a){(i&&e&&!t._fullData||i&&!e&&!t._fullLayout)&&b.supplyDefaults(t);var o=i?t._fullData:t.data,s=i?t._fullLayout:t.layout,l=(t._transitionData||{})._frames;function c(t,e){if("function"==typeof t)return e?"_function_":null;if(u.isPlainObject(t)){var n,i={};return Object.keys(t).sort().forEach((function(a){if(-1===["_","["].indexOf(a.charAt(0)))if("function"!=typeof t[a]){if("keepdata"===r){if("src"===a.substr(a.length-3))return}else if("keepstream"===r){if("string"==typeof(n=t[a+"src"])&&n.indexOf(":")>0&&!u.isPlainObject(t.stream))return}else if("keepall"!==r&&"string"==typeof(n=t[a+"src"])&&n.indexOf(":")>0)return;i[a]=c(t[a],e)}else e&&(i[a]="_function")})),i}return Array.isArray(t)?t.map((function(t){return c(t,e)})):u.isTypedArray(t)?u.simpleMap(t,u.identity):u.isJSDate(t)?u.ms2DateTimeLocal(+t):t}var f={data:(o||[]).map((function(t){var r=c(t);return e&&delete r.fit,r}))};if(!e&&(f.layout=c(s),i)){var h=s._size;f.layout.computed={margin:{b:h.b,l:h.l,r:h.r,t:h.t}}}return l&&(f.frames=c(l)),a&&(f.config=c(t._context,!0)),"object"===n?f:JSON.stringify(f)},b.modifyFrames=function(t,e){var r,n,i,a=t._transitionData._frames,o=t._transitionData._frameHash;for(r=0;r=0;a--)if(s[a].enabled){r._indexToPoints=s[a]._indexToPoints;break}n&&n.calc&&(o=n.calc(t,r))}Array.isArray(o)&&o[0]||(o=[{x:h,y:h}]),o[0].t||(o[0].t={}),o[0].trace=r,d[e]=o}}for(z(o,c,f),i=0;i1e-10?t:0}function h(t,e,r){e=e||0,r=r||0;for(var n=t.length,i=new Array(n),a=0;a0?r:1/0})),i=n.mod(r+1,e.length);return[e[r],e[i]]},findIntersectionXY:c,findXYatLength:function(t,e,r,n){var i=-e*r,a=e*e+1,o=2*(e*i-r),s=i*i+r*r-t*t,l=Math.sqrt(o*o-4*a*s),c=(-o+l)/(2*a),u=(-o-l)/(2*a);return[[c,e*c+i+n],[u,e*u+i+n]]},clampTiny:f,pathPolygon:function(t,e,r,n,i,a){return"M"+h(u(t,e,r,n),i,a).join("L")},pathPolygonAnnulus:function(t,e,r,n,i,a,o){var s,l;t=90||s>90&&l>=450?1:u<=0&&h<=0?0:Math.max(u,h);e=s<=180&&l>=180||s>180&&l>=540?-1:c>=0&&f>=0?0:Math.min(c,f);r=s<=270&&l>=270||s>270&&l>=630?-1:u>=0&&h>=0?0:Math.min(u,h);n=l>=360?1:c<=0&&f<=0?0:Math.max(c,f);return[e,r,n,i]}(p),b=x[2]-x[0],_=x[3]-x[1],w=h/f,T=Math.abs(_/b);w>T?(d=f,y=(h-(m=f*T))/n.h/2,g=[o[0],o[1]],v=[s[0]+y,s[1]-y]):(m=h,y=(f-(d=h/T))/n.w/2,g=[o[0]+y,o[1]-y],v=[s[0],s[1]]),this.xLength2=d,this.yLength2=m,this.xDomain2=g,this.yDomain2=v;var k,A=this.xOffset2=n.l+n.w*g[0],M=this.yOffset2=n.t+n.h*(1-v[1]),S=this.radius=d/b,E=this.innerRadius=this.getHole(e)*S,L=this.cx=A-S*x[0],C=this.cy=M+S*x[3],P=this.cxx=L-A,I=this.cyy=C-M,O=i.side;"counterclockwise"===O?(k=O,O="top"):"clockwise"===O&&(k=O,O="bottom"),this.radialAxis=this.mockAxis(t,e,i,{_id:"x",side:O,_trueSide:k,domain:[E/n.w,S/n.w]}),this.angularAxis=this.mockAxis(t,e,a,{side:"right",domain:[0,Math.PI],autorange:!1}),this.doAutoRange(t,e),this.updateAngularAxis(t,e),this.updateRadialAxis(t,e),this.updateRadialAxisTitle(t,e),this.xaxis=this.mockCartesianAxis(t,e,{_id:"x",domain:g}),this.yaxis=this.mockCartesianAxis(t,e,{_id:"y",domain:v});var z=this.pathSubplot();this.clipPaths.forTraces.select("path").attr("d",z).attr("transform",l(P,I)),r.frontplot.attr("transform",l(A,M)).call(u.setClipUrl,this._hasClipOnAxisFalse?null:this.clipIds.forTraces,this.gd),r.bg.attr("d",z).attr("transform",l(L,C)).call(c.fill,e.bgcolor)},N.mockAxis=function(t,e,r,n){var i=o.extendFlat({},r,n);return d(i,e,t),i},N.mockCartesianAxis=function(t,e,r){var n=this,i=n.isSmith,a=r._id,s=o.extendFlat({type:"linear"},r);p(s,t);var l={x:[0,2],y:[1,3]};return s.setRange=function(){var t=n.sectorBBox,r=l[a],i=n.radialAxis._rl,o=(i[1]-i[0])/(1-n.getHole(e));s.range=[t[r[0]]*o,t[r[1]]*o]},s.isPtWithinRange="x"!==a||i?function(){return!0}:function(t){return n.isPtInside(t)},s.setRange(),s.setScale(),s},N.doAutoRange=function(t,e){var r=this.gd,n=this.radialAxis,i=this.getRadial(e);m(r,n);var a=n.range;i.range=a.slice(),i._input.range=a.slice(),n._rl=[n.r2l(a[0],null,"gregorian"),n.r2l(a[1],null,"gregorian")]},N.updateRadialAxis=function(t,e){var r=this,n=r.gd,i=r.layers,a=r.radius,u=r.innerRadius,f=r.cx,p=r.cy,d=r.getRadial(e),m=D(r.getSector(e)[0],360),g=r.radialAxis,v=u90&&m<=270&&(g.tickangle=180);var x=y?function(t){var e=O(r,C([t.x,0]));return l(e[0]-f,e[1]-p)}:function(t){return l(g.l2p(t.x)+u,0)},b=y?function(t){return I(r,t.x,-1/0,1/0)}:function(t){return r.pathArc(g.r2p(t.x)+u)},_=j(d);if(r.radialTickLayout!==_&&(i["radial-axis"].selectAll(".xtick").remove(),r.radialTickLayout=_),v){g.setScale();var w=0,T=y?(g.tickvals||[]).filter((function(t){return t>=0})).map((function(t){return h.tickText(g,t,!0,!1)})):h.calcTicks(g),k=y?T:h.clipEnds(g,T),A=h.getTickSigns(g)[2];y&&(("top"===g.ticks&&"bottom"===g.side||"bottom"===g.ticks&&"top"===g.side)&&(A=-A),"top"===g.ticks&&"top"===g.side&&(w=-g.ticklen),"bottom"===g.ticks&&"bottom"===g.side&&(w=g.ticklen)),h.drawTicks(n,g,{vals:T,layer:i["radial-axis"],path:h.makeTickPath(g,0,A),transFn:x,crisp:!1}),h.drawGrid(n,g,{vals:k,layer:i["radial-grid"],path:b,transFn:o.noop,crisp:!1}),h.drawLabels(n,g,{vals:T,layer:i["radial-axis"],transFn:x,labelFns:h.makeLabelFns(g,w)})}var M=r.radialAxisAngle=r.vangles?F(U(R(d.angle),r.vangles)):d.angle,S=l(f,p),E=S+s(-M);V(i["radial-axis"],v&&(d.showticklabels||d.ticks),{transform:E}),V(i["radial-grid"],v&&d.showgrid,{transform:y?"":S}),V(i["radial-line"].select("line"),v&&d.showline,{x1:y?-a:u,y1:0,x2:a,y2:0,transform:E}).attr("stroke-width",d.linewidth).call(c.stroke,d.linecolor)},N.updateRadialAxisTitle=function(t,e,r){if(!this.isSmith){var n=this.gd,i=this.radius,a=this.cx,o=this.cy,s=this.getRadial(e),l=this.id+"title",c=0;if(s.title){var f=u.bBox(this.layers["radial-axis"].node()).height,h=s.title.font.size,p=s.side;c="top"===p?h:"counterclockwise"===p?-(f+.4*h):f+.8*h}var d=void 0!==r?r:this.radialAxisAngle,m=R(d),g=Math.cos(m),v=Math.sin(m),y=a+i/2*g+c*v,b=o-i/2*v+c*g;this.layers["radial-axis-title"]=x.draw(n,l,{propContainer:s,propName:this.id+".radialaxis.title",placeholder:z(n,"Click to enter radial axis title"),attributes:{x:y,y:b,"text-anchor":"middle"},transform:{rotate:-d}})}},N.updateAngularAxis=function(t,e){var r=this,n=r.gd,i=r.layers,a=r.radius,u=r.innerRadius,f=r.cx,p=r.cy,d=r.getAngular(e),m=r.angularAxis,g=r.isSmith;g||(r.fillViewInitialKey("angularaxis.rotation",d.rotation),m.setGeometry(),m.setScale());var v=g?function(t){var e=O(r,C([0,t.x]));return Math.atan2(e[0]-f,e[1]-p)-Math.PI/2}:function(t){return m.t2g(t.x)};"linear"===m.type&&"radians"===m.thetaunit&&(m.tick0=F(m.tick0),m.dtick=F(m.dtick));var y=function(t){return l(f+a*Math.cos(t),p-a*Math.sin(t))},x=g?function(t){var e=O(r,C([0,t.x]));return l(e[0],e[1])}:function(t){return y(v(t))},b=g?function(t){var e=O(r,C([0,t.x])),n=Math.atan2(e[0]-f,e[1]-p)-Math.PI/2;return l(e[0],e[1])+s(-F(n))}:function(t){var e=v(t);return y(e)+s(-F(e))},_=g?function(t){return P(r,t.x,0,1/0)}:function(t){var e=v(t),r=Math.cos(e),n=Math.sin(e);return"M"+[f+u*r,p-u*n]+"L"+[f+a*r,p-a*n]},w=h.makeLabelFns(m,0).labelStandoff,T={xFn:function(t){var e=v(t);return Math.cos(e)*w},yFn:function(t){var e=v(t),r=Math.sin(e)>0?.2:1;return-Math.sin(e)*(w+t.fontSize*r)+Math.abs(Math.cos(e))*(t.fontSize*M)},anchorFn:function(t){var e=v(t),r=Math.cos(e);return Math.abs(r)<.1?"middle":r>0?"start":"end"},heightFn:function(t,e,r){var n=v(t);return-.5*(1+Math.sin(n))*r}},k=j(d);r.angularTickLayout!==k&&(i["angular-axis"].selectAll("."+m._id+"tick").remove(),r.angularTickLayout=k);var A,S=g?[1/0].concat(m.tickvals||[]).map((function(t){return h.tickText(m,t,!0,!1)})):h.calcTicks(m);if(g&&(S[0].text="\u221e",S[0].fontSize*=1.75),"linear"===e.gridshape?(A=S.map(v),o.angleDelta(A[0],A[1])<0&&(A=A.slice().reverse())):A=null,r.vangles=A,"category"===m.type&&(S=S.filter((function(t){return o.isAngleInsideSector(v(t),r.sectorInRad)}))),m.visible){var E="inside"===m.ticks?-1:1,L=(m.linewidth||1)/2;h.drawTicks(n,m,{vals:S,layer:i["angular-axis"],path:"M"+E*L+",0h"+E*m.ticklen,transFn:b,crisp:!1}),h.drawGrid(n,m,{vals:S,layer:i["angular-grid"],path:_,transFn:o.noop,crisp:!1}),h.drawLabels(n,m,{vals:S,layer:i["angular-axis"],repositionOnUpdate:!0,transFn:x,labelFns:T})}V(i["angular-line"].select("path"),d.showline,{d:r.pathSubplot(),transform:l(f,p)}).attr("stroke-width",d.linewidth).call(c.stroke,d.linecolor)},N.updateFx=function(t,e){this.gd._context.staticPlot||(!this.isSmith&&(this.updateAngularDrag(t),this.updateRadialDrag(t,e,0),this.updateRadialDrag(t,e,1)),this.updateHoverAndMainDrag(t))},N.updateHoverAndMainDrag=function(t){var e,r,s=this,c=s.isSmith,u=s.gd,f=s.layers,h=t._zoomlayer,p=S.MINZOOM,d=S.OFFEDGE,m=s.radius,x=s.innerRadius,T=s.cx,k=s.cy,A=s.cxx,M=s.cyy,L=s.sectorInRad,C=s.vangles,P=s.radialAxis,I=E.clampTiny,O=E.findXYatLength,z=E.findEnclosingVertexAngles,D=S.cornerHalfWidth,R=S.cornerLen/2,F=g.makeDragger(f,"path","maindrag",!1===t.dragmode?"none":"crosshair");n.select(F).attr("d",s.pathSubplot()).attr("transform",l(T,k)),F.onmousemove=function(t){y.hover(u,t,s.id),u._fullLayout._lasthover=F,u._fullLayout._hoversubplot=s.id},F.onmouseout=function(t){u._dragging||v.unhover(u,t)};var B,N,j,U,V,H,q,G,Y,W={element:F,gd:u,subplot:s.id,plotinfo:{id:s.id,xaxis:s.xaxis,yaxis:s.yaxis},xaxes:[s.xaxis],yaxes:[s.yaxis]};function X(t,e){return Math.sqrt(t*t+e*e)}function Z(t,e){return X(t-A,e-M)}function J(t,e){return Math.atan2(M-e,t-A)}function K(t,e){return[t*Math.cos(e),t*Math.sin(-e)]}function Q(t,e){if(0===t)return s.pathSector(2*D);var r=R/t,n=e-r,i=e+r,a=Math.max(0,Math.min(t,m)),o=a-D,l=a+D;return"M"+K(o,n)+"A"+[o,o]+" 0,0,0 "+K(o,i)+"L"+K(l,i)+"A"+[l,l]+" 0,0,1 "+K(l,n)+"Z"}function $(t,e,r){if(0===t)return s.pathSector(2*D);var n,i,a=K(t,e),o=K(t,r),l=I((a[0]+o[0])/2),c=I((a[1]+o[1])/2);if(l&&c){var u=c/l,f=-1/u,h=O(D,u,l,c);n=O(R,f,h[0][0],h[0][1]),i=O(R,f,h[1][0],h[1][1])}else{var p,d;c?(p=R,d=D):(p=D,d=R),n=[[l-p,c-d],[l+p,c-d]],i=[[l-p,c+d],[l+p,c+d]]}return"M"+n.join("L")+"L"+i.reverse().join("L")+"Z"}function tt(t,e){return e=Math.max(Math.min(e,m),x),tp?(t-1&&1===t&&_(e,u,[s.xaxis],[s.yaxis],s.id,W),r.indexOf("event")>-1&&y.click(u,e,s.id)}W.prepFn=function(t,n,a){var l=u._fullLayout.dragmode,f=F.getBoundingClientRect();u._fullLayout._calcInverseTransform(u);var p=u._fullLayout._invTransform;e=u._fullLayout._invScaleX,r=u._fullLayout._invScaleY;var d=o.apply3DTransform(p)(n-f.left,a-f.top);if(B=d[0],N=d[1],C){var v=E.findPolygonOffset(m,L[0],L[1],C);B+=A+v[0],N+=M+v[1]}switch(l){case"zoom":W.clickFn=st,c||(W.moveFn=C?it:rt,W.doneFn=at,function(){j=null,U=null,V=s.pathSubplot(),H=!1;var t=u._fullLayout[s.id];q=i(t.bgcolor).getLuminance(),(G=g.makeZoombox(h,q,T,k,V)).attr("fill-rule","evenodd"),Y=g.makeCorners(h,T,k),w(u)}());break;case"select":case"lasso":b(t,n,a,W,l)}},v.init(W)},N.updateRadialDrag=function(t,e,r){var i=this,c=i.gd,u=i.layers,f=i.radius,h=i.innerRadius,p=i.cx,d=i.cy,m=i.radialAxis,y=S.radialDragBoxSize,x=y/2;if(m.visible){var b,_,T,M=R(i.radialAxisAngle),E=m._rl,L=E[0],C=E[1],P=E[r],I=.75*(E[1]-E[0])/(1-i.getHole(e))/f;r?(b=p+(f+x)*Math.cos(M),_=d-(f+x)*Math.sin(M),T="radialdrag"):(b=p+(h-x)*Math.cos(M),_=d-(h-x)*Math.sin(M),T="radialdrag-inner");var O,z,D,B=g.makeRectDragger(u,T,"crosshair",-x,-x,y,y),N={element:B,gd:c};!1===t.dragmode&&(N.dragmode=!1),V(n.select(B),m.visible&&h0==(r?D>L:Dn?function(t){return t<=0}:function(t){return t>=0};t.c2g=function(r){var n=t.c2l(r)-e;return(s(n)?n:0)+o},t.g2c=function(r){return t.l2c(r+e-o)},t.g2p=function(t){return t*a},t.c2p=function(e){return t.g2p(t.c2g(e))}}}(t,e);break;case"angularaxis":!function(t,e){var r=t.type;if("linear"===r){var i=t.d2c,s=t.c2d;t.d2c=function(t,e){return function(t,e){return"degrees"===e?a(t):t}(i(t),e)},t.c2d=function(t,e){return s(function(t,e){return"degrees"===e?o(t):t}(t,e))}}t.makeCalcdata=function(e,i){var a,o,s=e[i],l=e._length,c=function(r){return t.d2c(r,e.thetaunit)};if(s){if(n.isTypedArray(s)&&"linear"===r){if(l===s.length)return s;if(s.subarray)return s.subarray(0,l)}for(a=new Array(l),o=0;o0?1:0}function i(t){var e=t[0],r=t[1];if(!isFinite(e)||!isFinite(r))return[1,0];var n=(e+1)*(e+1)+r*r;return[(e*e+r*r-1)/n,2*r/n]}function a(t,e){var r=e[0],n=e[1];return[r*t.radius+t.cx,-n*t.radius+t.cy]}function o(t,e){return e*t.radius}e.exports={smith:i,reactanceArc:function(t,e,r,n){var s=a(t,i([r,e])),l=s[0],c=s[1],u=a(t,i([n,e])),f=u[0],h=u[1];if(0===e)return["M"+l+","+c,"L"+f+","+h].join(" ");var p=o(t,1/Math.abs(e));return["M"+l+","+c,"A"+p+","+p+" 0 0,"+(e<0?1:0)+" "+f+","+h].join(" ")},resistanceArc:function(t,e,r,s){var l=o(t,1/(e+1)),c=a(t,i([e,r])),u=c[0],f=c[1],h=a(t,i([e,s])),p=h[0],d=h[1];if(n(r)!==n(s)){var m=a(t,i([e,0]));return["M"+u+","+f,"A"+l+","+l+" 0 0,"+(00){for(var n=[],i=0;i=u&&(h.min=0,d.min=0,g.min=0,t.aaxis&&delete t.aaxis.min,t.baxis&&delete t.baxis.min,t.caxis&&delete t.caxis.min)}function m(t,e,r,n){var i=h[e._name];function o(r,n){return a.coerce(t,e,i,r,n)}o("uirevision",n.uirevision),e.type="linear";var p=o("color"),d=p!==i.color.dflt?p:r.font.color,m=e._name.charAt(0).toUpperCase(),g="Component "+m,v=o("title.text",g);e._hovertitle=v===g?v:m,a.coerceFont(o,"title.font",{family:r.font.family,size:a.bigFont(r.font.size),color:d}),o("min"),u(t,e,o,"linear"),l(t,e,o,"linear"),s(t,e,o,"linear"),c(t,e,o,{outerTicks:!0}),o("showticklabels")&&(a.coerceFont(o,"tickfont",{family:r.font.family,size:r.font.size,color:d}),o("tickangle"),o("tickformat")),f(t,e,o,{dfltColor:p,bgColor:r.bgColor,blend:60,showLine:!0,showGrid:!0,noZeroLine:!0,attributes:i}),o("hoverformat"),o("layer")}e.exports=function(t,e,r){o(t,e,r,{type:"ternary",attributes:h,handleDefaults:d,font:e.font,paper_bgcolor:e.paper_bgcolor})}},{"../../components/color":366,"../../lib":503,"../../plot_api/plot_template":543,"../cartesian/line_grid_defaults":571,"../cartesian/prefix_suffix_defaults":573,"../cartesian/tick_label_defaults":578,"../cartesian/tick_mark_defaults":579,"../cartesian/tick_value_defaults":580,"../subplot_defaults":632,"./layout_attributes":635}],637:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("tinycolor2"),a=t("../../registry"),o=t("../../lib"),s=o.strTranslate,l=o._,c=t("../../components/color"),u=t("../../components/drawing"),f=t("../cartesian/set_convert"),h=t("../../lib/extend").extendFlat,p=t("../plots"),d=t("../cartesian/axes"),m=t("../../components/dragelement"),g=t("../../components/fx"),v=t("../../components/dragelement/helpers"),y=v.freeMode,x=v.rectMode,b=t("../../components/titles"),_=t("../cartesian/select").prepSelect,w=t("../cartesian/select").selectOnClick,T=t("../cartesian/select").clearSelect,k=t("../cartesian/select").clearSelectionsCache,A=t("../cartesian/constants");function M(t,e){this.id=t.id,this.graphDiv=t.graphDiv,this.init(e),this.makeFramework(e),this.aTickLayout=null,this.bTickLayout=null,this.cTickLayout=null}e.exports=M;var S=M.prototype;S.init=function(t){this.container=t._ternarylayer,this.defs=t._defs,this.layoutId=t._uid,this.traceHash={},this.layers={}},S.plot=function(t,e){var r=e[this.id],n=e._size;this._hasClipOnAxisFalse=!1;for(var i=0;iE*b?i=(a=b)*E:a=(i=x)/E,o=v*i/x,l=y*a/b,r=e.l+e.w*m-i/2,n=e.t+e.h*(1-g)-a/2,p.x0=r,p.y0=n,p.w=i,p.h=a,p.sum=_,p.xaxis={type:"linear",range:[w+2*k-_,_-w-2*T],domain:[m-o/2,m+o/2],_id:"x"},f(p.xaxis,p.graphDiv._fullLayout),p.xaxis.setScale(),p.xaxis.isPtWithinRange=function(t){return t.a>=p.aaxis.range[0]&&t.a<=p.aaxis.range[1]&&t.b>=p.baxis.range[1]&&t.b<=p.baxis.range[0]&&t.c>=p.caxis.range[1]&&t.c<=p.caxis.range[0]},p.yaxis={type:"linear",range:[w,_-T-k],domain:[g-l/2,g+l/2],_id:"y"},f(p.yaxis,p.graphDiv._fullLayout),p.yaxis.setScale(),p.yaxis.isPtWithinRange=function(){return!0};var A=p.yaxis.domain[0],M=p.aaxis=h({},t.aaxis,{range:[w,_-T-k],side:"left",tickangle:(+t.aaxis.tickangle||0)-30,domain:[A,A+l*E],anchor:"free",position:0,_id:"y",_length:i});f(M,p.graphDiv._fullLayout),M.setScale();var S=p.baxis=h({},t.baxis,{range:[_-w-k,T],side:"bottom",domain:p.xaxis.domain,anchor:"free",position:0,_id:"x",_length:i});f(S,p.graphDiv._fullLayout),S.setScale();var L=p.caxis=h({},t.caxis,{range:[_-w-T,k],side:"right",tickangle:(+t.caxis.tickangle||0)+30,domain:[A,A+l*E],anchor:"free",position:0,_id:"y",_length:i});f(L,p.graphDiv._fullLayout),L.setScale();var C="M"+r+","+(n+a)+"h"+i+"l-"+i/2+",-"+a+"Z";p.clipDef.select("path").attr("d",C),p.layers.plotbg.select("path").attr("d",C);var P="M0,"+a+"h"+i+"l-"+i/2+",-"+a+"Z";p.clipDefRelative.select("path").attr("d",P);var I=s(r,n);p.plotContainer.selectAll(".scatterlayer,.maplayer").attr("transform",I),p.clipDefRelative.select("path").attr("transform",null);var O=s(r-S._offset,n+a);p.layers.baxis.attr("transform",O),p.layers.bgrid.attr("transform",O);var z=s(r+i/2,n)+"rotate(30)"+s(0,-M._offset);p.layers.aaxis.attr("transform",z),p.layers.agrid.attr("transform",z);var D=s(r+i/2,n)+"rotate(-30)"+s(0,-L._offset);p.layers.caxis.attr("transform",D),p.layers.cgrid.attr("transform",D),p.drawAxes(!0),p.layers.aline.select("path").attr("d",M.showline?"M"+r+","+(n+a)+"l"+i/2+",-"+a:"M0,0").call(c.stroke,M.linecolor||"#000").style("stroke-width",(M.linewidth||0)+"px"),p.layers.bline.select("path").attr("d",S.showline?"M"+r+","+(n+a)+"h"+i:"M0,0").call(c.stroke,S.linecolor||"#000").style("stroke-width",(S.linewidth||0)+"px"),p.layers.cline.select("path").attr("d",L.showline?"M"+(r+i/2)+","+n+"l"+i/2+","+a:"M0,0").call(c.stroke,L.linecolor||"#000").style("stroke-width",(L.linewidth||0)+"px"),p.graphDiv._context.staticPlot||p.initInteractions(),u.setClipUrl(p.layers.frontplot,p._hasClipOnAxisFalse?null:p.clipId,p.graphDiv)},S.drawAxes=function(t){var e=this.graphDiv,r=this.id.substr(7)+"title",n=this.layers,i=this.aaxis,a=this.baxis,o=this.caxis;if(this.drawAx(i),this.drawAx(a),this.drawAx(o),t){var s=Math.max(i.showticklabels?i.tickfont.size/2:0,(o.showticklabels?.75*o.tickfont.size:0)+("outside"===o.ticks?.87*o.ticklen:0)),c=(a.showticklabels?a.tickfont.size:0)+("outside"===a.ticks?a.ticklen:0)+3;n["a-title"]=b.draw(e,"a"+r,{propContainer:i,propName:this.id+".aaxis.title",placeholder:l(e,"Click to enter Component A title"),attributes:{x:this.x0+this.w/2,y:this.y0-i.title.font.size/3-s,"text-anchor":"middle"}}),n["b-title"]=b.draw(e,"b"+r,{propContainer:a,propName:this.id+".baxis.title",placeholder:l(e,"Click to enter Component B title"),attributes:{x:this.x0-c,y:this.y0+this.h+.83*a.title.font.size+c,"text-anchor":"middle"}}),n["c-title"]=b.draw(e,"c"+r,{propContainer:o,propName:this.id+".caxis.title",placeholder:l(e,"Click to enter Component C title"),attributes:{x:this.x0+this.w+c,y:this.y0+this.h+.83*o.title.font.size+c,"text-anchor":"middle"}})}},S.drawAx=function(t){var e,r=this.graphDiv,n=t._name,i=n.charAt(0),a=t._id,s=this.layers[n],l=i+"tickLayout",c=(e=t).ticks+String(e.ticklen)+String(e.showticklabels);this[l]!==c&&(s.selectAll("."+a+"tick").remove(),this[l]=c),t.setScale();var u=d.calcTicks(t),f=d.clipEnds(t,u),h=d.makeTransTickFn(t),p=d.getTickSigns(t)[2],m=o.deg2rad(30),g=p*(t.linewidth||1)/2,v=p*t.ticklen,y=this.w,x=this.h,b="b"===i?"M0,"+g+"l"+Math.sin(m)*v+","+Math.cos(m)*v:"M"+g+",0l"+Math.cos(m)*v+","+-Math.sin(m)*v,_={a:"M0,0l"+x+",-"+y/2,b:"M0,0l-"+y/2+",-"+x,c:"M0,0l-"+x+","+y/2}[i];d.drawTicks(r,t,{vals:"inside"===t.ticks?f:u,layer:s,path:b,transFn:h,crisp:!1}),d.drawGrid(r,t,{vals:f,layer:this.layers[i+"grid"],path:_,transFn:h,crisp:!1}),d.drawLabels(r,t,{vals:u,layer:s,transFn:h,labelFns:d.makeLabelFns(t,0,30)})};var L=A.MINZOOM/2+.87,C="m-0.87,.5h"+L+"v3h-"+(L+5.2)+"l"+(L/2+2.6)+",-"+(.87*L+4.5)+"l2.6,1.5l-"+L/2+","+.87*L+"Z",P="m0.87,.5h-"+L+"v3h"+(L+5.2)+"l-"+(L/2+2.6)+",-"+(.87*L+4.5)+"l-2.6,1.5l"+L/2+","+.87*L+"Z",I="m0,1l"+L/2+","+.87*L+"l2.6,-1.5l-"+(L/2+2.6)+",-"+(.87*L+4.5)+"l-"+(L/2+2.6)+","+(.87*L+4.5)+"l2.6,1.5l"+L/2+",-"+.87*L+"Z",O=!0;function z(t){n.select(t).selectAll(".zoombox,.js-zoombox-backdrop,.js-zoombox-menu,.zoombox-corners").remove()}S.clearSelect=function(){k(this.dragOptions),T(this.dragOptions.gd)},S.initInteractions=function(){var t,e,r,n,f,h,p,d,v,b,T,k,M=this,S=M.layers.plotbg.select("path").node(),L=M.graphDiv,D=L._fullLayout._zoomlayer;function R(t){var e={};return e[M.id+".aaxis.min"]=t.a,e[M.id+".baxis.min"]=t.b,e[M.id+".caxis.min"]=t.c,e}function F(t,e){var r=L._fullLayout.clickmode;z(L),2===t&&(L.emit("plotly_doubleclick",null),a.call("_guiRelayout",L,R({a:0,b:0,c:0}))),r.indexOf("select")>-1&&1===t&&w(e,L,[M.xaxis],[M.yaxis],M.id,M.dragOptions),r.indexOf("event")>-1&&g.click(L,e,M.id)}function B(t,e){return 1-e/M.h}function N(t,e){return 1-(t+(M.h-e)/Math.sqrt(3))/M.w}function j(t,e){return(t-(M.h-e)/Math.sqrt(3))/M.w}function U(i,a){var o=r+i*t,s=n+a*e,l=Math.max(0,Math.min(1,B(0,n),B(0,s))),c=Math.max(0,Math.min(1,N(r,n),N(o,s))),u=Math.max(0,Math.min(1,j(r,n),j(o,s))),m=(l/2+u)*M.w,g=(1-l/2-c)*M.w,y=(m+g)/2,x=g-m,_=(1-l)*M.h,w=_-x/E;x.2?"rgba(0,0,0,0.4)":"rgba(255,255,255,0.3)").duration(200),k.transition().style("opacity",1).duration(200),b=!0),L.emit("plotly_relayouting",R(p))}function V(){z(L),p!==f&&(a.call("_guiRelayout",L,R(p)),O&&L.data&&L._context.showTips&&(o.notifier(l(L,"Double-click to zoom back out"),"long"),O=!1))}function H(t,e){var r=t/M.xaxis._m,n=e/M.yaxis._m,i=[(p={a:f.a-n,b:f.b+(r+n)/2,c:f.c-(r-n)/2}).a,p.b,p.c].sort(o.sorterAsc),a=i.indexOf(p.a),l=i.indexOf(p.b),c=i.indexOf(p.c);i[0]<0&&(i[1]+i[0]/2<0?(i[2]+=i[0]+i[1],i[0]=i[1]=0):(i[2]+=i[0]/2,i[1]+=i[0]/2,i[0]=0),p={a:i[a],b:i[l],c:i[c]},e=(f.a-p.a)*M.yaxis._m,t=(f.c-p.c-f.b+p.b)*M.xaxis._m);var h=s(M.x0+t,M.y0+e);M.plotContainer.selectAll(".scatterlayer,.maplayer").attr("transform",h);var d=s(-t,-e);M.clipDefRelative.select("path").attr("transform",d),M.aaxis.range=[p.a,M.sum-p.b-p.c],M.baxis.range=[M.sum-p.a-p.c,p.b],M.caxis.range=[M.sum-p.a-p.b,p.c],M.drawAxes(!1),M._hasClipOnAxisFalse&&M.plotContainer.select(".scatterlayer").selectAll(".trace").call(u.hideOutsideRangePoints,M),L.emit("plotly_relayouting",R(p))}function q(){a.call("_guiRelayout",L,R(p))}this.dragOptions={element:S,gd:L,plotinfo:{id:M.id,domain:L._fullLayout[M.id].domain,xaxis:M.xaxis,yaxis:M.yaxis},subplot:M.id,prepFn:function(a,l,u){M.dragOptions.xaxes=[M.xaxis],M.dragOptions.yaxes=[M.yaxis],t=L._fullLayout._invScaleX,e=L._fullLayout._invScaleY;var m=M.dragOptions.dragmode=L._fullLayout.dragmode;y(m)?M.dragOptions.minDrag=1:M.dragOptions.minDrag=void 0,"zoom"===m?(M.dragOptions.moveFn=U,M.dragOptions.clickFn=F,M.dragOptions.doneFn=V,function(t,e,a){var l=S.getBoundingClientRect();r=e-l.left,n=a-l.top,L._fullLayout._calcInverseTransform(L);var u=L._fullLayout._invTransform,m=o.apply3DTransform(u)(r,n);r=m[0],n=m[1],f={a:M.aaxis.range[0],b:M.baxis.range[1],c:M.caxis.range[1]},p=f,h=M.aaxis.range[1]-f.a,d=i(M.graphDiv._fullLayout[M.id].bgcolor).getLuminance(),v="M0,"+M.h+"L"+M.w/2+", 0L"+M.w+","+M.h+"Z",b=!1,T=D.append("path").attr("class","zoombox").attr("transform",s(M.x0,M.y0)).style({fill:d>.2?"rgba(0,0,0,0)":"rgba(255,255,255,0)","stroke-width":0}).attr("d",v),k=D.append("path").attr("class","zoombox-corners").attr("transform",s(M.x0,M.y0)).style({fill:c.background,stroke:c.defaultLine,"stroke-width":1,opacity:0}).attr("d","M0,0Z"),M.clearSelect(L)}(0,l,u)):"pan"===m?(M.dragOptions.moveFn=H,M.dragOptions.clickFn=F,M.dragOptions.doneFn=q,f={a:M.aaxis.range[0],b:M.baxis.range[1],c:M.caxis.range[1]},p=f,M.clearSelect(L)):(x(m)||y(m))&&_(a,l,u,M.dragOptions,m)}},S.onmousemove=function(t){g.hover(L,t,M.id),L._fullLayout._lasthover=S,L._fullLayout._hoversubplot=M.id},S.onmouseout=function(t){L._dragging||m.unhover(L,t)},m.init(this.dragOptions)}},{"../../components/color":366,"../../components/dragelement":385,"../../components/dragelement/helpers":384,"../../components/drawing":388,"../../components/fx":406,"../../components/titles":464,"../../lib":503,"../../lib/extend":493,"../../registry":638,"../cartesian/axes":554,"../cartesian/constants":561,"../cartesian/select":575,"../cartesian/set_convert":576,"../plots":619,"@plotly/d3":58,tinycolor2:312}],638:[function(t,e,r){"use strict";var n=t("./lib/loggers"),i=t("./lib/noop"),a=t("./lib/push_unique"),o=t("./lib/is_plain_object"),s=t("./lib/dom").addStyleRule,l=t("./lib/extend"),c=t("./plots/attributes"),u=t("./plots/layout_attributes"),f=l.extendFlat,h=l.extendDeepAll;function p(t){var e=t.name,i=t.categories,a=t.meta;if(r.modules[e])n.log("Type "+e+" already registered");else{r.subplotsRegistry[t.basePlotModule.name]||function(t){var e=t.name;if(r.subplotsRegistry[e])return void n.log("Plot type "+e+" already registered.");for(var i in v(t),r.subplotsRegistry[e]=t,r.componentsRegistry)b(i,t.name)}(t.basePlotModule);for(var o={},l=0;l-1&&(f[p[r]].title={text:""});for(r=0;r")?"":e.html(t).text()}));return e.remove(),r}(_),_=(_=_.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g,"&")).replace(c,"'"),i.isIE()&&(_=(_=(_=_.replace(/"/gi,"'")).replace(/(\('#)([^']*)('\))/gi,'("#$2")')).replace(/(\\')/gi,'"')),_}},{"../components/color":366,"../components/drawing":388,"../constants/xmlns_namespaces":480,"../lib":503,"@plotly/d3":58}],647:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e){for(var r=0;rf+c||!n(u))}for(var p=0;pa))return e}return void 0!==r?r:t.dflt},r.coerceColor=function(t,e,r){return i(e).isValid()?e:void 0!==r?r:t.dflt},r.coerceEnumerated=function(t,e,r){return t.coerceNumber&&(e=+e),-1!==t.values.indexOf(e)?e:void 0!==r?r:t.dflt},r.getValue=function(t,e){var r;return Array.isArray(t)?e0?e+=r:u<0&&(e-=r)}return e}function z(t){var e=u,r=t.b,i=O(t);return n.inbox(r-e,i-e,_+(i-e)/(i-r)-1)}var D=t[f+"a"],R=t[h+"a"];m=Math.abs(D.r2c(D.range[1])-D.r2c(D.range[0]));var F=n.getDistanceFunction(i,p,d,(function(t){return(p(t)+d(t))/2}));if(n.getClosest(g,F,t),!1!==t.index&&g[t.index].p!==c){k||(L=function(t){return Math.min(A(t),t.p-y.bargroupwidth/2)},C=function(t){return Math.max(M(t),t.p+y.bargroupwidth/2)});var B=g[t.index],N=v.base?B.b+B.s:B.s;t[h+"0"]=t[h+"1"]=R.c2p(B[h],!0),t[h+"LabelVal"]=N;var j=y.extents[y.extents.round(B.p)];t[f+"0"]=D.c2p(x?L(B):j[0],!0),t[f+"1"]=D.c2p(x?C(B):j[1],!0);var U=void 0!==B.orig_p;return t[f+"LabelVal"]=U?B.orig_p:B.p,t.labelLabel=l(D,t[f+"LabelVal"],v[f+"hoverformat"]),t.valueLabel=l(R,t[h+"LabelVal"],v[h+"hoverformat"]),t.baseLabel=l(R,B.b,v[h+"hoverformat"]),t.spikeDistance=(function(t){var e=u,r=t.b,i=O(t);return n.inbox(r-e,i-e,w+(i-e)/(i-r)-1)}(B)+function(t){return P(A(t),M(t),w)}(B))/2,t[f+"Spike"]=D.c2p(B.p,!0),o(B,v,t),t.hovertemplate=v.hovertemplate,t}}function f(t,e){var r=e.mcc||t.marker.color,n=e.mlcc||t.marker.line.color,i=s(t,e);return a.opacity(r)?r:a.opacity(n)&&i?n:void 0}e.exports={hoverPoints:function(t,e,r,n,a){var o=u(t,e,r,n,a);if(o){var s=o.cd,l=s[0].trace,c=s[o.index];return o.color=f(l,c),i.getComponentMethod("errorbars","hoverInfo")(c,l,o),[o]}},hoverOnBars:u,getTraceColor:f}},{"../../components/color":366,"../../components/fx":406,"../../constants/numerical":479,"../../lib":503,"../../plots/cartesian/axes":554,"../../registry":638,"./helpers":654}],656:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults").supplyDefaults,crossTraceDefaults:t("./defaults").crossTraceDefaults,supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc"),crossTraceCalc:t("./cross_trace_calc").crossTraceCalc,colorbar:t("../scatter/marker_colorbar"),arraysToCalcdata:t("./arrays_to_calcdata"),plot:t("./plot").plot,style:t("./style").style,styleOnSelect:t("./style").styleOnSelect,hoverPoints:t("./hover").hoverPoints,eventData:t("./event_data"),selectPoints:t("./select"),moduleType:"trace",name:"bar",basePlotModule:t("../../plots/cartesian"),categories:["bar-like","cartesian","svg","bar","oriented","errorBarsOK","showLegend","zoomScale"],animatable:!0,meta:{}}},{"../../plots/cartesian":568,"../scatter/marker_colorbar":945,"./arrays_to_calcdata":647,"./attributes":648,"./calc":649,"./cross_trace_calc":651,"./defaults":652,"./event_data":653,"./hover":655,"./layout_attributes":657,"./layout_defaults":658,"./plot":659,"./select":660,"./style":662}],657:[function(t,e,r){"use strict";e.exports={barmode:{valType:"enumerated",values:["stack","group","overlay","relative"],dflt:"group",editType:"calc"},barnorm:{valType:"enumerated",values:["","fraction","percent"],dflt:"",editType:"calc"},bargap:{valType:"number",min:0,max:1,editType:"calc"},bargroupgap:{valType:"number",min:0,max:1,dflt:0,editType:"calc"}}},{}],658:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../plots/cartesian/axes"),a=t("../../lib"),o=t("./layout_attributes");e.exports=function(t,e,r){function s(r,n){return a.coerce(t,e,o,r,n)}for(var l=!1,c=!1,u=!1,f={},h=s("barmode"),p=0;p0}function S(t){return"auto"===t?0:t}function E(t,e){var r=Math.PI/180*e,n=Math.abs(Math.sin(r)),i=Math.abs(Math.cos(r));return{x:t.width*i+t.height*n,y:t.width*n+t.height*i}}function L(t,e,r,n,i,a){var o=!!a.isHorizontal,s=!!a.constrained,l=a.angle||0,c=a.anchor||"end",u="end"===c,f="start"===c,h=((a.leftToRight||0)+1)/2,p=1-h,d=i.width,m=i.height,g=Math.abs(e-t),v=Math.abs(n-r),y=g>2*_&&v>2*_?_:0;g-=2*y,v-=2*y;var x=S(l);"auto"!==l||d<=g&&m<=v||!(d>g||m>v)||(d>v||m>g)&&d.01?q:function(t,e,r){return r&&t===e?t:Math.abs(t-e)>=2?q(t):t>e?Math.ceil(t):Math.floor(t)};B=G(B,N,D),N=G(N,B,D),j=G(j,U,!D),U=G(U,j,!D)}var Y=A(a.ensureSingle(I,"path"),P,g,v);if(Y.style("vector-effect","non-scaling-stroke").attr("d",isNaN((N-B)*(U-j))||V&&t._context.staticPlot?"M0,0Z":"M"+B+","+j+"V"+U+"H"+N+"V"+j+"Z").call(l.setClipUrl,e.layerClipId,t),!P.uniformtext.mode&&R){var W=l.makePointStyleFns(f);l.singlePointStyle(c,Y,f,W,t)}!function(t,e,r,n,i,s,c,f,p,g,v){var w,T=e.xaxis,M=e.yaxis,C=t._fullLayout;function P(e,r,n){return a.ensureSingle(e,"text").text(r).attr({class:"bartext bartext-"+w,"text-anchor":"middle","data-notex":1}).call(l.font,n).call(o.convertToTspans,t)}var I=n[0].trace,O="h"===I.orientation,z=function(t,e,r,n,i){var o,s=e[0].trace;o=s.texttemplate?function(t,e,r,n,i){var o=e[0].trace,s=a.castOption(o,r,"texttemplate");if(!s)return"";var l,c,f,h,p="histogram"===o.type,d="waterfall"===o.type,m="funnel"===o.type,g="h"===o.orientation;g?(l="y",c=i,f="x",h=n):(l="x",c=n,f="y",h=i);function v(t){return u(h,h.c2l(t),!0).text}var y=e[r],x={};x.label=y.p,x.labelLabel=x[l+"Label"]=(_=y.p,u(c,c.c2l(_),!0).text);var _;var w=a.castOption(o,y.i,"text");(0===w||w)&&(x.text=w);x.value=y.s,x.valueLabel=x[f+"Label"]=v(y.s);var T={};b(T,o,y.i),(p||void 0===T.x)&&(T.x=g?x.value:x.label);(p||void 0===T.y)&&(T.y=g?x.label:x.value);(p||void 0===T.xLabel)&&(T.xLabel=g?x.valueLabel:x.labelLabel);(p||void 0===T.yLabel)&&(T.yLabel=g?x.labelLabel:x.valueLabel);d&&(x.delta=+y.rawS||y.s,x.deltaLabel=v(x.delta),x.final=y.v,x.finalLabel=v(x.final),x.initial=x.final-x.delta,x.initialLabel=v(x.initial));m&&(x.value=y.s,x.valueLabel=v(x.value),x.percentInitial=y.begR,x.percentInitialLabel=a.formatPercent(y.begR),x.percentPrevious=y.difR,x.percentPreviousLabel=a.formatPercent(y.difR),x.percentTotal=y.sumR,x.percenTotalLabel=a.formatPercent(y.sumR));var k=a.castOption(o,y.i,"customdata");k&&(x.customdata=k);return a.texttemplateString(s,x,t._d3locale,T,x,o._meta||{})}(t,e,r,n,i):s.textinfo?function(t,e,r,n){var i=t[0].trace,o="h"===i.orientation,s="waterfall"===i.type,l="funnel"===i.type;function c(t){return u(o?r:n,+t,!0).text}var f,h=i.textinfo,p=t[e],d=h.split("+"),m=[],g=function(t){return-1!==d.indexOf(t)};g("label")&&m.push((v=t[e].p,u(o?n:r,v,!0).text));var v;g("text")&&(0===(f=a.castOption(i,p.i,"text"))||f)&&m.push(f);if(s){var y=+p.rawS||p.s,x=p.v,b=x-y;g("initial")&&m.push(c(b)),g("delta")&&m.push(c(y)),g("final")&&m.push(c(x))}if(l){g("value")&&m.push(c(p.s));var _=0;g("percent initial")&&_++,g("percent previous")&&_++,g("percent total")&&_++;var w=_>1;g("percent initial")&&(f=a.formatPercent(p.begR),w&&(f+=" of initial"),m.push(f)),g("percent previous")&&(f=a.formatPercent(p.difR),w&&(f+=" of previous"),m.push(f)),g("percent total")&&(f=a.formatPercent(p.sumR),w&&(f+=" of total"),m.push(f))}return m.join("
    ")}(e,r,n,i):m.getValue(s.text,r);return m.coerceString(y,o)}(C,n,i,T,M);w=function(t,e){var r=m.getValue(t.textposition,e);return m.coerceEnumerated(x,r)}(I,i);var D="stack"===g.mode||"relative"===g.mode,R=n[i],F=!D||R._outmost;if(!z||"none"===w||(R.isBlank||s===c||f===p)&&("auto"===w||"inside"===w))return void r.select("text").remove();var B=C.font,N=d.getBarColor(n[i],I),j=d.getInsideTextFont(I,i,B,N),U=d.getOutsideTextFont(I,i,B),V=r.datum();O?"log"===T.type&&V.s0<=0&&(s=T.range[0]=G*(Z/Y):Z>=Y*(X/G);G>0&&Y>0&&(J||K||Q)?w="inside":(w="outside",H.remove(),H=null)}else w="inside";if(!H){W=a.ensureUniformFontSize(t,"outside"===w?U:j);var $=(H=P(r,z,W)).attr("transform");if(H.attr("transform",""),q=l.bBox(H.node()),G=q.width,Y=q.height,H.attr("transform",$),G<=0||Y<=0)return void H.remove()}var tt,et,rt=I.textangle;"outside"===w?(et="both"===I.constraintext||"outside"===I.constraintext,tt=function(t,e,r,n,i,a){var o,s=!!a.isHorizontal,l=!!a.constrained,c=a.angle||0,u=i.width,f=i.height,h=Math.abs(e-t),p=Math.abs(n-r);o=s?p>2*_?_:0:h>2*_?_:0;var d=1;l&&(d=s?Math.min(1,p/f):Math.min(1,h/u));var m=S(c),g=E(i,m),v=(s?g.x:g.y)/2,y=(i.left+i.right)/2,x=(i.top+i.bottom)/2,b=(t+e)/2,w=(r+n)/2,T=0,A=0,M=s?k(e,t):k(r,n);s?(b=e-M*o,T=M*v):(w=n+M*o,A=-M*v);return{textX:y,textY:x,targetX:b,targetY:w,anchorX:T,anchorY:A,scale:d,rotate:m}}(s,c,f,p,q,{isHorizontal:O,constrained:et,angle:rt})):(et="both"===I.constraintext||"inside"===I.constraintext,tt=L(s,c,f,p,q,{isHorizontal:O,constrained:et,angle:rt,anchor:I.insidetextanchor}));tt.fontSize=W.size,h("histogram"===I.type?"bar":I.type,tt,C),R.transform=tt,A(H,C,g,v).attr("transform",a.getTextTransform(tt))}(t,e,I,r,p,B,N,j,U,g,v),e.layerClipId&&l.hideOutsideRangePoint(c,I.select("text"),w,C,f.xcalendar,f.ycalendar)}));var j=!1===f.cliponaxis;l.setClipUrl(c,j?null:e.layerClipId,t)}));c.getComponentMethod("errorbars","plot")(t,I,e,g)},toMoveInsideBar:L}},{"../../components/color":366,"../../components/drawing":388,"../../components/fx/helpers":402,"../../lib":503,"../../lib/svg_text_utils":529,"../../plots/cartesian/axes":554,"../../registry":638,"./attributes":648,"./constants":650,"./helpers":654,"./style":662,"./uniform_text":664,"@plotly/d3":58,"fast-isnumeric":190}],660:[function(t,e,r){"use strict";function n(t,e,r,n,i){var a=e.c2p(n?t.s0:t.p0,!0),o=e.c2p(n?t.s1:t.p1,!0),s=r.c2p(n?t.p0:t.s0,!0),l=r.c2p(n?t.p1:t.s1,!0);return i?[(a+o)/2,(s+l)/2]:n?[o,(s+l)/2]:[(a+o)/2,l]}e.exports=function(t,e){var r,i=t.cd,a=t.xaxis,o=t.yaxis,s=i[0].trace,l="funnel"===s.type,c="h"===s.orientation,u=[];if(!1===e)for(r=0;r1||0===i.bargap&&0===i.bargroupgap&&!t[0].trace.marker.line.width)&&n.select(this).attr("shape-rendering","crispEdges")})),e.selectAll("g.points").each((function(e){d(n.select(this),e[0].trace,t)})),s.getComponentMethod("errorbars","style")(e)},styleTextPoints:m,styleOnSelect:function(t,e,r){var i=e[0].trace;i.selectedpoints?function(t,e,r){a.selectedPointStyle(t.selectAll("path"),e),function(t,e,r){t.each((function(t){var i,s=n.select(this);if(t.selected){i=o.ensureUniformFontSize(r,g(s,t,e,r));var l=e.selected.textfont&&e.selected.textfont.color;l&&(i.color=l),a.font(s,i)}else a.selectedTextStyle(s,e)}))}(t.selectAll("text"),e,r)}(r,i,t):(d(r,i,t),s.getComponentMethod("errorbars","style")(r))},getInsideTextFont:y,getOutsideTextFont:x,getBarColor:_,resizeText:l}},{"../../components/color":366,"../../components/drawing":388,"../../lib":503,"../../registry":638,"./attributes":648,"./helpers":654,"./uniform_text":664,"@plotly/d3":58}],663:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("../../components/colorscale/helpers").hasColorscale,a=t("../../components/colorscale/defaults"),o=t("../../lib").coercePattern;e.exports=function(t,e,r,s,l){var c=r("marker.color",s),u=i(t,"marker");u&&a(t,e,l,r,{prefix:"marker.",cLetter:"c"}),r("marker.line.color",n.defaultLine),i(t,"marker.line")&&a(t,e,l,r,{prefix:"marker.line.",cLetter:"c"}),r("marker.line.width"),r("marker.opacity"),o(r,"marker.pattern",c,u),r("selected.marker.color"),r("unselected.marker.color")}},{"../../components/color":366,"../../components/colorscale/defaults":376,"../../components/colorscale/helpers":377,"../../lib":503}],664:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib");function a(t){return"_"+t+"Text_minsize"}e.exports={recordMinTextSize:function(t,e,r){if(r.uniformtext.mode){var n=a(t),i=r.uniformtext.minsize,o=e.scale*e.fontSize;e.hide=oh.range[1]&&(x+=Math.PI);if(n.getClosest(c,(function(t){return m(y,x,[t.rp0,t.rp1],[t.thetag0,t.thetag1],d)?g+Math.min(1,Math.abs(t.thetag1-t.thetag0)/v)-1+(t.rp1-y)/(t.rp1-t.rp0)-1:1/0}),t),!1!==t.index){var b=c[t.index];t.x0=t.x1=b.ct[0],t.y0=t.y1=b.ct[1];var _=i.extendFlat({},b,{r:b.s,theta:b.p});return o(b,u,t),s(_,u,f,t),t.hovertemplate=u.hovertemplate,t.color=a(u,b),t.xLabelVal=t.yLabelVal=void 0,b.s<0&&(t.idealAlign="left"),[t]}}},{"../../components/fx":406,"../../lib":503,"../../plots/polar/helpers":621,"../bar/hover":655,"../scatterpolar/hover":1006}],669:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"barpolar",basePlotModule:t("../../plots/polar"),categories:["polar","bar","showLegend"],attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc").calc,crossTraceCalc:t("./calc").crossTraceCalc,plot:t("./plot"),colorbar:t("../scatter/marker_colorbar"),formatLabels:t("../scatterpolar/format_labels"),style:t("../bar/style").style,styleOnSelect:t("../bar/style").styleOnSelect,hoverPoints:t("./hover"),selectPoints:t("../bar/select"),meta:{}}},{"../../plots/polar":622,"../bar/select":660,"../bar/style":662,"../scatter/marker_colorbar":945,"../scatterpolar/format_labels":1005,"./attributes":665,"./calc":666,"./defaults":667,"./hover":668,"./layout_attributes":670,"./layout_defaults":671,"./plot":672}],670:[function(t,e,r){"use strict";e.exports={barmode:{valType:"enumerated",values:["stack","overlay"],dflt:"stack",editType:"calc"},bargap:{valType:"number",dflt:.1,min:0,max:1,editType:"calc"}}},{}],671:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e,r){var a,o={};function s(r,o){return n.coerce(t[a]||{},e[a],i,r,o)}for(var l=0;l0?(c=o,u=l):(c=l,u=o);var f=[s.findEnclosingVertexAngles(c,t.vangles)[0],(c+u)/2,s.findEnclosingVertexAngles(u,t.vangles)[1]];return s.pathPolygonAnnulus(n,i,c,u,f,e,r)};return function(t,n,i,o){return a.pathAnnulus(t,n,i,o,e,r)}}(e),p=e.layers.frontplot.select("g.barlayer");a.makeTraceGroups(p,r,"trace bars").each((function(){var r=n.select(this),s=a.ensureSingle(r,"g","points").selectAll("g.point").data(a.identity);s.enter().append("g").style("vector-effect","non-scaling-stroke").style("stroke-miterlimit",2).classed("point",!0),s.exit().remove(),s.each((function(t){var e,r=n.select(this),o=t.rp0=u.c2p(t.s0),s=t.rp1=u.c2p(t.s1),p=t.thetag0=f.c2g(t.p0),d=t.thetag1=f.c2g(t.p1);if(i(o)&&i(s)&&i(p)&&i(d)&&o!==s&&p!==d){var m=u.c2g(t.s1),g=(p+d)/2;t.ct=[l.c2p(m*Math.cos(g)),c.c2p(m*Math.sin(g))],e=h(o,s,p,d)}else e="M0,0Z";a.ensureSingle(r,"path").attr("d",e)})),o.setClipUrl(r,e._hasClipOnAxisFalse?e.clipIds.forTraces:null,t)}))}},{"../../components/drawing":388,"../../lib":503,"../../plots/polar/helpers":621,"@plotly/d3":58,"fast-isnumeric":190}],673:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../bar/attributes"),a=t("../../components/color/attributes"),o=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,s=t("../../plots/template_attributes").hovertemplateAttrs,l=t("../../lib/extend").extendFlat,c=n.marker,u=c.line;e.exports={y:{valType:"data_array",editType:"calc+clearAxisTypes"},x:{valType:"data_array",editType:"calc+clearAxisTypes"},x0:{valType:"any",editType:"calc+clearAxisTypes"},y0:{valType:"any",editType:"calc+clearAxisTypes"},dx:{valType:"number",editType:"calc"},dy:{valType:"number",editType:"calc"},xperiod:n.xperiod,yperiod:n.yperiod,xperiod0:n.xperiod0,yperiod0:n.yperiod0,xperiodalignment:n.xperiodalignment,yperiodalignment:n.yperiodalignment,xhoverformat:o("x"),yhoverformat:o("y"),name:{valType:"string",editType:"calc+clearAxisTypes"},q1:{valType:"data_array",editType:"calc+clearAxisTypes"},median:{valType:"data_array",editType:"calc+clearAxisTypes"},q3:{valType:"data_array",editType:"calc+clearAxisTypes"},lowerfence:{valType:"data_array",editType:"calc"},upperfence:{valType:"data_array",editType:"calc"},notched:{valType:"boolean",editType:"calc"},notchwidth:{valType:"number",min:0,max:.5,dflt:.25,editType:"calc"},notchspan:{valType:"data_array",editType:"calc"},boxpoints:{valType:"enumerated",values:["all","outliers","suspectedoutliers",!1],editType:"calc"},jitter:{valType:"number",min:0,max:1,editType:"calc"},pointpos:{valType:"number",min:-2,max:2,editType:"calc"},boxmean:{valType:"enumerated",values:[!0,"sd",!1],editType:"calc"},mean:{valType:"data_array",editType:"calc"},sd:{valType:"data_array",editType:"calc"},orientation:{valType:"enumerated",values:["v","h"],editType:"calc+clearAxisTypes"},quartilemethod:{valType:"enumerated",values:["linear","exclusive","inclusive"],dflt:"linear",editType:"calc"},width:{valType:"number",min:0,dflt:0,editType:"calc"},marker:{outliercolor:{valType:"color",dflt:"rgba(0, 0, 0, 0)",editType:"style"},symbol:l({},c.symbol,{arrayOk:!1,editType:"plot"}),opacity:l({},c.opacity,{arrayOk:!1,dflt:1,editType:"style"}),size:l({},c.size,{arrayOk:!1,editType:"calc"}),color:l({},c.color,{arrayOk:!1,editType:"style"}),line:{color:l({},u.color,{arrayOk:!1,dflt:a.defaultLine,editType:"style"}),width:l({},u.width,{arrayOk:!1,dflt:0,editType:"style"}),outliercolor:{valType:"color",editType:"style"},outlierwidth:{valType:"number",min:0,dflt:1,editType:"style"},editType:"style"},editType:"plot"},line:{color:{valType:"color",editType:"style"},width:{valType:"number",min:0,dflt:2,editType:"style"},editType:"plot"},fillcolor:n.fillcolor,whiskerwidth:{valType:"number",min:0,max:1,dflt:.5,editType:"calc"},offsetgroup:i.offsetgroup,alignmentgroup:i.alignmentgroup,selected:{marker:n.selected.marker,editType:"style"},unselected:{marker:n.unselected.marker,editType:"style"},text:l({},n.text,{}),hovertext:l({},n.hovertext,{}),hovertemplate:s({}),hoveron:{valType:"flaglist",flags:["boxes","points"],dflt:"boxes+points",editType:"style"}}},{"../../components/color/attributes":365,"../../lib/extend":493,"../../plots/cartesian/axis_format_attributes":557,"../../plots/template_attributes":633,"../bar/attributes":648,"../scatter/attributes":927}],674:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../plots/cartesian/axes"),a=t("../../plots/cartesian/align_period"),o=t("../../lib"),s=t("../../constants/numerical").BADNUM,l=o._;e.exports=function(t,e){var r,c,y,x,b,_,w,T=t._fullLayout,k=i.getFromId(t,e.xaxis||"x"),A=i.getFromId(t,e.yaxis||"y"),M=[],S="violin"===e.type?"_numViolins":"_numBoxes";"h"===e.orientation?(y=k,x="x",b=A,_="y",w=!!e.yperiodalignment):(y=A,x="y",b=k,_="x",w=!!e.xperiodalignment);var E,L,C,P,I,O,z=function(t,e,r,i){var s,l=e+"0"in t,c="d"+e in t;if(e in t||l&&c){var u=r.makeCalcdata(t,e);return[a(t,r,e,u).vals,u]}s=l?t[e+"0"]:"name"in t&&("category"===r.type||n(t.name)&&-1!==["linear","log"].indexOf(r.type)||o.isDateTime(t.name)&&"date"===r.type)?t.name:i;for(var f="multicategory"===r.type?r.r2c_just_indices(s):r.d2c(s,0,t[e+"calendar"]),h=t._length,p=new Array(h),d=0;dE.uf};if(e._hasPreCompStats){var U=e[x],V=function(t){return y.d2c((e[t]||[])[r])},H=1/0,q=-1/0;for(r=0;r=E.q1&&E.q3>=E.med){var Y=V("lowerfence");E.lf=Y!==s&&Y<=E.q1?Y:p(E,C,P);var W=V("upperfence");E.uf=W!==s&&W>=E.q3?W:d(E,C,P);var X=V("mean");E.mean=X!==s?X:P?o.mean(C,P):(E.q1+E.q3)/2;var Z=V("sd");E.sd=X!==s&&Z>=0?Z:P?o.stdev(C,P,E.mean):E.q3-E.q1,E.lo=m(E),E.uo=g(E);var J=V("notchspan");J=J!==s&&J>0?J:v(E,P),E.ln=E.med-J,E.un=E.med+J;var K=E.lf,Q=E.uf;e.boxpoints&&C.length&&(K=Math.min(K,C[0]),Q=Math.max(Q,C[P-1])),e.notched&&(K=Math.min(K,E.ln),Q=Math.max(Q,E.un)),E.min=K,E.max=Q}else{var $;o.warn(["Invalid input - make sure that q1 <= median <= q3","q1 = "+E.q1,"median = "+E.med,"q3 = "+E.q3].join("\n")),$=E.med!==s?E.med:E.q1!==s?E.q3!==s?(E.q1+E.q3)/2:E.q1:E.q3!==s?E.q3:0,E.med=$,E.q1=E.q3=$,E.lf=E.uf=$,E.mean=E.sd=$,E.ln=E.un=$,E.min=E.max=$}H=Math.min(H,E.min),q=Math.max(q,E.max),E.pts2=L.filter(j),M.push(E)}}e._extremes[y._id]=i.findExtremes(y,[H,q],{padded:!0})}else{var tt=y.makeCalcdata(e,x),et=function(t,e){for(var r=t.length,n=new Array(r+1),i=0;i=0&&it0){var ut,ft;if((E={}).pos=E[_]=B[r],L=E.pts=nt[r].sort(f),P=(C=E[x]=L.map(h)).length,E.min=C[0],E.max=C[P-1],E.mean=o.mean(C,P),E.sd=o.stdev(C,P,E.mean),E.med=o.interp(C,.5),P%2&&(lt||ct))lt?(ut=C.slice(0,P/2),ft=C.slice(P/2+1)):ct&&(ut=C.slice(0,P/2+1),ft=C.slice(P/2)),E.q1=o.interp(ut,.5),E.q3=o.interp(ft,.5);else E.q1=o.interp(C,.25),E.q3=o.interp(C,.75);E.lf=p(E,C,P),E.uf=d(E,C,P),E.lo=m(E),E.uo=g(E);var ht=v(E,P);E.ln=E.med-ht,E.un=E.med+ht,at=Math.min(at,E.ln),ot=Math.max(ot,E.un),E.pts2=L.filter(j),M.push(E)}e._extremes[y._id]=i.findExtremes(y,e.notched?tt.concat([at,ot]):tt,{padded:!0})}return function(t,e){if(o.isArrayOrTypedArray(e.selectedpoints))for(var r=0;r0?(M[0].t={num:T[S],dPos:N,posLetter:_,valLetter:x,labels:{med:l(t,"median:"),min:l(t,"min:"),q1:l(t,"q1:"),q3:l(t,"q3:"),max:l(t,"max:"),mean:"sd"===e.boxmean?l(t,"mean \xb1 \u03c3:"):l(t,"mean:"),lf:l(t,"lower fence:"),uf:l(t,"upper fence:")}},T[S]++,M):[{t:{empty:!0}}]};var c={text:"tx",hovertext:"htx"};function u(t,e,r){for(var n in c)o.isArrayOrTypedArray(e[n])&&(Array.isArray(r)?o.isArrayOrTypedArray(e[n][r[0]])&&(t[c[n]]=e[n][r[0]][r[1]]):t[c[n]]=e[n][r])}function f(t,e){return t.v-e.v}function h(t){return t.v}function p(t,e,r){return 0===r?t.q1:Math.min(t.q1,e[Math.min(o.findBin(2.5*t.q1-1.5*t.q3,e,!0)+1,r-1)])}function d(t,e,r){return 0===r?t.q3:Math.max(t.q3,e[Math.max(o.findBin(2.5*t.q3-1.5*t.q1,e),0)])}function m(t){return 4*t.q1-3*t.q3}function g(t){return 4*t.q3-3*t.q1}function v(t,e){return 0===e?0:1.57*(t.q3-t.q1)/Math.sqrt(e)}},{"../../constants/numerical":479,"../../lib":503,"../../plots/cartesian/align_period":551,"../../plots/cartesian/axes":554,"fast-isnumeric":190}],675:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../../lib"),a=t("../../plots/cartesian/constraints").getAxisGroup,o=["v","h"];function s(t,e,r,o){var s,l,c,u=e.calcdata,f=e._fullLayout,h=o._id,p=h.charAt(0),d=[],m=0;for(s=0;s1,b=1-f[t+"gap"],_=1-f[t+"groupgap"];for(s=0;s0){var q=E.pointpos,G=E.jitter,Y=E.marker.size/2,W=0;q+G>=0&&((W=V*(q+G))>M?(H=!0,j=Y,B=W):W>R&&(j=Y,B=M)),W<=M&&(B=M);var X=0;q-G<=0&&((X=-V*(q-G))>S?(H=!0,U=Y,N=X):X>F&&(U=Y,N=S)),X<=S&&(N=S)}else B=M,N=S;var Z=new Array(c.length);for(l=0;l0?(g="v",v=x>0?Math.min(_,b):Math.min(b)):x>0?(g="h",v=Math.min(_)):v=0;if(v){e._length=v;var S=r("orientation",g);e._hasPreCompStats?"v"===S&&0===x?(r("x0",0),r("dx",1)):"h"===S&&0===y&&(r("y0",0),r("dy",1)):"v"===S&&0===x?r("x0"):"h"===S&&0===y&&r("y0"),i.getComponentMethod("calendars","handleTraceDefaults")(t,e,["x","y"],a)}else e.visible=!1}function f(t,e,r,i){var a=i.prefix,o=n.coerce2(t,e,c,"marker.outliercolor"),s=r("marker.line.outliercolor"),l="outliers";e._hasPreCompStats?l="all":(o||s)&&(l="suspectedoutliers");var u=r(a+"points",l);u?(r("jitter","all"===u?.3:0),r("pointpos","all"===u?-1.5:0),r("marker.symbol"),r("marker.opacity"),r("marker.size"),r("marker.color",e.line.color),r("marker.line.color"),r("marker.line.width"),"suspectedoutliers"===u&&(r("marker.line.outliercolor",e.marker.color),r("marker.line.outlierwidth")),r("selected.marker.color"),r("unselected.marker.color"),r("selected.marker.size"),r("unselected.marker.size"),r("text"),r("hovertext")):delete e.marker;var f=r("hoveron");"all"!==f&&-1===f.indexOf("points")||r("hovertemplate"),n.coerceSelectionMarkerOpacity(e,r)}e.exports={supplyDefaults:function(t,e,r,i){function s(r,i){return n.coerce(t,e,c,r,i)}if(u(t,e,s,i),!1!==e.visible){o(t,e,i,s),s("xhoverformat"),s("yhoverformat");var l=e._hasPreCompStats;l&&(s("lowerfence"),s("upperfence")),s("line.color",(t.marker||{}).color||r),s("line.width"),s("fillcolor",a.addOpacity(e.line.color,.5));var h=!1;if(l){var p=s("mean"),d=s("sd");p&&p.length&&(h=!0,d&&d.length&&(h="sd"))}s("boxmean",h),s("whiskerwidth"),s("width"),s("quartilemethod");var m=!1;if(l){var g=s("notchspan");g&&g.length&&(m=!0)}else n.validate(t.notchwidth,c.notchwidth)&&(m=!0);s("notched",m)&&s("notchwidth"),f(t,e,s,{prefix:"box"})}},crossTraceDefaults:function(t,e){var r,i;function a(t){return n.coerce(i._input,i,c,t)}for(var o=0;ot.lo&&(x.so=!0)}return a}));h.enter().append("path").classed("point",!0),h.exit().remove(),h.call(a.translatePoints,o,s)}function l(t,e,r,a){var o,s,l=e.val,c=e.pos,u=!!c.rangebreaks,f=a.bPos,h=a.bPosPxOffset||0,p=r.boxmean||(r.meanline||{}).visible;Array.isArray(a.bdPos)?(o=a.bdPos[0],s=a.bdPos[1]):(o=a.bdPos,s=a.bdPos);var d=t.selectAll("path.mean").data("box"===r.type&&r.boxmean||"violin"===r.type&&r.box.visible&&r.meanline.visible?i.identity:[]);d.enter().append("path").attr("class","mean").style({fill:"none","vector-effect":"non-scaling-stroke"}),d.exit().remove(),d.each((function(t){var e=c.c2l(t.pos+f,!0),i=c.l2p(e-o)+h,a=c.l2p(e+s)+h,d=u?(i+a)/2:c.l2p(e)+h,m=l.c2p(t.mean,!0),g=l.c2p(t.mean-t.sd,!0),v=l.c2p(t.mean+t.sd,!0);"h"===r.orientation?n.select(this).attr("d","M"+m+","+i+"V"+a+("sd"===p?"m0,0L"+g+","+d+"L"+m+","+i+"L"+v+","+d+"Z":"")):n.select(this).attr("d","M"+i+","+m+"H"+a+("sd"===p?"m0,0L"+d+","+g+"L"+i+","+m+"L"+d+","+v+"Z":""))}))}e.exports={plot:function(t,e,r,a){var c=e.xaxis,u=e.yaxis;i.makeTraceGroups(a,r,"trace boxes").each((function(t){var e,r,i=n.select(this),a=t[0],f=a.t,h=a.trace;(f.wdPos=f.bdPos*h.whiskerwidth,!0!==h.visible||f.empty)?i.remove():("h"===h.orientation?(e=u,r=c):(e=c,r=u),o(i,{pos:e,val:r},h,f),s(i,{x:c,y:u},h,f),l(i,{pos:e,val:r},h,f))}))},plotBoxAndWhiskers:o,plotPoints:s,plotBoxMean:l}},{"../../components/drawing":388,"../../lib":503,"@plotly/d3":58}],683:[function(t,e,r){"use strict";e.exports=function(t,e){var r,n,i=t.cd,a=t.xaxis,o=t.yaxis,s=[];if(!1===e)for(r=0;r=10)return null;for(var i=1/0,a=-1/0,o=e.length,s=0;s0?Math.floor:Math.ceil,I=L>0?Math.ceil:Math.floor,O=L>0?Math.min:Math.max,z=L>0?Math.max:Math.min,D=P(S+C),R=I(E-C),F=[[f=M(S)]];for(a=D;a*L=0;i--)a[u-i]=t[f][i],o[u-i]=e[f][i];for(s.push({x:a,y:o,bicubic:l}),i=f,a=[],o=[];i>=0;i--)a[f-i]=t[i][0],o[f-i]=e[i][0];return s.push({x:a,y:o,bicubic:c}),s}},{}],697:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../../lib/extend").extendFlat;e.exports=function(t,e,r){var a,o,s,l,c,u,f,h,p,d,m,g,v,y,x=t["_"+e],b=t[e+"axis"],_=b._gridlines=[],w=b._minorgridlines=[],T=b._boundarylines=[],k=t["_"+r],A=t[r+"axis"];"array"===b.tickmode&&(b.tickvals=x.slice());var M=t._xctrl,S=t._yctrl,E=M[0].length,L=M.length,C=t._a.length,P=t._b.length;n.prepTicks(b),"array"===b.tickmode&&delete b.tickvals;var I=b.smoothing?3:1;function O(n){var i,a,o,s,l,c,u,f,p,d,m,g,v=[],y=[],x={};if("b"===e)for(a=t.b2j(n),o=Math.floor(Math.max(0,Math.min(P-2,a))),s=a-o,x.length=P,x.crossLength=C,x.xy=function(e){return t.evalxy([],e,a)},x.dxy=function(e,r){return t.dxydi([],e,o,r,s)},i=0;i0&&(p=t.dxydi([],i-1,o,0,s),v.push(l[0]+p[0]/3),y.push(l[1]+p[1]/3),d=t.dxydi([],i-1,o,1,s),v.push(f[0]-d[0]/3),y.push(f[1]-d[1]/3)),v.push(f[0]),y.push(f[1]),l=f;else for(i=t.a2i(n),c=Math.floor(Math.max(0,Math.min(C-2,i))),u=i-c,x.length=C,x.crossLength=P,x.xy=function(e){return t.evalxy([],i,e)},x.dxy=function(e,r){return t.dxydj([],c,e,u,r)},a=0;a0&&(m=t.dxydj([],c,a-1,u,0),v.push(l[0]+m[0]/3),y.push(l[1]+m[1]/3),g=t.dxydj([],c,a-1,u,1),v.push(f[0]-g[0]/3),y.push(f[1]-g[1]/3)),v.push(f[0]),y.push(f[1]),l=f;return x.axisLetter=e,x.axis=b,x.crossAxis=A,x.value=n,x.constvar=r,x.index=h,x.x=v,x.y=y,x.smoothing=A.smoothing,x}function z(n){var i,a,o,s,l,c=[],u=[],f={};if(f.length=x.length,f.crossLength=k.length,"b"===e)for(o=Math.max(0,Math.min(P-2,n)),l=Math.min(1,Math.max(0,n-o)),f.xy=function(e){return t.evalxy([],e,n)},f.dxy=function(e,r){return t.dxydi([],e,o,r,l)},i=0;ix.length-1||_.push(i(z(o),{color:b.gridcolor,width:b.gridwidth,dash:b.griddash}));for(h=u;hx.length-1||m<0||m>x.length-1))for(g=x[s],v=x[m],a=0;ax[x.length-1]||w.push(i(O(d),{color:b.minorgridcolor,width:b.minorgridwidth,dash:b.minorgriddash}));b.startline&&T.push(i(z(0),{color:b.startlinecolor,width:b.startlinewidth})),b.endline&&T.push(i(z(x.length-1),{color:b.endlinecolor,width:b.endlinewidth}))}else{for(l=5e-15,u=(c=[Math.floor((x[x.length-1]-b.tick0)/b.dtick*(1+l)),Math.ceil((x[0]-b.tick0)/b.dtick/(1+l))].sort((function(t,e){return t-e})))[0],f=c[1],h=u;h<=f;h++)p=b.tick0+b.dtick*h,_.push(i(O(p),{color:b.gridcolor,width:b.gridwidth,dash:b.griddash}));for(h=u-1;hx[x.length-1]||w.push(i(O(d),{color:b.minorgridcolor,width:b.minorgridwidth,dash:b.minorgriddash}));b.startline&&T.push(i(O(x[0]),{color:b.startlinecolor,width:b.startlinewidth})),b.endline&&T.push(i(O(x[x.length-1]),{color:b.endlinecolor,width:b.endlinewidth}))}}},{"../../lib/extend":493,"../../plots/cartesian/axes":554}],698:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../../lib/extend").extendFlat;e.exports=function(t,e){var r,a,o,s=e._labels=[],l=e._gridlines;for(r=0;re.length&&(t=t.slice(0,e.length)):t=[],i=0;i90&&(p-=180,l=-l),{angle:p,flip:l,p:t.c2p(n,e,r),offsetMultplier:c}}},{}],712:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../components/drawing"),a=t("./map_1d_array"),o=t("./makepath"),s=t("./orient_text"),l=t("../../lib/svg_text_utils"),c=t("../../lib"),u=c.strRotate,f=c.strTranslate,h=t("../../constants/alignment");function p(t,e,r,s,l,c){var u="const-"+l+"-lines",f=r.selectAll("."+u).data(c);f.enter().append("path").classed(u,!0).style("vector-effect","non-scaling-stroke"),f.each((function(r){var s=r,l=s.x,c=s.y,u=a([],l,t.c2p),f=a([],c,e.c2p),h="M"+o(u,f,s.smoothing);n.select(this).attr("d",h).style("stroke-width",s.width).style("stroke",s.color).style("stroke-dasharray",i.dashStyle(s.dash,s.width)).style("fill","none")})),f.exit().remove()}function d(t,e,r,a,o,c,h,p){var d=c.selectAll("text."+p).data(h);d.enter().append("text").classed(p,!0);var m=0,g={};return d.each((function(o,c){var h;if("auto"===o.axis.tickangle)h=s(a,e,r,o.xy,o.dxy);else{var p=(o.axis.tickangle+180)*Math.PI/180;h=s(a,e,r,o.xy,[Math.cos(p),Math.sin(p)])}c||(g={angle:h.angle,flip:h.flip});var d=(o.endAnchor?-1:1)*h.flip,v=n.select(this).attr({"text-anchor":d>0?"start":"end","data-notex":1}).call(i.font,o.font).text(o.text).call(l.convertToTspans,t),y=i.bBox(this);v.attr("transform",f(h.p[0],h.p[1])+u(h.angle)+f(o.axis.labelpadding*d,.3*y.height)),m=Math.max(m,y.width+o.axis.labelpadding)})),d.exit().remove(),g.maxExtent=m,g}e.exports=function(t,e,r,i){var l=e.xaxis,u=e.yaxis,f=t._fullLayout._clips;c.makeTraceGroups(i,r,"trace").each((function(e){var r=n.select(this),i=e[0],h=i.trace,m=h.aaxis,g=h.baxis,y=c.ensureSingle(r,"g","minorlayer"),x=c.ensureSingle(r,"g","majorlayer"),b=c.ensureSingle(r,"g","boundarylayer"),_=c.ensureSingle(r,"g","labellayer");r.style("opacity",h.opacity),p(l,u,x,m,"a",m._gridlines),p(l,u,x,g,"b",g._gridlines),p(l,u,y,m,"a",m._minorgridlines),p(l,u,y,g,"b",g._minorgridlines),p(l,u,b,m,"a-boundary",m._boundarylines),p(l,u,b,g,"b-boundary",g._boundarylines);var w=d(t,l,u,h,i,_,m._labels,"a-label"),T=d(t,l,u,h,i,_,g._labels,"b-label");!function(t,e,r,n,i,a,o,l){var u,f,h,p,d=c.aggNums(Math.min,null,r.a),m=c.aggNums(Math.max,null,r.a),g=c.aggNums(Math.min,null,r.b),y=c.aggNums(Math.max,null,r.b);u=.5*(d+m),f=g,h=r.ab2xy(u,f,!0),p=r.dxyda_rough(u,f),void 0===o.angle&&c.extendFlat(o,s(r,i,a,h,r.dxydb_rough(u,f)));v(t,e,r,n,h,p,r.aaxis,i,a,o,"a-title"),u=d,f=.5*(g+y),h=r.ab2xy(u,f,!0),p=r.dxydb_rough(u,f),void 0===l.angle&&c.extendFlat(l,s(r,i,a,h,r.dxyda_rough(u,f)));v(t,e,r,n,h,p,r.baxis,i,a,l,"b-title")}(t,_,h,i,l,u,w,T),function(t,e,r,n,i){var s,l,u,f,h=r.select("#"+t._clipPathId);h.size()||(h=r.append("clipPath").classed("carpetclip",!0));var p=c.ensureSingle(h,"path","carpetboundary"),d=e.clipsegments,m=[];for(f=0;f90&&y<270,b=n.select(this);b.text(h.title.text).call(l.convertToTspans,t),x&&(_=(-l.lineCount(b)+g)*m*a-_),b.attr("transform",f(e.p[0],e.p[1])+u(e.angle)+f(0,_)).attr("text-anchor","middle").call(i.font,h.title.font)})),b.exit().remove()}},{"../../components/drawing":388,"../../constants/alignment":471,"../../lib":503,"../../lib/svg_text_utils":529,"./makepath":709,"./map_1d_array":710,"./orient_text":711,"@plotly/d3":58}],713:[function(t,e,r){"use strict";var n=t("./constants"),i=t("../../lib/search").findBin,a=t("./compute_control_points"),o=t("./create_spline_evaluator"),s=t("./create_i_derivative_evaluator"),l=t("./create_j_derivative_evaluator");e.exports=function(t){var e=t._a,r=t._b,c=e.length,u=r.length,f=t.aaxis,h=t.baxis,p=e[0],d=e[c-1],m=r[0],g=r[u-1],v=e[e.length-1]-e[0],y=r[r.length-1]-r[0],x=v*n.RELATIVE_CULL_TOLERANCE,b=y*n.RELATIVE_CULL_TOLERANCE;p-=x,d+=x,m-=b,g+=b,t.isVisible=function(t,e){return t>p&&tm&&ed||eg},t.setScale=function(){var e=t._x,r=t._y,n=a(t._xctrl,t._yctrl,e,r,f.smoothing,h.smoothing);t._xctrl=n[0],t._yctrl=n[1],t.evalxy=o([t._xctrl,t._yctrl],c,u,f.smoothing,h.smoothing),t.dxydi=s([t._xctrl,t._yctrl],f.smoothing,h.smoothing),t.dxydj=l([t._xctrl,t._yctrl],f.smoothing,h.smoothing)},t.i2a=function(t){var r=Math.max(0,Math.floor(t[0]),c-2),n=t[0]-r;return(1-n)*e[r]+n*e[r+1]},t.j2b=function(t){var e=Math.max(0,Math.floor(t[1]),c-2),n=t[1]-e;return(1-n)*r[e]+n*r[e+1]},t.ij2ab=function(e){return[t.i2a(e[0]),t.j2b(e[1])]},t.a2i=function(t){var r=Math.max(0,Math.min(i(t,e),c-2)),n=e[r],a=e[r+1];return Math.max(0,Math.min(c-1,r+(t-n)/(a-n)))},t.b2j=function(t){var e=Math.max(0,Math.min(i(t,r),u-2)),n=r[e],a=r[e+1];return Math.max(0,Math.min(u-1,e+(t-n)/(a-n)))},t.ab2ij=function(e){return[t.a2i(e[0]),t.b2j(e[1])]},t.i2c=function(e,r){return t.evalxy([],e,r)},t.ab2xy=function(n,i,a){if(!a&&(ne[c-1]|ir[u-1]))return[!1,!1];var o=t.a2i(n),s=t.b2j(i),l=t.evalxy([],o,s);if(a){var f,h,p,d,m=0,g=0,v=[];ne[c-1]?(f=c-2,h=1,m=(n-e[c-1])/(e[c-1]-e[c-2])):h=o-(f=Math.max(0,Math.min(c-2,Math.floor(o)))),ir[u-1]?(p=u-2,d=1,g=(i-r[u-1])/(r[u-1]-r[u-2])):d=s-(p=Math.max(0,Math.min(u-2,Math.floor(s)))),m&&(t.dxydi(v,f,p,h,d),l[0]+=v[0]*m,l[1]+=v[1]*m),g&&(t.dxydj(v,f,p,h,d),l[0]+=v[0]*g,l[1]+=v[1]*g)}return l},t.c2p=function(t,e,r){return[e.c2p(t[0]),r.c2p(t[1])]},t.p2x=function(t,e,r){return[e.p2c(t[0]),r.p2c(t[1])]},t.dadi=function(t){var r=Math.max(0,Math.min(e.length-2,t));return e[r+1]-e[r]},t.dbdj=function(t){var e=Math.max(0,Math.min(r.length-2,t));return r[e+1]-r[e]},t.dxyda=function(e,r,n,i){var a=t.dxydi(null,e,r,n,i),o=t.dadi(e,n);return[a[0]/o,a[1]/o]},t.dxydb=function(e,r,n,i){var a=t.dxydj(null,e,r,n,i),o=t.dbdj(r,i);return[a[0]/o,a[1]/o]},t.dxyda_rough=function(e,r,n){var i=v*(n||.1),a=t.ab2xy(e+i,r,!0),o=t.ab2xy(e-i,r,!0);return[.5*(a[0]-o[0])/i,.5*(a[1]-o[1])/i]},t.dxydb_rough=function(e,r,n){var i=y*(n||.1),a=t.ab2xy(e,r+i,!0),o=t.ab2xy(e,r-i,!0);return[.5*(a[0]-o[0])/i,.5*(a[1]-o[1])/i]},t.dpdx=function(t){return t._m},t.dpdy=function(t){return t._m}}},{"../../lib/search":523,"./compute_control_points":701,"./constants":702,"./create_i_derivative_evaluator":703,"./create_j_derivative_evaluator":704,"./create_spline_evaluator":705}],714:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e,r){var i,a,o,s=[],l=[],c=t[0].length,u=t.length;function f(e,r){var n,i=0,a=0;return e>0&&void 0!==(n=t[r][e-1])&&(a++,i+=n),e0&&void 0!==(n=t[r-1][e])&&(a++,i+=n),r0&&a0&&i1e-5);return n.log("Smoother converged to",k,"after",A,"iterations"),t}},{"../../lib":503}],715:[function(t,e,r){"use strict";var n=t("../../lib").isArray1D;e.exports=function(t,e,r){var i=r("x"),a=i&&i.length,o=r("y"),s=o&&o.length;if(!a&&!s)return!1;if(e._cheater=!i,a&&!n(i)||s&&!n(o))e._length=null;else{var l=a?i.length:1/0;s&&(l=Math.min(l,o.length)),e.a&&e.a.length&&(l=Math.min(l,e.a.length)),e.b&&e.b.length&&(l=Math.min(l,e.b.length)),e._length=l}return!0}},{"../../lib":503}],716:[function(t,e,r){"use strict";var n=t("../../plots/template_attributes").hovertemplateAttrs,i=t("../scattergeo/attributes"),a=t("../../components/colorscale/attributes"),o=t("../../plots/attributes"),s=t("../../components/color/attributes").defaultLine,l=t("../../lib/extend").extendFlat,c=i.marker.line;e.exports=l({locations:{valType:"data_array",editType:"calc"},locationmode:i.locationmode,z:{valType:"data_array",editType:"calc"},geojson:l({},i.geojson,{}),featureidkey:i.featureidkey,text:l({},i.text,{}),hovertext:l({},i.hovertext,{}),marker:{line:{color:l({},c.color,{dflt:s}),width:l({},c.width,{dflt:1}),editType:"calc"},opacity:{valType:"number",arrayOk:!0,min:0,max:1,dflt:1,editType:"style"},editType:"calc"},selected:{marker:{opacity:i.selected.marker.opacity,editType:"plot"},editType:"plot"},unselected:{marker:{opacity:i.unselected.marker.opacity,editType:"plot"},editType:"plot"},hoverinfo:l({},o.hoverinfo,{editType:"calc",flags:["location","z","text","name"]}),hovertemplate:n(),showlegend:l({},o.showlegend,{dflt:!1})},a("",{cLetter:"z",editTypeOverride:"calc"}))},{"../../components/color/attributes":365,"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plots/attributes":550,"../../plots/template_attributes":633,"../scattergeo/attributes":969}],717:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../constants/numerical").BADNUM,a=t("../../components/colorscale/calc"),o=t("../scatter/arrays_to_calcdata"),s=t("../scatter/calc_selection");function l(t){return t&&"string"==typeof t}e.exports=function(t,e){var r,c=e._length,u=new Array(c);r=e.geojson?function(t){return l(t)||n(t)}:l;for(var f=0;f")}(t,f,o),[t]}},{"../../lib":503,"../../plots/cartesian/axes":554,"./attributes":716}],721:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../heatmap/colorbar"),calc:t("./calc"),calcGeoJSON:t("./plot").calcGeoJSON,plot:t("./plot").plot,style:t("./style").style,styleOnSelect:t("./style").styleOnSelect,hoverPoints:t("./hover"),eventData:t("./event_data"),selectPoints:t("./select"),moduleType:"trace",name:"choropleth",basePlotModule:t("../../plots/geo"),categories:["geo","noOpacity","showLegend"],meta:{}}},{"../../plots/geo":589,"../heatmap/colorbar":795,"./attributes":716,"./calc":717,"./defaults":718,"./event_data":719,"./hover":720,"./plot":722,"./select":723,"./style":724}],722:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=t("../../lib/geo_location_utils"),o=t("../../lib/topojson_utils").getTopojsonFeatures,s=t("../../plots/cartesian/autorange").findExtremes,l=t("./style").style;e.exports={calcGeoJSON:function(t,e){for(var r=t[0].trace,n=e[r.geo],i=n._subplot,l=r.locationmode,c=r._length,u="geojson-id"===l?a.extractTraceFeature(t):o(r,i.topojson),f=[],h=[],p=0;p=0;n--){var i=r[n].id;if("string"==typeof i&&0===i.indexOf("water"))for(var a=n+1;a=0;r--)t.removeLayer(e[r][1])},s.dispose=function(){var t=this.subplot.map;this._removeLayers(),t.removeSource(this.sourceId)},e.exports=function(t,e){var r=e[0].trace,i=new o(t,r.uid),a=i.sourceId,s=n(e),l=i.below=t.belowLookup["trace-"+r.uid];return t.map.addSource(a,{type:"geojson",data:s.geojson}),i._addLayers(s,l),e[0].trace._glTrace=i,i}},{"../../plots/mapbox/constants":611,"./convert":726}],730:[function(t,e,r){"use strict";var n=t("../../components/colorscale/attributes"),i=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,a=t("../../plots/template_attributes").hovertemplateAttrs,o=t("../mesh3d/attributes"),s=t("../../plots/attributes"),l=t("../../lib/extend").extendFlat,c={x:{valType:"data_array",editType:"calc+clearAxisTypes"},y:{valType:"data_array",editType:"calc+clearAxisTypes"},z:{valType:"data_array",editType:"calc+clearAxisTypes"},u:{valType:"data_array",editType:"calc"},v:{valType:"data_array",editType:"calc"},w:{valType:"data_array",editType:"calc"},sizemode:{valType:"enumerated",values:["scaled","absolute"],editType:"calc",dflt:"scaled"},sizeref:{valType:"number",editType:"calc",min:0},anchor:{valType:"enumerated",editType:"calc",values:["tip","tail","cm","center"],dflt:"cm"},text:{valType:"string",dflt:"",arrayOk:!0,editType:"calc"},hovertext:{valType:"string",dflt:"",arrayOk:!0,editType:"calc"},hovertemplate:a({editType:"calc"},{keys:["norm"]}),uhoverformat:i("u",1),vhoverformat:i("v",1),whoverformat:i("w",1),xhoverformat:i("x"),yhoverformat:i("y"),zhoverformat:i("z"),showlegend:l({},s.showlegend,{dflt:!1})};l(c,n("",{colorAttr:"u/v/w norm",showScaleDflt:!0,editTypeOverride:"calc"}));["opacity","lightposition","lighting"].forEach((function(t){c[t]=o[t]})),c.hoverinfo=l({},s.hoverinfo,{editType:"calc",flags:["x","y","z","u","v","w","norm","text","name"],dflt:"x+y+z+norm+text+name"}),c.transforms=void 0,e.exports=c},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plots/attributes":550,"../../plots/cartesian/axis_format_attributes":557,"../../plots/template_attributes":633,"../mesh3d/attributes":867}],731:[function(t,e,r){"use strict";var n=t("../../components/colorscale/calc");e.exports=function(t,e){for(var r=e.u,i=e.v,a=e.w,o=Math.min(e.x.length,e.y.length,e.z.length,r.length,i.length,a.length),s=-1/0,l=1/0,c=0;co.level||o.starts.length&&a===o.level)}break;case"constraint":if(n.prefixBoundary=!1,n.edgepaths.length)return;var s=n.x.length,l=n.y.length,c=-1/0,u=1/0;for(r=0;r":p>c&&(n.prefixBoundary=!0);break;case"<":(pc||n.starts.length&&h===u)&&(n.prefixBoundary=!0);break;case"][":f=Math.min(p[0],p[1]),h=Math.max(p[0],p[1]),fc&&(n.prefixBoundary=!0)}}}},{}],738:[function(t,e,r){"use strict";var n=t("../../components/colorscale"),i=t("./make_color_map"),a=t("./end_plus");e.exports={min:"zmin",max:"zmax",calc:function(t,e,r){var o=e.contours,s=e.line,l=o.size||1,c=o.coloring,u=i(e,{isColorbar:!0});if("heatmap"===c){var f=n.extractOpts(e);r._fillgradient=f.reversescale?n.flipScale(f.colorscale):f.colorscale,r._zrange=[f.min,f.max]}else"fill"===c&&(r._fillcolor=u);r._line={color:"lines"===c?u:s.color,width:!1!==o.showlines?s.width:0,dash:s.dash},r._levels={start:o.start,end:a(o),size:l}}}},{"../../components/colorscale":378,"./end_plus":746,"./make_color_map":751}],739:[function(t,e,r){"use strict";e.exports={BOTTOMSTART:[1,9,13,104,713],TOPSTART:[4,6,7,104,713],LEFTSTART:[8,12,14,208,1114],RIGHTSTART:[2,3,11,208,1114],NEWDELTA:[null,[-1,0],[0,-1],[-1,0],[1,0],null,[0,-1],[-1,0],[0,1],[0,1],null,[0,1],[1,0],[1,0],[0,-1]],CHOOSESADDLE:{104:[4,1],208:[2,8],713:[7,13],1114:[11,14]},SADDLEREMAINDER:{1:4,2:8,4:1,7:13,8:2,11:14,13:7,14:11},LABELDISTANCE:2,LABELINCREASE:10,LABELMIN:3,LABELMAX:10,LABELOPTIMIZER:{EDGECOST:1,ANGLECOST:1,NEIGHBORCOST:5,SAMELEVELFACTOR:10,SAMELEVELDISTANCE:5,MAXCOST:100,INITIALSEARCHPOINTS:10,ITERATIONS:5}}},{}],740:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("./label_defaults"),a=t("../../components/color"),o=a.addOpacity,s=a.opacity,l=t("../../constants/filter_ops"),c=l.CONSTRAINT_REDUCTION,u=l.COMPARISON_OPS2;e.exports=function(t,e,r,a,l,f){var h,p,d,m=e.contours,g=r("contours.operation");(m._operation=c[g],function(t,e){var r;-1===u.indexOf(e.operation)?(t("contours.value",[0,1]),Array.isArray(e.value)?e.value.length>2?e.value=e.value.slice(2):0===e.length?e.value=[0,1]:e.length<2?(r=parseFloat(e.value[0]),e.value=[r,r+1]):e.value=[parseFloat(e.value[0]),parseFloat(e.value[1])]:n(e.value)&&(r=parseFloat(e.value),e.value=[r,r+1])):(t("contours.value",0),n(e.value)||(Array.isArray(e.value)?e.value=parseFloat(e.value[0]):e.value=0))}(r,m),"="===g?h=m.showlines=!0:(h=r("contours.showlines"),d=r("fillcolor",o((t.line||{}).color||l,.5))),h)&&(p=r("line.color",d&&s(d)?o(e.fillcolor,1):l),r("line.width",2),r("line.dash"));r("line.smoothing"),i(r,a,p,f)}},{"../../components/color":366,"../../constants/filter_ops":475,"./label_defaults":750,"fast-isnumeric":190}],741:[function(t,e,r){"use strict";var n=t("../../constants/filter_ops"),i=t("fast-isnumeric");function a(t,e){var r,a=Array.isArray(e);function o(t){return i(t)?+t:null}return-1!==n.COMPARISON_OPS2.indexOf(t)?r=o(a?e[0]:e):-1!==n.INTERVAL_OPS.indexOf(t)?r=a?[o(e[0]),o(e[1])]:[o(e),o(e)]:-1!==n.SET_OPS.indexOf(t)&&(r=a?e.map(o):[o(e)]),r}function o(t){return function(e){e=a(t,e);var r=Math.min(e[0],e[1]),n=Math.max(e[0],e[1]);return{start:r,end:n,size:n-r}}}function s(t){return function(e){return{start:e=a(t,e),end:1/0,size:1/0}}}e.exports={"[]":o("[]"),"][":o("]["),">":s(">"),"<":s("<"),"=":s("=")}},{"../../constants/filter_ops":475,"fast-isnumeric":190}],742:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){var i=n("contours.start"),a=n("contours.end"),o=!1===i||!1===a,s=r("contours.size");!(o?e.autocontour=!0:r("autocontour",!1))&&s||r("ncontours")}},{}],743:[function(t,e,r){"use strict";var n=t("../../lib");function i(t){return n.extendFlat({},t,{edgepaths:n.extendDeep([],t.edgepaths),paths:n.extendDeep([],t.paths),starts:n.extendDeep([],t.starts)})}e.exports=function(t,e){var r,a,o,s=function(t){return t.reverse()},l=function(t){return t};switch(e){case"=":case"<":return t;case">":for(1!==t.length&&n.warn("Contour data invalid for the specified inequality operation."),a=t[0],r=0;r1e3){n.warn("Too many contours, clipping at 1000",t);break}return l}},{"../../lib":503,"./constraint_mapping":741,"./end_plus":746}],746:[function(t,e,r){"use strict";e.exports=function(t){return t.end+t.size/1e6}},{}],747:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./constants");function a(t,e,r,n){return Math.abs(t[0]-e[0])20&&e?208===t||1114===t?n=0===r[0]?1:-1:a=0===r[1]?1:-1:-1!==i.BOTTOMSTART.indexOf(t)?a=1:-1!==i.LEFTSTART.indexOf(t)?n=1:-1!==i.TOPSTART.indexOf(t)?a=-1:n=-1;return[n,a]}(f,r,e),p=[s(t,e,[-h[0],-h[1]])],d=t.z.length,m=t.z[0].length,g=e.slice(),v=h.slice();for(c=0;c<1e4;c++){if(f>20?(f=i.CHOOSESADDLE[f][(h[0]||h[1])<0?0:1],t.crossings[u]=i.SADDLEREMAINDER[f]):delete t.crossings[u],!(h=i.NEWDELTA[f])){n.log("Found bad marching index:",f,e,t.level);break}p.push(s(t,e,h)),e[0]+=h[0],e[1]+=h[1],u=e.join(","),a(p[p.length-1],p[p.length-2],o,l)&&p.pop();var y=h[0]&&(e[0]<0||e[0]>m-2)||h[1]&&(e[1]<0||e[1]>d-2);if(e[0]===g[0]&&e[1]===g[1]&&h[0]===v[0]&&h[1]===v[1]||r&&y)break;f=t.crossings[u]}1e4===c&&n.log("Infinite loop in contour?");var x,b,_,w,T,k,A,M,S,E,L,C,P,I,O,z=a(p[0],p[p.length-1],o,l),D=0,R=.2*t.smoothing,F=[],B=0;for(c=1;c=B;c--)if((x=F[c])=B&&x+F[b]M&&S--,t.edgepaths[S]=L.concat(p,E));break}V||(t.edgepaths[M]=p.concat(E))}for(M=0;Mt?0:1)+(e[0][1]>t?0:2)+(e[1][1]>t?0:4)+(e[1][0]>t?0:8);return 5===r||10===r?t>(e[0][0]+e[0][1]+e[1][0]+e[1][1])/4?5===r?713:1114:5===r?104:208:15===r?0:r}e.exports=function(t){var e,r,a,o,s,l,c,u,f,h=t[0].z,p=h.length,d=h[0].length,m=2===p||2===d;for(r=0;r=0&&(n=y,s=l):Math.abs(r[1]-n[1])<.01?Math.abs(r[1]-y[1])<.01&&(y[0]-r[0])*(n[0]-y[0])>=0&&(n=y,s=l):i.log("endpt to newendpt is not vert. or horz.",r,n,y)}if(r=n,s>=0)break;f+="L"+n}if(s===t.edgepaths.length){i.log("unclosed perimeter path");break}h=s,(d=-1===p.indexOf(h))&&(h=p[0],f+="Z")}for(h=0;hn.center?n.right-s:s-n.left)/(u+Math.abs(Math.sin(c)*o)),p=(l>n.middle?n.bottom-l:l-n.top)/(Math.abs(f)+Math.cos(c)*o);if(h<1||p<1)return 1/0;var d=v.EDGECOST*(1/(h-1)+1/(p-1));d+=v.ANGLECOST*c*c;for(var m=s-u,g=l-f,y=s+u,x=l+f,b=0;b2*v.MAXCOST)break;p&&(s/=2),l=(o=c-s/2)+1.5*s}if(h<=v.MAXCOST)return u},r.addLabelData=function(t,e,r,n){var i=e.fontSize,a=e.width+i/3,o=Math.max(0,e.height-i/3),s=t.x,l=t.y,c=t.theta,u=Math.sin(c),f=Math.cos(c),h=function(t,e){return[s+t*f-e*u,l+t*u+e*f]},p=[h(-a/2,-o/2),h(-a/2,o/2),h(a/2,o/2),h(a/2,-o/2)];r.push({text:e.text,x:s,y:l,dy:e.dy,theta:c,level:e.level,width:a,height:o}),n.push(p)},r.drawLabels=function(t,e,r,a,o){var l=t.selectAll("text").data(e,(function(t){return t.text+","+t.x+","+t.y+","+t.theta}));if(l.exit().remove(),l.enter().append("text").attr({"data-notex":1,"text-anchor":"middle"}).each((function(t){var e=t.x+Math.sin(t.theta)*t.dy,i=t.y-Math.cos(t.theta)*t.dy;n.select(this).text(t.text).attr({x:e,y:i,transform:"rotate("+180*t.theta/Math.PI+" "+e+" "+i+")"}).call(s.convertToTspans,r)})),o){for(var c="",u=0;ur.end&&(r.start=r.end=(r.start+r.end)/2),t._input.contours||(t._input.contours={}),i.extendFlat(t._input.contours,{start:r.start,end:r.end,size:r.size}),t._input.autocontour=!0}else if("constraint"!==r.type){var c,u=r.start,f=r.end,h=t._input.contours;if(u>f&&(r.start=h.start=f,f=r.end=h.end=u,u=r.start),!(r.size>0))c=u===f?1:a(u,f,t.ncontours).dtick,h.size=r.size=c}}},{"../../lib":503,"../../plots/cartesian/axes":554}],755:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../components/drawing"),a=t("../heatmap/style"),o=t("./make_color_map");e.exports=function(t){var e=n.select(t).selectAll("g.contour");e.style("opacity",(function(t){return t[0].trace.opacity})),e.each((function(t){var e=n.select(this),r=t[0].trace,a=r.contours,s=r.line,l=a.size||1,c=a.start,u="constraint"===a.type,f=!u&&"lines"===a.coloring,h=!u&&"fill"===a.coloring,p=f||h?o(r):null;e.selectAll("g.contourlevel").each((function(t){n.select(this).selectAll("path").call(i.lineGroupStyle,s.width,f?p(t.level):s.color,s.dash)}));var d=a.labelfont;if(e.selectAll("g.contourlabels text").each((function(t){i.font(n.select(this),{family:d.family,size:d.size,color:d.color||(f?p(t.level):s.color)})})),u)e.selectAll("g.contourfill path").style("fill",r.fillcolor);else if(h){var m;e.selectAll("g.contourfill path").style("fill",(function(t){return void 0===m&&(m=t.level),p(t.level+.5*l)})),void 0===m&&(m=c),e.selectAll("g.contourbg path").style("fill",p(m-.5*l))}})),a(t)}},{"../../components/drawing":388,"../heatmap/style":805,"./make_color_map":751,"@plotly/d3":58}],756:[function(t,e,r){"use strict";var n=t("../../components/colorscale/defaults"),i=t("./label_defaults");e.exports=function(t,e,r,a,o){var s,l=r("contours.coloring"),c="";"fill"===l&&(s=r("contours.showlines")),!1!==s&&("lines"!==l&&(c=r("line.color","#000")),r("line.width",.5),r("line.dash")),"none"!==l&&(!0!==t.showlegend&&(e.showlegend=!1),e._dfltShowLegend=!1,n(t,e,a,r,{prefix:"",cLetter:"z"})),r("line.smoothing"),i(r,a,c,o)}},{"../../components/colorscale/defaults":376,"./label_defaults":750}],757:[function(t,e,r){"use strict";var n=t("../heatmap/attributes"),i=t("../contour/attributes"),a=t("../../components/colorscale/attributes"),o=t("../../lib/extend").extendFlat,s=i.contours;e.exports=o({carpet:{valType:"string",editType:"calc"},z:n.z,a:n.x,a0:n.x0,da:n.dx,b:n.y,b0:n.y0,db:n.dy,text:n.text,hovertext:n.hovertext,transpose:n.transpose,atype:n.xtype,btype:n.ytype,fillcolor:i.fillcolor,autocontour:i.autocontour,ncontours:i.ncontours,contours:{type:s.type,start:s.start,end:s.end,size:s.size,coloring:{valType:"enumerated",values:["fill","lines","none"],dflt:"fill",editType:"calc"},showlines:s.showlines,showlabels:s.showlabels,labelfont:s.labelfont,labelformat:s.labelformat,operation:s.operation,value:s.value,editType:"calc",impliedEdits:{autocontour:!1}},line:{color:i.line.color,width:i.line.width,dash:i.line.dash,smoothing:i.line.smoothing,editType:"plot"},transforms:void 0},a("",{cLetter:"z",autoColorDflt:!1}))},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../contour/attributes":735,"../heatmap/attributes":792}],758:[function(t,e,r){"use strict";var n=t("../../components/colorscale/calc"),i=t("../../lib"),a=t("../heatmap/convert_column_xyz"),o=t("../heatmap/clean_2d_array"),s=t("../heatmap/interp2d"),l=t("../heatmap/find_empties"),c=t("../heatmap/make_bound_array"),u=t("./defaults"),f=t("../carpet/lookup_carpetid"),h=t("../contour/set_contours");e.exports=function(t,e){var r=e._carpetTrace=f(t,e);if(r&&r.visible&&"legendonly"!==r.visible){if(!e.a||!e.b){var p=t.data[r.index],d=t.data[e.index];d.a||(d.a=p.a),d.b||(d.b=p.b),u(d,e,e._defaultColor,t._fullLayout)}var m=function(t,e){var r,u,f,h,p,d,m,g=e._carpetTrace,v=g.aaxis,y=g.baxis;v._minDtick=0,y._minDtick=0,i.isArray1D(e.z)&&a(e,v,y,"a","b",["z"]);r=e._a=e._a||e.a,h=e._b=e._b||e.b,r=r?v.makeCalcdata(e,"_a"):[],h=h?y.makeCalcdata(e,"_b"):[],u=e.a0||0,f=e.da||1,p=e.b0||0,d=e.db||1,m=e._z=o(e._z||e.z,e.transpose),e._emptypoints=l(m),s(m,e._emptypoints);var x=i.maxRowLength(m),b="scaled"===e.xtype?"":r,_=c(e,b,u,f,x,v),w="scaled"===e.ytype?"":h,T=c(e,w,p,d,m.length,y),k={a:_,b:T,z:m};"levels"===e.contours.type&&"none"!==e.contours.coloring&&n(t,e,{vals:m,containerStr:"",cLetter:"z"});return[k]}(t,e);return h(e,e._z),m}}},{"../../components/colorscale/calc":374,"../../lib":503,"../carpet/lookup_carpetid":708,"../contour/set_contours":754,"../heatmap/clean_2d_array":794,"../heatmap/convert_column_xyz":796,"../heatmap/find_empties":798,"../heatmap/interp2d":801,"../heatmap/make_bound_array":803,"./defaults":759}],759:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../heatmap/xyz_defaults"),a=t("./attributes"),o=t("../contour/constraint_defaults"),s=t("../contour/contours_defaults"),l=t("../contour/style_defaults");e.exports=function(t,e,r,c){function u(r,i){return n.coerce(t,e,a,r,i)}if(u("carpet"),t.a&&t.b){if(!i(t,e,u,c,"a","b"))return void(e.visible=!1);u("text"),"constraint"===u("contours.type")?o(t,e,u,c,r,{hasHover:!1}):(s(t,e,u,(function(r){return n.coerce2(t,e,a,r)})),l(t,e,u,c,{hasHover:!1}))}else e._defaultColor=r,e._length=null}},{"../../lib":503,"../contour/constraint_defaults":740,"../contour/contours_defaults":742,"../contour/style_defaults":756,"../heatmap/xyz_defaults":807,"./attributes":757}],760:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../contour/colorbar"),calc:t("./calc"),plot:t("./plot"),style:t("../contour/style"),moduleType:"trace",name:"contourcarpet",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","carpet","contour","symbols","showLegend","hasLines","carpetDependent","noHover","noSortingByValue"],meta:{}}},{"../../plots/cartesian":568,"../contour/colorbar":738,"../contour/style":755,"./attributes":757,"./calc":758,"./defaults":759,"./plot":761}],761:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../carpet/map_1d_array"),a=t("../carpet/makepath"),o=t("../../components/drawing"),s=t("../../lib"),l=t("../contour/make_crossings"),c=t("../contour/find_all_paths"),u=t("../contour/plot"),f=t("../contour/constants"),h=t("../contour/convert_to_constraints"),p=t("../contour/empty_pathinfo"),d=t("../contour/close_boundaries"),m=t("../carpet/lookup_carpetid"),g=t("../carpet/axis_aligned_line");function v(t,e,r){var n=t.getPointAtLength(e),i=t.getPointAtLength(r),a=i.x-n.x,o=i.y-n.y,s=Math.sqrt(a*a+o*o);return[a/s,o/s]}function y(t){var e=Math.sqrt(t[0]*t[0]+t[1]*t[1]);return[t[0]/e,t[1]/e]}function x(t,e){var r=Math.abs(t[0]*e[0]+t[1]*e[1]);return Math.sqrt(1-r*r)/r}e.exports=function(t,e,r,b){var _=e.xaxis,w=e.yaxis;s.makeTraceGroups(b,r,"contour").each((function(r){var b=n.select(this),T=r[0],k=T.trace,A=k._carpetTrace=m(t,k),M=t.calcdata[A.index][0];if(A.visible&&"legendonly"!==A.visible){var S=T.a,E=T.b,L=k.contours,C=p(L,e,T),P="constraint"===L.type,I=L._operation,O=P?"="===I?"lines":"fill":L.coloring,z=[[S[0],E[E.length-1]],[S[S.length-1],E[E.length-1]],[S[S.length-1],E[0]],[S[0],E[0]]];l(C);var D=1e-8*(S[S.length-1]-S[0]),R=1e-8*(E[E.length-1]-E[0]);c(C,D,R);var F,B,N,j,U=C;"constraint"===L.type&&(U=h(C,I)),function(t,e){var r,n,i,a,o,s,l,c,u;for(r=0;r=0;j--)F=M.clipsegments[j],B=i([],F.x,_.c2p),N=i([],F.y,w.c2p),B.reverse(),N.reverse(),V.push(a(B,N,F.bicubic));var H="M"+V.join("L")+"Z";!function(t,e,r,n,o,l){var c,u,f,h,p=s.ensureSingle(t,"g","contourbg").selectAll("path").data("fill"!==l||o?[]:[0]);p.enter().append("path"),p.exit().remove();var d=[];for(h=0;h=0&&(h=L,d=m):Math.abs(f[1]-h[1])=0&&(h=L,d=m):s.log("endpt to newendpt is not vert. or horz.",f,h,L)}if(d>=0)break;y+=S(f,h),f=h}if(d===e.edgepaths.length){s.log("unclosed perimeter path");break}u=d,(b=-1===x.indexOf(u))&&(u=x[0],y+=S(f,h)+"Z",f=null)}for(u=0;ug&&(n.max=g);n.len=n.max-n.min}(this,r,t,n,c,e.height),!(n.len<(e.width+e.height)*f.LABELMIN)))for(var i=Math.min(Math.ceil(n.len/I),f.LABELMAX),a=0;a0?+p[u]:0),f.push({type:"Feature",geometry:{type:"Point",coordinates:v},properties:y})}}var b=o.extractOpts(e),_=b.reversescale?o.flipScale(b.colorscale):b.colorscale,w=_[0][1],T=["interpolate",["linear"],["heatmap-density"],0,a.opacity(w)<1?w:a.addOpacity(w,0)];for(u=1;u<_.length;u++)T.push(_[u][0],_[u][1]);var k=["interpolate",["linear"],["get","z"],b.min,0,b.max,1];return i.extendFlat(c.heatmap.paint,{"heatmap-weight":d?k:1/(b.max-b.min),"heatmap-color":T,"heatmap-radius":m?{type:"identity",property:"r"}:e.radius,"heatmap-opacity":e.opacity}),c.geojson={type:"FeatureCollection",features:f},c.heatmap.layout.visibility="visible",c}},{"../../components/color":366,"../../components/colorscale":378,"../../constants/numerical":479,"../../lib":503,"../../lib/geojson_utils":497,"fast-isnumeric":190}],765:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../components/colorscale/defaults"),a=t("./attributes");e.exports=function(t,e,r,o){function s(r,i){return n.coerce(t,e,a,r,i)}var l=s("lon")||[],c=s("lat")||[],u=Math.min(l.length,c.length);u?(e._length=u,s("z"),s("radius"),s("below"),s("text"),s("hovertext"),s("hovertemplate"),i(t,e,o,s,{prefix:"",cLetter:"z"})):e.visible=!1}},{"../../components/colorscale/defaults":376,"../../lib":503,"./attributes":762}],766:[function(t,e,r){"use strict";e.exports=function(t,e){return t.lon=e.lon,t.lat=e.lat,t.z=e.z,t}},{}],767:[function(t,e,r){"use strict";var n=t("../../plots/cartesian/axes"),i=t("../scattermapbox/hover").hoverPoints,a=t("../scattermapbox/hover").getExtraText;e.exports=function(t,e,r){var o=i(t,e,r);if(o){var s=o[0],l=s.cd,c=l[0].trace,u=l[s.index];if(delete s.color,"z"in u){var f=s.subplot.mockAxis;s.z=u.z,s.zLabel=n.tickText(f,f.c2l(u.z),"hover").text}return s.extraText=a(c,u,l[0].t.labels),[s]}}},{"../../plots/cartesian/axes":554,"../scattermapbox/hover":998}],768:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../heatmap/colorbar"),formatLabels:t("../scattermapbox/format_labels"),calc:t("./calc"),plot:t("./plot"),hoverPoints:t("./hover"),eventData:t("./event_data"),getBelow:function(t,e){for(var r=e.getMapLayers(),n=0;n=0;r--)t.removeLayer(e[r][1])},o.dispose=function(){var t=this.subplot.map;this._removeLayers(),t.removeSource(this.sourceId)},e.exports=function(t,e){var r=e[0].trace,i=new a(t,r.uid),o=i.sourceId,s=n(e),l=i.below=t.belowLookup["trace-"+r.uid];return t.map.addSource(o,{type:"geojson",data:s.geojson}),i._addLayers(s,l),i}},{"../../plots/mapbox/constants":611,"./convert":764}],770:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e){for(var r=0;r"),l.color=function(t,e){var r=t.marker,i=e.mc||r.color,a=e.mlc||r.line.color,o=e.mlw||r.line.width;if(n(i))return i;if(n(a)&&o)return a}(u,h),[l]}}},{"../../components/color":366,"../../lib":503,"../bar/hover":655}],778:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults").supplyDefaults,crossTraceDefaults:t("./defaults").crossTraceDefaults,supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc"),crossTraceCalc:t("./cross_trace_calc"),plot:t("./plot"),style:t("./style").style,hoverPoints:t("./hover"),eventData:t("./event_data"),selectPoints:t("../bar/select"),moduleType:"trace",name:"funnel",basePlotModule:t("../../plots/cartesian"),categories:["bar-like","cartesian","svg","oriented","showLegend","zoomScale"],meta:{}}},{"../../plots/cartesian":568,"../bar/select":660,"./attributes":771,"./calc":772,"./cross_trace_calc":774,"./defaults":775,"./event_data":776,"./hover":777,"./layout_attributes":779,"./layout_defaults":780,"./plot":781,"./style":782}],779:[function(t,e,r){"use strict";e.exports={funnelmode:{valType:"enumerated",values:["stack","group","overlay"],dflt:"stack",editType:"calc"},funnelgap:{valType:"number",min:0,max:1,editType:"calc"},funnelgroupgap:{valType:"number",min:0,max:1,dflt:0,editType:"calc"}}},{}],780:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e,r){var a=!1;function o(r,a){return n.coerce(t,e,i,r,a)}for(var s=0;s path").each((function(t){if(!t.isBlank){var e=s.marker;n.select(this).call(a.fill,t.mc||e.color).call(a.stroke,t.mlc||e.line.color).call(i.dashLine,e.line.dash,t.mlw||e.line.width).style("opacity",s.selectedpoints&&!t.selected?o:1)}})),c(r,s,t),r.selectAll(".regions").each((function(){n.select(this).selectAll("path").style("stroke-width",0).call(a.fill,s.connector.fillcolor)})),r.selectAll(".lines").each((function(){var t=s.connector.line;i.lineGroupStyle(n.select(this).selectAll("path"),t.width,t.color,t.dash)}))}))}}},{"../../components/color":366,"../../components/drawing":388,"../../constants/interactions":478,"../bar/style":662,"../bar/uniform_text":664,"@plotly/d3":58}],783:[function(t,e,r){"use strict";var n=t("../pie/attributes"),i=t("../../plots/attributes"),a=t("../../plots/domain").attributes,o=t("../../plots/template_attributes").hovertemplateAttrs,s=t("../../plots/template_attributes").texttemplateAttrs,l=t("../../lib/extend").extendFlat;e.exports={labels:n.labels,label0:n.label0,dlabel:n.dlabel,values:n.values,marker:{colors:n.marker.colors,line:{color:l({},n.marker.line.color,{dflt:null}),width:l({},n.marker.line.width,{dflt:1}),editType:"calc"},editType:"calc"},text:n.text,hovertext:n.hovertext,scalegroup:l({},n.scalegroup,{}),textinfo:l({},n.textinfo,{flags:["label","text","value","percent"]}),texttemplate:s({editType:"plot"},{keys:["label","color","value","text","percent"]}),hoverinfo:l({},i.hoverinfo,{flags:["label","text","value","percent","name"]}),hovertemplate:o({},{keys:["label","color","value","text","percent"]}),textposition:l({},n.textposition,{values:["inside","none"],dflt:"inside"}),textfont:n.textfont,insidetextfont:n.insidetextfont,title:{text:n.title.text,font:n.title.font,position:l({},n.title.position,{values:["top left","top center","top right"],dflt:"top center"}),editType:"plot"},domain:a({name:"funnelarea",trace:!0,editType:"calc"}),aspectratio:{valType:"number",min:0,dflt:1,editType:"plot"},baseratio:{valType:"number",min:0,max:1,dflt:.333,editType:"plot"}}},{"../../lib/extend":493,"../../plots/attributes":550,"../../plots/domain":584,"../../plots/template_attributes":633,"../pie/attributes":901}],784:[function(t,e,r){"use strict";var n=t("../../plots/plots");r.name="funnelarea",r.plot=function(t,e,i,a){n.plotBasePlot(r.name,t,e,i,a)},r.clean=function(t,e,i,a){n.cleanBasePlot(r.name,t,e,i,a)}},{"../../plots/plots":619}],785:[function(t,e,r){"use strict";var n=t("../pie/calc");e.exports={calc:function(t,e){return n.calc(t,e)},crossTraceCalc:function(t){n.crossTraceCalc(t,{type:"funnelarea"})}}},{"../pie/calc":903}],786:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes"),a=t("../../plots/domain").defaults,o=t("../bar/defaults").handleText,s=t("../pie/defaults").handleLabelsAndValues;e.exports=function(t,e,r,l){function c(r,a){return n.coerce(t,e,i,r,a)}var u=c("labels"),f=c("values"),h=s(u,f),p=h.len;if(e._hasLabels=h.hasLabels,e._hasValues=h.hasValues,!e._hasLabels&&e._hasValues&&(c("label0"),c("dlabel")),p){e._length=p,c("marker.line.width")&&c("marker.line.color",l.paper_bgcolor),c("marker.colors"),c("scalegroup");var d,m=c("text"),g=c("texttemplate");if(g||(d=c("textinfo",Array.isArray(m)?"text+percent":"percent")),c("hovertext"),c("hovertemplate"),g||d&&"none"!==d){var v=c("textposition");o(t,e,l,c,v,{moduleHasSelected:!1,moduleHasUnselected:!1,moduleHasConstrain:!1,moduleHasCliponaxis:!1,moduleHasTextangle:!1,moduleHasInsideanchor:!1})}a(e,l,c),c("title.text")&&(c("title.position"),n.coerceFont(c,"title.font",l.font)),c("aspectratio"),c("baseratio")}else e.visible=!1}},{"../../lib":503,"../../plots/domain":584,"../bar/defaults":652,"../pie/defaults":904,"./attributes":783}],787:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"funnelarea",basePlotModule:t("./base_plot"),categories:["pie-like","funnelarea","showLegend"],attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc").calc,crossTraceCalc:t("./calc").crossTraceCalc,plot:t("./plot"),style:t("./style"),styleOne:t("../pie/style_one"),meta:{}}},{"../pie/style_one":912,"./attributes":783,"./base_plot":784,"./calc":785,"./defaults":786,"./layout_attributes":788,"./layout_defaults":789,"./plot":790,"./style":791}],788:[function(t,e,r){"use strict";var n=t("../pie/layout_attributes").hiddenlabels;e.exports={hiddenlabels:n,funnelareacolorway:{valType:"colorlist",editType:"calc"},extendfunnelareacolors:{valType:"boolean",dflt:!0,editType:"calc"}}},{"../pie/layout_attributes":908}],789:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e){function r(r,a){return n.coerce(t,e,i,r,a)}r("hiddenlabels"),r("funnelareacolorway",e.colorway),r("extendfunnelareacolors")}},{"../../lib":503,"./layout_attributes":788}],790:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../components/drawing"),a=t("../../lib"),o=a.strScale,s=a.strTranslate,l=t("../../lib/svg_text_utils"),c=t("../bar/plot").toMoveInsideBar,u=t("../bar/uniform_text"),f=u.recordMinTextSize,h=u.clearMinTextSize,p=t("../pie/helpers"),d=t("../pie/plot"),m=d.attachFxHandlers,g=d.determineInsideTextFont,v=d.layoutAreas,y=d.prerenderTitles,x=d.positionTitleOutside,b=d.formatSliceLabel;function _(t,e){return"l"+(e[0]-t[0])+","+(e[1]-t[1])}e.exports=function(t,e){var r=t._fullLayout;h("funnelarea",r),y(e,t),v(e,r._size),a.makeTraceGroups(r._funnelarealayer,e,"trace").each((function(e){var u=n.select(this),h=e[0],d=h.trace;!function(t){if(!t.length)return;var e=t[0],r=e.trace,n=r.aspectratio,i=r.baseratio;i>.999&&(i=.999);var a,o=Math.pow(i,2),s=e.vTotal,l=s,c=s*o/(1-o)/s;function u(){var t,e={x:t=Math.sqrt(c),y:-t};return[e.x,e.y]}var f,h,p=[];for(p.push(u()),f=t.length-1;f>-1;f--)if(!(h=t[f]).hidden){var d=h.v/l;c+=d,p.push(u())}var m=1/0,g=-1/0;for(f=0;f-1;f--)if(!(h=t[f]).hidden){var A=p[k+=1][0],M=p[k][1];h.TL=[-A,M],h.TR=[A,M],h.BL=w,h.BR=T,h.pxmid=(S=h.TR,E=h.BR,[.5*(S[0]+E[0]),.5*(S[1]+E[1])]),w=h.TL,T=h.TR}var S,E}(e),u.each((function(){var u=n.select(this).selectAll("g.slice").data(e);u.enter().append("g").classed("slice",!0),u.exit().remove(),u.each((function(o,s){if(o.hidden)n.select(this).selectAll("path,g").remove();else{o.pointNumber=o.i,o.curveNumber=d.index;var u=h.cx,v=h.cy,y=n.select(this),x=y.selectAll("path.surface").data([o]);x.enter().append("path").classed("surface",!0).style({"pointer-events":"all"}),y.call(m,t,e);var w="M"+(u+o.TR[0])+","+(v+o.TR[1])+_(o.TR,o.BR)+_(o.BR,o.BL)+_(o.BL,o.TL)+"Z";x.attr("d",w),b(t,o,h);var T=p.castOption(d.textposition,o.pts),k=y.selectAll("g.slicetext").data(o.text&&"none"!==T?[0]:[]);k.enter().append("g").classed("slicetext",!0),k.exit().remove(),k.each((function(){var h=a.ensureSingle(n.select(this),"text","",(function(t){t.attr("data-notex",1)})),p=a.ensureUniformFontSize(t,g(d,o,r.font));h.text(o.text).attr({class:"slicetext",transform:"","text-anchor":"middle"}).call(i.font,p).call(l.convertToTspans,t);var m,y,x,b=i.bBox(h.node()),_=Math.min(o.BL[1],o.BR[1])+v,w=Math.max(o.TL[1],o.TR[1])+v;y=Math.max(o.TL[0],o.BL[0])+u,x=Math.min(o.TR[0],o.BR[0])+u,(m=c(y,x,_,w,b,{isHorizontal:!0,constrained:!0,angle:0,anchor:"middle"})).fontSize=p.size,f(d.type,m,r),e[s].transform=m,h.attr("transform",a.getTextTransform(m))}))}}));var v=n.select(this).selectAll("g.titletext").data(d.title.text?[0]:[]);v.enter().append("g").classed("titletext",!0),v.exit().remove(),v.each((function(){var e=a.ensureSingle(n.select(this),"text","",(function(t){t.attr("data-notex",1)})),c=d.title.text;d._meta&&(c=a.templateString(c,d._meta)),e.text(c).attr({class:"titletext",transform:"","text-anchor":"middle"}).call(i.font,d.title.font).call(l.convertToTspans,t);var u=x(h,r._size);e.attr("transform",s(u.x,u.y)+o(Math.min(1,u.scale))+s(u.tx,u.ty))}))}))}))}},{"../../components/drawing":388,"../../lib":503,"../../lib/svg_text_utils":529,"../bar/plot":659,"../bar/uniform_text":664,"../pie/helpers":906,"../pie/plot":910,"@plotly/d3":58}],791:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../pie/style_one"),a=t("../bar/uniform_text").resizeText;e.exports=function(t){var e=t._fullLayout._funnelarealayer.selectAll(".trace");a(t,e,"funnelarea"),e.each((function(t){var e=t[0].trace,r=n.select(this);r.style({opacity:e.opacity}),r.selectAll("path.surface").each((function(t){n.select(this).call(i,t,e)}))}))}},{"../bar/uniform_text":664,"../pie/style_one":912,"@plotly/d3":58}],792:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../plots/attributes"),a=t("../../plots/font_attributes"),o=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,s=t("../../plots/template_attributes").hovertemplateAttrs,l=t("../../plots/template_attributes").texttemplateAttrs,c=t("../../components/colorscale/attributes"),u=t("../../lib/extend").extendFlat;e.exports=u({z:{valType:"data_array",editType:"calc"},x:u({},n.x,{impliedEdits:{xtype:"array"}}),x0:u({},n.x0,{impliedEdits:{xtype:"scaled"}}),dx:u({},n.dx,{impliedEdits:{xtype:"scaled"}}),y:u({},n.y,{impliedEdits:{ytype:"array"}}),y0:u({},n.y0,{impliedEdits:{ytype:"scaled"}}),dy:u({},n.dy,{impliedEdits:{ytype:"scaled"}}),xperiod:u({},n.xperiod,{impliedEdits:{xtype:"scaled"}}),yperiod:u({},n.yperiod,{impliedEdits:{ytype:"scaled"}}),xperiod0:u({},n.xperiod0,{impliedEdits:{xtype:"scaled"}}),yperiod0:u({},n.yperiod0,{impliedEdits:{ytype:"scaled"}}),xperiodalignment:u({},n.xperiodalignment,{impliedEdits:{xtype:"scaled"}}),yperiodalignment:u({},n.yperiodalignment,{impliedEdits:{ytype:"scaled"}}),text:{valType:"data_array",editType:"calc"},hovertext:{valType:"data_array",editType:"calc"},transpose:{valType:"boolean",dflt:!1,editType:"calc"},xtype:{valType:"enumerated",values:["array","scaled"],editType:"calc+clearAxisTypes"},ytype:{valType:"enumerated",values:["array","scaled"],editType:"calc+clearAxisTypes"},zsmooth:{valType:"enumerated",values:["fast","best",!1],dflt:!1,editType:"calc"},hoverongaps:{valType:"boolean",dflt:!0,editType:"none"},connectgaps:{valType:"boolean",editType:"calc"},xgap:{valType:"number",dflt:0,min:0,editType:"plot"},ygap:{valType:"number",dflt:0,min:0,editType:"plot"},xhoverformat:o("x"),yhoverformat:o("y"),zhoverformat:o("z",1),hovertemplate:s(),texttemplate:l({arrayOk:!1,editType:"plot"},{keys:["x","y","z","text"]}),textfont:a({editType:"plot",autoSize:!0,autoColor:!0,colorEditType:"style"}),showlegend:u({},i.showlegend,{dflt:!1})},{transforms:void 0},c("",{cLetter:"z",autoColorDflt:!1}))},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plots/attributes":550,"../../plots/cartesian/axis_format_attributes":557,"../../plots/font_attributes":585,"../../plots/template_attributes":633,"../scatter/attributes":927}],793:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib"),a=t("../../plots/cartesian/axes"),o=t("../../plots/cartesian/align_period"),s=t("../histogram2d/calc"),l=t("../../components/colorscale/calc"),c=t("./convert_column_xyz"),u=t("./clean_2d_array"),f=t("./interp2d"),h=t("./find_empties"),p=t("./make_bound_array"),d=t("../../constants/numerical").BADNUM;function m(t){for(var e=[],r=t.length,n=0;nD){O("x scale is not linear");break}}if(x.length&&"fast"===P){var R=(x[x.length-1]-x[0])/(x.length-1),F=Math.abs(R/100);for(k=0;kF){O("y scale is not linear");break}}}var B=i.maxRowLength(T),N="scaled"===e.xtype?"":r,j=p(e,N,g,v,B,M),U="scaled"===e.ytype?"":x,V=p(e,U,b,_,T.length,S);C||(e._extremes[M._id]=a.findExtremes(M,j),e._extremes[S._id]=a.findExtremes(S,V));var H={x:j,y:V,z:T,text:e._text||e.text,hovertext:e._hovertext||e.hovertext};if(e.xperiodalignment&&y&&(H.orig_x=y),e.yperiodalignment&&w&&(H.orig_y=w),N&&N.length===j.length-1&&(H.xCenter=N),U&&U.length===V.length-1&&(H.yCenter=U),L&&(H.xRanges=A.xRanges,H.yRanges=A.yRanges,H.pts=A.pts),E||l(t,e,{vals:T,cLetter:"z"}),E&&e.contours&&"heatmap"===e.contours.coloring){var q={type:"contour"===e.type?"heatmap":"histogram2d",xcalendar:e.xcalendar,ycalendar:e.ycalendar};H.xfill=p(q,N,g,v,B,M),H.yfill=p(q,U,b,_,T.length,S)}return[H]}},{"../../components/colorscale/calc":374,"../../constants/numerical":479,"../../lib":503,"../../plots/cartesian/align_period":551,"../../plots/cartesian/axes":554,"../../registry":638,"../histogram2d/calc":826,"./clean_2d_array":794,"./convert_column_xyz":796,"./find_empties":798,"./interp2d":801,"./make_bound_array":803}],794:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../lib"),a=t("../../constants/numerical").BADNUM;e.exports=function(t,e,r,o){var s,l,c,u,f,h;function p(t){if(n(t))return+t}if(e&&e.transpose){for(s=0,f=0;f=0;o--)(s=((f[[(r=(a=h[o])[0])-1,i=a[1]]]||m)[2]+(f[[r+1,i]]||m)[2]+(f[[r,i-1]]||m)[2]+(f[[r,i+1]]||m)[2])/20)&&(l[a]=[r,i,s],h.splice(o,1),c=!0);if(!c)throw"findEmpties iterated with no new neighbors";for(a in l)f[a]=l[a],u.push(l[a])}return u.sort((function(t,e){return e[2]-t[2]}))}},{"../../lib":503}],799:[function(t,e,r){"use strict";var n=t("../../components/fx"),i=t("../../lib"),a=t("../../plots/cartesian/axes"),o=t("../../components/colorscale").extractOpts;e.exports=function(t,e,r,s,l){l||(l={});var c,u,f,h,p=l.isContour,d=t.cd[0],m=d.trace,g=t.xa,v=t.ya,y=d.x,x=d.y,b=d.z,_=d.xCenter,w=d.yCenter,T=d.zmask,k=m.zhoverformat,A=y,M=x;if(!1!==t.index){try{f=Math.round(t.index[1]),h=Math.round(t.index[0])}catch(e){return void i.error("Error hovering on heatmap, pointNumber must be [row,col], found:",t.index)}if(f<0||f>=b[0].length||h<0||h>b.length)return}else{if(n.inbox(e-y[0],e-y[y.length-1],0)>0||n.inbox(r-x[0],r-x[x.length-1],0)>0)return;if(p){var S;for(A=[2*y[0]-y[1]],S=1;Sm&&(v=Math.max(v,Math.abs(t[a][o]-d)/(g-m))))}return v}e.exports=function(t,e){var r,i=1;for(o(t,e),r=0;r.01;r++)i=o(t,e,a(i));return i>.01&&n.log("interp2d didn't converge quickly",i),t}},{"../../lib":503}],802:[function(t,e,r){"use strict";var n=t("../../lib");e.exports=function(t,e){t("texttemplate");var r=n.extendFlat({},e.font,{color:"auto",size:"auto"});n.coerceFont(t,"textfont",r)}},{"../../lib":503}],803:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib").isArrayOrTypedArray;e.exports=function(t,e,r,a,o,s){var l,c,u,f=[],h=n.traceIs(t,"contour"),p=n.traceIs(t,"histogram"),d=n.traceIs(t,"gl2d");if(i(e)&&e.length>1&&!p&&"category"!==s.type){var m=e.length;if(!(m<=o))return h?e.slice(0,o):e.slice(0,o+1);if(h||d)f=e.slice(0,o);else if(1===o)f=[e[0]-.5,e[0]+.5];else{for(f=[1.5*e[0]-.5*e[1]],u=1;u0;)_=w.c2p(R[S]),S--;for(_0;)M=T.c2p(F[S]),S--;if(MGt||Gt>T._length))for(E=Ut;EWt||Wt>w._length)){var Xt=u({x:Yt,y:qt},I,t._fullLayout);Xt.x=Yt,Xt.y=qt;var Zt=P.z[S][E];void 0===Zt?(Xt.z="",Xt.zLabel=""):(Xt.z=Zt,Xt.zLabel=s.tickText(Ft,Zt,"hover").text);var Jt=P.text&&P.text[S]&&P.text[S][E];void 0!==Jt&&!1!==Jt||(Jt=""),Xt.text=Jt;var Kt=l.texttemplateString(Dt,Xt,t._fullLayout._d3locale,Xt,I._meta||{});if(Kt){var Qt=Kt.split("
    "),$t=Qt.length,te=0;for(L=0;L<$t;L++)te=Math.max(te,Qt[L].length);Ht.push({l:$t,c:te,t:Kt,x:Wt,y:Gt,z:Zt})}}}}var ee=I.textfont,re=ee.family,ne=ee.size,ie=t._fullLayout.font.size;if(!ne||"auto"===ne){var ae=1/0,oe=1/0,se=0,le=0;for(L=0;L0&&(a=!0);for(var l=0;la){var o=a-r[t];return r[t]=a,o}}return 0},max:function(t,e,r,i){var a=i[e];if(n(a)){if(a=Number(a),!n(r[t]))return r[t]=a,a;if(r[t]c?t>o?t>1.1*i?i:t>1.1*a?a:o:t>s?s:t>l?l:c:Math.pow(10,Math.floor(Math.log(t)/Math.LN10))}function p(t,e,r,n,a,s){if(n&&t>o){var l=d(e,a,s),c=d(r,a,s),u=t===i?0:1;return l[u]!==c[u]}return Math.floor(r/t)-Math.floor(e/t)>.1}function d(t,e,r){var n=e.c2d(t,i,r).split("-");return""===n[0]&&(n.unshift(),n[0]="-"+n[0]),n}e.exports=function(t,e,r,n,a){var s,l,c=-1.1*e,h=-.1*e,p=t-h,d=r[0],m=r[1],g=Math.min(f(d+h,d+p,n,a),f(m+h,m+p,n,a)),v=Math.min(f(d+c,d+h,n,a),f(m+c,m+h,n,a));if(g>v&&vo){var y=s===i?1:6,x=s===i?"M12":"M1";return function(e,r){var o=n.c2d(e,i,a),s=o.indexOf("-",y);s>0&&(o=o.substr(0,s));var c=n.d2c(o,0,a);if(cr.r2l(B)&&(j=o.tickIncrement(j,b.size,!0,p)),z.start=r.l2r(j),F||i.nestedProperty(e,v+".start").set(z.start)}var U=b.end,V=r.r2l(O.end),H=void 0!==V;if((b.endFound||H)&&V!==r.r2l(U)){var q=H?V:i.aggNums(Math.max,null,d);z.end=r.l2r(q),H||i.nestedProperty(e,v+".start").set(z.end)}var G="autobin"+s;return!1===e._input[G]&&(e._input[v]=i.extendFlat({},e[v]||{}),delete e._input[G],delete e[G]),[z,d]}e.exports={calc:function(t,e){var r,a,p,d,m=[],g=[],v="h"===e.orientation,y=o.getFromId(t,v?e.yaxis:e.xaxis),x=v?"y":"x",b={x:"y",y:"x"}[x],_=e[x+"calendar"],w=e.cumulative,T=h(t,e,y,x),k=T[0],A=T[1],M="string"==typeof k.size,S=[],E=M?S:k,L=[],C=[],P=[],I=0,O=e.histnorm,z=e.histfunc,D=-1!==O.indexOf("density");w.enabled&&D&&(O=O.replace(/ ?density$/,""),D=!1);var R,F="max"===z||"min"===z?null:0,B=l.count,N=c[O],j=!1,U=function(t){return y.r2c(t,0,_)};for(i.isArrayOrTypedArray(e[b])&&"count"!==z&&(R=e[b],j="avg"===z,B=l[z]),r=U(k.start),p=U(k.end)+(r-o.tickIncrement(r,k.size,!1,_))/1e6;r=0&&d=0;n--)s(n);else if("increasing"===e){for(n=1;n=0;n--)t[n]+=t[n+1];"exclude"===r&&(t.push(0),t.shift())}}(g,w.direction,w.currentbin);var K=Math.min(m.length,g.length),Q=[],$=0,tt=K-1;for(r=0;r=$;r--)if(g[r]){tt=r;break}for(r=$;r<=tt;r++)if(n(m[r])&&n(g[r])){var et={p:m[r],s:g[r],b:0};w.enabled||(et.pts=P[r],Y?et.ph0=et.ph1=P[r].length?A[P[r][0]]:m[r]:(e._computePh=!0,et.ph0=q(S[r]),et.ph1=q(S[r+1],!0))),Q.push(et)}return 1===Q.length&&(Q[0].width1=o.tickIncrement(Q[0].p,k.size,!1,_)-Q[0].p),s(Q,e),i.isArrayOrTypedArray(e.selectedpoints)&&i.tagSelected(Q,e,Z),Q},calcAllAutoBins:h}},{"../../lib":503,"../../plots/cartesian/axes":554,"../../registry":638,"../bar/arrays_to_calcdata":647,"./average":813,"./bin_functions":815,"./bin_label_vals":816,"./norm_functions":824,"fast-isnumeric":190}],818:[function(t,e,r){"use strict";e.exports={eventDataKeys:["binNumber"]}},{}],819:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../plots/cartesian/axis_ids"),a=t("../../registry").traceIs,o=t("../bar/defaults").handleGroupingDefaults,s=n.nestedProperty,l=t("../../plots/cartesian/constraints").getAxisGroup,c=[{aStr:{x:"xbins.start",y:"ybins.start"},name:"start"},{aStr:{x:"xbins.end",y:"ybins.end"},name:"end"},{aStr:{x:"xbins.size",y:"ybins.size"},name:"size"},{aStr:{x:"nbinsx",y:"nbinsy"},name:"nbins"}],u=["x","y"];e.exports=function(t,e){var r,f,h,p,d,m,g,v=e._histogramBinOpts={},y=[],x={},b=[];function _(t,e){return n.coerce(r._input,r,r._module.attributes,t,e)}function w(t){return"v"===t.orientation?"x":"y"}function T(t,r,a){var o=t.uid+"__"+a;r||(r=o);var s=function(t,r){return i.getFromTrace({_fullLayout:e},t,r).type}(t,a),l=t[a+"calendar"]||"",c=v[r],u=!0;c&&(s===c.axType&&l===c.calendar?(u=!1,c.traces.push(t),c.dirs.push(a)):(r=o,s!==c.axType&&n.warn(["Attempted to group the bins of trace",t.index,"set on a","type:"+s,"axis","with bins on","type:"+c.axType,"axis."].join(" ")),l!==c.calendar&&n.warn(["Attempted to group the bins of trace",t.index,"set with a",l,"calendar","with bins",c.calendar?"on a "+c.calendar+" calendar":"w/o a set calendar"].join(" ")))),u&&(v[r]={traces:[t],dirs:[a],axType:s,calendar:t[a+"calendar"]||""}),t["_"+a+"bingroup"]=r}for(d=0;dS&&T.splice(S,T.length-S),M.length>S&&M.splice(S,M.length-S);var E=[],L=[],C=[],P="string"==typeof w.size,I="string"==typeof A.size,O=[],z=[],D=P?O:w,R=I?z:A,F=0,B=[],N=[],j=e.histnorm,U=e.histfunc,V=-1!==j.indexOf("density"),H="max"===U||"min"===U?null:0,q=a.count,G=o[j],Y=!1,W=[],X=[],Z="z"in e?e.z:"marker"in e&&Array.isArray(e.marker.color)?e.marker.color:"";Z&&"count"!==U&&(Y="avg"===U,q=a[U]);var J=w.size,K=x(w.start),Q=x(w.end)+(K-i.tickIncrement(K,J,!1,v))/1e6;for(r=K;r=0&&p=0&&d-1,flipY:E.tiling.flip.indexOf("y")>-1,orientation:E.tiling.orientation,pad:{inner:E.tiling.pad},maxDepth:E._maxDepth}).descendants(),O=1/0,z=-1/0;I.forEach((function(t){var e=t.depth;e>=E._maxDepth?(t.x0=t.x1=(t.x0+t.x1)/2,t.y0=t.y1=(t.y0+t.y1)/2):(O=Math.min(O,e),z=Math.max(z,e))})),p=p.data(I,u.getPtId),E._maxVisibleLayers=isFinite(z)?z-O+1:0,p.enter().append("g").classed("slice",!0),T(p,!1,{},[m,g],x),p.order();var D=null;if(w&&M){var R=u.getPtId(M);p.each((function(t){null===D&&u.getPtId(t)===R&&(D={x0:t.x0,x1:t.x1,y0:t.y0,y1:t.y1})}))}var F=function(){return D||{x0:0,x1:m,y0:0,y1:g}},B=p;return w&&(B=B.transition().each("end",(function(){var e=n.select(this);u.setSliceCursor(e,t,{hideOnRoot:!0,hideOnLeaves:!1,isTransitioning:!1})}))),B.each((function(s){s._x0=v(s.x0),s._x1=v(s.x1),s._y0=y(s.y0),s._y1=y(s.y1),s._hoverX=v(s.x1-E.tiling.pad),s._hoverY=y(P?s.y1-E.tiling.pad/2:s.y0+E.tiling.pad/2);var p=n.select(this),d=i.ensureSingle(p,"path","surface",(function(t){t.style("pointer-events","all")}));w?d.transition().attrTween("d",(function(t){var e=k(t,!1,F(),[m,g],{orientation:E.tiling.orientation,flipX:E.tiling.flip.indexOf("x")>-1,flipY:E.tiling.flip.indexOf("y")>-1});return function(t){return x(e(t))}})):d.attr("d",x),p.call(f,r,t,e,{styleOne:l,eventDataKeys:c.eventDataKeys,transitionTime:c.CLICK_TRANSITION_TIME,transitionEasing:c.CLICK_TRANSITION_EASING}).call(u.setSliceCursor,t,{isTransitioning:t._transitioning}),d.call(l,s,E,{hovered:!1}),s.x0===s.x1||s.y0===s.y1?s._text="":s._text=h(s,r,E,e,S)||"";var T=i.ensureSingle(p,"g","slicetext"),M=i.ensureSingle(T,"text","",(function(t){t.attr("data-notex",1)})),I=i.ensureUniformFontSize(t,u.determineTextFont(E,s,S.font));M.text(s._text||" ").classed("slicetext",!0).attr("text-anchor",C?"end":L?"start":"middle").call(a.font,I).call(o.convertToTspans,t),s.textBB=a.bBox(M.node()),s.transform=b(s,{fontSize:I.size}),s.transform.fontSize=I.size,w?M.transition().attrTween("transform",(function(t){var e=A(t,!1,F(),[m,g]);return function(t){return _(e(t))}})):M.attr("transform",_(s))})),D}},{"../../components/drawing":388,"../../lib":503,"../../lib/svg_text_utils":529,"../sunburst/fx":1054,"../sunburst/helpers":1055,"../sunburst/plot":1059,"../treemap/constants":1078,"./partition":842,"./style":844,"@plotly/d3":58}],839:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"icicle",basePlotModule:t("./base_plot"),categories:[],animatable:!0,attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc").calc,crossTraceCalc:t("./calc").crossTraceCalc,plot:t("./plot"),style:t("./style").style,colorbar:t("../scatter/marker_colorbar"),meta:{}}},{"../scatter/marker_colorbar":945,"./attributes":834,"./base_plot":835,"./calc":836,"./defaults":837,"./layout_attributes":840,"./layout_defaults":841,"./plot":843,"./style":844}],840:[function(t,e,r){"use strict";e.exports={iciclecolorway:{valType:"colorlist",editType:"calc"},extendiciclecolors:{valType:"boolean",dflt:!0,editType:"calc"}}},{}],841:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e){function r(r,a){return n.coerce(t,e,i,r,a)}r("iciclecolorway",e.colorway),r("extendiciclecolors")}},{"../../lib":503,"./layout_attributes":840}],842:[function(t,e,r){"use strict";var n=t("d3-hierarchy"),i=t("../treemap/flip_tree");e.exports=function(t,e,r){var a=r.flipX,o=r.flipY,s="h"===r.orientation,l=r.maxDepth,c=e[0],u=e[1];l&&(c=(t.height+1)*e[0]/Math.min(t.height+1,l),u=(t.height+1)*e[1]/Math.min(t.height+1,l));var f=n.partition().padding(r.pad.inner).size(s?[e[1],c]:[e[0],u])(t);return(s||a||o)&&i(f,e,{swapXY:s,flipX:a,flipY:o}),f}},{"../treemap/flip_tree":1083,"d3-hierarchy":115}],843:[function(t,e,r){"use strict";var n=t("../treemap/draw"),i=t("./draw_descendants");e.exports=function(t,e,r,a){return n(t,e,r,a,{type:"icicle",drawDescendants:i})}},{"../treemap/draw":1080,"./draw_descendants":838}],844:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../components/color"),a=t("../../lib"),o=t("../bar/uniform_text").resizeText;function s(t,e,r){var n=e.data.data,o=!e.children,s=n.i,l=a.castOption(r,s,"marker.line.color")||i.defaultLine,c=a.castOption(r,s,"marker.line.width")||0;t.style("stroke-width",c).call(i.fill,n.color).call(i.stroke,l).style("opacity",o?r.leaf.opacity:null)}e.exports={style:function(t){var e=t._fullLayout._iciclelayer.selectAll(".trace");o(t,e,"icicle"),e.each((function(t){var e=n.select(this),r=t[0].trace;e.style("opacity",r.opacity),e.selectAll("path.surface").each((function(t){n.select(this).call(s,t,r)}))}))},styleOne:s}},{"../../components/color":366,"../../lib":503,"../bar/uniform_text":664,"@plotly/d3":58}],845:[function(t,e,r){"use strict";for(var n=t("../../plots/attributes"),i=t("../../plots/template_attributes").hovertemplateAttrs,a=t("../../lib/extend").extendFlat,o=t("./constants").colormodel,s=["rgb","rgba","rgba256","hsl","hsla"],l=[],c=[],u=0;u0||n.inbox(r-o.y0,r-(o.y0+o.h*s.dy),0)>0)){var u,f=Math.floor((e-o.x0)/s.dx),h=Math.floor(Math.abs(r-o.y0)/s.dy);if(s._hasZ?u=o.z[h][f]:s._hasSource&&(u=s._canvas.el.getContext("2d",{willReadFrequently:!0}).getImageData(f,h,1,1).data),u){var p,d=o.hi||s.hoverinfo;if(d){var m=d.split("+");-1!==m.indexOf("all")&&(m=["color"]),-1!==m.indexOf("color")&&(p=!0)}var g,v=a.colormodel[s.colormodel],y=v.colormodel||s.colormodel,x=y.length,b=s._scaler(u),_=v.suffix,w=[];(s.hovertemplate||p)&&(w.push("["+[b[0]+_[0],b[1]+_[1],b[2]+_[2]].join(", ")),4===x&&w.push(", "+b[3]+_[3]),w.push("]"),w=w.join(""),t.extraText=y.toUpperCase()+": "+w),Array.isArray(s.hovertext)&&Array.isArray(s.hovertext[h])?g=s.hovertext[h][f]:Array.isArray(s.text)&&Array.isArray(s.text[h])&&(g=s.text[h][f]);var T=c.c2p(o.y0+(h+.5)*s.dy),k=o.x0+(f+.5)*s.dx,A=o.y0+(h+.5)*s.dy,M="["+u.slice(0,s.colormodel.length).join(", ")+"]";return[i.extendFlat(t,{index:[h,f],x0:l.c2p(o.x0+f*s.dx),x1:l.c2p(o.x0+(f+1)*s.dx),y0:T,y1:T,color:b,xVal:k,xLabelVal:k,yVal:A,yLabelVal:A,zLabelVal:M,text:g,hovertemplateLabels:{zLabel:M,colorLabel:w,"color[0]Label":b[0]+_[0],"color[1]Label":b[1]+_[1],"color[2]Label":b[2]+_[2],"color[3]Label":b[3]+_[3]}})]}}}},{"../../components/fx":406,"../../lib":503,"./constants":847}],852:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("./calc"),plot:t("./plot"),style:t("./style"),hoverPoints:t("./hover"),eventData:t("./event_data"),moduleType:"trace",name:"image",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","2dMap","noSortingByValue"],animatable:!1,meta:{}}},{"../../plots/cartesian":568,"./attributes":845,"./calc":846,"./defaults":848,"./event_data":849,"./hover":851,"./plot":853,"./style":854}],853:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=i.strTranslate,o=t("../../constants/xmlns_namespaces"),s=t("./constants"),l=i.isIOS()||i.isSafari()||i.isIE();e.exports=function(t,e,r,c){var u=e.xaxis,f=e.yaxis,h=!(l||t._context._exportedPlot);i.makeTraceGroups(c,r,"im").each((function(e){var r=n.select(this),l=e[0],c=l.trace,p=("fast"===c.zsmooth||!1===c.zsmooth&&h)&&!c._hasZ&&c._hasSource&&"linear"===u.type&&"linear"===f.type;c._realImage=p;var d,m,g,v,y,x,b=l.z,_=l.x0,w=l.y0,T=l.w,k=l.h,A=c.dx,M=c.dy;for(x=0;void 0===d&&x0;)m=u.c2p(_+x*A),x--;for(x=0;void 0===v&&x0;)y=f.c2p(w+x*M),x--;if(mI[0];if(O||z){var D=d+S/2,R=v+E/2;C+="transform:"+a(D+"px",R+"px")+"scale("+(O?-1:1)+","+(z?-1:1)+")"+a(-D+"px",-R+"px")+";"}}L.attr("style",C);var F=new Promise((function(t){if(c._hasZ)t();else if(c._hasSource)if(c._canvas&&c._canvas.el.width===T&&c._canvas.el.height===k&&c._canvas.source===c.source)t();else{var e=document.createElement("canvas");e.width=T,e.height=k;var r=e.getContext("2d",{willReadFrequently:!0});c._image=c._image||new Image;var n=c._image;n.onload=function(){r.drawImage(n,0,0),c._canvas={el:e,source:c.source},t()},n.setAttribute("src",c.source)}})).then((function(){var t;if(c._hasZ)t=B((function(t,e){return b[e][t]})).toDataURL("image/png");else if(c._hasSource)if(p)t=c.source;else{var e=c._canvas.el.getContext("2d",{willReadFrequently:!0}).getImageData(0,0,T,k).data;t=B((function(t,r){var n=4*(r*T+t);return[e[n],e[n+1],e[n+2],e[n+3]]})).toDataURL("image/png")}L.attr({"xlink:href":t,height:E,width:S,x:d,y:v})}));t._promises.push(F)}function B(t){var e=document.createElement("canvas");e.width=S,e.height=E;var r,n=e.getContext("2d",{willReadFrequently:!0}),a=function(t){return i.constrain(Math.round(u.c2p(_+t*A)-d),0,S)},o=function(t){return i.constrain(Math.round(f.c2p(w+t*M)-v),0,E)},h=s.colormodel[c.colormodel],p=h.colormodel||c.colormodel,m=h.fmt;for(x=0;x0}function T(t){t.each((function(t){y.stroke(n.select(this),t.line.color)})).each((function(t){y.fill(n.select(this),t.color)})).style("stroke-width",(function(t){return t.line.width}))}function k(t,e,r){var n=t._fullLayout,i=o.extendFlat({type:"linear",ticks:"outside",range:r,showline:!0},e),a={type:"linear",_id:"x"+e._id},s={letter:"x",font:n.font,noHover:!0,noTickson:!0};function l(t,e){return o.coerce(i,a,v,t,e)}return m(i,a,l,s,n),g(i,a,l,s),a}function A(t,e,r){return[Math.min(e/t.width,r/t.height),t,e+"x"+r]}function M(t,e,r,i){var a=document.createElementNS("http://www.w3.org/2000/svg","text"),o=n.select(a);return o.text(t).attr("x",0).attr("y",0).attr("text-anchor",r).attr("data-unformatted",t).call(p.convertToTspans,i).call(f.font,e),f.bBox(o.node())}function S(t,e,r,n,i,a){var s="_cache"+e;t[s]&&t[s].key===i||(t[s]={key:i,value:r});var l=o.aggNums(a,null,[t[s].value,n],2);return t[s].value=l,l}e.exports=function(t,e,r,m){var g,v=t._fullLayout;w(r)&&m&&(g=m()),o.makeTraceGroups(v._indicatorlayer,e,"trace").each((function(e){var m,E,L,C,P,I=e[0].trace,O=n.select(this),z=I._hasGauge,D=I._isAngular,R=I._isBullet,F=I.domain,B={w:v._size.w*(F.x[1]-F.x[0]),h:v._size.h*(F.y[1]-F.y[0]),l:v._size.l+v._size.w*F.x[0],r:v._size.r+v._size.w*(1-F.x[1]),t:v._size.t+v._size.h*(1-F.y[1]),b:v._size.b+v._size.h*F.y[0]},N=B.l+B.w/2,j=B.t+B.h/2,U=Math.min(B.w/2,B.h),V=h.innerRadius*U,H=I.align||"center";if(E=j,z){if(D&&(m=N,E=j+U/2,L=function(t){return function(t,e){var r=Math.sqrt(t.width/2*(t.width/2)+t.height*t.height);return[e/r,t,e]}(t,.9*V)}),R){var q=h.bulletPadding,G=1-h.bulletNumberDomainSize+q;m=B.l+(G+(1-G)*b[H])*B.w,L=function(t){return A(t,(h.bulletNumberDomainSize-q)*B.w,B.h)}}}else m=B.l+b[H]*B.w,L=function(t){return A(t,B.w,B.h)};!function(t,e,r,i){var c,u,h,m=r[0].trace,g=i.numbersX,v=i.numbersY,T=m.align||"center",A=x[T],E=i.transitionOpts,L=i.onComplete,C=o.ensureSingle(e,"g","numbers"),P=[];m._hasNumber&&P.push("number");m._hasDelta&&(P.push("delta"),"left"===m.delta.position&&P.reverse());var I=C.selectAll("text").data(P);function O(e,r,n,i){if(!e.match("s")||n>=0==i>=0||r(n).slice(-1).match(_)||r(i).slice(-1).match(_))return r;var a=e.slice().replace("s","f").replace(/\d+/,(function(t){return parseInt(t)-1})),o=k(t,{tickformat:a});return function(t){return Math.abs(t)<1?d.tickText(o,t).text:r(t)}}I.enter().append("text"),I.attr("text-anchor",(function(){return A})).attr("class",(function(t){return t})).attr("x",null).attr("y",null).attr("dx",null).attr("dy",null),I.exit().remove();var z,D=m.mode+m.align;m._hasDelta&&(z=function(){var e=k(t,{tickformat:m.delta.valueformat},m._range);e.setScale(),d.prepTicks(e);var i=function(t){return d.tickText(e,t).text},o=function(t){return m.delta.relative?t.relativeDelta:t.delta},s=function(t,e){return 0===t||"number"!=typeof t||isNaN(t)?"-":(t>0?m.delta.increasing.symbol:m.delta.decreasing.symbol)+e(t)},l=function(t){return t.delta>=0?m.delta.increasing.color:m.delta.decreasing.color};void 0===m._deltaLastValue&&(m._deltaLastValue=o(r[0]));var c=C.select("text.delta");function h(){c.text(s(o(r[0]),i)).call(y.fill,l(r[0])).call(p.convertToTspans,t)}return c.call(f.font,m.delta.font).call(y.fill,l({delta:m._deltaLastValue})),w(E)?c.transition().duration(E.duration).ease(E.easing).tween("text",(function(){var t=n.select(this),e=o(r[0]),c=m._deltaLastValue,u=O(m.delta.valueformat,i,c,e),f=a(c,e);return m._deltaLastValue=e,function(e){t.text(s(f(e),u)),t.call(y.fill,l({delta:f(e)}))}})).each("end",(function(){h(),L&&L()})).each("interrupt",(function(){h(),L&&L()})):h(),u=M(s(o(r[0]),i),m.delta.font,A,t),c}(),D+=m.delta.position+m.delta.font.size+m.delta.font.family+m.delta.valueformat,D+=m.delta.increasing.symbol+m.delta.decreasing.symbol,h=u);m._hasNumber&&(!function(){var e=k(t,{tickformat:m.number.valueformat},m._range);e.setScale(),d.prepTicks(e);var i=function(t){return d.tickText(e,t).text},o=m.number.suffix,s=m.number.prefix,l=C.select("text.number");function u(){var e="number"==typeof r[0].y?s+i(r[0].y)+o:"-";l.text(e).call(f.font,m.number.font).call(p.convertToTspans,t)}w(E)?l.transition().duration(E.duration).ease(E.easing).each("end",(function(){u(),L&&L()})).each("interrupt",(function(){u(),L&&L()})).attrTween("text",(function(){var t=n.select(this),e=a(r[0].lastY,r[0].y);m._lastValue=r[0].y;var l=O(m.number.valueformat,i,r[0].lastY,r[0].y);return function(r){t.text(s+l(e(r))+o)}})):u(),c=M(s+i(r[0].y)+o,m.number.font,A,t)}(),D+=m.number.font.size+m.number.font.family+m.number.valueformat+m.number.suffix+m.number.prefix,h=c);if(m._hasDelta&&m._hasNumber){var R,F,B=[(c.left+c.right)/2,(c.top+c.bottom)/2],N=[(u.left+u.right)/2,(u.top+u.bottom)/2],j=.75*m.delta.font.size;"left"===m.delta.position&&(R=S(m,"deltaPos",0,-1*(c.width*b[m.align]+u.width*(1-b[m.align])+j),D,Math.min),F=B[1]-N[1],h={width:c.width+u.width+j,height:Math.max(c.height,u.height),left:u.left+R,right:c.right,top:Math.min(c.top,u.top+F),bottom:Math.max(c.bottom,u.bottom+F)}),"right"===m.delta.position&&(R=S(m,"deltaPos",0,c.width*(1-b[m.align])+u.width*b[m.align]+j,D,Math.max),F=B[1]-N[1],h={width:c.width+u.width+j,height:Math.max(c.height,u.height),left:c.left,right:u.right+R,top:Math.min(c.top,u.top+F),bottom:Math.max(c.bottom,u.bottom+F)}),"bottom"===m.delta.position&&(R=null,F=u.height,h={width:Math.max(c.width,u.width),height:c.height+u.height,left:Math.min(c.left,u.left),right:Math.max(c.right,u.right),top:c.bottom-c.height,bottom:c.bottom+u.height}),"top"===m.delta.position&&(R=null,F=c.top,h={width:Math.max(c.width,u.width),height:c.height+u.height,left:Math.min(c.left,u.left),right:Math.max(c.right,u.right),top:c.bottom-c.height-u.height,bottom:c.bottom}),z.attr({dx:R,dy:F})}(m._hasNumber||m._hasDelta)&&C.attr("transform",(function(){var t=i.numbersScaler(h);D+=t[2];var e,r=S(m,"numbersScale",1,t[0],D,Math.min);m._scaleNumbers||(r=1),e=m._isAngular?v-r*h.bottom:v-r*(h.top+h.bottom)/2,m._numbersTop=r*h.top+e;var n=h[T];"center"===T&&(n=(h.left+h.right)/2);var a=g-r*n;return a=S(m,"numbersTranslate",0,a,D,Math.max),l(a,e)+s(r)}))}(t,O,e,{numbersX:m,numbersY:E,numbersScaler:L,transitionOpts:r,onComplete:g}),z&&(C={range:I.gauge.axis.range,color:I.gauge.bgcolor,line:{color:I.gauge.bordercolor,width:0},thickness:1},P={range:I.gauge.axis.range,color:"rgba(0, 0, 0, 0)",line:{color:I.gauge.bordercolor,width:I.gauge.borderwidth},thickness:1});var Y=O.selectAll("g.angular").data(D?e:[]);Y.exit().remove();var W=O.selectAll("g.angularaxis").data(D?e:[]);W.exit().remove(),D&&function(t,e,r,a){var o,s,f,h,p=r[0].trace,m=a.size,g=a.radius,v=a.innerRadius,y=a.gaugeBg,x=a.gaugeOutline,b=[m.l+m.w/2,m.t+m.h/2+g/2],_=a.gauge,A=a.layer,M=a.transitionOpts,S=a.onComplete,E=Math.PI/2;function L(t){var e=p.gauge.axis.range[0],r=(t-e)/(p.gauge.axis.range[1]-e)*Math.PI-E;return r<-E?-E:r>E?E:r}function C(t){return n.svg.arc().innerRadius((v+g)/2-t/2*(g-v)).outerRadius((v+g)/2+t/2*(g-v)).startAngle(-E)}function P(t){t.attr("d",(function(t){return C(t.thickness).startAngle(L(t.range[0])).endAngle(L(t.range[1]))()}))}_.enter().append("g").classed("angular",!0),_.attr("transform",l(b[0],b[1])),A.enter().append("g").classed("angularaxis",!0).classed("crisp",!0),A.selectAll("g.xangularaxistick,path,text").remove(),(o=k(t,p.gauge.axis)).type="linear",o.range=p.gauge.axis.range,o._id="xangularaxis",o.ticklabeloverflow="allow",o.setScale();var I=function(t){return(o.range[0]-t.x)/(o.range[1]-o.range[0])*Math.PI+Math.PI},O={},z=d.makeLabelFns(o,0).labelStandoff;O.xFn=function(t){var e=I(t);return Math.cos(e)*z},O.yFn=function(t){var e=I(t),r=Math.sin(e)>0?.2:1;return-Math.sin(e)*(z+t.fontSize*r)+Math.abs(Math.cos(e))*(t.fontSize*u)},O.anchorFn=function(t){var e=I(t),r=Math.cos(e);return Math.abs(r)<.1?"middle":r>0?"start":"end"},O.heightFn=function(t,e,r){var n=I(t);return-.5*(1+Math.sin(n))*r};var D=function(t){return l(b[0]+g*Math.cos(t),b[1]-g*Math.sin(t))};f=function(t){return D(I(t))};if(s=d.calcTicks(o),h=d.getTickSigns(o)[2],o.visible){h="inside"===o.ticks?-1:1;var R=(o.linewidth||1)/2;d.drawTicks(t,o,{vals:s,layer:A,path:"M"+h*R+",0h"+h*o.ticklen,transFn:function(t){var e=I(t);return D(e)+"rotate("+-c(e)+")"}}),d.drawLabels(t,o,{vals:s,layer:A,transFn:f,labelFns:O})}var F=[y].concat(p.gauge.steps),B=_.selectAll("g.bg-arc").data(F);B.enter().append("g").classed("bg-arc",!0).append("path"),B.select("path").call(P).call(T),B.exit().remove();var N=C(p.gauge.bar.thickness),j=_.selectAll("g.value-arc").data([p.gauge.bar]);j.enter().append("g").classed("value-arc",!0).append("path");var U=j.select("path");w(M)?(U.transition().duration(M.duration).ease(M.easing).each("end",(function(){S&&S()})).each("interrupt",(function(){S&&S()})).attrTween("d",(V=N,H=L(r[0].lastY),q=L(r[0].y),function(){var t=i(H,q);return function(e){return V.endAngle(t(e))()}})),p._lastValue=r[0].y):U.attr("d","number"==typeof r[0].y?N.endAngle(L(r[0].y)):"M0,0Z");var V,H,q;U.call(T),j.exit().remove(),F=[];var G=p.gauge.threshold.value;(G||0===G)&&F.push({range:[G,G],color:p.gauge.threshold.color,line:{color:p.gauge.threshold.line.color,width:p.gauge.threshold.line.width},thickness:p.gauge.threshold.thickness});var Y=_.selectAll("g.threshold-arc").data(F);Y.enter().append("g").classed("threshold-arc",!0).append("path"),Y.select("path").call(P).call(T),Y.exit().remove();var W=_.selectAll("g.gauge-outline").data([x]);W.enter().append("g").classed("gauge-outline",!0).append("path"),W.select("path").call(P).call(T),W.exit().remove()}(t,0,e,{radius:U,innerRadius:V,gauge:Y,layer:W,size:B,gaugeBg:C,gaugeOutline:P,transitionOpts:r,onComplete:g});var X=O.selectAll("g.bullet").data(R?e:[]);X.exit().remove();var Z=O.selectAll("g.bulletaxis").data(R?e:[]);Z.exit().remove(),R&&function(t,e,r,n){var i,a,o,s,c,u=r[0].trace,f=n.gauge,p=n.layer,m=n.gaugeBg,g=n.gaugeOutline,v=n.size,x=u.domain,b=n.transitionOpts,_=n.onComplete;f.enter().append("g").classed("bullet",!0),f.attr("transform",l(v.l,v.t)),p.enter().append("g").classed("bulletaxis",!0).classed("crisp",!0),p.selectAll("g.xbulletaxistick,path,text").remove();var A=v.h,M=u.gauge.bar.thickness*A,S=x.x[0],E=x.x[0]+(x.x[1]-x.x[0])*(u._hasNumber||u._hasDelta?1-h.bulletNumberDomainSize:1);(i=k(t,u.gauge.axis))._id="xbulletaxis",i.domain=[S,E],i.setScale(),a=d.calcTicks(i),o=d.makeTransTickFn(i),s=d.getTickSigns(i)[2],c=v.t+v.h,i.visible&&(d.drawTicks(t,i,{vals:"inside"===i.ticks?d.clipEnds(i,a):a,layer:p,path:d.makeTickPath(i,c,s),transFn:o}),d.drawLabels(t,i,{vals:a,layer:p,transFn:o,labelFns:d.makeLabelFns(i,c)}));function L(t){t.attr("width",(function(t){return Math.max(0,i.c2p(t.range[1])-i.c2p(t.range[0]))})).attr("x",(function(t){return i.c2p(t.range[0])})).attr("y",(function(t){return.5*(1-t.thickness)*A})).attr("height",(function(t){return t.thickness*A}))}var C=[m].concat(u.gauge.steps),P=f.selectAll("g.bg-bullet").data(C);P.enter().append("g").classed("bg-bullet",!0).append("rect"),P.select("rect").call(L).call(T),P.exit().remove();var I=f.selectAll("g.value-bullet").data([u.gauge.bar]);I.enter().append("g").classed("value-bullet",!0).append("rect"),I.select("rect").attr("height",M).attr("y",(A-M)/2).call(T),w(b)?I.select("rect").transition().duration(b.duration).ease(b.easing).each("end",(function(){_&&_()})).each("interrupt",(function(){_&&_()})).attr("width",Math.max(0,i.c2p(Math.min(u.gauge.axis.range[1],r[0].y)))):I.select("rect").attr("width","number"==typeof r[0].y?Math.max(0,i.c2p(Math.min(u.gauge.axis.range[1],r[0].y))):0);I.exit().remove();var O=r.filter((function(){return u.gauge.threshold.value||0===u.gauge.threshold.value})),z=f.selectAll("g.threshold-bullet").data(O);z.enter().append("g").classed("threshold-bullet",!0).append("line"),z.select("line").attr("x1",i.c2p(u.gauge.threshold.value)).attr("x2",i.c2p(u.gauge.threshold.value)).attr("y1",(1-u.gauge.threshold.thickness)/2*A).attr("y2",(1-(1-u.gauge.threshold.thickness)/2)*A).call(y.stroke,u.gauge.threshold.line.color).style("stroke-width",u.gauge.threshold.line.width),z.exit().remove();var D=f.selectAll("g.gauge-outline").data([g]);D.enter().append("g").classed("gauge-outline",!0).append("rect"),D.select("rect").call(L).call(T),D.exit().remove()}(t,0,e,{gauge:X,layer:Z,size:B,gaugeBg:C,gaugeOutline:P,transitionOpts:r,onComplete:g});var J=O.selectAll("text.title").data(e);J.exit().remove(),J.enter().append("text").classed("title",!0),J.attr("text-anchor",(function(){return R?x.right:x[I.title.align]})).text(I.title.text).call(f.font,I.title.font).call(p.convertToTspans,t),J.attr("transform",(function(){var t,e=B.l+B.w*b[I.title.align],r=h.titlePadding,n=f.bBox(J.node());if(z){if(D)if(I.gauge.axis.visible)t=f.bBox(W.node()).top-r-n.bottom;else t=B.t+B.h/2-U/2-n.bottom-r;R&&(t=E-(n.top+n.bottom)/2,e=B.l-h.bulletPadding*B.w)}else t=I._numbersTop-r-n.bottom;return l(e,t)}))}))}},{"../../components/color":366,"../../components/drawing":388,"../../constants/alignment":471,"../../lib":503,"../../lib/svg_text_utils":529,"../../plots/cartesian/axes":554,"../../plots/cartesian/axis_defaults":556,"../../plots/cartesian/layout_attributes":569,"../../plots/cartesian/position_defaults":572,"./constants":858,"@plotly/d3":58,"d3-interpolate":116}],862:[function(t,e,r){"use strict";var n=t("../../components/colorscale/attributes"),i=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,a=t("../../plots/template_attributes").hovertemplateAttrs,o=t("../mesh3d/attributes"),s=t("../../plots/attributes"),l=t("../../lib/extend").extendFlat,c=t("../../plot_api/edit_types").overrideAll;var u=e.exports=c(l({x:{valType:"data_array"},y:{valType:"data_array"},z:{valType:"data_array"},value:{valType:"data_array"},isomin:{valType:"number"},isomax:{valType:"number"},surface:{show:{valType:"boolean",dflt:!0},count:{valType:"integer",dflt:2,min:1},fill:{valType:"number",min:0,max:1,dflt:1},pattern:{valType:"flaglist",flags:["A","B","C","D","E"],extras:["all","odd","even"],dflt:"all"}},spaceframe:{show:{valType:"boolean",dflt:!1},fill:{valType:"number",min:0,max:1,dflt:.15}},slices:{x:{show:{valType:"boolean",dflt:!1},locations:{valType:"data_array",dflt:[]},fill:{valType:"number",min:0,max:1,dflt:1}},y:{show:{valType:"boolean",dflt:!1},locations:{valType:"data_array",dflt:[]},fill:{valType:"number",min:0,max:1,dflt:1}},z:{show:{valType:"boolean",dflt:!1},locations:{valType:"data_array",dflt:[]},fill:{valType:"number",min:0,max:1,dflt:1}}},caps:{x:{show:{valType:"boolean",dflt:!0},fill:{valType:"number",min:0,max:1,dflt:1}},y:{show:{valType:"boolean",dflt:!0},fill:{valType:"number",min:0,max:1,dflt:1}},z:{show:{valType:"boolean",dflt:!0},fill:{valType:"number",min:0,max:1,dflt:1}}},text:{valType:"string",dflt:"",arrayOk:!0},hovertext:{valType:"string",dflt:"",arrayOk:!0},hovertemplate:a(),xhoverformat:i("x"),yhoverformat:i("y"),zhoverformat:i("z"),valuehoverformat:i("value",1),showlegend:l({},s.showlegend,{dflt:!1})},n("",{colorAttr:"`value`",showScaleDflt:!0,editTypeOverride:"calc"}),{opacity:o.opacity,lightposition:o.lightposition,lighting:o.lighting,flatshading:o.flatshading,contour:o.contour,hoverinfo:l({},s.hoverinfo)}),"calc","nested");u.flatshading.dflt=!0,u.lighting.facenormalsepsilon.dflt=0,u.x.editType=u.y.editType=u.z.editType=u.value.editType="calc+clearAxisTypes",u.transforms=void 0},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plot_api/edit_types":536,"../../plots/attributes":550,"../../plots/cartesian/axis_format_attributes":557,"../../plots/template_attributes":633,"../mesh3d/attributes":867}],863:[function(t,e,r){"use strict";var n=t("../../components/colorscale/calc"),i=t("../streamtube/calc").processGrid,a=t("../streamtube/calc").filter;e.exports=function(t,e){e._len=Math.min(e.x.length,e.y.length,e.z.length,e.value.length),e._x=a(e.x,e._len),e._y=a(e.y,e._len),e._z=a(e.z,e._len),e._value=a(e.value,e._len);var r=i(e);e._gridFill=r.fill,e._Xs=r.Xs,e._Ys=r.Ys,e._Zs=r.Zs,e._len=r.len;for(var o=1/0,s=-1/0,l=0;l0;r--){var n=Math.min(e[r],e[r-1]),i=Math.max(e[r],e[r-1]);if(i>n&&n-1}function R(t,e){return null===t?e:t}function F(e,r,n){C();var i,a,o,l=[r],c=[n];if(s>=1)l=[r],c=[n];else if(s>0){var u=function(t,e){var r=t[0],n=t[1],i=t[2],a=function(t,e,r){for(var n=[],i=0;i-1?n[p]:L(d,m,v);h[p]=x>-1?x:I(d,m,v,R(e,y))}i=h[0],a=h[1],o=h[2],t._meshI.push(i),t._meshJ.push(a),t._meshK.push(o),++g}}function B(t,e,r,n){var i=t[3];in&&(i=n);for(var a=(t[3]-i)/(t[3]-e[3]+1e-9),o=[],s=0;s<4;s++)o[s]=(1-a)*t[s]+a*e[s];return o}function N(t,e,r){return t>=e&&t<=r}function j(t){var e=.001*(E-S);return t>=S-e&&t<=E+e}function U(e){for(var r=[],n=0;n<4;n++){var i=e[n];r.push([t._x[i],t._y[i],t._z[i],t._value[i]])}return r}function V(t,e,r,n,i,a){a||(a=1),r=[-1,-1,-1];var o=!1,s=[N(e[0][3],n,i),N(e[1][3],n,i),N(e[2][3],n,i)];if(!s[0]&&!s[1]&&!s[2])return!1;var l=function(t,e,r){return j(e[0][3])&&j(e[1][3])&&j(e[2][3])?(F(t,e,r),!0):a<3&&V(t,e,r,S,E,++a)};if(s[0]&&s[1]&&s[2])return l(t,e,r)||o;var c=!1;return[[0,1,2],[2,0,1],[1,2,0]].forEach((function(a){if(s[a[0]]&&s[a[1]]&&!s[a[2]]){var u=e[a[0]],f=e[a[1]],h=e[a[2]],p=B(h,u,n,i),d=B(h,f,n,i);o=l(t,[d,p,u],[-1,-1,r[a[0]]])||o,o=l(t,[u,f,d],[r[a[0]],r[a[1]],-1])||o,c=!0}})),c||[[0,1,2],[1,2,0],[2,0,1]].forEach((function(a){if(s[a[0]]&&!s[a[1]]&&!s[a[2]]){var u=e[a[0]],f=e[a[1]],h=e[a[2]],p=B(f,u,n,i),d=B(h,u,n,i);o=l(t,[d,p,u],[-1,-1,r[a[0]]])||o,c=!0}})),o}function H(t,e,r,n){var i=!1,a=U(e),o=[N(a[0][3],r,n),N(a[1][3],r,n),N(a[2][3],r,n),N(a[3][3],r,n)];if(!(o[0]||o[1]||o[2]||o[3]))return i;if(o[0]&&o[1]&&o[2]&&o[3])return m&&(i=function(t,e,r){var n=function(n,i,a){F(t,[e[n],e[i],e[a]],[r[n],r[i],r[a]])};n(0,1,2),n(3,0,1),n(2,3,0),n(1,2,3)}(t,a,e)||i),i;var s=!1;return[[0,1,2,3],[3,0,1,2],[2,3,0,1],[1,2,3,0]].forEach((function(l){if(o[l[0]]&&o[l[1]]&&o[l[2]]&&!o[l[3]]){var c=a[l[0]],u=a[l[1]],f=a[l[2]],h=a[l[3]];if(m)i=F(t,[c,u,f],[e[l[0]],e[l[1]],e[l[2]]])||i;else{var p=B(h,c,r,n),d=B(h,u,r,n),g=B(h,f,r,n);i=F(null,[p,d,g],[-1,-1,-1])||i}s=!0}})),s?i:([[0,1,2,3],[1,2,3,0],[2,3,0,1],[3,0,1,2],[0,2,3,1],[1,3,2,0]].forEach((function(l){if(o[l[0]]&&o[l[1]]&&!o[l[2]]&&!o[l[3]]){var c=a[l[0]],u=a[l[1]],f=a[l[2]],h=a[l[3]],p=B(f,c,r,n),d=B(f,u,r,n),g=B(h,u,r,n),v=B(h,c,r,n);m?(i=F(t,[c,v,p],[e[l[0]],-1,-1])||i,i=F(t,[u,d,g],[e[l[1]],-1,-1])||i):i=function(t,e,r){var n=function(n,i,a){F(t,[e[n],e[i],e[a]],[r[n],r[i],r[a]])};n(0,1,2),n(2,3,0)}(null,[p,d,g,v],[-1,-1,-1,-1])||i,s=!0}})),s||[[0,1,2,3],[1,2,3,0],[2,3,0,1],[3,0,1,2]].forEach((function(l){if(o[l[0]]&&!o[l[1]]&&!o[l[2]]&&!o[l[3]]){var c=a[l[0]],u=a[l[1]],f=a[l[2]],h=a[l[3]],p=B(u,c,r,n),d=B(f,c,r,n),g=B(h,c,r,n);m?(i=F(t,[c,p,d],[e[l[0]],-1,-1])||i,i=F(t,[c,d,g],[e[l[0]],-1,-1])||i,i=F(t,[c,g,p],[e[l[0]],-1,-1])||i):i=F(null,[p,d,g],[-1,-1,-1])||i,s=!0}})),i)}function q(t,e,r,n,i,a,o,s,l,c,u){var f=!1;return d&&(D(t,"A")&&(f=H(null,[e,r,n,a],c,u)||f),D(t,"B")&&(f=H(null,[r,n,i,l],c,u)||f),D(t,"C")&&(f=H(null,[r,a,o,l],c,u)||f),D(t,"D")&&(f=H(null,[n,a,s,l],c,u)||f),D(t,"E")&&(f=H(null,[r,n,a,l],c,u)||f)),m&&(f=H(t,[r,n,a,l],c,u)||f),f}function G(t,e,r,n,i,a,o,s){return[!0===s[0]||V(t,U([e,r,n]),[e,r,n],a,o),!0===s[1]||V(t,U([n,i,e]),[n,i,e],a,o)]}function Y(t,e,r,n,i,a,o,s,l){return s?G(t,e,r,i,n,a,o,l):G(t,r,i,n,e,a,o,l)}function W(t,e,r,n,i,a,o){var s,l,c,u,f=!1,h=function(){f=V(t,[s,l,c],[-1,-1,-1],i,a)||f,f=V(t,[c,u,s],[-1,-1,-1],i,a)||f},p=o[0],d=o[1],m=o[2];return p&&(s=O(U([k(e,r-0,n-0)])[0],U([k(e-1,r-0,n-0)])[0],p),l=O(U([k(e,r-0,n-1)])[0],U([k(e-1,r-0,n-1)])[0],p),c=O(U([k(e,r-1,n-1)])[0],U([k(e-1,r-1,n-1)])[0],p),u=O(U([k(e,r-1,n-0)])[0],U([k(e-1,r-1,n-0)])[0],p),h()),d&&(s=O(U([k(e-0,r,n-0)])[0],U([k(e-0,r-1,n-0)])[0],d),l=O(U([k(e-0,r,n-1)])[0],U([k(e-0,r-1,n-1)])[0],d),c=O(U([k(e-1,r,n-1)])[0],U([k(e-1,r-1,n-1)])[0],d),u=O(U([k(e-1,r,n-0)])[0],U([k(e-1,r-1,n-0)])[0],d),h()),m&&(s=O(U([k(e-0,r-0,n)])[0],U([k(e-0,r-0,n-1)])[0],m),l=O(U([k(e-0,r-1,n)])[0],U([k(e-0,r-1,n-1)])[0],m),c=O(U([k(e-1,r-1,n)])[0],U([k(e-1,r-1,n-1)])[0],m),u=O(U([k(e-1,r-0,n)])[0],U([k(e-1,r-0,n-1)])[0],m),h()),f}function X(t,e,r,n,i,a,o,s,l,c,u,f){var h=t;return f?(d&&"even"===t&&(h=null),q(h,e,r,n,i,a,o,s,l,c,u)):(d&&"odd"===t&&(h=null),q(h,l,s,o,a,i,n,r,e,c,u))}function Z(t,e,r,n,i){for(var a=[],o=0,s=0;sMath.abs(d-M)?[A,d]:[d,M];$(e,T[0],T[1])}}var L=[[Math.min(S,M),Math.max(S,M)],[Math.min(A,E),Math.max(A,E)]];["x","y","z"].forEach((function(e){for(var r=[],n=0;n0&&(u.push(p.id),"x"===e?f.push([p.distRatio,0,0]):"y"===e?f.push([0,p.distRatio,0]):f.push([0,0,p.distRatio]))}else c=nt(1,"x"===e?b-1:"y"===e?_-1:w-1);u.length>0&&(r[i]="x"===e?tt(null,u,a,o,f,r[i]):"y"===e?et(null,u,a,o,f,r[i]):rt(null,u,a,o,f,r[i]),i++),c.length>0&&(r[i]="x"===e?Z(null,c,a,o,r[i]):"y"===e?J(null,c,a,o,r[i]):K(null,c,a,o,r[i]),i++)}var d=t.caps[e];d.show&&d.fill&&(z(d.fill),r[i]="x"===e?Z(null,[0,b-1],a,o,r[i]):"y"===e?J(null,[0,_-1],a,o,r[i]):K(null,[0,w-1],a,o,r[i]),i++)}})),0===g&&P(),t._meshX=n,t._meshY=i,t._meshZ=a,t._meshIntensity=o,t._Xs=v,t._Ys=y,t._Zs=x}(),t}e.exports={findNearestOnAxis:l,generateIsoMeshes:h,createIsosurfaceTrace:function(t,e){var r=t.glplot.gl,i=n({gl:r}),a=new c(t,i,e.uid);return i._trace=a,a.update(e),t.glplot.add(i),a}}},{"../../../stackgl_modules":1124,"../../components/colorscale":378,"../../lib/gl_format_color":499,"../../lib/str2rgbarray":528,"../../plots/gl3d/zip3":609}],865:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry"),a=t("./attributes"),o=t("../../components/colorscale/defaults");function s(t,e,r,n,a){var s=a("isomin"),l=a("isomax");null!=l&&null!=s&&s>l&&(e.isomin=null,e.isomax=null);var c=a("x"),u=a("y"),f=a("z"),h=a("value");c&&c.length&&u&&u.length&&f&&f.length&&h&&h.length?(i.getComponentMethod("calendars","handleTraceDefaults")(t,e,["x","y","z"],n),a("valuehoverformat"),["x","y","z"].forEach((function(t){a(t+"hoverformat");var e="caps."+t;a(e+".show")&&a(e+".fill");var r="slices."+t;a(r+".show")&&(a(r+".fill"),a(r+".locations"))})),a("spaceframe.show")&&a("spaceframe.fill"),a("surface.show")&&(a("surface.count"),a("surface.fill"),a("surface.pattern")),a("contour.show")&&(a("contour.color"),a("contour.width")),["text","hovertext","hovertemplate","lighting.ambient","lighting.diffuse","lighting.specular","lighting.roughness","lighting.fresnel","lighting.vertexnormalsepsilon","lighting.facenormalsepsilon","lightposition.x","lightposition.y","lightposition.z","flatshading","opacity"].forEach((function(t){a(t)})),o(t,e,n,a,{prefix:"",cLetter:"c"}),e._length=null):e.visible=!1}e.exports={supplyDefaults:function(t,e,r,i){s(t,e,r,i,(function(r,i){return n.coerce(t,e,a,r,i)}))},supplyIsoDefaults:s}},{"../../components/colorscale/defaults":376,"../../lib":503,"../../registry":638,"./attributes":862}],866:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults").supplyDefaults,calc:t("./calc"),colorbar:{min:"cmin",max:"cmax"},plot:t("./convert").createIsosurfaceTrace,moduleType:"trace",name:"isosurface",basePlotModule:t("../../plots/gl3d"),categories:["gl3d","showLegend"],meta:{}}},{"../../plots/gl3d":598,"./attributes":862,"./calc":863,"./convert":864,"./defaults":865}],867:[function(t,e,r){"use strict";var n=t("../../components/colorscale/attributes"),i=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,a=t("../../plots/template_attributes").hovertemplateAttrs,o=t("../surface/attributes"),s=t("../../plots/attributes"),l=t("../../lib/extend").extendFlat;e.exports=l({x:{valType:"data_array",editType:"calc+clearAxisTypes"},y:{valType:"data_array",editType:"calc+clearAxisTypes"},z:{valType:"data_array",editType:"calc+clearAxisTypes"},i:{valType:"data_array",editType:"calc"},j:{valType:"data_array",editType:"calc"},k:{valType:"data_array",editType:"calc"},text:{valType:"string",dflt:"",arrayOk:!0,editType:"calc"},hovertext:{valType:"string",dflt:"",arrayOk:!0,editType:"calc"},hovertemplate:a({editType:"calc"}),xhoverformat:i("x"),yhoverformat:i("y"),zhoverformat:i("z"),delaunayaxis:{valType:"enumerated",values:["x","y","z"],dflt:"z",editType:"calc"},alphahull:{valType:"number",dflt:-1,editType:"calc"},intensity:{valType:"data_array",editType:"calc"},intensitymode:{valType:"enumerated",values:["vertex","cell"],dflt:"vertex",editType:"calc"},color:{valType:"color",editType:"calc"},vertexcolor:{valType:"data_array",editType:"calc"},facecolor:{valType:"data_array",editType:"calc"},transforms:void 0},n("",{colorAttr:"`intensity`",showScaleDflt:!0,editTypeOverride:"calc"}),{opacity:o.opacity,flatshading:{valType:"boolean",dflt:!1,editType:"calc"},contour:{show:l({},o.contours.x.show,{}),color:o.contours.x.color,width:o.contours.x.width,editType:"calc"},lightposition:{x:l({},o.lightposition.x,{dflt:1e5}),y:l({},o.lightposition.y,{dflt:1e5}),z:l({},o.lightposition.z,{dflt:0}),editType:"calc"},lighting:l({vertexnormalsepsilon:{valType:"number",min:0,max:1,dflt:1e-12,editType:"calc"},facenormalsepsilon:{valType:"number",min:0,max:1,dflt:1e-6,editType:"calc"},editType:"calc"},o.lighting),hoverinfo:l({},s.hoverinfo,{editType:"calc"}),showlegend:l({},s.showlegend,{dflt:!1})})},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plots/attributes":550,"../../plots/cartesian/axis_format_attributes":557,"../../plots/template_attributes":633,"../surface/attributes":1061}],868:[function(t,e,r){"use strict";var n=t("../../components/colorscale/calc");e.exports=function(t,e){e.intensity&&n(t,e,{vals:e.intensity,containerStr:"",cLetter:"c"})}},{"../../components/colorscale/calc":374}],869:[function(t,e,r){"use strict";var n=t("../../../stackgl_modules").gl_mesh3d,i=t("../../../stackgl_modules").delaunay_triangulate,a=t("../../../stackgl_modules").alpha_shape,o=t("../../../stackgl_modules").convex_hull,s=t("../../lib/gl_format_color").parseColorScale,l=t("../../lib/str2rgbarray"),c=t("../../components/colorscale").extractOpts,u=t("../../plots/gl3d/zip3");function f(t,e,r){this.scene=t,this.uid=r,this.mesh=e,this.name="",this.color="#fff",this.data=null,this.showContour=!1}var h=f.prototype;function p(t){for(var e=[],r=t.length,n=0;n=e-.5)return!1;return!0}h.handlePick=function(t){if(t.object===this.mesh){var e=t.index=t.data.index;t.data._cellCenter?t.traceCoordinate=t.data.dataCoordinate:t.traceCoordinate=[this.data.x[e],this.data.y[e],this.data.z[e]];var r=this.data.hovertext||this.data.text;return Array.isArray(r)&&void 0!==r[e]?t.textLabel=r[e]:r&&(t.textLabel=r),!0}},h.update=function(t){var e=this.scene,r=e.fullSceneLayout;this.data=t;var n,f=t.x.length,h=u(d(r.xaxis,t.x,e.dataScale[0],t.xcalendar),d(r.yaxis,t.y,e.dataScale[1],t.ycalendar),d(r.zaxis,t.z,e.dataScale[2],t.zcalendar));if(t.i&&t.j&&t.k){if(t.i.length!==t.j.length||t.j.length!==t.k.length||!g(t.i,f)||!g(t.j,f)||!g(t.k,f))return;n=u(m(t.i),m(t.j),m(t.k))}else n=0===t.alphahull?o(h):t.alphahull>0?a(t.alphahull,h):function(t,e){for(var r=["x","y","z"].indexOf(t),n=[],a=e.length,o=0;ov):g=A>w,v=A;var M=c(w,T,k,A);M.pos=_,M.yc=(w+A)/2,M.i=b,M.dir=g?"increasing":"decreasing",M.x=M.pos,M.y=[k,T],y&&(M.orig_p=r[b]),d&&(M.tx=e.text[b]),m&&(M.htx=e.hovertext[b]),x.push(M)}else x.push({pos:_,empty:!0})}return e._extremes[l._id]=a.findExtremes(l,n.concat(h,f),{padded:!0}),x.length&&(x[0].t={labels:{open:i(t,"open:")+" ",high:i(t,"high:")+" ",low:i(t,"low:")+" ",close:i(t,"close:")+" "}}),x}e.exports={calc:function(t,e){var r=a.getFromId(t,e.xaxis),i=a.getFromId(t,e.yaxis),s=function(t,e,r){var i=r._minDiff;if(!i){var a,s=t._fullData,l=[];for(i=1/0,a=0;a"+c.labels[x]+n.hoverLabelText(s,b,l.yhoverformat):((y=i.extendFlat({},h)).y0=y.y1=_,y.yLabelVal=b,y.yLabel=c.labels[x]+n.hoverLabelText(s,b,l.yhoverformat),y.name="",f.push(y),g[b]=y)}return f}function h(t,e,r,i){var a=t.cd,o=t.ya,l=a[0].trace,f=a[0].t,h=u(t,e,r,i);if(!h)return[];var p=a[h.index],d=h.index=p.i,m=p.dir;function g(t){return f.labels[t]+n.hoverLabelText(o,l[t][d],l.yhoverformat)}var v=p.hi||l.hoverinfo,y=v.split("+"),x="all"===v,b=x||-1!==y.indexOf("y"),_=x||-1!==y.indexOf("text"),w=b?[g("open"),g("high"),g("low"),g("close")+" "+c[m]]:[];return _&&s(p,l,w),h.extraText=w.join("
    "),h.y0=h.y1=o.c2p(p.yc,!0),[h]}e.exports={hoverPoints:function(t,e,r,n){return t.cd[0].trace.hoverlabel.split?f(t,e,r,n):h(t,e,r,n)},hoverSplit:f,hoverOnPoints:h}},{"../../components/color":366,"../../components/fx":406,"../../constants/delta.js":473,"../../lib":503,"../../plots/cartesian/axes":554}],876:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"ohlc",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","showLegend"],meta:{},attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("./calc").calc,plot:t("./plot"),style:t("./style"),hoverPoints:t("./hover").hoverPoints,selectPoints:t("./select")}},{"../../plots/cartesian":568,"./attributes":872,"./calc":873,"./defaults":874,"./hover":875,"./plot":878,"./select":879,"./style":880}],877:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib");e.exports=function(t,e,r,a){var o=r("x"),s=r("open"),l=r("high"),c=r("low"),u=r("close");if(r("hoverlabel.split"),n.getComponentMethod("calendars","handleTraceDefaults")(t,e,["x"],a),s&&l&&c&&u){var f=Math.min(s.length,l.length,c.length,u.length);return o&&(f=Math.min(f,i.minRowLength(o))),e._length=f,f}}},{"../../lib":503,"../../registry":638}],878:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib");e.exports=function(t,e,r,a){var o=e.yaxis,s=e.xaxis,l=!!s.rangebreaks;i.makeTraceGroups(a,r,"trace ohlc").each((function(t){var e=n.select(this),r=t[0],a=r.t;if(!0!==r.trace.visible||a.empty)e.remove();else{var c=a.tickLen,u=e.selectAll("path").data(i.identity);u.enter().append("path"),u.exit().remove(),u.attr("d",(function(t){if(t.empty)return"M0,0Z";var e=s.c2p(t.pos-c,!0),r=s.c2p(t.pos+c,!0),n=l?(e+r)/2:s.c2p(t.pos,!0);return"M"+e+","+o.c2p(t.o,!0)+"H"+n+"M"+n+","+o.c2p(t.h,!0)+"V"+o.c2p(t.l,!0)+"M"+r+","+o.c2p(t.c,!0)+"H"+n}))}}))}},{"../../lib":503,"@plotly/d3":58}],879:[function(t,e,r){"use strict";e.exports=function(t,e){var r,n=t.cd,i=t.xaxis,a=t.yaxis,o=[],s=n[0].t.bPos||0;if(!1===e)for(r=0;r=t.length)return!1;if(void 0!==e[t[r]])return!1;e[t[r]]=!0}return!0}(t.map((function(t){return t.displayindex}))))for(e=0;e0;c&&(o="array");var u=r("categoryorder",o);"array"===u?(r("categoryarray"),r("ticktext")):(delete t.categoryarray,delete t.ticktext),c||"array"!==u||(e.categoryorder="trace")}}e.exports=function(t,e,r,f){function h(r,i){return n.coerce(t,e,l,r,i)}var p=s(t,e,{name:"dimensions",handleItemDefaults:u}),d=function(t,e,r,o,s){s("line.shape"),s("line.hovertemplate");var l=s("line.color",o.colorway[0]);if(i(t,"line")&&n.isArrayOrTypedArray(l)){if(l.length)return s("line.colorscale"),a(t,e,o,s,{prefix:"line.",cLetter:"c"}),l.length;e.line.color=r}return 1/0}(t,e,r,f,h);o(e,f,h),Array.isArray(p)&&p.length||(e.visible=!1),c(e,p,"values",d),h("hoveron"),h("hovertemplate"),h("arrangement"),h("bundlecolors"),h("sortpaths"),h("counts");var m={family:f.font.family,size:Math.round(f.font.size),color:f.font.color};n.coerceFont(h,"labelfont",m);var g={family:f.font.family,size:Math.round(f.font.size/1.2),color:f.font.color};n.coerceFont(h,"tickfont",g)}},{"../../components/colorscale/defaults":376,"../../components/colorscale/helpers":377,"../../lib":503,"../../plots/array_container_defaults":549,"../../plots/domain":584,"../parcoords/merge_length":898,"./attributes":881}],885:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("./calc"),plot:t("./plot"),colorbar:{container:"line",min:"cmin",max:"cmax"},moduleType:"trace",name:"parcats",basePlotModule:t("./base_plot"),categories:["noOpacity"],meta:{}}},{"./attributes":881,"./base_plot":882,"./calc":883,"./defaults":884,"./plot":887}],886:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("d3-interpolate").interpolateNumber,a=t("../../plot_api/plot_api"),o=t("../../components/fx"),s=t("../../lib"),l=s.strTranslate,c=t("../../components/drawing"),u=t("tinycolor2"),f=t("../../lib/svg_text_utils");function h(t,e,r,i){var a=t.map(F.bind(0,e,r)),o=i.selectAll("g.parcatslayer").data([null]);o.enter().append("g").attr("class","parcatslayer").style("pointer-events","all");var u=o.selectAll("g.trace.parcats").data(a,p),h=u.enter().append("g").attr("class","trace parcats");u.attr("transform",(function(t){return l(t.x,t.y)})),h.append("g").attr("class","paths");var y=u.select("g.paths").selectAll("path.path").data((function(t){return t.paths}),p);y.attr("fill",(function(t){return t.model.color}));var x=y.enter().append("path").attr("class","path").attr("stroke-opacity",0).attr("fill",(function(t){return t.model.color})).attr("fill-opacity",0);_(x),y.attr("d",(function(t){return t.svgD})),x.empty()||y.sort(m),y.exit().remove(),y.on("mouseover",g).on("mouseout",v).on("click",b),h.append("g").attr("class","dimensions");var w=u.select("g.dimensions").selectAll("g.dimension").data((function(t){return t.dimensions}),p);w.enter().append("g").attr("class","dimension"),w.attr("transform",(function(t){return l(t.x,0)})),w.exit().remove();var A=w.selectAll("g.category").data((function(t){return t.categories}),p),M=A.enter().append("g").attr("class","category");A.attr("transform",(function(t){return l(0,t.y)})),M.append("rect").attr("class","catrect").attr("pointer-events","none"),A.select("rect.catrect").attr("fill","none").attr("width",(function(t){return t.width})).attr("height",(function(t){return t.height})),T(M);var S=A.selectAll("rect.bandrect").data((function(t){return t.bands}),p);S.each((function(){s.raiseToTop(this)})),S.attr("fill",(function(t){return t.color}));var E=S.enter().append("rect").attr("class","bandrect").attr("stroke-opacity",0).attr("fill",(function(t){return t.color})).attr("fill-opacity",0);S.attr("fill",(function(t){return t.color})).attr("width",(function(t){return t.width})).attr("height",(function(t){return t.height})).attr("y",(function(t){return t.y})).attr("cursor",(function(t){return"fixed"===t.parcatsViewModel.arrangement?"default":"perpendicular"===t.parcatsViewModel.arrangement?"ns-resize":"move"})),k(E),S.exit().remove(),M.append("text").attr("class","catlabel").attr("pointer-events","none");var z=e._fullLayout.paper_bgcolor;A.select("text.catlabel").attr("text-anchor",(function(t){return d(t)?"start":"end"})).attr("alignment-baseline","middle").style("text-shadow",f.makeTextShadow(z)).style("fill","rgb(0, 0, 0)").attr("x",(function(t){return d(t)?t.width+5:-5})).attr("y",(function(t){return t.height/2})).text((function(t){return t.model.categoryLabel})).each((function(t){c.font(n.select(this),t.parcatsViewModel.categorylabelfont),f.convertToTspans(n.select(this),e)})),M.append("text").attr("class","dimlabel"),A.select("text.dimlabel").attr("text-anchor","middle").attr("alignment-baseline","baseline").attr("cursor",(function(t){return"fixed"===t.parcatsViewModel.arrangement?"default":"ew-resize"})).attr("x",(function(t){return t.width/2})).attr("y",-5).text((function(t,e){return 0===e?t.parcatsViewModel.model.dimensions[t.model.dimensionInd].dimensionLabel:null})).each((function(t){c.font(n.select(this),t.parcatsViewModel.labelfont)})),A.selectAll("rect.bandrect").on("mouseover",L).on("mouseout",C),A.exit().remove(),w.call(n.behavior.drag().origin((function(t){return{x:t.x,y:0}})).on("dragstart",P).on("drag",I).on("dragend",O)),u.each((function(t){t.traceSelection=n.select(this),t.pathSelection=n.select(this).selectAll("g.paths").selectAll("path.path"),t.dimensionSelection=n.select(this).selectAll("g.dimensions").selectAll("g.dimension")})),u.exit().remove()}function p(t){return t.key}function d(t){var e=t.parcatsViewModel.dimensions.length,r=t.parcatsViewModel.dimensions[e-1].model.dimensionInd;return t.model.dimensionInd===r}function m(t,e){return t.model.rawColor>e.model.rawColor?1:t.model.rawColor"),L=n.mouse(f)[0];o.loneHover({trace:h,x:b-d.left+m.left,y:_-d.top+m.top,text:E,color:t.model.color,borderColor:"black",fontFamily:'Monaco, "Courier New", monospace',fontSize:10,fontColor:T,idealAlign:L1&&h.displayInd===f.dimensions.length-1?(i=c.left,a="left"):(i=c.left+c.width,a="right");var m=u.model.count,g=u.model.categoryLabel,v=m/u.parcatsViewModel.model.count,y={countLabel:m,categoryLabel:g,probabilityLabel:v.toFixed(3)},x=[];-1!==u.parcatsViewModel.hoverinfoItems.indexOf("count")&&x.push(["Count:",y.countLabel].join(" ")),-1!==u.parcatsViewModel.hoverinfoItems.indexOf("probability")&&x.push(["P("+y.categoryLabel+"):",y.probabilityLabel].join(" "));var b=x.join("
    ");return{trace:p,x:o*(i-e.left),y:s*(d-e.top),text:b,color:"lightgray",borderColor:"black",fontFamily:'Monaco, "Courier New", monospace',fontSize:12,fontColor:"black",idealAlign:a,hovertemplate:p.hovertemplate,hovertemplateLabels:y,eventData:[{data:p._input,fullData:p,count:m,category:g,probability:v}]}}function L(t){if(!t.parcatsViewModel.dragDimension&&-1===t.parcatsViewModel.hoverinfoItems.indexOf("skip")){if(n.mouse(this)[1]<-1)return;var e,r=t.parcatsViewModel.graphDiv,i=r._fullLayout,a=i._paperdiv.node().getBoundingClientRect(),l=t.parcatsViewModel.hoveron;if("color"===l?(!function(t){var e=n.select(t).datum(),r=A(e);w(r),r.each((function(){s.raiseToTop(this)})),n.select(t.parentNode).selectAll("rect.bandrect").filter((function(t){return t.color===e.color})).each((function(){s.raiseToTop(this),n.select(this).attr("stroke","black").attr("stroke-width",1.5)}))}(this),S(this,"plotly_hover",n.event)):(!function(t){n.select(t.parentNode).selectAll("rect.bandrect").each((function(t){var e=A(t);w(e),e.each((function(){s.raiseToTop(this)}))})),n.select(t.parentNode).select("rect.catrect").attr("stroke","black").attr("stroke-width",2.5)}(this),M(this,"plotly_hover",n.event)),-1===t.parcatsViewModel.hoverinfoItems.indexOf("none"))"category"===l?e=E(r,a,this):"color"===l?e=function(t,e,r){t._fullLayout._calcInverseTransform(t);var i,a,o=t._fullLayout._invScaleX,s=t._fullLayout._invScaleY,l=r.getBoundingClientRect(),c=n.select(r).datum(),f=c.categoryViewModel,h=f.parcatsViewModel,p=h.model.dimensions[f.model.dimensionInd],d=h.trace,m=l.y+l.height/2;h.dimensions.length>1&&p.displayInd===h.dimensions.length-1?(i=l.left,a="left"):(i=l.left+l.width,a="right");var g=f.model.categoryLabel,v=c.parcatsViewModel.model.count,y=0;c.categoryViewModel.bands.forEach((function(t){t.color===c.color&&(y+=t.count)}));var x=f.model.count,b=0;h.pathSelection.each((function(t){t.model.color===c.color&&(b+=t.model.count)}));var _=y/v,w=y/b,T=y/x,k={countLabel:v,categoryLabel:g,probabilityLabel:_.toFixed(3)},A=[];-1!==f.parcatsViewModel.hoverinfoItems.indexOf("count")&&A.push(["Count:",k.countLabel].join(" ")),-1!==f.parcatsViewModel.hoverinfoItems.indexOf("probability")&&(A.push("P(color \u2229 "+g+"): "+k.probabilityLabel),A.push("P("+g+" | color): "+w.toFixed(3)),A.push("P(color | "+g+"): "+T.toFixed(3)));var M=A.join("
    "),S=u.mostReadable(c.color,["black","white"]);return{trace:d,x:o*(i-e.left),y:s*(m-e.top),text:M,color:c.color,borderColor:"black",fontFamily:'Monaco, "Courier New", monospace',fontColor:S,fontSize:10,idealAlign:a,hovertemplate:d.hovertemplate,hovertemplateLabels:k,eventData:[{data:d._input,fullData:d,category:g,count:v,probability:_,categorycount:x,colorcount:b,bandcolorcount:y}]}}(r,a,this):"dimension"===l&&(e=function(t,e,r){var i=[];return n.select(r.parentNode.parentNode).selectAll("g.category").select("rect.catrect").each((function(){i.push(E(t,e,this))})),i}(r,a,this)),e&&o.loneHover(e,{container:i._hoverlayer.node(),outerContainer:i._paper.node(),gd:r})}}function C(t){var e=t.parcatsViewModel;if(!e.dragDimension&&(_(e.pathSelection),T(e.dimensionSelection.selectAll("g.category")),k(e.dimensionSelection.selectAll("g.category").selectAll("rect.bandrect")),o.loneUnhover(e.graphDiv._fullLayout._hoverlayer.node()),e.pathSelection.sort(m),-1===e.hoverinfoItems.indexOf("skip"))){"color"===t.parcatsViewModel.hoveron?S(this,"plotly_unhover",n.event):M(this,"plotly_unhover",n.event)}}function P(t){"fixed"!==t.parcatsViewModel.arrangement&&(t.dragDimensionDisplayInd=t.model.displayInd,t.initialDragDimensionDisplayInds=t.parcatsViewModel.model.dimensions.map((function(t){return t.displayInd})),t.dragHasMoved=!1,t.dragCategoryDisplayInd=null,n.select(this).selectAll("g.category").select("rect.catrect").each((function(e){var r=n.mouse(this)[0],i=n.mouse(this)[1];-2<=r&&r<=e.width+2&&-2<=i&&i<=e.height+2&&(t.dragCategoryDisplayInd=e.model.displayInd,t.initialDragCategoryDisplayInds=t.model.categories.map((function(t){return t.displayInd})),e.model.dragY=e.y,s.raiseToTop(this.parentNode),n.select(this.parentNode).selectAll("rect.bandrect").each((function(e){e.yf.y+f.height/2&&(o.model.displayInd=f.model.displayInd,f.model.displayInd=l),t.dragCategoryDisplayInd=o.model.displayInd}if(null===t.dragCategoryDisplayInd||"freeform"===t.parcatsViewModel.arrangement){a.model.dragX=n.event.x;var h=t.parcatsViewModel.dimensions[r],p=t.parcatsViewModel.dimensions[i];void 0!==h&&a.model.dragXp.x&&(a.model.displayInd=p.model.displayInd,p.model.displayInd=t.dragDimensionDisplayInd),t.dragDimensionDisplayInd=a.model.displayInd}j(t.parcatsViewModel),N(t.parcatsViewModel),R(t.parcatsViewModel),D(t.parcatsViewModel)}}function O(t){if("fixed"!==t.parcatsViewModel.arrangement&&null!==t.dragDimensionDisplayInd){n.select(this).selectAll("text").attr("font-weight","normal");var e={},r=z(t.parcatsViewModel),i=t.parcatsViewModel.model.dimensions.map((function(t){return t.displayInd})),o=t.initialDragDimensionDisplayInds.some((function(t,e){return t!==i[e]}));o&&i.forEach((function(r,n){var i=t.parcatsViewModel.model.dimensions[n].containerInd;e["dimensions["+i+"].displayindex"]=r}));var s=!1;if(null!==t.dragCategoryDisplayInd){var l=t.model.categories.map((function(t){return t.displayInd}));if(s=t.initialDragCategoryDisplayInds.some((function(t,e){return t!==l[e]}))){var c=t.model.categories.slice().sort((function(t,e){return t.displayInd-e.displayInd})),u=c.map((function(t){return t.categoryValue})),f=c.map((function(t){return t.categoryLabel}));e["dimensions["+t.model.containerInd+"].categoryarray"]=[u],e["dimensions["+t.model.containerInd+"].ticktext"]=[f],e["dimensions["+t.model.containerInd+"].categoryorder"]="array"}}if(-1===t.parcatsViewModel.hoverinfoItems.indexOf("skip")&&!t.dragHasMoved&&t.potentialClickBand&&("color"===t.parcatsViewModel.hoveron?S(t.potentialClickBand,"plotly_click",n.event.sourceEvent):M(t.potentialClickBand,"plotly_click",n.event.sourceEvent)),t.model.dragX=null,null!==t.dragCategoryDisplayInd)t.parcatsViewModel.dimensions[t.dragDimensionDisplayInd].categories[t.dragCategoryDisplayInd].model.dragY=null,t.dragCategoryDisplayInd=null;t.dragDimensionDisplayInd=null,t.parcatsViewModel.dragDimension=null,t.dragHasMoved=null,t.potentialClickBand=null,j(t.parcatsViewModel),N(t.parcatsViewModel),n.transition().duration(300).ease("cubic-in-out").each((function(){R(t.parcatsViewModel,!0),D(t.parcatsViewModel,!0)})).each("end",(function(){(o||s)&&a.restyle(t.parcatsViewModel.graphDiv,e,[r])}))}}function z(t){for(var e,r=t.graphDiv._fullData,n=0;n=0;s--)u+="C"+c[s]+","+(e[s+1]+n)+" "+l[s]+","+(e[s]+n)+" "+(t[s]+r[s])+","+(e[s]+n),u+="l-"+r[s]+",0 ";return u+="Z"}function N(t){var e=t.dimensions,r=t.model,n=e.map((function(t){return t.categories.map((function(t){return t.y}))})),i=t.model.dimensions.map((function(t){return t.categories.map((function(t){return t.displayInd}))})),a=t.model.dimensions.map((function(t){return t.displayInd})),o=t.dimensions.map((function(t){return t.model.dimensionInd})),s=e.map((function(t){return t.x})),l=e.map((function(t){return t.width})),c=[];for(var u in r.paths)r.paths.hasOwnProperty(u)&&c.push(r.paths[u]);function f(t){var e=t.categoryInds.map((function(t,e){return i[e][t]}));return o.map((function(t){return e[t]}))}c.sort((function(e,r){var n=f(e),i=f(r);return"backward"===t.sortpaths&&(n.reverse(),i.reverse()),n.push(e.valueInds[0]),i.push(r.valueInds[0]),t.bundlecolors&&(n.unshift(e.rawColor),i.unshift(r.rawColor)),ni?1:0}));for(var h=new Array(c.length),p=e[0].model.count,d=e[0].categories.map((function(t){return t.height})).reduce((function(t,e){return t+e})),m=0;m0?d*(v.count/p):0;for(var y,x=new Array(n.length),b=0;b1?(t.width-80-16)/(n-1):0)*i;var a,o,s,l,c,u=[],f=t.model.maxCats,h=e.categories.length,p=e.count,d=t.height-8*(f-1),m=8*(f-h)/2,g=e.categories.map((function(t){return{displayInd:t.displayInd,categoryInd:t.categoryInd}}));for(g.sort((function(t,e){return t.displayInd-e.displayInd})),c=0;c0?o.count/p*d:0,s={key:o.valueInds[0],model:o,width:16,height:a,y:null!==o.dragY?o.dragY:m,bands:[],parcatsViewModel:t},m=m+a+8,u.push(s);return{key:e.dimensionInd,x:null!==e.dragX?e.dragX:r,y:0,width:16,model:e,categories:u,parcatsViewModel:t,dragCategoryDisplayInd:null,dragDimensionDisplayInd:null,initialDragDimensionDisplayInds:null,initialDragCategoryDisplayInds:null,dragHasMoved:null,potentialClickBand:null}}e.exports=function(t,e,r,n){h(r,t,n,e)}},{"../../components/drawing":388,"../../components/fx":406,"../../lib":503,"../../lib/svg_text_utils":529,"../../plot_api/plot_api":540,"@plotly/d3":58,"d3-interpolate":116,tinycolor2:312}],887:[function(t,e,r){"use strict";var n=t("./parcats");e.exports=function(t,e,r,i){var a=t._fullLayout,o=a._paper,s=a._size;n(t,o,e,{width:s.w,height:s.h,margin:{t:s.t,r:s.r,b:s.b,l:s.l}},r,i)}},{"./parcats":886}],888:[function(t,e,r){"use strict";var n=t("../../components/colorscale/attributes"),i=t("../../plots/cartesian/layout_attributes"),a=t("../../plots/font_attributes"),o=t("../../plots/domain").attributes,s=t("../../lib/extend").extendFlat,l=t("../../plot_api/plot_template").templatedArray;e.exports={domain:o({name:"parcoords",trace:!0,editType:"plot"}),labelangle:{valType:"angle",dflt:0,editType:"plot"},labelside:{valType:"enumerated",values:["top","bottom"],dflt:"top",editType:"plot"},labelfont:a({editType:"plot"}),tickfont:a({editType:"plot"}),rangefont:a({editType:"plot"}),dimensions:l("dimension",{label:{valType:"string",editType:"plot"},tickvals:s({},i.tickvals,{editType:"plot"}),ticktext:s({},i.ticktext,{editType:"plot"}),tickformat:s({},i.tickformat,{editType:"plot"}),visible:{valType:"boolean",dflt:!0,editType:"plot"},range:{valType:"info_array",items:[{valType:"number",editType:"plot"},{valType:"number",editType:"plot"}],editType:"plot"},constraintrange:{valType:"info_array",freeLength:!0,dimensions:"1-2",items:[{valType:"any",editType:"plot"},{valType:"any",editType:"plot"}],editType:"plot"},multiselect:{valType:"boolean",dflt:!0,editType:"plot"},values:{valType:"data_array",editType:"calc"},editType:"calc"}),line:s({editType:"calc"},n("line",{colorscaleDflt:"Viridis",autoColorDflt:!1,editTypeOverride:"calc"}))}},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plot_api/plot_template":543,"../../plots/cartesian/layout_attributes":569,"../../plots/domain":584,"../../plots/font_attributes":585}],889:[function(t,e,r){"use strict";var n=t("./constants"),i=t("@plotly/d3"),a=t("../../lib/gup").keyFun,o=t("../../lib/gup").repeat,s=t("../../lib").sorterAsc,l=t("../../lib").strTranslate,c=n.bar.snapRatio;function u(t,e){return t*(1-c)+e*c}var f=n.bar.snapClose;function h(t,e){return t*(1-f)+e*f}function p(t,e,r,n){if(function(t,e){for(var r=0;r=e[r][0]&&t<=e[r][1])return!0;return!1}(r,n))return r;var i=t?-1:1,a=0,o=e.length-1;if(i<0){var s=a;a=o,o=s}for(var l=e[a],c=l,f=a;i*fe){h=r;break}}if(a=u,isNaN(a)&&(a=isNaN(f)||isNaN(h)?isNaN(f)?h:f:e-c[f][1]t[1]+r||e=.9*t[1]+.1*t[0]?"n":e<=.9*t[0]+.1*t[1]?"s":"ns"}(d,e);m&&(o.interval=l[a],o.intervalPix=d,o.region=m)}}if(t.ordinal&&!o.region){var g=t.unitTickvals,y=t.unitToPaddedPx.invert(e);for(r=0;r=x[0]&&y<=x[1]){o.clickableOrdinalRange=x;break}}}return o}function w(t,e){i.event.sourceEvent.stopPropagation();var r=e.height-i.mouse(t)[1]-2*n.verticalPadding,a=e.brush.svgBrush;a.wasDragged=!0,a._dragging=!0,a.grabbingBar?a.newExtent=[r-a.grabPoint,r+a.barLength-a.grabPoint].map(e.unitToPaddedPx.invert):a.newExtent=[a.startExtent,e.unitToPaddedPx.invert(r)].sort(s),e.brush.filterSpecified=!0,a.extent=a.stayingIntervals.concat([a.newExtent]),a.brushCallback(e),b(t.parentNode)}function T(t,e){var r=_(e,e.height-i.mouse(t)[1]-2*n.verticalPadding),a="crosshair";r.clickableOrdinalRange?a="pointer":r.region&&(a=r.region+"-resize"),i.select(document.body).style("cursor",a)}function k(t){t.on("mousemove",(function(t){i.event.preventDefault(),t.parent.inBrushDrag||T(this,t)})).on("mouseleave",(function(t){t.parent.inBrushDrag||y()})).call(i.behavior.drag().on("dragstart",(function(t){!function(t,e){i.event.sourceEvent.stopPropagation();var r=e.height-i.mouse(t)[1]-2*n.verticalPadding,a=e.unitToPaddedPx.invert(r),o=e.brush,s=_(e,r),l=s.interval,c=o.svgBrush;if(c.wasDragged=!1,c.grabbingBar="ns"===s.region,c.grabbingBar){var u=l.map(e.unitToPaddedPx);c.grabPoint=r-u[0]-n.verticalPadding,c.barLength=u[1]-u[0]}c.clickableOrdinalRange=s.clickableOrdinalRange,c.stayingIntervals=e.multiselect&&o.filterSpecified?o.filter.getConsolidated():[],l&&(c.stayingIntervals=c.stayingIntervals.filter((function(t){return t[0]!==l[0]&&t[1]!==l[1]}))),c.startExtent=s.region?l["s"===s.region?1:0]:a,e.parent.inBrushDrag=!0,c.brushStartCallback()}(this,t)})).on("drag",(function(t){w(this,t)})).on("dragend",(function(t){!function(t,e){var r=e.brush,n=r.filter,a=r.svgBrush;a._dragging||(T(t,e),w(t,e),e.brush.svgBrush.wasDragged=!1),a._dragging=!1,i.event.sourceEvent.stopPropagation();var o=a.grabbingBar;if(a.grabbingBar=!1,a.grabLocation=void 0,e.parent.inBrushDrag=!1,y(),!a.wasDragged)return a.wasDragged=void 0,a.clickableOrdinalRange?r.filterSpecified&&e.multiselect?a.extent.push(a.clickableOrdinalRange):(a.extent=[a.clickableOrdinalRange],r.filterSpecified=!0):o?(a.extent=a.stayingIntervals,0===a.extent.length&&M(r)):M(r),a.brushCallback(e),b(t.parentNode),void a.brushEndCallback(r.filterSpecified?n.getConsolidated():[]);var s=function(){n.set(n.getConsolidated())};if(e.ordinal){var l=e.unitTickvals;l[l.length-1]a.newExtent[0];a.extent=a.stayingIntervals.concat(c?[a.newExtent]:[]),a.extent.length||M(r),a.brushCallback(e),c?b(t.parentNode,s):(s(),b(t.parentNode))}else s();a.brushEndCallback(r.filterSpecified?n.getConsolidated():[])}(this,t)})))}function A(t,e){return t[0]-e[0]}function M(t){t.filterSpecified=!1,t.svgBrush.extent=[[-1/0,1/0]]}function S(t){for(var e,r=t.slice(),n=[],i=r.shift();i;){for(e=i.slice();(i=r.shift())&&i[0]<=e[1];)e[1]=Math.max(e[1],i[1]);n.push(e)}return 1===n.length&&n[0][0]>n[0][1]&&(n=[]),n}e.exports={makeBrush:function(t,e,r,n,i,a){var o,l=function(){var t,e,r=[];return{set:function(n){1===(r=n.map((function(t){return t.slice().sort(s)})).sort(A)).length&&r[0][0]===-1/0&&r[0][1]===1/0&&(r=[[0,-1]]),t=S(r),e=r.reduce((function(t,e){return[Math.min(t[0],e[0]),Math.max(t[1],e[1])]}),[1/0,-1/0])},get:function(){return r.slice()},getConsolidated:function(){return t},getBounds:function(){return e}}}();return l.set(r),{filter:l,filterSpecified:e,svgBrush:{extent:[],brushStartCallback:n,brushCallback:(o=i,function(t){var e=t.brush,r=function(t){return t.svgBrush.extent.map((function(t){return t.slice()}))}(e).slice();e.filter.set(r),o()}),brushEndCallback:a}}},ensureAxisBrush:function(t,e){var r=t.selectAll("."+n.cn.axisBrush).data(o,a);r.enter().append("g").classed(n.cn.axisBrush,!0),function(t,e){var r=t.selectAll(".background").data(o);r.enter().append("rect").classed("background",!0).call(d).call(m).style("pointer-events","auto").attr("transform",l(0,n.verticalPadding)),r.call(k).attr("height",(function(t){return t.height-n.verticalPadding}));var i=t.selectAll(".highlight-shadow").data(o);i.enter().append("line").classed("highlight-shadow",!0).attr("x",-n.bar.width/2).attr("stroke-width",n.bar.width+n.bar.strokeWidth).attr("stroke",e).attr("opacity",n.bar.strokeOpacity).attr("stroke-linecap","butt"),i.attr("y1",(function(t){return t.height})).call(x);var a=t.selectAll(".highlight").data(o);a.enter().append("line").classed("highlight",!0).attr("x",-n.bar.width/2).attr("stroke-width",n.bar.width-n.bar.strokeWidth).attr("stroke",n.bar.fillColor).attr("opacity",n.bar.fillOpacity).attr("stroke-linecap","butt"),a.attr("y1",(function(t){return t.height})).call(x)}(r,e)},cleanRanges:function(t,e){if(Array.isArray(t[0])?(t=t.map((function(t){return t.sort(s)})),t=e.multiselect?S(t.sort(A)):[t[0]]):t=[t.sort(s)],e.tickvals){var r=e.tickvals.slice().sort(s);if(!(t=t.map((function(t){var e=[p(0,r,t[0],[]),p(1,r,t[1],[])];if(e[1]>e[0])return e})).filter((function(t){return t}))).length)return}return t.length>1?t:t[0]}}},{"../../lib":503,"../../lib/gup":500,"./constants":893,"@plotly/d3":58}],890:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("./calc"),colorbar:{container:"line",min:"cmin",max:"cmax"},moduleType:"trace",name:"parcoords",basePlotModule:t("./base_plot"),categories:["gl","regl","noOpacity","noHover"],meta:{}}},{"./attributes":888,"./base_plot":891,"./calc":892,"./defaults":894}],891:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../plots/get_data").getModuleCalcData,a=t("./plot"),o=t("../../constants/xmlns_namespaces");r.name="parcoords",r.plot=function(t){var e=i(t.calcdata,"parcoords")[0];e.length&&a(t,e)},r.clean=function(t,e,r,n){var i=n._has&&n._has("parcoords"),a=e._has&&e._has("parcoords");i&&!a&&(n._paperdiv.selectAll(".parcoords").remove(),n._glimages.selectAll("*").remove())},r.toSVG=function(t){var e=t._fullLayout._glimages,r=n.select(t).selectAll(".svg-container");r.filter((function(t,e){return e===r.size()-1})).selectAll(".gl-canvas-context, .gl-canvas-focus").each((function(){var t=this.toDataURL("image/png");e.append("svg:image").attr({xmlns:o.svg,"xlink:href":t,preserveAspectRatio:"none",x:0,y:0,width:this.style.width,height:this.style.height})})),window.setTimeout((function(){n.selectAll("#filterBarPattern").attr("id","filterBarPattern")}),60)}},{"../../constants/xmlns_namespaces":480,"../../plots/get_data":593,"./plot":900,"@plotly/d3":58}],892:[function(t,e,r){"use strict";var n=t("../../lib").isArrayOrTypedArray,i=t("../../components/colorscale"),a=t("../../lib/gup").wrap;e.exports=function(t,e){var r,o;return i.hasColorscale(e,"line")&&n(e.line.color)?(r=e.line.color,o=i.extractOpts(e.line).colorscale,i.calc(t,e,{vals:r,containerStr:"line",cLetter:"c"})):(r=function(t){for(var e=new Array(t),r=0;rf&&(n.log("parcoords traces support up to "+f+" dimensions at the moment"),d.splice(f));var m=s(t,e,{name:"dimensions",layout:l,handleItemDefaults:p}),g=function(t,e,r,o,s){var l=s("line.color",r);if(i(t,"line")&&n.isArrayOrTypedArray(l)){if(l.length)return s("line.colorscale"),a(t,e,o,s,{prefix:"line.",cLetter:"c"}),l.length;e.line.color=r}return 1/0}(t,e,r,l,u);o(e,l,u),Array.isArray(m)&&m.length||(e.visible=!1),h(e,m,"values",g);var v={family:l.font.family,size:Math.round(l.font.size/1.2),color:l.font.color};n.coerceFont(u,"labelfont",v),n.coerceFont(u,"tickfont",v),n.coerceFont(u,"rangefont",v),u("labelangle"),u("labelside")}},{"../../components/colorscale/defaults":376,"../../components/colorscale/helpers":377,"../../lib":503,"../../plots/array_container_defaults":549,"../../plots/cartesian/axes":554,"../../plots/domain":584,"./attributes":888,"./axisbrush":889,"./constants":893,"./merge_length":898}],895:[function(t,e,r){"use strict";var n=t("../../lib").isTypedArray;r.convertTypedArray=function(t){return n(t)?Array.prototype.slice.call(t):t},r.isOrdinal=function(t){return!!t.tickvals},r.isVisible=function(t){return t.visible||!("visible"in t)}},{"../../lib":503}],896:[function(t,e,r){"use strict";var n=t("./base_index");n.plot=t("./plot"),e.exports=n},{"./base_index":890,"./plot":900}],897:[function(t,e,r){"use strict";var n=t("glslify"),i=n(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nattribute vec4 p01_04, p05_08, p09_12, p13_16,\n p17_20, p21_24, p25_28, p29_32,\n p33_36, p37_40, p41_44, p45_48,\n p49_52, p53_56, p57_60, colors;\n\nuniform mat4 dim0A, dim1A, dim0B, dim1B, dim0C, dim1C, dim0D, dim1D,\n loA, hiA, loB, hiB, loC, hiC, loD, hiD;\n\nuniform vec2 resolution, viewBoxPos, viewBoxSize;\nuniform float maskHeight;\nuniform float drwLayer; // 0: context, 1: focus, 2: pick\nuniform vec4 contextColor;\nuniform sampler2D maskTexture, palette;\n\nbool isPick = (drwLayer > 1.5);\nbool isContext = (drwLayer < 0.5);\n\nconst vec4 ZEROS = vec4(0.0, 0.0, 0.0, 0.0);\nconst vec4 UNITS = vec4(1.0, 1.0, 1.0, 1.0);\n\nfloat val(mat4 p, mat4 v) {\n return dot(matrixCompMult(p, v) * UNITS, UNITS);\n}\n\nfloat axisY(float ratio, mat4 A, mat4 B, mat4 C, mat4 D) {\n float y1 = val(A, dim0A) + val(B, dim0B) + val(C, dim0C) + val(D, dim0D);\n float y2 = val(A, dim1A) + val(B, dim1B) + val(C, dim1C) + val(D, dim1D);\n return y1 * (1.0 - ratio) + y2 * ratio;\n}\n\nint iMod(int a, int b) {\n return a - b * (a / b);\n}\n\nbool fOutside(float p, float lo, float hi) {\n return (lo < hi) && (lo > p || p > hi);\n}\n\nbool vOutside(vec4 p, vec4 lo, vec4 hi) {\n return (\n fOutside(p[0], lo[0], hi[0]) ||\n fOutside(p[1], lo[1], hi[1]) ||\n fOutside(p[2], lo[2], hi[2]) ||\n fOutside(p[3], lo[3], hi[3])\n );\n}\n\nbool mOutside(mat4 p, mat4 lo, mat4 hi) {\n return (\n vOutside(p[0], lo[0], hi[0]) ||\n vOutside(p[1], lo[1], hi[1]) ||\n vOutside(p[2], lo[2], hi[2]) ||\n vOutside(p[3], lo[3], hi[3])\n );\n}\n\nbool outsideBoundingBox(mat4 A, mat4 B, mat4 C, mat4 D) {\n return mOutside(A, loA, hiA) ||\n mOutside(B, loB, hiB) ||\n mOutside(C, loC, hiC) ||\n mOutside(D, loD, hiD);\n}\n\nbool outsideRasterMask(mat4 A, mat4 B, mat4 C, mat4 D) {\n mat4 pnts[4];\n pnts[0] = A;\n pnts[1] = B;\n pnts[2] = C;\n pnts[3] = D;\n\n for(int i = 0; i < 4; ++i) {\n for(int j = 0; j < 4; ++j) {\n for(int k = 0; k < 4; ++k) {\n if(0 == iMod(\n int(255.0 * texture2D(maskTexture,\n vec2(\n (float(i * 2 + j / 2) + 0.5) / 8.0,\n (pnts[i][j][k] * (maskHeight - 1.0) + 1.0) / maskHeight\n ))[3]\n ) / int(pow(2.0, float(iMod(j * 4 + k, 8)))),\n 2\n )) return true;\n }\n }\n }\n return false;\n}\n\nvec4 position(bool isContext, float v, mat4 A, mat4 B, mat4 C, mat4 D) {\n float x = 0.5 * sign(v) + 0.5;\n float y = axisY(x, A, B, C, D);\n float z = 1.0 - abs(v);\n\n z += isContext ? 0.0 : 2.0 * float(\n outsideBoundingBox(A, B, C, D) ||\n outsideRasterMask(A, B, C, D)\n );\n\n return vec4(\n 2.0 * (vec2(x, y) * viewBoxSize + viewBoxPos) / resolution - 1.0,\n z,\n 1.0\n );\n}\n\nvoid main() {\n mat4 A = mat4(p01_04, p05_08, p09_12, p13_16);\n mat4 B = mat4(p17_20, p21_24, p25_28, p29_32);\n mat4 C = mat4(p33_36, p37_40, p41_44, p45_48);\n mat4 D = mat4(p49_52, p53_56, p57_60, ZEROS);\n\n float v = colors[3];\n\n gl_Position = position(isContext, v, A, B, C, D);\n\n fragColor =\n isContext ? vec4(contextColor) :\n isPick ? vec4(colors.rgb, 1.0) : texture2D(palette, vec2(abs(v), 0.5));\n}\n"]),a=n(["precision highp float;\n#define GLSLIFY 1\n\nvarying vec4 fragColor;\n\nvoid main() {\n gl_FragColor = fragColor;\n}\n"]),o=t("./constants").maxDimensionCount,s=t("../../lib"),l=new Uint8Array(4),c=new Uint8Array(4),u={shape:[256,1],format:"rgba",type:"uint8",mag:"nearest",min:"nearest"};function f(t,e,r,n,i){var a=t._gl;a.enable(a.SCISSOR_TEST),a.scissor(e,r,n,i),t.clear({color:[0,0,0,0],depth:1})}function h(t,e,r,n,i,a){var o=a.key;r.drawCompleted||(!function(t){t.read({x:0,y:0,width:1,height:1,data:l})}(t),r.drawCompleted=!0),function s(l){var c=Math.min(n,i-l*n);0===l&&(window.cancelAnimationFrame(r.currentRafs[o]),delete r.currentRafs[o],f(t,a.scissorX,a.scissorY,a.scissorWidth,a.viewBoxSize[1])),r.clearOnly||(a.count=2*c,a.offset=2*l*n,e(a),l*n+c>>8*e)%256/255}function m(t,e,r){for(var n=new Array(8*e),i=0,a=0;au&&(u=t[i].dim1.canvasX,o=i);0===s&&f(T,0,0,r.canvasWidth,r.canvasHeight);var p=function(t){var e,r,n,i=[[],[]];for(n=0;n<64;n++){var a=!t&&no._length&&(S=S.slice(0,o._length));var L,C=o.tickvals;function P(t,e){return{val:t,text:L[e]}}function I(t,e){return t.val-e.val}if(Array.isArray(C)&&C.length){L=o.ticktext,Array.isArray(L)&&L.length?L.length>C.length?L=L.slice(0,C.length):C.length>L.length&&(C=C.slice(0,L.length)):L=C.map(a(o.tickformat));for(var O=1;O=r||l>=i)return;var c=t.lineLayer.readPixel(s,i-1-l),u=0!==c[3],f=u?c[2]+256*(c[1]+256*c[0]):null,h={x:s,y:l,clientX:e.clientX,clientY:e.clientY,dataIndex:t.model.key,curveNumber:f};f!==B&&(u?a.hover(h):a.unhover&&a.unhover(h),B=f)}})),F.style("opacity",(function(t){return t.pick?0:1})),h.style("background","rgba(255, 255, 255, 0)");var N=h.selectAll("."+y.cn.parcoords).data(R,d);N.exit().remove(),N.enter().append("g").classed(y.cn.parcoords,!0).style("shape-rendering","crispEdges").style("pointer-events","none"),N.attr("transform",(function(t){return c(t.model.translateX,t.model.translateY)}));var j=N.selectAll("."+y.cn.parcoordsControlView).data(m,d);j.enter().append("g").classed(y.cn.parcoordsControlView,!0),j.attr("transform",(function(t){return c(t.model.pad.l,t.model.pad.t)}));var U=j.selectAll("."+y.cn.yAxis).data((function(t){return t.dimensions}),d);U.enter().append("g").classed(y.cn.yAxis,!0),j.each((function(t){O(U,t,_)})),F.each((function(t){if(t.viewModel){!t.lineLayer||a?t.lineLayer=b(this,t):t.lineLayer.update(t),(t.key||0===t.key)&&(t.viewModel[t.key]=t.lineLayer);var e=!t.context||a;t.lineLayer.render(t.viewModel.panels,e)}})),U.attr("transform",(function(t){return c(t.xScale(t.xIndex),0)})),U.call(n.behavior.drag().origin((function(t){return t})).on("drag",(function(t){var e=t.parent;S.linePickActive(!1),t.x=Math.max(-y.overdrag,Math.min(t.model.width+y.overdrag,n.event.x)),t.canvasX=t.x*t.model.canvasPixelRatio,U.sort((function(t,e){return t.x-e.x})).each((function(e,r){e.xIndex=r,e.x=t===e?e.x:e.xScale(e.xIndex),e.canvasX=e.x*e.model.canvasPixelRatio})),O(U,e,_),U.filter((function(e){return 0!==Math.abs(t.xIndex-e.xIndex)})).attr("transform",(function(t){return c(t.xScale(t.xIndex),0)})),n.select(this).attr("transform",c(t.x,0)),U.each((function(r,n,i){i===t.parent.key&&(e.dimensions[n]=r)})),e.contextLayer&&e.contextLayer.render(e.panels,!1,!E(e)),e.focusLayer.render&&e.focusLayer.render(e.panels)})).on("dragend",(function(t){var e=t.parent;t.x=t.xScale(t.xIndex),t.canvasX=t.x*t.model.canvasPixelRatio,O(U,e,_),n.select(this).attr("transform",(function(t){return c(t.x,0)})),e.contextLayer&&e.contextLayer.render(e.panels,!1,!E(e)),e.focusLayer&&e.focusLayer.render(e.panels),e.pickLayer&&e.pickLayer.render(e.panels,!0),S.linePickActive(!0),a&&a.axesMoved&&a.axesMoved(e.key,e.dimensions.map((function(t){return t.crossfilterDimensionIndex})))}))),U.exit().remove();var V=U.selectAll("."+y.cn.axisOverlays).data(m,d);V.enter().append("g").classed(y.cn.axisOverlays,!0),V.selectAll("."+y.cn.axis).remove();var H=V.selectAll("."+y.cn.axis).data(m,d);H.enter().append("g").classed(y.cn.axis,!0),H.each((function(t){var e=t.model.height/t.model.tickDistance,r=t.domainScale,i=r.domain();n.select(this).call(n.svg.axis().orient("left").tickSize(4).outerTickSize(2).ticks(e,t.tickFormat).tickValues(t.ordinal?i:null).tickFormat((function(e){return v.isOrdinal(t)?e:z(t.model.dimensions[t.visibleIndex],e)})).scale(r)),f.font(H.selectAll("text"),t.model.tickFont)})),H.selectAll(".domain, .tick>line").attr("fill","none").attr("stroke","black").attr("stroke-opacity",.25).attr("stroke-width","1px"),H.selectAll("text").style("text-shadow",u.makeTextShadow(T)).style("cursor","default");var q=V.selectAll("."+y.cn.axisHeading).data(m,d);q.enter().append("g").classed(y.cn.axisHeading,!0);var G=q.selectAll("."+y.cn.axisTitle).data(m,d);G.enter().append("text").classed(y.cn.axisTitle,!0).attr("text-anchor","middle").style("cursor","ew-resize").style("pointer-events","auto"),G.text((function(t){return t.label})).each((function(e){var r=n.select(this);f.font(r,e.model.labelFont),u.convertToTspans(r,t)})).attr("transform",(function(t){var e=I(t.model.labelAngle,t.model.labelSide),r=y.axisTitleOffset;return(e.dir>0?"":c(0,2*r+t.model.height))+l(e.degrees)+c(-r*e.dx,-r*e.dy)})).attr("text-anchor",(function(t){var e=I(t.model.labelAngle,t.model.labelSide);return 2*Math.abs(e.dx)>Math.abs(e.dy)?e.dir*e.dx<0?"start":"end":"middle"}));var Y=V.selectAll("."+y.cn.axisExtent).data(m,d);Y.enter().append("g").classed(y.cn.axisExtent,!0);var W=Y.selectAll("."+y.cn.axisExtentTop).data(m,d);W.enter().append("g").classed(y.cn.axisExtentTop,!0),W.attr("transform",c(0,-y.axisExtentOffset));var X=W.selectAll("."+y.cn.axisExtentTopText).data(m,d);X.enter().append("text").classed(y.cn.axisExtentTopText,!0).call(P),X.text((function(t){return D(t,!0)})).each((function(t){f.font(n.select(this),t.model.rangeFont)}));var Z=Y.selectAll("."+y.cn.axisExtentBottom).data(m,d);Z.enter().append("g").classed(y.cn.axisExtentBottom,!0),Z.attr("transform",(function(t){return c(0,t.model.height+y.axisExtentOffset)}));var J=Z.selectAll("."+y.cn.axisExtentBottomText).data(m,d);J.enter().append("text").classed(y.cn.axisExtentBottomText,!0).attr("dy","0.75em").call(P),J.text((function(t){return D(t,!1)})).each((function(t){f.font(n.select(this),t.model.rangeFont)})),x.ensureAxisBrush(V,T)}},{"../../components/colorscale":378,"../../components/drawing":388,"../../lib":503,"../../lib/gup":500,"../../lib/svg_text_utils":529,"../../plots/cartesian/axes":554,"./axisbrush":889,"./constants":893,"./helpers":895,"./lines":897,"@plotly/d3":58,"color-rgba":91}],900:[function(t,e,r){"use strict";var n=t("./parcoords"),i=t("../../lib/prepare_regl"),a=t("./helpers").isVisible,o={};function s(t,e,r){var n=e.indexOf(r),i=t.indexOf(n);return-1===i&&(i+=e.length),i}(e.exports=function(t,e){var r=t._fullLayout;if(i(t,[],o)){var l={},c={},u={},f={},h=r._size;e.forEach((function(e,r){var n=e[0].trace;u[r]=n.index;var i=f[r]=n._fullInput.index;l[r]=t.data[i].dimensions,c[r]=t.data[i].dimensions.slice()}));n(t,e,{width:h.w,height:h.h,margin:{t:h.t,r:h.r,b:h.b,l:h.l}},{filterChanged:function(e,n,i){var a=c[e][n],o=i.map((function(t){return t.slice()})),s="dimensions["+n+"].constraintrange",l=r._tracePreGUI[t._fullData[u[e]]._fullInput.uid];if(void 0===l[s]){var h=a.constraintrange;l[s]=h||null}var p=t._fullData[u[e]].dimensions[n];o.length?(1===o.length&&(o=o[0]),a.constraintrange=o,p.constraintrange=o.slice(),o=[o]):(delete a.constraintrange,delete p.constraintrange,o=null);var d={};d[s]=o,t.emit("plotly_restyle",[d,[f[e]]])},hover:function(e){t.emit("plotly_hover",e)},unhover:function(e){t.emit("plotly_unhover",e)},axesMoved:function(e,r){var n=function(t,e){return function(r,n){return s(t,e,r)-s(t,e,n)}}(r,c[e].filter(a));l[e].sort(n),c[e].filter((function(t){return!a(t)})).sort((function(t){return c[e].indexOf(t)})).forEach((function(t){l[e].splice(l[e].indexOf(t),1),l[e].splice(c[e].indexOf(t),0,t)})),t.emit("plotly_restyle",[{dimensions:[l[e]]},[f[e]]])}})}}).reglPrecompiled=o},{"../../lib/prepare_regl":516,"./helpers":895,"./parcoords":899}],901:[function(t,e,r){"use strict";var n=t("../../plots/attributes"),i=t("../../plots/domain").attributes,a=t("../../plots/font_attributes"),o=t("../../components/color/attributes"),s=t("../../plots/template_attributes").hovertemplateAttrs,l=t("../../plots/template_attributes").texttemplateAttrs,c=t("../../lib/extend").extendFlat,u=a({editType:"plot",arrayOk:!0,colorEditType:"plot"});e.exports={labels:{valType:"data_array",editType:"calc"},label0:{valType:"number",dflt:0,editType:"calc"},dlabel:{valType:"number",dflt:1,editType:"calc"},values:{valType:"data_array",editType:"calc"},marker:{colors:{valType:"data_array",editType:"calc"},line:{color:{valType:"color",dflt:o.defaultLine,arrayOk:!0,editType:"style"},width:{valType:"number",min:0,dflt:0,arrayOk:!0,editType:"style"},editType:"calc"},editType:"calc"},text:{valType:"data_array",editType:"plot"},hovertext:{valType:"string",dflt:"",arrayOk:!0,editType:"style"},scalegroup:{valType:"string",dflt:"",editType:"calc"},textinfo:{valType:"flaglist",flags:["label","text","value","percent"],extras:["none"],editType:"calc"},hoverinfo:c({},n.hoverinfo,{flags:["label","text","value","percent","name"]}),hovertemplate:s({},{keys:["label","color","value","percent","text"]}),texttemplate:l({editType:"plot"},{keys:["label","color","value","percent","text"]}),textposition:{valType:"enumerated",values:["inside","outside","auto","none"],dflt:"auto",arrayOk:!0,editType:"plot"},textfont:c({},u,{}),insidetextorientation:{valType:"enumerated",values:["horizontal","radial","tangential","auto"],dflt:"auto",editType:"plot"},insidetextfont:c({},u,{}),outsidetextfont:c({},u,{}),automargin:{valType:"boolean",dflt:!1,editType:"plot"},title:{text:{valType:"string",dflt:"",editType:"plot"},font:c({},u,{}),position:{valType:"enumerated",values:["top left","top center","top right","middle center","bottom left","bottom center","bottom right"],editType:"plot"},editType:"plot"},domain:i({name:"pie",trace:!0,editType:"calc"}),hole:{valType:"number",min:0,max:1,dflt:0,editType:"calc"},sort:{valType:"boolean",dflt:!0,editType:"calc"},direction:{valType:"enumerated",values:["clockwise","counterclockwise"],dflt:"counterclockwise",editType:"calc"},rotation:{valType:"number",min:-360,max:360,dflt:0,editType:"calc"},pull:{valType:"number",min:0,max:1,dflt:0,arrayOk:!0,editType:"calc"},_deprecated:{title:{valType:"string",dflt:"",editType:"calc"},titlefont:c({},u,{}),titleposition:{valType:"enumerated",values:["top left","top center","top right","middle center","bottom left","bottom center","bottom right"],editType:"calc"}}}},{"../../components/color/attributes":365,"../../lib/extend":493,"../../plots/attributes":550,"../../plots/domain":584,"../../plots/font_attributes":585,"../../plots/template_attributes":633}],902:[function(t,e,r){"use strict";var n=t("../../plots/plots");r.name="pie",r.plot=function(t,e,i,a){n.plotBasePlot(r.name,t,e,i,a)},r.clean=function(t,e,i,a){n.cleanBasePlot(r.name,t,e,i,a)}},{"../../plots/plots":619}],903:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("tinycolor2"),a=t("../../components/color"),o={};function s(t){return function(e,r){return!!e&&(!!(e=i(e)).isValid()&&(e=a.addOpacity(e,e.getAlpha()),t[r]||(t[r]=e),e))}}function l(t,e){var r,n=JSON.stringify(t),a=e[n];if(!a){for(a=t.slice(),r=0;r=0})),("funnelarea"===e.type?v:e.sort)&&a.sort((function(t,e){return e.v-t.v})),a[0]&&(a[0].vTotal=g),a},crossTraceCalc:function(t,e){var r=(e||{}).type;r||(r="pie");var n=t._fullLayout,i=t.calcdata,a=n[r+"colorway"],s=n["_"+r+"colormap"];n["extend"+r+"colors"]&&(a=l(a,o));for(var c=0,u=0;u0){s=!0;break}}s||(o=0)}return{hasLabels:r,hasValues:a,len:o}}e.exports={handleLabelsAndValues:l,supplyDefaults:function(t,e,r,n){function c(r,n){return i.coerce(t,e,a,r,n)}var u=l(c("labels"),c("values")),f=u.len;if(e._hasLabels=u.hasLabels,e._hasValues=u.hasValues,!e._hasLabels&&e._hasValues&&(c("label0"),c("dlabel")),f){e._length=f,c("marker.line.width")&&c("marker.line.color"),c("marker.colors"),c("scalegroup");var h,p=c("text"),d=c("texttemplate");if(d||(h=c("textinfo",Array.isArray(p)?"text+percent":"percent")),c("hovertext"),c("hovertemplate"),d||h&&"none"!==h){var m=c("textposition");s(t,e,n,c,m,{moduleHasSelected:!1,moduleHasUnselected:!1,moduleHasConstrain:!1,moduleHasCliponaxis:!1,moduleHasTextangle:!1,moduleHasInsideanchor:!1}),(Array.isArray(m)||"auto"===m||"outside"===m)&&c("automargin"),("inside"===m||"auto"===m||Array.isArray(m))&&c("insidetextorientation")}o(e,n,c);var g=c("hole");if(c("title.text")){var v=c("title.position",g?"middle center":"top center");g||"middle center"!==v||(e.title.position="top center"),i.coerceFont(c,"title.font",n.font)}c("sort"),c("direction"),c("rotation"),c("pull")}else e.visible=!1}}},{"../../lib":503,"../../plots/domain":584,"../bar/defaults":652,"./attributes":901,"fast-isnumeric":190}],905:[function(t,e,r){"use strict";var n=t("../../components/fx/helpers").appendArrayMultiPointValues;e.exports=function(t,e){var r={curveNumber:e.index,pointNumbers:t.pts,data:e._input,fullData:e,label:t.label,color:t.color,value:t.v,percent:t.percent,text:t.text,bbox:t.bbox,v:t.v};return 1===t.pts.length&&(r.pointNumber=r.i=t.pts[0]),n(r,e,t.pts),"funnelarea"===e.type&&(delete r.v,delete r.i),r}},{"../../components/fx/helpers":402}],906:[function(t,e,r){"use strict";var n=t("../../lib");function i(t){return-1!==t.indexOf("e")?t.replace(/[.]?0+e/,"e"):-1!==t.indexOf(".")?t.replace(/[.]?0+$/,""):t}r.formatPiePercent=function(t,e){var r=i((100*t).toPrecision(3));return n.numSeparate(r,e)+"%"},r.formatPieValue=function(t,e){var r=i(t.toPrecision(10));return n.numSeparate(r,e)},r.getFirstFilled=function(t,e){if(Array.isArray(t))for(var r=0;r"),name:f.hovertemplate||-1!==h.indexOf("name")?f.name:void 0,idealAlign:t.pxmid[0]<0?"left":"right",color:g.castOption(_.bgcolor,t.pts)||t.color,borderColor:g.castOption(_.bordercolor,t.pts),fontFamily:g.castOption(w.family,t.pts),fontSize:g.castOption(w.size,t.pts),fontColor:g.castOption(w.color,t.pts),nameLength:g.castOption(_.namelength,t.pts),textAlign:g.castOption(_.align,t.pts),hovertemplate:g.castOption(f.hovertemplate,t.pts),hovertemplateLabels:t,eventData:[v(t,f)]},{container:r._hoverlayer.node(),outerContainer:r._paper.node(),gd:e,inOut_bbox:T}),t.bbox=T[0],c._hasHoverLabel=!0}c._hasHoverEvent=!0,e.emit("plotly_hover",{points:[v(t,f)],event:n.event})}})),t.on("mouseout",(function(t){var r=e._fullLayout,i=e._fullData[c.index],o=n.select(this).datum();c._hasHoverEvent&&(t.originalEvent=n.event,e.emit("plotly_unhover",{points:[v(o,i)],event:n.event}),c._hasHoverEvent=!1),c._hasHoverLabel&&(a.loneUnhover(r._hoverlayer.node()),c._hasHoverLabel=!1)})),t.on("click",(function(t){var r=e._fullLayout,i=e._fullData[c.index];e._dragging||!1===r.hovermode||(e._hoverdata=[v(t,i)],a.click(e,n.event))}))}function b(t,e,r){var n=g.castOption(t.insidetextfont.color,e.pts);!n&&t._input.textfont&&(n=g.castOption(t._input.textfont.color,e.pts));var i=g.castOption(t.insidetextfont.family,e.pts)||g.castOption(t.textfont.family,e.pts)||r.family,a=g.castOption(t.insidetextfont.size,e.pts)||g.castOption(t.textfont.size,e.pts)||r.size;return{color:n||o.contrast(e.color),family:i,size:a}}function _(t,e){for(var r,n,i=0;ie&&e>n||r=-4;g-=2)v(Math.PI*g,"tan");for(g=4;g>=-4;g-=2)v(Math.PI*(g+1),"tan")}if(f||p){for(g=4;g>=-4;g-=2)v(Math.PI*(g+1.5),"rad");for(g=4;g>=-4;g-=2)v(Math.PI*(g+.5),"rad")}}if(s||d||f){var y=Math.sqrt(t.width*t.width+t.height*t.height);if((a={scale:i*n*2/y,rCenter:1-i,rotate:0}).textPosAngle=(e.startangle+e.stopangle)/2,a.scale>=1)return a;m.push(a)}(d||p)&&((a=T(t,n,o,l,c)).textPosAngle=(e.startangle+e.stopangle)/2,m.push(a)),(d||h)&&((a=k(t,n,o,l,c)).textPosAngle=(e.startangle+e.stopangle)/2,m.push(a));for(var x=0,b=0,_=0;_=1)break}return m[x]}function T(t,e,r,n,i){e=Math.max(0,e-2*m);var a=t.width/t.height,o=S(a,n,e,r);return{scale:2*o/t.height,rCenter:A(a,o/e),rotate:M(i)}}function k(t,e,r,n,i){e=Math.max(0,e-2*m);var a=t.height/t.width,o=S(a,n,e,r);return{scale:2*o/t.width,rCenter:A(a,o/e),rotate:M(i+Math.PI/2)}}function A(t,e){return Math.cos(e)-t*e}function M(t){return(180/Math.PI*t+720)%180-90}function S(t,e,r,n){var i=t+1/(2*Math.tan(e));return r*Math.min(1/(Math.sqrt(i*i+.5)+i),n/(Math.sqrt(t*t+n/2)+t))}function E(t,e){return t.v!==e.vTotal||e.trace.hole?Math.min(1/(1+1/Math.sin(t.halfangle)),t.ring/2):1}function L(t,e){var r=e.pxmid[0],n=e.pxmid[1],i=t.width/2,a=t.height/2;return r<0&&(i*=-1),n<0&&(a*=-1),{scale:1,rCenter:1,rotate:0,x:i+Math.abs(a)*(i>0?1:-1)/2,y:a/(1+r*r/(n*n)),outside:!0}}function C(t,e){var r,n,i,a=t.trace,o={x:t.cx,y:t.cy},s={tx:0,ty:0};s.ty+=a.title.font.size,i=I(a),-1!==a.title.position.indexOf("top")?(o.y-=(1+i)*t.r,s.ty-=t.titleBox.height):-1!==a.title.position.indexOf("bottom")&&(o.y+=(1+i)*t.r);var l,c,u=(l=t.r,c=t.trace.aspectratio,l/(void 0===c?1:c)),f=e.w*(a.domain.x[1]-a.domain.x[0])/2;return-1!==a.title.position.indexOf("left")?(f+=u,o.x-=(1+i)*u,s.tx+=t.titleBox.width/2):-1!==a.title.position.indexOf("center")?f*=2:-1!==a.title.position.indexOf("right")&&(f+=u,o.x+=(1+i)*u,s.tx-=t.titleBox.width/2),r=f/t.titleBox.width,n=P(t,e)/t.titleBox.height,{x:o.x,y:o.y,scale:Math.min(r,n),tx:s.tx,ty:s.ty}}function P(t,e){var r=t.trace,n=e.h*(r.domain.y[1]-r.domain.y[0]);return Math.min(t.titleBox.height,n/2)}function I(t){var e,r=t.pull;if(!r)return 0;if(Array.isArray(r))for(r=0,e=0;er&&(r=t.pull[e]);return r}function O(t,e){for(var r=[],n=0;n1?(c=r.r,u=c/i.aspectratio):(u=r.r,c=u*i.aspectratio),c*=(1+i.baseratio)/2,l=c*u}o=Math.min(o,l/r.vTotal)}for(n=0;n")}if(a){var x=l.castOption(i,e.i,"texttemplate");if(x){var b=function(t){return{label:t.label,value:t.v,valueLabel:g.formatPieValue(t.v,n.separators),percent:t.v/r.vTotal,percentLabel:g.formatPiePercent(t.v/r.vTotal,n.separators),color:t.color,text:t.text,customdata:l.castOption(i,t.i,"customdata")}}(e),_=g.getFirstFilled(i.text,e.pts);(y(_)||""===_)&&(b.text=_),e.text=l.texttemplateString(x,b,t._fullLayout._d3locale,b,i._meta||{})}else e.text=""}}function R(t,e){var r=t.rotate*Math.PI/180,n=Math.cos(r),i=Math.sin(r),a=(e.left+e.right)/2,o=(e.top+e.bottom)/2;t.textX=a*n-o*i,t.textY=a*i+o*n,t.noCenter=!0}e.exports={plot:function(t,e){var r=t._fullLayout,a=r._size;d("pie",r),_(e,t),O(e,a);var h=l.makeTraceGroups(r._pielayer,e,"trace").each((function(e){var h=n.select(this),d=e[0],m=d.trace;!function(t){var e,r,n,i=t[0],a=i.r,o=i.trace,s=g.getRotationAngle(o.rotation),l=2*Math.PI/i.vTotal,c="px0",u="px1";if("counterclockwise"===o.direction){for(e=0;ei.vTotal/2?1:0,r.halfangle=Math.PI*Math.min(r.v/i.vTotal,.5),r.ring=1-o.hole,r.rInscribed=E(r,i))}(e),h.attr("stroke-linejoin","round"),h.each((function(){var v=n.select(this).selectAll("g.slice").data(e);v.enter().append("g").classed("slice",!0),v.exit().remove();var y=[[[],[]],[[],[]]],_=!1;v.each((function(i,a){if(i.hidden)n.select(this).selectAll("path,g").remove();else{i.pointNumber=i.i,i.curveNumber=m.index,y[i.pxmid[1]<0?0:1][i.pxmid[0]<0?0:1].push(i);var o=d.cx,c=d.cy,u=n.select(this),h=u.selectAll("path.surface").data([i]);if(h.enter().append("path").classed("surface",!0).style({"pointer-events":"all"}),u.call(x,t,e),m.pull){var v=+g.castOption(m.pull,i.pts)||0;v>0&&(o+=v*i.pxmid[0],c+=v*i.pxmid[1])}i.cxFinal=o,i.cyFinal=c;var T=m.hole;if(i.v===d.vTotal){var k="M"+(o+i.px0[0])+","+(c+i.px0[1])+C(i.px0,i.pxmid,!0,1)+C(i.pxmid,i.px0,!0,1)+"Z";T?h.attr("d","M"+(o+T*i.px0[0])+","+(c+T*i.px0[1])+C(i.px0,i.pxmid,!1,T)+C(i.pxmid,i.px0,!1,T)+"Z"+k):h.attr("d",k)}else{var A=C(i.px0,i.px1,!0,1);if(T){var M=1-T;h.attr("d","M"+(o+T*i.px1[0])+","+(c+T*i.px1[1])+C(i.px1,i.px0,!1,T)+"l"+M*i.px0[0]+","+M*i.px0[1]+A+"Z")}else h.attr("d","M"+o+","+c+"l"+i.px0[0]+","+i.px0[1]+A+"Z")}D(t,i,d);var S=g.castOption(m.textposition,i.pts),E=u.selectAll("g.slicetext").data(i.text&&"none"!==S?[0]:[]);E.enter().append("g").classed("slicetext",!0),E.exit().remove(),E.each((function(){var u=l.ensureSingle(n.select(this),"text","",(function(t){t.attr("data-notex",1)})),h=l.ensureUniformFontSize(t,"outside"===S?function(t,e,r){var n=g.castOption(t.outsidetextfont.color,e.pts)||g.castOption(t.textfont.color,e.pts)||r.color,i=g.castOption(t.outsidetextfont.family,e.pts)||g.castOption(t.textfont.family,e.pts)||r.family,a=g.castOption(t.outsidetextfont.size,e.pts)||g.castOption(t.textfont.size,e.pts)||r.size;return{color:n,family:i,size:a}}(m,i,r.font):b(m,i,r.font));u.text(i.text).attr({class:"slicetext",transform:"","text-anchor":"middle"}).call(s.font,h).call(f.convertToTspans,t);var v,y=s.bBox(u.node());if("outside"===S)v=L(y,i);else if(v=w(y,i,d),"auto"===S&&v.scale<1){var x=l.ensureUniformFontSize(t,m.outsidetextfont);u.call(s.font,x),v=L(y=s.bBox(u.node()),i)}var T=v.textPosAngle,k=void 0===T?i.pxmid:z(d.r,T);if(v.targetX=o+k[0]*v.rCenter+(v.x||0),v.targetY=c+k[1]*v.rCenter+(v.y||0),R(v,y),v.outside){var A=v.targetY;i.yLabelMin=A-y.height/2,i.yLabelMid=A,i.yLabelMax=A+y.height/2,i.labelExtraX=0,i.labelExtraY=0,_=!0}v.fontSize=h.size,p(m.type,v,r),e[a].transform=v,u.attr("transform",l.getTextTransform(v))}))}function C(t,e,r,n){var a=n*(e[0]-t[0]),o=n*(e[1]-t[1]);return"a"+n*d.r+","+n*d.r+" 0 "+i.largeArc+(r?" 1 ":" 0 ")+a+","+o}}));var T=n.select(this).selectAll("g.titletext").data(m.title.text?[0]:[]);if(T.enter().append("g").classed("titletext",!0),T.exit().remove(),T.each((function(){var e,r=l.ensureSingle(n.select(this),"text","",(function(t){t.attr("data-notex",1)})),i=m.title.text;m._meta&&(i=l.templateString(i,m._meta)),r.text(i).attr({class:"titletext",transform:"","text-anchor":"middle"}).call(s.font,m.title.font).call(f.convertToTspans,t),e="middle center"===m.title.position?function(t){var e=Math.sqrt(t.titleBox.width*t.titleBox.width+t.titleBox.height*t.titleBox.height);return{x:t.cx,y:t.cy,scale:t.trace.hole*t.r*2/e,tx:0,ty:-t.titleBox.height/2+t.trace.title.font.size}}(d):C(d,a),r.attr("transform",u(e.x,e.y)+c(Math.min(1,e.scale))+u(e.tx,e.ty))})),_&&function(t,e){var r,n,i,a,o,s,l,c,u,f,h,p,d;function m(t,e){return t.pxmid[1]-e.pxmid[1]}function v(t,e){return e.pxmid[1]-t.pxmid[1]}function y(t,r){r||(r={});var i,c,u,h,p=r.labelExtraY+(n?r.yLabelMax:r.yLabelMin),d=n?t.yLabelMin:t.yLabelMax,m=n?t.yLabelMax:t.yLabelMin,v=t.cyFinal+o(t.px0[1],t.px1[1]),y=p-d;if(y*l>0&&(t.labelExtraY=y),Array.isArray(e.pull))for(c=0;c=(g.castOption(e.pull,u.pts)||0)||((t.pxmid[1]-u.pxmid[1])*l>0?(y=u.cyFinal+o(u.px0[1],u.px1[1])-d-t.labelExtraY)*l>0&&(t.labelExtraY+=y):(m+t.labelExtraY-v)*l>0&&(i=3*s*Math.abs(c-f.indexOf(t)),(h=u.cxFinal+a(u.px0[0],u.px1[0])+i-(t.cxFinal+t.pxmid[0])-t.labelExtraX)*s>0&&(t.labelExtraX+=h)))}for(n=0;n<2;n++)for(i=n?m:v,o=n?Math.max:Math.min,l=n?1:-1,r=0;r<2;r++){for(a=r?Math.max:Math.min,s=r?1:-1,(c=t[n][r]).sort(i),u=t[1-n][r],f=u.concat(c),p=[],h=0;hMath.abs(f)?s+="l"+f*t.pxmid[0]/t.pxmid[1]+","+f+"H"+(a+t.labelExtraX+c):s+="l"+t.labelExtraX+","+u+"v"+(f-u)+"h"+c}else s+="V"+(t.yLabelMid+t.labelExtraY)+"h"+c;l.ensureSingle(r,"path","textline").call(o.stroke,e.outsidetextfont.color).attr({"stroke-width":Math.min(2,e.outsidetextfont.size/8),d:s,fill:"none"})}else r.select("path.textline").remove()}))}(v,m),_&&m.automargin){var k=s.bBox(h.node()),A=m.domain,M=a.w*(A.x[1]-A.x[0]),S=a.h*(A.y[1]-A.y[0]),E=(.5*M-d.r)/a.w,P=(.5*S-d.r)/a.h;i.autoMargin(t,"pie."+m.uid+".automargin",{xl:A.x[0]-E,xr:A.x[1]+E,yb:A.y[0]-P,yt:A.y[1]+P,l:Math.max(d.cx-d.r-k.left,0),r:Math.max(k.right-(d.cx+d.r),0),b:Math.max(k.bottom-(d.cy+d.r),0),t:Math.max(d.cy-d.r-k.top,0),pad:5})}}))}));setTimeout((function(){h.selectAll("tspan").each((function(){var t=n.select(this);t.attr("dy")&&t.attr("dy",t.attr("dy"))}))}),0)},formatSliceLabel:D,transformInsideText:w,determineInsideTextFont:b,positionTitleOutside:C,prerenderTitles:_,layoutAreas:O,attachFxHandlers:x,computeTransform:R}},{"../../components/color":366,"../../components/drawing":388,"../../components/fx":406,"../../lib":503,"../../lib/svg_text_utils":529,"../../plots/plots":619,"../bar/constants":650,"../bar/uniform_text":664,"./event_data":905,"./helpers":906,"@plotly/d3":58}],911:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("./style_one"),a=t("../bar/uniform_text").resizeText;e.exports=function(t){var e=t._fullLayout._pielayer.selectAll(".trace");a(t,e,"pie"),e.each((function(t){var e=t[0].trace,r=n.select(this);r.style({opacity:e.opacity}),r.selectAll("path.surface").each((function(t){n.select(this).call(i,t,e)}))}))}},{"../bar/uniform_text":664,"./style_one":912,"@plotly/d3":58}],912:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("./helpers").castOption;e.exports=function(t,e,r){var a=r.marker.line,o=i(a.color,e.pts)||n.defaultLine,s=i(a.width,e.pts)||0;t.style("stroke-width",s).call(n.fill,e.color).call(n.stroke,o)}},{"../../components/color":366,"./helpers":906}],913:[function(t,e,r){"use strict";var n=t("../scatter/attributes");e.exports={x:n.x,y:n.y,xy:{valType:"data_array",editType:"calc"},indices:{valType:"data_array",editType:"calc"},xbounds:{valType:"data_array",editType:"calc"},ybounds:{valType:"data_array",editType:"calc"},text:n.text,marker:{color:{valType:"color",arrayOk:!1,editType:"calc"},opacity:{valType:"number",min:0,max:1,dflt:1,arrayOk:!1,editType:"calc"},blend:{valType:"boolean",dflt:null,editType:"calc"},sizemin:{valType:"number",min:.1,max:2,dflt:.5,editType:"calc"},sizemax:{valType:"number",min:.1,dflt:20,editType:"calc"},border:{color:{valType:"color",arrayOk:!1,editType:"calc"},arearatio:{valType:"number",min:0,max:1,dflt:0,editType:"calc"},editType:"calc"},editType:"calc"},transforms:void 0}},{"../scatter/attributes":927}],914:[function(t,e,r){"use strict";var n=t("../../../stackgl_modules").gl_pointcloud2d,i=t("../../lib/str2rgbarray"),a=t("../../plots/cartesian/autorange").findExtremes,o=t("../scatter/get_trace_color");function s(t,e){this.scene=t,this.uid=e,this.type="pointcloud",this.pickXData=[],this.pickYData=[],this.xData=[],this.yData=[],this.textLabels=[],this.color="rgb(0, 0, 0)",this.name="",this.hoverinfo="all",this.idToIndex=new Int32Array(0),this.bounds=[0,0,0,0],this.pointcloudOptions={positions:new Float32Array(0),idToIndex:this.idToIndex,sizemin:.5,sizemax:12,color:[0,0,0,1],areaRatio:1,borderColor:[0,0,0,1]},this.pointcloud=n(t.glplot,this.pointcloudOptions),this.pointcloud._trace=this}var l=s.prototype;l.handlePick=function(t){var e=this.idToIndex[t.pointId];return{trace:this,dataCoord:t.dataCoord,traceCoord:this.pickXYData?[this.pickXYData[2*e],this.pickXYData[2*e+1]]:[this.pickXData[e],this.pickYData[e]],textLabel:Array.isArray(this.textLabels)?this.textLabels[e]:this.textLabels,color:this.color,name:this.name,pointIndex:e,hoverinfo:this.hoverinfo}},l.update=function(t){this.index=t.index,this.textLabels=t.text,this.name=t.name,this.hoverinfo=t.hoverinfo,this.bounds=[1/0,1/0,-1/0,-1/0],this.updateFast(t),this.color=o(t,{})},l.updateFast=function(t){var e,r,n,o,s,l,c=this.xData=this.pickXData=t.x,u=this.yData=this.pickYData=t.y,f=this.pickXYData=t.xy,h=t.xbounds&&t.ybounds,p=t.indices,d=this.bounds;if(f){if(n=f,e=f.length>>>1,h)d[0]=t.xbounds[0],d[2]=t.xbounds[1],d[1]=t.ybounds[0],d[3]=t.ybounds[1];else for(l=0;ld[2]&&(d[2]=o),sd[3]&&(d[3]=s);if(p)r=p;else for(r=new Int32Array(e),l=0;ld[2]&&(d[2]=o),sd[3]&&(d[3]=s);this.idToIndex=r,this.pointcloudOptions.idToIndex=r,this.pointcloudOptions.positions=n;var m=i(t.marker.color),g=i(t.marker.border.color),v=t.opacity*t.marker.opacity;m[3]*=v,this.pointcloudOptions.color=m;var y=t.marker.blend;if(null===y){y=c.length<100||u.length<100}this.pointcloudOptions.blend=y,g[3]*=v,this.pointcloudOptions.borderColor=g;var x=t.marker.sizemin,b=Math.max(t.marker.sizemax,t.marker.sizemin);this.pointcloudOptions.sizeMin=x,this.pointcloudOptions.sizeMax=b,this.pointcloudOptions.areaRatio=t.marker.border.arearatio,this.pointcloud.update(this.pointcloudOptions);var _=this.scene.xaxis,w=this.scene.yaxis,T=b/2||.5;t._extremes[_._id]=a(_,[d[0],d[2]],{ppad:T}),t._extremes[w._id]=a(w,[d[1],d[3]],{ppad:T})},l.dispose=function(){this.pointcloud.dispose()},e.exports=function(t,e){var r=new s(t,e.uid);return r.update(e),r}},{"../../../stackgl_modules":1124,"../../lib/str2rgbarray":528,"../../plots/cartesian/autorange":553,"../scatter/get_trace_color":937}],915:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes");e.exports=function(t,e,r){function a(r,a){return n.coerce(t,e,i,r,a)}a("x"),a("y"),a("xbounds"),a("ybounds"),t.xy&&t.xy instanceof Float32Array&&(e.xy=t.xy),t.indices&&t.indices instanceof Int32Array&&(e.indices=t.indices),a("text"),a("marker.color",r),a("marker.opacity"),a("marker.blend"),a("marker.sizemin"),a("marker.sizemax"),a("marker.border.color",r),a("marker.border.arearatio"),e._length=null}},{"../../lib":503,"./attributes":913}],916:[function(t,e,r){"use strict";["*pointcloud* trace is deprecated!","Please consider switching to the *scattergl* trace type."].join(" ");e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("../scatter3d/calc"),plot:t("./convert"),moduleType:"trace",name:"pointcloud",basePlotModule:t("../../plots/gl2d"),categories:["gl","gl2d","showLegend"],meta:{}}},{"../../plots/gl2d":596,"../scatter3d/calc":956,"./attributes":913,"./convert":914,"./defaults":915}],917:[function(t,e,r){"use strict";var n=t("../../plots/font_attributes"),i=t("../../plots/attributes"),a=t("../../components/color/attributes"),o=t("../../components/fx/attributes"),s=t("../../plots/domain").attributes,l=t("../../plots/template_attributes").hovertemplateAttrs,c=t("../../components/colorscale/attributes"),u=t("../../plot_api/plot_template").templatedArray,f=t("../../plots/cartesian/axis_format_attributes").descriptionOnlyNumbers,h=t("../../lib/extend").extendFlat,p=t("../../plot_api/edit_types").overrideAll;(e.exports=p({hoverinfo:h({},i.hoverinfo,{flags:[],arrayOk:!1}),hoverlabel:o.hoverlabel,domain:s({name:"sankey",trace:!0}),orientation:{valType:"enumerated",values:["v","h"],dflt:"h"},valueformat:{valType:"string",dflt:".3s",description:f("value")},valuesuffix:{valType:"string",dflt:""},arrangement:{valType:"enumerated",values:["snap","perpendicular","freeform","fixed"],dflt:"snap"},textfont:n({}),customdata:void 0,node:{label:{valType:"data_array",dflt:[]},groups:{valType:"info_array",impliedEdits:{x:[],y:[]},dimensions:2,freeLength:!0,dflt:[],items:{valType:"number",editType:"calc"}},x:{valType:"data_array",dflt:[]},y:{valType:"data_array",dflt:[]},color:{valType:"color",arrayOk:!0},customdata:{valType:"data_array",editType:"calc"},line:{color:{valType:"color",dflt:a.defaultLine,arrayOk:!0},width:{valType:"number",min:0,dflt:.5,arrayOk:!0}},pad:{valType:"number",arrayOk:!1,min:0,dflt:20},thickness:{valType:"number",arrayOk:!1,min:1,dflt:20},hoverinfo:{valType:"enumerated",values:["all","none","skip"],dflt:"all"},hoverlabel:o.hoverlabel,hovertemplate:l({},{keys:["value","label"]})},link:{label:{valType:"data_array",dflt:[]},color:{valType:"color",arrayOk:!0},customdata:{valType:"data_array",editType:"calc"},line:{color:{valType:"color",dflt:a.defaultLine,arrayOk:!0},width:{valType:"number",min:0,dflt:0,arrayOk:!0}},source:{valType:"data_array",dflt:[]},target:{valType:"data_array",dflt:[]},value:{valType:"data_array",dflt:[]},hoverinfo:{valType:"enumerated",values:["all","none","skip"],dflt:"all"},hoverlabel:o.hoverlabel,hovertemplate:l({},{keys:["value","label"]}),colorscales:u("concentrationscales",{editType:"calc",label:{valType:"string",editType:"calc",dflt:""},cmax:{valType:"number",editType:"calc",dflt:1},cmin:{valType:"number",editType:"calc",dflt:0},colorscale:h(c().colorscale,{dflt:[[0,"white"],[1,"black"]]})})}},"calc","nested")).transforms=void 0},{"../../components/color/attributes":365,"../../components/colorscale/attributes":373,"../../components/fx/attributes":397,"../../lib/extend":493,"../../plot_api/edit_types":536,"../../plot_api/plot_template":543,"../../plots/attributes":550,"../../plots/cartesian/axis_format_attributes":557,"../../plots/domain":584,"../../plots/font_attributes":585,"../../plots/template_attributes":633}],918:[function(t,e,r){"use strict";var n=t("../../plot_api/edit_types").overrideAll,i=t("../../plots/get_data").getModuleCalcData,a=t("./plot"),o=t("../../components/fx/layout_attributes"),s=t("../../lib/setcursor"),l=t("../../components/dragelement"),c=t("../../plots/cartesian/select").prepSelect,u=t("../../lib"),f=t("../../registry");function h(t,e){var r=t._fullData[e],n=t._fullLayout,i=n.dragmode,a="pan"===n.dragmode?"move":"crosshair",o=r._bgRect;if("pan"!==i&&"zoom"!==i){s(o,a);var h={_id:"x",c2p:u.identity,_offset:r._sankey.translateX,_length:r._sankey.width},p={_id:"y",c2p:u.identity,_offset:r._sankey.translateY,_length:r._sankey.height},d={gd:t,element:o.node(),plotinfo:{id:e,xaxis:h,yaxis:p,fillRangeItems:u.noop},subplot:e,xaxes:[h],yaxes:[p],doneFnCompleted:function(r){var n,i=t._fullData[e],a=i.node.groups.slice(),o=[];function s(t){for(var e=i._sankey.graph.nodes,r=0;ry&&(y=a.source[e]),a.target[e]>y&&(y=a.target[e]);var x,b=y+1;t.node._count=b;var _=t.node.groups,w={};for(e=0;e<_.length;e++){var T=_[e];for(x=0;x0&&s(E,b)&&s(L,b)&&(!w.hasOwnProperty(E)||!w.hasOwnProperty(L)||w[E]!==w[L])){w.hasOwnProperty(L)&&(L=w[L]),w.hasOwnProperty(E)&&(E=w[E]),L=+L,h[E=+E]=h[L]=!0;var C="";a.label&&a.label[e]&&(C=a.label[e]);var P=null;C&&p.hasOwnProperty(C)&&(P=p[C]),c.push({pointNumber:e,label:C,color:u?a.color[e]:a.color,customdata:f?a.customdata[e]:a.customdata,concentrationscale:P,source:E,target:L,value:+S}),M.source.push(E),M.target.push(L)}}var I=b+_.length,O=o(r.color),z=o(r.customdata),D=[];for(e=0;eb-1,childrenNodes:[],pointNumber:e,label:R,color:O?r.color[e]:r.color,customdata:z?r.customdata[e]:r.customdata})}var F=!1;return function(t,e,r){for(var a=i.init2dArray(t,0),o=0;o1}))}(I,M.source,M.target)&&(F=!0),{circular:F,links:c,nodes:D,groups:_,groupLookup:w}}e.exports=function(t,e){var r=c(e);return a({circular:r.circular,_nodes:r.nodes,_links:r.links,_groups:r.groups,_groupLookup:r.groupLookup})}},{"../../components/colorscale":378,"../../lib":503,"../../lib/gup":500,"strongly-connected-components":306}],920:[function(t,e,r){"use strict";e.exports={nodeTextOffsetHorizontal:4,nodeTextOffsetVertical:3,nodePadAcross:10,sankeyIterations:50,forceIterations:5,forceTicksPerFrame:10,duration:500,ease:"linear",cn:{sankey:"sankey",sankeyLinks:"sankey-links",sankeyLink:"sankey-link",sankeyNodeSet:"sankey-node-set",sankeyNode:"sankey-node",nodeRect:"node-rect",nodeLabel:"node-label"}}},{}],921:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes"),a=t("../../components/color"),o=t("tinycolor2"),s=t("../../plots/domain").defaults,l=t("../../components/fx/hoverlabel_defaults"),c=t("../../plot_api/plot_template"),u=t("../../plots/array_container_defaults");function f(t,e){function r(r,a){return n.coerce(t,e,i.link.colorscales,r,a)}r("label"),r("cmin"),r("cmax"),r("colorscale")}e.exports=function(t,e,r,h){function p(r,a){return n.coerce(t,e,i,r,a)}var d=n.extendDeep(h.hoverlabel,t.hoverlabel),m=t.node,g=c.newContainer(e,"node");function v(t,e){return n.coerce(m,g,i.node,t,e)}v("label"),v("groups"),v("x"),v("y"),v("pad"),v("thickness"),v("line.color"),v("line.width"),v("hoverinfo",t.hoverinfo),l(m,g,v,d),v("hovertemplate");var y=h.colorway;v("color",g.label.map((function(t,e){return a.addOpacity(function(t){return y[t%y.length]}(e),.8)}))),v("customdata");var x=t.link||{},b=c.newContainer(e,"link");function _(t,e){return n.coerce(x,b,i.link,t,e)}_("label"),_("source"),_("target"),_("value"),_("line.color"),_("line.width"),_("hoverinfo",t.hoverinfo),l(x,b,_,d),_("hovertemplate");var w,T=o(h.paper_bgcolor).getLuminance()<.333?"rgba(255, 255, 255, 0.6)":"rgba(0, 0, 0, 0.2)";_("color",n.repeat(T,b.value.length)),_("customdata"),u(x,b,{name:"colorscales",handleItemDefaults:f}),s(e,h,p),p("orientation"),p("valueformat"),p("valuesuffix"),g.x.length&&g.y.length&&(w="freeform"),p("arrangement",w),n.coerceFont(p,"textfont",n.extendFlat({},h.font)),e._length=null}},{"../../components/color":366,"../../components/fx/hoverlabel_defaults":404,"../../lib":503,"../../plot_api/plot_template":543,"../../plots/array_container_defaults":549,"../../plots/domain":584,"./attributes":917,tinycolor2:312}],922:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),calc:t("./calc"),plot:t("./plot"),moduleType:"trace",name:"sankey",basePlotModule:t("./base_plot"),selectPoints:t("./select.js"),categories:["noOpacity"],meta:{}}},{"./attributes":917,"./base_plot":918,"./calc":919,"./defaults":921,"./plot":923,"./select.js":925}],923:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=i.numberFormat,o=t("./render"),s=t("../../components/fx"),l=t("../../components/color"),c=t("./constants").cn,u=i._;function f(t){return""!==t}function h(t,e){return t.filter((function(t){return t.key===e.traceId}))}function p(t,e){n.select(t).select("path").style("fill-opacity",e),n.select(t).select("rect").style("fill-opacity",e)}function d(t){n.select(t).select("text.name").style("fill","black")}function m(t){return function(e){return-1!==t.node.sourceLinks.indexOf(e.link)||-1!==t.node.targetLinks.indexOf(e.link)}}function g(t){return function(e){return-1!==e.node.sourceLinks.indexOf(t.link)||-1!==e.node.targetLinks.indexOf(t.link)}}function v(t,e,r){e&&r&&h(r,e).selectAll("."+c.sankeyLink).filter(m(e)).call(x.bind(0,e,r,!1))}function y(t,e,r){e&&r&&h(r,e).selectAll("."+c.sankeyLink).filter(m(e)).call(b.bind(0,e,r,!1))}function x(t,e,r,n){var i=n.datum().link.label;n.style("fill-opacity",(function(t){if(!t.link.concentrationscale)return.4})),i&&h(e,t).selectAll("."+c.sankeyLink).filter((function(t){return t.link.label===i})).style("fill-opacity",(function(t){if(!t.link.concentrationscale)return.4})),r&&h(e,t).selectAll("."+c.sankeyNode).filter(g(t)).call(v)}function b(t,e,r,n){var i=n.datum().link.label;n.style("fill-opacity",(function(t){return t.tinyColorAlpha})),i&&h(e,t).selectAll("."+c.sankeyLink).filter((function(t){return t.link.label===i})).style("fill-opacity",(function(t){return t.tinyColorAlpha})),r&&h(e,t).selectAll(c.sankeyNode).filter(g(t)).call(y)}function _(t,e){var r=t.hoverlabel||{},n=i.nestedProperty(r,e).get();return!Array.isArray(n)&&n}e.exports=function(t,e){for(var r=t._fullLayout,i=r._paper,h=r._size,m=0;m"),color:_(o,"bgcolor")||l.addOpacity(m.color,1),borderColor:_(o,"bordercolor"),fontFamily:_(o,"font.family"),fontSize:_(o,"font.size"),fontColor:_(o,"font.color"),nameLength:_(o,"namelength"),textAlign:_(o,"align"),idealAlign:n.event.x"),color:_(o,"bgcolor")||i.tinyColorHue,borderColor:_(o,"bordercolor"),fontFamily:_(o,"font.family"),fontSize:_(o,"font.size"),fontColor:_(o,"font.color"),nameLength:_(o,"namelength"),textAlign:_(o,"align"),idealAlign:"left",hovertemplate:o.hovertemplate,hovertemplateLabels:y,eventData:[i.node]},{container:r._hoverlayer.node(),outerContainer:r._paper.node(),gd:t});p(w,.85),d(w)}}},unhover:function(e,i,a){!1!==t._fullLayout.hovermode&&(n.select(e).call(y,i,a),"skip"!==i.node.trace.node.hoverinfo&&(i.node.fullData=i.node.trace,t.emit("plotly_unhover",{event:n.event,points:[i.node]})),s.loneUnhover(r._hoverlayer.node()))},select:function(e,r,i){var a=r.node;a.originalEvent=n.event,t._hoverdata=[a],n.select(e).call(y,r,i),s.click(t,{target:!0})}}})}},{"../../components/color":366,"../../components/fx":406,"../../lib":503,"./constants":920,"./render":924,"@plotly/d3":58}],924:[function(t,e,r){"use strict";var n=t("d3-force"),i=t("d3-interpolate").interpolateNumber,a=t("@plotly/d3"),o=t("@plotly/d3-sankey"),s=t("@plotly/d3-sankey-circular"),l=t("./constants"),c=t("tinycolor2"),u=t("../../components/color"),f=t("../../components/drawing"),h=t("../../lib"),p=h.strTranslate,d=h.strRotate,m=t("../../lib/gup"),g=m.keyFun,v=m.repeat,y=m.unwrap,x=t("../../lib/svg_text_utils"),b=t("../../registry"),_=t("../../constants/alignment"),w=_.CAP_SHIFT,T=_.LINE_SPACING;function k(t,e,r){var n,i=y(e),a=i.trace,u=a.domain,f="h"===a.orientation,p=a.node.pad,d=a.node.thickness,m=t.width*(u.x[1]-u.x[0]),g=t.height*(u.y[1]-u.y[0]),v=i._nodes,x=i._links,b=i.circular;(n=b?s.sankeyCircular().circularLinkGap(0):o.sankey()).iterations(l.sankeyIterations).size(f?[m,g]:[g,m]).nodeWidth(d).nodePadding(p).nodeId((function(t){return t.pointNumber})).nodes(v).links(x);var _,w,T,k=n();for(var A in n.nodePadding()=i||(r=i-e.y0)>1e-6&&(e.y0+=r,e.y1+=r),i=e.y1+p}))}(function(t){var e,r,n=t.map((function(t,e){return{x0:t.x0,index:e}})).sort((function(t,e){return t.x0-e.x0})),i=[],a=-1,o=-1/0;for(_=0;_o+d&&(a+=1,e=s.x0),o=s.x0,i[a]||(i[a]=[]),i[a].push(s),r=e-s.x0,s.x0+=r,s.x1+=r}return i}(v=k.nodes));n.update(k)}return{circular:b,key:r,trace:a,guid:h.randstr(),horizontal:f,width:m,height:g,nodePad:a.node.pad,nodeLineColor:a.node.line.color,nodeLineWidth:a.node.line.width,linkLineColor:a.link.line.color,linkLineWidth:a.link.line.width,valueFormat:a.valueformat,valueSuffix:a.valuesuffix,textFont:a.textfont,translateX:u.x[0]*t.width+t.margin.l,translateY:t.height-u.y[1]*t.height+t.margin.t,dragParallel:f?g:m,dragPerpendicular:f?m:g,arrangement:a.arrangement,sankey:n,graph:k,forceLayouts:{},interactionState:{dragInProgress:!1,hovered:!1}}}function A(t,e,r){var n=c(e.color),i=e.source.label+"|"+e.target.label+"__"+r;return e.trace=t.trace,e.curveNumber=t.trace.index,{circular:t.circular,key:i,traceId:t.key,pointNumber:e.pointNumber,link:e,tinyColorHue:u.tinyRGB(n),tinyColorAlpha:n.getAlpha(),linkPath:M,linkLineColor:t.linkLineColor,linkLineWidth:t.linkLineWidth,valueFormat:t.valueFormat,valueSuffix:t.valueSuffix,sankey:t.sankey,parent:t,interactionState:t.interactionState,flow:e.flow}}function M(){return function(t){if(t.link.circular)return e=t.link,r=e.width/2,n=e.circularPathData,"top"===e.circularLinkType?"M "+n.targetX+" "+(n.targetY+r)+" L"+n.rightInnerExtent+" "+(n.targetY+r)+"A"+(n.rightLargeArcRadius+r)+" "+(n.rightSmallArcRadius+r)+" 0 0 1 "+(n.rightFullExtent-r)+" "+(n.targetY-n.rightSmallArcRadius)+"L"+(n.rightFullExtent-r)+" "+n.verticalRightInnerExtent+"A"+(n.rightLargeArcRadius+r)+" "+(n.rightLargeArcRadius+r)+" 0 0 1 "+n.rightInnerExtent+" "+(n.verticalFullExtent-r)+"L"+n.leftInnerExtent+" "+(n.verticalFullExtent-r)+"A"+(n.leftLargeArcRadius+r)+" "+(n.leftLargeArcRadius+r)+" 0 0 1 "+(n.leftFullExtent+r)+" "+n.verticalLeftInnerExtent+"L"+(n.leftFullExtent+r)+" "+(n.sourceY-n.leftSmallArcRadius)+"A"+(n.leftLargeArcRadius+r)+" "+(n.leftSmallArcRadius+r)+" 0 0 1 "+n.leftInnerExtent+" "+(n.sourceY+r)+"L"+n.sourceX+" "+(n.sourceY+r)+"L"+n.sourceX+" "+(n.sourceY-r)+"L"+n.leftInnerExtent+" "+(n.sourceY-r)+"A"+(n.leftLargeArcRadius-r)+" "+(n.leftSmallArcRadius-r)+" 0 0 0 "+(n.leftFullExtent-r)+" "+(n.sourceY-n.leftSmallArcRadius)+"L"+(n.leftFullExtent-r)+" "+n.verticalLeftInnerExtent+"A"+(n.leftLargeArcRadius-r)+" "+(n.leftLargeArcRadius-r)+" 0 0 0 "+n.leftInnerExtent+" "+(n.verticalFullExtent+r)+"L"+n.rightInnerExtent+" "+(n.verticalFullExtent+r)+"A"+(n.rightLargeArcRadius-r)+" "+(n.rightLargeArcRadius-r)+" 0 0 0 "+(n.rightFullExtent+r)+" "+n.verticalRightInnerExtent+"L"+(n.rightFullExtent+r)+" "+(n.targetY-n.rightSmallArcRadius)+"A"+(n.rightLargeArcRadius-r)+" "+(n.rightSmallArcRadius-r)+" 0 0 0 "+n.rightInnerExtent+" "+(n.targetY-r)+"L"+n.targetX+" "+(n.targetY-r)+"Z":"M "+n.targetX+" "+(n.targetY-r)+" L"+n.rightInnerExtent+" "+(n.targetY-r)+"A"+(n.rightLargeArcRadius+r)+" "+(n.rightSmallArcRadius+r)+" 0 0 0 "+(n.rightFullExtent-r)+" "+(n.targetY+n.rightSmallArcRadius)+"L"+(n.rightFullExtent-r)+" "+n.verticalRightInnerExtent+"A"+(n.rightLargeArcRadius+r)+" "+(n.rightLargeArcRadius+r)+" 0 0 0 "+n.rightInnerExtent+" "+(n.verticalFullExtent+r)+"L"+n.leftInnerExtent+" "+(n.verticalFullExtent+r)+"A"+(n.leftLargeArcRadius+r)+" "+(n.leftLargeArcRadius+r)+" 0 0 0 "+(n.leftFullExtent+r)+" "+n.verticalLeftInnerExtent+"L"+(n.leftFullExtent+r)+" "+(n.sourceY+n.leftSmallArcRadius)+"A"+(n.leftLargeArcRadius+r)+" "+(n.leftSmallArcRadius+r)+" 0 0 0 "+n.leftInnerExtent+" "+(n.sourceY-r)+"L"+n.sourceX+" "+(n.sourceY-r)+"L"+n.sourceX+" "+(n.sourceY+r)+"L"+n.leftInnerExtent+" "+(n.sourceY+r)+"A"+(n.leftLargeArcRadius-r)+" "+(n.leftSmallArcRadius-r)+" 0 0 1 "+(n.leftFullExtent-r)+" "+(n.sourceY+n.leftSmallArcRadius)+"L"+(n.leftFullExtent-r)+" "+n.verticalLeftInnerExtent+"A"+(n.leftLargeArcRadius-r)+" "+(n.leftLargeArcRadius-r)+" 0 0 1 "+n.leftInnerExtent+" "+(n.verticalFullExtent-r)+"L"+n.rightInnerExtent+" "+(n.verticalFullExtent-r)+"A"+(n.rightLargeArcRadius-r)+" "+(n.rightLargeArcRadius-r)+" 0 0 1 "+(n.rightFullExtent+r)+" "+n.verticalRightInnerExtent+"L"+(n.rightFullExtent+r)+" "+(n.targetY+n.rightSmallArcRadius)+"A"+(n.rightLargeArcRadius-r)+" "+(n.rightSmallArcRadius-r)+" 0 0 1 "+n.rightInnerExtent+" "+(n.targetY+r)+"L"+n.targetX+" "+(n.targetY+r)+"Z";var e,r,n,a=t.link.source.x1,o=t.link.target.x0,s=i(a,o),l=s(.5),c=s(.5),u=t.link.y0-t.link.width/2,f=t.link.y0+t.link.width/2,h=t.link.y1-t.link.width/2,p=t.link.y1+t.link.width/2;return"M"+a+","+u+"C"+l+","+u+" "+c+","+h+" "+o+","+h+"L"+o+","+p+"C"+c+","+p+" "+l+","+f+" "+a+","+f+"Z"}}function S(t,e){var r=c(e.color),n=l.nodePadAcross,i=t.nodePad/2;e.dx=e.x1-e.x0,e.dy=e.y1-e.y0;var a=e.dx,o=Math.max(.5,e.dy),s="node_"+e.pointNumber;return e.group&&(s=h.randstr()),e.trace=t.trace,e.curveNumber=t.trace.index,{index:e.pointNumber,key:s,partOfGroup:e.partOfGroup||!1,group:e.group,traceId:t.key,trace:t.trace,node:e,nodePad:t.nodePad,nodeLineColor:t.nodeLineColor,nodeLineWidth:t.nodeLineWidth,textFont:t.textFont,size:t.horizontal?t.height:t.width,visibleWidth:Math.ceil(a),visibleHeight:o,zoneX:-n,zoneY:-i,zoneWidth:a+2*n,zoneHeight:o+2*i,labelY:t.horizontal?e.dy/2+1:e.dx/2+1,left:1===e.originalLayer,sizeAcross:t.width,forceLayouts:t.forceLayouts,horizontal:t.horizontal,darkBackground:r.getBrightness()<=128,tinyColorHue:u.tinyRGB(r),tinyColorAlpha:r.getAlpha(),valueFormat:t.valueFormat,valueSuffix:t.valueSuffix,sankey:t.sankey,graph:t.graph,arrangement:t.arrangement,uniqueNodeLabelPathId:[t.guid,t.key,s].join("_"),interactionState:t.interactionState,figure:t}}function E(t){t.attr("transform",(function(t){return p(t.node.x0.toFixed(3),t.node.y0.toFixed(3))}))}function L(t){t.call(E)}function C(t,e){t.call(L),e.attr("d",M())}function P(t){t.attr("width",(function(t){return t.node.x1-t.node.x0})).attr("height",(function(t){return t.visibleHeight}))}function I(t){return t.link.width>1||t.linkLineWidth>0}function O(t){return p(t.translateX,t.translateY)+(t.horizontal?"matrix(1 0 0 1 0 0)":"matrix(0 1 1 0 0 0)")}function z(t,e,r){t.on(".basic",null).on("mouseover.basic",(function(t){t.interactionState.dragInProgress||t.partOfGroup||(r.hover(this,t,e),t.interactionState.hovered=[this,t])})).on("mousemove.basic",(function(t){t.interactionState.dragInProgress||t.partOfGroup||(r.follow(this,t),t.interactionState.hovered=[this,t])})).on("mouseout.basic",(function(t){t.interactionState.dragInProgress||t.partOfGroup||(r.unhover(this,t,e),t.interactionState.hovered=!1)})).on("click.basic",(function(t){t.interactionState.hovered&&(r.unhover(this,t,e),t.interactionState.hovered=!1),t.interactionState.dragInProgress||t.partOfGroup||r.select(this,t,e)}))}function D(t,e,r,i){var o=a.behavior.drag().origin((function(t){return{x:t.node.x0+t.visibleWidth/2,y:t.node.y0+t.visibleHeight/2}})).on("dragstart",(function(a){if("fixed"!==a.arrangement&&(h.ensureSingle(i._fullLayout._infolayer,"g","dragcover",(function(t){i._fullLayout._dragCover=t})),h.raiseToTop(this),a.interactionState.dragInProgress=a.node,F(a.node),a.interactionState.hovered&&(r.nodeEvents.unhover.apply(0,a.interactionState.hovered),a.interactionState.hovered=!1),"snap"===a.arrangement)){var o=a.traceId+"|"+a.key;a.forceLayouts[o]?a.forceLayouts[o].alpha(1):function(t,e,r,i){!function(t){for(var e=0;e0&&n.forceLayouts[e].alpha(0)}}(0,e,a,r)).stop()}(0,o,a),function(t,e,r,n,i){window.requestAnimationFrame((function a(){var o;for(o=0;o0)window.requestAnimationFrame(a);else{var s=r.node.originalX;r.node.x0=s-r.visibleWidth/2,r.node.x1=s+r.visibleWidth/2,R(r,i)}}))}(t,e,a,o,i)}})).on("drag",(function(r){if("fixed"!==r.arrangement){var n=a.event.x,i=a.event.y;"snap"===r.arrangement?(r.node.x0=n-r.visibleWidth/2,r.node.x1=n+r.visibleWidth/2,r.node.y0=i-r.visibleHeight/2,r.node.y1=i+r.visibleHeight/2):("freeform"===r.arrangement&&(r.node.x0=n-r.visibleWidth/2,r.node.x1=n+r.visibleWidth/2),i=Math.max(0,Math.min(r.size-r.visibleHeight/2,i)),r.node.y0=i-r.visibleHeight/2,r.node.y1=i+r.visibleHeight/2),F(r.node),"snap"!==r.arrangement&&(r.sankey.update(r.graph),C(t.filter(B(r)),e))}})).on("dragend",(function(t){if("fixed"!==t.arrangement){t.interactionState.dragInProgress=!1;for(var e=0;el&&C[v].gap;)v--;for(x=C[v].s,m=C.length-1;m>v;m--)C[m].s=x;for(;lM[u]&&u=0;i--){var a=t[i];if("scatter"===a.type&&a.xaxis===r.xaxis&&a.yaxis===r.yaxis){a.opacity=void 0;break}}}}}},{}],934:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry"),a=t("./attributes"),o=t("./constants"),s=t("./subtypes"),l=t("./xy_defaults"),c=t("./period_defaults"),u=t("./stack_defaults"),f=t("./marker_defaults"),h=t("./line_defaults"),p=t("./line_shape_defaults"),d=t("./text_defaults"),m=t("./fillcolor_defaults"),g=t("../../lib").coercePattern;e.exports=function(t,e,r,v){function y(r,i){return n.coerce(t,e,a,r,i)}var x=l(t,e,v,y);if(x||(e.visible=!1),e.visible){c(t,e,v,y),y("xhoverformat"),y("yhoverformat");var b=u(t,e,v,y),_=!b&&x=Math.min(e,r)&&d<=Math.max(e,r)?0:1/0}var n=Math.max(3,t.mrc||0),i=1-1/n,a=Math.abs(h.c2p(t.x)-d);return a=Math.min(e,r)&&m<=Math.max(e,r)?0:1/0}var n=Math.max(3,t.mrc||0),i=1-1/n,a=Math.abs(p.c2p(t.y)-m);return aW!=(N=z[I][1])>=W&&(R=z[I-1][0],F=z[I][0],N-B&&(D=R+(F-R)*(W-B)/(N-B),H=Math.min(H,D),q=Math.max(q,D)));H=Math.max(H,0),q=Math.min(q,h._length);var X=s.defaultLine;return s.opacity(f.fillcolor)?X=f.fillcolor:s.opacity((f.line||{}).color)&&(X=f.line.color),n.extendFlat(t,{distance:t.maxHoverDistance,x0:H,x1:q,y0:W,y1:W,color:X,hovertemplate:!1}),delete t.index,f.text&&!Array.isArray(f.text)?t.text=String(f.text):t.text=f.name,[t]}}}},{"../../components/color":366,"../../components/fx":406,"../../lib":503,"../../registry":638,"./get_trace_color":937}],939:[function(t,e,r){"use strict";var n=t("./subtypes");e.exports={hasLines:n.hasLines,hasMarkers:n.hasMarkers,hasText:n.hasText,isBubble:n.isBubble,attributes:t("./attributes"),supplyDefaults:t("./defaults"),crossTraceDefaults:t("./cross_trace_defaults"),calc:t("./calc").calc,crossTraceCalc:t("./cross_trace_calc"),arraysToCalcdata:t("./arrays_to_calcdata"),plot:t("./plot"),colorbar:t("./marker_colorbar"),formatLabels:t("./format_labels"),style:t("./style").style,styleOnSelect:t("./style").styleOnSelect,hoverPoints:t("./hover"),selectPoints:t("./select"),animatable:!0,moduleType:"trace",name:"scatter",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","symbols","errorBarsOK","showLegend","scatter-like","zoomScale"],meta:{}}},{"../../plots/cartesian":568,"./arrays_to_calcdata":926,"./attributes":927,"./calc":928,"./cross_trace_calc":932,"./cross_trace_defaults":933,"./defaults":934,"./format_labels":936,"./hover":938,"./marker_colorbar":945,"./plot":948,"./select":949,"./style":951,"./subtypes":952}],940:[function(t,e,r){"use strict";var n=t("../../lib").isArrayOrTypedArray,i=t("../../components/colorscale/helpers").hasColorscale,a=t("../../components/colorscale/defaults");e.exports=function(t,e,r,o,s,l){var c=(t.marker||{}).color;(s("line.color",r),i(t,"line"))?a(t,e,o,s,{prefix:"line.",cLetter:"c"}):s("line.color",!n(c)&&c||r);s("line.width"),(l||{}).noDash||s("line.dash")}},{"../../components/colorscale/defaults":376,"../../components/colorscale/helpers":377,"../../lib":503}],941:[function(t,e,r){"use strict";var n=t("../../constants/numerical"),i=n.BADNUM,a=n.LOG_CLIP,o=a+.5,s=a-.5,l=t("../../lib"),c=l.segmentsIntersect,u=l.constrain,f=t("./constants");e.exports=function(t,e){var r,n,a,h,p,d,m,g,v,y,x,b,_,w,T,k,A,M,S=e.xaxis,E=e.yaxis,L="log"===S.type,C="log"===E.type,P=S._length,I=E._length,O=e.connectGaps,z=e.baseTolerance,D=e.shape,R="linear"===D,F=e.fill&&"none"!==e.fill,B=[],N=f.minTolerance,j=t.length,U=new Array(j),V=0;function H(r){var n=t[r];if(!n)return!1;var a=e.linearized?S.l2p(n.x):S.c2p(n.x),l=e.linearized?E.l2p(n.y):E.c2p(n.y);if(a===i){if(L&&(a=S.c2p(n.x,!0)),a===i)return!1;C&&l===i&&(a*=Math.abs(S._m*I*(S._m>0?o:s)/(E._m*P*(E._m>0?o:s)))),a*=1e3}if(l===i){if(C&&(l=E.c2p(n.y,!0)),l===i)return!1;l*=1e3}return[a,l]}function q(t,e,r,n){var i=r-t,a=n-e,o=.5-t,s=.5-e,l=i*i+a*a,c=i*o+a*s;if(c>0&&crt||t[1]it)return[u(t[0],et,rt),u(t[1],nt,it)]}function st(t,e){return t[0]===e[0]&&(t[0]===et||t[0]===rt)||(t[1]===e[1]&&(t[1]===nt||t[1]===it)||void 0)}function lt(t,e,r){return function(n,i){var a=ot(n),o=ot(i),s=[];if(a&&o&&st(a,o))return s;a&&s.push(a),o&&s.push(o);var c=2*l.constrain((n[t]+i[t])/2,e,r)-((a||n)[t]+(o||i)[t]);c&&((a&&o?c>0==a[t]>o[t]?a:o:a||o)[t]+=c);return s}}function ct(t){var e=t[0],r=t[1],n=e===U[V-1][0],i=r===U[V-1][1];if(!n||!i)if(V>1){var a=e===U[V-2][0],o=r===U[V-2][1];n&&(e===et||e===rt)&&a?o?V--:U[V-1]=t:i&&(r===nt||r===it)&&o?a?V--:U[V-1]=t:U[V++]=t}else U[V++]=t}function ut(t){U[V-1][0]!==t[0]&&U[V-1][1]!==t[1]&&ct([Z,J]),ct(t),K=null,Z=J=0}function ft(t){if(A=t[0]/P,M=t[1]/I,W=t[0]rt?rt:0,X=t[1]it?it:0,W||X){if(V)if(K){var e=$(K,t);e.length>1&&(ut(e[0]),U[V++]=e[1])}else Q=$(U[V-1],t)[0],U[V++]=Q;else U[V++]=[W||t[0],X||t[1]];var r=U[V-1];W&&X&&(r[0]!==W||r[1]!==X)?(K&&(Z!==W&&J!==X?ct(Z&&J?(n=K,a=(i=t)[0]-n[0],o=(i[1]-n[1])/a,(n[1]*i[0]-i[1]*n[0])/a>0?[o>0?et:rt,it]:[o>0?rt:et,nt]):[Z||W,J||X]):Z&&J&&ct([Z,J])),ct([W,X])):Z-W&&J-X&&ct([W||Z,X||J]),K=t,Z=W,J=X}else K&&ut($(K,t)[0]),U[V++]=t;var n,i,a,o}for("linear"===D||"spline"===D?$=function(t,e){for(var r=[],n=0,i=0;i<4;i++){var a=at[i],o=c(t[0],t[1],e[0],e[1],a[0],a[1],a[2],a[3]);o&&(!n||Math.abs(o.x-r[0][0])>1||Math.abs(o.y-r[0][1])>1)&&(o=[o.x,o.y],n&&Y(o,t)G(d,ht))break;a=d,(_=v[0]*g[0]+v[1]*g[1])>x?(x=_,h=d,m=!1):_=t.length||!d)break;ft(d),n=d}}else ft(h)}K&&ct([Z||K[0],J||K[1]]),B.push(U.slice(0,V))}return B}},{"../../constants/numerical":479,"../../lib":503,"./constants":931}],942:[function(t,e,r){"use strict";e.exports=function(t,e,r){"spline"===r("line.shape")&&r("line.smoothing")}},{}],943:[function(t,e,r){"use strict";var n={tonextx:1,tonexty:1,tonext:1};e.exports=function(t,e,r){var i,a,o,s,l,c={},u=!1,f=-1,h=0,p=-1;for(a=0;a=0?l=p:(l=p=h,h++),l0?Math.max(r,a):0}}},{"fast-isnumeric":190}],945:[function(t,e,r){"use strict";e.exports={container:"marker",min:"cmin",max:"cmax"}},{}],946:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("../../components/colorscale/helpers").hasColorscale,a=t("../../components/colorscale/defaults"),o=t("./subtypes");e.exports=function(t,e,r,s,l,c){var u=o.isBubble(t),f=(t.line||{}).color;(c=c||{},f&&(r=f),l("marker.symbol"),l("marker.opacity",u?.7:1),l("marker.size"),l("marker.color",r),i(t,"marker")&&a(t,e,s,l,{prefix:"marker.",cLetter:"c"}),c.noSelect||(l("selected.marker.color"),l("unselected.marker.color"),l("selected.marker.size"),l("unselected.marker.size")),c.noLine||(l("marker.line.color",f&&!Array.isArray(f)&&e.marker.color!==f?f:u?n.background:n.defaultLine),i(t,"marker.line")&&a(t,e,s,l,{prefix:"marker.line.",cLetter:"c"}),l("marker.line.width",u?1:0)),u&&(l("marker.sizeref"),l("marker.sizemin"),l("marker.sizemode")),c.gradient)&&("none"!==l("marker.gradient.type")&&l("marker.gradient.color"))}},{"../../components/color":366,"../../components/colorscale/defaults":376,"../../components/colorscale/helpers":377,"./subtypes":952}],947:[function(t,e,r){"use strict";var n=t("../../lib").dateTick0,i=t("../../constants/numerical").ONEWEEK;function a(t,e){return n(e,t%i==0?1:0)}e.exports=function(t,e,r,n,i){if(i||(i={x:!0,y:!0}),i.x){var o=n("xperiod");o&&(n("xperiod0",a(o,e.xcalendar)),n("xperiodalignment"))}if(i.y){var s=n("yperiod");s&&(n("yperiod0",a(s,e.ycalendar)),n("yperiodalignment"))}}},{"../../constants/numerical":479,"../../lib":503}],948:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../registry"),a=t("../../lib"),o=a.ensureSingle,s=a.identity,l=t("../../components/drawing"),c=t("./subtypes"),u=t("./line_points"),f=t("./link_traces"),h=t("../../lib/polygon").tester;function p(t,e,r,f,p,d,m){var g;!function(t,e,r,i,o){var s=r.xaxis,l=r.yaxis,u=n.extent(a.simpleMap(s.range,s.r2c)),f=n.extent(a.simpleMap(l.range,l.r2c)),h=i[0].trace;if(!c.hasMarkers(h))return;var p=h.marker.maxdisplayed;if(0===p)return;var d=i.filter((function(t){return t.x>=u[0]&&t.x<=u[1]&&t.y>=f[0]&&t.y<=f[1]})),m=Math.ceil(d.length/p),g=0;o.forEach((function(t,r){var n=t[0].trace;c.hasMarkers(n)&&n.marker.maxdisplayed>0&&r0;function y(t){return v?t.transition():t}var x=r.xaxis,b=r.yaxis,_=f[0].trace,w=_.line,T=n.select(d),k=o(T,"g","errorbars"),A=o(T,"g","lines"),M=o(T,"g","points"),S=o(T,"g","text");if(i.getComponentMethod("errorbars","plot")(t,k,r,m),!0===_.visible){var E,L;y(T).style("opacity",_.opacity);var C=_.fill.charAt(_.fill.length-1);"x"!==C&&"y"!==C&&(C=""),f[0][r.isRangePlot?"nodeRangePlot3":"node3"]=T;var P,I,O="",z=[],D=_._prevtrace;D&&(O=D._prevRevpath||"",L=D._nextFill,z=D._polygons);var R,F,B,N,j,U,V,H="",q="",G=[],Y=a.noop;if(E=_._ownFill,c.hasLines(_)||"none"!==_.fill){for(L&&L.datum(f),-1!==["hv","vh","hvh","vhv"].indexOf(w.shape)?(R=l.steps(w.shape),F=l.steps(w.shape.split("").reverse().join(""))):R=F="spline"===w.shape?function(t){var e=t[t.length-1];return t.length>1&&t[0][0]===e[0]&&t[0][1]===e[1]?l.smoothclosed(t.slice(1),w.smoothing):l.smoothopen(t,w.smoothing)}:function(t){return"M"+t.join("L")},B=function(t){return F(t.reverse())},G=u(f,{xaxis:x,yaxis:b,connectGaps:_.connectgaps,baseTolerance:Math.max(w.width||1,3)/4,shape:w.shape,simplify:w.simplify,fill:_.fill}),V=_._polygons=new Array(G.length),g=0;g1){var r=n.select(this);if(r.datum(f),t)y(r.style("opacity",0).attr("d",P).call(l.lineGroupStyle)).style("opacity",1);else{var i=y(r);i.attr("d",P),l.singleLineStyle(f,i)}}}}}var W=A.selectAll(".js-line").data(G);y(W.exit()).style("opacity",0).remove(),W.each(Y(!1)),W.enter().append("path").classed("js-line",!0).style("vector-effect","non-scaling-stroke").call(l.lineGroupStyle).each(Y(!0)),l.setClipUrl(W,r.layerClipId,t),G.length?(E?(E.datum(f),N&&U&&(C?("y"===C?N[1]=U[1]=b.c2p(0,!0):"x"===C&&(N[0]=U[0]=x.c2p(0,!0)),y(E).attr("d","M"+U+"L"+N+"L"+H.substr(1)).call(l.singleFillStyle,t)):y(E).attr("d",H+"Z").call(l.singleFillStyle,t))):L&&("tonext"===_.fill.substr(0,6)&&H&&O?("tonext"===_.fill?y(L).attr("d",H+"Z"+O+"Z").call(l.singleFillStyle,t):y(L).attr("d",H+"L"+O.substr(1)+"Z").call(l.singleFillStyle,t),_._polygons=_._polygons.concat(z)):(Z(L),_._polygons=null)),_._prevRevpath=q,_._prevPolygons=V):(E?Z(E):L&&Z(L),_._polygons=_._prevRevpath=_._prevPolygons=null),M.datum(f),S.datum(f),function(e,i,a){var o,u=a[0].trace,f=c.hasMarkers(u),h=c.hasText(u),p=tt(u),d=et,m=et;if(f||h){var g=s,_=u.stackgroup,w=_&&"infer zero"===t._fullLayout._scatterStackOpts[x._id+b._id][_].stackgaps;u.marker.maxdisplayed||u._needsCull?g=w?K:J:_&&!w&&(g=Q),f&&(d=g),h&&(m=g)}var T,k=(o=e.selectAll("path.point").data(d,p)).enter().append("path").classed("point",!0);v&&k.call(l.pointStyle,u,t).call(l.translatePoints,x,b).style("opacity",0).transition().style("opacity",1),o.order(),f&&(T=l.makePointStyleFns(u)),o.each((function(e){var i=n.select(this),a=y(i);l.translatePoint(e,a,x,b)?(l.singlePointStyle(e,a,u,T,t),r.layerClipId&&l.hideOutsideRangePoint(e,a,x,b,u.xcalendar,u.ycalendar),u.customdata&&i.classed("plotly-customdata",null!==e.data&&void 0!==e.data)):a.remove()})),v?o.exit().transition().style("opacity",0).remove():o.exit().remove(),(o=i.selectAll("g").data(m,p)).enter().append("g").classed("textpoint",!0).append("text"),o.order(),o.each((function(t){var e=n.select(this),i=y(e.select("text"));l.translatePoint(t,i,x,b)?r.layerClipId&&l.hideOutsideRangePoint(t,e,x,b,u.xcalendar,u.ycalendar):e.remove()})),o.selectAll("text").call(l.textPointStyle,u,t).each((function(t){var e=x.c2p(t.x),r=b.c2p(t.y);n.select(this).selectAll("tspan.line").each((function(){y(n.select(this)).attr({x:e,y:r})}))})),o.exit().remove()}(M,S,f);var X=!1===_.cliponaxis?null:r.layerClipId;l.setClipUrl(M,X,t),l.setClipUrl(S,X,t)}function Z(t){y(t).attr("d","M0,0Z")}function J(t){return t.filter((function(t){return!t.gap&&t.vis}))}function K(t){return t.filter((function(t){return t.vis}))}function Q(t){return t.filter((function(t){return!t.gap}))}function $(t){return t.id}function tt(t){if(t.ids)return $}function et(){return!1}}e.exports=function(t,e,r,i,a,c){var u,h,d=!a,m=!!a&&a.duration>0,g=f(t,e,r);((u=i.selectAll("g.trace").data(g,(function(t){return t[0].trace.uid}))).enter().append("g").attr("class",(function(t){return"trace scatter trace"+t[0].trace.uid})).style("stroke-miterlimit",2),u.order(),function(t,e,r){e.each((function(e){var i=o(n.select(this),"g","fills");l.setClipUrl(i,r.layerClipId,t);var a=e[0].trace,c=[];a._ownfill&&c.push("_ownFill"),a._nexttrace&&c.push("_nextFill");var u=i.selectAll("g").data(c,s);u.enter().append("g"),u.exit().each((function(t){a[t]=null})).remove(),u.order().each((function(t){a[t]=o(n.select(this),"path","js-fill")}))}))}(t,u,e),m)?(c&&(h=c()),n.transition().duration(a.duration).ease(a.easing).each("end",(function(){h&&h()})).each("interrupt",(function(){h&&h()})).each((function(){i.selectAll("g.trace").each((function(r,n){p(t,n,e,r,g,this,a)}))}))):u.each((function(r,n){p(t,n,e,r,g,this,a)}));d&&u.exit().remove(),i.selectAll("path:not([d])").remove()}},{"../../components/drawing":388,"../../lib":503,"../../lib/polygon":515,"../../registry":638,"./line_points":941,"./link_traces":943,"./subtypes":952,"@plotly/d3":58}],949:[function(t,e,r){"use strict";var n=t("./subtypes");e.exports=function(t,e){var r,i,a,o,s=t.cd,l=t.xaxis,c=t.yaxis,u=[],f=s[0].trace;if(!n.hasMarkers(f)&&!n.hasText(f))return[];if(!1===e)for(r=0;r0){var h=i.c2l(u);i._lowerLogErrorBound||(i._lowerLogErrorBound=h),i._lowerErrorBound=Math.min(i._lowerLogErrorBound,h)}}else o[s]=[-l[0]*r,l[1]*r]}return o}e.exports=function(t,e,r){var n=[i(t.x,t.error_x,e[0],r.xaxis),i(t.y,t.error_y,e[1],r.yaxis),i(t.z,t.error_z,e[2],r.zaxis)],a=function(t){for(var e=0;e-1?-1:t.indexOf("right")>-1?1:0}function b(t){return null==t?0:t.indexOf("top")>-1?-1:t.indexOf("bottom")>-1?1:0}function _(t,e){return e(4*t)}function w(t){return p[t]}function T(t,e,r,n,i){var a=null;if(l.isArrayOrTypedArray(t)){a=[];for(var o=0;o=0){var m=function(t,e,r){var n,i=(r+1)%3,a=(r+2)%3,o=[],l=[];for(n=0;n=0&&f("surfacecolor",h||p);for(var d=["x","y","z"],m=0;m<3;++m){var g="projection."+d[m];f(g+".show")&&(f(g+".opacity"),f(g+".scale"))}var v=n.getComponentMethod("errorbars","supplyDefaults");v(t,e,h||p||r,{axis:"z"}),v(t,e,h||p||r,{axis:"y",inherit:"z"}),v(t,e,h||p||r,{axis:"x",inherit:"z"})}else e.visible=!1}},{"../../lib":503,"../../registry":638,"../scatter/line_defaults":940,"../scatter/marker_defaults":946,"../scatter/subtypes":952,"../scatter/text_defaults":953,"./attributes":955}],960:[function(t,e,r){"use strict";e.exports={plot:t("./convert"),attributes:t("./attributes"),markerSymbols:t("../../constants/gl3d_markers"),supplyDefaults:t("./defaults"),colorbar:[{container:"marker",min:"cmin",max:"cmax"},{container:"line",min:"cmin",max:"cmax"}],calc:t("./calc"),moduleType:"trace",name:"scatter3d",basePlotModule:t("../../plots/gl3d"),categories:["gl3d","symbols","showLegend","scatter-like"],meta:{}}},{"../../constants/gl3d_markers":477,"../../plots/gl3d":598,"./attributes":955,"./calc":956,"./convert":958,"./defaults":959}],961:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../plots/attributes"),a=t("../../plots/template_attributes").hovertemplateAttrs,o=t("../../plots/template_attributes").texttemplateAttrs,s=t("../../components/colorscale/attributes"),l=t("../../lib/extend").extendFlat,c=n.marker,u=n.line,f=c.line;e.exports={carpet:{valType:"string",editType:"calc"},a:{valType:"data_array",editType:"calc"},b:{valType:"data_array",editType:"calc"},mode:l({},n.mode,{dflt:"markers"}),text:l({},n.text,{}),texttemplate:o({editType:"plot"},{keys:["a","b","text"]}),hovertext:l({},n.hovertext,{}),line:{color:u.color,width:u.width,dash:u.dash,shape:l({},u.shape,{values:["linear","spline"]}),smoothing:u.smoothing,editType:"calc"},connectgaps:n.connectgaps,fill:l({},n.fill,{values:["none","toself","tonext"],dflt:"none"}),fillcolor:n.fillcolor,marker:l({symbol:c.symbol,opacity:c.opacity,maxdisplayed:c.maxdisplayed,size:c.size,sizeref:c.sizeref,sizemin:c.sizemin,sizemode:c.sizemode,line:l({width:f.width,editType:"calc"},s("marker.line")),gradient:c.gradient,editType:"calc"},s("marker")),textfont:n.textfont,textposition:n.textposition,selected:n.selected,unselected:n.unselected,hoverinfo:l({},i.hoverinfo,{flags:["a","b","text","name"]}),hoveron:n.hoveron,hovertemplate:a()}},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plots/attributes":550,"../../plots/template_attributes":633,"../scatter/attributes":927}],962:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../scatter/colorscale_calc"),a=t("../scatter/arrays_to_calcdata"),o=t("../scatter/calc_selection"),s=t("../scatter/calc").calcMarkerSize,l=t("../carpet/lookup_carpetid");e.exports=function(t,e){var r=e._carpetTrace=l(t,e);if(r&&r.visible&&"legendonly"!==r.visible){var c;e.xaxis=r.xaxis,e.yaxis=r.yaxis;var u,f,h=e._length,p=new Array(h),d=!1;for(c=0;c")}return o}function y(t,e){var r;r=t.labelprefix&&t.labelprefix.length>0?t.labelprefix.replace(/ = $/,""):t._hovertitle,g.push(r+": "+e.toFixed(3)+t.labelsuffix)}}},{"../../lib":503,"../scatter/hover":938}],967:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../scatter/marker_colorbar"),formatLabels:t("./format_labels"),calc:t("./calc"),plot:t("./plot"),style:t("../scatter/style").style,styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover"),selectPoints:t("../scatter/select"),eventData:t("./event_data"),moduleType:"trace",name:"scattercarpet",basePlotModule:t("../../plots/cartesian"),categories:["svg","carpet","symbols","showLegend","carpetDependent","zoomScale"],meta:{}}},{"../../plots/cartesian":568,"../scatter/marker_colorbar":945,"../scatter/select":949,"../scatter/style":951,"./attributes":961,"./calc":962,"./defaults":963,"./event_data":964,"./format_labels":965,"./hover":966,"./plot":968}],968:[function(t,e,r){"use strict";var n=t("../scatter/plot"),i=t("../../plots/cartesian/axes"),a=t("../../components/drawing");e.exports=function(t,e,r,o){var s,l,c,u=r[0][0].carpet,f={xaxis:i.getFromId(t,u.xaxis||"x"),yaxis:i.getFromId(t,u.yaxis||"y"),plot:e.plot};for(n(t,f,r,o),s=0;s")}(c,m,t,l[0].t.labels),t.hovertemplate=c.hovertemplate,[t]}}},{"../../components/fx":406,"../../constants/numerical":479,"../../lib":503,"../scatter/get_trace_color":937,"./attributes":969}],975:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../scatter/marker_colorbar"),formatLabels:t("./format_labels"),calc:t("./calc"),calcGeoJSON:t("./plot").calcGeoJSON,plot:t("./plot").plot,style:t("./style"),styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover"),eventData:t("./event_data"),selectPoints:t("./select"),moduleType:"trace",name:"scattergeo",basePlotModule:t("../../plots/geo"),categories:["geo","symbols","showLegend","scatter-like"],meta:{}}},{"../../plots/geo":589,"../scatter/marker_colorbar":945,"../scatter/style":951,"./attributes":969,"./calc":970,"./defaults":971,"./event_data":972,"./format_labels":973,"./hover":974,"./plot":976,"./select":977,"./style":978}],976:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=t("../../lib/topojson_utils").getTopojsonFeatures,o=t("../../lib/geojson_utils"),s=t("../../lib/geo_location_utils"),l=t("../../plots/cartesian/autorange").findExtremes,c=t("../../constants/numerical").BADNUM,u=t("../scatter/calc").calcMarkerSize,f=t("../scatter/subtypes"),h=t("./style");e.exports={calcGeoJSON:function(t,e){var r,n,i=t[0].trace,o=e[i.geo],f=o._subplot,h=i._length;if(Array.isArray(i.locations)){var p=i.locationmode,d="geojson-id"===p?s.extractTraceFeature(t):a(i,f.topojson);for(r=0;r=g,w=2*b,T={},k=l.makeCalcdata(e,"x"),A=y.makeCalcdata(e,"y"),M=s(e,l,"x",k),S=s(e,y,"y",A),E=M.vals,L=S.vals;e._x=E,e._y=L,e.xperiodalignment&&(e._origX=k,e._xStarts=M.starts,e._xEnds=M.ends),e.yperiodalignment&&(e._origY=A,e._yStarts=S.starts,e._yEnds=S.ends);var C=new Array(w),P=new Array(b);for(r=0;r1&&i.extendFlat(s.line,p.linePositions(t,r,n));if(s.errorX||s.errorY){var l=p.errorBarPositions(t,r,n,a,o);s.errorX&&i.extendFlat(s.errorX,l.x),s.errorY&&i.extendFlat(s.errorY,l.y)}s.text&&(i.extendFlat(s.text,{positions:n},p.textPosition(t,r,s.text,s.marker)),i.extendFlat(s.textSel,{positions:n},p.textPosition(t,r,s.text,s.markerSel)),i.extendFlat(s.textUnsel,{positions:n},p.textPosition(t,r,s.text,s.markerUnsel)));return s}(t,0,e,C,E,L),z=d(t,x);return f(o,e),_?O.marker&&(I=O.marker.sizeAvg||Math.max(O.marker.size,3)):I=c(e,b),u(t,e,l,y,E,L,I),O.errorX&&v(e,l,O.errorX),O.errorY&&v(e,y,O.errorY),O.fill&&!z.fill2d&&(z.fill2d=!0),O.marker&&!z.scatter2d&&(z.scatter2d=!0),O.line&&!z.line2d&&(z.line2d=!0),!O.errorX&&!O.errorY||z.error2d||(z.error2d=!0),O.text&&!z.glText&&(z.glText=!0),O.marker&&(O.marker.snap=b),z.lineOptions.push(O.line),z.errorXOptions.push(O.errorX),z.errorYOptions.push(O.errorY),z.fillOptions.push(O.fill),z.markerOptions.push(O.marker),z.markerSelectedOptions.push(O.markerSel),z.markerUnselectedOptions.push(O.markerUnsel),z.textOptions.push(O.text),z.textSelectedOptions.push(O.textSel),z.textUnselectedOptions.push(O.textUnsel),z.selectBatch.push([]),z.unselectBatch.push([]),T._scene=z,T.index=z.count,T.x=E,T.y=L,T.positions=C,z.count++,[{x:!1,y:!1,t:T,trace:e}]}},{"../../constants/numerical":479,"../../lib":503,"../../plots/cartesian/align_period":551,"../../plots/cartesian/autorange":553,"../../plots/cartesian/axis_ids":558,"../scatter/calc":928,"../scatter/colorscale_calc":930,"./constants":982,"./convert":983,"./scene_update":991,"@plotly/point-cluster":59}],982:[function(t,e,r){"use strict";e.exports={TOO_MANY_POINTS:1e5,SYMBOL_SDF_SIZE:200,SYMBOL_SIZE:20,SYMBOL_STROKE:1,DOT_RE:/-dot/,OPEN_RE:/-open/,DASHES:{solid:[1],dot:[1,1],dash:[4,1],longdash:[8,1],dashdot:[4,1,1,1],longdashdot:[8,1,1,1]}}},{}],983:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("svg-path-sdf"),a=t("color-normalize"),o=t("../../registry"),s=t("../../lib"),l=t("../../components/drawing"),c=t("../../plots/cartesian/axis_ids"),u=t("../../lib/gl_format_color").formatColor,f=t("../scatter/subtypes"),h=t("../scatter/make_bubble_size_func"),p=t("./helpers"),d=t("./constants"),m=t("../../constants/interactions").DESELECTDIM,g={start:1,left:1,end:-1,right:-1,middle:0,center:0,bottom:1,top:-1},v=t("../../components/fx/helpers").appendArrayPointValue;function y(t,e){var r,i=t._fullLayout,a=e._length,o=e.textfont,l=e.textposition,c=Array.isArray(l)?l:[l],u=o.color,f=o.size,h=o.family,p={},d=t._context.plotGlPixelRatio,m=e.texttemplate;if(m){p.text=[];var g=i._d3locale,y=Array.isArray(m),x=y?Math.min(m.length,a):a,b=y?function(t){return m[t]}:function(){return m};for(r=0;rd.TOO_MANY_POINTS||f.hasMarkers(e)?"rect":"round";if(c&&e.connectgaps){var h=n[0],p=n[1];for(i=0;i1?l[i]:l[0]:l,d=Array.isArray(c)?c.length>1?c[i]:c[0]:c,m=g[p],v=g[d],y=u?u/.8+1:0,x=-v*y-.5*v;o.offset[i]=[m*y/h,x/h]}}return o}}},{"../../components/drawing":388,"../../components/fx/helpers":402,"../../constants/interactions":478,"../../lib":503,"../../lib/gl_format_color":499,"../../plots/cartesian/axis_ids":558,"../../registry":638,"../scatter/make_bubble_size_func":944,"../scatter/subtypes":952,"./constants":982,"./helpers":987,"color-normalize":89,"fast-isnumeric":190,"svg-path-sdf":310}],984:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../registry"),a=t("./helpers"),o=t("./attributes"),s=t("../scatter/constants"),l=t("../scatter/subtypes"),c=t("../scatter/xy_defaults"),u=t("../scatter/period_defaults"),f=t("../scatter/marker_defaults"),h=t("../scatter/line_defaults"),p=t("../scatter/fillcolor_defaults"),d=t("../scatter/text_defaults");e.exports=function(t,e,r,m){function g(r,i){return n.coerce(t,e,o,r,i)}var v=!!t.marker&&a.isOpenSymbol(t.marker.symbol),y=l.isBubble(t),x=c(t,e,m,g);if(x){u(t,e,m,g),g("xhoverformat"),g("yhoverformat");var b=x100},r.isDotSymbol=function(t){return"string"==typeof t?n.DOT_RE.test(t):t>200}},{"./constants":982}],988:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../lib"),a=t("../scatter/get_trace_color");function o(t,e,r,o){var s=t.xa,l=t.ya,c=t.distance,u=t.dxy,f=t.index,h={pointNumber:f,x:e[f],y:r[f]};h.tx=Array.isArray(o.text)?o.text[f]:o.text,h.htx=Array.isArray(o.hovertext)?o.hovertext[f]:o.hovertext,h.data=Array.isArray(o.customdata)?o.customdata[f]:o.customdata,h.tp=Array.isArray(o.textposition)?o.textposition[f]:o.textposition;var p=o.textfont;p&&(h.ts=i.isArrayOrTypedArray(p.size)?p.size[f]:p.size,h.tc=Array.isArray(p.color)?p.color[f]:p.color,h.tf=Array.isArray(p.family)?p.family[f]:p.family);var d=o.marker;d&&(h.ms=i.isArrayOrTypedArray(d.size)?d.size[f]:d.size,h.mo=i.isArrayOrTypedArray(d.opacity)?d.opacity[f]:d.opacity,h.mx=i.isArrayOrTypedArray(d.symbol)?d.symbol[f]:d.symbol,h.mc=i.isArrayOrTypedArray(d.color)?d.color[f]:d.color);var m=d&&d.line;m&&(h.mlc=Array.isArray(m.color)?m.color[f]:m.color,h.mlw=i.isArrayOrTypedArray(m.width)?m.width[f]:m.width);var g=d&&d.gradient;g&&"none"!==g.type&&(h.mgt=Array.isArray(g.type)?g.type[f]:g.type,h.mgc=Array.isArray(g.color)?g.color[f]:g.color);var v=s.c2p(h.x,!0),y=l.c2p(h.y,!0),x=h.mrc||1,b=o.hoverlabel;b&&(h.hbg=Array.isArray(b.bgcolor)?b.bgcolor[f]:b.bgcolor,h.hbc=Array.isArray(b.bordercolor)?b.bordercolor[f]:b.bordercolor,h.hts=i.isArrayOrTypedArray(b.font.size)?b.font.size[f]:b.font.size,h.htc=Array.isArray(b.font.color)?b.font.color[f]:b.font.color,h.htf=Array.isArray(b.font.family)?b.font.family[f]:b.font.family,h.hnl=i.isArrayOrTypedArray(b.namelength)?b.namelength[f]:b.namelength);var _=o.hoverinfo;_&&(h.hi=Array.isArray(_)?_[f]:_);var w=o.hovertemplate;w&&(h.ht=Array.isArray(w)?w[f]:w);var T={};T[t.index]=h;var k=o._origX,A=o._origY,M=i.extendFlat({},t,{color:a(o,h),x0:v-x,x1:v+x,xLabelVal:k?k[f]:h.x,y0:y-x,y1:y+x,yLabelVal:A?A[f]:h.y,cd:T,distance:c,spikeDistance:u,hovertemplate:h.ht});return h.htx?M.text=h.htx:h.tx?M.text=h.tx:o.text&&(M.text=o.text),i.fillText(h,o,M),n.getComponentMethod("errorbars","hoverInfo")(h,o,M),M}e.exports={hoverPoints:function(t,e,r,n){var i,a,s,l,c,u,f,h,p,d,m=t.cd,g=m[0].t,v=m[0].trace,y=t.xa,x=t.ya,b=g.x,_=g.y,w=y.c2p(e),T=x.c2p(r),k=t.distance;if(g.tree){var A=y.p2c(w-k),M=y.p2c(w+k),S=x.p2c(T-k),E=x.p2c(T+k);i="x"===n?g.tree.range(Math.min(A,M),Math.min(x._rl[0],x._rl[1]),Math.max(A,M),Math.max(x._rl[0],x._rl[1])):g.tree.range(Math.min(A,M),Math.min(S,E),Math.max(A,M),Math.max(S,E))}else i=g.ids;var L=k;if("x"===n){var C=!!v.xperiodalignment,P=!!v.yperiodalignment;for(u=0;u=Math.min(I,O)&&w<=Math.max(I,O)?0:1/0}if(f=Math.min(z,D)&&T<=Math.max(z,D)?0:1/0}d=Math.sqrt(f*f+h*h),s=i[u]}}}else for(u=i.length-1;u>-1;u--)l=b[a=i[u]],c=_[a],f=y.c2p(l)-w,h=x.c2p(c)-T,(p=Math.sqrt(f*f+h*h))y.glText.length){var T=_-y.glText.length;for(m=0;mr&&(isNaN(e[n])||isNaN(e[n+1]));)n-=2;t.positions=e.slice(r,n+2)}return t})),y.line2d.update(y.lineOptions)),y.error2d){var A=(y.errorXOptions||[]).concat(y.errorYOptions||[]);y.error2d.update(A)}y.scatter2d&&y.scatter2d.update(y.markerOptions),y.fillOrder=s.repeat(null,_),y.fill2d&&(y.fillOptions=y.fillOptions.map((function(t,e){var n=r[e];if(t&&n&&n[0]&&n[0].trace){var i,a,o=n[0],s=o.trace,l=o.t,c=y.lineOptions[e],u=[];s._ownfill&&u.push(e),s._nexttrace&&u.push(e+1),u.length&&(y.fillOrder[e]=u);var f,h,p=[],d=c&&c.positions||l.positions;if("tozeroy"===s.fill){for(f=0;ff&&isNaN(d[h+1]);)h-=2;0!==d[f+1]&&(p=[d[f],0]),p=p.concat(d.slice(f,h+2)),0!==d[h+1]&&(p=p.concat([d[h],0]))}else if("tozerox"===s.fill){for(f=0;ff&&isNaN(d[h]);)h-=2;0!==d[f]&&(p=[0,d[f+1]]),p=p.concat(d.slice(f,h+2)),0!==d[h]&&(p=p.concat([0,d[h+1]]))}else if("toself"===s.fill||"tonext"===s.fill){for(p=[],i=0,t.splitNull=!0,a=0;a-1;for(m=0;m<_;m++){var L=r[m][0],C=L.trace,P=L.t,I=P.index,O=C._length,z=P.x,D=P.y;if(C.selectedpoints||S||E){if(S||(S=!0),C.selectedpoints){var R=y.selectBatch[I]=s.selIndices2selPoints(C),F={};for(g=0;g")}function u(t){return t+"\xb0"}}e.exports={hoverPoints:function(t,e,r){var o=t.cd,c=o[0].trace,u=t.xa,f=t.ya,h=t.subplot,p=360*(e>=0?Math.floor((e+180)/360):Math.ceil((e-180)/360)),d=e-p;if(n.getClosest(o,(function(t){var e=t.lonlat;if(e[0]===s)return 1/0;var n=i.modHalf(e[0],360),a=e[1],o=h.project([n,a]),l=o.x-u.c2p([d,a]),c=o.y-f.c2p([n,r]),p=Math.max(3,t.mrc||0);return Math.max(Math.sqrt(l*l+c*c)-p,1-3/p)}),t),!1!==t.index){var m=o[t.index],g=m.lonlat,v=[i.modHalf(g[0],360)+p,g[1]],y=u.c2p(v),x=f.c2p(v),b=m.mrc||1;t.x0=y-b,t.x1=y+b,t.y0=x-b,t.y1=x+b;var _={};_[c.subplot]={_subplot:h};var w=c._module.formatLabels(m,c,_);return t.lonLabel=w.lonLabel,t.latLabel=w.latLabel,t.color=a(c,m),t.extraText=l(c,m,o[0].t.labels),t.hovertemplate=c.hovertemplate,[t]}},getExtraText:l}},{"../../components/fx":406,"../../constants/numerical":479,"../../lib":503,"../scatter/get_trace_color":937}],999:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../scatter/marker_colorbar"),formatLabels:t("./format_labels"),calc:t("../scattergeo/calc"),plot:t("./plot"),hoverPoints:t("./hover").hoverPoints,eventData:t("./event_data"),selectPoints:t("./select"),styleOnSelect:function(t,e){e&&e[0].trace._glTrace.update(e)},moduleType:"trace",name:"scattermapbox",basePlotModule:t("../../plots/mapbox"),categories:["mapbox","gl","symbols","showLegend","scatter-like"],meta:{}}},{"../../plots/mapbox":613,"../scatter/marker_colorbar":945,"../scattergeo/calc":970,"./attributes":993,"./defaults":995,"./event_data":996,"./format_labels":997,"./hover":998,"./plot":1e3,"./select":1001}],1e3:[function(t,e,r){"use strict";var n=t("./convert"),i=t("../../plots/mapbox/constants").traceLayerPrefix,a=["fill","line","circle","symbol"];function o(t,e){this.type="scattermapbox",this.subplot=t,this.uid=e,this.sourceIds={fill:"source-"+e+"-fill",line:"source-"+e+"-line",circle:"source-"+e+"-circle",symbol:"source-"+e+"-symbol"},this.layerIds={fill:i+e+"-fill",line:i+e+"-line",circle:i+e+"-circle",symbol:i+e+"-symbol"},this.below=null}var s=o.prototype;s.addSource=function(t,e){this.subplot.map.addSource(this.sourceIds[t],{type:"geojson",data:e.geojson})},s.setSourceData=function(t,e){this.subplot.map.getSource(this.sourceIds[t]).setData(e.geojson)},s.addLayer=function(t,e,r){this.subplot.addLayer({type:t,id:this.layerIds[t],source:this.sourceIds[t],layout:e.layout,paint:e.paint},r)},s.update=function(t){var e,r,i,o=this.subplot,s=o.map,l=n(o.gd,t),c=o.belowLookup["trace-"+this.uid];if(c!==this.below){for(e=a.length-1;e>=0;e--)r=a[e],s.removeLayer(this.layerIds[r]);for(e=0;e=0;e--){var r=a[e];t.removeLayer(this.layerIds[r]),t.removeSource(this.sourceIds[r])}},e.exports=function(t,e){for(var r=e[0].trace,i=new o(t,r.uid),s=n(t.gd,e),l=i.below=t.belowLookup["trace-"+r.uid],c=0;c")}}e.exports={hoverPoints:function(t,e,r,a){var o=n(t,e,r,a);if(o&&!1!==o[0].index){var s=o[0];if(void 0===s.index)return o;var l=t.subplot,c=s.cd[s.index],u=s.trace;if(l.isPtInside(c))return s.xLabelVal=void 0,s.yLabelVal=void 0,i(c,u,l,s),s.hovertemplate=u.hovertemplate,o}},makeHoverPointText:i}},{"../scatter/hover":938}],1007:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"scatterpolar",basePlotModule:t("../../plots/polar"),categories:["polar","symbols","showLegend","scatter-like"],attributes:t("./attributes"),supplyDefaults:t("./defaults").supplyDefaults,colorbar:t("../scatter/marker_colorbar"),formatLabels:t("./format_labels"),calc:t("./calc"),plot:t("./plot"),style:t("../scatter/style").style,styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover").hoverPoints,selectPoints:t("../scatter/select"),meta:{}}},{"../../plots/polar":622,"../scatter/marker_colorbar":945,"../scatter/select":949,"../scatter/style":951,"./attributes":1002,"./calc":1003,"./defaults":1004,"./format_labels":1005,"./hover":1006,"./plot":1008}],1008:[function(t,e,r){"use strict";var n=t("../scatter/plot"),i=t("../../constants/numerical").BADNUM;e.exports=function(t,e,r){for(var a=e.layers.frontplot.select("g.scatterlayer"),o={xaxis:e.xaxis,yaxis:e.yaxis,plot:e.framework,layerClipId:e._hasClipOnAxisFalse?e.clipIds.forTraces:null},s=e.radialAxis,l=e.angularAxis,c=0;c=c&&(y.marker.cluster=d.tree),y.marker&&(y.markerSel.positions=y.markerUnsel.positions=y.marker.positions=_),y.line&&_.length>1&&l.extendFlat(y.line,s.linePositions(t,p,_)),y.text&&(l.extendFlat(y.text,{positions:_},s.textPosition(t,p,y.text,y.marker)),l.extendFlat(y.textSel,{positions:_},s.textPosition(t,p,y.text,y.markerSel)),l.extendFlat(y.textUnsel,{positions:_},s.textPosition(t,p,y.text,y.markerUnsel))),y.fill&&!h.fill2d&&(h.fill2d=!0),y.marker&&!h.scatter2d&&(h.scatter2d=!0),y.line&&!h.line2d&&(h.line2d=!0),y.text&&!h.glText&&(h.glText=!0),h.lineOptions.push(y.line),h.fillOptions.push(y.fill),h.markerOptions.push(y.marker),h.markerSelectedOptions.push(y.markerSel),h.markerUnselectedOptions.push(y.markerUnsel),h.textOptions.push(y.text),h.textSelectedOptions.push(y.textSel),h.textUnselectedOptions.push(y.textUnsel),h.selectBatch.push([]),h.unselectBatch.push([]),d.x=w,d.y=T,d.rawx=w,d.rawy=T,d.r=g,d.theta=v,d.positions=_,d._scene=h,d.index=h.count,h.count++}})),a(t,e,r)}},e.exports.reglPrecompiled={}},{"../../lib":503,"../scattergl/constants":982,"../scattergl/convert":983,"../scattergl/plot":990,"../scattergl/scene_update":991,"@plotly/point-cluster":59,"fast-isnumeric":190}],1017:[function(t,e,r){"use strict";var n=t("../../plots/template_attributes").hovertemplateAttrs,i=t("../../plots/template_attributes").texttemplateAttrs,a=t("../../lib/extend").extendFlat,o=t("../scatter/attributes"),s=t("../../plots/attributes"),l=o.line;e.exports={mode:o.mode,real:{valType:"data_array",editType:"calc+clearAxisTypes"},imag:{valType:"data_array",editType:"calc+clearAxisTypes"},text:o.text,texttemplate:i({editType:"plot"},{keys:["real","imag","text"]}),hovertext:o.hovertext,line:{color:l.color,width:l.width,dash:l.dash,shape:a({},l.shape,{values:["linear","spline"]}),smoothing:l.smoothing,editType:"calc"},connectgaps:o.connectgaps,marker:o.marker,cliponaxis:a({},o.cliponaxis,{dflt:!1}),textposition:o.textposition,textfont:o.textfont,fill:a({},o.fill,{values:["none","toself","tonext"],dflt:"none"}),fillcolor:o.fillcolor,hoverinfo:a({},s.hoverinfo,{flags:["real","imag","text","name"]}),hoveron:o.hoveron,hovertemplate:n(),selected:o.selected,unselected:o.unselected}},{"../../lib/extend":493,"../../plots/attributes":550,"../../plots/template_attributes":633,"../scatter/attributes":927}],1018:[function(t,e,r){"use strict";var n=t("fast-isnumeric"),i=t("../../constants/numerical").BADNUM,a=t("../scatter/colorscale_calc"),o=t("../scatter/arrays_to_calcdata"),s=t("../scatter/calc_selection"),l=t("../scatter/calc").calcMarkerSize;e.exports=function(t,e){for(var r=t._fullLayout,c=e.subplot,u=r[c].realaxis,f=r[c].imaginaryaxis,h=u.makeCalcdata(e,"real"),p=f.makeCalcdata(e,"imag"),d=e._length,m=new Array(d),g=0;g")}}e.exports={hoverPoints:function(t,e,r,a){var o=n(t,e,r,a);if(o&&!1!==o[0].index){var s=o[0];if(void 0===s.index)return o;var l=t.subplot,c=s.cd[s.index],u=s.trace;if(l.isPtInside(c))return s.xLabelVal=void 0,s.yLabelVal=void 0,i(c,u,l,s),s.hovertemplate=u.hovertemplate,o}},makeHoverPointText:i}},{"../scatter/hover":938}],1022:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"scattersmith",basePlotModule:t("../../plots/smith"),categories:["smith","symbols","showLegend","scatter-like"],attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../scatter/marker_colorbar"),formatLabels:t("./format_labels"),calc:t("./calc"),plot:t("./plot"),style:t("../scatter/style").style,styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover").hoverPoints,selectPoints:t("../scatter/select"),meta:{}}},{"../../plots/smith":629,"../scatter/marker_colorbar":945,"../scatter/select":949,"../scatter/style":951,"./attributes":1017,"./calc":1018,"./defaults":1019,"./format_labels":1020,"./hover":1021,"./plot":1023}],1023:[function(t,e,r){"use strict";var n=t("../scatter/plot"),i=t("../../constants/numerical").BADNUM,a=t("../../plots/smith/helpers").smith;e.exports=function(t,e,r){for(var o=e.layers.frontplot.select("g.scatterlayer"),s={xaxis:e.xaxis,yaxis:e.yaxis,plot:e.framework,layerClipId:e._hasClipOnAxisFalse?e.clipIds.forTraces:null},l=0;l"),o.hovertemplate=h.hovertemplate,a}function x(t,e){v.push(t._hovertitle+": "+e)}}},{"../scatter/hover":938}],1030:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../scatter/marker_colorbar"),formatLabels:t("./format_labels"),calc:t("./calc"),plot:t("./plot"),style:t("../scatter/style").style,styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover"),selectPoints:t("../scatter/select"),eventData:t("./event_data"),moduleType:"trace",name:"scatterternary",basePlotModule:t("../../plots/ternary"),categories:["ternary","symbols","showLegend","scatter-like"],meta:{}}},{"../../plots/ternary":634,"../scatter/marker_colorbar":945,"../scatter/select":949,"../scatter/style":951,"./attributes":1024,"./calc":1025,"./defaults":1026,"./event_data":1027,"./format_labels":1028,"./hover":1029,"./plot":1031}],1031:[function(t,e,r){"use strict";var n=t("../scatter/plot");e.exports=function(t,e,r){var i=e.plotContainer;i.select(".scatterlayer").selectAll("*").remove();var a={xaxis:e.xaxis,yaxis:e.yaxis,plot:i,layerClipId:e._hasClipOnAxisFalse?e.clipIdRelative:null},o=e.layers.frontplot.select("g.scatterlayer");n(t,a,r,o)}},{"../scatter/plot":948}],1032:[function(t,e,r){"use strict";var n=t("../scatter/attributes"),i=t("../../components/colorscale/attributes"),a=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,o=t("../../plots/template_attributes").hovertemplateAttrs,s=t("../scattergl/attributes"),l=t("../../plots/cartesian/constants").idRegex,c=t("../../plot_api/plot_template").templatedArray,u=t("../../lib/extend").extendFlat,f=n.marker,h=f.line,p=u(i("marker.line",{editTypeOverride:"calc"}),{width:u({},h.width,{editType:"calc"}),editType:"calc"}),d=u(i("marker"),{symbol:f.symbol,size:u({},f.size,{editType:"markerSize"}),sizeref:f.sizeref,sizemin:f.sizemin,sizemode:f.sizemode,opacity:f.opacity,colorbar:f.colorbar,line:p,editType:"calc"});function m(t){return{valType:"info_array",freeLength:!0,editType:"calc",items:{valType:"subplotid",regex:l[t],editType:"plot"}}}d.color.editType=d.cmin.editType=d.cmax.editType="style",e.exports={dimensions:c("dimension",{visible:{valType:"boolean",dflt:!0,editType:"calc"},label:{valType:"string",editType:"calc"},values:{valType:"data_array",editType:"calc+clearAxisTypes"},axis:{type:{valType:"enumerated",values:["linear","log","date","category"],editType:"calc+clearAxisTypes"},matches:{valType:"boolean",dflt:!1,editType:"calc"},editType:"calc+clearAxisTypes"},editType:"calc+clearAxisTypes"}),text:u({},s.text,{}),hovertext:u({},s.hovertext,{}),hovertemplate:o(),xhoverformat:a("x"),yhoverformat:a("y"),marker:d,xaxes:m("x"),yaxes:m("y"),diagonal:{visible:{valType:"boolean",dflt:!0,editType:"calc"},editType:"calc"},showupperhalf:{valType:"boolean",dflt:!0,editType:"calc"},showlowerhalf:{valType:"boolean",dflt:!0,editType:"calc"},selected:{marker:s.selected.marker,editType:"calc"},unselected:{marker:s.unselected.marker,editType:"calc"},opacity:s.opacity}},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plot_api/plot_template":543,"../../plots/cartesian/axis_format_attributes":557,"../../plots/cartesian/constants":561,"../../plots/template_attributes":633,"../scatter/attributes":927,"../scattergl/attributes":979}],1033:[function(t,e,r){"use strict";var n=t("../../registry"),i=t("../../components/grid");e.exports={moduleType:"trace",name:"splom",categories:["gl","regl","cartesian","symbols","showLegend","scatter-like"],attributes:t("./attributes"),supplyDefaults:t("./defaults"),colorbar:t("../scatter/marker_colorbar"),calc:t("./calc"),plot:t("./plot"),hoverPoints:t("./hover").hoverPoints,selectPoints:t("./select"),editStyle:t("./edit_style"),meta:{}},n.register(i)},{"../../components/grid":410,"../../registry":638,"../scatter/marker_colorbar":945,"./attributes":1032,"./calc":1035,"./defaults":1036,"./edit_style":1037,"./hover":1039,"./plot":1041,"./select":1043}],1034:[function(t,e,r){"use strict";var n=t("regl-line2d"),i=t("../../registry"),a=t("../../lib/prepare_regl"),o=t("../../plots/get_data").getModuleCalcData,s=t("../../plots/cartesian"),l=t("../../plots/cartesian/axis_ids").getFromId,c=t("../../plots/cartesian/axes").shouldShowZeroLine,u={};function f(t,e,r){for(var n=r.matrixOptions.data.length,i=e._visibleDims,a=r.viewOpts.ranges=new Array(n),o=0;oh?b.sizeAvg||Math.max(b.size,3):a(e,x),p=0;pa&&l||i-1,P=!0;if(o(x)||!!p.selectedpoints||C){var I=p._length;if(p.selectedpoints){m.selectBatch=p.selectedpoints;var O=p.selectedpoints,z={};for(l=0;l1&&(u=m[y-1],h=g[y-1],d=v[y-1]),e=0;eu?"-":"+")+"x")).replace("y",(f>h?"-":"+")+"y")).replace("z",(p>d?"-":"+")+"z");var L=function(){y=0,M=[],S=[],E=[]};(!y||y2?t.slice(1,e-1):2===e?[(t[0]+t[1])/2]:t}function p(t){var e=t.length;return 1===e?[.5,.5]:[t[1]-t[0],t[e-1]-t[e-2]]}function d(t,e){var r=t.fullSceneLayout,i=t.dataScale,u=e._len,f={};function d(t,e){var n=r[e],o=i[c[e]];return a.simpleMap(t,(function(t){return n.d2l(t)*o}))}if(f.vectors=l(d(e._u,"xaxis"),d(e._v,"yaxis"),d(e._w,"zaxis"),u),!u)return{positions:[],cells:[]};var m=d(e._Xs,"xaxis"),g=d(e._Ys,"yaxis"),v=d(e._Zs,"zaxis");if(f.meshgrid=[m,g,v],f.gridFill=e._gridFill,e._slen)f.startingPositions=l(d(e._startsX,"xaxis"),d(e._startsY,"yaxis"),d(e._startsZ,"zaxis"));else{for(var y=g[0],x=h(m),b=h(v),_=new Array(x.length*b.length),w=0,T=0;T=0};v?(r=Math.min(g.length,x.length),l=function(t){return A(g[t])&&M(t)},f=function(t){return String(g[t])}):(r=Math.min(y.length,x.length),l=function(t){return A(y[t])&&M(t)},f=function(t){return String(y[t])}),_&&(r=Math.min(r,b.length));for(var S=0;S1){for(var P=a.randstr(),I=0;I"),name:A||z("name")?y.name:void 0,color:k("hoverlabel.bgcolor")||x.color,borderColor:k("hoverlabel.bordercolor"),fontFamily:k("hoverlabel.font.family"),fontSize:k("hoverlabel.font.size"),fontColor:k("hoverlabel.font.color"),nameLength:k("hoverlabel.namelength"),textAlign:k("hoverlabel.align"),hovertemplate:A,hovertemplateLabels:P,eventData:l};g&&(F.x0=E-i.rInscribed*i.rpx1,F.x1=E+i.rInscribed*i.rpx1,F.idealAlign=i.pxmid[0]<0?"left":"right"),v&&(F.x=E,F.idealAlign=E<0?"left":"right");var B=[];o.loneHover(F,{container:a._hoverlayer.node(),outerContainer:a._paper.node(),gd:r,inOut_bbox:B}),l[0].bbox=B[0],d._hasHoverLabel=!0}if(v){var N=t.select("path.surface");h.styleOne(N,i,y,{hovered:!0})}d._hasHoverEvent=!0,r.emit("plotly_hover",{points:l||[f(i,y,h.eventDataKeys)],event:n.event})}})),t.on("mouseout",(function(e){var i=r._fullLayout,a=r._fullData[d.index],s=n.select(this).datum();if(d._hasHoverEvent&&(e.originalEvent=n.event,r.emit("plotly_unhover",{points:[f(s,a,h.eventDataKeys)],event:n.event}),d._hasHoverEvent=!1),d._hasHoverLabel&&(o.loneUnhover(i._hoverlayer.node()),d._hasHoverLabel=!1),v){var l=t.select("path.surface");h.styleOne(l,s,a,{hovered:!1})}})),t.on("click",(function(t){var e=r._fullLayout,a=r._fullData[d.index],s=g&&(c.isHierarchyRoot(t)||c.isLeaf(t)),u=c.getPtId(t),p=c.isEntry(t)?c.findEntryWithChild(m,u):c.findEntryWithLevel(m,u),v=c.getPtId(p),y={points:[f(t,a,h.eventDataKeys)],event:n.event};s||(y.nextLevel=v);var x=l.triggerHandler(r,"plotly_"+d.type+"click",y);if(!1!==x&&e.hovermode&&(r._hoverdata=[f(t,a,h.eventDataKeys)],o.click(r,n.event)),!s&&!1!==x&&!r._dragging&&!r._transitioning){i.call("_storeDirectGUIEdit",a,e._tracePreGUI[a.uid],{level:a.level});var b={data:[{level:v}],traces:[d.index]},_={frame:{redraw:!1,duration:h.transitionTime},transition:{duration:h.transitionTime,easing:h.transitionEasing},mode:"immediate",fromcurrent:!0};o.loneUnhover(e._hoverlayer.node()),i.call("animate",r,b,_)}}))}},{"../../components/fx":406,"../../components/fx/helpers":402,"../../lib":503,"../../lib/events":492,"../../registry":638,"../pie/helpers":906,"./helpers":1055,"@plotly/d3":58}],1055:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("../../components/color"),a=t("../../lib/setcursor"),o=t("../pie/helpers");function s(t){return t.data.data.pid}r.findEntryWithLevel=function(t,e){var n;return e&&t.eachAfter((function(t){if(r.getPtId(t)===e)return n=t.copy()})),n||t},r.findEntryWithChild=function(t,e){var n;return t.eachAfter((function(t){for(var i=t.children||[],a=0;a0)},r.getMaxDepth=function(t){return t.maxdepth>=0?t.maxdepth:1/0},r.isHeader=function(t,e){return!(r.isLeaf(t)||t.depth===e._maxDepth-1)},r.getParent=function(t,e){return r.findEntryWithLevel(t,s(e))},r.listPath=function(t,e){var n=t.parent;if(!n)return[];var i=e?[n.data[e]]:[n];return r.listPath(n,e).concat(i)},r.getPath=function(t){return r.listPath(t,"label").join("/")+"/"},r.formatValue=o.formatPieValue,r.formatPercent=function(t,e){var r=n.formatPercent(t,0);return"0%"===r&&(r=o.formatPiePercent(t,e)),r}},{"../../components/color":366,"../../lib":503,"../../lib/setcursor":524,"../pie/helpers":906}],1056:[function(t,e,r){"use strict";e.exports={moduleType:"trace",name:"sunburst",basePlotModule:t("./base_plot"),categories:[],animatable:!0,attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc").calc,crossTraceCalc:t("./calc").crossTraceCalc,plot:t("./plot").plot,style:t("./style").style,colorbar:t("../scatter/marker_colorbar"),meta:{}}},{"../scatter/marker_colorbar":945,"./attributes":1049,"./base_plot":1050,"./calc":1051,"./defaults":1053,"./layout_attributes":1057,"./layout_defaults":1058,"./plot":1059,"./style":1060}],1057:[function(t,e,r){"use strict";e.exports={sunburstcolorway:{valType:"colorlist",editType:"calc"},extendsunburstcolors:{valType:"boolean",dflt:!0,editType:"calc"}}},{}],1058:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e){function r(r,a){return n.coerce(t,e,i,r,a)}r("sunburstcolorway",e.colorway),r("extendsunburstcolors")}},{"../../lib":503,"./layout_attributes":1057}],1059:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("d3-hierarchy"),a=t("d3-interpolate").interpolate,o=t("../../components/drawing"),s=t("../../lib"),l=t("../../lib/svg_text_utils"),c=t("../bar/uniform_text"),u=c.recordMinTextSize,f=c.clearMinTextSize,h=t("../pie/plot"),p=t("../pie/helpers").getRotationAngle,d=h.computeTransform,m=h.transformInsideText,g=t("./style").styleOne,v=t("../bar/style").resizeText,y=t("./fx"),x=t("./constants"),b=t("./helpers");function _(t,e,c,f){var h=t._fullLayout,v=!h.uniformtext.mode&&b.hasTransition(f),_=n.select(c).selectAll("g.slice"),T=e[0],k=T.trace,A=T.hierarchy,M=b.findEntryWithLevel(A,k.level),S=b.getMaxDepth(k),E=h._size,L=k.domain,C=E.w*(L.x[1]-L.x[0]),P=E.h*(L.y[1]-L.y[0]),I=.5*Math.min(C,P),O=T.cx=E.l+E.w*(L.x[1]+L.x[0])/2,z=T.cy=E.t+E.h*(1-L.y[0])-P/2;if(!M)return _.remove();var D=null,R={};v&&_.each((function(t){R[b.getPtId(t)]={rpx0:t.rpx0,rpx1:t.rpx1,x0:t.x0,x1:t.x1,transform:t.transform},!D&&b.isEntry(t)&&(D=t)}));var F=function(t){return i.partition().size([2*Math.PI,t.height+1])(t)}(M).descendants(),B=M.height+1,N=0,j=S;T.hasMultipleRoots&&b.isHierarchyRoot(M)&&(F=F.slice(1),B-=1,N=1,j+=1),F=F.filter((function(t){return t.y1<=j}));var U=p(k.rotation);U&&F.forEach((function(t){t.x0+=U,t.x1+=U}));var V=Math.min(B,S),H=function(t){return(t-N)/V*I},q=function(t,e){return[t*Math.cos(e),-t*Math.sin(e)]},G=function(t){return s.pathAnnulus(t.rpx0,t.rpx1,t.x0,t.x1,O,z)},Y=function(t){return O+w(t)[0]*(t.transform.rCenter||0)+(t.transform.x||0)},W=function(t){return z+w(t)[1]*(t.transform.rCenter||0)+(t.transform.y||0)};(_=_.data(F,b.getPtId)).enter().append("g").classed("slice",!0),v?_.exit().transition().each((function(){var t=n.select(this);t.select("path.surface").transition().attrTween("d",(function(t){var e=function(t){var e,r=b.getPtId(t),n=R[r],i=R[b.getPtId(M)];if(i){var o=(t.x1>i.x1?2*Math.PI:0)+U;e=t.rpx1X?2*Math.PI:0)+U;e={x0:i,x1:i}}else e={rpx0:I,rpx1:I},s.extendFlat(e,K(t));else e={rpx0:0,rpx1:0};else e={x0:U,x1:U};return a(e,n)}(t);return function(t){return G(e(t))}})):f.attr("d",G),c.call(y,M,t,e,{eventDataKeys:x.eventDataKeys,transitionTime:x.CLICK_TRANSITION_TIME,transitionEasing:x.CLICK_TRANSITION_EASING}).call(b.setSliceCursor,t,{hideOnRoot:!0,hideOnLeaves:!0,isTransitioning:t._transitioning}),f.call(g,i,k);var p=s.ensureSingle(c,"g","slicetext"),_=s.ensureSingle(p,"text","",(function(t){t.attr("data-notex",1)})),w=s.ensureUniformFontSize(t,b.determineTextFont(k,i,h.font));_.text(r.formatSliceLabel(i,M,k,e,h)).classed("slicetext",!0).attr("text-anchor","middle").call(o.font,w).call(l.convertToTspans,t);var A=o.bBox(_.node());i.transform=m(A,i,T),i.transform.targetX=Y(i),i.transform.targetY=W(i);var S=function(t,e){var r=t.transform;return d(r,e),r.fontSize=w.size,u(k.type,r,h),s.getTextTransform(r)};v?_.transition().attrTween("transform",(function(t){var e=function(t){var e,r=R[b.getPtId(t)],n=t.transform;if(r)e=r;else if(e={rpx1:t.rpx1,transform:{textPosAngle:n.textPosAngle,scale:0,rotate:n.rotate,rCenter:n.rCenter,x:n.x,y:n.y}},D)if(t.parent)if(X){var i=t.x1>X?2*Math.PI:0;e.x0=e.x1=i}else s.extendFlat(e,K(t));else e.x0=e.x1=U;else e.x0=e.x1=U;var o=a(e.transform.textPosAngle,t.transform.textPosAngle),l=a(e.rpx1,t.rpx1),c=a(e.x0,t.x0),f=a(e.x1,t.x1),p=a(e.transform.scale,n.scale),d=a(e.transform.rotate,n.rotate),m=0===n.rCenter?3:0===e.transform.rCenter?1/3:1,g=a(e.transform.rCenter,n.rCenter);return function(t){var e=l(t),r=c(t),i=f(t),a=function(t){return g(Math.pow(t,m))}(t),s={pxmid:q(e,(r+i)/2),rpx1:e,transform:{textPosAngle:o(t),rCenter:a,x:n.x,y:n.y}};return u(k.type,n,h),{transform:{targetX:Y(s),targetY:W(s),scale:p(t),rotate:d(t),rCenter:a}}}}(t);return function(t){return S(e(t),A)}})):_.attr("transform",S(i,A))}))}function w(t){return e=t.rpx1,r=t.transform.textPosAngle,[e*Math.sin(r),-e*Math.cos(r)];var e,r}r.plot=function(t,e,r,i){var a,o,s=t._fullLayout,l=s._sunburstlayer,c=!r,u=!s.uniformtext.mode&&b.hasTransition(r);(f("sunburst",s),(a=l.selectAll("g.trace.sunburst").data(e,(function(t){return t[0].trace.uid}))).enter().append("g").classed("trace",!0).classed("sunburst",!0).attr("stroke-linejoin","round"),a.order(),u)?(i&&(o=i()),n.transition().duration(r.duration).ease(r.easing).each("end",(function(){o&&o()})).each("interrupt",(function(){o&&o()})).each((function(){l.selectAll("g.trace").each((function(e){_(t,e,this,r)}))}))):(a.each((function(e){_(t,e,this,r)})),s.uniformtext.mode&&v(t,s._sunburstlayer.selectAll(".trace"),"sunburst"));c&&a.exit().remove()},r.formatSliceLabel=function(t,e,r,n,i){var a=r.texttemplate,o=r.textinfo;if(!(a||o&&"none"!==o))return"";var l=i.separators,c=n[0],u=t.data.data,f=c.hierarchy,h=b.isHierarchyRoot(t),p=b.getParent(f,t),d=b.getValue(t);if(!a){var m,g=o.split("+"),v=function(t){return-1!==g.indexOf(t)},y=[];if(v("label")&&u.label&&y.push(u.label),u.hasOwnProperty("v")&&v("value")&&y.push(b.formatValue(u.v,l)),!h){v("current path")&&y.push(b.getPath(t.data));var x=0;v("percent parent")&&x++,v("percent entry")&&x++,v("percent root")&&x++;var _=x>1;if(x){var w,T=function(t){m=b.formatPercent(w,l),_&&(m+=" of "+t),y.push(m)};v("percent parent")&&!h&&(w=d/b.getValue(p),T("parent")),v("percent entry")&&(w=d/b.getValue(e),T("entry")),v("percent root")&&(w=d/b.getValue(f),T("root"))}}return v("text")&&(m=s.castOption(r,u.i,"text"),s.isValidTextValue(m)&&y.push(m)),y.join("
    ")}var k=s.castOption(r,u.i,"texttemplate");if(!k)return"";var A={};u.label&&(A.label=u.label),u.hasOwnProperty("v")&&(A.value=u.v,A.valueLabel=b.formatValue(u.v,l)),A.currentPath=b.getPath(t.data),h||(A.percentParent=d/b.getValue(p),A.percentParentLabel=b.formatPercent(A.percentParent,l),A.parent=b.getPtLabel(p)),A.percentEntry=d/b.getValue(e),A.percentEntryLabel=b.formatPercent(A.percentEntry,l),A.entry=b.getPtLabel(e),A.percentRoot=d/b.getValue(f),A.percentRootLabel=b.formatPercent(A.percentRoot,l),A.root=b.getPtLabel(f),u.hasOwnProperty("color")&&(A.color=u.color);var M=s.castOption(r,u.i,"text");return(s.isValidTextValue(M)||""===M)&&(A.text=M),A.customdata=s.castOption(r,u.i,"customdata"),s.texttemplateString(k,A,i._d3locale,A,r._meta||{})}},{"../../components/drawing":388,"../../lib":503,"../../lib/svg_text_utils":529,"../bar/style":662,"../bar/uniform_text":664,"../pie/helpers":906,"../pie/plot":910,"./constants":1052,"./fx":1054,"./helpers":1055,"./style":1060,"@plotly/d3":58,"d3-hierarchy":115,"d3-interpolate":116}],1060:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../components/color"),a=t("../../lib"),o=t("../bar/uniform_text").resizeText;function s(t,e,r){var n=e.data.data,o=!e.children,s=n.i,l=a.castOption(r,s,"marker.line.color")||i.defaultLine,c=a.castOption(r,s,"marker.line.width")||0;t.style("stroke-width",c).call(i.fill,n.color).call(i.stroke,l).style("opacity",o?r.leaf.opacity:null)}e.exports={style:function(t){var e=t._fullLayout._sunburstlayer.selectAll(".trace");o(t,e,"sunburst"),e.each((function(t){var e=n.select(this),r=t[0].trace;e.style("opacity",r.opacity),e.selectAll("path.surface").each((function(t){n.select(this).call(s,t,r)}))}))},styleOne:s}},{"../../components/color":366,"../../lib":503,"../bar/uniform_text":664,"@plotly/d3":58}],1061:[function(t,e,r){"use strict";var n=t("../../components/color"),i=t("../../components/colorscale/attributes"),a=t("../../plots/cartesian/axis_format_attributes").axisHoverFormat,o=t("../../plots/template_attributes").hovertemplateAttrs,s=t("../../plots/attributes"),l=t("../../lib/extend").extendFlat,c=t("../../plot_api/edit_types").overrideAll;function u(t){return{show:{valType:"boolean",dflt:!1},start:{valType:"number",dflt:null,editType:"plot"},end:{valType:"number",dflt:null,editType:"plot"},size:{valType:"number",dflt:null,min:0,editType:"plot"},project:{x:{valType:"boolean",dflt:!1},y:{valType:"boolean",dflt:!1},z:{valType:"boolean",dflt:!1}},color:{valType:"color",dflt:n.defaultLine},usecolormap:{valType:"boolean",dflt:!1},width:{valType:"number",min:1,max:16,dflt:2},highlight:{valType:"boolean",dflt:!0},highlightcolor:{valType:"color",dflt:n.defaultLine},highlightwidth:{valType:"number",min:1,max:16,dflt:2}}}var f=e.exports=c(l({z:{valType:"data_array"},x:{valType:"data_array"},y:{valType:"data_array"},text:{valType:"string",dflt:"",arrayOk:!0},hovertext:{valType:"string",dflt:"",arrayOk:!0},hovertemplate:o(),xhoverformat:a("x"),yhoverformat:a("y"),zhoverformat:a("z"),connectgaps:{valType:"boolean",dflt:!1,editType:"calc"},surfacecolor:{valType:"data_array"}},i("",{colorAttr:"z or surfacecolor",showScaleDflt:!0,autoColorDflt:!1,editTypeOverride:"calc"}),{contours:{x:u(),y:u(),z:u()},hidesurface:{valType:"boolean",dflt:!1},lightposition:{x:{valType:"number",min:-1e5,max:1e5,dflt:10},y:{valType:"number",min:-1e5,max:1e5,dflt:1e4},z:{valType:"number",min:-1e5,max:1e5,dflt:0}},lighting:{ambient:{valType:"number",min:0,max:1,dflt:.8},diffuse:{valType:"number",min:0,max:1,dflt:.8},specular:{valType:"number",min:0,max:2,dflt:.05},roughness:{valType:"number",min:0,max:1,dflt:.5},fresnel:{valType:"number",min:0,max:5,dflt:.2}},opacity:{valType:"number",min:0,max:1,dflt:1},opacityscale:{valType:"any",editType:"calc"},_deprecated:{zauto:l({},i.zauto,{}),zmin:l({},i.zmin,{}),zmax:l({},i.zmax,{})},hoverinfo:l({},s.hoverinfo),showlegend:l({},s.showlegend,{dflt:!1})}),"calc","nested");f.x.editType=f.y.editType=f.z.editType="calc+clearAxisTypes",f.transforms=void 0},{"../../components/color":366,"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plot_api/edit_types":536,"../../plots/attributes":550,"../../plots/cartesian/axis_format_attributes":557,"../../plots/template_attributes":633}],1062:[function(t,e,r){"use strict";var n=t("../../components/colorscale/calc");e.exports=function(t,e){e.surfacecolor?n(t,e,{vals:e.surfacecolor,containerStr:"",cLetter:"c"}):n(t,e,{vals:e.z,containerStr:"",cLetter:"c"})}},{"../../components/colorscale/calc":374}],1063:[function(t,e,r){"use strict";var n=t("../../../stackgl_modules").gl_surface3d,i=t("../../../stackgl_modules").ndarray,a=t("../../../stackgl_modules").ndarray_linear_interpolate.d2,o=t("../heatmap/interp2d"),s=t("../heatmap/find_empties"),l=t("../../lib").isArrayOrTypedArray,c=t("../../lib/gl_format_color").parseColorScale,u=t("../../lib/str2rgbarray"),f=t("../../components/colorscale").extractOpts;function h(t,e,r){this.scene=t,this.uid=r,this.surface=e,this.data=null,this.showContour=[!1,!1,!1],this.contourStart=[null,null,null],this.contourEnd=[null,null,null],this.contourSize=[0,0,0],this.minValues=[1/0,1/0,1/0],this.maxValues=[-1/0,-1/0,-1/0],this.dataScaleX=1,this.dataScaleY=1,this.refineData=!0,this.objectOffset=[0,0,0]}var p=h.prototype;p.getXat=function(t,e,r,n){var i=l(this.data.x)?l(this.data.x[0])?this.data.x[e][t]:this.data.x[t]:t;return void 0===r?i:n.d2l(i,0,r)},p.getYat=function(t,e,r,n){var i=l(this.data.y)?l(this.data.y[0])?this.data.y[e][t]:this.data.y[e]:e;return void 0===r?i:n.d2l(i,0,r)},p.getZat=function(t,e,r,n){var i=this.data.z[e][t];return null===i&&this.data.connectgaps&&this.data._interpolatedZ&&(i=this.data._interpolatedZ[e][t]),void 0===r?i:n.d2l(i,0,r)},p.handlePick=function(t){if(t.object===this.surface){var e=(t.data.index[0]-1)/this.dataScaleX-1,r=(t.data.index[1]-1)/this.dataScaleY-1,n=Math.max(Math.min(Math.round(e),this.data.z[0].length-1),0),i=Math.max(Math.min(Math.round(r),this.data._ylength-1),0);t.index=[n,i],t.traceCoordinate=[this.getXat(n,i),this.getYat(n,i),this.getZat(n,i)],t.dataCoordinate=[this.getXat(n,i,this.data.xcalendar,this.scene.fullSceneLayout.xaxis),this.getYat(n,i,this.data.ycalendar,this.scene.fullSceneLayout.yaxis),this.getZat(n,i,this.data.zcalendar,this.scene.fullSceneLayout.zaxis)];for(var a=0;a<3;a++){var o=t.dataCoordinate[a];null!=o&&(t.dataCoordinate[a]*=this.scene.dataScale[a])}var s=this.data.hovertext||this.data.text;return Array.isArray(s)&&s[i]&&void 0!==s[i][n]?t.textLabel=s[i][n]:t.textLabel=s||"",t.data.dataCoordinate=t.dataCoordinate.slice(),this.surface.highlight(t.data),this.scene.glplot.spikes.position=t.dataCoordinate,!0}};var d=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999];function m(t,e){if(t0){r=d[n];break}return r}function y(t,e){if(!(t<1||e<1)){for(var r=g(t),n=g(e),i=1,a=0;a_;)r--,r/=v(r),++r1?n:1},p.refineCoords=function(t){for(var e=this.dataScaleX,r=this.dataScaleY,n=t[0].shape[0],a=t[0].shape[1],o=0|Math.floor(t[0].shape[0]*e+1),s=0|Math.floor(t[0].shape[1]*r+1),l=1+n+1,c=1+a+1,u=i(new Float32Array(l*c),[l,c]),f=[1/e,0,0,0,1/r,0,0,0,1],h=0;h0&&null!==this.contourStart[t]&&null!==this.contourEnd[t]&&this.contourEnd[t]>this.contourStart[t]))for(i[t]=!0,e=this.contourStart[t];ea&&(this.minValues[e]=a),this.maxValues[e]",maxDimensionCount:60,overdrag:45,releaseTransitionDuration:120,releaseTransitionEase:"cubic-out",scrollbarCaptureWidth:18,scrollbarHideDelay:1e3,scrollbarHideDuration:1e3,scrollbarOffset:5,scrollbarWidth:8,transitionDuration:100,transitionEase:"cubic-out",uplift:5,wrapSpacer:" ",wrapSplitCharacter:" ",cn:{table:"table",tableControlView:"table-control-view",scrollBackground:"scroll-background",yColumn:"y-column",columnBlock:"column-block",scrollAreaClip:"scroll-area-clip",scrollAreaClipRect:"scroll-area-clip-rect",columnBoundary:"column-boundary",columnBoundaryClippath:"column-boundary-clippath",columnBoundaryRect:"column-boundary-rect",columnCells:"column-cells",columnCell:"column-cell",cellRect:"cell-rect",cellText:"cell-text",cellTextHolder:"cell-text-holder",scrollbarKit:"scrollbar-kit",scrollbar:"scrollbar",scrollbarSlider:"scrollbar-slider",scrollbarGlyph:"scrollbar-glyph",scrollbarCaptureZone:"scrollbar-capture-zone"}}},{}],1070:[function(t,e,r){"use strict";var n=t("./constants"),i=t("../../lib/extend").extendFlat,a=t("fast-isnumeric");function o(t){if(Array.isArray(t)){for(var e=0,r=0;r=e||c===t.length-1)&&(n[i]=o,o.key=l++,o.firstRowIndex=s,o.lastRowIndex=c,o={firstRowIndex:null,lastRowIndex:null,rows:[]},i+=a,s=c+1,a=0);return n}e.exports=function(t,e){var r=l(e.cells.values),p=function(t){return t.slice(e.header.values.length,t.length)},d=l(e.header.values);d.length&&!d[0].length&&(d[0]=[""],d=l(d));var m=d.concat(p(r).map((function(){return c((d[0]||[""]).length)}))),g=e.domain,v=Math.floor(t._fullLayout._size.w*(g.x[1]-g.x[0])),y=Math.floor(t._fullLayout._size.h*(g.y[1]-g.y[0])),x=e.header.values.length?m[0].map((function(){return e.header.height})):[n.emptyHeaderHeight],b=r.length?r[0].map((function(){return e.cells.height})):[],_=x.reduce(s,0),w=h(b,y-_+n.uplift),T=f(h(x,_),[]),k=f(w,T),A={},M=e._fullInput.columnorder.concat(p(r.map((function(t,e){return e})))),S=m.map((function(t,r){var n=Array.isArray(e.columnwidth)?e.columnwidth[Math.min(r,e.columnwidth.length-1)]:e.columnwidth;return a(n)?Number(n):1})),E=S.reduce(s,0);S=S.map((function(t){return t/E*v}));var L=Math.max(o(e.header.line.width),o(e.cells.line.width)),C={key:e.uid+t._context.staticPlot,translateX:g.x[0]*t._fullLayout._size.w,translateY:t._fullLayout._size.h*(1-g.y[1]),size:t._fullLayout._size,width:v,maxLineWidth:L,height:y,columnOrder:M,groupHeight:y,rowBlocks:k,headerRowBlocks:T,scrollY:0,cells:i({},e.cells,{values:r}),headerCells:i({},e.header,{values:m}),gdColumns:m.map((function(t){return t[0]})),gdColumnsOriginalOrder:m.map((function(t){return t[0]})),prevPages:[0,0],scrollbarState:{scrollbarScrollInProgress:!1},columns:m.map((function(t,e){var r=A[t];return A[t]=(r||0)+1,{key:t+"__"+A[t],label:t,specIndex:e,xIndex:M[e],xScale:u,x:void 0,calcdata:void 0,columnWidth:S[e]}}))};return C.columns.forEach((function(t){t.calcdata=C,t.x=u(t)})),C}},{"../../lib/extend":493,"./constants":1069,"fast-isnumeric":190}],1071:[function(t,e,r){"use strict";var n=t("../../lib/extend").extendFlat;r.splitToPanels=function(t){var e=[0,0],r=n({},t,{key:"header",type:"header",page:0,prevPages:e,currentRepaint:[null,null],dragHandle:!0,values:t.calcdata.headerCells.values[t.specIndex],rowBlocks:t.calcdata.headerRowBlocks,calcdata:n({},t.calcdata,{cells:t.calcdata.headerCells})});return[n({},t,{key:"cells1",type:"cells",page:0,prevPages:e,currentRepaint:[null,null],dragHandle:!1,values:t.calcdata.cells.values[t.specIndex],rowBlocks:t.calcdata.rowBlocks}),n({},t,{key:"cells2",type:"cells",page:1,prevPages:e,currentRepaint:[null,null],dragHandle:!1,values:t.calcdata.cells.values[t.specIndex],rowBlocks:t.calcdata.rowBlocks}),r]},r.splitToCells=function(t){var e=function(t){var e=t.rowBlocks[t.page],r=e?e.rows[0].rowIndex:0,n=e?r+e.rows.length:0;return[r,n]}(t);return(t.values||[]).slice(e[0],e[1]).map((function(r,n){return{keyWithinBlock:n+("string"==typeof r&&r.match(/[<$&> ]/)?"_keybuster_"+Math.random():""),key:e[0]+n,column:t,calcdata:t.calcdata,page:t.page,rowBlocks:t.rowBlocks,value:r}}))}},{"../../lib/extend":493}],1072:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes"),a=t("../../plots/domain").defaults;e.exports=function(t,e,r,o){function s(r,a){return n.coerce(t,e,i,r,a)}a(e,o,s),s("columnwidth"),s("header.values"),s("header.format"),s("header.align"),s("header.prefix"),s("header.suffix"),s("header.height"),s("header.line.width"),s("header.line.color"),s("header.fill.color"),n.coerceFont(s,"header.font",n.extendFlat({},o.font)),function(t,e){for(var r=t.columnorder||[],n=t.header.values.length,i=r.slice(0,n),a=i.slice().sort((function(t,e){return t-e})),o=i.map((function(t){return a.indexOf(t)})),s=o.length;s/i),l=!o||s;t.mayHaveMarkup=o&&i.match(/[<&>]/);var c,u="string"==typeof(c=i)&&c.match(n.latexCheck);t.latex=u;var f,h,p=u?"":T(t.calcdata.cells.prefix,e,r)||"",d=u?"":T(t.calcdata.cells.suffix,e,r)||"",m=u?null:T(t.calcdata.cells.format,e,r)||null,g=p+(m?a(m)(t.value):t.value)+d;if(t.wrappingNeeded=!t.wrapped&&!l&&!u&&(f=w(g)),t.cellHeightMayIncrease=s||u||t.mayHaveMarkup||(void 0===f?w(g):f),t.needsConvertToTspans=t.mayHaveMarkup||t.wrappingNeeded||t.latex,t.wrappingNeeded){var v=(" "===n.wrapSplitCharacter?g.replace(/i&&n.push(a),i+=l}return n}(i,l,s);1===c.length&&(c[0]===i.length-1?c.unshift(c[0]-1):c.push(c[0]+1)),c[0]%2&&c.reverse(),e.each((function(t,e){t.page=c[e],t.scrollY=l})),e.attr("transform",(function(t){var e=D(t.rowBlocks,t.page)-t.scrollY;return u(0,e)})),t&&(C(t,r,e,c,n.prevPages,n,0),C(t,r,e,c,n.prevPages,n,1),x(r,t))}}function L(t,e,r,a){return function(o){var s=o.calcdata?o.calcdata:o,l=e.filter((function(t){return s.key===t.key})),c=r||s.scrollbarState.dragMultiplier,u=s.scrollY;s.scrollY=void 0===a?s.scrollY+c*i.event.dy:a;var f=l.selectAll("."+n.cn.yColumn).selectAll("."+n.cn.columnBlock).filter(A);return E(t,f,l),s.scrollY===u}}function C(t,e,r,n,i,a,o){n[o]!==i[o]&&(clearTimeout(a.currentRepaint[o]),a.currentRepaint[o]=setTimeout((function(){var a=r.filter((function(t,e){return e===o&&n[e]!==i[e]}));b(t,e,a,r),i[o]=n[o]})))}function P(t,e,r,a){return function(){var o=i.select(e.parentNode);o.each((function(t){var e=t.fragments;o.selectAll("tspan.line").each((function(t,r){e[r].width=this.getComputedTextLength()}));var r,i,a=e[e.length-1].width,s=e.slice(0,-1),l=[],c=0,u=t.column.columnWidth-2*n.cellPad;for(t.value="";s.length;)c+(i=(r=s.shift()).width+a)>u&&(t.value+=l.join(n.wrapSpacer)+n.lineBreaker,l=[],c=0),l.push(r.text),c+=i;c&&(t.value+=l.join(n.wrapSpacer)),t.wrapped=!0})),o.selectAll("tspan.line").remove(),_(o.select("."+n.cn.cellText),r,t,a),i.select(e.parentNode.parentNode).call(z)}}function I(t,e,r,a,o){return function(){if(!o.settledY){var s=i.select(e.parentNode),l=B(o),c=o.key-l.firstRowIndex,f=l.rows[c].rowHeight,h=o.cellHeightMayIncrease?e.parentNode.getBoundingClientRect().height+2*n.cellPad:f,p=Math.max(h,f);p-l.rows[c].rowHeight&&(l.rows[c].rowHeight=p,t.selectAll("."+n.cn.columnCell).call(z),E(null,t.filter(A),0),x(r,a,!0)),s.attr("transform",(function(){var t=this.parentNode.getBoundingClientRect(),e=i.select(this.parentNode).select("."+n.cn.cellRect).node().getBoundingClientRect(),r=this.transform.baseVal.consolidate(),a=e.top-t.top+(r?r.matrix.f:n.cellPad);return u(O(o,i.select(this.parentNode).select("."+n.cn.cellTextHolder).node().getBoundingClientRect().width),a)})),o.settledY=!0}}}function O(t,e){switch(t.align){case"left":return n.cellPad;case"right":return t.column.columnWidth-(e||0)-n.cellPad;case"center":return(t.column.columnWidth-(e||0))/2;default:return n.cellPad}}function z(t){t.attr("transform",(function(t){var e=t.rowBlocks[0].auxiliaryBlocks.reduce((function(t,e){return t+R(e,1/0)}),0),r=R(B(t),t.key);return u(0,r+e)})).selectAll("."+n.cn.cellRect).attr("height",(function(t){return(e=B(t),r=t.key,e.rows[r-e.firstRowIndex]).rowHeight;var e,r}))}function D(t,e){for(var r=0,n=e-1;n>=0;n--)r+=F(t[n]);return r}function R(t,e){for(var r=0,n=0;n","<","|","/","\\"],dflt:">",editType:"plot"},thickness:{valType:"number",min:12,editType:"plot"},textfont:u({},s.textfont,{}),editType:"calc"},text:s.text,textinfo:l.textinfo,texttemplate:i({editType:"plot"},{keys:c.eventDataKeys.concat(["label","value"])}),hovertext:s.hovertext,hoverinfo:l.hoverinfo,hovertemplate:n({},{keys:c.eventDataKeys}),textfont:s.textfont,insidetextfont:s.insidetextfont,outsidetextfont:u({},s.outsidetextfont,{}),textposition:{valType:"enumerated",values:["top left","top center","top right","middle left","middle center","middle right","bottom left","bottom center","bottom right"],dflt:"top left",editType:"plot"},sort:s.sort,root:l.root,domain:o({name:"treemap",trace:!0,editType:"calc"})}},{"../../components/colorscale/attributes":373,"../../lib/extend":493,"../../plots/domain":584,"../../plots/template_attributes":633,"../pie/attributes":901,"../sunburst/attributes":1049,"./constants":1078}],1076:[function(t,e,r){"use strict";var n=t("../../plots/plots");r.name="treemap",r.plot=function(t,e,i,a){n.plotBasePlot(r.name,t,e,i,a)},r.clean=function(t,e,i,a){n.cleanBasePlot(r.name,t,e,i,a)}},{"../../plots/plots":619}],1077:[function(t,e,r){"use strict";var n=t("../sunburst/calc");r.calc=function(t,e){return n.calc(t,e)},r.crossTraceCalc=function(t){return n._runCrossTraceCalc("treemap",t)}},{"../sunburst/calc":1051}],1078:[function(t,e,r){"use strict";e.exports={CLICK_TRANSITION_TIME:750,CLICK_TRANSITION_EASING:"poly",eventDataKeys:["currentPath","root","entry","percentRoot","percentEntry","percentParent"],gapWithPathbar:1}},{}],1079:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./attributes"),a=t("../../components/color"),o=t("../../plots/domain").defaults,s=t("../bar/defaults").handleText,l=t("../bar/constants").TEXTPAD,c=t("../../components/colorscale"),u=c.hasColorscale,f=c.handleDefaults;e.exports=function(t,e,r,c){function h(r,a){return n.coerce(t,e,i,r,a)}var p=h("labels"),d=h("parents");if(p&&p.length&&d&&d.length){var m=h("values");m&&m.length?h("branchvalues"):h("count"),h("level"),h("maxdepth"),"squarify"===h("tiling.packing")&&h("tiling.squarifyratio"),h("tiling.flip"),h("tiling.pad");var g=h("text");h("texttemplate"),e.texttemplate||h("textinfo",Array.isArray(g)?"text+label":"label"),h("hovertext"),h("hovertemplate");var v=h("pathbar.visible");s(t,e,c,h,"auto",{hasPathbar:v,moduleHasSelected:!1,moduleHasUnselected:!1,moduleHasConstrain:!1,moduleHasCliponaxis:!1,moduleHasTextangle:!1,moduleHasInsideanchor:!1}),h("textposition");var y=-1!==e.textposition.indexOf("bottom");h("marker.line.width")&&h("marker.line.color",c.paper_bgcolor);var x=h("marker.colors");(e._hasColorscale=u(t,"marker","colors")||(t.marker||{}).coloraxis)?f(t,e,c,h,{prefix:"marker.",cLetter:"c"}):h("marker.depthfade",!(x||[]).length);var b=2*e.textfont.size;h("marker.pad.t",y?b/4:b),h("marker.pad.l",b/4),h("marker.pad.r",b/4),h("marker.pad.b",y?b:b/4),e._hovered={marker:{line:{width:2,color:a.contrast(c.paper_bgcolor)}}},v&&(h("pathbar.thickness",e.pathbar.textfont.size+2*l),h("pathbar.side"),h("pathbar.edgeshape")),h("sort"),h("root.color"),o(e,c,h),e._length=null}else e.visible=!1}},{"../../components/color":366,"../../components/colorscale":378,"../../lib":503,"../../plots/domain":584,"../bar/constants":650,"../bar/defaults":652,"./attributes":1075}],1080:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../sunburst/helpers"),a=t("../bar/uniform_text").clearMinTextSize,o=t("../bar/style").resizeText,s=t("./plot_one");e.exports=function(t,e,r,l,c){var u,f,h=c.type,p=c.drawDescendants,d=t._fullLayout,m=d["_"+h+"layer"],g=!r;(a(h,d),(u=m.selectAll("g.trace."+h).data(e,(function(t){return t[0].trace.uid}))).enter().append("g").classed("trace",!0).classed(h,!0),u.order(),!d.uniformtext.mode&&i.hasTransition(r))?(l&&(f=l()),n.transition().duration(r.duration).ease(r.easing).each("end",(function(){f&&f()})).each("interrupt",(function(){f&&f()})).each((function(){m.selectAll("g.trace").each((function(e){s(t,e,this,r,p)}))}))):(u.each((function(e){s(t,e,this,r,p)})),d.uniformtext.mode&&o(t,m.selectAll(".trace"),h));g&&u.exit().remove()}},{"../bar/style":662,"../bar/uniform_text":664,"../sunburst/helpers":1055,"./plot_one":1089,"@plotly/d3":58}],1081:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=t("../../components/drawing"),o=t("../../lib/svg_text_utils"),s=t("./partition"),l=t("./style").styleOne,c=t("./constants"),u=t("../sunburst/helpers"),f=t("../sunburst/fx");e.exports=function(t,e,r,h,p){var d=p.barDifY,m=p.width,g=p.height,v=p.viewX,y=p.viewY,x=p.pathSlice,b=p.toMoveInsideSlice,_=p.strTransform,w=p.hasTransition,T=p.handleSlicesExit,k=p.makeUpdateSliceInterpolator,A=p.makeUpdateTextInterpolator,M={},S=t._fullLayout,E=e[0],L=E.trace,C=E.hierarchy,P=m/L._entryDepth,I=u.listPath(r.data,"id"),O=s(C.copy(),[m,g],{packing:"dice",pad:{inner:0,top:0,left:0,right:0,bottom:0}}).descendants();(O=O.filter((function(t){var e=I.indexOf(t.data.id);return-1!==e&&(t.x0=P*e,t.x1=P*(e+1),t.y0=d,t.y1=d+g,t.onPathbar=!0,!0)}))).reverse(),(h=h.data(O,u.getPtId)).enter().append("g").classed("pathbar",!0),T(h,!0,M,[m,g],x),h.order();var z=h;w&&(z=z.transition().each("end",(function(){var e=n.select(this);u.setSliceCursor(e,t,{hideOnRoot:!1,hideOnLeaves:!1,isTransitioning:!1})}))),z.each((function(s){s._x0=v(s.x0),s._x1=v(s.x1),s._y0=y(s.y0),s._y1=y(s.y1),s._hoverX=v(s.x1-Math.min(m,g)/2),s._hoverY=y(s.y1-g/2);var h=n.select(this),p=i.ensureSingle(h,"path","surface",(function(t){t.style("pointer-events","all")}));w?p.transition().attrTween("d",(function(t){var e=k(t,!0,M,[m,g]);return function(t){return x(e(t))}})):p.attr("d",x),h.call(f,r,t,e,{styleOne:l,eventDataKeys:c.eventDataKeys,transitionTime:c.CLICK_TRANSITION_TIME,transitionEasing:c.CLICK_TRANSITION_EASING}).call(u.setSliceCursor,t,{hideOnRoot:!1,hideOnLeaves:!1,isTransitioning:t._transitioning}),p.call(l,s,L,{hovered:!1}),s._text=(u.getPtLabel(s)||"").split("
    ").join(" ")||"";var d=i.ensureSingle(h,"g","slicetext"),T=i.ensureSingle(d,"text","",(function(t){t.attr("data-notex",1)})),E=i.ensureUniformFontSize(t,u.determineTextFont(L,s,S.font,{onPathbar:!0}));T.text(s._text||" ").classed("slicetext",!0).attr("text-anchor","start").call(a.font,E).call(o.convertToTspans,t),s.textBB=a.bBox(T.node()),s.transform=b(s,{fontSize:E.size,onPathbar:!0}),s.transform.fontSize=E.size,w?T.transition().attrTween("transform",(function(t){var e=A(t,!0,M,[m,g]);return function(t){return _(e(t))}})):T.attr("transform",_(s))}))}},{"../../components/drawing":388,"../../lib":503,"../../lib/svg_text_utils":529,"../sunburst/fx":1054,"../sunburst/helpers":1055,"./constants":1078,"./partition":1087,"./style":1090,"@plotly/d3":58}],1082:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=t("../../components/drawing"),o=t("../../lib/svg_text_utils"),s=t("./partition"),l=t("./style").styleOne,c=t("./constants"),u=t("../sunburst/helpers"),f=t("../sunburst/fx"),h=t("../sunburst/plot").formatSliceLabel;e.exports=function(t,e,r,p,d){var m=d.width,g=d.height,v=d.viewX,y=d.viewY,x=d.pathSlice,b=d.toMoveInsideSlice,_=d.strTransform,w=d.hasTransition,T=d.handleSlicesExit,k=d.makeUpdateSliceInterpolator,A=d.makeUpdateTextInterpolator,M=d.prevEntry,S=t._fullLayout,E=e[0].trace,L=-1!==E.textposition.indexOf("left"),C=-1!==E.textposition.indexOf("right"),P=-1!==E.textposition.indexOf("bottom"),I=!P&&!E.marker.pad.t||P&&!E.marker.pad.b,O=s(r,[m,g],{packing:E.tiling.packing,squarifyratio:E.tiling.squarifyratio,flipX:E.tiling.flip.indexOf("x")>-1,flipY:E.tiling.flip.indexOf("y")>-1,pad:{inner:E.tiling.pad,top:E.marker.pad.t,left:E.marker.pad.l,right:E.marker.pad.r,bottom:E.marker.pad.b}}).descendants(),z=1/0,D=-1/0;O.forEach((function(t){var e=t.depth;e>=E._maxDepth?(t.x0=t.x1=(t.x0+t.x1)/2,t.y0=t.y1=(t.y0+t.y1)/2):(z=Math.min(z,e),D=Math.max(D,e))})),p=p.data(O,u.getPtId),E._maxVisibleLayers=isFinite(D)?D-z+1:0,p.enter().append("g").classed("slice",!0),T(p,!1,{},[m,g],x),p.order();var R=null;if(w&&M){var F=u.getPtId(M);p.each((function(t){null===R&&u.getPtId(t)===F&&(R={x0:t.x0,x1:t.x1,y0:t.y0,y1:t.y1})}))}var B=function(){return R||{x0:0,x1:m,y0:0,y1:g}},N=p;return w&&(N=N.transition().each("end",(function(){var e=n.select(this);u.setSliceCursor(e,t,{hideOnRoot:!0,hideOnLeaves:!1,isTransitioning:!1})}))),N.each((function(s){var p=u.isHeader(s,E);s._x0=v(s.x0),s._x1=v(s.x1),s._y0=y(s.y0),s._y1=y(s.y1),s._hoverX=v(s.x1-E.marker.pad.r),s._hoverY=y(P?s.y1-E.marker.pad.b/2:s.y0+E.marker.pad.t/2);var d=n.select(this),T=i.ensureSingle(d,"path","surface",(function(t){t.style("pointer-events","all")}));w?T.transition().attrTween("d",(function(t){var e=k(t,!1,B(),[m,g]);return function(t){return x(e(t))}})):T.attr("d",x),d.call(f,r,t,e,{styleOne:l,eventDataKeys:c.eventDataKeys,transitionTime:c.CLICK_TRANSITION_TIME,transitionEasing:c.CLICK_TRANSITION_EASING}).call(u.setSliceCursor,t,{isTransitioning:t._transitioning}),T.call(l,s,E,{hovered:!1}),s.x0===s.x1||s.y0===s.y1?s._text="":s._text=p?I?"":u.getPtLabel(s)||"":h(s,r,E,e,S)||"";var M=i.ensureSingle(d,"g","slicetext"),O=i.ensureSingle(M,"text","",(function(t){t.attr("data-notex",1)})),z=i.ensureUniformFontSize(t,u.determineTextFont(E,s,S.font));O.text(s._text||" ").classed("slicetext",!0).attr("text-anchor",C?"end":L||p?"start":"middle").call(a.font,z).call(o.convertToTspans,t),s.textBB=a.bBox(O.node()),s.transform=b(s,{fontSize:z.size,isHeader:p}),s.transform.fontSize=z.size,w?O.transition().attrTween("transform",(function(t){var e=A(t,!1,B(),[m,g]);return function(t){return _(e(t))}})):O.attr("transform",_(s))})),R}},{"../../components/drawing":388,"../../lib":503,"../../lib/svg_text_utils":529,"../sunburst/fx":1054,"../sunburst/helpers":1055,"../sunburst/plot":1059,"./constants":1078,"./partition":1087,"./style":1090,"@plotly/d3":58}],1083:[function(t,e,r){"use strict";e.exports=function t(e,r,n){var i;n.swapXY&&(i=e.x0,e.x0=e.y0,e.y0=i,i=e.x1,e.x1=e.y1,e.y1=i),n.flipX&&(i=e.x0,e.x0=r[0]-e.x1,e.x1=r[0]-i),n.flipY&&(i=e.y0,e.y0=r[1]-e.y1,e.y1=r[1]-i);var a=e.children;if(a)for(var o=0;o-1?C+O:-(I+O):0,D={x0:P,x1:P,y0:z,y1:z+I},R=function(t,e,r){var n=v.tiling.pad,i=function(t){return t-n<=e.x0},a=function(t){return t+n>=e.x1},o=function(t){return t-n<=e.y0},s=function(t){return t+n>=e.y1};return t.x0===e.x0&&t.x1===e.x1&&t.y0===e.y0&&t.y1===e.y1?{x0:t.x0,x1:t.x1,y0:t.y0,y1:t.y1}:{x0:i(t.x0-n)?0:a(t.x0-n)?r[0]:t.x0,x1:i(t.x1+n)?0:a(t.x1+n)?r[0]:t.x1,y0:o(t.y0-n)?0:s(t.y0-n)?r[1]:t.y0,y1:o(t.y1+n)?0:s(t.y1+n)?r[1]:t.y1}},F=null,B={},N={},j=null,U=function(t,e){return e?B[h(t)]:N[h(t)]},V=function(t,e,r,n){if(e)return B[h(x)]||D;var i=N[v.level]||r;return function(t){return t.data.depth-b.data.depth=(n-=(y?g:g.r)-s)){var x=(r+n)/2;r=x,n=x}var b;f?i<(b=a-(y?g:g.b))&&b"===tt?(l.x-=a,c.x-=a,u.x-=a,f.x-=a):"/"===tt?(u.x-=a,f.x-=a,o.x-=a/2,s.x-=a/2):"\\"===tt?(l.x-=a,c.x-=a,o.x-=a/2,s.x-=a/2):"<"===tt&&(o.x-=a,s.x-=a),$(l),$(f),$(o),$(c),$(u),$(s),"M"+K(l.x,l.y)+"L"+K(c.x,c.y)+"L"+K(s.x,s.y)+"L"+K(u.x,u.y)+"L"+K(f.x,f.y)+"L"+K(o.x,o.y)+"Z"},toMoveInsideSlice:et,makeUpdateSliceInterpolator:nt,makeUpdateTextInterpolator:it,handleSlicesExit:at,hasTransition:A,strTransform:ot}):w.remove()}},{"../../lib":503,"../bar/constants":650,"../bar/plot":659,"../bar/uniform_text":664,"../sunburst/helpers":1055,"./constants":1078,"./draw_ancestors":1081,"@plotly/d3":58,"d3-interpolate":116}],1090:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../components/color"),a=t("../../lib"),o=t("../sunburst/helpers"),s=t("../bar/uniform_text").resizeText;function l(t,e,r,n){var s,l,c=(n||{}).hovered,u=e.data.data,f=u.i,h=u.color,p=o.isHierarchyRoot(e),d=1;if(c)s=r._hovered.marker.line.color,l=r._hovered.marker.line.width;else if(p&&h===r.root.color)d=100,s="rgba(0,0,0,0)",l=0;else if(s=a.castOption(r,f,"marker.line.color")||i.defaultLine,l=a.castOption(r,f,"marker.line.width")||0,!r._hasColorscale&&!e.onPathbar){var m=r.marker.depthfade;if(m){var g,v=i.combine(i.addOpacity(r._backgroundColor,.75),h);if(!0===m){var y=o.getMaxDepth(r);g=isFinite(y)?o.isLeaf(e)?0:r._maxVisibleLayers-(e.data.depth-r._entryDepth):e.data.height+1}else g=e.data.depth-r._entryDepth,r._atRootLevel||g++;if(g>0)for(var x=0;x0){var x,b,_,w,T,k=t.xa,A=t.ya;"h"===p.orientation?(T=e,x="y",_=A,b="x",w=k):(T=r,x="x",_=k,b="y",w=A);var M=h[t.index];if(T>=M.span[0]&&T<=M.span[1]){var S=n.extendFlat({},t),E=w.c2p(T,!0),L=o.getKdeValue(M,p,T),C=o.getPositionOnKdePath(M,p,E),P=_._offset,I=_._length;S[x+"0"]=C[0],S[x+"1"]=C[1],S[b+"0"]=S[b+"1"]=E,S[b+"Label"]=b+": "+i.hoverLabelText(w,T,p[b+"hoverformat"])+", "+h[0].t.labels.kde+" "+L.toFixed(3),S.spikeDistance=y[0].spikeDistance;var O=x+"Spike";S[O]=y[0][O],y[0].spikeDistance=void 0,y[0][O]=void 0,S.hovertemplate=!1,v.push(S),(u={stroke:t.color})[x+"1"]=n.constrain(P+C[0],P,P+I),u[x+"2"]=n.constrain(P+C[1],P,P+I),u[b+"1"]=u[b+"2"]=w._offset+E}}m&&(v=v.concat(y))}-1!==d.indexOf("points")&&(c=a.hoverOnPoints(t,e,r));var z=f.selectAll(".violinline-"+p.uid).data(u?[0]:[]);return z.enter().append("line").classed("violinline-"+p.uid,!0).attr("stroke-width",1.5),z.exit().remove(),z.attr(u),"closest"===s?c?[c]:v:c?(v.push(c),v):v}},{"../../lib":503,"../../plots/cartesian/axes":554,"../box/hover":678,"./helpers":1095}],1097:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults"),crossTraceDefaults:t("../box/defaults").crossTraceDefaults,supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc"),crossTraceCalc:t("./cross_trace_calc"),plot:t("./plot"),style:t("./style"),styleOnSelect:t("../scatter/style").styleOnSelect,hoverPoints:t("./hover"),selectPoints:t("../box/select"),moduleType:"trace",name:"violin",basePlotModule:t("../../plots/cartesian"),categories:["cartesian","svg","symbols","oriented","box-violin","showLegend","violinLayout","zoomScale"],meta:{}}},{"../../plots/cartesian":568,"../box/defaults":676,"../box/select":683,"../scatter/style":951,"./attributes":1091,"./calc":1092,"./cross_trace_calc":1093,"./defaults":1094,"./hover":1096,"./layout_attributes":1098,"./layout_defaults":1099,"./plot":1100,"./style":1101}],1098:[function(t,e,r){"use strict";var n=t("../box/layout_attributes"),i=t("../../lib").extendFlat;e.exports={violinmode:i({},n.boxmode,{}),violingap:i({},n.boxgap,{}),violingroupgap:i({},n.boxgroupgap,{})}},{"../../lib":503,"../box/layout_attributes":680}],1099:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes"),a=t("../box/layout_defaults");e.exports=function(t,e,r){a._supply(t,e,r,(function(r,a){return n.coerce(t,e,i,r,a)}),"violin")}},{"../../lib":503,"../box/layout_defaults":681,"./layout_attributes":1098}],1100:[function(t,e,r){"use strict";var n=t("@plotly/d3"),i=t("../../lib"),a=t("../../components/drawing"),o=t("../box/plot"),s=t("../scatter/line_points"),l=t("./helpers");e.exports=function(t,e,r,c){var u=t._fullLayout,f=e.xaxis,h=e.yaxis;function p(t){var e=s(t,{xaxis:f,yaxis:h,connectGaps:!0,baseTolerance:.75,shape:"spline",simplify:!0,linearized:!0});return a.smoothopen(e[0],1)}i.makeTraceGroups(c,r,"trace violins").each((function(t){var r=n.select(this),a=t[0],s=a.t,c=a.trace;if(!0!==c.visible||s.empty)r.remove();else{var d=s.bPos,m=s.bdPos,g=e[s.valLetter+"axis"],v=e[s.posLetter+"axis"],y="both"===c.side,x=y||"positive"===c.side,b=y||"negative"===c.side,_=r.selectAll("path.violin").data(i.identity);_.enter().append("path").style("vector-effect","non-scaling-stroke").attr("class","violin"),_.exit().remove(),_.each((function(t){var e,r,i,a,o,l,f,h,_=n.select(this),w=t.density,T=w.length,k=v.c2l(t.pos+d,!0),A=v.l2p(k);if(c.width)e=s.maxKDE/m;else{var M=u._violinScaleGroupStats[c.scalegroup];e="count"===c.scalemode?M.maxKDE/m*(M.maxCount/t.pts.length):M.maxKDE/m}if(x){for(f=new Array(T),o=0;o")),u.color=function(t,e){var r=t[e.dir].marker,n=r.color,a=r.line.color,o=r.line.width;if(i(n))return n;if(i(a)&&o)return a}(h,g),[u]}function k(t){return n(m,t,h[d+"hoverformat"])}}},{"../../components/color":366,"../../constants/delta.js":473,"../../plots/cartesian/axes":554,"../bar/hover":655}],1113:[function(t,e,r){"use strict";e.exports={attributes:t("./attributes"),layoutAttributes:t("./layout_attributes"),supplyDefaults:t("./defaults").supplyDefaults,crossTraceDefaults:t("./defaults").crossTraceDefaults,supplyLayoutDefaults:t("./layout_defaults"),calc:t("./calc"),crossTraceCalc:t("./cross_trace_calc"),plot:t("./plot"),style:t("./style").style,hoverPoints:t("./hover"),eventData:t("./event_data"),selectPoints:t("../bar/select"),moduleType:"trace",name:"waterfall",basePlotModule:t("../../plots/cartesian"),categories:["bar-like","cartesian","svg","oriented","showLegend","zoomScale"],meta:{}}},{"../../plots/cartesian":568,"../bar/select":660,"./attributes":1106,"./calc":1107,"./cross_trace_calc":1109,"./defaults":1110,"./event_data":1111,"./hover":1112,"./layout_attributes":1114,"./layout_defaults":1115,"./plot":1116,"./style":1117}],1114:[function(t,e,r){"use strict";e.exports={waterfallmode:{valType:"enumerated",values:["group","overlay"],dflt:"group",editType:"calc"},waterfallgap:{valType:"number",min:0,max:1,editType:"calc"},waterfallgroupgap:{valType:"number",min:0,max:1,dflt:0,editType:"calc"}}},{}],1115:[function(t,e,r){"use strict";var n=t("../../lib"),i=t("./layout_attributes");e.exports=function(t,e,r){var a=!1;function o(r,a){return n.coerce(t,e,i,r,a)}for(var s=0;s0&&(g+=h?"M"+f[0]+","+d[1]+"V"+d[0]:"M"+f[1]+","+d[0]+"H"+f[0]),"between"!==p&&(r.isSum||s path").each((function(t){if(!t.isBlank){var e=s[t.dir].marker;n.select(this).call(a.fill,e.color).call(a.stroke,e.line.color).call(i.dashLine,e.line.dash,e.line.width).style("opacity",s.selectedpoints&&!t.selected?o:1)}})),c(r,s,t),r.selectAll(".lines").each((function(){var t=s.connector.line;i.lineGroupStyle(n.select(this).selectAll("path"),t.width,t.color,t.dash)}))}))}}},{"../../components/color":366,"../../components/drawing":388,"../../constants/interactions":478,"../bar/style":662,"../bar/uniform_text":664,"@plotly/d3":58}],1118:[function(t,e,r){"use strict";var n=t("../plots/cartesian/axes"),i=t("../lib"),a=t("../plot_api/plot_schema"),o=t("./helpers").pointsAccessorFunction,s=t("../constants/numerical").BADNUM;r.moduleType="transform",r.name="aggregate";var l=r.attributes={enabled:{valType:"boolean",dflt:!0,editType:"calc"},groups:{valType:"string",strict:!0,noBlank:!0,arrayOk:!0,dflt:"x",editType:"calc"},aggregations:{_isLinkedToArray:"aggregation",target:{valType:"string",editType:"calc"},func:{valType:"enumerated",values:["count","sum","avg","median","mode","rms","stddev","min","max","first","last","change","range"],dflt:"first",editType:"calc"},funcmode:{valType:"enumerated",values:["sample","population"],dflt:"sample",editType:"calc"},enabled:{valType:"boolean",dflt:!0,editType:"calc"},editType:"calc"},editType:"calc"},c=l.aggregations;function u(t,e,r,a){if(a.enabled){for(var o=a.target,l=i.nestedProperty(e,o),c=l.get(),u=function(t,e){var r=t.func,n=e.d2c,a=e.c2d;switch(r){case"count":return f;case"first":return h;case"last":return p;case"sum":return function(t,e){for(var r=0,i=0;ii&&(i=u,o=c)}}return i?a(o):s};case"rms":return function(t,e){for(var r=0,i=0,o=0;o":return function(t){return h(t)>s};case">=":return function(t){return h(t)>=s};case"[]":return function(t){var e=h(t);return e>=s[0]&&e<=s[1]};case"()":return function(t){var e=h(t);return e>s[0]&&e=s[0]&&es[0]&&e<=s[1]};case"][":return function(t){var e=h(t);return e<=s[0]||e>=s[1]};case")(":return function(t){var e=h(t);return es[1]};case"](":return function(t){var e=h(t);return e<=s[0]||e>s[1]};case")[":return function(t){var e=h(t);return e=s[1]};case"{}":return function(t){return-1!==s.indexOf(h(t))};case"}{":return function(t){return-1===s.indexOf(h(t))}}}(r,a.getDataToCoordFunc(t,e,s,i),h),x={},b={},_=0;d?(g=function(t){x[t.astr]=n.extendDeep([],t.get()),t.set(new Array(f))},v=function(t,e){var r=x[t.astr][e];t.get()[e]=r}):(g=function(t){x[t.astr]=n.extendDeep([],t.get()),t.set([])},v=function(t,e){var r=x[t.astr][e];t.get().push(r)}),k(g);for(var w=o(e.transforms,r),T=0;T1?"%{group} (%{trace})":"%{group}");var l=t.styles,c=o.styles=[];if(l)for(a=0;a0?o-4:o;for(r=0;r>16&255,l[u++]=e>>8&255,l[u++]=255&e;2===s&&(e=i[t.charCodeAt(r)]<<2|i[t.charCodeAt(r+1)]>>4,l[u++]=255&e);1===s&&(e=i[t.charCodeAt(r)]<<10|i[t.charCodeAt(r+1)]<<4|i[t.charCodeAt(r+2)]>>2,l[u++]=e>>8&255,l[u++]=255&e);return l},r.fromByteArray=function(t){for(var e,r=t.length,i=r%3,a=[],o=0,s=r-i;os?s:o+16383));1===i?(e=t[r-1],a.push(n[e>>2]+n[e<<4&63]+"==")):2===i&&(e=(t[r-2]<<8)+t[r-1],a.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"="));return a.join("")};for(var n=[],i=[],a="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",s=0,l=o.length;s0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return-1===r&&(r=e),[r,r===e?0:4-r%4]}function u(t,e,r){for(var i,a,o=[],s=e;s>18&63]+n[a>>12&63]+n[a>>6&63]+n[63&a]);return o.join("")}i["-".charCodeAt(0)]=62,i["_".charCodeAt(0)]=63},{}],2:[function(t,e,r){},{}],3:[function(t,e,r){(function(e){(function(){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +"use strict";var e=t("base64-js"),n=t("ieee754");r.Buffer=a,r.SlowBuffer=function(t){+t!=t&&(t=0);return a.alloc(+t)},r.INSPECT_MAX_BYTES=50;function i(t){if(t>2147483647)throw new RangeError('The value "'+t+'" is invalid for option "size"');var e=new Uint8Array(t);return e.__proto__=a.prototype,e}function a(t,e,r){if("number"==typeof t){if("string"==typeof e)throw new TypeError('The "string" argument must be of type string. Received type number');return l(t)}return o(t,e,r)}function o(t,e,r){if("string"==typeof t)return function(t,e){"string"==typeof e&&""!==e||(e="utf8");if(!a.isEncoding(e))throw new TypeError("Unknown encoding: "+e);var r=0|f(t,e),n=i(r),o=n.write(t,e);o!==r&&(n=n.slice(0,o));return n}(t,e);if(ArrayBuffer.isView(t))return c(t);if(null==t)throw TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof t);if(B(t,ArrayBuffer)||t&&B(t.buffer,ArrayBuffer))return function(t,e,r){if(e<0||t.byteLength=2147483647)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+2147483647..toString(16)+" bytes");return 0|t}function f(t,e){if(a.isBuffer(t))return t.length;if(ArrayBuffer.isView(t)||B(t,ArrayBuffer))return t.byteLength;if("string"!=typeof t)throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof t);var r=t.length,n=arguments.length>2&&!0===arguments[2];if(!n&&0===r)return 0;for(var i=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":return D(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return R(t).length;default:if(i)return n?-1:D(t).length;e=(""+e).toLowerCase(),i=!0}}function h(t,e,r){var n=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return M(this,e,r);case"utf8":case"utf-8":return T(this,e,r);case"ascii":return k(this,e,r);case"latin1":case"binary":return A(this,e,r);case"base64":return w(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return S(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function p(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function d(t,e,r,n,i){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),N(r=+r)&&(r=i?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(i)return-1;r=t.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof e&&(e=a.from(e,n)),a.isBuffer(e))return 0===e.length?-1:m(t,e,r,n,i);if("number"==typeof e)return e&=255,"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):m(t,[e],r,n,i);throw new TypeError("val must be string, number or Buffer")}function m(t,e,r,n,i){var a,o=1,s=t.length,l=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;o=2,s/=2,l/=2,r/=2}function c(t,e){return 1===o?t[e]:t.readUInt16BE(e*o)}if(i){var u=-1;for(a=r;as&&(r=s-l),a=r;a>=0;a--){for(var f=!0,h=0;hi&&(n=i):n=i;var a=e.length;n>a/2&&(n=a/2);for(var o=0;o>8,i=r%256,a.push(i),a.push(n);return a}(e,t.length-r),t,r,n)}function w(t,r,n){return 0===r&&n===t.length?e.fromByteArray(t):e.fromByteArray(t.slice(r,n))}function T(t,e,r){r=Math.min(t.length,r);for(var n=[],i=e;i239?4:c>223?3:c>191?2:1;if(i+f<=r)switch(f){case 1:c<128&&(u=c);break;case 2:128==(192&(a=t[i+1]))&&(l=(31&c)<<6|63&a)>127&&(u=l);break;case 3:a=t[i+1],o=t[i+2],128==(192&a)&&128==(192&o)&&(l=(15&c)<<12|(63&a)<<6|63&o)>2047&&(l<55296||l>57343)&&(u=l);break;case 4:a=t[i+1],o=t[i+2],s=t[i+3],128==(192&a)&&128==(192&o)&&128==(192&s)&&(l=(15&c)<<18|(63&a)<<12|(63&o)<<6|63&s)>65535&&l<1114112&&(u=l)}null===u?(u=65533,f=1):u>65535&&(u-=65536,n.push(u>>>10&1023|55296),u=56320|1023&u),n.push(u),i+=f}return function(t){var e=t.length;if(e<=4096)return String.fromCharCode.apply(String,t);var r="",n=0;for(;ne&&(t+=" ... "),""},a.prototype.compare=function(t,e,r,n,i){if(B(t,Uint8Array)&&(t=a.from(t,t.offset,t.byteLength)),!a.isBuffer(t))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof t);if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),e<0||r>t.length||n<0||i>this.length)throw new RangeError("out of range index");if(n>=i&&e>=r)return 0;if(n>=i)return-1;if(e>=r)return 1;if(this===t)return 0;for(var o=(i>>>=0)-(n>>>=0),s=(r>>>=0)-(e>>>=0),l=Math.min(o,s),c=this.slice(n,i),u=t.slice(e,r),f=0;f>>=0,isFinite(r)?(r>>>=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var i=this.length-e;if((void 0===r||r>i)&&(r=i),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var a=!1;;)switch(n){case"hex":return g(this,t,e,r);case"utf8":case"utf-8":return v(this,t,e,r);case"ascii":return y(this,t,e,r);case"latin1":case"binary":return x(this,t,e,r);case"base64":return b(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return _(this,t,e,r);default:if(a)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),a=!0}},a.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function k(t,e,r){var n="";r=Math.min(t.length,r);for(var i=e;in)&&(r=n);for(var i="",a=e;ar)throw new RangeError("Trying to access beyond buffer length")}function L(t,e,r,n,i,o){if(!a.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>i||et.length)throw new RangeError("Index out of range")}function C(t,e,r,n,i,a){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function P(t,e,r,i,a){return e=+e,r>>>=0,a||C(t,0,r,4),n.write(t,e,r,i,23,4),r+4}function I(t,e,r,i,a){return e=+e,r>>>=0,a||C(t,0,r,8),n.write(t,e,r,i,52,8),r+8}a.prototype.slice=function(t,e){var r=this.length;(t=~~t)<0?(t+=r)<0&&(t=0):t>r&&(t=r),(e=void 0===e?r:~~e)<0?(e+=r)<0&&(e=0):e>r&&(e=r),e>>=0,e>>>=0,r||E(t,e,this.length);for(var n=this[t],i=1,a=0;++a>>=0,e>>>=0,r||E(t,e,this.length);for(var n=this[t+--e],i=1;e>0&&(i*=256);)n+=this[t+--e]*i;return n},a.prototype.readUInt8=function(t,e){return t>>>=0,e||E(t,1,this.length),this[t]},a.prototype.readUInt16LE=function(t,e){return t>>>=0,e||E(t,2,this.length),this[t]|this[t+1]<<8},a.prototype.readUInt16BE=function(t,e){return t>>>=0,e||E(t,2,this.length),this[t]<<8|this[t+1]},a.prototype.readUInt32LE=function(t,e){return t>>>=0,e||E(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},a.prototype.readUInt32BE=function(t,e){return t>>>=0,e||E(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},a.prototype.readIntLE=function(t,e,r){t>>>=0,e>>>=0,r||E(t,e,this.length);for(var n=this[t],i=1,a=0;++a=(i*=128)&&(n-=Math.pow(2,8*e)),n},a.prototype.readIntBE=function(t,e,r){t>>>=0,e>>>=0,r||E(t,e,this.length);for(var n=e,i=1,a=this[t+--n];n>0&&(i*=256);)a+=this[t+--n]*i;return a>=(i*=128)&&(a-=Math.pow(2,8*e)),a},a.prototype.readInt8=function(t,e){return t>>>=0,e||E(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},a.prototype.readInt16LE=function(t,e){t>>>=0,e||E(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},a.prototype.readInt16BE=function(t,e){t>>>=0,e||E(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},a.prototype.readInt32LE=function(t,e){return t>>>=0,e||E(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},a.prototype.readInt32BE=function(t,e){return t>>>=0,e||E(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},a.prototype.readFloatLE=function(t,e){return t>>>=0,e||E(t,4,this.length),n.read(this,t,!0,23,4)},a.prototype.readFloatBE=function(t,e){return t>>>=0,e||E(t,4,this.length),n.read(this,t,!1,23,4)},a.prototype.readDoubleLE=function(t,e){return t>>>=0,e||E(t,8,this.length),n.read(this,t,!0,52,8)},a.prototype.readDoubleBE=function(t,e){return t>>>=0,e||E(t,8,this.length),n.read(this,t,!1,52,8)},a.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e>>>=0,r>>>=0,n)||L(this,t,e,r,Math.pow(2,8*r)-1,0);var i=1,a=0;for(this[e]=255&t;++a>>=0,r>>>=0,n)||L(this,t,e,r,Math.pow(2,8*r)-1,0);var i=r-1,a=1;for(this[e+i]=255&t;--i>=0&&(a*=256);)this[e+i]=t/a&255;return e+r},a.prototype.writeUInt8=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,1,255,0),this[e]=255&t,e+1},a.prototype.writeUInt16LE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,2,65535,0),this[e]=255&t,this[e+1]=t>>>8,e+2},a.prototype.writeUInt16BE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,2,65535,0),this[e]=t>>>8,this[e+1]=255&t,e+2},a.prototype.writeUInt32LE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,4,4294967295,0),this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t,e+4},a.prototype.writeUInt32BE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,4,4294967295,0),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},a.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e>>>=0,!n){var i=Math.pow(2,8*r-1);L(this,t,e,r,i-1,-i)}var a=0,o=1,s=0;for(this[e]=255&t;++a>0)-s&255;return e+r},a.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e>>>=0,!n){var i=Math.pow(2,8*r-1);L(this,t,e,r,i-1,-i)}var a=r-1,o=1,s=0;for(this[e+a]=255&t;--a>=0&&(o*=256);)t<0&&0===s&&0!==this[e+a+1]&&(s=1),this[e+a]=(t/o>>0)-s&255;return e+r},a.prototype.writeInt8=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,1,127,-128),t<0&&(t=255+t+1),this[e]=255&t,e+1},a.prototype.writeInt16LE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,2,32767,-32768),this[e]=255&t,this[e+1]=t>>>8,e+2},a.prototype.writeInt16BE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,2,32767,-32768),this[e]=t>>>8,this[e+1]=255&t,e+2},a.prototype.writeInt32LE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,4,2147483647,-2147483648),this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24,e+4},a.prototype.writeInt32BE=function(t,e,r){return t=+t,e>>>=0,r||L(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t,e+4},a.prototype.writeFloatLE=function(t,e,r){return P(this,t,e,!0,r)},a.prototype.writeFloatBE=function(t,e,r){return P(this,t,e,!1,r)},a.prototype.writeDoubleLE=function(t,e,r){return I(this,t,e,!0,r)},a.prototype.writeDoubleBE=function(t,e,r){return I(this,t,e,!1,r)},a.prototype.copy=function(t,e,r,n){if(!a.isBuffer(t))throw new TypeError("argument should be a Buffer");if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n=this.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e=0;--o)t[o+e]=this[o+r];else Uint8Array.prototype.set.call(t,this.subarray(r,n),e);return i},a.prototype.fill=function(t,e,r,n){if("string"==typeof t){if("string"==typeof e?(n=e,e=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!a.isEncoding(n))throw new TypeError("Unknown encoding: "+n);if(1===t.length){var i=t.charCodeAt(0);("utf8"===n&&i<128||"latin1"===n)&&(t=i)}}else"number"==typeof t&&(t&=255);if(e<0||this.length>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(o=e;o55295&&r<57344){if(!i){if(r>56319){(e-=3)>-1&&a.push(239,191,189);continue}if(o+1===n){(e-=3)>-1&&a.push(239,191,189);continue}i=r;continue}if(r<56320){(e-=3)>-1&&a.push(239,191,189),i=r;continue}r=65536+(i-55296<<10|r-56320)}else i&&(e-=3)>-1&&a.push(239,191,189);if(i=null,r<128){if((e-=1)<0)break;a.push(r)}else if(r<2048){if((e-=2)<0)break;a.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;a.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;a.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return a}function R(t){return e.toByteArray(function(t){if((t=(t=t.split("=")[0]).trim().replace(O,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function F(t,e,r,n){for(var i=0;i=e.length||i>=t.length);++i)e[i+r]=t[i];return i}function B(t,e){return t instanceof e||null!=t&&null!=t.constructor&&null!=t.constructor.name&&t.constructor.name===e.name}function N(t){return t!=t}}).call(this)}).call(this,t("buffer").Buffer)},{"base64-js":1,buffer:3,ieee754:4}],4:[function(t,e,r){r.read=function(t,e,r,n,i){var a,o,s=8*i-n-1,l=(1<>1,u=-7,f=r?i-1:0,h=r?-1:1,p=t[e+f];for(f+=h,a=p&(1<<-u)-1,p>>=-u,u+=s;u>0;a=256*a+t[e+f],f+=h,u-=8);for(o=a&(1<<-u)-1,a>>=-u,u+=n;u>0;o=256*o+t[e+f],f+=h,u-=8);if(0===a)a=1-c;else{if(a===l)return o?NaN:1/0*(p?-1:1);o+=Math.pow(2,n),a-=c}return(p?-1:1)*o*Math.pow(2,a-n)},r.write=function(t,e,r,n,i,a){var o,s,l,c=8*a-i-1,u=(1<>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,p=n?0:a-1,d=n?1:-1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,o=u):(o=Math.floor(Math.log(e)/Math.LN2),e*(l=Math.pow(2,-o))<1&&(o--,l*=2),(e+=o+f>=1?h/l:h*Math.pow(2,1-f))*l>=2&&(o++,l/=2),o+f>=u?(s=0,o=u):o+f>=1?(s=(e*l-1)*Math.pow(2,i),o+=f):(s=e*Math.pow(2,f-1)*Math.pow(2,i),o=0));i>=8;t[r+p]=255&s,p+=d,s/=256,i-=8);for(o=o<0;t[r+p]=255&o,p+=d,o/=256,c-=8);t[r+p-d]|=128*m}},{}],5:[function(t,e,r){var n,i,a=e.exports={};function o(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function l(t){if(n===setTimeout)return setTimeout(t,0);if((n===o||!n)&&setTimeout)return n=setTimeout,setTimeout(t,0);try{return n(t,0)}catch(e){try{return n.call(null,t,0)}catch(e){return n.call(this,t,0)}}}!function(){try{n="function"==typeof setTimeout?setTimeout:o}catch(t){n=o}try{i="function"==typeof clearTimeout?clearTimeout:s}catch(t){i=s}}();var c,u=[],f=!1,h=-1;function p(){f&&c&&(f=!1,c.length?u=c.concat(u):h=-1,u.length&&d())}function d(){if(!f){var t=l(p);f=!0;for(var e=u.length;e;){for(c=u,u=[];++h1)for(var r=1;r0?c=c.ushln(f):f<0&&(u=u.ushln(-f));return s(c,u)}},{"./div":17,"./is-rat":19,"./lib/is-bn":23,"./lib/num-to-bn":24,"./lib/rationalize":25,"./lib/str-to-bn":26}],19:[function(t,e,r){"use strict";var n=t("./lib/is-bn");e.exports=function(t){return Array.isArray(t)&&2===t.length&&n(t[0])&&n(t[1])}},{"./lib/is-bn":23}],20:[function(t,e,r){"use strict";var n=t("bn.js");e.exports=function(t){return t.cmp(new n(0))}},{"bn.js":33}],21:[function(t,e,r){"use strict";var n=t("./bn-sign");e.exports=function(t){var e=t.length,r=t.words,i=0;if(1===e)i=r[0];else if(2===e)i=r[0]+67108864*r[1];else for(var a=0;a20)return 52;return r+32}},{"bit-twiddle":32,"double-bits":64}],23:[function(t,e,r){"use strict";t("bn.js");e.exports=function(t){return t&&"object"==typeof t&&Boolean(t.words)}},{"bn.js":33}],24:[function(t,e,r){"use strict";var n=t("bn.js"),i=t("double-bits");e.exports=function(t){var e=i.exponent(t);return e<52?new n(t):new n(t*Math.pow(2,52-e)).ushln(e-52)}},{"bn.js":33,"double-bits":64}],25:[function(t,e,r){"use strict";var n=t("./num-to-bn"),i=t("./bn-sign");e.exports=function(t,e){var r=i(t),a=i(e);if(0===r)return[n(0),n(1)];if(0===a)return[n(0),n(0)];a<0&&(t=t.neg(),e=e.neg());var o=t.gcd(e);if(o.cmpn(1))return[t.div(o),e.div(o)];return[t,e]}},{"./bn-sign":20,"./num-to-bn":24}],26:[function(t,e,r){"use strict";var n=t("bn.js");e.exports=function(t){return new n(t)}},{"bn.js":33}],27:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[0]),t[1].mul(e[1]))}},{"./lib/rationalize":25}],28:[function(t,e,r){"use strict";var n=t("./lib/bn-sign");e.exports=function(t){return n(t[0])*n(t[1])}},{"./lib/bn-sign":20}],29:[function(t,e,r){"use strict";var n=t("./lib/rationalize");e.exports=function(t,e){return n(t[0].mul(e[1]).sub(t[1].mul(e[0])),t[1].mul(e[1]))}},{"./lib/rationalize":25}],30:[function(t,e,r){"use strict";var n=t("./lib/bn-to-num"),i=t("./lib/ctz");e.exports=function(t){var e=t[0],r=t[1];if(0===e.cmpn(0))return 0;var a=e.abs().divmod(r.abs()),o=a.div,s=n(o),l=a.mod,c=e.negative!==r.negative?-1:1;if(0===l.cmpn(0))return c*s;if(s){var u=i(s)+4,f=n(l.ushln(u).divRound(r));return c*(s+f*Math.pow(2,-u))}var h=r.bitLength()-l.bitLength()+53;f=n(l.ushln(h).divRound(r));return h<1023?c*f*Math.pow(2,-h):(f*=Math.pow(2,-1023),c*f*Math.pow(2,1023-h))}},{"./lib/bn-to-num":21,"./lib/ctz":22}],31:[function(t,e,r){"use strict";function n(t,e,r,n,i){for(var a=i+1;n<=i;){var o=n+i>>>1,s=t[o];(void 0!==r?r(s,e):s-e)>=0?(a=o,i=o-1):n=o+1}return a}function i(t,e,r,n,i){for(var a=i+1;n<=i;){var o=n+i>>>1,s=t[o];(void 0!==r?r(s,e):s-e)>0?(a=o,i=o-1):n=o+1}return a}function a(t,e,r,n,i){for(var a=n-1;n<=i;){var o=n+i>>>1,s=t[o];(void 0!==r?r(s,e):s-e)<0?(a=o,n=o+1):i=o-1}return a}function o(t,e,r,n,i){for(var a=n-1;n<=i;){var o=n+i>>>1,s=t[o];(void 0!==r?r(s,e):s-e)<=0?(a=o,n=o+1):i=o-1}return a}function s(t,e,r,n,i){for(;n<=i;){var a=n+i>>>1,o=t[a],s=void 0!==r?r(o,e):o-e;if(0===s)return a;s<=0?n=a+1:i=a-1}return-1}function l(t,e,r,n,i,a){return"function"==typeof r?a(t,e,r,void 0===n?0:0|n,void 0===i?t.length-1:0|i):a(t,e,void 0,void 0===r?0:0|r,void 0===n?t.length-1:0|n)}e.exports={ge:function(t,e,r,i,a){return l(t,e,r,i,a,n)},gt:function(t,e,r,n,a){return l(t,e,r,n,a,i)},lt:function(t,e,r,n,i){return l(t,e,r,n,i,a)},le:function(t,e,r,n,i){return l(t,e,r,n,i,o)},eq:function(t,e,r,n,i){return l(t,e,r,n,i,s)}}},{}],32:[function(t,e,r){"use strict";function n(t){var e=32;return(t&=-t)&&e--,65535&t&&(e-=16),16711935&t&&(e-=8),252645135&t&&(e-=4),858993459&t&&(e-=2),1431655765&t&&(e-=1),e}r.INT_BITS=32,r.INT_MAX=2147483647,r.INT_MIN=-1<<31,r.sign=function(t){return(t>0)-(t<0)},r.abs=function(t){var e=t>>31;return(t^e)-e},r.min=function(t,e){return e^(t^e)&-(t65535)<<4,e|=r=((t>>>=e)>255)<<3,e|=r=((t>>>=r)>15)<<2,(e|=r=((t>>>=r)>3)<<1)|(t>>>=r)>>1},r.log10=function(t){return t>=1e9?9:t>=1e8?8:t>=1e7?7:t>=1e6?6:t>=1e5?5:t>=1e4?4:t>=1e3?3:t>=100?2:t>=10?1:0},r.popCount=function(t){return 16843009*((t=(858993459&(t-=t>>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135)>>>24},r.countTrailingZeros=n,r.nextPow2=function(t){return t+=0===t,--t,t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)+1},r.prevPow2=function(t){return t|=t>>>1,t|=t>>>2,t|=t>>>4,t|=t>>>8,(t|=t>>>16)-(t>>>1)},r.parity=function(t){return t^=t>>>16,t^=t>>>8,t^=t>>>4,27030>>>(t&=15)&1};var i=new Array(256);!function(t){for(var e=0;e<256;++e){var r=e,n=e,i=7;for(r>>>=1;r;r>>>=1)n<<=1,n|=1&r,--i;t[e]=n<>>8&255]<<16|i[t>>>16&255]<<8|i[t>>>24&255]},r.interleave2=function(t,e){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t&=65535)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e&=65535)|e<<8))|e<<4))|e<<2))|e<<1))<<1},r.deinterleave2=function(t,e){return(t=65535&((t=16711935&((t=252645135&((t=858993459&((t=t>>>e&1431655765)|t>>>1))|t>>>2))|t>>>4))|t>>>16))<<16>>16},r.interleave3=function(t,e,r){return t=1227133513&((t=3272356035&((t=251719695&((t=4278190335&((t&=1023)|t<<16))|t<<8))|t<<4))|t<<2),(t|=(e=1227133513&((e=3272356035&((e=251719695&((e=4278190335&((e&=1023)|e<<16))|e<<8))|e<<4))|e<<2))<<1)|(r=1227133513&((r=3272356035&((r=251719695&((r=4278190335&((r&=1023)|r<<16))|r<<8))|r<<4))|r<<2))<<2},r.deinterleave3=function(t,e){return(t=1023&((t=4278190335&((t=251719695&((t=3272356035&((t=t>>>e&1227133513)|t>>>2))|t>>>4))|t>>>8))|t>>>16))<<22>>22},r.nextCombination=function(t){var e=t|t-1;return e+1|(~e&-~e)-1>>>n(t)+1}},{}],33:[function(t,e,r){!function(e,r){"use strict";function n(t,e){if(!t)throw new Error(e||"Assertion failed")}function i(t,e){t.super_=e;var r=function(){};r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t}function a(t,e,r){if(a.isBN(t))return t;this.negative=0,this.words=null,this.length=0,this.red=null,null!==t&&("le"!==e&&"be"!==e||(r=e,e=10),this._init(t||0,e||10,r||"be"))}var o;"object"==typeof e?e.exports=a:r.BN=a,a.BN=a,a.wordSize=26;try{o="undefined"!=typeof window&&void 0!==window.Buffer?window.Buffer:t("buffer").Buffer}catch(t){}function s(t,e){var r=t.charCodeAt(e);return r>=65&&r<=70?r-55:r>=97&&r<=102?r-87:r-48&15}function l(t,e,r){var n=s(t,r);return r-1>=e&&(n|=s(t,r-1)<<4),n}function c(t,e,r,n){for(var i=0,a=Math.min(t.length,r),o=e;o=49?s-49+10:s>=17?s-17+10:s}return i}a.isBN=function(t){return t instanceof a||null!==t&&"object"==typeof t&&t.constructor.wordSize===a.wordSize&&Array.isArray(t.words)},a.max=function(t,e){return t.cmp(e)>0?t:e},a.min=function(t,e){return t.cmp(e)<0?t:e},a.prototype._init=function(t,e,r){if("number"==typeof t)return this._initNumber(t,e,r);if("object"==typeof t)return this._initArray(t,e,r);"hex"===e&&(e=16),n(e===(0|e)&&e>=2&&e<=36);var i=0;"-"===(t=t.toString().replace(/\s+/g,""))[0]&&(i++,this.negative=1),i=0;i-=3)o=t[i]|t[i-1]<<8|t[i-2]<<16,this.words[a]|=o<>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);else if("le"===r)for(i=0,a=0;i>>26-s&67108863,(s+=24)>=26&&(s-=26,a++);return this.strip()},a.prototype._parseHex=function(t,e,r){this.length=Math.ceil((t.length-e)/6),this.words=new Array(this.length);for(var n=0;n=e;n-=2)i=l(t,e,n)<=18?(a-=18,o+=1,this.words[o]|=i>>>26):a+=8;else for(n=(t.length-e)%2==0?e+1:e;n=18?(a-=18,o+=1,this.words[o]|=i>>>26):a+=8;this.strip()},a.prototype._parseBase=function(t,e,r){this.words=[0],this.length=1;for(var n=0,i=1;i<=67108863;i*=e)n++;n--,i=i/e|0;for(var a=t.length-r,o=a%n,s=Math.min(a,a-o)+r,l=0,u=r;u1&&0===this.words[this.length-1];)this.length--;return this._normSign()},a.prototype._normSign=function(){return 1===this.length&&0===this.words[0]&&(this.negative=0),this},a.prototype.inspect=function(){return(this.red?""};var u=["","0","00","000","0000","00000","000000","0000000","00000000","000000000","0000000000","00000000000","000000000000","0000000000000","00000000000000","000000000000000","0000000000000000","00000000000000000","000000000000000000","0000000000000000000","00000000000000000000","000000000000000000000","0000000000000000000000","00000000000000000000000","000000000000000000000000","0000000000000000000000000"],f=[0,0,25,16,12,11,10,9,8,8,7,7,7,7,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5],h=[0,0,33554432,43046721,16777216,48828125,60466176,40353607,16777216,43046721,1e7,19487171,35831808,62748517,7529536,11390625,16777216,24137569,34012224,47045881,64e6,4084101,5153632,6436343,7962624,9765625,11881376,14348907,17210368,20511149,243e5,28629151,33554432,39135393,45435424,52521875,60466176];function p(t,e,r){r.negative=e.negative^t.negative;var n=t.length+e.length|0;r.length=n,n=n-1|0;var i=0|t.words[0],a=0|e.words[0],o=i*a,s=67108863&o,l=o/67108864|0;r.words[0]=s;for(var c=1;c>>26,f=67108863&l,h=Math.min(c,e.length-1),p=Math.max(0,c-t.length+1);p<=h;p++){var d=c-p|0;u+=(o=(i=0|t.words[d])*(a=0|e.words[p])+f)/67108864|0,f=67108863&o}r.words[c]=0|f,l=0|u}return 0!==l?r.words[c]=0|l:r.length--,r.strip()}a.prototype.toString=function(t,e){var r;if(e=0|e||1,16===(t=t||10)||"hex"===t){r="";for(var i=0,a=0,o=0;o>>24-i&16777215)||o!==this.length-1?u[6-l.length]+l+r:l+r,(i+=2)>=26&&(i-=26,o--)}for(0!==a&&(r=a.toString(16)+r);r.length%e!=0;)r="0"+r;return 0!==this.negative&&(r="-"+r),r}if(t===(0|t)&&t>=2&&t<=36){var c=f[t],p=h[t];r="";var d=this.clone();for(d.negative=0;!d.isZero();){var m=d.modn(p).toString(t);r=(d=d.idivn(p)).isZero()?m+r:u[c-m.length]+m+r}for(this.isZero()&&(r="0"+r);r.length%e!=0;)r="0"+r;return 0!==this.negative&&(r="-"+r),r}n(!1,"Base should be between 2 and 36")},a.prototype.toNumber=function(){var t=this.words[0];return 2===this.length?t+=67108864*this.words[1]:3===this.length&&1===this.words[2]?t+=4503599627370496+67108864*this.words[1]:this.length>2&&n(!1,"Number can only safely store up to 53 bits"),0!==this.negative?-t:t},a.prototype.toJSON=function(){return this.toString(16)},a.prototype.toBuffer=function(t,e){return n(void 0!==o),this.toArrayLike(o,t,e)},a.prototype.toArray=function(t,e){return this.toArrayLike(Array,t,e)},a.prototype.toArrayLike=function(t,e,r){var i=this.byteLength(),a=r||Math.max(1,i);n(i<=a,"byte array longer than desired length"),n(a>0,"Requested array length <= 0"),this.strip();var o,s,l="le"===e,c=new t(a),u=this.clone();if(l){for(s=0;!u.isZero();s++)o=u.andln(255),u.iushrn(8),c[s]=o;for(;s=4096&&(r+=13,e>>>=13),e>=64&&(r+=7,e>>>=7),e>=8&&(r+=4,e>>>=4),e>=2&&(r+=2,e>>>=2),r+e},a.prototype._zeroBits=function(t){if(0===t)return 26;var e=t,r=0;return 0==(8191&e)&&(r+=13,e>>>=13),0==(127&e)&&(r+=7,e>>>=7),0==(15&e)&&(r+=4,e>>>=4),0==(3&e)&&(r+=2,e>>>=2),0==(1&e)&&r++,r},a.prototype.bitLength=function(){var t=this.words[this.length-1],e=this._countBits(t);return 26*(this.length-1)+e},a.prototype.zeroBits=function(){if(this.isZero())return 0;for(var t=0,e=0;et.length?this.clone().ior(t):t.clone().ior(this)},a.prototype.uor=function(t){return this.length>t.length?this.clone().iuor(t):t.clone().iuor(this)},a.prototype.iuand=function(t){var e;e=this.length>t.length?t:this;for(var r=0;rt.length?this.clone().iand(t):t.clone().iand(this)},a.prototype.uand=function(t){return this.length>t.length?this.clone().iuand(t):t.clone().iuand(this)},a.prototype.iuxor=function(t){var e,r;this.length>t.length?(e=this,r=t):(e=t,r=this);for(var n=0;nt.length?this.clone().ixor(t):t.clone().ixor(this)},a.prototype.uxor=function(t){return this.length>t.length?this.clone().iuxor(t):t.clone().iuxor(this)},a.prototype.inotn=function(t){n("number"==typeof t&&t>=0);var e=0|Math.ceil(t/26),r=t%26;this._expand(e),r>0&&e--;for(var i=0;i0&&(this.words[i]=~this.words[i]&67108863>>26-r),this.strip()},a.prototype.notn=function(t){return this.clone().inotn(t)},a.prototype.setn=function(t,e){n("number"==typeof t&&t>=0);var r=t/26|0,i=t%26;return this._expand(r+1),this.words[r]=e?this.words[r]|1<t.length?(r=this,n=t):(r=t,n=this);for(var i=0,a=0;a>>26;for(;0!==i&&a>>26;if(this.length=r.length,0!==i)this.words[this.length]=i,this.length++;else if(r!==this)for(;at.length?this.clone().iadd(t):t.clone().iadd(this)},a.prototype.isub=function(t){if(0!==t.negative){t.negative=0;var e=this.iadd(t);return t.negative=1,e._normSign()}if(0!==this.negative)return this.negative=0,this.iadd(t),this.negative=1,this._normSign();var r,n,i=this.cmp(t);if(0===i)return this.negative=0,this.length=1,this.words[0]=0,this;i>0?(r=this,n=t):(r=t,n=this);for(var a=0,o=0;o>26,this.words[o]=67108863&e;for(;0!==a&&o>26,this.words[o]=67108863&e;if(0===a&&o>>13,p=0|o[1],d=8191&p,m=p>>>13,g=0|o[2],v=8191&g,y=g>>>13,x=0|o[3],b=8191&x,_=x>>>13,w=0|o[4],T=8191&w,k=w>>>13,A=0|o[5],M=8191&A,S=A>>>13,E=0|o[6],L=8191&E,C=E>>>13,P=0|o[7],I=8191&P,O=P>>>13,z=0|o[8],D=8191&z,R=z>>>13,F=0|o[9],B=8191&F,N=F>>>13,j=0|s[0],U=8191&j,V=j>>>13,H=0|s[1],q=8191&H,G=H>>>13,Y=0|s[2],W=8191&Y,X=Y>>>13,Z=0|s[3],J=8191&Z,K=Z>>>13,Q=0|s[4],$=8191&Q,tt=Q>>>13,et=0|s[5],rt=8191&et,nt=et>>>13,it=0|s[6],at=8191&it,ot=it>>>13,st=0|s[7],lt=8191&st,ct=st>>>13,ut=0|s[8],ft=8191&ut,ht=ut>>>13,pt=0|s[9],dt=8191&pt,mt=pt>>>13;r.negative=t.negative^e.negative,r.length=19;var gt=(c+(n=Math.imul(f,U))|0)+((8191&(i=(i=Math.imul(f,V))+Math.imul(h,U)|0))<<13)|0;c=((a=Math.imul(h,V))+(i>>>13)|0)+(gt>>>26)|0,gt&=67108863,n=Math.imul(d,U),i=(i=Math.imul(d,V))+Math.imul(m,U)|0,a=Math.imul(m,V);var vt=(c+(n=n+Math.imul(f,q)|0)|0)+((8191&(i=(i=i+Math.imul(f,G)|0)+Math.imul(h,q)|0))<<13)|0;c=((a=a+Math.imul(h,G)|0)+(i>>>13)|0)+(vt>>>26)|0,vt&=67108863,n=Math.imul(v,U),i=(i=Math.imul(v,V))+Math.imul(y,U)|0,a=Math.imul(y,V),n=n+Math.imul(d,q)|0,i=(i=i+Math.imul(d,G)|0)+Math.imul(m,q)|0,a=a+Math.imul(m,G)|0;var yt=(c+(n=n+Math.imul(f,W)|0)|0)+((8191&(i=(i=i+Math.imul(f,X)|0)+Math.imul(h,W)|0))<<13)|0;c=((a=a+Math.imul(h,X)|0)+(i>>>13)|0)+(yt>>>26)|0,yt&=67108863,n=Math.imul(b,U),i=(i=Math.imul(b,V))+Math.imul(_,U)|0,a=Math.imul(_,V),n=n+Math.imul(v,q)|0,i=(i=i+Math.imul(v,G)|0)+Math.imul(y,q)|0,a=a+Math.imul(y,G)|0,n=n+Math.imul(d,W)|0,i=(i=i+Math.imul(d,X)|0)+Math.imul(m,W)|0,a=a+Math.imul(m,X)|0;var xt=(c+(n=n+Math.imul(f,J)|0)|0)+((8191&(i=(i=i+Math.imul(f,K)|0)+Math.imul(h,J)|0))<<13)|0;c=((a=a+Math.imul(h,K)|0)+(i>>>13)|0)+(xt>>>26)|0,xt&=67108863,n=Math.imul(T,U),i=(i=Math.imul(T,V))+Math.imul(k,U)|0,a=Math.imul(k,V),n=n+Math.imul(b,q)|0,i=(i=i+Math.imul(b,G)|0)+Math.imul(_,q)|0,a=a+Math.imul(_,G)|0,n=n+Math.imul(v,W)|0,i=(i=i+Math.imul(v,X)|0)+Math.imul(y,W)|0,a=a+Math.imul(y,X)|0,n=n+Math.imul(d,J)|0,i=(i=i+Math.imul(d,K)|0)+Math.imul(m,J)|0,a=a+Math.imul(m,K)|0;var bt=(c+(n=n+Math.imul(f,$)|0)|0)+((8191&(i=(i=i+Math.imul(f,tt)|0)+Math.imul(h,$)|0))<<13)|0;c=((a=a+Math.imul(h,tt)|0)+(i>>>13)|0)+(bt>>>26)|0,bt&=67108863,n=Math.imul(M,U),i=(i=Math.imul(M,V))+Math.imul(S,U)|0,a=Math.imul(S,V),n=n+Math.imul(T,q)|0,i=(i=i+Math.imul(T,G)|0)+Math.imul(k,q)|0,a=a+Math.imul(k,G)|0,n=n+Math.imul(b,W)|0,i=(i=i+Math.imul(b,X)|0)+Math.imul(_,W)|0,a=a+Math.imul(_,X)|0,n=n+Math.imul(v,J)|0,i=(i=i+Math.imul(v,K)|0)+Math.imul(y,J)|0,a=a+Math.imul(y,K)|0,n=n+Math.imul(d,$)|0,i=(i=i+Math.imul(d,tt)|0)+Math.imul(m,$)|0,a=a+Math.imul(m,tt)|0;var _t=(c+(n=n+Math.imul(f,rt)|0)|0)+((8191&(i=(i=i+Math.imul(f,nt)|0)+Math.imul(h,rt)|0))<<13)|0;c=((a=a+Math.imul(h,nt)|0)+(i>>>13)|0)+(_t>>>26)|0,_t&=67108863,n=Math.imul(L,U),i=(i=Math.imul(L,V))+Math.imul(C,U)|0,a=Math.imul(C,V),n=n+Math.imul(M,q)|0,i=(i=i+Math.imul(M,G)|0)+Math.imul(S,q)|0,a=a+Math.imul(S,G)|0,n=n+Math.imul(T,W)|0,i=(i=i+Math.imul(T,X)|0)+Math.imul(k,W)|0,a=a+Math.imul(k,X)|0,n=n+Math.imul(b,J)|0,i=(i=i+Math.imul(b,K)|0)+Math.imul(_,J)|0,a=a+Math.imul(_,K)|0,n=n+Math.imul(v,$)|0,i=(i=i+Math.imul(v,tt)|0)+Math.imul(y,$)|0,a=a+Math.imul(y,tt)|0,n=n+Math.imul(d,rt)|0,i=(i=i+Math.imul(d,nt)|0)+Math.imul(m,rt)|0,a=a+Math.imul(m,nt)|0;var wt=(c+(n=n+Math.imul(f,at)|0)|0)+((8191&(i=(i=i+Math.imul(f,ot)|0)+Math.imul(h,at)|0))<<13)|0;c=((a=a+Math.imul(h,ot)|0)+(i>>>13)|0)+(wt>>>26)|0,wt&=67108863,n=Math.imul(I,U),i=(i=Math.imul(I,V))+Math.imul(O,U)|0,a=Math.imul(O,V),n=n+Math.imul(L,q)|0,i=(i=i+Math.imul(L,G)|0)+Math.imul(C,q)|0,a=a+Math.imul(C,G)|0,n=n+Math.imul(M,W)|0,i=(i=i+Math.imul(M,X)|0)+Math.imul(S,W)|0,a=a+Math.imul(S,X)|0,n=n+Math.imul(T,J)|0,i=(i=i+Math.imul(T,K)|0)+Math.imul(k,J)|0,a=a+Math.imul(k,K)|0,n=n+Math.imul(b,$)|0,i=(i=i+Math.imul(b,tt)|0)+Math.imul(_,$)|0,a=a+Math.imul(_,tt)|0,n=n+Math.imul(v,rt)|0,i=(i=i+Math.imul(v,nt)|0)+Math.imul(y,rt)|0,a=a+Math.imul(y,nt)|0,n=n+Math.imul(d,at)|0,i=(i=i+Math.imul(d,ot)|0)+Math.imul(m,at)|0,a=a+Math.imul(m,ot)|0;var Tt=(c+(n=n+Math.imul(f,lt)|0)|0)+((8191&(i=(i=i+Math.imul(f,ct)|0)+Math.imul(h,lt)|0))<<13)|0;c=((a=a+Math.imul(h,ct)|0)+(i>>>13)|0)+(Tt>>>26)|0,Tt&=67108863,n=Math.imul(D,U),i=(i=Math.imul(D,V))+Math.imul(R,U)|0,a=Math.imul(R,V),n=n+Math.imul(I,q)|0,i=(i=i+Math.imul(I,G)|0)+Math.imul(O,q)|0,a=a+Math.imul(O,G)|0,n=n+Math.imul(L,W)|0,i=(i=i+Math.imul(L,X)|0)+Math.imul(C,W)|0,a=a+Math.imul(C,X)|0,n=n+Math.imul(M,J)|0,i=(i=i+Math.imul(M,K)|0)+Math.imul(S,J)|0,a=a+Math.imul(S,K)|0,n=n+Math.imul(T,$)|0,i=(i=i+Math.imul(T,tt)|0)+Math.imul(k,$)|0,a=a+Math.imul(k,tt)|0,n=n+Math.imul(b,rt)|0,i=(i=i+Math.imul(b,nt)|0)+Math.imul(_,rt)|0,a=a+Math.imul(_,nt)|0,n=n+Math.imul(v,at)|0,i=(i=i+Math.imul(v,ot)|0)+Math.imul(y,at)|0,a=a+Math.imul(y,ot)|0,n=n+Math.imul(d,lt)|0,i=(i=i+Math.imul(d,ct)|0)+Math.imul(m,lt)|0,a=a+Math.imul(m,ct)|0;var kt=(c+(n=n+Math.imul(f,ft)|0)|0)+((8191&(i=(i=i+Math.imul(f,ht)|0)+Math.imul(h,ft)|0))<<13)|0;c=((a=a+Math.imul(h,ht)|0)+(i>>>13)|0)+(kt>>>26)|0,kt&=67108863,n=Math.imul(B,U),i=(i=Math.imul(B,V))+Math.imul(N,U)|0,a=Math.imul(N,V),n=n+Math.imul(D,q)|0,i=(i=i+Math.imul(D,G)|0)+Math.imul(R,q)|0,a=a+Math.imul(R,G)|0,n=n+Math.imul(I,W)|0,i=(i=i+Math.imul(I,X)|0)+Math.imul(O,W)|0,a=a+Math.imul(O,X)|0,n=n+Math.imul(L,J)|0,i=(i=i+Math.imul(L,K)|0)+Math.imul(C,J)|0,a=a+Math.imul(C,K)|0,n=n+Math.imul(M,$)|0,i=(i=i+Math.imul(M,tt)|0)+Math.imul(S,$)|0,a=a+Math.imul(S,tt)|0,n=n+Math.imul(T,rt)|0,i=(i=i+Math.imul(T,nt)|0)+Math.imul(k,rt)|0,a=a+Math.imul(k,nt)|0,n=n+Math.imul(b,at)|0,i=(i=i+Math.imul(b,ot)|0)+Math.imul(_,at)|0,a=a+Math.imul(_,ot)|0,n=n+Math.imul(v,lt)|0,i=(i=i+Math.imul(v,ct)|0)+Math.imul(y,lt)|0,a=a+Math.imul(y,ct)|0,n=n+Math.imul(d,ft)|0,i=(i=i+Math.imul(d,ht)|0)+Math.imul(m,ft)|0,a=a+Math.imul(m,ht)|0;var At=(c+(n=n+Math.imul(f,dt)|0)|0)+((8191&(i=(i=i+Math.imul(f,mt)|0)+Math.imul(h,dt)|0))<<13)|0;c=((a=a+Math.imul(h,mt)|0)+(i>>>13)|0)+(At>>>26)|0,At&=67108863,n=Math.imul(B,q),i=(i=Math.imul(B,G))+Math.imul(N,q)|0,a=Math.imul(N,G),n=n+Math.imul(D,W)|0,i=(i=i+Math.imul(D,X)|0)+Math.imul(R,W)|0,a=a+Math.imul(R,X)|0,n=n+Math.imul(I,J)|0,i=(i=i+Math.imul(I,K)|0)+Math.imul(O,J)|0,a=a+Math.imul(O,K)|0,n=n+Math.imul(L,$)|0,i=(i=i+Math.imul(L,tt)|0)+Math.imul(C,$)|0,a=a+Math.imul(C,tt)|0,n=n+Math.imul(M,rt)|0,i=(i=i+Math.imul(M,nt)|0)+Math.imul(S,rt)|0,a=a+Math.imul(S,nt)|0,n=n+Math.imul(T,at)|0,i=(i=i+Math.imul(T,ot)|0)+Math.imul(k,at)|0,a=a+Math.imul(k,ot)|0,n=n+Math.imul(b,lt)|0,i=(i=i+Math.imul(b,ct)|0)+Math.imul(_,lt)|0,a=a+Math.imul(_,ct)|0,n=n+Math.imul(v,ft)|0,i=(i=i+Math.imul(v,ht)|0)+Math.imul(y,ft)|0,a=a+Math.imul(y,ht)|0;var Mt=(c+(n=n+Math.imul(d,dt)|0)|0)+((8191&(i=(i=i+Math.imul(d,mt)|0)+Math.imul(m,dt)|0))<<13)|0;c=((a=a+Math.imul(m,mt)|0)+(i>>>13)|0)+(Mt>>>26)|0,Mt&=67108863,n=Math.imul(B,W),i=(i=Math.imul(B,X))+Math.imul(N,W)|0,a=Math.imul(N,X),n=n+Math.imul(D,J)|0,i=(i=i+Math.imul(D,K)|0)+Math.imul(R,J)|0,a=a+Math.imul(R,K)|0,n=n+Math.imul(I,$)|0,i=(i=i+Math.imul(I,tt)|0)+Math.imul(O,$)|0,a=a+Math.imul(O,tt)|0,n=n+Math.imul(L,rt)|0,i=(i=i+Math.imul(L,nt)|0)+Math.imul(C,rt)|0,a=a+Math.imul(C,nt)|0,n=n+Math.imul(M,at)|0,i=(i=i+Math.imul(M,ot)|0)+Math.imul(S,at)|0,a=a+Math.imul(S,ot)|0,n=n+Math.imul(T,lt)|0,i=(i=i+Math.imul(T,ct)|0)+Math.imul(k,lt)|0,a=a+Math.imul(k,ct)|0,n=n+Math.imul(b,ft)|0,i=(i=i+Math.imul(b,ht)|0)+Math.imul(_,ft)|0,a=a+Math.imul(_,ht)|0;var St=(c+(n=n+Math.imul(v,dt)|0)|0)+((8191&(i=(i=i+Math.imul(v,mt)|0)+Math.imul(y,dt)|0))<<13)|0;c=((a=a+Math.imul(y,mt)|0)+(i>>>13)|0)+(St>>>26)|0,St&=67108863,n=Math.imul(B,J),i=(i=Math.imul(B,K))+Math.imul(N,J)|0,a=Math.imul(N,K),n=n+Math.imul(D,$)|0,i=(i=i+Math.imul(D,tt)|0)+Math.imul(R,$)|0,a=a+Math.imul(R,tt)|0,n=n+Math.imul(I,rt)|0,i=(i=i+Math.imul(I,nt)|0)+Math.imul(O,rt)|0,a=a+Math.imul(O,nt)|0,n=n+Math.imul(L,at)|0,i=(i=i+Math.imul(L,ot)|0)+Math.imul(C,at)|0,a=a+Math.imul(C,ot)|0,n=n+Math.imul(M,lt)|0,i=(i=i+Math.imul(M,ct)|0)+Math.imul(S,lt)|0,a=a+Math.imul(S,ct)|0,n=n+Math.imul(T,ft)|0,i=(i=i+Math.imul(T,ht)|0)+Math.imul(k,ft)|0,a=a+Math.imul(k,ht)|0;var Et=(c+(n=n+Math.imul(b,dt)|0)|0)+((8191&(i=(i=i+Math.imul(b,mt)|0)+Math.imul(_,dt)|0))<<13)|0;c=((a=a+Math.imul(_,mt)|0)+(i>>>13)|0)+(Et>>>26)|0,Et&=67108863,n=Math.imul(B,$),i=(i=Math.imul(B,tt))+Math.imul(N,$)|0,a=Math.imul(N,tt),n=n+Math.imul(D,rt)|0,i=(i=i+Math.imul(D,nt)|0)+Math.imul(R,rt)|0,a=a+Math.imul(R,nt)|0,n=n+Math.imul(I,at)|0,i=(i=i+Math.imul(I,ot)|0)+Math.imul(O,at)|0,a=a+Math.imul(O,ot)|0,n=n+Math.imul(L,lt)|0,i=(i=i+Math.imul(L,ct)|0)+Math.imul(C,lt)|0,a=a+Math.imul(C,ct)|0,n=n+Math.imul(M,ft)|0,i=(i=i+Math.imul(M,ht)|0)+Math.imul(S,ft)|0,a=a+Math.imul(S,ht)|0;var Lt=(c+(n=n+Math.imul(T,dt)|0)|0)+((8191&(i=(i=i+Math.imul(T,mt)|0)+Math.imul(k,dt)|0))<<13)|0;c=((a=a+Math.imul(k,mt)|0)+(i>>>13)|0)+(Lt>>>26)|0,Lt&=67108863,n=Math.imul(B,rt),i=(i=Math.imul(B,nt))+Math.imul(N,rt)|0,a=Math.imul(N,nt),n=n+Math.imul(D,at)|0,i=(i=i+Math.imul(D,ot)|0)+Math.imul(R,at)|0,a=a+Math.imul(R,ot)|0,n=n+Math.imul(I,lt)|0,i=(i=i+Math.imul(I,ct)|0)+Math.imul(O,lt)|0,a=a+Math.imul(O,ct)|0,n=n+Math.imul(L,ft)|0,i=(i=i+Math.imul(L,ht)|0)+Math.imul(C,ft)|0,a=a+Math.imul(C,ht)|0;var Ct=(c+(n=n+Math.imul(M,dt)|0)|0)+((8191&(i=(i=i+Math.imul(M,mt)|0)+Math.imul(S,dt)|0))<<13)|0;c=((a=a+Math.imul(S,mt)|0)+(i>>>13)|0)+(Ct>>>26)|0,Ct&=67108863,n=Math.imul(B,at),i=(i=Math.imul(B,ot))+Math.imul(N,at)|0,a=Math.imul(N,ot),n=n+Math.imul(D,lt)|0,i=(i=i+Math.imul(D,ct)|0)+Math.imul(R,lt)|0,a=a+Math.imul(R,ct)|0,n=n+Math.imul(I,ft)|0,i=(i=i+Math.imul(I,ht)|0)+Math.imul(O,ft)|0,a=a+Math.imul(O,ht)|0;var Pt=(c+(n=n+Math.imul(L,dt)|0)|0)+((8191&(i=(i=i+Math.imul(L,mt)|0)+Math.imul(C,dt)|0))<<13)|0;c=((a=a+Math.imul(C,mt)|0)+(i>>>13)|0)+(Pt>>>26)|0,Pt&=67108863,n=Math.imul(B,lt),i=(i=Math.imul(B,ct))+Math.imul(N,lt)|0,a=Math.imul(N,ct),n=n+Math.imul(D,ft)|0,i=(i=i+Math.imul(D,ht)|0)+Math.imul(R,ft)|0,a=a+Math.imul(R,ht)|0;var It=(c+(n=n+Math.imul(I,dt)|0)|0)+((8191&(i=(i=i+Math.imul(I,mt)|0)+Math.imul(O,dt)|0))<<13)|0;c=((a=a+Math.imul(O,mt)|0)+(i>>>13)|0)+(It>>>26)|0,It&=67108863,n=Math.imul(B,ft),i=(i=Math.imul(B,ht))+Math.imul(N,ft)|0,a=Math.imul(N,ht);var Ot=(c+(n=n+Math.imul(D,dt)|0)|0)+((8191&(i=(i=i+Math.imul(D,mt)|0)+Math.imul(R,dt)|0))<<13)|0;c=((a=a+Math.imul(R,mt)|0)+(i>>>13)|0)+(Ot>>>26)|0,Ot&=67108863;var zt=(c+(n=Math.imul(B,dt))|0)+((8191&(i=(i=Math.imul(B,mt))+Math.imul(N,dt)|0))<<13)|0;return c=((a=Math.imul(N,mt))+(i>>>13)|0)+(zt>>>26)|0,zt&=67108863,l[0]=gt,l[1]=vt,l[2]=yt,l[3]=xt,l[4]=bt,l[5]=_t,l[6]=wt,l[7]=Tt,l[8]=kt,l[9]=At,l[10]=Mt,l[11]=St,l[12]=Et,l[13]=Lt,l[14]=Ct,l[15]=Pt,l[16]=It,l[17]=Ot,l[18]=zt,0!==c&&(l[19]=c,r.length++),r};function m(t,e,r){return(new g).mulp(t,e,r)}function g(t,e){this.x=t,this.y=e}Math.imul||(d=p),a.prototype.mulTo=function(t,e){var r=this.length+t.length;return 10===this.length&&10===t.length?d(this,t,e):r<63?p(this,t,e):r<1024?function(t,e,r){r.negative=e.negative^t.negative,r.length=t.length+e.length;for(var n=0,i=0,a=0;a>>26)|0)>>>26,o&=67108863}r.words[a]=s,n=o,o=i}return 0!==n?r.words[a]=n:r.length--,r.strip()}(this,t,e):m(this,t,e)},g.prototype.makeRBT=function(t){for(var e=new Array(t),r=a.prototype._countBits(t)-1,n=0;n>=1;return n},g.prototype.permute=function(t,e,r,n,i,a){for(var o=0;o>>=1)i++;return 1<>>=13,r[2*o+1]=8191&a,a>>>=13;for(o=2*e;o>=26,e+=i/67108864|0,e+=a>>>26,this.words[r]=67108863&a}return 0!==e&&(this.words[r]=e,this.length++),this},a.prototype.muln=function(t){return this.clone().imuln(t)},a.prototype.sqr=function(){return this.mul(this)},a.prototype.isqr=function(){return this.imul(this.clone())},a.prototype.pow=function(t){var e=function(t){for(var e=new Array(t.bitLength()),r=0;r>>i}return e}(t);if(0===e.length)return new a(1);for(var r=this,n=0;n=0);var e,r=t%26,i=(t-r)/26,a=67108863>>>26-r<<26-r;if(0!==r){var o=0;for(e=0;e>>26-r}o&&(this.words[e]=o,this.length++)}if(0!==i){for(e=this.length-1;e>=0;e--)this.words[e+i]=this.words[e];for(e=0;e=0),i=e?(e-e%26)/26:0;var a=t%26,o=Math.min((t-a)/26,this.length),s=67108863^67108863>>>a<o)for(this.length-=o,c=0;c=0&&(0!==u||c>=i);c--){var f=0|this.words[c];this.words[c]=u<<26-a|f>>>a,u=f&s}return l&&0!==u&&(l.words[l.length++]=u),0===this.length&&(this.words[0]=0,this.length=1),this.strip()},a.prototype.ishrn=function(t,e,r){return n(0===this.negative),this.iushrn(t,e,r)},a.prototype.shln=function(t){return this.clone().ishln(t)},a.prototype.ushln=function(t){return this.clone().iushln(t)},a.prototype.shrn=function(t){return this.clone().ishrn(t)},a.prototype.ushrn=function(t){return this.clone().iushrn(t)},a.prototype.testn=function(t){n("number"==typeof t&&t>=0);var e=t%26,r=(t-e)/26,i=1<=0);var e=t%26,r=(t-e)/26;if(n(0===this.negative,"imaskn works only with positive numbers"),this.length<=r)return this;if(0!==e&&r++,this.length=Math.min(r,this.length),0!==e){var i=67108863^67108863>>>e<=67108864;e++)this.words[e]-=67108864,e===this.length-1?this.words[e+1]=1:this.words[e+1]++;return this.length=Math.max(this.length,e+1),this},a.prototype.isubn=function(t){if(n("number"==typeof t),n(t<67108864),t<0)return this.iaddn(-t);if(0!==this.negative)return this.negative=0,this.iaddn(t),this.negative=1,this;if(this.words[0]-=t,1===this.length&&this.words[0]<0)this.words[0]=-this.words[0],this.negative=1;else for(var e=0;e>26)-(l/67108864|0),this.words[i+r]=67108863&a}for(;i>26,this.words[i+r]=67108863&a;if(0===s)return this.strip();for(n(-1===s),s=0,i=0;i>26,this.words[i]=67108863&a;return this.negative=1,this.strip()},a.prototype._wordDiv=function(t,e){var r=(this.length,t.length),n=this.clone(),i=t,o=0|i.words[i.length-1];0!==(r=26-this._countBits(o))&&(i=i.ushln(r),n.iushln(r),o=0|i.words[i.length-1]);var s,l=n.length-i.length;if("mod"!==e){(s=new a(null)).length=l+1,s.words=new Array(s.length);for(var c=0;c=0;f--){var h=67108864*(0|n.words[i.length+f])+(0|n.words[i.length+f-1]);for(h=Math.min(h/o|0,67108863),n._ishlnsubmul(i,h,f);0!==n.negative;)h--,n.negative=0,n._ishlnsubmul(i,1,f),n.isZero()||(n.negative^=1);s&&(s.words[f]=h)}return s&&s.strip(),n.strip(),"div"!==e&&0!==r&&n.iushrn(r),{div:s||null,mod:n}},a.prototype.divmod=function(t,e,r){return n(!t.isZero()),this.isZero()?{div:new a(0),mod:new a(0)}:0!==this.negative&&0===t.negative?(s=this.neg().divmod(t,e),"mod"!==e&&(i=s.div.neg()),"div"!==e&&(o=s.mod.neg(),r&&0!==o.negative&&o.iadd(t)),{div:i,mod:o}):0===this.negative&&0!==t.negative?(s=this.divmod(t.neg(),e),"mod"!==e&&(i=s.div.neg()),{div:i,mod:s.mod}):0!=(this.negative&t.negative)?(s=this.neg().divmod(t.neg(),e),"div"!==e&&(o=s.mod.neg(),r&&0!==o.negative&&o.isub(t)),{div:s.div,mod:o}):t.length>this.length||this.cmp(t)<0?{div:new a(0),mod:this}:1===t.length?"div"===e?{div:this.divn(t.words[0]),mod:null}:"mod"===e?{div:null,mod:new a(this.modn(t.words[0]))}:{div:this.divn(t.words[0]),mod:new a(this.modn(t.words[0]))}:this._wordDiv(t,e);var i,o,s},a.prototype.div=function(t){return this.divmod(t,"div",!1).div},a.prototype.mod=function(t){return this.divmod(t,"mod",!1).mod},a.prototype.umod=function(t){return this.divmod(t,"mod",!0).mod},a.prototype.divRound=function(t){var e=this.divmod(t);if(e.mod.isZero())return e.div;var r=0!==e.div.negative?e.mod.isub(t):e.mod,n=t.ushrn(1),i=t.andln(1),a=r.cmp(n);return a<0||1===i&&0===a?e.div:0!==e.div.negative?e.div.isubn(1):e.div.iaddn(1)},a.prototype.modn=function(t){n(t<=67108863);for(var e=(1<<26)%t,r=0,i=this.length-1;i>=0;i--)r=(e*r+(0|this.words[i]))%t;return r},a.prototype.idivn=function(t){n(t<=67108863);for(var e=0,r=this.length-1;r>=0;r--){var i=(0|this.words[r])+67108864*e;this.words[r]=i/t|0,e=i%t}return this.strip()},a.prototype.divn=function(t){return this.clone().idivn(t)},a.prototype.egcd=function(t){n(0===t.negative),n(!t.isZero());var e=this,r=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i=new a(1),o=new a(0),s=new a(0),l=new a(1),c=0;e.isEven()&&r.isEven();)e.iushrn(1),r.iushrn(1),++c;for(var u=r.clone(),f=e.clone();!e.isZero();){for(var h=0,p=1;0==(e.words[0]&p)&&h<26;++h,p<<=1);if(h>0)for(e.iushrn(h);h-- >0;)(i.isOdd()||o.isOdd())&&(i.iadd(u),o.isub(f)),i.iushrn(1),o.iushrn(1);for(var d=0,m=1;0==(r.words[0]&m)&&d<26;++d,m<<=1);if(d>0)for(r.iushrn(d);d-- >0;)(s.isOdd()||l.isOdd())&&(s.iadd(u),l.isub(f)),s.iushrn(1),l.iushrn(1);e.cmp(r)>=0?(e.isub(r),i.isub(s),o.isub(l)):(r.isub(e),s.isub(i),l.isub(o))}return{a:s,b:l,gcd:r.iushln(c)}},a.prototype._invmp=function(t){n(0===t.negative),n(!t.isZero());var e=this,r=t.clone();e=0!==e.negative?e.umod(t):e.clone();for(var i,o=new a(1),s=new a(0),l=r.clone();e.cmpn(1)>0&&r.cmpn(1)>0;){for(var c=0,u=1;0==(e.words[0]&u)&&c<26;++c,u<<=1);if(c>0)for(e.iushrn(c);c-- >0;)o.isOdd()&&o.iadd(l),o.iushrn(1);for(var f=0,h=1;0==(r.words[0]&h)&&f<26;++f,h<<=1);if(f>0)for(r.iushrn(f);f-- >0;)s.isOdd()&&s.iadd(l),s.iushrn(1);e.cmp(r)>=0?(e.isub(r),o.isub(s)):(r.isub(e),s.isub(o))}return(i=0===e.cmpn(1)?o:s).cmpn(0)<0&&i.iadd(t),i},a.prototype.gcd=function(t){if(this.isZero())return t.abs();if(t.isZero())return this.abs();var e=this.clone(),r=t.clone();e.negative=0,r.negative=0;for(var n=0;e.isEven()&&r.isEven();n++)e.iushrn(1),r.iushrn(1);for(;;){for(;e.isEven();)e.iushrn(1);for(;r.isEven();)r.iushrn(1);var i=e.cmp(r);if(i<0){var a=e;e=r,r=a}else if(0===i||0===r.cmpn(1))break;e.isub(r)}return r.iushln(n)},a.prototype.invm=function(t){return this.egcd(t).a.umod(t)},a.prototype.isEven=function(){return 0==(1&this.words[0])},a.prototype.isOdd=function(){return 1==(1&this.words[0])},a.prototype.andln=function(t){return this.words[0]&t},a.prototype.bincn=function(t){n("number"==typeof t);var e=t%26,r=(t-e)/26,i=1<>>26,s&=67108863,this.words[o]=s}return 0!==a&&(this.words[o]=a,this.length++),this},a.prototype.isZero=function(){return 1===this.length&&0===this.words[0]},a.prototype.cmpn=function(t){var e,r=t<0;if(0!==this.negative&&!r)return-1;if(0===this.negative&&r)return 1;if(this.strip(),this.length>1)e=1;else{r&&(t=-t),n(t<=67108863,"Number is too big");var i=0|this.words[0];e=i===t?0:it.length)return 1;if(this.length=0;r--){var n=0|this.words[r],i=0|t.words[r];if(n!==i){ni&&(e=1);break}}return e},a.prototype.gtn=function(t){return 1===this.cmpn(t)},a.prototype.gt=function(t){return 1===this.cmp(t)},a.prototype.gten=function(t){return this.cmpn(t)>=0},a.prototype.gte=function(t){return this.cmp(t)>=0},a.prototype.ltn=function(t){return-1===this.cmpn(t)},a.prototype.lt=function(t){return-1===this.cmp(t)},a.prototype.lten=function(t){return this.cmpn(t)<=0},a.prototype.lte=function(t){return this.cmp(t)<=0},a.prototype.eqn=function(t){return 0===this.cmpn(t)},a.prototype.eq=function(t){return 0===this.cmp(t)},a.red=function(t){return new T(t)},a.prototype.toRed=function(t){return n(!this.red,"Already a number in reduction context"),n(0===this.negative,"red works only with positives"),t.convertTo(this)._forceRed(t)},a.prototype.fromRed=function(){return n(this.red,"fromRed works only with numbers in reduction context"),this.red.convertFrom(this)},a.prototype._forceRed=function(t){return this.red=t,this},a.prototype.forceRed=function(t){return n(!this.red,"Already a number in reduction context"),this._forceRed(t)},a.prototype.redAdd=function(t){return n(this.red,"redAdd works only with red numbers"),this.red.add(this,t)},a.prototype.redIAdd=function(t){return n(this.red,"redIAdd works only with red numbers"),this.red.iadd(this,t)},a.prototype.redSub=function(t){return n(this.red,"redSub works only with red numbers"),this.red.sub(this,t)},a.prototype.redISub=function(t){return n(this.red,"redISub works only with red numbers"),this.red.isub(this,t)},a.prototype.redShl=function(t){return n(this.red,"redShl works only with red numbers"),this.red.shl(this,t)},a.prototype.redMul=function(t){return n(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.mul(this,t)},a.prototype.redIMul=function(t){return n(this.red,"redMul works only with red numbers"),this.red._verify2(this,t),this.red.imul(this,t)},a.prototype.redSqr=function(){return n(this.red,"redSqr works only with red numbers"),this.red._verify1(this),this.red.sqr(this)},a.prototype.redISqr=function(){return n(this.red,"redISqr works only with red numbers"),this.red._verify1(this),this.red.isqr(this)},a.prototype.redSqrt=function(){return n(this.red,"redSqrt works only with red numbers"),this.red._verify1(this),this.red.sqrt(this)},a.prototype.redInvm=function(){return n(this.red,"redInvm works only with red numbers"),this.red._verify1(this),this.red.invm(this)},a.prototype.redNeg=function(){return n(this.red,"redNeg works only with red numbers"),this.red._verify1(this),this.red.neg(this)},a.prototype.redPow=function(t){return n(this.red&&!t.red,"redPow(normalNum)"),this.red._verify1(this),this.red.pow(this,t)};var v={k256:null,p224:null,p192:null,p25519:null};function y(t,e){this.name=t,this.p=new a(e,16),this.n=this.p.bitLength(),this.k=new a(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function x(){y.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function b(){y.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function _(){y.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function w(){y.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function T(t){if("string"==typeof t){var e=a._prime(t);this.m=e.p,this.prime=e}else n(t.gtn(1),"modulus must be greater than 1"),this.m=t,this.prime=null}function k(t){T.call(this,t),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new a(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}y.prototype._tmp=function(){var t=new a(null);return t.words=new Array(Math.ceil(this.n/13)),t},y.prototype.ireduce=function(t){var e,r=t;do{this.split(r,this.tmp),e=(r=(r=this.imulK(r)).iadd(this.tmp)).bitLength()}while(e>this.n);var n=e0?r.isub(this.p):void 0!==r.strip?r.strip():r._strip(),r},y.prototype.split=function(t,e){t.iushrn(this.n,0,e)},y.prototype.imulK=function(t){return t.imul(this.k)},i(x,y),x.prototype.split=function(t,e){for(var r=Math.min(t.length,9),n=0;n>>22,i=a}i>>>=22,t.words[n-10]=i,0===i&&t.length>10?t.length-=10:t.length-=9},x.prototype.imulK=function(t){t.words[t.length]=0,t.words[t.length+1]=0,t.length+=2;for(var e=0,r=0;r>>=26,t.words[r]=i,e=n}return 0!==e&&(t.words[t.length++]=e),t},a._prime=function(t){if(v[t])return v[t];var e;if("k256"===t)e=new x;else if("p224"===t)e=new b;else if("p192"===t)e=new _;else{if("p25519"!==t)throw new Error("Unknown prime "+t);e=new w}return v[t]=e,e},T.prototype._verify1=function(t){n(0===t.negative,"red works only with positives"),n(t.red,"red works only with red numbers")},T.prototype._verify2=function(t,e){n(0==(t.negative|e.negative),"red works only with positives"),n(t.red&&t.red===e.red,"red works only with red numbers")},T.prototype.imod=function(t){return this.prime?this.prime.ireduce(t)._forceRed(this):t.umod(this.m)._forceRed(this)},T.prototype.neg=function(t){return t.isZero()?t.clone():this.m.sub(t)._forceRed(this)},T.prototype.add=function(t,e){this._verify2(t,e);var r=t.add(e);return r.cmp(this.m)>=0&&r.isub(this.m),r._forceRed(this)},T.prototype.iadd=function(t,e){this._verify2(t,e);var r=t.iadd(e);return r.cmp(this.m)>=0&&r.isub(this.m),r},T.prototype.sub=function(t,e){this._verify2(t,e);var r=t.sub(e);return r.cmpn(0)<0&&r.iadd(this.m),r._forceRed(this)},T.prototype.isub=function(t,e){this._verify2(t,e);var r=t.isub(e);return r.cmpn(0)<0&&r.iadd(this.m),r},T.prototype.shl=function(t,e){return this._verify1(t),this.imod(t.ushln(e))},T.prototype.imul=function(t,e){return this._verify2(t,e),this.imod(t.imul(e))},T.prototype.mul=function(t,e){return this._verify2(t,e),this.imod(t.mul(e))},T.prototype.isqr=function(t){return this.imul(t,t.clone())},T.prototype.sqr=function(t){return this.mul(t,t)},T.prototype.sqrt=function(t){if(t.isZero())return t.clone();var e=this.m.andln(3);if(n(e%2==1),3===e){var r=this.m.add(new a(1)).iushrn(2);return this.pow(t,r)}for(var i=this.m.subn(1),o=0;!i.isZero()&&0===i.andln(1);)o++,i.iushrn(1);n(!i.isZero());var s=new a(1).toRed(this),l=s.redNeg(),c=this.m.subn(1).iushrn(1),u=this.m.bitLength();for(u=new a(2*u*u).toRed(this);0!==this.pow(u,c).cmp(l);)u.redIAdd(l);for(var f=this.pow(u,i),h=this.pow(t,i.addn(1).iushrn(1)),p=this.pow(t,i),d=o;0!==p.cmp(s);){for(var m=p,g=0;0!==m.cmp(s);g++)m=m.redSqr();n(g=0;n--){for(var c=e.words[n],u=l-1;u>=0;u--){var f=c>>u&1;i!==r[0]&&(i=this.sqr(i)),0!==f||0!==o?(o<<=1,o|=f,(4===++s||0===n&&0===u)&&(i=this.mul(i,r[o]),s=0,o=0)):s=0}l=26}return i},T.prototype.convertTo=function(t){var e=t.umod(this.m);return e===t?e.clone():e},T.prototype.convertFrom=function(t){var e=t.clone();return e.red=null,e},a.mont=function(t){return new k(t)},i(k,T),k.prototype.convertTo=function(t){return this.imod(t.ushln(this.shift))},k.prototype.convertFrom=function(t){var e=this.imod(t.mul(this.rinv));return e.red=null,e},k.prototype.imul=function(t,e){if(t.isZero()||e.isZero())return t.words[0]=0,t.length=1,t;var r=t.imul(e),n=r.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=r.isub(n).iushrn(this.shift),a=i;return i.cmp(this.m)>=0?a=i.isub(this.m):i.cmpn(0)<0&&(a=i.iadd(this.m)),a._forceRed(this)},k.prototype.mul=function(t,e){if(t.isZero()||e.isZero())return new a(0)._forceRed(this);var r=t.mul(e),n=r.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m),i=r.isub(n).iushrn(this.shift),o=i;return i.cmp(this.m)>=0?o=i.isub(this.m):i.cmpn(0)<0&&(o=i.iadd(this.m)),o._forceRed(this)},k.prototype.invm=function(t){return this.imod(t._invmp(this.m).mul(this.r2))._forceRed(this)}}(void 0===e||e,this)},{buffer:2}],34:[function(t,e,r){"use strict";e.exports=function(t){var e,r,n,i=t.length,a=0;for(e=0;e>>1;if(!(u<=0)){var f,h=i.mallocDouble(2*u*s),p=i.mallocInt32(s);if((s=l(t,u,h,p))>0){if(1===u&&n)a.init(s),f=a.sweepComplete(u,r,0,s,h,p,0,s,h,p);else{var d=i.mallocDouble(2*u*c),m=i.mallocInt32(c);(c=l(e,u,d,m))>0&&(a.init(s+c),f=1===u?a.sweepBipartite(u,r,0,s,h,p,0,c,d,m):o(u,r,n,s,h,p,c,d,m),i.free(d),i.free(m))}i.free(h),i.free(p)}return f}}}function u(t,e){n.push([t,e])}function f(t){return n=[],c(t,t,u,!0),n}function h(t,e){return n=[],c(t,e,u,!1),n}},{"./lib/intersect":37,"./lib/sweep":41,"typedarray-pool":308}],36:[function(t,e,r){"use strict";function n(t){return t?function(t,e,r,n,i,a,o,s,l,c,u){return i-n>l-s?function(t,e,r,n,i,a,o,s,l,c,u){for(var f=2*t,h=n,p=f*n;hc-l?n?function(t,e,r,n,i,a,o,s,l,c,u){for(var f=2*t,h=n,p=f*n;h0;){var L=6*(S-=1),C=v[L],P=v[L+1],I=v[L+2],O=v[L+3],z=v[L+4],D=v[L+5],R=2*S,F=y[R],B=y[R+1],N=1&D,j=!!(16&D),U=u,V=w,H=k,q=A;if(N&&(U=k,V=A,H=u,q=w),!(2&D&&(I=p(t,C,P,I,U,V,B),P>=I)||4&D&&(P=d(t,C,P,I,U,V,F))>=I)){var G=I-P,Y=z-O;if(j){if(t*G*(G+Y)<1<<22){if(void 0!==(M=l.scanComplete(t,C,e,P,I,U,V,O,z,H,q)))return M;continue}}else{if(t*Math.min(G,Y)<128){if(void 0!==(M=o(t,C,e,N,P,I,U,V,O,z,H,q)))return M;continue}if(t*G*Y<1<<22){if(void 0!==(M=l.scanBipartite(t,C,e,N,P,I,U,V,O,z,H,q)))return M;continue}}var W=f(t,C,P,I,U,V,F,B);if(P=p0)&&!(p1>=hi)"),h=u("lo===p0"),p=u("lo>>1,f=2*t,h=u,p=o[f*u+e];for(;l=y?(h=v,p=y):g>=b?(h=m,p=g):(h=x,p=b):y>=b?(h=v,p=y):b>=g?(h=m,p=g):(h=x,p=b);for(var _=f*(c-1),w=f*h,T=0;Tr&&i[f+e]>c;--u,f-=o){for(var h=f,p=f+o,d=0;dh;++h,l+=s){if(i[l+f]===o)if(u===h)u+=1,c+=s;else{for(var p=0;s>p;++p){var d=i[l+p];i[l+p]=i[c],i[c++]=d}var m=a[h];a[h]=a[u],a[u++]=m}}return u},"loh;++h,l+=s){if(i[l+f]p;++p){var d=i[l+p];i[l+p]=i[c],i[c++]=d}var m=a[h];a[h]=a[u],a[u++]=m}}return u},"lo<=p0":function(t,e,r,n,i,a,o){for(var s=2*t,l=s*r,c=l,u=r,f=t+e,h=r;n>h;++h,l+=s){if(i[l+f]<=o)if(u===h)u+=1,c+=s;else{for(var p=0;s>p;++p){var d=i[l+p];i[l+p]=i[c],i[c++]=d}var m=a[h];a[h]=a[u],a[u++]=m}}return u},"hi<=p0":function(t,e,r,n,i,a,o){for(var s=2*t,l=s*r,c=l,u=r,f=t+e,h=r;n>h;++h,l+=s){if(i[l+f]<=o)if(u===h)u+=1,c+=s;else{for(var p=0;s>p;++p){var d=i[l+p];i[l+p]=i[c],i[c++]=d}var m=a[h];a[h]=a[u],a[u++]=m}}return u},"lop;++p,l+=s){var d=i[l+f],m=i[l+h];if(dg;++g){var v=i[l+g];i[l+g]=i[c],i[c++]=v}var y=a[p];a[p]=a[u],a[u++]=y}}return u},"lo<=p0&&p0<=hi":function(t,e,r,n,i,a,o){for(var s=2*t,l=s*r,c=l,u=r,f=e,h=t+e,p=r;n>p;++p,l+=s){var d=i[l+f],m=i[l+h];if(d<=o&&o<=m)if(u===p)u+=1,c+=s;else{for(var g=0;s>g;++g){var v=i[l+g];i[l+g]=i[c],i[c++]=v}var y=a[p];a[p]=a[u],a[u++]=y}}return u},"!(lo>=p0)&&!(p1>=hi)":function(t,e,r,n,i,a,o,s){for(var l=2*t,c=l*r,u=c,f=r,h=e,p=t+e,d=r;n>d;++d,c+=l){var m=i[c+h],g=i[c+p];if(!(m>=o||s>=g))if(f===d)f+=1,u+=l;else{for(var v=0;l>v;++v){var y=i[c+v];i[c+v]=i[u],i[u++]=y}var x=a[d];a[d]=a[f],a[f++]=x}}return f}}},{}],40:[function(t,e,r){"use strict";e.exports=function(t,e){e<=128?n(0,e-1,t):function t(e,r,u){var f=(r-e+1)/6|0,h=e+f,p=r-f,d=e+r>>1,m=d-f,g=d+f,v=h,y=m,x=d,b=g,_=p,w=e+1,T=r-1,k=0;l(v,y,u)&&(k=v,v=y,y=k);l(b,_,u)&&(k=b,b=_,_=k);l(v,x,u)&&(k=v,v=x,x=k);l(y,x,u)&&(k=y,y=x,x=k);l(v,b,u)&&(k=v,v=b,b=k);l(x,b,u)&&(k=x,x=b,b=k);l(y,_,u)&&(k=y,y=_,_=k);l(y,x,u)&&(k=y,y=x,x=k);l(b,_,u)&&(k=b,b=_,_=k);for(var A=u[2*y],M=u[2*y+1],S=u[2*b],E=u[2*b+1],L=2*v,C=2*x,P=2*_,I=2*h,O=2*d,z=2*p,D=0;D<2;++D){var R=u[L+D],F=u[C+D],B=u[P+D];u[I+D]=R,u[O+D]=F,u[z+D]=B}a(m,e,u),a(g,r,u);for(var N=w;N<=T;++N)if(c(N,A,M,u))N!==w&&i(N,w,u),++w;else if(!c(N,S,E,u))for(;;){if(c(T,S,E,u)){c(T,A,M,u)?(o(N,w,T,u),++w,--T):(i(N,T,u),--T);break}if(--Tt;){var c=r[l-2],u=r[l-1];if(cr[e+1])}function c(t,e,r,n){var i=n[t*=2];return i>>1;a(h,M);var S=0,E=0;for(w=0;w=1<<28)p(l,c,E--,L=L-(1<<28)|0);else if(L>=0)p(o,s,S--,L);else if(L<=-(1<<28)){L=-L-(1<<28)|0;for(var C=0;C>>1;a(h,E);var L=0,C=0,P=0;for(k=0;k>1==h[2*k+3]>>1&&(O=2,k+=1),I<0){for(var z=-(I>>1)-1,D=0;D>1)-1;0===O?p(o,s,L--,z):1===O?p(l,c,C--,z):2===O&&p(u,f,P--,z)}}},scanBipartite:function(t,e,r,n,i,l,c,u,f,m,g,v){var y=0,x=2*t,b=e,_=e+t,w=1,T=1;n?T=1<<28:w=1<<28;for(var k=i;k>>1;a(h,E);var L=0;for(k=0;k=1<<28?(P=!n,A-=1<<28):(P=!!n,A-=1),P)d(o,s,L++,A);else{var I=v[A],O=x*A,z=g[O+e+1],D=g[O+e+1+t];t:for(var R=0;R>>1;a(h,w);var T=0;for(y=0;y=1<<28)o[T++]=x-(1<<28);else{var A=p[x-=1],M=m*x,S=f[M+e+1],E=f[M+e+1+t];t:for(var L=0;L=0;--L)if(o[L]===x){for(O=L+1;O0;){for(var p=r.pop(),d=(s=r.pop(),u=-1,f=-1,l=o[s],1);d=0||(e.flip(s,p),i(t,e,r,u,s,f),i(t,e,r,s,f,u),i(t,e,r,f,p,u),i(t,e,r,p,u,f)))}}},{"binary-search-bounds":31,"robust-in-sphere":282}],44:[function(t,e,r){"use strict";var n,i=t("binary-search-bounds");function a(t,e,r,n,i,a,o){this.cells=t,this.neighbor=e,this.flags=n,this.constraint=r,this.active=i,this.next=a,this.boundary=o}function o(t,e){return t[0]-e[0]||t[1]-e[1]||t[2]-e[2]}e.exports=function(t,e,r){var n=function(t,e){for(var r=t.cells(),n=r.length,i=0;i0||l.length>0;){for(;s.length>0;){var p=s.pop();if(c[p]!==-i){c[p]=i;u[p];for(var d=0;d<3;++d){var m=h[3*p+d];m>=0&&0===c[m]&&(f[3*p+d]?l.push(m):(s.push(m),c[m]=i))}}}var g=l;l=s,s=g,l.length=0,i=-i}var v=function(t,e,r){for(var n=0,i=0;i1&&i(r[h[p-2]],r[h[p-1]],a)>0;)t.push([h[p-1],h[p-2],o]),p-=1;h.length=p,h.push(o);var d=f.upperIds;for(p=d.length;p>1&&i(r[d[p-2]],r[d[p-1]],a)<0;)t.push([d[p-2],d[p-1],o]),p-=1;d.length=p,d.push(o)}}function u(t,e){var r;return(r=t.a[0]d[0]&&i.push(new o(d,p,2,l),new o(p,d,1,l))}i.sort(s);for(var m=i[0].a[0]-(1+Math.abs(i[0].a[0]))*Math.pow(2,-52),g=[new a([m,1],[m,0],-1,[],[],[],[])],v=[],y=(l=0,i.length);l=0}}(),a.removeTriangle=function(t,e,r){var n=this.stars;o(n[t],e,r),o(n[e],r,t),o(n[r],t,e)},a.addTriangle=function(t,e,r){var n=this.stars;n[t].push(e,r),n[e].push(r,t),n[r].push(t,e)},a.opposite=function(t,e){for(var r=this.stars[e],n=1,i=r.length;ne[2]?1:0)}function v(t,e,r){if(0!==t.length){if(e)for(var n=0;n=0;--a){var x=e[u=(S=n[a])[0]],b=x[0],_=x[1],w=t[b],T=t[_];if((w[0]-T[0]||w[1]-T[1])<0){var k=b;b=_,_=k}x[0]=b;var A,M=x[1]=S[1];for(i&&(A=x[2]);a>0&&n[a-1][0]===u;){var S,E=(S=n[--a])[1];i?e.push([M,E,A]):e.push([M,E]),M=E}i?e.push([M,_,A]):e.push([M,_])}return h}(t,e,h,g,r));return v(e,y,r),!!y||(h.length>0||g.length>0)}},{"./lib/rat-seg-intersect":51,"big-rat":18,"big-rat/cmp":16,"big-rat/to-float":30,"box-intersect":35,nextafter:260,"rat-vec":273,"robust-segment-intersect":287,"union-find":309}],51:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){var a=s(e,t),f=s(n,r),h=u(a,f);if(0===o(h))return null;var p=s(t,r),d=u(f,p),m=i(d,h),g=c(a,m);return l(t,g)};var n=t("big-rat/mul"),i=t("big-rat/div"),a=t("big-rat/sub"),o=t("big-rat/sign"),s=t("rat-vec/sub"),l=t("rat-vec/add"),c=t("rat-vec/muls");function u(t,e){return a(n(t[0],e[1]),n(t[1],e[0]))}},{"big-rat/div":17,"big-rat/mul":27,"big-rat/sign":28,"big-rat/sub":29,"rat-vec/add":272,"rat-vec/muls":274,"rat-vec/sub":275}],52:[function(t,e,r){e.exports={jet:[{index:0,rgb:[0,0,131]},{index:.125,rgb:[0,60,170]},{index:.375,rgb:[5,255,255]},{index:.625,rgb:[255,255,0]},{index:.875,rgb:[250,0,0]},{index:1,rgb:[128,0,0]}],hsv:[{index:0,rgb:[255,0,0]},{index:.169,rgb:[253,255,2]},{index:.173,rgb:[247,255,2]},{index:.337,rgb:[0,252,4]},{index:.341,rgb:[0,252,10]},{index:.506,rgb:[1,249,255]},{index:.671,rgb:[2,0,253]},{index:.675,rgb:[8,0,253]},{index:.839,rgb:[255,0,251]},{index:.843,rgb:[255,0,245]},{index:1,rgb:[255,0,6]}],hot:[{index:0,rgb:[0,0,0]},{index:.3,rgb:[230,0,0]},{index:.6,rgb:[255,210,0]},{index:1,rgb:[255,255,255]}],spring:[{index:0,rgb:[255,0,255]},{index:1,rgb:[255,255,0]}],summer:[{index:0,rgb:[0,128,102]},{index:1,rgb:[255,255,102]}],autumn:[{index:0,rgb:[255,0,0]},{index:1,rgb:[255,255,0]}],winter:[{index:0,rgb:[0,0,255]},{index:1,rgb:[0,255,128]}],bone:[{index:0,rgb:[0,0,0]},{index:.376,rgb:[84,84,116]},{index:.753,rgb:[169,200,200]},{index:1,rgb:[255,255,255]}],copper:[{index:0,rgb:[0,0,0]},{index:.804,rgb:[255,160,102]},{index:1,rgb:[255,199,127]}],greys:[{index:0,rgb:[0,0,0]},{index:1,rgb:[255,255,255]}],yignbu:[{index:0,rgb:[8,29,88]},{index:.125,rgb:[37,52,148]},{index:.25,rgb:[34,94,168]},{index:.375,rgb:[29,145,192]},{index:.5,rgb:[65,182,196]},{index:.625,rgb:[127,205,187]},{index:.75,rgb:[199,233,180]},{index:.875,rgb:[237,248,217]},{index:1,rgb:[255,255,217]}],greens:[{index:0,rgb:[0,68,27]},{index:.125,rgb:[0,109,44]},{index:.25,rgb:[35,139,69]},{index:.375,rgb:[65,171,93]},{index:.5,rgb:[116,196,118]},{index:.625,rgb:[161,217,155]},{index:.75,rgb:[199,233,192]},{index:.875,rgb:[229,245,224]},{index:1,rgb:[247,252,245]}],yiorrd:[{index:0,rgb:[128,0,38]},{index:.125,rgb:[189,0,38]},{index:.25,rgb:[227,26,28]},{index:.375,rgb:[252,78,42]},{index:.5,rgb:[253,141,60]},{index:.625,rgb:[254,178,76]},{index:.75,rgb:[254,217,118]},{index:.875,rgb:[255,237,160]},{index:1,rgb:[255,255,204]}],bluered:[{index:0,rgb:[0,0,255]},{index:1,rgb:[255,0,0]}],rdbu:[{index:0,rgb:[5,10,172]},{index:.35,rgb:[106,137,247]},{index:.5,rgb:[190,190,190]},{index:.6,rgb:[220,170,132]},{index:.7,rgb:[230,145,90]},{index:1,rgb:[178,10,28]}],picnic:[{index:0,rgb:[0,0,255]},{index:.1,rgb:[51,153,255]},{index:.2,rgb:[102,204,255]},{index:.3,rgb:[153,204,255]},{index:.4,rgb:[204,204,255]},{index:.5,rgb:[255,255,255]},{index:.6,rgb:[255,204,255]},{index:.7,rgb:[255,153,255]},{index:.8,rgb:[255,102,204]},{index:.9,rgb:[255,102,102]},{index:1,rgb:[255,0,0]}],rainbow:[{index:0,rgb:[150,0,90]},{index:.125,rgb:[0,0,200]},{index:.25,rgb:[0,25,255]},{index:.375,rgb:[0,152,255]},{index:.5,rgb:[44,255,150]},{index:.625,rgb:[151,255,0]},{index:.75,rgb:[255,234,0]},{index:.875,rgb:[255,111,0]},{index:1,rgb:[255,0,0]}],portland:[{index:0,rgb:[12,51,131]},{index:.25,rgb:[10,136,186]},{index:.5,rgb:[242,211,56]},{index:.75,rgb:[242,143,56]},{index:1,rgb:[217,30,30]}],blackbody:[{index:0,rgb:[0,0,0]},{index:.2,rgb:[230,0,0]},{index:.4,rgb:[230,210,0]},{index:.7,rgb:[255,255,255]},{index:1,rgb:[160,200,255]}],earth:[{index:0,rgb:[0,0,130]},{index:.1,rgb:[0,180,180]},{index:.2,rgb:[40,210,40]},{index:.4,rgb:[230,230,50]},{index:.6,rgb:[120,70,20]},{index:1,rgb:[255,255,255]}],electric:[{index:0,rgb:[0,0,0]},{index:.15,rgb:[30,0,100]},{index:.4,rgb:[120,0,100]},{index:.6,rgb:[160,90,0]},{index:.8,rgb:[230,200,0]},{index:1,rgb:[255,250,220]}],alpha:[{index:0,rgb:[255,255,255,0]},{index:1,rgb:[255,255,255,1]}],viridis:[{index:0,rgb:[68,1,84]},{index:.13,rgb:[71,44,122]},{index:.25,rgb:[59,81,139]},{index:.38,rgb:[44,113,142]},{index:.5,rgb:[33,144,141]},{index:.63,rgb:[39,173,129]},{index:.75,rgb:[92,200,99]},{index:.88,rgb:[170,220,50]},{index:1,rgb:[253,231,37]}],inferno:[{index:0,rgb:[0,0,4]},{index:.13,rgb:[31,12,72]},{index:.25,rgb:[85,15,109]},{index:.38,rgb:[136,34,106]},{index:.5,rgb:[186,54,85]},{index:.63,rgb:[227,89,51]},{index:.75,rgb:[249,140,10]},{index:.88,rgb:[249,201,50]},{index:1,rgb:[252,255,164]}],magma:[{index:0,rgb:[0,0,4]},{index:.13,rgb:[28,16,68]},{index:.25,rgb:[79,18,123]},{index:.38,rgb:[129,37,129]},{index:.5,rgb:[181,54,122]},{index:.63,rgb:[229,80,100]},{index:.75,rgb:[251,135,97]},{index:.88,rgb:[254,194,135]},{index:1,rgb:[252,253,191]}],plasma:[{index:0,rgb:[13,8,135]},{index:.13,rgb:[75,3,161]},{index:.25,rgb:[125,3,168]},{index:.38,rgb:[168,34,150]},{index:.5,rgb:[203,70,121]},{index:.63,rgb:[229,107,93]},{index:.75,rgb:[248,148,65]},{index:.88,rgb:[253,195,40]},{index:1,rgb:[240,249,33]}],warm:[{index:0,rgb:[125,0,179]},{index:.13,rgb:[172,0,187]},{index:.25,rgb:[219,0,170]},{index:.38,rgb:[255,0,130]},{index:.5,rgb:[255,63,74]},{index:.63,rgb:[255,123,0]},{index:.75,rgb:[234,176,0]},{index:.88,rgb:[190,228,0]},{index:1,rgb:[147,255,0]}],cool:[{index:0,rgb:[125,0,179]},{index:.13,rgb:[116,0,218]},{index:.25,rgb:[98,74,237]},{index:.38,rgb:[68,146,231]},{index:.5,rgb:[0,204,197]},{index:.63,rgb:[0,247,146]},{index:.75,rgb:[0,255,88]},{index:.88,rgb:[40,255,8]},{index:1,rgb:[147,255,0]}],"rainbow-soft":[{index:0,rgb:[125,0,179]},{index:.1,rgb:[199,0,180]},{index:.2,rgb:[255,0,121]},{index:.3,rgb:[255,108,0]},{index:.4,rgb:[222,194,0]},{index:.5,rgb:[150,255,0]},{index:.6,rgb:[0,255,55]},{index:.7,rgb:[0,246,150]},{index:.8,rgb:[50,167,222]},{index:.9,rgb:[103,51,235]},{index:1,rgb:[124,0,186]}],bathymetry:[{index:0,rgb:[40,26,44]},{index:.13,rgb:[59,49,90]},{index:.25,rgb:[64,76,139]},{index:.38,rgb:[63,110,151]},{index:.5,rgb:[72,142,158]},{index:.63,rgb:[85,174,163]},{index:.75,rgb:[120,206,163]},{index:.88,rgb:[187,230,172]},{index:1,rgb:[253,254,204]}],cdom:[{index:0,rgb:[47,15,62]},{index:.13,rgb:[87,23,86]},{index:.25,rgb:[130,28,99]},{index:.38,rgb:[171,41,96]},{index:.5,rgb:[206,67,86]},{index:.63,rgb:[230,106,84]},{index:.75,rgb:[242,149,103]},{index:.88,rgb:[249,193,135]},{index:1,rgb:[254,237,176]}],chlorophyll:[{index:0,rgb:[18,36,20]},{index:.13,rgb:[25,63,41]},{index:.25,rgb:[24,91,59]},{index:.38,rgb:[13,119,72]},{index:.5,rgb:[18,148,80]},{index:.63,rgb:[80,173,89]},{index:.75,rgb:[132,196,122]},{index:.88,rgb:[175,221,162]},{index:1,rgb:[215,249,208]}],density:[{index:0,rgb:[54,14,36]},{index:.13,rgb:[89,23,80]},{index:.25,rgb:[110,45,132]},{index:.38,rgb:[120,77,178]},{index:.5,rgb:[120,113,213]},{index:.63,rgb:[115,151,228]},{index:.75,rgb:[134,185,227]},{index:.88,rgb:[177,214,227]},{index:1,rgb:[230,241,241]}],"freesurface-blue":[{index:0,rgb:[30,4,110]},{index:.13,rgb:[47,14,176]},{index:.25,rgb:[41,45,236]},{index:.38,rgb:[25,99,212]},{index:.5,rgb:[68,131,200]},{index:.63,rgb:[114,156,197]},{index:.75,rgb:[157,181,203]},{index:.88,rgb:[200,208,216]},{index:1,rgb:[241,237,236]}],"freesurface-red":[{index:0,rgb:[60,9,18]},{index:.13,rgb:[100,17,27]},{index:.25,rgb:[142,20,29]},{index:.38,rgb:[177,43,27]},{index:.5,rgb:[192,87,63]},{index:.63,rgb:[205,125,105]},{index:.75,rgb:[216,162,148]},{index:.88,rgb:[227,199,193]},{index:1,rgb:[241,237,236]}],oxygen:[{index:0,rgb:[64,5,5]},{index:.13,rgb:[106,6,15]},{index:.25,rgb:[144,26,7]},{index:.38,rgb:[168,64,3]},{index:.5,rgb:[188,100,4]},{index:.63,rgb:[206,136,11]},{index:.75,rgb:[220,174,25]},{index:.88,rgb:[231,215,44]},{index:1,rgb:[248,254,105]}],par:[{index:0,rgb:[51,20,24]},{index:.13,rgb:[90,32,35]},{index:.25,rgb:[129,44,34]},{index:.38,rgb:[159,68,25]},{index:.5,rgb:[182,99,19]},{index:.63,rgb:[199,134,22]},{index:.75,rgb:[212,171,35]},{index:.88,rgb:[221,210,54]},{index:1,rgb:[225,253,75]}],phase:[{index:0,rgb:[145,105,18]},{index:.13,rgb:[184,71,38]},{index:.25,rgb:[186,58,115]},{index:.38,rgb:[160,71,185]},{index:.5,rgb:[110,97,218]},{index:.63,rgb:[50,123,164]},{index:.75,rgb:[31,131,110]},{index:.88,rgb:[77,129,34]},{index:1,rgb:[145,105,18]}],salinity:[{index:0,rgb:[42,24,108]},{index:.13,rgb:[33,50,162]},{index:.25,rgb:[15,90,145]},{index:.38,rgb:[40,118,137]},{index:.5,rgb:[59,146,135]},{index:.63,rgb:[79,175,126]},{index:.75,rgb:[120,203,104]},{index:.88,rgb:[193,221,100]},{index:1,rgb:[253,239,154]}],temperature:[{index:0,rgb:[4,35,51]},{index:.13,rgb:[23,51,122]},{index:.25,rgb:[85,59,157]},{index:.38,rgb:[129,79,143]},{index:.5,rgb:[175,95,130]},{index:.63,rgb:[222,112,101]},{index:.75,rgb:[249,146,66]},{index:.88,rgb:[249,196,65]},{index:1,rgb:[232,250,91]}],turbidity:[{index:0,rgb:[34,31,27]},{index:.13,rgb:[65,50,41]},{index:.25,rgb:[98,69,52]},{index:.38,rgb:[131,89,57]},{index:.5,rgb:[161,112,59]},{index:.63,rgb:[185,140,66]},{index:.75,rgb:[202,174,88]},{index:.88,rgb:[216,209,126]},{index:1,rgb:[233,246,171]}],"velocity-blue":[{index:0,rgb:[17,32,64]},{index:.13,rgb:[35,52,116]},{index:.25,rgb:[29,81,156]},{index:.38,rgb:[31,113,162]},{index:.5,rgb:[50,144,169]},{index:.63,rgb:[87,173,176]},{index:.75,rgb:[149,196,189]},{index:.88,rgb:[203,221,211]},{index:1,rgb:[254,251,230]}],"velocity-green":[{index:0,rgb:[23,35,19]},{index:.13,rgb:[24,64,38]},{index:.25,rgb:[11,95,45]},{index:.38,rgb:[39,123,35]},{index:.5,rgb:[95,146,12]},{index:.63,rgb:[152,165,18]},{index:.75,rgb:[201,186,69]},{index:.88,rgb:[233,216,137]},{index:1,rgb:[255,253,205]}],cubehelix:[{index:0,rgb:[0,0,0]},{index:.07,rgb:[22,5,59]},{index:.13,rgb:[60,4,105]},{index:.2,rgb:[109,1,135]},{index:.27,rgb:[161,0,147]},{index:.33,rgb:[210,2,142]},{index:.4,rgb:[251,11,123]},{index:.47,rgb:[255,29,97]},{index:.53,rgb:[255,54,69]},{index:.6,rgb:[255,85,46]},{index:.67,rgb:[255,120,34]},{index:.73,rgb:[255,157,37]},{index:.8,rgb:[241,191,57]},{index:.87,rgb:[224,220,93]},{index:.93,rgb:[218,241,142]},{index:1,rgb:[227,253,198]}]}},{}],53:[function(t,e,r){"use strict";var n=t("./colorScale"),i=t("lerp");function a(t){return[t[0]/255,t[1]/255,t[2]/255,t[3]]}function o(t){for(var e,r="#",n=0;n<3;++n)r+=("00"+(e=(e=t[n]).toString(16))).substr(e.length);return r}function s(t){return"rgba("+t.join(",")+")"}e.exports=function(t){var e,r,l,c,u,f,h,p,d,m;t||(t={});p=(t.nshades||72)-1,h=t.format||"hex",(f=t.colormap)||(f="jet");if("string"==typeof f){if(f=f.toLowerCase(),!n[f])throw Error(f+" not a supported colorscale");u=n[f]}else{if(!Array.isArray(f))throw Error("unsupported colormap option",f);u=f.slice()}if(u.length>p+1)throw new Error(f+" map requires nshades to be at least size "+u.length);d=Array.isArray(t.alpha)?2!==t.alpha.length?[1,1]:t.alpha.slice():"number"==typeof t.alpha?[t.alpha,t.alpha]:[1,1];e=u.map((function(t){return Math.round(t.index*p)})),d[0]=Math.min(Math.max(d[0],0),1),d[1]=Math.min(Math.max(d[1],0),1);var g=u.map((function(t,e){var r=u[e].index,n=u[e].rgb.slice();return 4===n.length&&n[3]>=0&&n[3]<=1||(n[3]=d[0]+(d[1]-d[0])*r),n})),v=[];for(m=0;m0||l(t,e,a)?-1:1:0===s?c>0||l(t,e,r)?1:-1:i(c-s)}var h=n(t,e,r);return h>0?o>0&&n(t,e,a)>0?1:-1:h<0?o>0||n(t,e,a)>0?1:-1:n(t,e,a)>0||l(t,e,r)?1:-1};var n=t("robust-orientation"),i=t("signum"),a=t("two-sum"),o=t("robust-product"),s=t("robust-sum");function l(t,e,r){var n=a(t[0],-e[0]),i=a(t[1],-e[1]),l=a(r[0],-e[0]),c=a(r[1],-e[1]),u=s(o(n,l),o(i,c));return u[u.length-1]>=0}},{"robust-orientation":284,"robust-product":285,"robust-sum":289,signum:55,"two-sum":307}],55:[function(t,e,r){"use strict";e.exports=function(t){return t<0?-1:t>0?1:0}},{}],56:[function(t,e,r){e.exports=function(t,e){var r=t.length,a=t.length-e.length;if(a)return a;switch(r){case 0:return 0;case 1:return t[0]-e[0];case 2:return t[0]+t[1]-e[0]-e[1]||n(t[0],t[1])-n(e[0],e[1]);case 3:var o=t[0]+t[1],s=e[0]+e[1];if(a=o+t[2]-(s+e[2]))return a;var l=n(t[0],t[1]),c=n(e[0],e[1]);return n(l,t[2])-n(c,e[2])||n(l+t[2],o)-n(c+e[2],s);case 4:var u=t[0],f=t[1],h=t[2],p=t[3],d=e[0],m=e[1],g=e[2],v=e[3];return u+f+h+p-(d+m+g+v)||n(u,f,h,p)-n(d,m,g,v,d)||n(u+f,u+h,u+p,f+h,f+p,h+p)-n(d+m,d+g,d+v,m+g,m+v,g+v)||n(u+f+h,u+f+p,u+h+p,f+h+p)-n(d+m+g,d+m+v,d+g+v,m+g+v);default:for(var y=t.slice().sort(i),x=e.slice().sort(i),b=0;bt[r][0]&&(r=n);return er?[[r],[e]]:[[e]]}},{}],60:[function(t,e,r){"use strict";e.exports=function(t){var e=n(t),r=e.length;if(r<=2)return[];for(var i=new Array(r),a=e[r-1],o=0;o=e[l]&&(s+=1);a[o]=s}}return t}(n(a,!0),r)}};var n=t("incremental-convex-hull"),i=t("affine-hull")},{"affine-hull":10,"incremental-convex-hull":233}],62:[function(t,e,r){"use strict";e.exports=function(t,e,r,n,i,a){var o=i-1,s=i*i,l=o*o,c=(1+2*i)*l,u=i*l,f=s*(3-2*i),h=s*o;if(t.length){a||(a=new Array(t.length));for(var p=t.length-1;p>=0;--p)a[p]=c*t[p]+u*e[p]+f*r[p]+h*n[p];return a}return c*t+u*e+f*r+h*n},e.exports.derivative=function(t,e,r,n,i,a){var o=6*i*i-6*i,s=3*i*i-4*i+1,l=-6*i*i+6*i,c=3*i*i-2*i;if(t.length){a||(a=new Array(t.length));for(var u=t.length-1;u>=0;--u)a[u]=o*t[u]+s*e[u]+l*r[u]+c*n[u];return a}return o*t+s*e+l*r[u]+c*n}},{}],63:[function(t,e,r){"use strict";var n=t("incremental-convex-hull"),i=t("uniq");function a(t,e){this.point=t,this.index=e}function o(t,e){for(var r=t.point,n=e.point,i=r.length,a=0;a=2)return!1;t[r]=n}return!0})):_.filter((function(t){for(var e=0;e<=s;++e){var r=v[t[e]];if(r<0)return!1;t[e]=r}return!0}));if(1&s)for(u=0;u<_.length;++u){h=(b=_[u])[0];b[0]=b[1],b[1]=h}return _}},{"incremental-convex-hull":233,uniq:310}],64:[function(t,e,r){(function(t){(function(){var r=!1;if("undefined"!=typeof Float64Array){var n=new Float64Array(1),i=new Uint32Array(n.buffer);if(n[0]=1,r=!0,1072693248===i[1]){e.exports=function(t){return n[0]=t,[i[0],i[1]]},e.exports.pack=function(t,e){return i[0]=t,i[1]=e,n[0]},e.exports.lo=function(t){return n[0]=t,i[0]},e.exports.hi=function(t){return n[0]=t,i[1]}}else if(1072693248===i[0]){e.exports=function(t){return n[0]=t,[i[1],i[0]]},e.exports.pack=function(t,e){return i[1]=t,i[0]=e,n[0]},e.exports.lo=function(t){return n[0]=t,i[1]},e.exports.hi=function(t){return n[0]=t,i[0]}}else r=!1}if(!r){var a=new t(8);e.exports=function(t){return a.writeDoubleLE(t,0,!0),[a.readUInt32LE(0,!0),a.readUInt32LE(4,!0)]},e.exports.pack=function(t,e){return a.writeUInt32LE(t,0,!0),a.writeUInt32LE(e,4,!0),a.readDoubleLE(0,!0)},e.exports.lo=function(t){return a.writeDoubleLE(t,0,!0),a.readUInt32LE(0,!0)},e.exports.hi=function(t){return a.writeDoubleLE(t,0,!0),a.readUInt32LE(4,!0)}}e.exports.sign=function(t){return e.exports.hi(t)>>>31},e.exports.exponent=function(t){return(e.exports.hi(t)<<1>>>21)-1023},e.exports.fraction=function(t){var r=e.exports.lo(t),n=e.exports.hi(t),i=1048575&n;return 2146435072&n&&(i+=1<<20),[r,i]},e.exports.denormalized=function(t){return!(2146435072&e.exports.hi(t))}}).call(this)}).call(this,t("buffer").Buffer)},{buffer:3}],65:[function(t,e,r){"use strict";e.exports=function(t,e){switch(void 0===e&&(e=0),typeof t){case"number":if(t>0)return function(t,e){var r,n;for(r=new Array(t),n=0;n=r-1){h=l.length-1;var d=t-e[r-1];for(p=0;p=r-1)for(var u=s.length-1,f=(e[r-1],0);f=0;--r)if(t[--e])return!1;return!0},s.jump=function(t){var e=this.lastT(),r=this.dimension;if(!(t0;--f)n.push(a(l[f-1],c[f-1],arguments[f])),i.push(0)}},s.push=function(t){var e=this.lastT(),r=this.dimension;if(!(t1e-6?1/s:0;this._time.push(t);for(var h=r;h>0;--h){var p=a(c[h-1],u[h-1],arguments[h]);n.push(p),i.push((p-n[o++])*f)}}},s.set=function(t){var e=this.dimension;if(!(t0;--l)r.push(a(o[l-1],s[l-1],arguments[l])),n.push(0)}},s.move=function(t){var e=this.lastT(),r=this.dimension;if(!(t<=e||arguments.length!==r+1)){var n=this._state,i=this._velocity,o=n.length-this.dimension,s=this.bounds,l=s[0],c=s[1],u=t-e,f=u>1e-6?1/u:0;this._time.push(t);for(var h=r;h>0;--h){var p=arguments[h];n.push(a(l[h-1],c[h-1],n[o++]+p)),i.push(p*f)}}},s.idle=function(t){var e=this.lastT();if(!(t=0;--f)n.push(a(l[f],c[f],n[o]+u*i[o])),i.push(0),o+=1}}},{"binary-search-bounds":31,"cubic-hermite":62}],69:[function(t,e,r){"use strict";e.exports=function(t){return new s(t||m,null)};function n(t,e,r,n,i,a){this._color=t,this.key=e,this.value=r,this.left=n,this.right=i,this._count=a}function i(t){return new n(t._color,t.key,t.value,t.left,t.right,t._count)}function a(t,e){return new n(t,e.key,e.value,e.left,e.right,e._count)}function o(t){t._count=1+(t.left?t.left._count:0)+(t.right?t.right._count:0)}function s(t,e){this._compare=t,this.root=e}var l=s.prototype;function c(t,e){var r;if(e.left&&(r=c(t,e.left)))return r;return(r=t(e.key,e.value))||(e.right?c(t,e.right):void 0)}function u(t,e,r,n){if(e(t,n.key)<=0){var i;if(n.left)if(i=u(t,e,r,n.left))return i;if(i=r(n.key,n.value))return i}if(n.right)return u(t,e,r,n.right)}function f(t,e,r,n,i){var a,o=r(t,i.key),s=r(e,i.key);if(o<=0){if(i.left&&(a=f(t,e,r,n,i.left)))return a;if(s>0&&(a=n(i.key,i.value)))return a}if(s>0&&i.right)return f(t,e,r,n,i.right)}function h(t,e){this.tree=t,this._stack=e}Object.defineProperty(l,"keys",{get:function(){var t=[];return this.forEach((function(e,r){t.push(e)})),t}}),Object.defineProperty(l,"values",{get:function(){var t=[];return this.forEach((function(e,r){t.push(r)})),t}}),Object.defineProperty(l,"length",{get:function(){return this.root?this.root._count:0}}),l.insert=function(t,e){for(var r=this._compare,i=this.root,l=[],c=[];i;){var u=r(t,i.key);l.push(i),c.push(u),i=u<=0?i.left:i.right}l.push(new n(0,t,e,null,null,1));for(var f=l.length-2;f>=0;--f){i=l[f];c[f]<=0?l[f]=new n(i._color,i.key,i.value,l[f+1],i.right,i._count+1):l[f]=new n(i._color,i.key,i.value,i.left,l[f+1],i._count+1)}for(f=l.length-1;f>1;--f){var h=l[f-1];i=l[f];if(1===h._color||1===i._color)break;var p=l[f-2];if(p.left===h)if(h.left===i){if(!(d=p.right)||0!==d._color){if(p._color=0,p.left=h.right,h._color=1,h.right=p,l[f-2]=h,l[f-1]=i,o(p),o(h),f>=3)(m=l[f-3]).left===p?m.left=h:m.right=h;break}h._color=1,p.right=a(1,d),p._color=0,f-=1}else{if(!(d=p.right)||0!==d._color){if(h.right=i.left,p._color=0,p.left=i.right,i._color=1,i.left=h,i.right=p,l[f-2]=i,l[f-1]=h,o(p),o(h),o(i),f>=3)(m=l[f-3]).left===p?m.left=i:m.right=i;break}h._color=1,p.right=a(1,d),p._color=0,f-=1}else if(h.right===i){if(!(d=p.left)||0!==d._color){if(p._color=0,p.right=h.left,h._color=1,h.left=p,l[f-2]=h,l[f-1]=i,o(p),o(h),f>=3)(m=l[f-3]).right===p?m.right=h:m.left=h;break}h._color=1,p.left=a(1,d),p._color=0,f-=1}else{var d;if(!(d=p.left)||0!==d._color){var m;if(h.left=i.right,p._color=0,p.right=i.left,i._color=1,i.right=h,i.left=p,l[f-2]=i,l[f-1]=h,o(p),o(h),o(i),f>=3)(m=l[f-3]).right===p?m.right=i:m.left=i;break}h._color=1,p.left=a(1,d),p._color=0,f-=1}}return l[0]._color=1,new s(r,l[0])},l.forEach=function(t,e,r){if(this.root)switch(arguments.length){case 1:return c(t,this.root);case 2:return u(e,this._compare,t,this.root);case 3:if(this._compare(e,r)>=0)return;return f(e,r,this._compare,t,this.root)}},Object.defineProperty(l,"begin",{get:function(){for(var t=[],e=this.root;e;)t.push(e),e=e.left;return new h(this,t)}}),Object.defineProperty(l,"end",{get:function(){for(var t=[],e=this.root;e;)t.push(e),e=e.right;return new h(this,t)}}),l.at=function(t){if(t<0)return new h(this,[]);for(var e=this.root,r=[];;){if(r.push(e),e.left){if(t=e.right._count)break;e=e.right}return new h(this,[])},l.ge=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a<=0&&(i=n.length),r=a<=0?r.left:r.right}return n.length=i,new h(this,n)},l.gt=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a<0&&(i=n.length),r=a<0?r.left:r.right}return n.length=i,new h(this,n)},l.lt=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a>0&&(i=n.length),r=a<=0?r.left:r.right}return n.length=i,new h(this,n)},l.le=function(t){for(var e=this._compare,r=this.root,n=[],i=0;r;){var a=e(t,r.key);n.push(r),a>=0&&(i=n.length),r=a<0?r.left:r.right}return n.length=i,new h(this,n)},l.find=function(t){for(var e=this._compare,r=this.root,n=[];r;){var i=e(t,r.key);if(n.push(r),0===i)return new h(this,n);r=i<=0?r.left:r.right}return new h(this,[])},l.remove=function(t){var e=this.find(t);return e?e.remove():this},l.get=function(t){for(var e=this._compare,r=this.root;r;){var n=e(t,r.key);if(0===n)return r.value;r=n<=0?r.left:r.right}};var p=h.prototype;function d(t,e){t.key=e.key,t.value=e.value,t.left=e.left,t.right=e.right,t._color=e._color,t._count=e._count}function m(t,e){return te?1:0}Object.defineProperty(p,"valid",{get:function(){return this._stack.length>0}}),Object.defineProperty(p,"node",{get:function(){return this._stack.length>0?this._stack[this._stack.length-1]:null},enumerable:!0}),p.clone=function(){return new h(this.tree,this._stack.slice())},p.remove=function(){var t=this._stack;if(0===t.length)return this.tree;var e=new Array(t.length),r=t[t.length-1];e[e.length-1]=new n(r._color,r.key,r.value,r.left,r.right,r._count);for(var l=t.length-2;l>=0;--l){(r=t[l]).left===t[l+1]?e[l]=new n(r._color,r.key,r.value,e[l+1],r.right,r._count):e[l]=new n(r._color,r.key,r.value,r.left,e[l+1],r._count)}if((r=e[e.length-1]).left&&r.right){var c=e.length;for(r=r.left;r.right;)e.push(r),r=r.right;var u=e[c-1];e.push(new n(r._color,u.key,u.value,r.left,r.right,r._count)),e[c-1].key=r.key,e[c-1].value=r.value;for(l=e.length-2;l>=c;--l)r=e[l],e[l]=new n(r._color,r.key,r.value,r.left,e[l+1],r._count);e[c-1].left=e[c]}if(0===(r=e[e.length-1])._color){var f=e[e.length-2];f.left===r?f.left=null:f.right===r&&(f.right=null),e.pop();for(l=0;l=0;--l){if(e=t[l],0===l)return void(e._color=1);if((r=t[l-1]).left===e){if((n=r.right).right&&0===n.right._color){if(s=(n=r.right=i(n)).right=i(n.right),r.right=n.left,n.left=r,n.right=s,n._color=r._color,e._color=1,r._color=1,s._color=1,o(r),o(n),l>1)(c=t[l-2]).left===r?c.left=n:c.right=n;return void(t[l-1]=n)}if(n.left&&0===n.left._color){if(s=(n=r.right=i(n)).left=i(n.left),r.right=s.left,n.left=s.right,s.left=r,s.right=n,s._color=r._color,r._color=1,n._color=1,e._color=1,o(r),o(n),o(s),l>1)(c=t[l-2]).left===r?c.left=s:c.right=s;return void(t[l-1]=s)}if(1===n._color){if(0===r._color)return r._color=1,void(r.right=a(0,n));r.right=a(0,n);continue}n=i(n),r.right=n.left,n.left=r,n._color=r._color,r._color=0,o(r),o(n),l>1&&((c=t[l-2]).left===r?c.left=n:c.right=n),t[l-1]=n,t[l]=r,l+11)(c=t[l-2]).right===r?c.right=n:c.left=n;return void(t[l-1]=n)}if(n.right&&0===n.right._color){if(s=(n=r.left=i(n)).right=i(n.right),r.left=s.right,n.right=s.left,s.right=r,s.left=n,s._color=r._color,r._color=1,n._color=1,e._color=1,o(r),o(n),o(s),l>1)(c=t[l-2]).right===r?c.right=s:c.left=s;return void(t[l-1]=s)}if(1===n._color){if(0===r._color)return r._color=1,void(r.left=a(0,n));r.left=a(0,n);continue}var c;n=i(n),r.left=n.right,n.right=r,n._color=r._color,r._color=0,o(r),o(n),l>1&&((c=t[l-2]).right===r?c.right=n:c.left=n),t[l-1]=n,t[l]=r,l+10)return this._stack[this._stack.length-1].key},enumerable:!0}),Object.defineProperty(p,"value",{get:function(){if(this._stack.length>0)return this._stack[this._stack.length-1].value},enumerable:!0}),Object.defineProperty(p,"index",{get:function(){var t=0,e=this._stack;if(0===e.length){var r=this.tree.root;return r?r._count:0}e[e.length-1].left&&(t=e[e.length-1].left._count);for(var n=e.length-2;n>=0;--n)e[n+1]===e[n].right&&(++t,e[n].left&&(t+=e[n].left._count));return t},enumerable:!0}),p.next=function(){var t=this._stack;if(0!==t.length){var e=t[t.length-1];if(e.right)for(e=e.right;e;)t.push(e),e=e.left;else for(t.pop();t.length>0&&t[t.length-1].right===e;)e=t[t.length-1],t.pop()}},Object.defineProperty(p,"hasNext",{get:function(){var t=this._stack;if(0===t.length)return!1;if(t[t.length-1].right)return!0;for(var e=t.length-1;e>0;--e)if(t[e-1].left===t[e])return!0;return!1}}),p.update=function(t){var e=this._stack;if(0===e.length)throw new Error("Can't update empty node!");var r=new Array(e.length),i=e[e.length-1];r[r.length-1]=new n(i._color,i.key,t,i.left,i.right,i._count);for(var a=e.length-2;a>=0;--a)(i=e[a]).left===e[a+1]?r[a]=new n(i._color,i.key,i.value,r[a+1],i.right,i._count):r[a]=new n(i._color,i.key,i.value,i.left,r[a+1],i._count);return new s(this.tree._compare,r[0])},p.prev=function(){var t=this._stack;if(0!==t.length){var e=t[t.length-1];if(e.left)for(e=e.left;e;)t.push(e),e=e.right;else for(t.pop();t.length>0&&t[t.length-1].left===e;)e=t[t.length-1],t.pop()}},Object.defineProperty(p,"hasPrev",{get:function(){var t=this._stack;if(0===t.length)return!1;if(t[t.length-1].left)return!0;for(var e=t.length-1;e>0;--e)if(t[e-1].right===t[e])return!0;return!1}})},{}],70:[function(t,e,r){"use strict";e.exports=function(t,e){var r=new u(t);return r.update(e),r};var n=t("./lib/text.js"),i=t("./lib/lines.js"),a=t("./lib/background.js"),o=t("./lib/cube.js"),s=t("./lib/ticks.js"),l=new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);function c(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t}function u(t){this.gl=t,this.pixelRatio=1,this.bounds=[[-10,-10,-10],[10,10,10]],this.ticks=[[],[],[]],this.autoTicks=!0,this.tickSpacing=[1,1,1],this.tickEnable=[!0,!0,!0],this.tickFont=["sans-serif","sans-serif","sans-serif"],this.tickSize=[12,12,12],this.tickAngle=[0,0,0],this.tickAlign=["auto","auto","auto"],this.tickColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.tickPad=[10,10,10],this.lastCubeProps={cubeEdges:[0,0,0],axis:[0,0,0]},this.labels=["x","y","z"],this.labelEnable=[!0,!0,!0],this.labelFont="sans-serif",this.labelSize=[20,20,20],this.labelAngle=[0,0,0],this.labelAlign=["auto","auto","auto"],this.labelColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.labelPad=[10,10,10],this.lineEnable=[!0,!0,!0],this.lineMirror=[!1,!1,!1],this.lineWidth=[1,1,1],this.lineColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.lineTickEnable=[!0,!0,!0],this.lineTickMirror=[!1,!1,!1],this.lineTickLength=[0,0,0],this.lineTickWidth=[1,1,1],this.lineTickColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.gridEnable=[!0,!0,!0],this.gridWidth=[1,1,1],this.gridColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.zeroEnable=[!0,!0,!0],this.zeroLineColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.zeroLineWidth=[2,2,2],this.backgroundEnable=[!1,!1,!1],this.backgroundColor=[[.8,.8,.8,.5],[.8,.8,.8,.5],[.8,.8,.8,.5]],this._firstInit=!0,this._text=null,this._lines=null,this._background=a(t)}var f=u.prototype;function h(){this.primalOffset=[0,0,0],this.primalMinor=[0,0,0],this.mirrorOffset=[0,0,0],this.mirrorMinor=[0,0,0]}f.update=function(t){function e(e,r,n){if(n in t){var i,a=t[n],o=this[n];(e?Array.isArray(a)&&Array.isArray(a[0]):Array.isArray(a))?this[n]=i=[r(a[0]),r(a[1]),r(a[2])]:this[n]=i=[r(a),r(a),r(a)];for(var s=0;s<3;++s)if(i[s]!==o[s])return!0}return!1}t=t||{};var r,a=e.bind(this,!1,Number),o=e.bind(this,!1,Boolean),l=e.bind(this,!1,String),c=e.bind(this,!0,(function(t){if(Array.isArray(t)){if(3===t.length)return[+t[0],+t[1],+t[2],1];if(4===t.length)return[+t[0],+t[1],+t[2],+t[3]]}return[0,0,0,1]})),u=!1,f=!1;if("bounds"in t)for(var h=t.bounds,p=0;p<2;++p)for(var d=0;d<3;++d)h[p][d]!==this.bounds[p][d]&&(f=!0),this.bounds[p][d]=h[p][d];if("ticks"in t){r=t.ticks,u=!0,this.autoTicks=!1;for(p=0;p<3;++p)this.tickSpacing[p]=0}else a("tickSpacing")&&(this.autoTicks=!0,f=!0);if(this._firstInit&&("ticks"in t||"tickSpacing"in t||(this.autoTicks=!0),f=!0,u=!0,this._firstInit=!1),f&&this.autoTicks&&(r=s.create(this.bounds,this.tickSpacing),u=!0),u){for(p=0;p<3;++p)r[p].sort((function(t,e){return t.x-e.x}));s.equal(r,this.ticks)?u=!1:this.ticks=r}o("tickEnable"),l("tickFont")&&(u=!0),a("tickSize"),a("tickAngle"),a("tickPad"),c("tickColor");var m=l("labels");l("labelFont")&&(m=!0),o("labelEnable"),a("labelSize"),a("labelPad"),c("labelColor"),o("lineEnable"),o("lineMirror"),a("lineWidth"),c("lineColor"),o("lineTickEnable"),o("lineTickMirror"),a("lineTickLength"),a("lineTickWidth"),c("lineTickColor"),o("gridEnable"),a("gridWidth"),c("gridColor"),o("zeroEnable"),c("zeroLineColor"),a("zeroLineWidth"),o("backgroundEnable"),c("backgroundColor"),this._text?this._text&&(m||u)&&this._text.update(this.bounds,this.labels,this.labelFont,this.ticks,this.tickFont):this._text=n(this.gl,this.bounds,this.labels,this.labelFont,this.ticks,this.tickFont),this._lines&&u&&(this._lines.dispose(),this._lines=null),this._lines||(this._lines=i(this.gl,this.bounds,this.ticks))};var p=[new h,new h,new h];function d(t,e,r,n,i){for(var a=t.primalOffset,o=t.primalMinor,s=t.mirrorOffset,l=t.mirrorMinor,c=n[e],u=0;u<3;++u)if(e!==u){var f=a,h=s,p=o,d=l;c&1<0?(p[u]=-1,d[u]=0):(p[u]=0,d[u]=1)}}var m=[0,0,0],g={model:l,view:l,projection:l,_ortho:!1};f.isOpaque=function(){return!0},f.isTransparent=function(){return!1},f.drawTransparent=function(t){};var v=[0,0,0],y=[0,0,0],x=[0,0,0];f.draw=function(t){t=t||g;for(var e=this.gl,r=t.model||l,n=t.view||l,i=t.projection||l,a=this.bounds,s=t._ortho||!1,u=o(r,n,i,a,s),f=u.cubeEdges,h=u.axis,b=n[12],_=n[13],w=n[14],T=n[15],k=(s?2:1)*this.pixelRatio*(i[3]*b+i[7]*_+i[11]*w+i[15]*T)/e.drawingBufferHeight,A=0;A<3;++A)this.lastCubeProps.cubeEdges[A]=f[A],this.lastCubeProps.axis[A]=h[A];var M=p;for(A=0;A<3;++A)d(p[A],A,this.bounds,f,h);e=this.gl;var S,E=m;for(A=0;A<3;++A)this.backgroundEnable[A]?E[A]=h[A]:E[A]=0;this._background.draw(r,n,i,a,E,this.backgroundColor),this._lines.bind(r,n,i,this);for(A=0;A<3;++A){var L=[0,0,0];h[A]>0?L[A]=a[1][A]:L[A]=a[0][A];for(var C=0;C<2;++C){var P=(A+1+C)%3,I=(A+1+(1^C))%3;this.gridEnable[P]&&this._lines.drawGrid(P,I,this.bounds,L,this.gridColor[P],this.gridWidth[P]*this.pixelRatio)}for(C=0;C<2;++C){P=(A+1+C)%3,I=(A+1+(1^C))%3;this.zeroEnable[I]&&Math.min(a[0][I],a[1][I])<=0&&Math.max(a[0][I],a[1][I])>=0&&this._lines.drawZero(P,I,this.bounds,L,this.zeroLineColor[I],this.zeroLineWidth[I]*this.pixelRatio)}}for(A=0;A<3;++A){this.lineEnable[A]&&this._lines.drawAxisLine(A,this.bounds,M[A].primalOffset,this.lineColor[A],this.lineWidth[A]*this.pixelRatio),this.lineMirror[A]&&this._lines.drawAxisLine(A,this.bounds,M[A].mirrorOffset,this.lineColor[A],this.lineWidth[A]*this.pixelRatio);var O=c(v,M[A].primalMinor),z=c(y,M[A].mirrorMinor),D=this.lineTickLength;for(C=0;C<3;++C){var R=k/r[5*C];O[C]*=D[C]*R,z[C]*=D[C]*R}this.lineTickEnable[A]&&this._lines.drawAxisTicks(A,M[A].primalOffset,O,this.lineTickColor[A],this.lineTickWidth[A]*this.pixelRatio),this.lineTickMirror[A]&&this._lines.drawAxisTicks(A,M[A].mirrorOffset,z,this.lineTickColor[A],this.lineTickWidth[A]*this.pixelRatio)}this._lines.unbind(),this._text.bind(r,n,i,this.pixelRatio);var F,B;function N(t){(B=[0,0,0])[t]=1}function j(t,e,r){var n=(t+1)%3,i=(t+2)%3,a=e[n],o=e[i],s=r[n],l=r[i];a>0&&l>0||a>0&&l<0||a<0&&l>0||a<0&&l<0?N(n):(o>0&&s>0||o>0&&s<0||o<0&&s>0||o<0&&s<0)&&N(i)}for(A=0;A<3;++A){var U=M[A].primalMinor,V=M[A].mirrorMinor,H=c(x,M[A].primalOffset);for(C=0;C<3;++C)this.lineTickEnable[A]&&(H[C]+=k*U[C]*Math.max(this.lineTickLength[C],0)/r[5*C]);var q=[0,0,0];if(q[A]=1,this.tickEnable[A]){-3600===this.tickAngle[A]?(this.tickAngle[A]=0,this.tickAlign[A]="auto"):this.tickAlign[A]=-1,F=1,"auto"===(S=[this.tickAlign[A],.5,F])[0]?S[0]=0:S[0]=parseInt(""+S[0]),B=[0,0,0],j(A,U,V);for(C=0;C<3;++C)H[C]+=k*U[C]*this.tickPad[C]/r[5*C];this._text.drawTicks(A,this.tickSize[A],this.tickAngle[A],H,this.tickColor[A],q,B,S)}if(this.labelEnable[A]){F=0,B=[0,0,0],this.labels[A].length>4&&(N(A),F=1),"auto"===(S=[this.labelAlign[A],.5,F])[0]?S[0]=0:S[0]=parseInt(""+S[0]);for(C=0;C<3;++C)H[C]+=k*U[C]*this.labelPad[C]/r[5*C];H[A]+=.5*(a[0][A]+a[1][A]),this._text.drawLabel(A,this.labelSize[A],this.labelAngle[A],H,this.labelColor[A],[0,0,0],B,S)}}this._text.unbind()},f.dispose=function(){this._text.dispose(),this._lines.dispose(),this._background.dispose(),this._lines=null,this._text=null,this._background=null,this.gl=null}},{"./lib/background.js":71,"./lib/cube.js":72,"./lib/lines.js":73,"./lib/text.js":75,"./lib/ticks.js":76}],71:[function(t,e,r){"use strict";e.exports=function(t){for(var e=[],r=[],s=0,l=0;l<3;++l)for(var c=(l+1)%3,u=(l+2)%3,f=[0,0,0],h=[0,0,0],p=-1;p<=1;p+=2){r.push(s,s+2,s+1,s+1,s+2,s+3),f[l]=p,h[l]=p;for(var d=-1;d<=1;d+=2){f[c]=d;for(var m=-1;m<=1;m+=2)f[u]=m,e.push(f[0],f[1],f[2],h[0],h[1],h[2]),s+=1}var g=c;c=u,u=g}var v=n(t,new Float32Array(e)),y=n(t,new Uint16Array(r),t.ELEMENT_ARRAY_BUFFER),x=i(t,[{buffer:v,type:t.FLOAT,size:3,offset:0,stride:24},{buffer:v,type:t.FLOAT,size:3,offset:12,stride:24}],y),b=a(t);return b.attributes.position.location=0,b.attributes.normal.location=1,new o(t,v,x,b)};var n=t("gl-buffer"),i=t("gl-vao"),a=t("./shaders").bg;function o(t,e,r,n){this.gl=t,this.buffer=e,this.vao=r,this.shader=n}var s=o.prototype;s.draw=function(t,e,r,n,i,a){for(var o=!1,s=0;s<3;++s)o=o||i[s];if(o){var l=this.gl;l.enable(l.POLYGON_OFFSET_FILL),l.polygonOffset(1,2),this.shader.bind(),this.shader.uniforms={model:t,view:e,projection:r,bounds:n,enable:i,colors:a},this.vao.bind(),this.vao.draw(this.gl.TRIANGLES,36),this.vao.unbind(),l.disable(l.POLYGON_OFFSET_FILL)}},s.dispose=function(){this.vao.dispose(),this.buffer.dispose(),this.shader.dispose()}},{"./shaders":74,"gl-buffer":78,"gl-vao":150}],72:[function(t,e,r){"use strict";e.exports=function(t,e,r,a,p){i(s,e,t),i(s,r,s);for(var y=0,x=0;x<2;++x){u[2]=a[x][2];for(var b=0;b<2;++b){u[1]=a[b][1];for(var _=0;_<2;++_)u[0]=a[_][0],h(l[y],u,s),y+=1}}var w=-1;for(x=0;x<8;++x){for(var T=l[x][3],k=0;k<3;++k)c[x][k]=l[x][k]/T;p&&(c[x][2]*=-1),T<0&&(w<0||c[x][2]E&&(w|=1<E&&(w|=1<c[x][1])&&(R=x);var F=-1;for(x=0;x<3;++x){if((N=R^1<c[B][0]&&(B=N)}var j=m;j[0]=j[1]=j[2]=0,j[n.log2(F^R)]=R&F,j[n.log2(R^B)]=R&B;var U=7^B;U===w||U===D?(U=7^F,j[n.log2(B^U)]=U&B):j[n.log2(F^U)]=U&F;var V=g,H=w;for(A=0;A<3;++A)V[A]=H&1< HALF_PI) && (b <= ONE_AND_HALF_PI)) ?\n b - PI :\n b;\n}\n\nfloat look_horizontal_or_vertical(float a, float ratio) {\n // ratio controls the ratio between being horizontal to (vertical + horizontal)\n // if ratio is set to 0.5 then it is 50%, 50%.\n // when using a higher ratio e.g. 0.75 the result would\n // likely be more horizontal than vertical.\n\n float b = positive_angle(a);\n\n return\n (b < ( ratio) * HALF_PI) ? 0.0 :\n (b < (2.0 - ratio) * HALF_PI) ? -HALF_PI :\n (b < (2.0 + ratio) * HALF_PI) ? 0.0 :\n (b < (4.0 - ratio) * HALF_PI) ? HALF_PI :\n 0.0;\n}\n\nfloat roundTo(float a, float b) {\n return float(b * floor((a + 0.5 * b) / b));\n}\n\nfloat look_round_n_directions(float a, int n) {\n float b = positive_angle(a);\n float div = TWO_PI / float(n);\n float c = roundTo(b, div);\n return look_upwards(c);\n}\n\nfloat applyAlignOption(float rawAngle, float delta) {\n return\n (option > 2) ? look_round_n_directions(rawAngle + delta, option) : // option 3-n: round to n directions\n (option == 2) ? look_horizontal_or_vertical(rawAngle + delta, hv_ratio) : // horizontal or vertical\n (option == 1) ? rawAngle + delta : // use free angle, and flip to align with one direction of the axis\n (option == 0) ? look_upwards(rawAngle) : // use free angle, and stay upwards\n (option ==-1) ? 0.0 : // useful for backward compatibility, all texts remains horizontal\n rawAngle; // otherwise return back raw input angle\n}\n\nbool isAxisTitle = (axis.x == 0.0) &&\n (axis.y == 0.0) &&\n (axis.z == 0.0);\n\nvoid main() {\n //Compute world offset\n float axisDistance = position.z;\n vec3 dataPosition = axisDistance * axis + offset;\n\n float beta = angle; // i.e. user defined attributes for each tick\n\n float axisAngle;\n float clipAngle;\n float flip;\n\n if (enableAlign) {\n axisAngle = (isAxisTitle) ? HALF_PI :\n computeViewAngle(dataPosition, dataPosition + axis);\n clipAngle = computeViewAngle(dataPosition, dataPosition + alignDir);\n\n axisAngle += (sin(axisAngle) < 0.0) ? PI : 0.0;\n clipAngle += (sin(clipAngle) < 0.0) ? PI : 0.0;\n\n flip = (dot(vec2(cos(axisAngle), sin(axisAngle)),\n vec2(sin(clipAngle),-cos(clipAngle))) > 0.0) ? 1.0 : 0.0;\n\n beta += applyAlignOption(clipAngle, flip * PI);\n }\n\n //Compute plane offset\n vec2 planeCoord = position.xy * pixelScale;\n\n mat2 planeXform = scale * mat2(\n cos(beta), sin(beta),\n -sin(beta), cos(beta)\n );\n\n vec2 viewOffset = 2.0 * planeXform * planeCoord / resolution;\n\n //Compute clip position\n vec3 clipPosition = project(dataPosition);\n\n //Apply text offset in clip coordinates\n clipPosition += vec3(viewOffset, 0.0);\n\n //Done\n gl_Position = vec4(clipPosition, 1.0);\n}"]),l=n(["precision highp float;\n#define GLSLIFY 1\n\nuniform vec4 color;\nvoid main() {\n gl_FragColor = color;\n}"]);r.text=function(t){return i(t,s,l,null,[{name:"position",type:"vec3"}])};var c=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec3 normal;\n\nuniform mat4 model, view, projection;\nuniform vec3 enable;\nuniform vec3 bounds[2];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n\n vec3 signAxis = sign(bounds[1] - bounds[0]);\n\n vec3 realNormal = signAxis * normal;\n\n if(dot(realNormal, enable) > 0.0) {\n vec3 minRange = min(bounds[0], bounds[1]);\n vec3 maxRange = max(bounds[0], bounds[1]);\n vec3 nPosition = mix(minRange, maxRange, 0.5 * (position + 1.0));\n gl_Position = projection * view * model * vec4(nPosition, 1.0);\n } else {\n gl_Position = vec4(0,0,0,0);\n }\n\n colorChannel = abs(realNormal);\n}"]),u=n(["precision highp float;\n#define GLSLIFY 1\n\nuniform vec4 colors[3];\n\nvarying vec3 colorChannel;\n\nvoid main() {\n gl_FragColor = colorChannel.x * colors[0] +\n colorChannel.y * colors[1] +\n colorChannel.z * colors[2];\n}"]);r.bg=function(t){return i(t,c,u,null,[{name:"position",type:"vec3"},{name:"normal",type:"vec3"}])}},{"gl-shader":132,glslify:231}],75:[function(t,e,r){(function(r){(function(){"use strict";e.exports=function(t,e,r,a,s,l){var u=n(t),f=i(t,[{buffer:u,size:3}]),h=o(t);h.attributes.position.location=0;var p=new c(t,h,u,f);return p.update(e,r,a,s,l),p};var n=t("gl-buffer"),i=t("gl-vao"),a=t("vectorize-text"),o=t("./shaders").text,s=window||r.global||{},l=s.__TEXT_CACHE||{};s.__TEXT_CACHE={};function c(t,e,r,n){this.gl=t,this.shader=e,this.buffer=r,this.vao=n,this.tickOffset=this.tickCount=this.labelOffset=this.labelCount=null}var u=c.prototype,f=[0,0];u.bind=function(t,e,r,n){this.vao.bind(),this.shader.bind();var i=this.shader.uniforms;i.model=t,i.view=e,i.projection=r,i.pixelScale=n,f[0]=this.gl.drawingBufferWidth,f[1]=this.gl.drawingBufferHeight,this.shader.uniforms.resolution=f},u.unbind=function(){this.vao.unbind()},u.update=function(t,e,r,n,i){var o=[];function s(t,e,r,n,i,s){var c=l[r];c||(c=l[r]={});var u=c[e];u||(u=c[e]=function(t,e){try{return a(t,e)}catch(e){return console.warn('error vectorizing text:"'+t+'" error:',e),{cells:[],positions:[]}}}(e,{triangles:!0,font:r,textAlign:"center",textBaseline:"middle",lineSpacing:i,styletags:s}));for(var f=(n||12)/12,h=u.positions,p=u.cells,d=0,m=p.length;d=0;--v){var y=h[g[v]];o.push(f*y[0],-f*y[1],t)}}for(var c=[0,0,0],u=[0,0,0],f=[0,0,0],h=[0,0,0],p={breaklines:!0,bolds:!0,italics:!0,subscripts:!0,superscripts:!0},d=0;d<3;++d){f[d]=o.length/3|0,s(.5*(t[0][d]+t[1][d]),e[d],r[d],12,1.25,p),h[d]=(o.length/3|0)-f[d],c[d]=o.length/3|0;for(var m=0;m=0&&(i=r.length-n-1);var a=Math.pow(10,i),o=Math.round(t*e*a),s=o+"";if(s.indexOf("e")>=0)return s;var l=o/a,c=o%a;o<0?(l=0|-Math.ceil(l),c=0|-c):(l=0|Math.floor(l),c|=0);var u=""+l;if(o<0&&(u="-"+u),i){for(var f=""+c;f.length=t[0][i];--o)a.push({x:o*e[i],text:n(e[i],o)});r.push(a)}return r},r.equal=function(t,e){for(var r=0;r<3;++r){if(t[r].length!==e[r].length)return!1;for(var n=0;nr)throw new Error("gl-buffer: If resizing buffer, must not specify offset");return t.bufferSubData(e,a,i),r}function u(t,e){for(var r=n.malloc(t.length,e),i=t.length,a=0;a=0;--n){if(e[n]!==r)return!1;r*=t[n]}return!0}(t.shape,t.stride))0===t.offset&&t.data.length===t.shape[0]?this.length=c(this.gl,this.type,this.length,this.usage,t.data,e):this.length=c(this.gl,this.type,this.length,this.usage,t.data.subarray(t.offset,t.shape[0]),e);else{var s=n.malloc(t.size,r),l=a(s,t.shape);i.assign(l,t),this.length=c(this.gl,this.type,this.length,this.usage,e<0?s:s.subarray(0,t.size),e),n.free(s)}}else if(Array.isArray(t)){var f;f=this.type===this.gl.ELEMENT_ARRAY_BUFFER?u(t,"uint16"):u(t,"float32"),this.length=c(this.gl,this.type,this.length,this.usage,e<0?f:f.subarray(0,t.length),e),n.free(f)}else if("object"==typeof t&&"number"==typeof t.length)this.length=c(this.gl,this.type,this.length,this.usage,t,e);else{if("number"!=typeof t&&void 0!==t)throw new Error("gl-buffer: Invalid data type");if(e>=0)throw new Error("gl-buffer: Cannot specify offset when resizing buffer");(t|=0)<=0&&(t=1),this.gl.bufferData(this.type,0|t,this.usage),this.length=t}},e.exports=function(t,e,r,n){if(r=r||t.ARRAY_BUFFER,n=n||t.DYNAMIC_DRAW,r!==t.ARRAY_BUFFER&&r!==t.ELEMENT_ARRAY_BUFFER)throw new Error("gl-buffer: Invalid type for webgl buffer, must be either gl.ARRAY_BUFFER or gl.ELEMENT_ARRAY_BUFFER");if(n!==t.DYNAMIC_DRAW&&n!==t.STATIC_DRAW&&n!==t.STREAM_DRAW)throw new Error("gl-buffer: Invalid usage for buffer, must be either gl.DYNAMIC_DRAW, gl.STATIC_DRAW or gl.STREAM_DRAW");var i=t.createBuffer(),a=new s(t,r,i,0,n);return a.update(e),a}},{ndarray:259,"ndarray-ops":254,"typedarray-pool":308}],79:[function(t,e,r){"use strict";var n=t("gl-vec3");e.exports=function(t,e){var r=t.positions,i=t.vectors,a={positions:[],vertexIntensity:[],vertexIntensityBounds:t.vertexIntensityBounds,vectors:[],cells:[],coneOffset:t.coneOffset,colormap:t.colormap};if(0===t.positions.length)return e&&(e[0]=[0,0,0],e[1]=[0,0,0]),a;for(var o=0,s=1/0,l=-1/0,c=1/0,u=-1/0,f=1/0,h=-1/0,p=null,d=null,m=[],g=1/0,v=!1,y=0;yo&&(o=n.length(b)),y){var _=2*n.distance(p,x)/(n.length(d)+n.length(b));_?(g=Math.min(g,_),v=!1):v=!0}v||(p=x,d=b),m.push(b)}var w=[s,c,f],T=[l,u,h];e&&(e[0]=w,e[1]=T),0===o&&(o=1);var k=1/o;isFinite(g)||(g=1),a.vectorScale=g;var A=t.coneSize||.5;t.absoluteConeSize&&(A=t.absoluteConeSize*k),a.coneScale=A;y=0;for(var M=0;y=1},p.isTransparent=function(){return this.opacity<1},p.pickSlots=1,p.setPickBase=function(t){this.pickId=t},p.update=function(t){t=t||{};var e=this.gl;this.dirty=!0,"lightPosition"in t&&(this.lightPosition=t.lightPosition),"opacity"in t&&(this.opacity=t.opacity),"ambient"in t&&(this.ambientLight=t.ambient),"diffuse"in t&&(this.diffuseLight=t.diffuse),"specular"in t&&(this.specularLight=t.specular),"roughness"in t&&(this.roughness=t.roughness),"fresnel"in t&&(this.fresnel=t.fresnel),void 0!==t.tubeScale&&(this.tubeScale=t.tubeScale),void 0!==t.vectorScale&&(this.vectorScale=t.vectorScale),void 0!==t.coneScale&&(this.coneScale=t.coneScale),void 0!==t.coneOffset&&(this.coneOffset=t.coneOffset),t.colormap&&(this.texture.shape=[256,256],this.texture.minFilter=e.LINEAR_MIPMAP_LINEAR,this.texture.magFilter=e.LINEAR,this.texture.setPixels(function(t){for(var e=u({colormap:t,nshades:256,format:"rgba"}),r=new Uint8Array(1024),n=0;n<256;++n){for(var i=e[n],a=0;a<3;++a)r[4*n+a]=i[a];r[4*n+3]=255*i[3]}return c(r,[256,256,4],[4,0,1])}(t.colormap)),this.texture.generateMipmap());var r=t.cells,n=t.positions,i=t.vectors;if(n&&r&&i){var a=[],o=[],s=[],l=[],f=[];this.cells=r,this.positions=n,this.vectors=i;var h=t.meshColor||[1,1,1,1],p=t.vertexIntensity,d=1/0,m=-1/0;if(p)if(t.vertexIntensityBounds)d=+t.vertexIntensityBounds[0],m=+t.vertexIntensityBounds[1];else for(var g=0;g0){var m=this.triShader;m.bind(),m.uniforms=c,this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind()}},p.drawPick=function(t){t=t||{};for(var e=this.gl,r=t.model||f,n=t.view||f,i=t.projection||f,a=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],o=0;o<3;++o)a[0][o]=Math.max(a[0][o],this.clipBounds[0][o]),a[1][o]=Math.min(a[1][o],this.clipBounds[1][o]);this._model=[].slice.call(r),this._view=[].slice.call(n),this._projection=[].slice.call(i),this._resolution=[e.drawingBufferWidth,e.drawingBufferHeight];var s={model:r,view:n,projection:i,clipBounds:a,tubeScale:this.tubeScale,vectorScale:this.vectorScale,coneScale:this.coneScale,coneOffset:this.coneOffset,pickId:this.pickId/255},l=this.pickShader;l.bind(),l.uniforms=s,this.triangleCount>0&&(this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind())},p.pick=function(t){if(!t)return null;if(t.id!==this.pickId)return null;var e=t.value[0]+256*t.value[1]+65536*t.value[2],r=this.cells[e],n=this.positions[r[1]].slice(0,3),i={position:n,dataCoordinate:n,index:Math.floor(r[1]/48)};return"cone"===this.traceType?i.index=Math.floor(r[1]/48):"streamtube"===this.traceType&&(i.intensity=this.intensity[r[1]],i.velocity=this.vectors[r[1]].slice(0,3),i.divergence=this.vectors[r[1]][3],i.index=e),i},p.dispose=function(){this.texture.dispose(),this.triShader.dispose(),this.pickShader.dispose(),this.triangleVAO.dispose(),this.trianglePositions.dispose(),this.triangleVectors.dispose(),this.triangleColors.dispose(),this.triangleUVs.dispose(),this.triangleIds.dispose()},e.exports=function(t,e,r){var n=r.shaders;1===arguments.length&&(t=(e=t).gl);var s=d(t,n),l=m(t,n),u=o(t,c(new Uint8Array([255,255,255,255]),[1,1,4]));u.generateMipmap(),u.minFilter=t.LINEAR_MIPMAP_LINEAR,u.magFilter=t.LINEAR;var f=i(t),p=i(t),g=i(t),v=i(t),y=i(t),x=a(t,[{buffer:f,type:t.FLOAT,size:4},{buffer:y,type:t.UNSIGNED_BYTE,size:4,normalized:!0},{buffer:g,type:t.FLOAT,size:4},{buffer:v,type:t.FLOAT,size:2},{buffer:p,type:t.FLOAT,size:4}]),b=new h(t,u,s,l,f,p,y,g,v,x,r.traceType||"cone");return b.update(e),b}},{colormap:53,"gl-buffer":78,"gl-mat4/invert":98,"gl-mat4/multiply":100,"gl-shader":132,"gl-texture2d":146,"gl-vao":150,ndarray:259}],81:[function(t,e,r){var n=t("glslify"),i=n(["precision highp float;\n\nprecision highp float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float rawIndex, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n float index = rawIndex - floor(rawIndex /\n (segmentCount * 6.0)) *\n (segmentCount * 6.0);\n\n float segment = floor(0.001 + index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex > 2.99 && segmentIndex < 3.01) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n float nextAngle = (\n (segmentIndex > 0.99 && segmentIndex < 1.01) ||\n (segmentIndex > 4.99 && segmentIndex < 5.01)\n ) ? 1.0 : 0.0;\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex < 3.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec3 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\n\nuniform float vectorScale, coneScale, coneOffset;\nuniform mat4 model, view, projection, inverseModel;\nuniform vec3 eyePosition, lightPosition;\n\nvarying vec3 f_normal, f_lightDirection, f_eyeDirection, f_data, f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * conePosition;\n cameraCoordinate.xyz /= cameraCoordinate.w;\n f_lightDirection = lightPosition - cameraCoordinate.xyz;\n f_eyeDirection = eyePosition - cameraCoordinate.xyz;\n f_normal = normalize((vec4(normal, 0.0) * inverseModel).xyz);\n\n // vec4 m_position = model * vec4(conePosition, 1.0);\n vec4 t_position = view * conePosition;\n gl_Position = projection * t_position;\n\n f_color = color;\n f_data = conePosition.xyz;\n f_position = position.xyz;\n f_uv = uv;\n}\n"]),a=n(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness, fresnel, kambient, kdiffuse, kspecular, opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal, f_lightDirection, f_eyeDirection, f_data, f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = min(1.0, max(0.0, cookTorranceSpecular(L, V, N, roughness, fresnel)));\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}\n"]),o=n(["precision highp float;\n\nprecision highp float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the cone vertex and normal at the given index.\n//\n// The returned vertex is for a cone with its top at origin and height of 1.0,\n// pointing in the direction of the vector attribute.\n//\n// Each cone is made up of a top vertex, a center base vertex and base perimeter vertices.\n// These vertices are used to make up the triangles of the cone by the following:\n// segment + 0 top vertex\n// segment + 1 perimeter vertex a+1\n// segment + 2 perimeter vertex a\n// segment + 3 center base vertex\n// segment + 4 perimeter vertex a\n// segment + 5 perimeter vertex a+1\n// Where segment is the number of the radial segment * 6 and a is the angle at that radial segment.\n// To go from index to segment, floor(index / 6)\n// To go from segment to angle, 2*pi * (segment/segmentCount)\n// To go from index to segment index, index - (segment*6)\n//\nvec3 getConePosition(vec3 d, float rawIndex, float coneOffset, out vec3 normal) {\n\n const float segmentCount = 8.0;\n\n float index = rawIndex - floor(rawIndex /\n (segmentCount * 6.0)) *\n (segmentCount * 6.0);\n\n float segment = floor(0.001 + index/6.0);\n float segmentIndex = index - (segment*6.0);\n\n normal = -normalize(d);\n\n if (segmentIndex > 2.99 && segmentIndex < 3.01) {\n return mix(vec3(0.0), -d, coneOffset);\n }\n\n float nextAngle = (\n (segmentIndex > 0.99 && segmentIndex < 1.01) ||\n (segmentIndex > 4.99 && segmentIndex < 5.01)\n ) ? 1.0 : 0.0;\n float angle = 2.0 * 3.14159 * ((segment + nextAngle) / segmentCount);\n\n vec3 v1 = mix(d, vec3(0.0), coneOffset);\n vec3 v2 = v1 - d;\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d)*0.25;\n vec3 y = v * sin(angle) * length(d)*0.25;\n vec3 v3 = v2 + x + y;\n if (segmentIndex < 3.0) {\n vec3 tx = u * sin(angle);\n vec3 ty = v * -cos(angle);\n vec3 tangent = tx + ty;\n normal = normalize(cross(v3 - v1, tangent));\n }\n\n if (segmentIndex == 0.0) {\n return mix(d, vec3(0.0), coneOffset);\n }\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform float vectorScale, coneScale, coneOffset;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getConePosition(mat3(model) * ((vectorScale * coneScale) * vector.xyz), position.w, coneOffset, normal);\n vec4 conePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n gl_Position = projection * view * conePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]),s=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]);r.meshShader={vertex:i,fragment:a,attributes:[{name:"position",type:"vec4"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"},{name:"vector",type:"vec3"}]},r.pickShader={vertex:o,fragment:s,attributes:[{name:"position",type:"vec4"},{name:"id",type:"vec4"},{name:"vector",type:"vec3"}]}},{glslify:231}],82:[function(t,e,r){e.exports={0:"NONE",1:"ONE",2:"LINE_LOOP",3:"LINE_STRIP",4:"TRIANGLES",5:"TRIANGLE_STRIP",6:"TRIANGLE_FAN",256:"DEPTH_BUFFER_BIT",512:"NEVER",513:"LESS",514:"EQUAL",515:"LEQUAL",516:"GREATER",517:"NOTEQUAL",518:"GEQUAL",519:"ALWAYS",768:"SRC_COLOR",769:"ONE_MINUS_SRC_COLOR",770:"SRC_ALPHA",771:"ONE_MINUS_SRC_ALPHA",772:"DST_ALPHA",773:"ONE_MINUS_DST_ALPHA",774:"DST_COLOR",775:"ONE_MINUS_DST_COLOR",776:"SRC_ALPHA_SATURATE",1024:"STENCIL_BUFFER_BIT",1028:"FRONT",1029:"BACK",1032:"FRONT_AND_BACK",1280:"INVALID_ENUM",1281:"INVALID_VALUE",1282:"INVALID_OPERATION",1285:"OUT_OF_MEMORY",1286:"INVALID_FRAMEBUFFER_OPERATION",2304:"CW",2305:"CCW",2849:"LINE_WIDTH",2884:"CULL_FACE",2885:"CULL_FACE_MODE",2886:"FRONT_FACE",2928:"DEPTH_RANGE",2929:"DEPTH_TEST",2930:"DEPTH_WRITEMASK",2931:"DEPTH_CLEAR_VALUE",2932:"DEPTH_FUNC",2960:"STENCIL_TEST",2961:"STENCIL_CLEAR_VALUE",2962:"STENCIL_FUNC",2963:"STENCIL_VALUE_MASK",2964:"STENCIL_FAIL",2965:"STENCIL_PASS_DEPTH_FAIL",2966:"STENCIL_PASS_DEPTH_PASS",2967:"STENCIL_REF",2968:"STENCIL_WRITEMASK",2978:"VIEWPORT",3024:"DITHER",3042:"BLEND",3088:"SCISSOR_BOX",3089:"SCISSOR_TEST",3106:"COLOR_CLEAR_VALUE",3107:"COLOR_WRITEMASK",3317:"UNPACK_ALIGNMENT",3333:"PACK_ALIGNMENT",3379:"MAX_TEXTURE_SIZE",3386:"MAX_VIEWPORT_DIMS",3408:"SUBPIXEL_BITS",3410:"RED_BITS",3411:"GREEN_BITS",3412:"BLUE_BITS",3413:"ALPHA_BITS",3414:"DEPTH_BITS",3415:"STENCIL_BITS",3553:"TEXTURE_2D",4352:"DONT_CARE",4353:"FASTEST",4354:"NICEST",5120:"BYTE",5121:"UNSIGNED_BYTE",5122:"SHORT",5123:"UNSIGNED_SHORT",5124:"INT",5125:"UNSIGNED_INT",5126:"FLOAT",5386:"INVERT",5890:"TEXTURE",6401:"STENCIL_INDEX",6402:"DEPTH_COMPONENT",6406:"ALPHA",6407:"RGB",6408:"RGBA",6409:"LUMINANCE",6410:"LUMINANCE_ALPHA",7680:"KEEP",7681:"REPLACE",7682:"INCR",7683:"DECR",7936:"VENDOR",7937:"RENDERER",7938:"VERSION",9728:"NEAREST",9729:"LINEAR",9984:"NEAREST_MIPMAP_NEAREST",9985:"LINEAR_MIPMAP_NEAREST",9986:"NEAREST_MIPMAP_LINEAR",9987:"LINEAR_MIPMAP_LINEAR",10240:"TEXTURE_MAG_FILTER",10241:"TEXTURE_MIN_FILTER",10242:"TEXTURE_WRAP_S",10243:"TEXTURE_WRAP_T",10497:"REPEAT",10752:"POLYGON_OFFSET_UNITS",16384:"COLOR_BUFFER_BIT",32769:"CONSTANT_COLOR",32770:"ONE_MINUS_CONSTANT_COLOR",32771:"CONSTANT_ALPHA",32772:"ONE_MINUS_CONSTANT_ALPHA",32773:"BLEND_COLOR",32774:"FUNC_ADD",32777:"BLEND_EQUATION_RGB",32778:"FUNC_SUBTRACT",32779:"FUNC_REVERSE_SUBTRACT",32819:"UNSIGNED_SHORT_4_4_4_4",32820:"UNSIGNED_SHORT_5_5_5_1",32823:"POLYGON_OFFSET_FILL",32824:"POLYGON_OFFSET_FACTOR",32854:"RGBA4",32855:"RGB5_A1",32873:"TEXTURE_BINDING_2D",32926:"SAMPLE_ALPHA_TO_COVERAGE",32928:"SAMPLE_COVERAGE",32936:"SAMPLE_BUFFERS",32937:"SAMPLES",32938:"SAMPLE_COVERAGE_VALUE",32939:"SAMPLE_COVERAGE_INVERT",32968:"BLEND_DST_RGB",32969:"BLEND_SRC_RGB",32970:"BLEND_DST_ALPHA",32971:"BLEND_SRC_ALPHA",33071:"CLAMP_TO_EDGE",33170:"GENERATE_MIPMAP_HINT",33189:"DEPTH_COMPONENT16",33306:"DEPTH_STENCIL_ATTACHMENT",33635:"UNSIGNED_SHORT_5_6_5",33648:"MIRRORED_REPEAT",33901:"ALIASED_POINT_SIZE_RANGE",33902:"ALIASED_LINE_WIDTH_RANGE",33984:"TEXTURE0",33985:"TEXTURE1",33986:"TEXTURE2",33987:"TEXTURE3",33988:"TEXTURE4",33989:"TEXTURE5",33990:"TEXTURE6",33991:"TEXTURE7",33992:"TEXTURE8",33993:"TEXTURE9",33994:"TEXTURE10",33995:"TEXTURE11",33996:"TEXTURE12",33997:"TEXTURE13",33998:"TEXTURE14",33999:"TEXTURE15",34e3:"TEXTURE16",34001:"TEXTURE17",34002:"TEXTURE18",34003:"TEXTURE19",34004:"TEXTURE20",34005:"TEXTURE21",34006:"TEXTURE22",34007:"TEXTURE23",34008:"TEXTURE24",34009:"TEXTURE25",34010:"TEXTURE26",34011:"TEXTURE27",34012:"TEXTURE28",34013:"TEXTURE29",34014:"TEXTURE30",34015:"TEXTURE31",34016:"ACTIVE_TEXTURE",34024:"MAX_RENDERBUFFER_SIZE",34041:"DEPTH_STENCIL",34055:"INCR_WRAP",34056:"DECR_WRAP",34067:"TEXTURE_CUBE_MAP",34068:"TEXTURE_BINDING_CUBE_MAP",34069:"TEXTURE_CUBE_MAP_POSITIVE_X",34070:"TEXTURE_CUBE_MAP_NEGATIVE_X",34071:"TEXTURE_CUBE_MAP_POSITIVE_Y",34072:"TEXTURE_CUBE_MAP_NEGATIVE_Y",34073:"TEXTURE_CUBE_MAP_POSITIVE_Z",34074:"TEXTURE_CUBE_MAP_NEGATIVE_Z",34076:"MAX_CUBE_MAP_TEXTURE_SIZE",34338:"VERTEX_ATTRIB_ARRAY_ENABLED",34339:"VERTEX_ATTRIB_ARRAY_SIZE",34340:"VERTEX_ATTRIB_ARRAY_STRIDE",34341:"VERTEX_ATTRIB_ARRAY_TYPE",34342:"CURRENT_VERTEX_ATTRIB",34373:"VERTEX_ATTRIB_ARRAY_POINTER",34466:"NUM_COMPRESSED_TEXTURE_FORMATS",34467:"COMPRESSED_TEXTURE_FORMATS",34660:"BUFFER_SIZE",34661:"BUFFER_USAGE",34816:"STENCIL_BACK_FUNC",34817:"STENCIL_BACK_FAIL",34818:"STENCIL_BACK_PASS_DEPTH_FAIL",34819:"STENCIL_BACK_PASS_DEPTH_PASS",34877:"BLEND_EQUATION_ALPHA",34921:"MAX_VERTEX_ATTRIBS",34922:"VERTEX_ATTRIB_ARRAY_NORMALIZED",34930:"MAX_TEXTURE_IMAGE_UNITS",34962:"ARRAY_BUFFER",34963:"ELEMENT_ARRAY_BUFFER",34964:"ARRAY_BUFFER_BINDING",34965:"ELEMENT_ARRAY_BUFFER_BINDING",34975:"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",35040:"STREAM_DRAW",35044:"STATIC_DRAW",35048:"DYNAMIC_DRAW",35632:"FRAGMENT_SHADER",35633:"VERTEX_SHADER",35660:"MAX_VERTEX_TEXTURE_IMAGE_UNITS",35661:"MAX_COMBINED_TEXTURE_IMAGE_UNITS",35663:"SHADER_TYPE",35664:"FLOAT_VEC2",35665:"FLOAT_VEC3",35666:"FLOAT_VEC4",35667:"INT_VEC2",35668:"INT_VEC3",35669:"INT_VEC4",35670:"BOOL",35671:"BOOL_VEC2",35672:"BOOL_VEC3",35673:"BOOL_VEC4",35674:"FLOAT_MAT2",35675:"FLOAT_MAT3",35676:"FLOAT_MAT4",35678:"SAMPLER_2D",35680:"SAMPLER_CUBE",35712:"DELETE_STATUS",35713:"COMPILE_STATUS",35714:"LINK_STATUS",35715:"VALIDATE_STATUS",35716:"INFO_LOG_LENGTH",35717:"ATTACHED_SHADERS",35718:"ACTIVE_UNIFORMS",35719:"ACTIVE_UNIFORM_MAX_LENGTH",35720:"SHADER_SOURCE_LENGTH",35721:"ACTIVE_ATTRIBUTES",35722:"ACTIVE_ATTRIBUTE_MAX_LENGTH",35724:"SHADING_LANGUAGE_VERSION",35725:"CURRENT_PROGRAM",36003:"STENCIL_BACK_REF",36004:"STENCIL_BACK_VALUE_MASK",36005:"STENCIL_BACK_WRITEMASK",36006:"FRAMEBUFFER_BINDING",36007:"RENDERBUFFER_BINDING",36048:"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",36049:"FRAMEBUFFER_ATTACHMENT_OBJECT_NAME",36050:"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL",36051:"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE",36053:"FRAMEBUFFER_COMPLETE",36054:"FRAMEBUFFER_INCOMPLETE_ATTACHMENT",36055:"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",36057:"FRAMEBUFFER_INCOMPLETE_DIMENSIONS",36061:"FRAMEBUFFER_UNSUPPORTED",36064:"COLOR_ATTACHMENT0",36096:"DEPTH_ATTACHMENT",36128:"STENCIL_ATTACHMENT",36160:"FRAMEBUFFER",36161:"RENDERBUFFER",36162:"RENDERBUFFER_WIDTH",36163:"RENDERBUFFER_HEIGHT",36164:"RENDERBUFFER_INTERNAL_FORMAT",36168:"STENCIL_INDEX8",36176:"RENDERBUFFER_RED_SIZE",36177:"RENDERBUFFER_GREEN_SIZE",36178:"RENDERBUFFER_BLUE_SIZE",36179:"RENDERBUFFER_ALPHA_SIZE",36180:"RENDERBUFFER_DEPTH_SIZE",36181:"RENDERBUFFER_STENCIL_SIZE",36194:"RGB565",36336:"LOW_FLOAT",36337:"MEDIUM_FLOAT",36338:"HIGH_FLOAT",36339:"LOW_INT",36340:"MEDIUM_INT",36341:"HIGH_INT",36346:"SHADER_COMPILER",36347:"MAX_VERTEX_UNIFORM_VECTORS",36348:"MAX_VARYING_VECTORS",36349:"MAX_FRAGMENT_UNIFORM_VECTORS",37440:"UNPACK_FLIP_Y_WEBGL",37441:"UNPACK_PREMULTIPLY_ALPHA_WEBGL",37442:"CONTEXT_LOST_WEBGL",37443:"UNPACK_COLORSPACE_CONVERSION_WEBGL",37444:"BROWSER_DEFAULT_WEBGL"}},{}],83:[function(t,e,r){var n=t("./1.0/numbers");e.exports=function(t){return n[t]}},{"./1.0/numbers":82}],84:[function(t,e,r){"use strict";e.exports=function(t){var e=t.gl,r=n(e),o=i(e,[{buffer:r,type:e.FLOAT,size:3,offset:0,stride:40},{buffer:r,type:e.FLOAT,size:4,offset:12,stride:40},{buffer:r,type:e.FLOAT,size:3,offset:28,stride:40}]),l=a(e);l.attributes.position.location=0,l.attributes.color.location=1,l.attributes.offset.location=2;var c=new s(e,r,o,l);return c.update(t),c};var n=t("gl-buffer"),i=t("gl-vao"),a=t("./shaders/index"),o=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function s(t,e,r,n){this.gl=t,this.shader=n,this.buffer=e,this.vao=r,this.pixelRatio=1,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.lineWidth=[1,1,1],this.capSize=[10,10,10],this.lineCount=[0,0,0],this.lineOffset=[0,0,0],this.opacity=1,this.hasAlpha=!1}var l=s.prototype;function c(t,e){for(var r=0;r<3;++r)t[0][r]=Math.min(t[0][r],e[r]),t[1][r]=Math.max(t[1][r],e[r])}l.isOpaque=function(){return!this.hasAlpha},l.isTransparent=function(){return this.hasAlpha},l.drawTransparent=l.draw=function(t){var e=this.gl,r=this.shader.uniforms;this.shader.bind();var n=r.view=t.view||o,i=r.projection=t.projection||o;r.model=t.model||o,r.clipBounds=this.clipBounds,r.opacity=this.opacity;var a=n[12],s=n[13],l=n[14],c=n[15],u=(t._ortho||!1?2:1)*this.pixelRatio*(i[3]*a+i[7]*s+i[11]*l+i[15]*c)/e.drawingBufferHeight;this.vao.bind();for(var f=0;f<3;++f)e.lineWidth(this.lineWidth[f]*this.pixelRatio),r.capSize=this.capSize[f]*u,this.lineCount[f]&&e.drawArrays(e.LINES,this.lineOffset[f],this.lineCount[f]);this.vao.unbind()};var u=function(){for(var t=new Array(3),e=0;e<3;++e){for(var r=[],n=1;n<=2;++n)for(var i=-1;i<=1;i+=2){var a=[0,0,0];a[(n+e)%3]=i,r.push(a)}t[e]=r}return t}();function f(t,e,r,n){for(var i=u[n],a=0;a0)(m=u.slice())[s]+=p[1][s],i.push(u[0],u[1],u[2],d[0],d[1],d[2],d[3],0,0,0,m[0],m[1],m[2],d[0],d[1],d[2],d[3],0,0,0),c(this.bounds,m),o+=2+f(i,m,d,s)}}this.lineCount[s]=o-this.lineOffset[s]}this.buffer.update(i)}},l.dispose=function(){this.shader.dispose(),this.buffer.dispose(),this.vao.dispose()}},{"./shaders/index":85,"gl-buffer":78,"gl-vao":150}],85:[function(t,e,r){"use strict";var n=t("glslify"),i=t("gl-shader"),a=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position, offset;\nattribute vec4 color;\nuniform mat4 model, view, projection;\nuniform float capSize;\nvarying vec4 fragColor;\nvarying vec3 fragPosition;\n\nvoid main() {\n vec4 worldPosition = model * vec4(position, 1.0);\n worldPosition = (worldPosition / worldPosition.w) + vec4(capSize * offset, 0.0);\n gl_Position = projection * view * worldPosition;\n fragColor = color;\n fragPosition = position;\n}"]),o=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float opacity;\nvarying vec3 fragPosition;\nvarying vec4 fragColor;\n\nvoid main() {\n if (\n outOfRange(clipBounds[0], clipBounds[1], fragPosition) ||\n fragColor.a * opacity == 0.\n ) discard;\n\n gl_FragColor = opacity * fragColor;\n}"]);e.exports=function(t){return i(t,a,o,null,[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"offset",type:"vec3"}])}},{"gl-shader":132,glslify:231}],86:[function(t,e,r){"use strict";var n=t("gl-texture2d");e.exports=function(t,e,r,n){i||(i=t.FRAMEBUFFER_UNSUPPORTED,a=t.FRAMEBUFFER_INCOMPLETE_ATTACHMENT,o=t.FRAMEBUFFER_INCOMPLETE_DIMENSIONS,s=t.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);var c=t.getExtension("WEBGL_draw_buffers");!l&&c&&function(t,e){var r=t.getParameter(e.MAX_COLOR_ATTACHMENTS_WEBGL);l=new Array(r+1);for(var n=0;n<=r;++n){for(var i=new Array(r),a=0;au||r<0||r>u)throw new Error("gl-fbo: Parameters are too large for FBO");var f=1;if("color"in(n=n||{})){if((f=Math.max(0|n.color,0))<0)throw new Error("gl-fbo: Must specify a nonnegative number of colors");if(f>1){if(!c)throw new Error("gl-fbo: Multiple draw buffer extension not supported");if(f>t.getParameter(c.MAX_COLOR_ATTACHMENTS_WEBGL))throw new Error("gl-fbo: Context does not support "+f+" draw buffers")}}var h=t.UNSIGNED_BYTE,p=t.getExtension("OES_texture_float");if(n.float&&f>0){if(!p)throw new Error("gl-fbo: Context does not support floating point textures");h=t.FLOAT}else n.preferFloat&&f>0&&p&&(h=t.FLOAT);var m=!0;"depth"in n&&(m=!!n.depth);var g=!1;"stencil"in n&&(g=!!n.stencil);return new d(t,e,r,h,f,m,g,c)};var i,a,o,s,l=null;function c(t){return[t.getParameter(t.FRAMEBUFFER_BINDING),t.getParameter(t.RENDERBUFFER_BINDING),t.getParameter(t.TEXTURE_BINDING_2D)]}function u(t,e){t.bindFramebuffer(t.FRAMEBUFFER,e[0]),t.bindRenderbuffer(t.RENDERBUFFER,e[1]),t.bindTexture(t.TEXTURE_2D,e[2])}function f(t){switch(t){case i:throw new Error("gl-fbo: Framebuffer unsupported");case a:throw new Error("gl-fbo: Framebuffer incomplete attachment");case o:throw new Error("gl-fbo: Framebuffer incomplete dimensions");case s:throw new Error("gl-fbo: Framebuffer incomplete missing attachment");default:throw new Error("gl-fbo: Framebuffer failed for unspecified reason")}}function h(t,e,r,i,a,o){if(!i)return null;var s=n(t,e,r,a,i);return s.magFilter=t.NEAREST,s.minFilter=t.NEAREST,s.mipSamples=1,s.bind(),t.framebufferTexture2D(t.FRAMEBUFFER,o,t.TEXTURE_2D,s.handle,0),s}function p(t,e,r,n,i){var a=t.createRenderbuffer();return t.bindRenderbuffer(t.RENDERBUFFER,a),t.renderbufferStorage(t.RENDERBUFFER,n,e,r),t.framebufferRenderbuffer(t.FRAMEBUFFER,i,t.RENDERBUFFER,a),a}function d(t,e,r,n,i,a,o,s){this.gl=t,this._shape=[0|e,0|r],this._destroyed=!1,this._ext=s,this.color=new Array(i);for(var d=0;d1&&s.drawBuffersWEBGL(l[o]);var y=r.getExtension("WEBGL_depth_texture");y?d?t.depth=h(r,i,a,y.UNSIGNED_INT_24_8_WEBGL,r.DEPTH_STENCIL,r.DEPTH_STENCIL_ATTACHMENT):m&&(t.depth=h(r,i,a,r.UNSIGNED_SHORT,r.DEPTH_COMPONENT,r.DEPTH_ATTACHMENT)):m&&d?t._depth_rb=p(r,i,a,r.DEPTH_STENCIL,r.DEPTH_STENCIL_ATTACHMENT):m?t._depth_rb=p(r,i,a,r.DEPTH_COMPONENT16,r.DEPTH_ATTACHMENT):d&&(t._depth_rb=p(r,i,a,r.STENCIL_INDEX,r.STENCIL_ATTACHMENT));var x=r.checkFramebufferStatus(r.FRAMEBUFFER);if(x!==r.FRAMEBUFFER_COMPLETE){t._destroyed=!0,r.bindFramebuffer(r.FRAMEBUFFER,null),r.deleteFramebuffer(t.handle),t.handle=null,t.depth&&(t.depth.dispose(),t.depth=null),t._depth_rb&&(r.deleteRenderbuffer(t._depth_rb),t._depth_rb=null);for(v=0;vi||r<0||r>i)throw new Error("gl-fbo: Can't resize FBO, invalid dimensions");t._shape[0]=e,t._shape[1]=r;for(var a=c(n),o=0;o>8*p&255;this.pickOffset=r,i.bind();var d=i.uniforms;d.viewTransform=t,d.pickOffset=e,d.shape=this.shape;var m=i.attributes;return this.positionBuffer.bind(),m.position.pointer(),this.weightBuffer.bind(),m.weight.pointer(s.UNSIGNED_BYTE,!1),this.idBuffer.bind(),m.pickId.pointer(s.UNSIGNED_BYTE,!1),s.drawArrays(s.TRIANGLES,0,o),r+this.shape[0]*this.shape[1]}}}(),f.pick=function(t,e,r){var n=this.pickOffset,i=this.shape[0]*this.shape[1];if(r=n+i)return null;var a=r-n,o=this.xData,s=this.yData;return{object:this,pointId:a,dataCoord:[o[a%this.shape[0]],s[a/this.shape[0]|0]]}},f.update=function(t){var e=(t=t||{}).shape||[0,0],r=t.x||i(e[0]),o=t.y||i(e[1]),s=t.z||new Float32Array(e[0]*e[1]),l=!1!==t.zsmooth;this.xData=r,this.yData=o;var c,u,f,p,d=t.colorLevels||[0],m=t.colorValues||[0,0,0,1],g=d.length,v=this.bounds;l?(c=v[0]=r[0],u=v[1]=o[0],f=v[2]=r[r.length-1],p=v[3]=o[o.length-1]):(c=v[0]=r[0]+(r[1]-r[0])/2,u=v[1]=o[0]+(o[1]-o[0])/2,f=v[2]=r[r.length-1]+(r[r.length-1]-r[r.length-2])/2,p=v[3]=o[o.length-1]+(o[o.length-1]-o[o.length-2])/2);var y=1/(f-c),x=1/(p-u),b=e[0],_=e[1];this.shape=[b,_];var w=(l?(b-1)*(_-1):b*_)*(h.length>>>1);this.numVertices=w;for(var T=a.mallocUint8(4*w),k=a.mallocFloat32(2*w),A=a.mallocUint8(2*w),M=a.mallocUint32(w),S=0,E=l?b-1:b,L=l?_-1:_,C=0;C max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D dashTexture;\nuniform float dashScale;\nuniform float opacity;\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (\n outOfRange(clipBounds[0], clipBounds[1], worldPosition) ||\n fragColor.a * opacity == 0.\n ) discard;\n\n float dashWeight = texture2D(dashTexture, vec2(dashScale * pixelArcLength, 0)).r;\n if(dashWeight < 0.5) {\n discard;\n }\n gl_FragColor = fragColor * opacity;\n}\n"]),s=n(["precision highp float;\n#define GLSLIFY 1\n\n#define FLOAT_MAX 1.70141184e38\n#define FLOAT_MIN 1.17549435e-38\n\n// https://github.com/mikolalysenko/glsl-read-float/blob/master/index.glsl\nvec4 packFloat(float v) {\n float av = abs(v);\n\n //Handle special cases\n if(av < FLOAT_MIN) {\n return vec4(0.0, 0.0, 0.0, 0.0);\n } else if(v > FLOAT_MAX) {\n return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;\n } else if(v < -FLOAT_MAX) {\n return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;\n }\n\n vec4 c = vec4(0,0,0,0);\n\n //Compute exponent and mantissa\n float e = floor(log2(av));\n float m = av * pow(2.0, -e) - 1.0;\n\n //Unpack mantissa\n c[1] = floor(128.0 * m);\n m -= c[1] / 128.0;\n c[2] = floor(32768.0 * m);\n m -= c[2] / 32768.0;\n c[3] = floor(8388608.0 * m);\n\n //Unpack exponent\n float ebias = e + 127.0;\n c[0] = floor(ebias / 2.0);\n ebias -= c[0] * 2.0;\n c[1] += floor(ebias) * 128.0;\n\n //Unpack sign bit\n c[0] += 128.0 * step(0.0, -v);\n\n //Scale back to range\n return c / 255.0;\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform float pickId;\nuniform vec3 clipBounds[2];\n\nvarying vec3 worldPosition;\nvarying float pixelArcLength;\nvarying vec4 fragColor;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], worldPosition)) discard;\n\n gl_FragColor = vec4(pickId/255.0, packFloat(pixelArcLength).xyz);\n}"]),l=[{name:"position",type:"vec3"},{name:"nextPosition",type:"vec3"},{name:"arcLength",type:"float"},{name:"lineWidth",type:"float"},{name:"color",type:"vec4"}];r.createShader=function(t){return i(t,a,o,null,l)},r.createPickShader=function(t){return i(t,a,s,null,l)}},{"gl-shader":132,glslify:231}],91:[function(t,e,r){"use strict";e.exports=function(t){var e=t.gl||t.scene&&t.scene.gl,r=f(e);r.attributes.position.location=0,r.attributes.nextPosition.location=1,r.attributes.arcLength.location=2,r.attributes.lineWidth.location=3,r.attributes.color.location=4;var o=h(e);o.attributes.position.location=0,o.attributes.nextPosition.location=1,o.attributes.arcLength.location=2,o.attributes.lineWidth.location=3,o.attributes.color.location=4;for(var s=n(e),l=i(e,[{buffer:s,size:3,offset:0,stride:48},{buffer:s,size:3,offset:12,stride:48},{buffer:s,size:1,offset:24,stride:48},{buffer:s,size:1,offset:28,stride:48},{buffer:s,size:4,offset:32,stride:48}]),u=c(new Array(1024),[256,1,4]),p=0;p<1024;++p)u.data[p]=255;var d=a(e,u);d.wrap=e.REPEAT;var m=new v(e,r,o,s,l,d);return m.update(t),m};var n=t("gl-buffer"),i=t("gl-vao"),a=t("gl-texture2d"),o=new Uint8Array(4),s=new Float32Array(o.buffer);var l=t("binary-search-bounds"),c=t("ndarray"),u=t("./lib/shaders"),f=u.createShader,h=u.createPickShader,p=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function d(t,e){for(var r=0,n=0;n<3;++n){var i=t[n]-e[n];r+=i*i}return Math.sqrt(r)}function m(t){for(var e=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],r=0;r<3;++r)e[0][r]=Math.max(t[0][r],e[0][r]),e[1][r]=Math.min(t[1][r],e[1][r]);return e}function g(t,e,r,n){this.arcLength=t,this.position=e,this.index=r,this.dataCoordinate=n}function v(t,e,r,n,i,a){this.gl=t,this.shader=e,this.pickShader=r,this.buffer=n,this.vao=i,this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.points=[],this.arcLength=[],this.vertexCount=0,this.bounds=[[0,0,0],[0,0,0]],this.pickId=0,this.lineWidth=1,this.texture=a,this.dashScale=1,this.opacity=1,this.hasAlpha=!1,this.dirty=!0,this.pixelRatio=1}var y=v.prototype;y.isTransparent=function(){return this.hasAlpha},y.isOpaque=function(){return!this.hasAlpha},y.pickSlots=1,y.setPickBase=function(t){this.pickId=t},y.drawTransparent=y.draw=function(t){if(this.vertexCount){var e=this.gl,r=this.shader,n=this.vao;r.bind(),r.uniforms={model:t.model||p,view:t.view||p,projection:t.projection||p,clipBounds:m(this.clipBounds),dashTexture:this.texture.bind(),dashScale:this.dashScale/this.arcLength[this.arcLength.length-1],opacity:this.opacity,screenShape:[e.drawingBufferWidth,e.drawingBufferHeight],pixelRatio:this.pixelRatio},n.bind(),n.draw(e.TRIANGLE_STRIP,this.vertexCount),n.unbind()}},y.drawPick=function(t){if(this.vertexCount){var e=this.gl,r=this.pickShader,n=this.vao;r.bind(),r.uniforms={model:t.model||p,view:t.view||p,projection:t.projection||p,pickId:this.pickId,clipBounds:m(this.clipBounds),screenShape:[e.drawingBufferWidth,e.drawingBufferHeight],pixelRatio:this.pixelRatio},n.bind(),n.draw(e.TRIANGLE_STRIP,this.vertexCount),n.unbind()}},y.update=function(t){var e,r;this.dirty=!0;var n=!!t.connectGaps;"dashScale"in t&&(this.dashScale=t.dashScale),this.hasAlpha=!1,"opacity"in t&&(this.opacity=+t.opacity,this.opacity<1&&(this.hasAlpha=!0));var i=[],a=[],o=[],s=0,u=0,f=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],h=t.position||t.positions;if(h){var p=t.color||t.colors||[0,0,0,1],m=t.lineWidth||1,g=!1;t:for(e=1;e0){for(var w=0;w<24;++w)i.push(i[i.length-12]);u+=2,g=!0}continue t}f[0][r]=Math.min(f[0][r],b[r],_[r]),f[1][r]=Math.max(f[1][r],b[r],_[r])}Array.isArray(p[0])?(v=p.length>e-1?p[e-1]:p.length>0?p[p.length-1]:[0,0,0,1],y=p.length>e?p[e]:p.length>0?p[p.length-1]:[0,0,0,1]):v=y=p,3===v.length&&(v=[v[0],v[1],v[2],1]),3===y.length&&(y=[y[0],y[1],y[2],1]),!this.hasAlpha&&v[3]<1&&(this.hasAlpha=!0),x=Array.isArray(m)?m.length>e-1?m[e-1]:m.length>0?m[m.length-1]:[0,0,0,1]:m;var T=s;if(s+=d(b,_),g){for(r=0;r<2;++r)i.push(b[0],b[1],b[2],_[0],_[1],_[2],T,x,v[0],v[1],v[2],v[3]);u+=2,g=!1}i.push(b[0],b[1],b[2],_[0],_[1],_[2],T,x,v[0],v[1],v[2],v[3],b[0],b[1],b[2],_[0],_[1],_[2],T,-x,v[0],v[1],v[2],v[3],_[0],_[1],_[2],b[0],b[1],b[2],s,-x,y[0],y[1],y[2],y[3],_[0],_[1],_[2],b[0],b[1],b[2],s,x,y[0],y[1],y[2],y[3]),u+=4}}if(this.buffer.update(i),a.push(s),o.push(h[h.length-1].slice()),this.bounds=f,this.vertexCount=u,this.points=o,this.arcLength=a,"dashes"in t){var k=t.dashes.slice();for(k.unshift(0),e=1;e1.0001)return null;v+=g[f]}if(Math.abs(v-1)>.001)return null;return[h,s(t,g),g]}},{barycentric:14,"polytope-closest-point/lib/closest_point_2d.js":270}],111:[function(t,e,r){var n=t("glslify"),i=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position, normal;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model\n , view\n , projection\n , inverseModel;\nuniform vec3 eyePosition\n , lightPosition;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvec4 project(vec3 p) {\n return projection * view * model * vec4(p, 1.0);\n}\n\nvoid main() {\n gl_Position = project(position);\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * vec4(position , 1.0);\n cameraCoordinate.xyz /= cameraCoordinate.w;\n f_lightDirection = lightPosition - cameraCoordinate.xyz;\n f_eyeDirection = eyePosition - cameraCoordinate.xyz;\n f_normal = normalize((vec4(normal, 0.0) * inverseModel).xyz);\n\n f_color = color;\n f_data = position;\n f_uv = uv;\n}\n"]),a=n(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\n//#pragma glslify: beckmann = require(glsl-specular-beckmann) // used in gl-surface3d\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness\n , fresnel\n , kambient\n , kdiffuse\n , kspecular;\nuniform sampler2D texture;\n\nvarying vec3 f_normal\n , f_lightDirection\n , f_eyeDirection\n , f_data;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (f_color.a == 0.0 ||\n outOfRange(clipBounds[0], clipBounds[1], f_data)\n ) discard;\n\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = min(1.0, max(0.0, cookTorranceSpecular(L, V, N, roughness, fresnel)));\n //float specular = max(0.0, beckmann(L, V, N, roughness)); // used in gl-surface3d\n\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = vec4(f_color.rgb, 1.0) * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * f_color.a;\n}\n"]),o=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\n\nuniform mat4 model, view, projection;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_color = color;\n f_data = position;\n f_uv = uv;\n}"]),s=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec3 f_data;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_data)) discard;\n\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]),l=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 uv;\nattribute float pointSize;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0.0, 0.0 ,0.0 ,0.0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n }\n gl_PointSize = pointSize;\n f_color = color;\n f_uv = uv;\n}"]),c=n(["precision highp float;\n#define GLSLIFY 1\n\nuniform sampler2D texture;\nuniform float opacity;\n\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n vec2 pointR = gl_PointCoord.xy - vec2(0.5, 0.5);\n if(dot(pointR, pointR) > 0.25) {\n discard;\n }\n gl_FragColor = f_color * texture2D(texture, f_uv) * opacity;\n}"]),u=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n f_id = id;\n f_position = position;\n}"]),f=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]),h=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute float pointSize;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0.0, 0.0, 0.0, 0.0);\n } else {\n gl_Position = projection * view * model * vec4(position, 1.0);\n gl_PointSize = pointSize;\n }\n f_id = id;\n f_position = position;\n}"]),p=n(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec3 position;\n\nuniform mat4 model, view, projection;\n\nvoid main() {\n gl_Position = projection * view * model * vec4(position, 1.0);\n}"]),d=n(["precision highp float;\n#define GLSLIFY 1\n\nuniform vec3 contourColor;\n\nvoid main() {\n gl_FragColor = vec4(contourColor, 1.0);\n}\n"]);r.meshShader={vertex:i,fragment:a,attributes:[{name:"position",type:"vec3"},{name:"normal",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"}]},r.wireShader={vertex:o,fragment:s,attributes:[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"}]},r.pointShader={vertex:l,fragment:c,attributes:[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"},{name:"pointSize",type:"float"}]},r.pickShader={vertex:u,fragment:f,attributes:[{name:"position",type:"vec3"},{name:"id",type:"vec4"}]},r.pointPickShader={vertex:h,fragment:f,attributes:[{name:"position",type:"vec3"},{name:"pointSize",type:"float"},{name:"id",type:"vec4"}]},r.contourShader={vertex:p,fragment:d,attributes:[{name:"position",type:"vec3"}]}},{glslify:231}],112:[function(t,e,r){"use strict";var n=t("gl-shader"),i=t("gl-buffer"),a=t("gl-vao"),o=t("gl-texture2d"),s=t("normals"),l=t("gl-mat4/multiply"),c=t("gl-mat4/invert"),u=t("ndarray"),f=t("colormap"),h=t("simplicial-complex-contour"),p=t("typedarray-pool"),d=t("./lib/shaders"),m=t("./lib/closest-point"),g=d.meshShader,v=d.wireShader,y=d.pointShader,x=d.pickShader,b=d.pointPickShader,_=d.contourShader,w=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function T(t,e,r,n,i,a,o,s,l,c,u,f,h,p,d,m,g,v,y,x,b,_,T,k,A,M,S){this.gl=t,this.pixelRatio=1,this.cells=[],this.positions=[],this.intensity=[],this.texture=e,this.dirty=!0,this.triShader=r,this.lineShader=n,this.pointShader=i,this.pickShader=a,this.pointPickShader=o,this.contourShader=s,this.trianglePositions=l,this.triangleColors=u,this.triangleNormals=h,this.triangleUVs=f,this.triangleIds=c,this.triangleVAO=p,this.triangleCount=0,this.lineWidth=1,this.edgePositions=d,this.edgeColors=g,this.edgeUVs=v,this.edgeIds=m,this.edgeVAO=y,this.edgeCount=0,this.pointPositions=x,this.pointColors=_,this.pointUVs=T,this.pointSizes=k,this.pointIds=b,this.pointVAO=A,this.pointCount=0,this.contourLineWidth=1,this.contourPositions=M,this.contourVAO=S,this.contourCount=0,this.contourColor=[0,0,0],this.contourEnable=!0,this.pickVertex=!0,this.pickId=1,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.lightPosition=[1e5,1e5,0],this.ambientLight=.8,this.diffuseLight=.8,this.specularLight=2,this.roughness=.5,this.fresnel=1.5,this.opacity=1,this.hasAlpha=!1,this.opacityscale=!1,this._model=w,this._view=w,this._projection=w,this._resolution=[1,1]}var k=T.prototype;function A(t,e){if(!e)return 1;if(!e.length)return 1;for(var r=0;rt&&r>0){var n=(e[r][0]-t)/(e[r][0]-e[r-1][0]);return e[r][1]*(1-n)+n*e[r-1][1]}}return 1}function M(t){var e=n(t,g.vertex,g.fragment);return e.attributes.position.location=0,e.attributes.color.location=2,e.attributes.uv.location=3,e.attributes.normal.location=4,e}function S(t){var e=n(t,v.vertex,v.fragment);return e.attributes.position.location=0,e.attributes.color.location=2,e.attributes.uv.location=3,e}function E(t){var e=n(t,y.vertex,y.fragment);return e.attributes.position.location=0,e.attributes.color.location=2,e.attributes.uv.location=3,e.attributes.pointSize.location=4,e}function L(t){var e=n(t,x.vertex,x.fragment);return e.attributes.position.location=0,e.attributes.id.location=1,e}function C(t){var e=n(t,b.vertex,b.fragment);return e.attributes.position.location=0,e.attributes.id.location=1,e.attributes.pointSize.location=4,e}function P(t){var e=n(t,_.vertex,_.fragment);return e.attributes.position.location=0,e}k.isOpaque=function(){return!this.hasAlpha},k.isTransparent=function(){return this.hasAlpha},k.pickSlots=1,k.setPickBase=function(t){this.pickId=t},k.highlight=function(t){if(t&&this.contourEnable){for(var e=h(this.cells,this.intensity,t.intensity),r=e.cells,n=e.vertexIds,i=e.vertexWeights,a=r.length,o=p.mallocFloat32(6*a),s=0,l=0;l0&&((f=this.triShader).bind(),f.uniforms=s,this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind());this.edgeCount>0&&this.lineWidth>0&&((f=this.lineShader).bind(),f.uniforms=s,this.edgeVAO.bind(),e.lineWidth(this.lineWidth*this.pixelRatio),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind());this.pointCount>0&&((f=this.pointShader).bind(),f.uniforms=s,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind());this.contourEnable&&this.contourCount>0&&this.contourLineWidth>0&&((f=this.contourShader).bind(),f.uniforms=s,this.contourVAO.bind(),e.drawArrays(e.LINES,0,this.contourCount),this.contourVAO.unbind())},k.drawPick=function(t){t=t||{};for(var e=this.gl,r=t.model||w,n=t.view||w,i=t.projection||w,a=[[-1e6,-1e6,-1e6],[1e6,1e6,1e6]],o=0;o<3;++o)a[0][o]=Math.max(a[0][o],this.clipBounds[0][o]),a[1][o]=Math.min(a[1][o],this.clipBounds[1][o]);this._model=[].slice.call(r),this._view=[].slice.call(n),this._projection=[].slice.call(i),this._resolution=[e.drawingBufferWidth,e.drawingBufferHeight];var s,l={model:r,view:n,projection:i,clipBounds:a,pickId:this.pickId/255};((s=this.pickShader).bind(),s.uniforms=l,this.triangleCount>0&&(this.triangleVAO.bind(),e.drawArrays(e.TRIANGLES,0,3*this.triangleCount),this.triangleVAO.unbind()),this.edgeCount>0&&(this.edgeVAO.bind(),e.lineWidth(this.lineWidth*this.pixelRatio),e.drawArrays(e.LINES,0,2*this.edgeCount),this.edgeVAO.unbind()),this.pointCount>0)&&((s=this.pointPickShader).bind(),s.uniforms=l,this.pointVAO.bind(),e.drawArrays(e.POINTS,0,this.pointCount),this.pointVAO.unbind())},k.pick=function(t){if(!t)return null;if(t.id!==this.pickId)return null;for(var e=t.value[0]+256*t.value[1]+65536*t.value[2],r=this.cells[e],n=this.positions,i=new Array(r.length),a=0;ai[k]&&(r.uniforms.dataAxis=c,r.uniforms.screenOffset=u,r.uniforms.color=g[t],r.uniforms.angle=v[t],a.drawArrays(a.TRIANGLES,i[k],i[A]-i[k]))),y[t]&&T&&(u[1^t]-=M*p*x[t],r.uniforms.dataAxis=f,r.uniforms.screenOffset=u,r.uniforms.color=b[t],r.uniforms.angle=_[t],a.drawArrays(a.TRIANGLES,w,T)),u[1^t]=M*s[2+(1^t)]-1,d[t+2]&&(u[1^t]+=M*p*m[t+2],ki[k]&&(r.uniforms.dataAxis=c,r.uniforms.screenOffset=u,r.uniforms.color=g[t+2],r.uniforms.angle=v[t+2],a.drawArrays(a.TRIANGLES,i[k],i[A]-i[k]))),y[t+2]&&T&&(u[1^t]+=M*p*x[t+2],r.uniforms.dataAxis=f,r.uniforms.screenOffset=u,r.uniforms.color=b[t+2],r.uniforms.angle=_[t+2],a.drawArrays(a.TRIANGLES,w,T))}),m.drawTitle=function(){var t=[0,0],e=[0,0];return function(){var r=this.plot,n=this.shader,i=r.gl,a=r.screenBox,o=r.titleCenter,s=r.titleAngle,l=r.titleColor,c=r.pixelRatio;if(this.titleCount){for(var u=0;u<2;++u)e[u]=2*(o[u]*c-a[u])/(a[2+u]-a[u])-1;n.bind(),n.uniforms.dataAxis=t,n.uniforms.screenOffset=e,n.uniforms.angle=s,n.uniforms.color=l,i.drawArrays(i.TRIANGLES,this.titleOffset,this.titleCount)}}}(),m.bind=(h=[0,0],p=[0,0],d=[0,0],function(){var t=this.plot,e=this.shader,r=t._tickBounds,n=t.dataBox,i=t.screenBox,a=t.viewBox;e.bind();for(var o=0;o<2;++o){var s=r[o],l=r[o+2]-s,c=.5*(n[o+2]+n[o]),u=n[o+2]-n[o],f=a[o],m=a[o+2]-f,g=i[o],v=i[o+2]-g;p[o]=2*l/u*m/v,h[o]=2*(s-c)/u*m/v}d[1]=2*t.pixelRatio/(i[3]-i[1]),d[0]=d[1]*(i[3]-i[1])/(i[2]-i[0]),e.uniforms.dataScale=p,e.uniforms.dataShift=h,e.uniforms.textScale=d,this.vbo.bind(),e.attributes.textCoordinate.pointer()}),m.update=function(t){var e,r,n,i,o,s=[],l=t.ticks,c=t.bounds;for(o=0;o<2;++o){var u=[Math.floor(s.length/3)],f=[-1/0],h=l[o];for(e=0;e=0){var m=e[d]-n[d]*(e[d+2]-e[d])/(n[d+2]-n[d]);0===d?o.drawLine(m,e[1],m,e[3],p[d],h[d]):o.drawLine(e[0],m,e[2],m,p[d],h[d])}}for(d=0;d=0;--t)this.objects[t].dispose();this.objects.length=0;for(t=this.overlays.length-1;t>=0;--t)this.overlays[t].dispose();this.overlays.length=0,this.gl=null},c.addObject=function(t){this.objects.indexOf(t)<0&&(this.objects.push(t),this.setDirty())},c.removeObject=function(t){for(var e=this.objects,r=0;rMath.abs(e))c.rotate(a,0,0,-t*r*Math.PI*d.rotateSpeed/window.innerWidth);else if(!d._ortho){var o=-d.zoomSpeed*i*e/window.innerHeight*(a-c.lastT())/20;c.pan(a,0,0,f*(Math.exp(o)-1))}}}),!0)},d.enableMouseListeners(),d};var n=t("right-now"),i=t("3d-view"),a=t("mouse-change"),o=t("mouse-wheel"),s=t("mouse-event-offset"),l=t("has-passive-events")},{"3d-view":7,"has-passive-events":232,"mouse-change":247,"mouse-event-offset":248,"mouse-wheel":250,"right-now":278}],120:[function(t,e,r){var n=t("glslify"),i=t("gl-shader"),a=n(["precision mediump float;\n#define GLSLIFY 1\nattribute vec2 position;\nvarying vec2 uv;\nvoid main() {\n uv = position;\n gl_Position = vec4(position, 0, 1);\n}"]),o=n(["precision mediump float;\n#define GLSLIFY 1\n\nuniform sampler2D accumBuffer;\nvarying vec2 uv;\n\nvoid main() {\n vec4 accum = texture2D(accumBuffer, 0.5 * (uv + 1.0));\n gl_FragColor = min(vec4(1,1,1,1), accum);\n}"]);e.exports=function(t){return i(t,a,o,null,[{name:"position",type:"vec2"}])}},{"gl-shader":132,glslify:231}],121:[function(t,e,r){"use strict";var n=t("./camera.js"),i=t("gl-axes3d"),a=t("gl-axes3d/properties"),o=t("gl-spikes3d"),s=t("gl-select-static"),l=t("gl-fbo"),c=t("a-big-triangle"),u=t("mouse-change"),f=t("gl-mat4/perspective"),h=t("gl-mat4/ortho"),p=t("./lib/shader"),d=t("is-mobile")({tablet:!0,featureDetect:!0});function m(){this.mouse=[-1,-1],this.screen=null,this.distance=1/0,this.index=null,this.dataCoordinate=null,this.dataPosition=null,this.object=null,this.data=null}function g(t){var e=Math.round(Math.log(Math.abs(t))/Math.log(10));if(e<0){var r=Math.round(Math.pow(10,-e));return Math.ceil(t*r)/r}if(e>0){r=Math.round(Math.pow(10,e));return Math.ceil(t/r)*r}return Math.ceil(t)}function v(t){return"boolean"!=typeof t||t}e.exports={createScene:function(t){(t=t||{}).camera=t.camera||{};var e=t.canvas;if(!e){if(e=document.createElement("canvas"),t.container)t.container.appendChild(e);else document.body.appendChild(e)}var r=t.gl;r||(t.glOptions&&(d=!!t.glOptions.preserveDrawingBuffer),r=function(t,e){var r=null;try{(r=t.getContext("webgl",e))||(r=t.getContext("experimental-webgl",e))}catch(t){return null}return r}(e,t.glOptions||{premultipliedAlpha:!0,antialias:!0,preserveDrawingBuffer:d}));if(!r)throw new Error("webgl not supported");var y=t.bounds||[[-10,-10,-10],[10,10,10]],x=new m,b=l(r,r.drawingBufferWidth,r.drawingBufferHeight,{preferFloat:!d}),_=p(r),w=t.cameraObject&&!0===t.cameraObject._ortho||t.camera.projection&&"orthographic"===t.camera.projection.type||!1,T={eye:t.camera.eye||[2,0,0],center:t.camera.center||[0,0,0],up:t.camera.up||[0,1,0],zoomMin:t.camera.zoomMax||.1,zoomMax:t.camera.zoomMin||100,mode:t.camera.mode||"turntable",_ortho:w},k=t.axes||{},A=i(r,k);A.enable=!k.disable;var M=t.spikes||{},S=o(r,M),E=[],L=[],C=[],P=[],I=!0,O=!0,z=new Array(16),D=new Array(16),R={view:null,projection:z,model:D,_ortho:!1},F=(O=!0,[r.drawingBufferWidth,r.drawingBufferHeight]),B=t.cameraObject||n(e,T),N={gl:r,contextLost:!1,pixelRatio:t.pixelRatio||1,canvas:e,selection:x,camera:B,axes:A,axesPixels:null,spikes:S,bounds:y,objects:E,shape:F,aspect:t.aspectRatio||[1,1,1],pickRadius:t.pickRadius||10,zNear:t.zNear||.01,zFar:t.zFar||1e3,fovy:t.fovy||Math.PI/4,clearColor:t.clearColor||[0,0,0,0],autoResize:v(t.autoResize),autoBounds:v(t.autoBounds),autoScale:!!t.autoScale,autoCenter:v(t.autoCenter),clipToBounds:v(t.clipToBounds),snapToData:!!t.snapToData,onselect:t.onselect||null,onrender:t.onrender||null,onclick:t.onclick||null,cameraParams:R,oncontextloss:null,mouseListener:null,_stopped:!1,getAspectratio:function(){return{x:this.aspect[0],y:this.aspect[1],z:this.aspect[2]}},setAspectratio:function(t){this.aspect[0]=t.x,this.aspect[1]=t.y,this.aspect[2]=t.z,O=!0},setBounds:function(t,e){this.bounds[0][t]=e.min,this.bounds[1][t]=e.max},setClearColor:function(t){this.clearColor=t},clearRGBA:function(){this.gl.clearColor(this.clearColor[0],this.clearColor[1],this.clearColor[2],this.clearColor[3]),this.gl.clear(this.gl.COLOR_BUFFER_BIT|this.gl.DEPTH_BUFFER_BIT)}},j=[r.drawingBufferWidth/N.pixelRatio|0,r.drawingBufferHeight/N.pixelRatio|0];function U(){if(!N._stopped&&N.autoResize){var t=e.parentNode,r=1,n=1;t&&t!==document.body?(r=t.clientWidth,n=t.clientHeight):(r=window.innerWidth,n=window.innerHeight);var i=0|Math.ceil(r*N.pixelRatio),a=0|Math.ceil(n*N.pixelRatio);if(i!==e.width||a!==e.height){e.width=i,e.height=a;var o=e.style;o.position=o.position||"absolute",o.left="0px",o.top="0px",o.width=r+"px",o.height=n+"px",I=!0}}}N.autoResize&&U();function V(){for(var t=E.length,e=P.length,n=0;n0&&0===C[e-1];)C.pop(),P.pop().dispose()}function H(){if(N.contextLost)return!0;r.isContextLost()&&(N.contextLost=!0,N.mouseListener.enabled=!1,N.selection.object=null,N.oncontextloss&&N.oncontextloss())}window.addEventListener("resize",U),N.update=function(t){N._stopped||(t=t||{},I=!0,O=!0)},N.add=function(t){N._stopped||(t.axes=A,E.push(t),L.push(-1),I=!0,O=!0,V())},N.remove=function(t){if(!N._stopped){var e=E.indexOf(t);e<0||(E.splice(e,1),L.pop(),I=!0,O=!0,V())}},N.dispose=function(){if(!N._stopped&&(N._stopped=!0,window.removeEventListener("resize",U),e.removeEventListener("webglcontextlost",H),N.mouseListener.enabled=!1,!N.contextLost)){A.dispose(),S.dispose();for(var t=0;tx.distance)continue;for(var c=0;c 1.0) {\n discard;\n }\n baseColor = mix(borderColor, color, step(radius, centerFraction));\n gl_FragColor = vec4(baseColor.rgb * baseColor.a, baseColor.a);\n }\n}\n"]),r.pickVertex=n(["precision mediump float;\n#define GLSLIFY 1\n\nattribute vec2 position;\nattribute vec4 pickId;\n\nuniform mat3 matrix;\nuniform float pointSize;\nuniform vec4 pickOffset;\n\nvarying vec4 fragId;\n\nvoid main() {\n vec3 hgPosition = matrix * vec3(position, 1);\n gl_Position = vec4(hgPosition.xy, 0, hgPosition.z);\n gl_PointSize = pointSize;\n\n vec4 id = pickId + pickOffset;\n id.y += floor(id.x / 256.0);\n id.x -= floor(id.x / 256.0) * 256.0;\n\n id.z += floor(id.y / 256.0);\n id.y -= floor(id.y / 256.0) * 256.0;\n\n id.w += floor(id.z / 256.0);\n id.z -= floor(id.z / 256.0) * 256.0;\n\n fragId = id;\n}\n"]),r.pickFragment=n(["precision mediump float;\n#define GLSLIFY 1\n\nvarying vec4 fragId;\n\nvoid main() {\n float radius = length(2.0 * gl_PointCoord.xy - 1.0);\n if(radius > 1.0) {\n discard;\n }\n gl_FragColor = fragId / 255.0;\n}\n"])},{glslify:231}],123:[function(t,e,r){"use strict";var n=t("gl-shader"),i=t("gl-buffer"),a=t("typedarray-pool"),o=t("./lib/shader");function s(t,e,r,n,i){this.plot=t,this.offsetBuffer=e,this.pickBuffer=r,this.shader=n,this.pickShader=i,this.sizeMin=.5,this.sizeMinCap=2,this.sizeMax=20,this.areaRatio=1,this.pointCount=0,this.color=[1,0,0,1],this.borderColor=[0,0,0,1],this.blend=!1,this.pickOffset=0,this.points=null}e.exports=function(t,e){var r=t.gl,a=i(r),l=i(r),c=n(r,o.pointVertex,o.pointFragment),u=n(r,o.pickVertex,o.pickFragment),f=new s(t,a,l,c,u);return f.update(e),t.addObject(f),f};var l,c,u=s.prototype;u.dispose=function(){this.shader.dispose(),this.pickShader.dispose(),this.offsetBuffer.dispose(),this.pickBuffer.dispose(),this.plot.removeObject(this)},u.update=function(t){var e;function r(e,r){return e in t?t[e]:r}t=t||{},this.sizeMin=r("sizeMin",.5),this.sizeMax=r("sizeMax",20),this.color=r("color",[1,0,0,1]).slice(),this.areaRatio=r("areaRatio",1),this.borderColor=r("borderColor",[0,0,0,1]).slice(),this.blend=r("blend",!1);var n=t.positions.length>>>1,i=t.positions instanceof Float32Array,o=t.idToIndex instanceof Int32Array&&t.idToIndex.length>=n,s=t.positions,l=i?s:a.mallocFloat32(s.length),c=o?t.idToIndex:a.mallocInt32(n);if(i||l.set(s),!o)for(l.set(s),e=0;e>>1;for(r=0;r=e[0]&&a<=e[2]&&o>=e[1]&&o<=e[3]&&n++}return n}(this.points,i),u=this.plot.pickPixelRatio*Math.max(Math.min(this.sizeMinCap,this.sizeMin),Math.min(this.sizeMax,this.sizeMax/Math.pow(s,.33333)));l[0]=2/a,l[4]=2/o,l[6]=-2*i[0]/a-1,l[7]=-2*i[1]/o-1,this.offsetBuffer.bind(),r.bind(),r.attributes.position.pointer(),r.uniforms.matrix=l,r.uniforms.color=this.color,r.uniforms.borderColor=this.borderColor,r.uniforms.pointCloud=u<5,r.uniforms.pointSize=u,r.uniforms.centerFraction=Math.min(1,Math.max(0,Math.sqrt(1-this.areaRatio))),e&&(c[0]=255&t,c[1]=t>>8&255,c[2]=t>>16&255,c[3]=t>>24&255,this.pickBuffer.bind(),r.attributes.pickId.pointer(n.UNSIGNED_BYTE),r.uniforms.pickOffset=c,this.pickOffset=t);var f=n.getParameter(n.BLEND),h=n.getParameter(n.DITHER);return f&&!this.blend&&n.disable(n.BLEND),h&&n.disable(n.DITHER),n.drawArrays(n.POINTS,0,this.pointCount),f&&!this.blend&&n.enable(n.BLEND),h&&n.enable(n.DITHER),t+this.pointCount}),u.draw=u.unifiedDraw,u.drawPick=u.unifiedDraw,u.pick=function(t,e,r){var n=this.pickOffset,i=this.pointCount;if(r=n+i)return null;var a=r-n,o=this.points;return{object:this,pointId:a,dataCoord:[o[2*a],o[2*a+1]]}}},{"./lib/shader":122,"gl-buffer":78,"gl-shader":132,"typedarray-pool":308}],124:[function(t,e,r){e.exports=function(t,e,r,n){var i,a,o,s,l,c=e[0],u=e[1],f=e[2],h=e[3],p=r[0],d=r[1],m=r[2],g=r[3];(a=c*p+u*d+f*m+h*g)<0&&(a=-a,p=-p,d=-d,m=-m,g=-g);1-a>1e-6?(i=Math.acos(a),o=Math.sin(i),s=Math.sin((1-n)*i)/o,l=Math.sin(n*i)/o):(s=1-n,l=n);return t[0]=s*c+l*p,t[1]=s*u+l*d,t[2]=s*f+l*m,t[3]=s*h+l*g,t}},{}],125:[function(t,e,r){"use strict";e.exports=function(t){return t||0===t?t.toString():""}},{}],126:[function(t,e,r){"use strict";var n=t("vectorize-text");e.exports=function(t,e,r){var a=i[e];a||(a=i[e]={});if(t in a)return a[t];var o={textAlign:"center",textBaseline:"middle",lineHeight:1,font:e,lineSpacing:1.25,styletags:{breaklines:!0,bolds:!0,italics:!0,subscripts:!0,superscripts:!0},triangles:!0},s=n(t,o);o.triangles=!1;var l,c,u=n(t,o);if(r&&1!==r){for(l=0;l max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform vec4 highlightId;\nuniform float highlightScale;\nuniform mat4 model, view, projection;\nuniform vec3 clipBounds[2];\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = 1.0;\n if(distance(highlightId, id) < 0.0001) {\n scale = highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1);\n vec4 viewPosition = view * worldPosition;\n viewPosition = viewPosition / viewPosition.w;\n vec4 clipPosition = projection * (viewPosition + scale * vec4(glyph.x, -glyph.y, 0, 0));\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]),o=i(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float highlightScale, pixelRatio;\nuniform vec4 highlightId;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float scale = pixelRatio;\n if(distance(highlightId.bgr, id.bgr) < 0.001) {\n scale *= highlightScale;\n }\n\n vec4 worldPosition = model * vec4(position, 1.0);\n vec4 viewPosition = view * worldPosition;\n vec4 clipPosition = projection * viewPosition;\n clipPosition /= clipPosition.w;\n\n gl_Position = clipPosition + vec4(screenSize * scale * vec2(glyph.x, -glyph.y), 0.0, 0.0);\n interpColor = color;\n pickId = id;\n dataCoordinate = position;\n }\n}"]),s=i(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nattribute vec3 position;\nattribute vec4 color;\nattribute vec2 glyph;\nattribute vec4 id;\n\nuniform float highlightScale;\nuniform vec4 highlightId;\nuniform vec3 axes[2];\nuniform mat4 model, view, projection;\nuniform vec2 screenSize;\nuniform vec3 clipBounds[2];\nuniform float scale, pixelRatio;\n\nvarying vec4 interpColor;\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], position)) {\n\n gl_Position = vec4(0,0,0,0);\n } else {\n float lscale = pixelRatio * scale;\n if(distance(highlightId, id) < 0.0001) {\n lscale *= highlightScale;\n }\n\n vec4 clipCenter = projection * view * model * vec4(position, 1);\n vec3 dataPosition = position + 0.5*lscale*(axes[0] * glyph.x + axes[1] * glyph.y) * clipCenter.w * screenSize.y;\n vec4 clipPosition = projection * view * model * vec4(dataPosition, 1);\n\n gl_Position = clipPosition;\n interpColor = color;\n pickId = id;\n dataCoordinate = dataPosition;\n }\n}\n"]),l=i(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float opacity;\n\nvarying vec4 interpColor;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (\n outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate) ||\n interpColor.a * opacity == 0.\n ) discard;\n gl_FragColor = interpColor * opacity;\n}\n"]),c=i(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 fragClipBounds[2];\nuniform float pickGroup;\n\nvarying vec4 pickId;\nvarying vec3 dataCoordinate;\n\nvoid main() {\n if (outOfRange(fragClipBounds[0], fragClipBounds[1], dataCoordinate)) discard;\n\n gl_FragColor = vec4(pickGroup, pickId.bgr);\n}"]),u=[{name:"position",type:"vec3"},{name:"color",type:"vec4"},{name:"glyph",type:"vec2"},{name:"id",type:"vec4"}],f={vertex:a,fragment:l,attributes:u},h={vertex:o,fragment:l,attributes:u},p={vertex:s,fragment:l,attributes:u},d={vertex:a,fragment:c,attributes:u},m={vertex:o,fragment:c,attributes:u},g={vertex:s,fragment:c,attributes:u};function v(t,e){var r=n(t,e),i=r.attributes;return i.position.location=0,i.color.location=1,i.glyph.location=2,i.id.location=3,r}r.createPerspective=function(t){return v(t,f)},r.createOrtho=function(t){return v(t,h)},r.createProject=function(t){return v(t,p)},r.createPickPerspective=function(t){return v(t,d)},r.createPickOrtho=function(t){return v(t,m)},r.createPickProject=function(t){return v(t,g)}},{"gl-shader":132,glslify:231}],128:[function(t,e,r){"use strict";var n=t("is-string-blank"),i=t("gl-buffer"),a=t("gl-vao"),o=t("typedarray-pool"),s=t("gl-mat4/multiply"),l=t("./lib/shaders"),c=t("./lib/glyphs"),u=t("./lib/get-simple-string"),f=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1];function h(t,e){var r=t[0],n=t[1],i=t[2],a=t[3];return t[0]=e[0]*r+e[4]*n+e[8]*i+e[12]*a,t[1]=e[1]*r+e[5]*n+e[9]*i+e[13]*a,t[2]=e[2]*r+e[6]*n+e[10]*i+e[14]*a,t[3]=e[3]*r+e[7]*n+e[11]*i+e[15]*a,t}function p(t,e,r,n){return h(n,n),h(n,n),h(n,n)}function d(t,e){this.index=t,this.dataCoordinate=this.position=e}function m(t){return!0===t||t>1?1:t}function g(t,e,r,n,i,a,o,s,l,c,u,f){this.gl=t,this.pixelRatio=1,this.shader=e,this.orthoShader=r,this.projectShader=n,this.pointBuffer=i,this.colorBuffer=a,this.glyphBuffer=o,this.idBuffer=s,this.vao=l,this.vertexCount=0,this.lineVertexCount=0,this.opacity=1,this.hasAlpha=!1,this.lineWidth=0,this.projectScale=[2/3,2/3,2/3],this.projectOpacity=[1,1,1],this.projectHasAlpha=!1,this.pickId=0,this.pickPerspectiveShader=c,this.pickOrthoShader=u,this.pickProjectShader=f,this.points=[],this._selectResult=new d(0,[0,0,0]),this.useOrtho=!0,this.bounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.axesProject=[!0,!0,!0],this.axesBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.highlightId=[1,1,1,1],this.highlightScale=2,this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.dirty=!0}e.exports=function(t){var e=t.gl,r=l.createPerspective(e),n=l.createOrtho(e),o=l.createProject(e),s=l.createPickPerspective(e),c=l.createPickOrtho(e),u=l.createPickProject(e),f=i(e),h=i(e),p=i(e),d=i(e),m=a(e,[{buffer:f,size:3,type:e.FLOAT},{buffer:h,size:4,type:e.FLOAT},{buffer:p,size:2,type:e.FLOAT},{buffer:d,size:4,type:e.UNSIGNED_BYTE,normalized:!0}]),v=new g(e,r,n,o,f,h,p,d,m,s,c,u);return v.update(t),v};var v=g.prototype;v.pickSlots=1,v.setPickBase=function(t){this.pickId=t},v.isTransparent=function(){if(this.hasAlpha)return!0;for(var t=0;t<3;++t)if(this.axesProject[t]&&this.projectHasAlpha)return!0;return!1},v.isOpaque=function(){if(!this.hasAlpha)return!0;for(var t=0;t<3;++t)if(this.axesProject[t]&&!this.projectHasAlpha)return!0;return!1};var y=[0,0],x=[0,0,0],b=[0,0,0],_=[0,0,0,1],w=[0,0,0,1],T=f.slice(),k=[0,0,0],A=[[0,0,0],[0,0,0]];function M(t){return t[0]=t[1]=t[2]=0,t}function S(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=1,t}function E(t,e,r,n){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[r]=n,t}function L(t,e,r,n){var i,a=e.axesProject,o=e.gl,l=t.uniforms,c=r.model||f,u=r.view||f,h=r.projection||f,d=e.axesBounds,m=function(t){for(var e=A,r=0;r<2;++r)for(var n=0;n<3;++n)e[r][n]=Math.max(Math.min(t[r][n],1e8),-1e8);return e}(e.clipBounds);i=e.axes&&e.axes.lastCubeProps?e.axes.lastCubeProps.axis:[1,1,1],y[0]=2/o.drawingBufferWidth,y[1]=2/o.drawingBufferHeight,t.bind(),l.view=u,l.projection=h,l.screenSize=y,l.highlightId=e.highlightId,l.highlightScale=e.highlightScale,l.clipBounds=m,l.pickGroup=e.pickId/255,l.pixelRatio=n;for(var g=0;g<3;++g)if(a[g]){l.scale=e.projectScale[g],l.opacity=e.projectOpacity[g];for(var v=T,L=0;L<16;++L)v[L]=0;for(L=0;L<4;++L)v[5*L]=1;v[5*g]=0,i[g]<0?v[12+g]=d[0][g]:v[12+g]=d[1][g],s(v,c,v),l.model=v;var C=(g+1)%3,P=(g+2)%3,I=M(x),O=M(b);I[C]=1,O[P]=1;var z=p(0,0,0,S(_,I)),D=p(0,0,0,S(w,O));if(Math.abs(z[1])>Math.abs(D[1])){var R=z;z=D,D=R,R=I,I=O,O=R;var F=C;C=P,P=F}z[0]<0&&(I[C]=-1),D[1]>0&&(O[P]=-1);var B=0,N=0;for(L=0;L<4;++L)B+=Math.pow(c[4*C+L],2),N+=Math.pow(c[4*P+L],2);I[C]/=Math.sqrt(B),O[P]/=Math.sqrt(N),l.axes[0]=I,l.axes[1]=O,l.fragClipBounds[0]=E(k,m[0],g,-1e8),l.fragClipBounds[1]=E(k,m[1],g,1e8),e.vao.bind(),e.vao.draw(o.TRIANGLES,e.vertexCount),e.lineWidth>0&&(o.lineWidth(e.lineWidth*n),e.vao.draw(o.LINES,e.lineVertexCount,e.vertexCount)),e.vao.unbind()}}var C=[[-1e8,-1e8,-1e8],[1e8,1e8,1e8]];function P(t,e,r,n,i,a,o){var s=r.gl;if((a===r.projectHasAlpha||o)&&L(e,r,n,i),a===r.hasAlpha||o){t.bind();var l=t.uniforms;l.model=n.model||f,l.view=n.view||f,l.projection=n.projection||f,y[0]=2/s.drawingBufferWidth,y[1]=2/s.drawingBufferHeight,l.screenSize=y,l.highlightId=r.highlightId,l.highlightScale=r.highlightScale,l.fragClipBounds=C,l.clipBounds=r.axes.bounds,l.opacity=r.opacity,l.pickGroup=r.pickId/255,l.pixelRatio=i,r.vao.bind(),r.vao.draw(s.TRIANGLES,r.vertexCount),r.lineWidth>0&&(s.lineWidth(r.lineWidth*i),r.vao.draw(s.LINES,r.lineVertexCount,r.vertexCount)),r.vao.unbind()}}function I(t,e,r,i){var a;a=Array.isArray(t)?e=this.pointCount||e<0)return null;var r=this.points[e],n=this._selectResult;n.index=e;for(var i=0;i<3;++i)n.position[i]=n.dataCoordinate[i]=r[i];return n},v.highlight=function(t){if(t){var e=t.index,r=255&e,n=e>>8&255,i=e>>16&255;this.highlightId=[r/255,n/255,i/255,0]}else this.highlightId=[1,1,1,1]},v.update=function(t){if("perspective"in(t=t||{})&&(this.useOrtho=!t.perspective),"orthographic"in t&&(this.useOrtho=!!t.orthographic),"lineWidth"in t&&(this.lineWidth=t.lineWidth),"project"in t)if(Array.isArray(t.project))this.axesProject=t.project;else{var e=!!t.project;this.axesProject=[e,e,e]}if("projectScale"in t)if(Array.isArray(t.projectScale))this.projectScale=t.projectScale.slice();else{var r=+t.projectScale;this.projectScale=[r,r,r]}if(this.projectHasAlpha=!1,"projectOpacity"in t){if(Array.isArray(t.projectOpacity))this.projectOpacity=t.projectOpacity.slice();else{r=+t.projectOpacity;this.projectOpacity=[r,r,r]}for(var n=0;n<3;++n)this.projectOpacity[n]=m(this.projectOpacity[n]),this.projectOpacity[n]<1&&(this.projectHasAlpha=!0)}this.hasAlpha=!1,"opacity"in t&&(this.opacity=m(t.opacity),this.opacity<1&&(this.hasAlpha=!0)),this.dirty=!0;var i,a,s=t.position,l=t.font||"normal",c=t.alignment||[0,0];if(2===c.length)i=c[0],a=c[1];else{i=[],a=[];for(n=0;n0){var O=0,z=x,D=[0,0,0,1],R=[0,0,0,1],F=Array.isArray(p)&&Array.isArray(p[0]),B=Array.isArray(v)&&Array.isArray(v[0]);t:for(n=0;n<_;++n){y+=1;for(w=s[n],T=0;T<3;++T){if(isNaN(w[T])||!isFinite(w[T]))continue t;f[T]=Math.max(f[T],w[T]),u[T]=Math.min(u[T],w[T])}k=(N=I(h,n,l,this.pixelRatio)).mesh,A=N.lines,M=N.bounds;var N,j=N.visible;if(j)if(Array.isArray(p)){if(3===(U=F?n0?1-M[0][0]:Y<0?1+M[1][0]:1,W*=W>0?1-M[0][1]:W<0?1+M[1][1]:1],Z=k.cells||[],J=k.positions||[];for(T=0;T0){var v=r*u;o.drawBox(f-v,h-v,p+v,h+v,a),o.drawBox(f-v,d-v,p+v,d+v,a),o.drawBox(f-v,h-v,f+v,d+v,a),o.drawBox(p-v,h-v,p+v,d+v,a)}}}},s.update=function(t){t=t||{},this.innerFill=!!t.innerFill,this.outerFill=!!t.outerFill,this.innerColor=(t.innerColor||[0,0,0,.5]).slice(),this.outerColor=(t.outerColor||[0,0,0,.5]).slice(),this.borderColor=(t.borderColor||[0,0,0,1]).slice(),this.borderWidth=t.borderWidth||0,this.selectBox=(t.selectBox||this.selectBox).slice()},s.dispose=function(){this.boxBuffer.dispose(),this.boxShader.dispose(),this.plot.removeOverlay(this)}},{"./lib/shaders":129,"gl-buffer":78,"gl-shader":132}],131:[function(t,e,r){"use strict";e.exports=function(t,e){var r=e[0],a=e[1],o=n(t,r,a,{}),s=i.mallocUint8(r*a*4);return new l(t,o,s)};var n=t("gl-fbo"),i=t("typedarray-pool"),a=t("ndarray"),o=t("bit-twiddle").nextPow2;function s(t,e,r,n,i){this.coord=[t,e],this.id=r,this.value=n,this.distance=i}function l(t,e,r){this.gl=t,this.fbo=e,this.buffer=r,this._readTimeout=null;var n=this;this._readCallback=function(){n.gl&&(e.bind(),t.readPixels(0,0,e.shape[0],e.shape[1],t.RGBA,t.UNSIGNED_BYTE,n.buffer),n._readTimeout=null)}}var c=l.prototype;Object.defineProperty(c,"shape",{get:function(){return this.gl?this.fbo.shape.slice():[0,0]},set:function(t){if(this.gl){this.fbo.shape=t;var e=this.fbo.shape[0],r=this.fbo.shape[1];if(r*e*4>this.buffer.length){i.free(this.buffer);for(var n=this.buffer=i.mallocUint8(o(r*e*4)),a=0;ar)for(t=r;te)for(t=e;t=0){for(var T=0|w.type.charAt(w.type.length-1),k=new Array(T),A=0;A=0;)M+=1;_[y]=M}var S=new Array(r.length);function E(){h.program=o.program(p,h._vref,h._fref,b,_);for(var t=0;t=0){if((d=h.charCodeAt(h.length-1)-48)<2||d>4)throw new n("","Invalid data type for attribute "+f+": "+h);s(t,e,p[0],i,d,a,f)}else{if(!(h.indexOf("mat")>=0))throw new n("","Unknown data type for attribute "+f+": "+h);var d;if((d=h.charCodeAt(h.length-1)-48)<2||d>4)throw new n("","Invalid data type for attribute "+f+": "+h);l(t,e,p,i,d,a,f)}}}return a};var n=t("./GLError");function i(t,e,r,n,i,a){this._gl=t,this._wrapper=e,this._index=r,this._locations=n,this._dimension=i,this._constFunc=a}var a=i.prototype;a.pointer=function(t,e,r,n){var i=this._gl,a=this._locations[this._index];i.vertexAttribPointer(a,this._dimension,t||i.FLOAT,!!e,r||0,n||0),i.enableVertexAttribArray(a)},a.set=function(t,e,r,n){return this._constFunc(this._locations[this._index],t,e,r,n)},Object.defineProperty(a,"location",{get:function(){return this._locations[this._index]},set:function(t){return t!==this._locations[this._index]&&(this._locations[this._index]=0|t,this._wrapper.program=null),0|t}});var o=[function(t,e,r){return void 0===r.length?t.vertexAttrib1f(e,r):t.vertexAttrib1fv(e,r)},function(t,e,r,n){return void 0===r.length?t.vertexAttrib2f(e,r,n):t.vertexAttrib2fv(e,r)},function(t,e,r,n,i){return void 0===r.length?t.vertexAttrib3f(e,r,n,i):t.vertexAttrib3fv(e,r)},function(t,e,r,n,i,a){return void 0===r.length?t.vertexAttrib4f(e,r,n,i,a):t.vertexAttrib4fv(e,r)}];function s(t,e,r,n,a,s,l){var c=o[a],u=new i(t,e,r,n,a,c);Object.defineProperty(s,l,{set:function(e){return t.disableVertexAttribArray(n[r]),c(t,n[r],e),e},get:function(){return u},enumerable:!0})}function l(t,e,r,n,i,a,o){for(var l=new Array(i),c=new Array(i),u=0;u4)throw new i("","Invalid uniform dimension type for matrix "+name+": "+v);t["uniformMatrix"+g+"fv"](s[u],!1,f);break}throw new i("","Unknown uniform data type for "+name+": "+v)}if((g=v.charCodeAt(v.length-1)-48)<2||g>4)throw new i("","Invalid data type");switch(v.charAt(0)){case"b":case"i":t["uniform"+g+"iv"](s[u],f);break;case"v":t["uniform"+g+"fv"](s[u],f);break;default:throw new i("","Unrecognized data type for vector "+name+": "+v)}}}}}}function c(t,e,n){if("object"==typeof n){var c=u(n);Object.defineProperty(t,e,{get:a(c),set:l(n),enumerable:!0,configurable:!1})}else s[n]?Object.defineProperty(t,e,{get:(f=n,function(t,e,r){return t.getUniform(e.program,r[f])}),set:l(n),enumerable:!0,configurable:!1}):t[e]=function(t){switch(t){case"bool":return!1;case"int":case"sampler2D":case"samplerCube":case"float":return 0;default:var e=t.indexOf("vec");if(0<=e&&e<=1&&t.length===4+e){if((r=t.charCodeAt(t.length-1)-48)<2||r>4)throw new i("","Invalid data type");return"b"===t.charAt(0)?o(r,!1):o(r,0)}if(0===t.indexOf("mat")&&4===t.length){var r;if((r=t.charCodeAt(t.length-1)-48)<2||r>4)throw new i("","Invalid uniform dimension type for matrix "+name+": "+t);return o(r*r,0)}throw new i("","Unknown uniform data type for "+name+": "+t)}}(r[n].type);var f}function u(t){var e;if(Array.isArray(t)){e=new Array(t.length);for(var r=0;r1){s[0]in a||(a[s[0]]=[]),a=a[s[0]];for(var l=1;l1)for(var l=0;l 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 color, position;\nattribute vec2 uv;\n\nuniform float vectorScale, tubeScale;\nuniform mat4 model, view, projection, inverseModel;\nuniform vec3 eyePosition, lightPosition;\n\nvarying vec3 f_normal, f_lightDirection, f_eyeDirection, f_data, f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n // Scale the vector magnitude to stay constant with\n // model & view changes.\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * tubePosition;\n cameraCoordinate.xyz /= cameraCoordinate.w;\n f_lightDirection = lightPosition - cameraCoordinate.xyz;\n f_eyeDirection = eyePosition - cameraCoordinate.xyz;\n f_normal = normalize((vec4(normal, 0.0) * inverseModel).xyz);\n\n // vec4 m_position = model * vec4(tubePosition, 1.0);\n vec4 t_position = view * tubePosition;\n gl_Position = projection * t_position;\n\n f_color = color;\n f_data = tubePosition.xyz;\n f_position = position.xyz;\n f_uv = uv;\n}\n"]),a=n(["#extension GL_OES_standard_derivatives : enable\n\nprecision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat cookTorranceSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness,\n float fresnel) {\n\n float VdotN = max(dot(viewDirection, surfaceNormal), 0.0);\n float LdotN = max(dot(lightDirection, surfaceNormal), 0.0);\n\n //Half angle vector\n vec3 H = normalize(lightDirection + viewDirection);\n\n //Geometric term\n float NdotH = max(dot(surfaceNormal, H), 0.0);\n float VdotH = max(dot(viewDirection, H), 0.000001);\n float LdotH = max(dot(lightDirection, H), 0.000001);\n float G1 = (2.0 * NdotH * VdotN) / VdotH;\n float G2 = (2.0 * NdotH * LdotN) / LdotH;\n float G = min(1.0, min(G1, G2));\n \n //Distribution term\n float D = beckmannDistribution(NdotH, roughness);\n\n //Fresnel term\n float F = pow(1.0 - VdotN, fresnel);\n\n //Multiply terms and done\n return G * F * D / max(3.14159265 * VdotN, 0.000001);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float roughness, fresnel, kambient, kdiffuse, kspecular, opacity;\nuniform sampler2D texture;\n\nvarying vec3 f_normal, f_lightDirection, f_eyeDirection, f_data, f_position;\nvarying vec4 f_color;\nvarying vec2 f_uv;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n vec3 N = normalize(f_normal);\n vec3 L = normalize(f_lightDirection);\n vec3 V = normalize(f_eyeDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = min(1.0, max(0.0, cookTorranceSpecular(L, V, N, roughness, fresnel)));\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n vec4 surfaceColor = f_color * texture2D(texture, f_uv);\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = litColor * opacity;\n}\n"]),o=n(["precision highp float;\n\nprecision highp float;\n#define GLSLIFY 1\n\nvec3 getOrthogonalVector(vec3 v) {\n // Return up-vector for only-z vector.\n // Return ax + by + cz = 0, a point that lies on the plane that has v as a normal and that isn't (0,0,0).\n // From the above if-statement we have ||a|| > 0 U ||b|| > 0.\n // Assign z = 0, x = -b, y = a:\n // a*-b + b*a + c*0 = -ba + ba + 0 = 0\n if (v.x*v.x > v.z*v.z || v.y*v.y > v.z*v.z) {\n return normalize(vec3(-v.y, v.x, 0.0));\n } else {\n return normalize(vec3(0.0, v.z, -v.y));\n }\n}\n\n// Calculate the tube vertex and normal at the given index.\n//\n// The returned vertex is for a tube ring with its center at origin, radius of length(d), pointing in the direction of d.\n//\n// Each tube segment is made up of a ring of vertices.\n// These vertices are used to make up the triangles of the tube by connecting them together in the vertex array.\n// The indexes of tube segments run from 0 to 8.\n//\nvec3 getTubePosition(vec3 d, float index, out vec3 normal) {\n float segmentCount = 8.0;\n\n float angle = 2.0 * 3.14159 * (index / segmentCount);\n\n vec3 u = getOrthogonalVector(d);\n vec3 v = normalize(cross(u, d));\n\n vec3 x = u * cos(angle) * length(d);\n vec3 y = v * sin(angle) * length(d);\n vec3 v3 = x + y;\n\n normal = normalize(v3);\n\n return v3;\n}\n\nattribute vec4 vector;\nattribute vec4 position;\nattribute vec4 id;\n\nuniform mat4 model, view, projection;\nuniform float tubeScale;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n vec3 normal;\n vec3 XYZ = getTubePosition(mat3(model) * (tubeScale * vector.w * normalize(vector.xyz)), position.w, normal);\n vec4 tubePosition = model * vec4(position.xyz, 1.0) + vec4(XYZ, 0.0);\n\n gl_Position = projection * view * tubePosition;\n f_id = id;\n f_position = position.xyz;\n}\n"]),s=n(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying vec3 f_position;\nvarying vec4 f_id;\n\nvoid main() {\n if (outOfRange(clipBounds[0], clipBounds[1], f_position)) discard;\n\n gl_FragColor = vec4(pickId, f_id.xyz);\n}"]);r.meshShader={vertex:i,fragment:a,attributes:[{name:"position",type:"vec4"},{name:"color",type:"vec4"},{name:"uv",type:"vec2"},{name:"vector",type:"vec4"}]},r.pickShader={vertex:o,fragment:s,attributes:[{name:"position",type:"vec4"},{name:"id",type:"vec4"},{name:"vector",type:"vec4"}]}},{glslify:231}],143:[function(t,e,r){"use strict";var n=t("gl-vec3"),i=t("gl-vec4"),a=["xyz","xzy","yxz","yzx","zxy","zyx"],o=function(t,e,r,a){for(var o=0,s=0;s0)for(T=0;T<8;T++){var k=(T+1)%8;c.push(h[T],p[T],p[k],p[k],h[k],h[T]),f.push(y,v,v,v,y,y),d.push(m,g,g,g,m,m);var A=c.length;u.push([A-6,A-5,A-4],[A-3,A-2,A-1])}var M=h;h=p,p=M;var S=y;y=v,v=S;var E=m;m=g,g=E}return{positions:c,cells:u,vectors:f,vertexIntensity:d}}(t,r,a,o)})),f=[],h=[],p=[],d=[];for(s=0;se)return r-1}return r},l=function(t,e,r){return tr?r:t},c=function(t){var e=1/0;t.sort((function(t,e){return t-e}));for(var r=t.length,n=1;nf-1||y>h-1||x>p-1)return n.create();var b,_,w,T,k,A,M=a[0][d],S=a[0][v],E=a[1][m],L=a[1][y],C=a[2][g],P=(o-M)/(S-M),I=(c-E)/(L-E),O=(u-C)/(a[2][x]-C);switch(isFinite(P)||(P=.5),isFinite(I)||(I=.5),isFinite(O)||(O=.5),r.reversedX&&(d=f-1-d,v=f-1-v),r.reversedY&&(m=h-1-m,y=h-1-y),r.reversedZ&&(g=p-1-g,x=p-1-x),r.filled){case 5:k=g,A=x,w=m*p,T=y*p,b=d*p*h,_=v*p*h;break;case 4:k=g,A=x,b=d*p,_=v*p,w=m*p*f,T=y*p*f;break;case 3:w=m,T=y,k=g*h,A=x*h,b=d*h*p,_=v*h*p;break;case 2:w=m,T=y,b=d*h,_=v*h,k=g*h*f,A=x*h*f;break;case 1:b=d,_=v,k=g*f,A=x*f,w=m*f*p,T=y*f*p;break;default:b=d,_=v,w=m*f,T=y*f,k=g*f*h,A=x*f*h}var z=i[b+w+k],D=i[b+w+A],R=i[b+T+k],F=i[b+T+A],B=i[_+w+k],N=i[_+w+A],j=i[_+T+k],U=i[_+T+A],V=n.create(),H=n.create(),q=n.create(),G=n.create();n.lerp(V,z,B,P),n.lerp(H,D,N,P),n.lerp(q,R,j,P),n.lerp(G,F,U,P);var Y=n.create(),W=n.create();n.lerp(Y,V,q,I),n.lerp(W,H,G,I);var X=n.create();return n.lerp(X,Y,W,O),X}(e,t,p)},m=t.getDivergence||function(t,e){var r=n.create(),i=1e-4;n.add(r,t,[i,0,0]);var a=d(r);n.subtract(a,a,e),n.scale(a,a,1/i),n.add(r,t,[0,i,0]);var o=d(r);n.subtract(o,o,e),n.scale(o,o,1/i),n.add(r,t,[0,0,i]);var s=d(r);return n.subtract(s,s,e),n.scale(s,s,1/i),n.add(r,a,o),n.add(r,r,s),r},g=[],v=e[0][0],y=e[0][1],x=e[0][2],b=e[1][0],_=e[1][1],w=e[1][2],T=function(t){var e=t[0],r=t[1],n=t[2];return!(eb||r_||nw)},k=10*n.distance(e[0],e[1])/i,A=k*k,M=1,S=0,E=r.length;E>1&&(M=function(t){for(var e=[],r=[],n=[],i={},a={},o={},s=t.length,l=0;lS&&(S=F),D.push(F),g.push({points:P,velocities:I,divergences:D});for(var B=0;B<100*i&&P.lengthA&&n.scale(N,N,k/Math.sqrt(j)),n.add(N,N,C),O=d(N),n.squaredDistance(z,N)-A>-1e-4*A){P.push(N),z=N,I.push(O);R=m(N,O),F=n.length(R);isFinite(F)&&F>S&&(S=F),D.push(F)}C=N}}var U=o(g,t.colormap,S,M);return f?U.tubeScale=f:(0===S&&(S=1),U.tubeScale=.5*u*M/S),U};var u=t("./lib/shaders"),f=t("gl-cone3d").createMesh;e.exports.createTubeMesh=function(t,e){return f(t,e,{shaders:u,traceType:"streamtube"})}},{"./lib/shaders":142,"gl-cone3d":79,"gl-vec3":169,"gl-vec4":205}],144:[function(t,e,r){var n=t("gl-shader"),i=t("glslify"),a=i(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 uv;\nattribute vec3 f;\nattribute vec3 normal;\n\nuniform vec3 objectOffset;\nuniform mat4 model, view, projection, inverseModel;\nuniform vec3 lightPosition, eyePosition;\nuniform sampler2D colormap;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n vec3 localCoordinate = vec3(uv.zw, f.x);\n worldCoordinate = objectOffset + localCoordinate;\n vec4 worldPosition = model * vec4(worldCoordinate, 1.0);\n vec4 clipPosition = projection * view * worldPosition;\n gl_Position = clipPosition;\n kill = f.y;\n value = f.z;\n planeCoordinate = uv.xy;\n\n vColor = texture2D(colormap, vec2(value, value));\n\n //Lighting geometry parameters\n vec4 cameraCoordinate = view * worldPosition;\n cameraCoordinate.xyz /= cameraCoordinate.w;\n lightDirection = lightPosition - cameraCoordinate.xyz;\n eyeDirection = eyePosition - cameraCoordinate.xyz;\n surfaceNormal = normalize((vec4(normal,0) * inverseModel).xyz);\n}\n"]),o=i(["precision highp float;\n#define GLSLIFY 1\n\nfloat beckmannDistribution(float x, float roughness) {\n float NdotH = max(x, 0.0001);\n float cos2Alpha = NdotH * NdotH;\n float tan2Alpha = (cos2Alpha - 1.0) / cos2Alpha;\n float roughness2 = roughness * roughness;\n float denom = 3.141592653589793 * roughness2 * cos2Alpha * cos2Alpha;\n return exp(tan2Alpha / roughness2) / denom;\n}\n\nfloat beckmannSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float roughness) {\n return beckmannDistribution(dot(surfaceNormal, normalize(lightDirection + viewDirection)), roughness);\n}\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec3 lowerBound, upperBound;\nuniform float contourTint;\nuniform vec4 contourColor;\nuniform sampler2D colormap;\nuniform vec3 clipBounds[2];\nuniform float roughness, fresnel, kambient, kdiffuse, kspecular, opacity;\nuniform float vertexColor;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n if (\n kill > 0.0 ||\n vColor.a == 0.0 ||\n outOfRange(clipBounds[0], clipBounds[1], worldCoordinate)\n ) discard;\n\n vec3 N = normalize(surfaceNormal);\n vec3 V = normalize(eyeDirection);\n vec3 L = normalize(lightDirection);\n\n if(gl_FrontFacing) {\n N = -N;\n }\n\n float specular = max(beckmannSpecular(L, V, N, roughness), 0.);\n float diffuse = min(kambient + kdiffuse * max(dot(N, L), 0.0), 1.0);\n\n //decide how to interpolate color \u2014 in vertex or in fragment\n vec4 surfaceColor =\n step(vertexColor, .5) * texture2D(colormap, vec2(value, value)) +\n step(.5, vertexColor) * vColor;\n\n vec4 litColor = surfaceColor.a * vec4(diffuse * surfaceColor.rgb + kspecular * vec3(1,1,1) * specular, 1.0);\n\n gl_FragColor = mix(litColor, contourColor, contourTint) * opacity;\n}\n"]),s=i(["precision highp float;\n#define GLSLIFY 1\n\nattribute vec4 uv;\nattribute float f;\n\nuniform vec3 objectOffset;\nuniform mat3 permutation;\nuniform mat4 model, view, projection;\nuniform float height, zOffset;\nuniform sampler2D colormap;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 lightDirection, eyeDirection, surfaceNormal;\nvarying vec4 vColor;\n\nvoid main() {\n vec3 dataCoordinate = permutation * vec3(uv.xy, height);\n worldCoordinate = objectOffset + dataCoordinate;\n vec4 worldPosition = model * vec4(worldCoordinate, 1.0);\n\n vec4 clipPosition = projection * view * worldPosition;\n clipPosition.z += zOffset;\n\n gl_Position = clipPosition;\n value = f + objectOffset.z;\n kill = -1.0;\n planeCoordinate = uv.zw;\n\n vColor = texture2D(colormap, vec2(value, value));\n\n //Don't do lighting for contours\n surfaceNormal = vec3(1,0,0);\n eyeDirection = vec3(0,1,0);\n lightDirection = vec3(0,0,1);\n}\n"]),l=i(["precision highp float;\n#define GLSLIFY 1\n\nbool outOfRange(float a, float b, float p) {\n return ((p > max(a, b)) || \n (p < min(a, b)));\n}\n\nbool outOfRange(vec2 a, vec2 b, vec2 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y));\n}\n\nbool outOfRange(vec3 a, vec3 b, vec3 p) {\n return (outOfRange(a.x, b.x, p.x) ||\n outOfRange(a.y, b.y, p.y) ||\n outOfRange(a.z, b.z, p.z));\n}\n\nbool outOfRange(vec4 a, vec4 b, vec4 p) {\n return outOfRange(a.xyz, b.xyz, p.xyz);\n}\n\nuniform vec2 shape;\nuniform vec3 clipBounds[2];\nuniform float pickId;\n\nvarying float value, kill;\nvarying vec3 worldCoordinate;\nvarying vec2 planeCoordinate;\nvarying vec3 surfaceNormal;\n\nvec2 splitFloat(float v) {\n float vh = 255.0 * v;\n float upper = floor(vh);\n float lower = fract(vh);\n return vec2(upper / 255.0, floor(lower * 16.0) / 16.0);\n}\n\nvoid main() {\n if ((kill > 0.0) ||\n (outOfRange(clipBounds[0], clipBounds[1], worldCoordinate))) discard;\n\n vec2 ux = splitFloat(planeCoordinate.x / shape.x);\n vec2 uy = splitFloat(planeCoordinate.y / shape.y);\n gl_FragColor = vec4(pickId, ux.x, uy.x, ux.y + (uy.y/16.0));\n}\n"]);r.createShader=function(t){var e=n(t,a,o,null,[{name:"uv",type:"vec4"},{name:"f",type:"vec3"},{name:"normal",type:"vec3"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e.attributes.normal.location=2,e},r.createPickShader=function(t){var e=n(t,a,l,null,[{name:"uv",type:"vec4"},{name:"f",type:"vec3"},{name:"normal",type:"vec3"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e.attributes.normal.location=2,e},r.createContourShader=function(t){var e=n(t,s,o,null,[{name:"uv",type:"vec4"},{name:"f",type:"float"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e},r.createPickContourShader=function(t){var e=n(t,s,l,null,[{name:"uv",type:"vec4"},{name:"f",type:"float"}]);return e.attributes.uv.location=0,e.attributes.f.location=1,e}},{"gl-shader":132,glslify:231}],145:[function(t,e,r){"use strict";e.exports=function(t){var e=t.gl,r=y(e),n=b(e),s=x(e),l=_(e),c=i(e),u=a(e,[{buffer:c,size:4,stride:40,offset:0},{buffer:c,size:3,stride:40,offset:16},{buffer:c,size:3,stride:40,offset:28}]),f=i(e),h=a(e,[{buffer:f,size:4,stride:20,offset:0},{buffer:f,size:1,stride:20,offset:16}]),p=i(e),d=a(e,[{buffer:p,size:2,type:e.FLOAT}]),m=o(e,1,256,e.RGBA,e.UNSIGNED_BYTE);m.minFilter=e.LINEAR,m.magFilter=e.LINEAR;var g=new M(e,[0,0],[[0,0,0],[0,0,0]],r,n,c,u,m,s,l,f,h,p,d,[0,0,0]),v={levels:[[],[],[]]};for(var w in t)v[w]=t[w];return v.colormap=v.colormap||"jet",g.update(v),g};var n=t("bit-twiddle"),i=t("gl-buffer"),a=t("gl-vao"),o=t("gl-texture2d"),s=t("typedarray-pool"),l=t("colormap"),c=t("ndarray-ops"),u=t("ndarray-pack"),f=t("ndarray"),h=t("surface-nets"),p=t("gl-mat4/multiply"),d=t("gl-mat4/invert"),m=t("binary-search-bounds"),g=t("ndarray-gradient"),v=t("./lib/shaders"),y=v.createShader,x=v.createContourShader,b=v.createPickShader,_=v.createPickContourShader,w=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],T=[[0,0],[0,1],[1,0],[1,1],[1,0],[0,1]],k=[[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0]];function A(t,e,r,n,i){this.position=t,this.index=e,this.uv=r,this.level=n,this.dataCoordinate=i}!function(){for(var t=0;t<3;++t){var e=k[t],r=(t+2)%3;e[(t+1)%3+0]=1,e[r+3]=1,e[t+6]=1}}();function M(t,e,r,n,i,a,o,l,c,u,h,p,d,m,g){this.gl=t,this.shape=e,this.bounds=r,this.objectOffset=g,this.intensityBounds=[],this._shader=n,this._pickShader=i,this._coordinateBuffer=a,this._vao=o,this._colorMap=l,this._contourShader=c,this._contourPickShader=u,this._contourBuffer=h,this._contourVAO=p,this._contourOffsets=[[],[],[]],this._contourCounts=[[],[],[]],this._vertexCount=0,this._pickResult=new A([0,0,0],[0,0],[0,0],[0,0,0],[0,0,0]),this._dynamicBuffer=d,this._dynamicVAO=m,this._dynamicOffsets=[0,0,0],this._dynamicCounts=[0,0,0],this.contourWidth=[1,1,1],this.contourLevels=[[1],[1],[1]],this.contourTint=[0,0,0],this.contourColor=[[.5,.5,.5,1],[.5,.5,.5,1],[.5,.5,.5,1]],this.showContour=!0,this.showSurface=!0,this.enableHighlight=[!0,!0,!0],this.highlightColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.highlightTint=[1,1,1],this.highlightLevel=[-1,-1,-1],this.enableDynamic=[!0,!0,!0],this.dynamicLevel=[NaN,NaN,NaN],this.dynamicColor=[[0,0,0,1],[0,0,0,1],[0,0,0,1]],this.dynamicTint=[1,1,1],this.dynamicWidth=[1,1,1],this.axesBounds=[[1/0,1/0,1/0],[-1/0,-1/0,-1/0]],this.surfaceProject=[!1,!1,!1],this.contourProject=[[!1,!1,!1],[!1,!1,!1],[!1,!1,!1]],this.colorBounds=[!1,!1],this._field=[f(s.mallocFloat(1024),[0,0]),f(s.mallocFloat(1024),[0,0]),f(s.mallocFloat(1024),[0,0])],this.pickId=1,this.clipBounds=[[-1/0,-1/0,-1/0],[1/0,1/0,1/0]],this.snapToData=!1,this.pixelRatio=1,this.opacity=1,this.lightPosition=[10,1e4,0],this.ambientLight=.8,this.diffuseLight=.8,this.specularLight=2,this.roughness=.5,this.fresnel=1.5,this.vertexColor=0,this.dirty=!0}var S=M.prototype;S.genColormap=function(t,e){var r=!1,n=u([l({colormap:t,nshades:256,format:"rgba"}).map((function(t,n){var i=e?function(t,e){if(!e)return 1;if(!e.length)return 1;for(var r=0;rt&&r>0){var n=(e[r][0]-t)/(e[r][0]-e[r-1][0]);return e[r][1]*(1-n)+n*e[r-1][1]}}return 1}(n/255,e):t[3];return i<1&&(r=!0),[t[0],t[1],t[2],255*i]}))]);return c.divseq(n,255),this.hasAlphaScale=r,n},S.isTransparent=function(){return this.opacity<1||this.hasAlphaScale},S.isOpaque=function(){return!this.isTransparent()},S.pickSlots=1,S.setPickBase=function(t){this.pickId=t};var E=[0,0,0],L={showSurface:!1,showContour:!1,projections:[w.slice(),w.slice(),w.slice()],clipBounds:[[[0,0,0],[0,0,0]],[[0,0,0],[0,0,0]],[[0,0,0],[0,0,0]]]};function C(t,e){var r,n,i,a=e.axes&&e.axes.lastCubeProps.axis||E,o=e.showSurface,s=e.showContour;for(r=0;r<3;++r)for(o=o||e.surfaceProject[r],n=0;n<3;++n)s=s||e.contourProject[r][n];for(r=0;r<3;++r){var l=L.projections[r];for(n=0;n<16;++n)l[n]=0;for(n=0;n<4;++n)l[5*n]=1;l[5*r]=0,l[12+r]=e.axesBounds[+(a[r]>0)][r],p(l,t.model,l);var c=L.clipBounds[r];for(i=0;i<2;++i)for(n=0;n<3;++n)c[i][n]=t.clipBounds[i][n];c[0][r]=-1e8,c[1][r]=1e8}return L.showSurface=o,L.showContour=s,L}var P={model:w,view:w,projection:w,inverseModel:w.slice(),lowerBound:[0,0,0],upperBound:[0,0,0],colorMap:0,clipBounds:[[0,0,0],[0,0,0]],height:0,contourTint:0,contourColor:[0,0,0,1],permutation:[1,0,0,0,1,0,0,0,1],zOffset:-1e-4,objectOffset:[0,0,0],kambient:1,kdiffuse:1,kspecular:1,lightPosition:[1e3,1e3,1e3],eyePosition:[0,0,0],roughness:1,fresnel:1,opacity:1,vertexColor:0},I=w.slice(),O=[1,0,0,0,1,0,0,0,1];function z(t,e){t=t||{};var r=this.gl;r.disable(r.CULL_FACE),this._colorMap.bind(0);var n=P;n.model=t.model||w,n.view=t.view||w,n.projection=t.projection||w,n.lowerBound=[this.bounds[0][0],this.bounds[0][1],this.colorBounds[0]||this.bounds[0][2]],n.upperBound=[this.bounds[1][0],this.bounds[1][1],this.colorBounds[1]||this.bounds[1][2]],n.objectOffset=this.objectOffset,n.contourColor=this.contourColor[0],n.inverseModel=d(n.inverseModel,n.model);for(var i=0;i<2;++i)for(var a=n.clipBounds[i],o=0;o<3;++o)a[o]=Math.min(Math.max(this.clipBounds[i][o],-1e8),1e8);n.kambient=this.ambientLight,n.kdiffuse=this.diffuseLight,n.kspecular=this.specularLight,n.roughness=this.roughness,n.fresnel=this.fresnel,n.opacity=this.opacity,n.height=0,n.permutation=O,n.vertexColor=this.vertexColor;var s=I;for(p(s,n.view,n.model),p(s,n.projection,s),d(s,s),i=0;i<3;++i)n.eyePosition[i]=s[12+i]/s[15];var l=s[15];for(i=0;i<3;++i)l+=this.lightPosition[i]*s[4*i+3];for(i=0;i<3;++i){var c=s[12+i];for(o=0;o<3;++o)c+=s[4*o+i]*this.lightPosition[o];n.lightPosition[i]=c/l}var u=C(n,this);if(u.showSurface){for(this._shader.bind(),this._shader.uniforms=n,this._vao.bind(),this.showSurface&&this._vertexCount&&this._vao.draw(r.TRIANGLES,this._vertexCount),i=0;i<3;++i)this.surfaceProject[i]&&this.vertexCount&&(this._shader.uniforms.model=u.projections[i],this._shader.uniforms.clipBounds=u.clipBounds[i],this._vao.draw(r.TRIANGLES,this._vertexCount));this._vao.unbind()}if(u.showContour){var f=this._contourShader;n.kambient=1,n.kdiffuse=0,n.kspecular=0,n.opacity=1,f.bind(),f.uniforms=n;var h=this._contourVAO;for(h.bind(),i=0;i<3;++i)for(f.uniforms.permutation=k[i],r.lineWidth(this.contourWidth[i]*this.pixelRatio),o=0;o>4)/16)/255,i=Math.floor(n),a=n-i,o=e[1]*(t.value[1]+(15&t.value[2])/16)/255,s=Math.floor(o),l=o-s;i+=1,s+=1;var c=r.position;c[0]=c[1]=c[2]=0;for(var u=0;u<2;++u)for(var f=u?a:1-a,h=0;h<2;++h)for(var p=i+u,d=s+h,g=f*(h?l:1-l),v=0;v<3;++v)c[v]+=this._field[v].get(p,d)*g;for(var y=this._pickResult.level,x=0;x<3;++x)if(y[x]=m.le(this.contourLevels[x],c[x]),y[x]<0)this.contourLevels[x].length>0&&(y[x]=0);else if(y[x]Math.abs(_-c[x])&&(y[x]+=1)}for(r.index[0]=a<.5?i:i+1,r.index[1]=l<.5?s:s+1,r.uv[0]=n/e[0],r.uv[1]=o/e[1],v=0;v<3;++v)r.dataCoordinate[v]=this._field[v].get(r.index[0],r.index[1]);return r},S.padField=function(t,e){var r=e.shape.slice(),n=t.shape.slice();c.assign(t.lo(1,1).hi(r[0],r[1]),e),c.assign(t.lo(1).hi(r[0],1),e.hi(r[0],1)),c.assign(t.lo(1,n[1]-1).hi(r[0],1),e.lo(0,r[1]-1).hi(r[0],1)),c.assign(t.lo(0,1).hi(1,r[1]),e.hi(1)),c.assign(t.lo(n[0]-1,1).hi(1,r[1]),e.lo(r[0]-1)),t.set(0,0,e.get(0,0)),t.set(0,n[1]-1,e.get(0,r[1]-1)),t.set(n[0]-1,0,e.get(r[0]-1,0)),t.set(n[0]-1,n[1]-1,e.get(r[0]-1,r[1]-1))},S.update=function(t){t=t||{},this.objectOffset=t.objectOffset||this.objectOffset,this.dirty=!0,"contourWidth"in t&&(this.contourWidth=R(t.contourWidth,Number)),"showContour"in t&&(this.showContour=R(t.showContour,Boolean)),"showSurface"in t&&(this.showSurface=!!t.showSurface),"contourTint"in t&&(this.contourTint=R(t.contourTint,Boolean)),"contourColor"in t&&(this.contourColor=B(t.contourColor)),"contourProject"in t&&(this.contourProject=R(t.contourProject,(function(t){return R(t,Boolean)}))),"surfaceProject"in t&&(this.surfaceProject=t.surfaceProject),"dynamicColor"in t&&(this.dynamicColor=B(t.dynamicColor)),"dynamicTint"in t&&(this.dynamicTint=R(t.dynamicTint,Number)),"dynamicWidth"in t&&(this.dynamicWidth=R(t.dynamicWidth,Number)),"opacity"in t&&(this.opacity=t.opacity),"opacityscale"in t&&(this.opacityscale=t.opacityscale),"colorBounds"in t&&(this.colorBounds=t.colorBounds),"vertexColor"in t&&(this.vertexColor=t.vertexColor?1:0),"colormap"in t&&this._colorMap.setPixels(this.genColormap(t.colormap,this.opacityscale));var e=t.field||t.coords&&t.coords[2]||null,r=!1;if(e||(e=this._field[2].shape[0]||this._field[2].shape[2]?this._field[2].lo(1,1).hi(this._field[2].shape[0]-2,this._field[2].shape[1]-2):this._field[2].hi(0,0)),"field"in t||"coords"in t){var i=(e.shape[0]+2)*(e.shape[1]+2);i>this._field[2].data.length&&(s.freeFloat(this._field[2].data),this._field[2].data=s.mallocFloat(n.nextPow2(i))),this._field[2]=f(this._field[2].data,[e.shape[0]+2,e.shape[1]+2]),this.padField(this._field[2],e),this.shape=e.shape.slice();for(var a=this.shape,o=0;o<2;++o)this._field[2].size>this._field[o].data.length&&(s.freeFloat(this._field[o].data),this._field[o].data=s.mallocFloat(this._field[2].size)),this._field[o]=f(this._field[o].data,[a[0]+2,a[1]+2]);if(t.coords){var l=t.coords;if(!Array.isArray(l)||3!==l.length)throw new Error("gl-surface: invalid coordinates for x/y");for(o=0;o<2;++o){var c=l[o];for(v=0;v<2;++v)if(c.shape[v]!==a[v])throw new Error("gl-surface: coords have incorrect shape");this.padField(this._field[o],c)}}else if(t.ticks){var u=t.ticks;if(!Array.isArray(u)||2!==u.length)throw new Error("gl-surface: invalid ticks");for(o=0;o<2;++o){var p=u[o];if((Array.isArray(p)||p.length)&&(p=f(p)),p.shape[0]!==a[o])throw new Error("gl-surface: invalid tick length");var d=f(p.data,a);d.stride[o]=p.stride[0],d.stride[1^o]=0,this.padField(this._field[o],d)}}else{for(o=0;o<2;++o){var m=[0,0];m[o]=1,this._field[o]=f(this._field[o].data,[a[0]+2,a[1]+2],m,0)}this._field[0].set(0,0,0);for(var v=0;v0){for(var xt=0;xt<5;++xt)Q.pop();U-=1}continue t}Q.push(nt[0],nt[1],ot[0],ot[1],nt[2]),U+=1}}rt.push(U)}this._contourOffsets[$]=et,this._contourCounts[$]=rt}var bt=s.mallocFloat(Q.length);for(o=0;oi||r<0||r>i)throw new Error("gl-texture2d: Invalid texture size");return t._shape=[e,r],t.bind(),n.texImage2D(n.TEXTURE_2D,0,t.format,e,r,0,t.format,t.type,null),t._mipLevels=[0],t}function p(t,e,r,n,i,a){this.gl=t,this.handle=e,this.format=i,this.type=a,this._shape=[r,n],this._mipLevels=[0],this._magFilter=t.NEAREST,this._minFilter=t.NEAREST,this._wrapS=t.CLAMP_TO_EDGE,this._wrapT=t.CLAMP_TO_EDGE,this._anisoSamples=1;var o=this,s=[this._wrapS,this._wrapT];Object.defineProperties(s,[{get:function(){return o._wrapS},set:function(t){return o.wrapS=t}},{get:function(){return o._wrapT},set:function(t){return o.wrapT=t}}]),this._wrapVector=s;var l=[this._shape[0],this._shape[1]];Object.defineProperties(l,[{get:function(){return o._shape[0]},set:function(t){return o.width=t}},{get:function(){return o._shape[1]},set:function(t){return o.height=t}}]),this._shapeVector=l}var d=p.prototype;function m(t,e){return 3===t.length?1===e[2]&&e[1]===t[0]*t[2]&&e[0]===t[2]:1===e[0]&&e[1]===t[0]}function g(t){var e=t.createTexture();return t.bindTexture(t.TEXTURE_2D,e),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),e}function v(t,e,r,n,i){var a=t.getParameter(t.MAX_TEXTURE_SIZE);if(e<0||e>a||r<0||r>a)throw new Error("gl-texture2d: Invalid texture shape");if(i===t.FLOAT&&!t.getExtension("OES_texture_float"))throw new Error("gl-texture2d: Floating point textures not supported on this platform");var o=g(t);return t.texImage2D(t.TEXTURE_2D,0,n,e,r,0,n,i,null),new p(t,o,e,r,n,i)}function y(t,e,r,n,i,a){var o=g(t);return t.texImage2D(t.TEXTURE_2D,0,i,i,a,e),new p(t,o,r,n,i,a)}function x(t,e){var r=e.dtype,o=e.shape.slice(),s=t.getParameter(t.MAX_TEXTURE_SIZE);if(o[0]<0||o[0]>s||o[1]<0||o[1]>s)throw new Error("gl-texture2d: Invalid texture size");var l=m(o,e.stride.slice()),c=0;"float32"===r?c=t.FLOAT:"float64"===r?(c=t.FLOAT,l=!1,r="float32"):"uint8"===r?c=t.UNSIGNED_BYTE:(c=t.UNSIGNED_BYTE,l=!1,r="uint8");var u,h,d=0;if(2===o.length)d=t.LUMINANCE,o=[o[0],o[1],1],e=n(e.data,o,[e.stride[0],e.stride[1],1],e.offset);else{if(3!==o.length)throw new Error("gl-texture2d: Invalid shape for texture");if(1===o[2])d=t.ALPHA;else if(2===o[2])d=t.LUMINANCE_ALPHA;else if(3===o[2])d=t.RGB;else{if(4!==o[2])throw new Error("gl-texture2d: Invalid shape for pixel coords");d=t.RGBA}}c!==t.FLOAT||t.getExtension("OES_texture_float")||(c=t.UNSIGNED_BYTE,l=!1);var v=e.size;if(l)u=0===e.offset&&e.data.length===v?e.data:e.data.subarray(e.offset,e.offset+v);else{var y=[o[2],o[2]*o[0],1];h=a.malloc(v,r);var x=n(h,o,y,0);"float32"!==r&&"float64"!==r||c!==t.UNSIGNED_BYTE?i.assign(x,e):f(x,e),u=h.subarray(0,v)}var b=g(t);return t.texImage2D(t.TEXTURE_2D,0,d,o[0],o[1],0,d,c,u),l||a.free(h),new p(t,b,o[0],o[1],d,c)}Object.defineProperties(d,{minFilter:{get:function(){return this._minFilter},set:function(t){this.bind();var e=this.gl;if(this.type===e.FLOAT&&o.indexOf(t)>=0&&(e.getExtension("OES_texture_float_linear")||(t=e.NEAREST)),s.indexOf(t)<0)throw new Error("gl-texture2d: Unknown filter mode "+t);return e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,t),this._minFilter=t}},magFilter:{get:function(){return this._magFilter},set:function(t){this.bind();var e=this.gl;if(this.type===e.FLOAT&&o.indexOf(t)>=0&&(e.getExtension("OES_texture_float_linear")||(t=e.NEAREST)),s.indexOf(t)<0)throw new Error("gl-texture2d: Unknown filter mode "+t);return e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,t),this._magFilter=t}},mipSamples:{get:function(){return this._anisoSamples},set:function(t){var e=this._anisoSamples;if(this._anisoSamples=0|Math.max(t,1),e!==this._anisoSamples){var r=this.gl.getExtension("EXT_texture_filter_anisotropic");r&&this.gl.texParameterf(this.gl.TEXTURE_2D,r.TEXTURE_MAX_ANISOTROPY_EXT,this._anisoSamples)}return this._anisoSamples}},wrapS:{get:function(){return this._wrapS},set:function(t){if(this.bind(),l.indexOf(t)<0)throw new Error("gl-texture2d: Unknown wrap mode "+t);return this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_S,t),this._wrapS=t}},wrapT:{get:function(){return this._wrapT},set:function(t){if(this.bind(),l.indexOf(t)<0)throw new Error("gl-texture2d: Unknown wrap mode "+t);return this.gl.texParameteri(this.gl.TEXTURE_2D,this.gl.TEXTURE_WRAP_T,t),this._wrapT=t}},wrap:{get:function(){return this._wrapVector},set:function(t){if(Array.isArray(t)||(t=[t,t]),2!==t.length)throw new Error("gl-texture2d: Must specify wrap mode for rows and columns");for(var e=0;e<2;++e)if(l.indexOf(t[e])<0)throw new Error("gl-texture2d: Unknown wrap mode "+t);this._wrapS=t[0],this._wrapT=t[1];var r=this.gl;return this.bind(),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_S,this._wrapS),r.texParameteri(r.TEXTURE_2D,r.TEXTURE_WRAP_T,this._wrapT),t}},shape:{get:function(){return this._shapeVector},set:function(t){if(Array.isArray(t)){if(2!==t.length)throw new Error("gl-texture2d: Invalid texture shape")}else t=[0|t,0|t];return h(this,0|t[0],0|t[1]),[0|t[0],0|t[1]]}},width:{get:function(){return this._shape[0]},set:function(t){return h(this,t|=0,this._shape[1]),t}},height:{get:function(){return this._shape[1]},set:function(t){return t|=0,h(this,this._shape[0],t),t}}}),d.bind=function(t){var e=this.gl;return void 0!==t&&e.activeTexture(e.TEXTURE0+(0|t)),e.bindTexture(e.TEXTURE_2D,this.handle),void 0!==t?0|t:e.getParameter(e.ACTIVE_TEXTURE)-e.TEXTURE0},d.dispose=function(){this.gl.deleteTexture(this.handle)},d.generateMipmap=function(){this.bind(),this.gl.generateMipmap(this.gl.TEXTURE_2D);for(var t=Math.min(this._shape[0],this._shape[1]),e=0;t>0;++e,t>>>=1)this._mipLevels.indexOf(e)<0&&this._mipLevels.push(e)},d.setPixels=function(t,e,r,o){var s=this.gl;this.bind(),Array.isArray(e)?(o=r,r=0|e[1],e=0|e[0]):(e=e||0,r=r||0),o=o||0;var l=u(t)?t:t.raw;if(l){this._mipLevels.indexOf(o)<0?(s.texImage2D(s.TEXTURE_2D,0,this.format,this.format,this.type,l),this._mipLevels.push(o)):s.texSubImage2D(s.TEXTURE_2D,o,e,r,this.format,this.type,l)}else{if(!(t.shape&&t.stride&&t.data))throw new Error("gl-texture2d: Unsupported data type");if(t.shape.length<2||e+t.shape[1]>this._shape[1]>>>o||r+t.shape[0]>this._shape[0]>>>o||e<0||r<0)throw new Error("gl-texture2d: Texture dimensions are out of bounds");!function(t,e,r,o,s,l,c,u){var h=u.dtype,p=u.shape.slice();if(p.length<2||p.length>3)throw new Error("gl-texture2d: Invalid ndarray, must be 2d or 3d");var d=0,g=0,v=m(p,u.stride.slice());"float32"===h?d=t.FLOAT:"float64"===h?(d=t.FLOAT,v=!1,h="float32"):"uint8"===h?d=t.UNSIGNED_BYTE:(d=t.UNSIGNED_BYTE,v=!1,h="uint8");if(2===p.length)g=t.LUMINANCE,p=[p[0],p[1],1],u=n(u.data,p,[u.stride[0],u.stride[1],1],u.offset);else{if(3!==p.length)throw new Error("gl-texture2d: Invalid shape for texture");if(1===p[2])g=t.ALPHA;else if(2===p[2])g=t.LUMINANCE_ALPHA;else if(3===p[2])g=t.RGB;else{if(4!==p[2])throw new Error("gl-texture2d: Invalid shape for pixel coords");g=t.RGBA}p[2]}g!==t.LUMINANCE&&g!==t.ALPHA||s!==t.LUMINANCE&&s!==t.ALPHA||(g=s);if(g!==s)throw new Error("gl-texture2d: Incompatible texture format for setPixels");var y=u.size,x=c.indexOf(o)<0;x&&c.push(o);if(d===l&&v)0===u.offset&&u.data.length===y?x?t.texImage2D(t.TEXTURE_2D,o,s,p[0],p[1],0,s,l,u.data):t.texSubImage2D(t.TEXTURE_2D,o,e,r,p[0],p[1],s,l,u.data):x?t.texImage2D(t.TEXTURE_2D,o,s,p[0],p[1],0,s,l,u.data.subarray(u.offset,u.offset+y)):t.texSubImage2D(t.TEXTURE_2D,o,e,r,p[0],p[1],s,l,u.data.subarray(u.offset,u.offset+y));else{var b;b=l===t.FLOAT?a.mallocFloat32(y):a.mallocUint8(y);var _=n(b,p,[p[2],p[2]*p[0],1]);d===t.FLOAT&&l===t.UNSIGNED_BYTE?f(_,u):i.assign(_,u),x?t.texImage2D(t.TEXTURE_2D,o,s,p[0],p[1],0,s,l,b.subarray(0,y)):t.texSubImage2D(t.TEXTURE_2D,o,e,r,p[0],p[1],s,l,b.subarray(0,y)),l===t.FLOAT?a.freeFloat32(b):a.freeUint8(b)}}(s,e,r,o,this.format,this.type,this._mipLevels,t)}}},{ndarray:259,"ndarray-ops":254,"typedarray-pool":308}],147:[function(t,e,r){"use strict";e.exports=function(t,e,r){e?e.bind():t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null);var n=0|t.getParameter(t.MAX_VERTEX_ATTRIBS);if(r){if(r.length>n)throw new Error("gl-vao: Too many vertex attributes");for(var i=0;i1?0:Math.acos(s)};var n=t("./fromValues"),i=t("./normalize"),a=t("./dot")},{"./dot":162,"./fromValues":168,"./normalize":179}],153:[function(t,e,r){e.exports=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2]),t}},{}],154:[function(t,e,r){e.exports=function(t){var e=new Float32Array(3);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e}},{}],155:[function(t,e,r){e.exports=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t}},{}],156:[function(t,e,r){e.exports=function(){var t=new Float32Array(3);return t[0]=0,t[1]=0,t[2]=0,t}},{}],157:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],l=r[2];return t[0]=i*l-a*s,t[1]=a*o-n*l,t[2]=n*s-i*o,t}},{}],158:[function(t,e,r){e.exports=t("./distance")},{"./distance":159}],159:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2];return Math.sqrt(r*r+n*n+i*i)}},{}],160:[function(t,e,r){e.exports=t("./divide")},{"./divide":161}],161:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]/r[0],t[1]=e[1]/r[1],t[2]=e[2]/r[2],t}},{}],162:[function(t,e,r){e.exports=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}},{}],163:[function(t,e,r){e.exports=1e-6},{}],164:[function(t,e,r){e.exports=function(t,e){var r=t[0],i=t[1],a=t[2],o=e[0],s=e[1],l=e[2];return Math.abs(r-o)<=n*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(i-s)<=n*Math.max(1,Math.abs(i),Math.abs(s))&&Math.abs(a-l)<=n*Math.max(1,Math.abs(a),Math.abs(l))};var n=t("./epsilon")},{"./epsilon":163}],165:[function(t,e,r){e.exports=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]}},{}],166:[function(t,e,r){e.exports=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2]),t}},{}],167:[function(t,e,r){e.exports=function(t,e,r,i,a,o){var s,l;e||(e=3);r||(r=0);l=i?Math.min(i*e+r,t.length):t.length;for(s=r;s0&&(a=1/Math.sqrt(a),t[0]=e[0]*a,t[1]=e[1]*a,t[2]=e[2]*a);return t}},{}],180:[function(t,e,r){e.exports=function(t,e){e=e||1;var r=2*Math.random()*Math.PI,n=2*Math.random()-1,i=Math.sqrt(1-n*n)*e;return t[0]=Math.cos(r)*i,t[1]=Math.sin(r)*i,t[2]=n*e,t}},{}],181:[function(t,e,r){e.exports=function(t,e,r,n){var i=r[1],a=r[2],o=e[1]-i,s=e[2]-a,l=Math.sin(n),c=Math.cos(n);return t[0]=e[0],t[1]=i+o*c-s*l,t[2]=a+o*l+s*c,t}},{}],182:[function(t,e,r){e.exports=function(t,e,r,n){var i=r[0],a=r[2],o=e[0]-i,s=e[2]-a,l=Math.sin(n),c=Math.cos(n);return t[0]=i+s*l+o*c,t[1]=e[1],t[2]=a+s*c-o*l,t}},{}],183:[function(t,e,r){e.exports=function(t,e,r,n){var i=r[0],a=r[1],o=e[0]-i,s=e[1]-a,l=Math.sin(n),c=Math.cos(n);return t[0]=i+o*c-s*l,t[1]=a+o*l+s*c,t[2]=e[2],t}},{}],184:[function(t,e,r){e.exports=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t[2]=Math.round(e[2]),t}},{}],185:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]*r,t[1]=e[1]*r,t[2]=e[2]*r,t}},{}],186:[function(t,e,r){e.exports=function(t,e,r,n){return t[0]=e[0]+r[0]*n,t[1]=e[1]+r[1]*n,t[2]=e[2]+r[2]*n,t}},{}],187:[function(t,e,r){e.exports=function(t,e,r,n){return t[0]=e,t[1]=r,t[2]=n,t}},{}],188:[function(t,e,r){e.exports=t("./squaredDistance")},{"./squaredDistance":190}],189:[function(t,e,r){e.exports=t("./squaredLength")},{"./squaredLength":191}],190:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2];return r*r+n*n+i*i}},{}],191:[function(t,e,r){e.exports=function(t){var e=t[0],r=t[1],n=t[2];return e*e+r*r+n*n}},{}],192:[function(t,e,r){e.exports=t("./subtract")},{"./subtract":193}],193:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]-r[0],t[1]=e[1]-r[1],t[2]=e[2]-r[2],t}},{}],194:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2];return t[0]=n*r[0]+i*r[3]+a*r[6],t[1]=n*r[1]+i*r[4]+a*r[7],t[2]=n*r[2]+i*r[5]+a*r[8],t}},{}],195:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[3]*n+r[7]*i+r[11]*a+r[15];return o=o||1,t[0]=(r[0]*n+r[4]*i+r[8]*a+r[12])/o,t[1]=(r[1]*n+r[5]*i+r[9]*a+r[13])/o,t[2]=(r[2]*n+r[6]*i+r[10]*a+r[14])/o,t}},{}],196:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],l=r[2],c=r[3],u=c*n+s*a-l*i,f=c*i+l*n-o*a,h=c*a+o*i-s*n,p=-o*n-s*i-l*a;return t[0]=u*c+p*-o+f*-l-h*-s,t[1]=f*c+p*-s+h*-o-u*-l,t[2]=h*c+p*-l+u*-s-f*-o,t}},{}],197:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]+r[0],t[1]=e[1]+r[1],t[2]=e[2]+r[2],t[3]=e[3]+r[3],t}},{}],198:[function(t,e,r){e.exports=function(t){var e=new Float32Array(4);return e[0]=t[0],e[1]=t[1],e[2]=t[2],e[3]=t[3],e}},{}],199:[function(t,e,r){e.exports=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t}},{}],200:[function(t,e,r){e.exports=function(){var t=new Float32Array(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t}},{}],201:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2],a=e[3]-t[3];return Math.sqrt(r*r+n*n+i*i+a*a)}},{}],202:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]/r[0],t[1]=e[1]/r[1],t[2]=e[2]/r[2],t[3]=e[3]/r[3],t}},{}],203:[function(t,e,r){e.exports=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]+t[3]*e[3]}},{}],204:[function(t,e,r){e.exports=function(t,e,r,n){var i=new Float32Array(4);return i[0]=t,i[1]=e,i[2]=r,i[3]=n,i}},{}],205:[function(t,e,r){e.exports={create:t("./create"),clone:t("./clone"),fromValues:t("./fromValues"),copy:t("./copy"),set:t("./set"),add:t("./add"),subtract:t("./subtract"),multiply:t("./multiply"),divide:t("./divide"),min:t("./min"),max:t("./max"),scale:t("./scale"),scaleAndAdd:t("./scaleAndAdd"),distance:t("./distance"),squaredDistance:t("./squaredDistance"),length:t("./length"),squaredLength:t("./squaredLength"),negate:t("./negate"),inverse:t("./inverse"),normalize:t("./normalize"),dot:t("./dot"),lerp:t("./lerp"),random:t("./random"),transformMat4:t("./transformMat4"),transformQuat:t("./transformQuat")}},{"./add":197,"./clone":198,"./copy":199,"./create":200,"./distance":201,"./divide":202,"./dot":203,"./fromValues":204,"./inverse":206,"./length":207,"./lerp":208,"./max":209,"./min":210,"./multiply":211,"./negate":212,"./normalize":213,"./random":214,"./scale":215,"./scaleAndAdd":216,"./set":217,"./squaredDistance":218,"./squaredLength":219,"./subtract":220,"./transformMat4":221,"./transformQuat":222}],206:[function(t,e,r){e.exports=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t[2]=1/e[2],t[3]=1/e[3],t}},{}],207:[function(t,e,r){e.exports=function(t){var e=t[0],r=t[1],n=t[2],i=t[3];return Math.sqrt(e*e+r*r+n*n+i*i)}},{}],208:[function(t,e,r){e.exports=function(t,e,r,n){var i=e[0],a=e[1],o=e[2],s=e[3];return t[0]=i+n*(r[0]-i),t[1]=a+n*(r[1]-a),t[2]=o+n*(r[2]-o),t[3]=s+n*(r[3]-s),t}},{}],209:[function(t,e,r){e.exports=function(t,e,r){return t[0]=Math.max(e[0],r[0]),t[1]=Math.max(e[1],r[1]),t[2]=Math.max(e[2],r[2]),t[3]=Math.max(e[3],r[3]),t}},{}],210:[function(t,e,r){e.exports=function(t,e,r){return t[0]=Math.min(e[0],r[0]),t[1]=Math.min(e[1],r[1]),t[2]=Math.min(e[2],r[2]),t[3]=Math.min(e[3],r[3]),t}},{}],211:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]*r[0],t[1]=e[1]*r[1],t[2]=e[2]*r[2],t[3]=e[3]*r[3],t}},{}],212:[function(t,e,r){e.exports=function(t,e){return t[0]=-e[0],t[1]=-e[1],t[2]=-e[2],t[3]=-e[3],t}},{}],213:[function(t,e,r){e.exports=function(t,e){var r=e[0],n=e[1],i=e[2],a=e[3],o=r*r+n*n+i*i+a*a;o>0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=n*o,t[2]=i*o,t[3]=a*o);return t}},{}],214:[function(t,e,r){var n=t("./normalize"),i=t("./scale");e.exports=function(t,e){return e=e||1,t[0]=Math.random(),t[1]=Math.random(),t[2]=Math.random(),t[3]=Math.random(),n(t,t),i(t,t,e),t}},{"./normalize":213,"./scale":215}],215:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]*r,t[1]=e[1]*r,t[2]=e[2]*r,t[3]=e[3]*r,t}},{}],216:[function(t,e,r){e.exports=function(t,e,r,n){return t[0]=e[0]+r[0]*n,t[1]=e[1]+r[1]*n,t[2]=e[2]+r[2]*n,t[3]=e[3]+r[3]*n,t}},{}],217:[function(t,e,r){e.exports=function(t,e,r,n,i){return t[0]=e,t[1]=r,t[2]=n,t[3]=i,t}},{}],218:[function(t,e,r){e.exports=function(t,e){var r=e[0]-t[0],n=e[1]-t[1],i=e[2]-t[2],a=e[3]-t[3];return r*r+n*n+i*i+a*a}},{}],219:[function(t,e,r){e.exports=function(t){var e=t[0],r=t[1],n=t[2],i=t[3];return e*e+r*r+n*n+i*i}},{}],220:[function(t,e,r){e.exports=function(t,e,r){return t[0]=e[0]-r[0],t[1]=e[1]-r[1],t[2]=e[2]-r[2],t[3]=e[3]-r[3],t}},{}],221:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=e[3];return t[0]=r[0]*n+r[4]*i+r[8]*a+r[12]*o,t[1]=r[1]*n+r[5]*i+r[9]*a+r[13]*o,t[2]=r[2]*n+r[6]*i+r[10]*a+r[14]*o,t[3]=r[3]*n+r[7]*i+r[11]*a+r[15]*o,t}},{}],222:[function(t,e,r){e.exports=function(t,e,r){var n=e[0],i=e[1],a=e[2],o=r[0],s=r[1],l=r[2],c=r[3],u=c*n+s*a-l*i,f=c*i+l*n-o*a,h=c*a+o*i-s*n,p=-o*n-s*i-l*a;return t[0]=u*c+p*-o+f*-l-h*-s,t[1]=f*c+p*-s+h*-o-u*-l,t[2]=h*c+p*-l+u*-s-f*-o,t[3]=e[3],t}},{}],223:[function(t,e,r){var n=t("glsl-tokenizer"),i=t("atob-lite");e.exports=function(t){for(var e=Array.isArray(t)?t:n(t),r=0;r0)continue;r=t.slice(0,1).join("")}return A(r),v+=r.length,(p=p.slice(r.length)).length}}function I(){return/[^a-fA-F0-9]/.test(e)?(A(p.join("")),h=999,u):(p.push(e),r=e,u+1)}function O(){return"."===e||/[eE]/.test(e)?(p.push(e),h=5,r=e,u+1):"x"===e&&1===p.length&&"0"===p[0]?(h=11,p.push(e),r=e,u+1):/[^\d]/.test(e)?(A(p.join("")),h=999,u):(p.push(e),r=e,u+1)}function z(){return"f"===e&&(p.push(e),r=e,u+=1),/[eE]/.test(e)?(p.push(e),r=e,u+1):("-"!==e&&"+"!==e||!/[eE]/.test(r))&&/[^\d]/.test(e)?(A(p.join("")),h=999,u):(p.push(e),r=e,u+1)}function D(){if(/[^\d\w_]/.test(e)){var t=p.join("");return h=k[t]?8:T[t]?7:6,A(p.join("")),h=999,u}return p.push(e),r=e,u+1}};var n=t("./lib/literals"),i=t("./lib/operators"),a=t("./lib/builtins"),o=t("./lib/literals-300es"),s=t("./lib/builtins-300es"),l=["block-comment","line-comment","preprocessor","operator","integer","float","ident","builtin","keyword","whitespace","eof","integer"]},{"./lib/builtins":226,"./lib/builtins-300es":225,"./lib/literals":228,"./lib/literals-300es":227,"./lib/operators":229}],225:[function(t,e,r){var n=t("./builtins");n=n.slice().filter((function(t){return!/^(gl\_|texture)/.test(t)})),e.exports=n.concat(["gl_VertexID","gl_InstanceID","gl_Position","gl_PointSize","gl_FragCoord","gl_FrontFacing","gl_FragDepth","gl_PointCoord","gl_MaxVertexAttribs","gl_MaxVertexUniformVectors","gl_MaxVertexOutputVectors","gl_MaxFragmentInputVectors","gl_MaxVertexTextureImageUnits","gl_MaxCombinedTextureImageUnits","gl_MaxTextureImageUnits","gl_MaxFragmentUniformVectors","gl_MaxDrawBuffers","gl_MinProgramTexelOffset","gl_MaxProgramTexelOffset","gl_DepthRangeParameters","gl_DepthRange","trunc","round","roundEven","isnan","isinf","floatBitsToInt","floatBitsToUint","intBitsToFloat","uintBitsToFloat","packSnorm2x16","unpackSnorm2x16","packUnorm2x16","unpackUnorm2x16","packHalf2x16","unpackHalf2x16","outerProduct","transpose","determinant","inverse","texture","textureSize","textureProj","textureLod","textureOffset","texelFetch","texelFetchOffset","textureProjOffset","textureLodOffset","textureProjLod","textureProjLodOffset","textureGrad","textureGradOffset","textureProjGrad","textureProjGradOffset"])},{"./builtins":226}],226:[function(t,e,r){e.exports=["abs","acos","all","any","asin","atan","ceil","clamp","cos","cross","dFdx","dFdy","degrees","distance","dot","equal","exp","exp2","faceforward","floor","fract","gl_BackColor","gl_BackLightModelProduct","gl_BackLightProduct","gl_BackMaterial","gl_BackSecondaryColor","gl_ClipPlane","gl_ClipVertex","gl_Color","gl_DepthRange","gl_DepthRangeParameters","gl_EyePlaneQ","gl_EyePlaneR","gl_EyePlaneS","gl_EyePlaneT","gl_Fog","gl_FogCoord","gl_FogFragCoord","gl_FogParameters","gl_FragColor","gl_FragCoord","gl_FragData","gl_FragDepth","gl_FragDepthEXT","gl_FrontColor","gl_FrontFacing","gl_FrontLightModelProduct","gl_FrontLightProduct","gl_FrontMaterial","gl_FrontSecondaryColor","gl_LightModel","gl_LightModelParameters","gl_LightModelProducts","gl_LightProducts","gl_LightSource","gl_LightSourceParameters","gl_MaterialParameters","gl_MaxClipPlanes","gl_MaxCombinedTextureImageUnits","gl_MaxDrawBuffers","gl_MaxFragmentUniformComponents","gl_MaxLights","gl_MaxTextureCoords","gl_MaxTextureImageUnits","gl_MaxTextureUnits","gl_MaxVaryingFloats","gl_MaxVertexAttribs","gl_MaxVertexTextureImageUnits","gl_MaxVertexUniformComponents","gl_ModelViewMatrix","gl_ModelViewMatrixInverse","gl_ModelViewMatrixInverseTranspose","gl_ModelViewMatrixTranspose","gl_ModelViewProjectionMatrix","gl_ModelViewProjectionMatrixInverse","gl_ModelViewProjectionMatrixInverseTranspose","gl_ModelViewProjectionMatrixTranspose","gl_MultiTexCoord0","gl_MultiTexCoord1","gl_MultiTexCoord2","gl_MultiTexCoord3","gl_MultiTexCoord4","gl_MultiTexCoord5","gl_MultiTexCoord6","gl_MultiTexCoord7","gl_Normal","gl_NormalMatrix","gl_NormalScale","gl_ObjectPlaneQ","gl_ObjectPlaneR","gl_ObjectPlaneS","gl_ObjectPlaneT","gl_Point","gl_PointCoord","gl_PointParameters","gl_PointSize","gl_Position","gl_ProjectionMatrix","gl_ProjectionMatrixInverse","gl_ProjectionMatrixInverseTranspose","gl_ProjectionMatrixTranspose","gl_SecondaryColor","gl_TexCoord","gl_TextureEnvColor","gl_TextureMatrix","gl_TextureMatrixInverse","gl_TextureMatrixInverseTranspose","gl_TextureMatrixTranspose","gl_Vertex","greaterThan","greaterThanEqual","inversesqrt","length","lessThan","lessThanEqual","log","log2","matrixCompMult","max","min","mix","mod","normalize","not","notEqual","pow","radians","reflect","refract","sign","sin","smoothstep","sqrt","step","tan","texture2D","texture2DLod","texture2DProj","texture2DProjLod","textureCube","textureCubeLod","texture2DLodEXT","texture2DProjLodEXT","textureCubeLodEXT","texture2DGradEXT","texture2DProjGradEXT","textureCubeGradEXT"]},{}],227:[function(t,e,r){var n=t("./literals");e.exports=n.slice().concat(["layout","centroid","smooth","case","mat2x2","mat2x3","mat2x4","mat3x2","mat3x3","mat3x4","mat4x2","mat4x3","mat4x4","uvec2","uvec3","uvec4","samplerCubeShadow","sampler2DArray","sampler2DArrayShadow","isampler2D","isampler3D","isamplerCube","isampler2DArray","usampler2D","usampler3D","usamplerCube","usampler2DArray","coherent","restrict","readonly","writeonly","resource","atomic_uint","noperspective","patch","sample","subroutine","common","partition","active","filter","image1D","image2D","image3D","imageCube","iimage1D","iimage2D","iimage3D","iimageCube","uimage1D","uimage2D","uimage3D","uimageCube","image1DArray","image2DArray","iimage1DArray","iimage2DArray","uimage1DArray","uimage2DArray","image1DShadow","image2DShadow","image1DArrayShadow","image2DArrayShadow","imageBuffer","iimageBuffer","uimageBuffer","sampler1DArray","sampler1DArrayShadow","isampler1D","isampler1DArray","usampler1D","usampler1DArray","isampler2DRect","usampler2DRect","samplerBuffer","isamplerBuffer","usamplerBuffer","sampler2DMS","isampler2DMS","usampler2DMS","sampler2DMSArray","isampler2DMSArray","usampler2DMSArray"])},{"./literals":228}],228:[function(t,e,r){e.exports=["precision","highp","mediump","lowp","attribute","const","uniform","varying","break","continue","do","for","while","if","else","in","out","inout","float","int","uint","void","bool","true","false","discard","return","mat2","mat3","mat4","vec2","vec3","vec4","ivec2","ivec3","ivec4","bvec2","bvec3","bvec4","sampler1D","sampler2D","sampler3D","samplerCube","sampler1DShadow","sampler2DShadow","struct","asm","class","union","enum","typedef","template","this","packed","goto","switch","default","inline","noinline","volatile","public","static","extern","external","interface","long","short","double","half","fixed","unsigned","input","output","hvec2","hvec3","hvec4","dvec2","dvec3","dvec4","fvec2","fvec3","fvec4","sampler2DRect","sampler3DRect","sampler2DRectShadow","sizeof","cast","namespace","using"]},{}],229:[function(t,e,r){e.exports=["<<=",">>=","++","--","<<",">>","<=",">=","==","!=","&&","||","+=","-=","*=","/=","%=","&=","^^","^=","|=","(",")","[","]",".","!","~","*","/","%","+","-","<",">","&","^","|","?",":","=",",",";","{","}"]},{}],230:[function(t,e,r){var n=t("./index");e.exports=function(t,e){var r=n(e),i=[];return i=(i=i.concat(r(t))).concat(r(null))}},{"./index":224}],231:[function(t,e,r){e.exports=function(t){"string"==typeof t&&(t=[t]);for(var e=[].slice.call(arguments,1),r=[],n=0;n0;)for(var s=(t=o.pop()).adjacent,l=0;l<=r;++l){var c=s[l];if(c.boundary&&!(c.lastVisited<=-n)){for(var u=c.vertices,f=0;f<=r;++f){var h=u[f];i[f]=h<0?e:a[h]}var p=this.orient();if(p>0)return c;c.lastVisited=-n,0===p&&o.push(c)}}return null},u.walk=function(t,e){var r=this.vertices.length-1,n=this.dimension,i=this.vertices,a=this.tuple,o=e?this.interior.length*Math.random()|0:this.interior.length-1,s=this.interior[o];t:for(;!s.boundary;){for(var l=s.vertices,c=s.adjacent,u=0;u<=n;++u)a[u]=i[l[u]];s.lastVisited=r;for(u=0;u<=n;++u){var f=c[u];if(!(f.lastVisited>=r)){var h=a[u];a[u]=t;var p=this.orient();if(a[u]=h,p<0){s=f;continue t}f.boundary?f.lastVisited=-r:f.lastVisited=r}}return}return s},u.addPeaks=function(t,e){var r=this.vertices.length-1,n=this.dimension,i=this.vertices,l=this.tuple,c=this.interior,u=this.simplices,f=[e];e.lastVisited=r,e.vertices[e.vertices.indexOf(-1)]=r,e.boundary=!1,c.push(e);for(var h=[];f.length>0;){var p=(e=f.pop()).vertices,d=e.adjacent,m=p.indexOf(r);if(!(m<0))for(var g=0;g<=n;++g)if(g!==m){var v=d[g];if(v.boundary&&!(v.lastVisited>=r)){var y=v.vertices;if(v.lastVisited!==-r){for(var x=0,b=0;b<=n;++b)y[b]<0?(x=b,l[b]=t):l[b]=i[y[b]];if(this.orient()>0){y[x]=r,v.boundary=!1,c.push(v),f.push(v),v.lastVisited=r;continue}v.lastVisited=-r}var _=v.adjacent,w=p.slice(),T=d.slice(),k=new a(w,T,!0);u.push(k);var A=_.indexOf(e);if(!(A<0)){_[A]=k,T[m]=v,w[g]=-1,T[g]=e,d[g]=k,k.flip();for(b=0;b<=n;++b){var M=w[b];if(!(M<0||M===r)){for(var S=new Array(n-1),E=0,L=0;L<=n;++L){var C=w[L];C<0||L===b||(S[E++]=C)}h.push(new o(S,k,b))}}}}}}h.sort(s);for(g=0;g+1=0?o[l++]=s[u]:c=1&u;if(c===(1&t)){var f=o[0];o[0]=o[1],o[1]=f}e.push(o)}}return e}},{"robust-orientation":284,"simplicial-complex":293}],234:[function(t,e,r){"use strict";var n=t("binary-search-bounds");function i(t,e,r,n,i){this.mid=t,this.left=e,this.right=r,this.leftPoints=n,this.rightPoints=i,this.count=(e?e.count:0)+(r?r.count:0)+n.length}e.exports=function(t){if(!t||0===t.length)return new v(null);return new v(g(t))};var a=i.prototype;function o(t,e){t.mid=e.mid,t.left=e.left,t.right=e.right,t.leftPoints=e.leftPoints,t.rightPoints=e.rightPoints,t.count=e.count}function s(t,e){var r=g(e);t.mid=r.mid,t.left=r.left,t.right=r.right,t.leftPoints=r.leftPoints,t.rightPoints=r.rightPoints,t.count=r.count}function l(t,e){var r=t.intervals([]);r.push(e),s(t,r)}function c(t,e){var r=t.intervals([]),n=r.indexOf(e);return n<0?0:(r.splice(n,1),s(t,r),1)}function u(t,e,r){for(var n=0;n=0&&t[n][1]>=e;--n){var i=r(t[n]);if(i)return i}}function h(t,e){for(var r=0;r>1],a=[],o=[],s=[];for(r=0;r3*(e+1)?l(this,t):this.left.insert(t):this.left=g([t]);else if(t[0]>this.mid)this.right?4*(this.right.count+1)>3*(e+1)?l(this,t):this.right.insert(t):this.right=g([t]);else{var r=n.ge(this.leftPoints,t,d),i=n.ge(this.rightPoints,t,m);this.leftPoints.splice(r,0,t),this.rightPoints.splice(i,0,t)}},a.remove=function(t){var e=this.count-this.leftPoints;if(t[1]3*(e-1)?c(this,t):2===(s=this.left.remove(t))?(this.left=null,this.count-=1,1):(1===s&&(this.count-=1),s):0;if(t[0]>this.mid)return this.right?4*(this.left?this.left.count:0)>3*(e-1)?c(this,t):2===(s=this.right.remove(t))?(this.right=null,this.count-=1,1):(1===s&&(this.count-=1),s):0;if(1===this.count)return this.leftPoints[0]===t?2:0;if(1===this.leftPoints.length&&this.leftPoints[0]===t){if(this.left&&this.right){for(var r=this,i=this.left;i.right;)r=i,i=i.right;if(r===this)i.right=this.right;else{var a=this.left,s=this.right;r.count-=i.count,r.right=i.left,i.left=a,i.right=s}o(this,i),this.count=(this.left?this.left.count:0)+(this.right?this.right.count:0)+this.leftPoints.length}else this.left?o(this,this.left):o(this,this.right);return 1}for(a=n.ge(this.leftPoints,t,d);athis.mid){var r;if(this.right)if(r=this.right.queryPoint(t,e))return r;return f(this.rightPoints,t,e)}return h(this.leftPoints,e)},a.queryInterval=function(t,e,r){var n;if(tthis.mid&&this.right&&(n=this.right.queryInterval(t,e,r)))return n;return ethis.mid?f(this.rightPoints,t,r):h(this.leftPoints,r)};var y=v.prototype;y.insert=function(t){this.root?this.root.insert(t):this.root=new i(t[0],null,null,[t],[t])},y.remove=function(t){if(this.root){var e=this.root.remove(t);return 2===e&&(this.root=null),0!==e}return!1},y.queryPoint=function(t,e){if(this.root)return this.root.queryPoint(t,e)},y.queryInterval=function(t,e,r){if(t<=e&&this.root)return this.root.queryInterval(t,e,r)},Object.defineProperty(y,"count",{get:function(){return this.root?this.root.count:0}}),Object.defineProperty(y,"intervals",{get:function(){return this.root?this.root.intervals([]):[]}})},{"binary-search-bounds":31}],235:[function(t,e,r){"use strict";e.exports=function(t){for(var e=new Array(t),r=0;r + * @license MIT + */ +e.exports=function(t){return null!=t&&(n(t)||function(t){return"function"==typeof t.readFloatLE&&"function"==typeof t.slice&&n(t.slice(0,0))}(t)||!!t._isBuffer)}},{}],238:[function(t,e,r){"use strict";e.exports=a,e.exports.isMobile=a,e.exports.default=a;var n=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series[46]0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i,i=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series[46]0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino|android|ipad|playbook|silk/i;function a(t){t||(t={});var e=t.ua;if(e||"undefined"==typeof navigator||(e=navigator.userAgent),e&&e.headers&&"string"==typeof e.headers["user-agent"]&&(e=e.headers["user-agent"]),"string"!=typeof e)return!1;var r=t.tablet?i.test(e):n.test(e);return!r&&t.tablet&&t.featureDetect&&navigator&&navigator.maxTouchPoints>1&&-1!==e.indexOf("Macintosh")&&-1!==e.indexOf("Safari")&&(r=!0),r}},{}],239:[function(t,e,r){"use strict";e.exports=function(t){for(var e,r=t.length,n=0;n13)&&32!==e&&133!==e&&160!==e&&5760!==e&&6158!==e&&(e<8192||e>8205)&&8232!==e&&8233!==e&&8239!==e&&8287!==e&&8288!==e&&12288!==e&&65279!==e)return!1;return!0}},{}],240:[function(t,e,r){e.exports=function(t,e,r){return t*(1-r)+e*r}},{}],241:[function(t,e,r){var n=t("./normalize"),i=t("gl-mat4/create"),a=t("gl-mat4/clone"),o=t("gl-mat4/determinant"),s=t("gl-mat4/invert"),l=t("gl-mat4/transpose"),c={length:t("gl-vec3/length"),normalize:t("gl-vec3/normalize"),dot:t("gl-vec3/dot"),cross:t("gl-vec3/cross")},u=i(),f=i(),h=[0,0,0,0],p=[[0,0,0],[0,0,0],[0,0,0]],d=[0,0,0];function m(t,e,r,n,i){t[0]=e[0]*n+r[0]*i,t[1]=e[1]*n+r[1]*i,t[2]=e[2]*n+r[2]*i}e.exports=function(t,e,r,i,g,v){if(e||(e=[0,0,0]),r||(r=[0,0,0]),i||(i=[0,0,0]),g||(g=[0,0,0,1]),v||(v=[0,0,0,1]),!n(u,t))return!1;if(a(f,u),f[3]=0,f[7]=0,f[11]=0,f[15]=1,Math.abs(o(f)<1e-8))return!1;var y,x,b,_,w,T,k,A=u[3],M=u[7],S=u[11],E=u[12],L=u[13],C=u[14],P=u[15];if(0!==A||0!==M||0!==S){if(h[0]=A,h[1]=M,h[2]=S,h[3]=P,!s(f,f))return!1;l(f,f),y=g,b=f,_=(x=h)[0],w=x[1],T=x[2],k=x[3],y[0]=b[0]*_+b[4]*w+b[8]*T+b[12]*k,y[1]=b[1]*_+b[5]*w+b[9]*T+b[13]*k,y[2]=b[2]*_+b[6]*w+b[10]*T+b[14]*k,y[3]=b[3]*_+b[7]*w+b[11]*T+b[15]*k}else g[0]=g[1]=g[2]=0,g[3]=1;if(e[0]=E,e[1]=L,e[2]=C,function(t,e){t[0][0]=e[0],t[0][1]=e[1],t[0][2]=e[2],t[1][0]=e[4],t[1][1]=e[5],t[1][2]=e[6],t[2][0]=e[8],t[2][1]=e[9],t[2][2]=e[10]}(p,u),r[0]=c.length(p[0]),c.normalize(p[0],p[0]),i[0]=c.dot(p[0],p[1]),m(p[1],p[1],p[0],1,-i[0]),r[1]=c.length(p[1]),c.normalize(p[1],p[1]),i[0]/=r[1],i[1]=c.dot(p[0],p[2]),m(p[2],p[2],p[0],1,-i[1]),i[2]=c.dot(p[1],p[2]),m(p[2],p[2],p[1],1,-i[2]),r[2]=c.length(p[2]),c.normalize(p[2],p[2]),i[1]/=r[2],i[2]/=r[2],c.cross(d,p[1],p[2]),c.dot(p[0],d)<0)for(var I=0;I<3;I++)r[I]*=-1,p[I][0]*=-1,p[I][1]*=-1,p[I][2]*=-1;return v[0]=.5*Math.sqrt(Math.max(1+p[0][0]-p[1][1]-p[2][2],0)),v[1]=.5*Math.sqrt(Math.max(1-p[0][0]+p[1][1]-p[2][2],0)),v[2]=.5*Math.sqrt(Math.max(1-p[0][0]-p[1][1]+p[2][2],0)),v[3]=.5*Math.sqrt(Math.max(1+p[0][0]+p[1][1]+p[2][2],0)),p[2][1]>p[1][2]&&(v[0]=-v[0]),p[0][2]>p[2][0]&&(v[1]=-v[1]),p[1][0]>p[0][1]&&(v[2]=-v[2]),!0}},{"./normalize":242,"gl-mat4/clone":92,"gl-mat4/create":93,"gl-mat4/determinant":94,"gl-mat4/invert":98,"gl-mat4/transpose":109,"gl-vec3/cross":157,"gl-vec3/dot":162,"gl-vec3/length":172,"gl-vec3/normalize":179}],242:[function(t,e,r){e.exports=function(t,e){var r=e[15];if(0===r)return!1;for(var n=1/r,i=0;i<16;i++)t[i]=e[i]*n;return!0}},{}],243:[function(t,e,r){var n=t("gl-vec3/lerp"),i=t("mat4-recompose"),a=t("mat4-decompose"),o=t("gl-mat4/determinant"),s=t("quat-slerp"),l=f(),c=f(),u=f();function f(){return{translate:h(),scale:h(1),skew:h(),perspective:[0,0,0,1],quaternion:[0,0,0,1]}}function h(t){return[t||0,t||0,t||0]}e.exports=function(t,e,r,f){if(0===o(e)||0===o(r))return!1;var h=a(e,l.translate,l.scale,l.skew,l.perspective,l.quaternion),p=a(r,c.translate,c.scale,c.skew,c.perspective,c.quaternion);return!(!h||!p)&&(n(u.translate,l.translate,c.translate,f),n(u.skew,l.skew,c.skew,f),n(u.scale,l.scale,c.scale,f),n(u.perspective,l.perspective,c.perspective,f),s(u.quaternion,l.quaternion,c.quaternion,f),i(t,u.translate,u.scale,u.skew,u.perspective,u.quaternion),!0)}},{"gl-mat4/determinant":94,"gl-vec3/lerp":173,"mat4-decompose":241,"mat4-recompose":244,"quat-slerp":271}],244:[function(t,e,r){var n={identity:t("gl-mat4/identity"),translate:t("gl-mat4/translate"),multiply:t("gl-mat4/multiply"),create:t("gl-mat4/create"),scale:t("gl-mat4/scale"),fromRotationTranslation:t("gl-mat4/fromRotationTranslation")},i=(n.create(),n.create());e.exports=function(t,e,r,a,o,s){return n.identity(t),n.fromRotationTranslation(t,s,e),t[3]=o[0],t[7]=o[1],t[11]=o[2],t[15]=o[3],n.identity(i),0!==a[2]&&(i[9]=a[2],n.multiply(t,t,i)),0!==a[1]&&(i[9]=0,i[8]=a[1],n.multiply(t,t,i)),0!==a[0]&&(i[8]=0,i[4]=a[0],n.multiply(t,t,i)),n.scale(t,t,r),t}},{"gl-mat4/create":93,"gl-mat4/fromRotationTranslation":96,"gl-mat4/identity":97,"gl-mat4/multiply":100,"gl-mat4/scale":107,"gl-mat4/translate":108}],245:[function(t,e,r){"use strict";var n=t("binary-search-bounds"),i=t("mat4-interpolate"),a=t("gl-mat4/invert"),o=t("gl-mat4/rotateX"),s=t("gl-mat4/rotateY"),l=t("gl-mat4/rotateZ"),c=t("gl-mat4/lookAt"),u=t("gl-mat4/translate"),f=(t("gl-mat4/scale"),t("gl-vec3/normalize")),h=[0,0,0];function p(t){this._components=t.slice(),this._time=[0],this.prevMatrix=t.slice(),this.nextMatrix=t.slice(),this.computedMatrix=t.slice(),this.computedInverse=t.slice(),this.computedEye=[0,0,0],this.computedUp=[0,0,0],this.computedCenter=[0,0,0],this.computedRadius=[0],this._limits=[-1/0,1/0]}e.exports=function(t){return new p((t=t||{}).matrix||[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1])};var d=p.prototype;d.recalcMatrix=function(t){var e=this._time,r=n.le(e,t),o=this.computedMatrix;if(!(r<0)){var s=this._components;if(r===e.length-1)for(var l=16*r,c=0;c<16;++c)o[c]=s[l++];else{var u=e[r+1]-e[r],h=(l=16*r,this.prevMatrix),p=!0;for(c=0;c<16;++c)h[c]=s[l++];var d=this.nextMatrix;for(c=0;c<16;++c)d[c]=s[l++],p=p&&h[c]===d[c];if(u<1e-6||p)for(c=0;c<16;++c)o[c]=h[c];else i(o,h,d,(t-e[r])/u)}var m=this.computedUp;m[0]=o[1],m[1]=o[5],m[2]=o[9],f(m,m);var g=this.computedInverse;a(g,o);var v=this.computedEye,y=g[15];v[0]=g[12]/y,v[1]=g[13]/y,v[2]=g[14]/y;var x=this.computedCenter,b=Math.exp(this.computedRadius[0]);for(c=0;c<3;++c)x[c]=v[c]-o[2+4*c]*b}},d.idle=function(t){if(!(t1&&n(t[o[u-2]],t[o[u-1]],c)<=0;)u-=1,o.pop();for(o.push(l),u=s.length;u>1&&n(t[s[u-2]],t[s[u-1]],c)>=0;)u-=1,s.pop();s.push(l)}r=new Array(s.length+o.length-2);for(var f=0,h=(i=0,o.length);i0;--p)r[f++]=s[p];return r};var n=t("robust-orientation")[3]},{"robust-orientation":284}],247:[function(t,e,r){"use strict";e.exports=function(t,e){e||(e=t,t=window);var r=0,i=0,a=0,o={shift:!1,alt:!1,control:!1,meta:!1},s=!1;function l(t){var e=!1;return"altKey"in t&&(e=e||t.altKey!==o.alt,o.alt=!!t.altKey),"shiftKey"in t&&(e=e||t.shiftKey!==o.shift,o.shift=!!t.shiftKey),"ctrlKey"in t&&(e=e||t.ctrlKey!==o.control,o.control=!!t.ctrlKey),"metaKey"in t&&(e=e||t.metaKey!==o.meta,o.meta=!!t.metaKey),e}function c(t,s){var c=n.x(s),u=n.y(s);"buttons"in s&&(t=0|s.buttons),(t!==r||c!==i||u!==a||l(s))&&(r=0|t,i=c||0,a=u||0,e&&e(r,i,a,o))}function u(t){c(0,t)}function f(){(r||i||a||o.shift||o.alt||o.meta||o.control)&&(i=a=0,r=0,o.shift=o.alt=o.control=o.meta=!1,e&&e(0,0,0,o))}function h(t){l(t)&&e&&e(r,i,a,o)}function p(t){0===n.buttons(t)?c(0,t):c(r,t)}function d(t){c(r|n.buttons(t),t)}function m(t){c(r&~n.buttons(t),t)}function g(){s||(s=!0,t.addEventListener("mousemove",p),t.addEventListener("mousedown",d),t.addEventListener("mouseup",m),t.addEventListener("mouseleave",u),t.addEventListener("mouseenter",u),t.addEventListener("mouseout",u),t.addEventListener("mouseover",u),t.addEventListener("blur",f),t.addEventListener("keyup",h),t.addEventListener("keydown",h),t.addEventListener("keypress",h),t!==window&&(window.addEventListener("blur",f),window.addEventListener("keyup",h),window.addEventListener("keydown",h),window.addEventListener("keypress",h)))}g();var v={element:t};return Object.defineProperties(v,{enabled:{get:function(){return s},set:function(e){e?g():function(){if(!s)return;s=!1,t.removeEventListener("mousemove",p),t.removeEventListener("mousedown",d),t.removeEventListener("mouseup",m),t.removeEventListener("mouseleave",u),t.removeEventListener("mouseenter",u),t.removeEventListener("mouseout",u),t.removeEventListener("mouseover",u),t.removeEventListener("blur",f),t.removeEventListener("keyup",h),t.removeEventListener("keydown",h),t.removeEventListener("keypress",h),t!==window&&(window.removeEventListener("blur",f),window.removeEventListener("keyup",h),window.removeEventListener("keydown",h),window.removeEventListener("keypress",h))}()},enumerable:!0},buttons:{get:function(){return r},enumerable:!0},x:{get:function(){return i},enumerable:!0},y:{get:function(){return a},enumerable:!0},mods:{get:function(){return o},enumerable:!0}}),v};var n=t("mouse-event")},{"mouse-event":249}],248:[function(t,e,r){var n={left:0,top:0};e.exports=function(t,e,r){e=e||t.currentTarget||t.srcElement,Array.isArray(r)||(r=[0,0]);var i=t.clientX||0,a=t.clientY||0,o=(s=e,s===window||s===document||s===document.body?n:s.getBoundingClientRect());var s;return r[0]=i-o.left,r[1]=a-o.top,r}},{}],249:[function(t,e,r){"use strict";function n(t){return t.target||t.srcElement||window}r.buttons=function(t){if("object"==typeof t){if("buttons"in t)return t.buttons;if("which"in t){if(2===(e=t.which))return 4;if(3===e)return 2;if(e>0)return 1<=0)return 1< 0");"function"!=typeof t.vertex&&e("Must specify vertex creation function");"function"!=typeof t.cell&&e("Must specify cell creation function");"function"!=typeof t.phase&&e("Must specify phase function");for(var s=t.getters||[],l=new Array(a),c=0;c=0?l[c]=!0:l[c]=!1;return function(t,e,r,a,o,s){var l=[s,o].join(",");return(0,i[l])(t,e,r,n.mallocUint32,n.freeUint32)}(t.vertex,t.cell,t.phase,0,r,l)};var i={"false,0,1":function(t,e,r,n,i){return function(a,o,s,l){var c,u=0|a.shape[0],f=0|a.shape[1],h=a.data,p=0|a.offset,d=0|a.stride[0],m=0|a.stride[1],g=p,v=0|-d,y=0,x=0|-m,b=0,_=-d-m|0,w=0,T=0|d,k=m-d*u|0,A=0,M=0,S=0,E=2*u|0,L=n(E),C=n(E),P=0,I=0,O=-1,z=-1,D=0,R=0|-u,F=0|u,B=0,N=-u-1|0,j=u-1|0,U=0,V=0,H=0;for(A=0;A0){if(M=1,L[P++]=r(h[g],o,s,l),g+=T,u>0)for(A=1,c=h[g],I=L[P]=r(c,o,s,l),D=L[P+O],B=L[P+R],U=L[P+N],I===D&&I===B&&I===U||(y=h[g+v],b=h[g+x],w=h[g+_],t(A,M,c,y,b,w,I,D,B,U,o,s,l),V=C[P]=S++),P+=1,g+=T,A=2;A0)for(A=1,c=h[g],I=L[P]=r(c,o,s,l),D=L[P+O],B=L[P+R],U=L[P+N],I===D&&I===B&&I===U||(y=h[g+v],b=h[g+x],w=h[g+_],t(A,M,c,y,b,w,I,D,B,U,o,s,l),V=C[P]=S++,U!==B&&e(C[P+R],V,b,w,B,U,o,s,l)),P+=1,g+=T,A=2;A0){if(A=1,L[P++]=r(h[g],o,s,l),g+=T,f>0)for(M=1,c=h[g],I=L[P]=r(c,o,s,l),B=L[P+R],D=L[P+O],U=L[P+N],I===B&&I===D&&I===U||(y=h[g+v],b=h[g+x],w=h[g+_],t(A,M,c,y,b,w,I,B,D,U,o,s,l),V=C[P]=S++),P+=1,g+=T,M=2;M0)for(M=1,c=h[g],I=L[P]=r(c,o,s,l),B=L[P+R],D=L[P+O],U=L[P+N],I===B&&I===D&&I===U||(y=h[g+v],b=h[g+x],w=h[g+_],t(A,M,c,y,b,w,I,B,D,U,o,s,l),V=C[P]=S++,U!==B&&e(C[P+R],V,w,y,U,B,o,s,l)),P+=1,g+=T,M=2;M2&&a[1]>2&&n(i.pick(-1,-1).lo(1,1).hi(a[0]-2,a[1]-2),t.pick(-1,-1,0).lo(1,1).hi(a[0]-2,a[1]-2),t.pick(-1,-1,1).lo(1,1).hi(a[0]-2,a[1]-2)),a[1]>2&&(r(i.pick(0,-1).lo(1).hi(a[1]-2),t.pick(0,-1,1).lo(1).hi(a[1]-2)),e(t.pick(0,-1,0).lo(1).hi(a[1]-2))),a[1]>2&&(r(i.pick(a[0]-1,-1).lo(1).hi(a[1]-2),t.pick(a[0]-1,-1,1).lo(1).hi(a[1]-2)),e(t.pick(a[0]-1,-1,0).lo(1).hi(a[1]-2))),a[0]>2&&(r(i.pick(-1,0).lo(1).hi(a[0]-2),t.pick(-1,0,0).lo(1).hi(a[0]-2)),e(t.pick(-1,0,1).lo(1).hi(a[0]-2))),a[0]>2&&(r(i.pick(-1,a[1]-1).lo(1).hi(a[0]-2),t.pick(-1,a[1]-1,0).lo(1).hi(a[0]-2)),e(t.pick(-1,a[1]-1,1).lo(1).hi(a[0]-2))),t.set(0,0,0,0),t.set(0,0,1,0),t.set(a[0]-1,0,0,0),t.set(a[0]-1,0,1,0),t.set(0,a[1]-1,0,0),t.set(0,a[1]-1,1,0),t.set(a[0]-1,a[1]-1,0,0),t.set(a[0]-1,a[1]-1,1,0),t}}e.exports=function(t,e,r){return Array.isArray(r)||(r=n(e.dimension,"string"==typeof r?r:"clamp")),0===e.size?t:0===e.dimension?(t.set(0),t):function(t){var e=t.join();if(a=u[e])return a;for(var r=t.length,n=[f,h],i=1;i<=r;++i)n.push(p(i));var a=d.apply(void 0,n);return u[e]=a,a}(r)(t,e)}},{dup:65}],253:[function(t,e,r){"use strict";function n(t,e){var r=Math.floor(e),n=e-r,i=0<=r&&r0;){x<64?(l=x,x=0):(l=64,x-=64);for(var b=0|t[1];b>0;){b<64?(c=b,b=0):(c=64,b-=64),n=v+x*f+b*h,o=y+x*d+b*m;var _=0,w=0,T=0,k=p,A=f-u*p,M=h-l*f,S=g,E=d-u*g,L=m-l*d;for(T=0;T0;){m<64?(l=m,m=0):(l=64,m-=64);for(var g=0|t[0];g>0;){g<64?(s=g,g=0):(s=64,g-=64),n=p+m*u+g*c,o=d+m*h+g*f;var v=0,y=0,x=u,b=c-l*u,_=h,w=f-l*h;for(y=0;y0;){y<64?(c=y,y=0):(c=64,y-=64);for(var x=0|t[0];x>0;){x<64?(s=x,x=0):(s=64,x-=64);for(var b=0|t[1];b>0;){b<64?(l=b,b=0):(l=64,b-=64),n=g+y*h+x*u+b*f,o=v+y*m+x*p+b*d;var _=0,w=0,T=0,k=h,A=u-c*h,M=f-s*u,S=m,E=p-c*m,L=d-s*p;for(T=0;Tr;){v=0,y=m-o;e:for(g=0;gb)break e;y+=f,v+=h}for(v=m,y=m-o,g=0;g>1,q=H-j,G=H+j,Y=U,W=q,X=H,Z=G,J=V,K=i+1,Q=a-1,$=!0,tt=0,et=0,rt=0,nt=f,it=e(nt),at=e(nt);A=l*Y,M=l*W,N=s;t:for(k=0;k0){g=Y,Y=W,W=g;break t}if(rt<0)break t;N+=p}A=l*Z,M=l*J,N=s;t:for(k=0;k0){g=Z,Z=J,J=g;break t}if(rt<0)break t;N+=p}A=l*Y,M=l*X,N=s;t:for(k=0;k0){g=Y,Y=X,X=g;break t}if(rt<0)break t;N+=p}A=l*W,M=l*X,N=s;t:for(k=0;k0){g=W,W=X,X=g;break t}if(rt<0)break t;N+=p}A=l*Y,M=l*Z,N=s;t:for(k=0;k0){g=Y,Y=Z,Z=g;break t}if(rt<0)break t;N+=p}A=l*X,M=l*Z,N=s;t:for(k=0;k0){g=X,X=Z,Z=g;break t}if(rt<0)break t;N+=p}A=l*W,M=l*J,N=s;t:for(k=0;k0){g=W,W=J,J=g;break t}if(rt<0)break t;N+=p}A=l*W,M=l*X,N=s;t:for(k=0;k0){g=W,W=X,X=g;break t}if(rt<0)break t;N+=p}A=l*Z,M=l*J,N=s;t:for(k=0;k0){g=Z,Z=J,J=g;break t}if(rt<0)break t;N+=p}for(A=l*Y,M=l*W,S=l*X,E=l*Z,L=l*J,C=l*U,P=l*H,I=l*V,B=0,N=s,k=0;k0)){if(rt<0){for(A=l*b,M=l*K,S=l*Q,N=s,k=0;k0)for(;;){_=s+Q*l,B=0;t:for(k=0;k0)){_=s+Q*l,B=0;t:for(k=0;kV){t:for(;;){for(_=s+K*l,B=0,N=s,k=0;k1&&n?s(r,n[0],n[1]):s(r)}(t,e,l);return n(l,c)}},{"typedarray-pool":308}],258:[function(t,e,r){"use strict";var n=t("./lib/compile_sort.js"),i={};e.exports=function(t){var e=t.order,r=t.dtype,a=[e,r].join(":"),o=i[a];return o||(i[a]=o=n(e,r)),o(t),t}},{"./lib/compile_sort.js":257}],259:[function(t,e,r){var n=t("is-buffer"),i="undefined"!=typeof Float64Array;function a(t,e){return t[0]-e[0]}function o(){var t,e=this.stride,r=new Array(e.length);for(t=0;t=0&&(e+=a*(r=0|t),i-=r),new n(this.data,i,a,e)},i.step=function(t){var e=this.shape[0],r=this.stride[0],i=this.offset,a=0,o=Math.ceil;return"number"==typeof t&&((a=0|t)<0?(i+=r*(e-1),e=o(-e/a)):e=o(e/a),r*=a),new n(this.data,e,r,i)},i.transpose=function(t){t=void 0===t?0:0|t;var e=this.shape,r=this.stride;return new n(this.data,e[t],r[t],this.offset)},i.pick=function(t){var r=[],n=[],i=this.offset;return"number"==typeof t&&t>=0?i=i+this.stride[0]*t|0:(r.push(this.shape[0]),n.push(this.stride[0])),(0,e[r.length+1])(this.data,r,n,i)},function(t,e,r,i){return new n(t,e[0],r[0],i)}},2:function(t,e,r){function n(t,e,r,n,i,a){this.data=t,this.shape=[e,r],this.stride=[n,i],this.offset=0|a}var i=n.prototype;return i.dtype=t,i.dimension=2,Object.defineProperty(i,"size",{get:function(){return this.shape[0]*this.shape[1]}}),Object.defineProperty(i,"order",{get:function(){return Math.abs(this.stride[0])>Math.abs(this.stride[1])?[1,0]:[0,1]}}),i.set=function(e,r,n){return"generic"===t?this.data.set(this.offset+this.stride[0]*e+this.stride[1]*r,n):this.data[this.offset+this.stride[0]*e+this.stride[1]*r]=n},i.get=function(e,r){return"generic"===t?this.data.get(this.offset+this.stride[0]*e+this.stride[1]*r):this.data[this.offset+this.stride[0]*e+this.stride[1]*r]},i.index=function(t,e){return this.offset+this.stride[0]*t+this.stride[1]*e},i.hi=function(t,e){return new n(this.data,"number"!=typeof t||t<0?this.shape[0]:0|t,"number"!=typeof e||e<0?this.shape[1]:0|e,this.stride[0],this.stride[1],this.offset)},i.lo=function(t,e){var r=this.offset,i=0,a=this.shape[0],o=this.shape[1],s=this.stride[0],l=this.stride[1];return"number"==typeof t&&t>=0&&(r+=s*(i=0|t),a-=i),"number"==typeof e&&e>=0&&(r+=l*(i=0|e),o-=i),new n(this.data,a,o,s,l,r)},i.step=function(t,e){var r=this.shape[0],i=this.shape[1],a=this.stride[0],o=this.stride[1],s=this.offset,l=0,c=Math.ceil;return"number"==typeof t&&((l=0|t)<0?(s+=a*(r-1),r=c(-r/l)):r=c(r/l),a*=l),"number"==typeof e&&((l=0|e)<0?(s+=o*(i-1),i=c(-i/l)):i=c(i/l),o*=l),new n(this.data,r,i,a,o,s)},i.transpose=function(t,e){t=void 0===t?0:0|t,e=void 0===e?1:0|e;var r=this.shape,i=this.stride;return new n(this.data,r[t],r[e],i[t],i[e],this.offset)},i.pick=function(t,r){var n=[],i=[],a=this.offset;return"number"==typeof t&&t>=0?a=a+this.stride[0]*t|0:(n.push(this.shape[0]),i.push(this.stride[0])),"number"==typeof r&&r>=0?a=a+this.stride[1]*r|0:(n.push(this.shape[1]),i.push(this.stride[1])),(0,e[n.length+1])(this.data,n,i,a)},function(t,e,r,i){return new n(t,e[0],e[1],r[0],r[1],i)}},3:function(t,e,r){function n(t,e,r,n,i,a,o,s){this.data=t,this.shape=[e,r,n],this.stride=[i,a,o],this.offset=0|s}var i=n.prototype;return i.dtype=t,i.dimension=3,Object.defineProperty(i,"size",{get:function(){return this.shape[0]*this.shape[1]*this.shape[2]}}),Object.defineProperty(i,"order",{get:function(){var t=Math.abs(this.stride[0]),e=Math.abs(this.stride[1]),r=Math.abs(this.stride[2]);return t>e?e>r?[2,1,0]:t>r?[1,2,0]:[1,0,2]:t>r?[2,0,1]:r>e?[0,1,2]:[0,2,1]}}),i.set=function(e,r,n,i){return"generic"===t?this.data.set(this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n,i):this.data[this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n]=i},i.get=function(e,r,n){return"generic"===t?this.data.get(this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n):this.data[this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n]},i.index=function(t,e,r){return this.offset+this.stride[0]*t+this.stride[1]*e+this.stride[2]*r},i.hi=function(t,e,r){return new n(this.data,"number"!=typeof t||t<0?this.shape[0]:0|t,"number"!=typeof e||e<0?this.shape[1]:0|e,"number"!=typeof r||r<0?this.shape[2]:0|r,this.stride[0],this.stride[1],this.stride[2],this.offset)},i.lo=function(t,e,r){var i=this.offset,a=0,o=this.shape[0],s=this.shape[1],l=this.shape[2],c=this.stride[0],u=this.stride[1],f=this.stride[2];return"number"==typeof t&&t>=0&&(i+=c*(a=0|t),o-=a),"number"==typeof e&&e>=0&&(i+=u*(a=0|e),s-=a),"number"==typeof r&&r>=0&&(i+=f*(a=0|r),l-=a),new n(this.data,o,s,l,c,u,f,i)},i.step=function(t,e,r){var i=this.shape[0],a=this.shape[1],o=this.shape[2],s=this.stride[0],l=this.stride[1],c=this.stride[2],u=this.offset,f=0,h=Math.ceil;return"number"==typeof t&&((f=0|t)<0?(u+=s*(i-1),i=h(-i/f)):i=h(i/f),s*=f),"number"==typeof e&&((f=0|e)<0?(u+=l*(a-1),a=h(-a/f)):a=h(a/f),l*=f),"number"==typeof r&&((f=0|r)<0?(u+=c*(o-1),o=h(-o/f)):o=h(o/f),c*=f),new n(this.data,i,a,o,s,l,c,u)},i.transpose=function(t,e,r){t=void 0===t?0:0|t,e=void 0===e?1:0|e,r=void 0===r?2:0|r;var i=this.shape,a=this.stride;return new n(this.data,i[t],i[e],i[r],a[t],a[e],a[r],this.offset)},i.pick=function(t,r,n){var i=[],a=[],o=this.offset;return"number"==typeof t&&t>=0?o=o+this.stride[0]*t|0:(i.push(this.shape[0]),a.push(this.stride[0])),"number"==typeof r&&r>=0?o=o+this.stride[1]*r|0:(i.push(this.shape[1]),a.push(this.stride[1])),"number"==typeof n&&n>=0?o=o+this.stride[2]*n|0:(i.push(this.shape[2]),a.push(this.stride[2])),(0,e[i.length+1])(this.data,i,a,o)},function(t,e,r,i){return new n(t,e[0],e[1],e[2],r[0],r[1],r[2],i)}},4:function(t,e,r){function n(t,e,r,n,i,a,o,s,l,c){this.data=t,this.shape=[e,r,n,i],this.stride=[a,o,s,l],this.offset=0|c}var i=n.prototype;return i.dtype=t,i.dimension=4,Object.defineProperty(i,"size",{get:function(){return this.shape[0]*this.shape[1]*this.shape[2]*this.shape[3]}}),Object.defineProperty(i,"order",{get:r}),i.set=function(e,r,n,i,a){return"generic"===t?this.data.set(this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i,a):this.data[this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i]=a},i.get=function(e,r,n,i){return"generic"===t?this.data.get(this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i):this.data[this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i]},i.index=function(t,e,r,n){return this.offset+this.stride[0]*t+this.stride[1]*e+this.stride[2]*r+this.stride[3]*n},i.hi=function(t,e,r,i){return new n(this.data,"number"!=typeof t||t<0?this.shape[0]:0|t,"number"!=typeof e||e<0?this.shape[1]:0|e,"number"!=typeof r||r<0?this.shape[2]:0|r,"number"!=typeof i||i<0?this.shape[3]:0|i,this.stride[0],this.stride[1],this.stride[2],this.stride[3],this.offset)},i.lo=function(t,e,r,i){var a=this.offset,o=0,s=this.shape[0],l=this.shape[1],c=this.shape[2],u=this.shape[3],f=this.stride[0],h=this.stride[1],p=this.stride[2],d=this.stride[3];return"number"==typeof t&&t>=0&&(a+=f*(o=0|t),s-=o),"number"==typeof e&&e>=0&&(a+=h*(o=0|e),l-=o),"number"==typeof r&&r>=0&&(a+=p*(o=0|r),c-=o),"number"==typeof i&&i>=0&&(a+=d*(o=0|i),u-=o),new n(this.data,s,l,c,u,f,h,p,d,a)},i.step=function(t,e,r,i){var a=this.shape[0],o=this.shape[1],s=this.shape[2],l=this.shape[3],c=this.stride[0],u=this.stride[1],f=this.stride[2],h=this.stride[3],p=this.offset,d=0,m=Math.ceil;return"number"==typeof t&&((d=0|t)<0?(p+=c*(a-1),a=m(-a/d)):a=m(a/d),c*=d),"number"==typeof e&&((d=0|e)<0?(p+=u*(o-1),o=m(-o/d)):o=m(o/d),u*=d),"number"==typeof r&&((d=0|r)<0?(p+=f*(s-1),s=m(-s/d)):s=m(s/d),f*=d),"number"==typeof i&&((d=0|i)<0?(p+=h*(l-1),l=m(-l/d)):l=m(l/d),h*=d),new n(this.data,a,o,s,l,c,u,f,h,p)},i.transpose=function(t,e,r,i){t=void 0===t?0:0|t,e=void 0===e?1:0|e,r=void 0===r?2:0|r,i=void 0===i?3:0|i;var a=this.shape,o=this.stride;return new n(this.data,a[t],a[e],a[r],a[i],o[t],o[e],o[r],o[i],this.offset)},i.pick=function(t,r,n,i){var a=[],o=[],s=this.offset;return"number"==typeof t&&t>=0?s=s+this.stride[0]*t|0:(a.push(this.shape[0]),o.push(this.stride[0])),"number"==typeof r&&r>=0?s=s+this.stride[1]*r|0:(a.push(this.shape[1]),o.push(this.stride[1])),"number"==typeof n&&n>=0?s=s+this.stride[2]*n|0:(a.push(this.shape[2]),o.push(this.stride[2])),"number"==typeof i&&i>=0?s=s+this.stride[3]*i|0:(a.push(this.shape[3]),o.push(this.stride[3])),(0,e[a.length+1])(this.data,a,o,s)},function(t,e,r,i){return new n(t,e[0],e[1],e[2],e[3],r[0],r[1],r[2],r[3],i)}},5:function(t,e,r){function n(t,e,r,n,i,a,o,s,l,c,u,f){this.data=t,this.shape=[e,r,n,i,a],this.stride=[o,s,l,c,u],this.offset=0|f}var i=n.prototype;return i.dtype=t,i.dimension=5,Object.defineProperty(i,"size",{get:function(){return this.shape[0]*this.shape[1]*this.shape[2]*this.shape[3]*this.shape[4]}}),Object.defineProperty(i,"order",{get:r}),i.set=function(e,r,n,i,a,o){return"generic"===t?this.data.set(this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i+this.stride[4]*a,o):this.data[this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i+this.stride[4]*a]=o},i.get=function(e,r,n,i,a){return"generic"===t?this.data.get(this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i+this.stride[4]*a):this.data[this.offset+this.stride[0]*e+this.stride[1]*r+this.stride[2]*n+this.stride[3]*i+this.stride[4]*a]},i.index=function(t,e,r,n,i){return this.offset+this.stride[0]*t+this.stride[1]*e+this.stride[2]*r+this.stride[3]*n+this.stride[4]*i},i.hi=function(t,e,r,i,a){return new n(this.data,"number"!=typeof t||t<0?this.shape[0]:0|t,"number"!=typeof e||e<0?this.shape[1]:0|e,"number"!=typeof r||r<0?this.shape[2]:0|r,"number"!=typeof i||i<0?this.shape[3]:0|i,"number"!=typeof a||a<0?this.shape[4]:0|a,this.stride[0],this.stride[1],this.stride[2],this.stride[3],this.stride[4],this.offset)},i.lo=function(t,e,r,i,a){var o=this.offset,s=0,l=this.shape[0],c=this.shape[1],u=this.shape[2],f=this.shape[3],h=this.shape[4],p=this.stride[0],d=this.stride[1],m=this.stride[2],g=this.stride[3],v=this.stride[4];return"number"==typeof t&&t>=0&&(o+=p*(s=0|t),l-=s),"number"==typeof e&&e>=0&&(o+=d*(s=0|e),c-=s),"number"==typeof r&&r>=0&&(o+=m*(s=0|r),u-=s),"number"==typeof i&&i>=0&&(o+=g*(s=0|i),f-=s),"number"==typeof a&&a>=0&&(o+=v*(s=0|a),h-=s),new n(this.data,l,c,u,f,h,p,d,m,g,v,o)},i.step=function(t,e,r,i,a){var o=this.shape[0],s=this.shape[1],l=this.shape[2],c=this.shape[3],u=this.shape[4],f=this.stride[0],h=this.stride[1],p=this.stride[2],d=this.stride[3],m=this.stride[4],g=this.offset,v=0,y=Math.ceil;return"number"==typeof t&&((v=0|t)<0?(g+=f*(o-1),o=y(-o/v)):o=y(o/v),f*=v),"number"==typeof e&&((v=0|e)<0?(g+=h*(s-1),s=y(-s/v)):s=y(s/v),h*=v),"number"==typeof r&&((v=0|r)<0?(g+=p*(l-1),l=y(-l/v)):l=y(l/v),p*=v),"number"==typeof i&&((v=0|i)<0?(g+=d*(c-1),c=y(-c/v)):c=y(c/v),d*=v),"number"==typeof a&&((v=0|a)<0?(g+=m*(u-1),u=y(-u/v)):u=y(u/v),m*=v),new n(this.data,o,s,l,c,u,f,h,p,d,m,g)},i.transpose=function(t,e,r,i,a){t=void 0===t?0:0|t,e=void 0===e?1:0|e,r=void 0===r?2:0|r,i=void 0===i?3:0|i,a=void 0===a?4:0|a;var o=this.shape,s=this.stride;return new n(this.data,o[t],o[e],o[r],o[i],o[a],s[t],s[e],s[r],s[i],s[a],this.offset)},i.pick=function(t,r,n,i,a){var o=[],s=[],l=this.offset;return"number"==typeof t&&t>=0?l=l+this.stride[0]*t|0:(o.push(this.shape[0]),s.push(this.stride[0])),"number"==typeof r&&r>=0?l=l+this.stride[1]*r|0:(o.push(this.shape[1]),s.push(this.stride[1])),"number"==typeof n&&n>=0?l=l+this.stride[2]*n|0:(o.push(this.shape[2]),s.push(this.stride[2])),"number"==typeof i&&i>=0?l=l+this.stride[3]*i|0:(o.push(this.shape[3]),s.push(this.stride[3])),"number"==typeof a&&a>=0?l=l+this.stride[4]*a|0:(o.push(this.shape[4]),s.push(this.stride[4])),(0,e[o.length+1])(this.data,o,s,l)},function(t,e,r,i){return new n(t,e[0],e[1],e[2],e[3],e[4],r[0],r[1],r[2],r[3],r[4],i)}}};function l(t,e){var r=-1===e?"T":String(e),n=s[r];return-1===e?n(t):0===e?n(t,c[t][0]):n(t,c[t],o)}var c={generic:[],buffer:[],array:[],float32:[],float64:[],int8:[],int16:[],int32:[],uint8_clamped:[],uint8:[],uint16:[],uint32:[],bigint64:[],biguint64:[]};e.exports=function(t,e,r,a){if(void 0===t)return(0,c.array[0])([]);"number"==typeof t&&(t=[t]),void 0===e&&(e=[t.length]);var o=e.length;if(void 0===r){r=new Array(o);for(var s=o-1,u=1;s>=0;--s)r[s]=u,u*=e[s]}if(void 0===a){a=0;for(s=0;st==t>0?a===-1>>>0?(r+=1,a=0):a+=1:0===a?(a=-1>>>0,r-=1):a-=1;return n.pack(a,r)}},{"double-bits":64}],261:[function(t,e,r){r.vertexNormals=function(t,e,r){for(var n=e.length,i=new Array(n),a=void 0===r?1e-6:r,o=0;oa){var b=i[c],_=1/Math.sqrt(g*y);for(x=0;x<3;++x){var w=(x+1)%3,T=(x+2)%3;b[x]+=_*(v[w]*m[T]-v[T]*m[w])}}}for(o=0;oa)for(_=1/Math.sqrt(k),x=0;x<3;++x)b[x]*=_;else for(x=0;x<3;++x)b[x]=0}return i},r.faceNormals=function(t,e,r){for(var n=t.length,i=new Array(n),a=void 0===r?1e-6:r,o=0;oa?1/Math.sqrt(p):0;for(c=0;c<3;++c)h[c]*=p;i[o]=h}return i}},{}],262:[function(t,e,r){"use strict";e.exports=function(t,e,r,n,i,a,o,s,l,c){var u=e+a+c;if(f>0){var f=Math.sqrt(u+1);t[0]=.5*(o-l)/f,t[1]=.5*(s-n)/f,t[2]=.5*(r-a)/f,t[3]=.5*f}else{var h=Math.max(e,a,c);f=Math.sqrt(2*h-u+1);e>=h?(t[0]=.5*f,t[1]=.5*(i+r)/f,t[2]=.5*(s+n)/f,t[3]=.5*(o-l)/f):a>=h?(t[0]=.5*(r+i)/f,t[1]=.5*f,t[2]=.5*(l+o)/f,t[3]=.5*(s-n)/f):(t[0]=.5*(n+s)/f,t[1]=.5*(o+l)/f,t[2]=.5*f,t[3]=.5*(r-i)/f)}return t}},{}],263:[function(t,e,r){"use strict";e.exports=function(t){var e=(t=t||{}).center||[0,0,0],r=t.rotation||[0,0,0,1],n=t.radius||1;e=[].slice.call(e,0,3),u(r=[].slice.call(r,0,4),r);var i=new f(r,e,Math.log(n));i.setDistanceLimits(t.zoomMin,t.zoomMax),("eye"in t||"up"in t)&&i.lookAt(0,t.eye,t.center,t.up);return i};var n=t("filtered-vector"),i=t("gl-mat4/lookAt"),a=t("gl-mat4/fromQuat"),o=t("gl-mat4/invert"),s=t("./lib/quatFromFrame");function l(t,e,r){return Math.sqrt(Math.pow(t,2)+Math.pow(e,2)+Math.pow(r,2))}function c(t,e,r,n){return Math.sqrt(Math.pow(t,2)+Math.pow(e,2)+Math.pow(r,2)+Math.pow(n,2))}function u(t,e){var r=e[0],n=e[1],i=e[2],a=e[3],o=c(r,n,i,a);o>1e-6?(t[0]=r/o,t[1]=n/o,t[2]=i/o,t[3]=a/o):(t[0]=t[1]=t[2]=0,t[3]=1)}function f(t,e,r){this.radius=n([r]),this.center=n(e),this.rotation=n(t),this.computedRadius=this.radius.curve(0),this.computedCenter=this.center.curve(0),this.computedRotation=this.rotation.curve(0),this.computedUp=[.1,0,0],this.computedEye=[.1,0,0],this.computedMatrix=[.1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],this.recalcMatrix(0)}var h=f.prototype;h.lastT=function(){return Math.max(this.radius.lastT(),this.center.lastT(),this.rotation.lastT())},h.recalcMatrix=function(t){this.radius.curve(t),this.center.curve(t),this.rotation.curve(t);var e=this.computedRotation;u(e,e);var r=this.computedMatrix;a(r,e);var n=this.computedCenter,i=this.computedEye,o=this.computedUp,s=Math.exp(this.computedRadius[0]);i[0]=n[0]+s*r[2],i[1]=n[1]+s*r[6],i[2]=n[2]+s*r[10],o[0]=r[1],o[1]=r[5],o[2]=r[9];for(var l=0;l<3;++l){for(var c=0,f=0;f<3;++f)c+=r[l+4*f]*i[f];r[12+l]=-c}},h.getMatrix=function(t,e){this.recalcMatrix(t);var r=this.computedMatrix;if(e){for(var n=0;n<16;++n)e[n]=r[n];return e}return r},h.idle=function(t){this.center.idle(t),this.radius.idle(t),this.rotation.idle(t)},h.flush=function(t){this.center.flush(t),this.radius.flush(t),this.rotation.flush(t)},h.pan=function(t,e,r,n){e=e||0,r=r||0,n=n||0,this.recalcMatrix(t);var i=this.computedMatrix,a=i[1],o=i[5],s=i[9],c=l(a,o,s);a/=c,o/=c,s/=c;var u=i[0],f=i[4],h=i[8],p=u*a+f*o+h*s,d=l(u-=a*p,f-=o*p,h-=s*p);u/=d,f/=d,h/=d;var m=i[2],g=i[6],v=i[10],y=m*a+g*o+v*s,x=m*u+g*f+v*h,b=l(m-=y*a+x*u,g-=y*o+x*f,v-=y*s+x*h);m/=b,g/=b,v/=b;var _=u*e+a*r,w=f*e+o*r,T=h*e+s*r;this.center.move(t,_,w,T);var k=Math.exp(this.computedRadius[0]);k=Math.max(1e-4,k+n),this.radius.set(t,Math.log(k))},h.rotate=function(t,e,r,n){this.recalcMatrix(t),e=e||0,r=r||0;var i=this.computedMatrix,a=i[0],o=i[4],s=i[8],u=i[1],f=i[5],h=i[9],p=i[2],d=i[6],m=i[10],g=e*a+r*u,v=e*o+r*f,y=e*s+r*h,x=-(d*y-m*v),b=-(m*g-p*y),_=-(p*v-d*g),w=Math.sqrt(Math.max(0,1-Math.pow(x,2)-Math.pow(b,2)-Math.pow(_,2))),T=c(x,b,_,w);T>1e-6?(x/=T,b/=T,_/=T,w/=T):(x=b=_=0,w=1);var k=this.computedRotation,A=k[0],M=k[1],S=k[2],E=k[3],L=A*w+E*x+M*_-S*b,C=M*w+E*b+S*x-A*_,P=S*w+E*_+A*b-M*x,I=E*w-A*x-M*b-S*_;if(n){x=p,b=d,_=m;var O=Math.sin(n)/l(x,b,_);x*=O,b*=O,_*=O,I=I*(w=Math.cos(e))-(L=L*w+I*x+C*_-P*b)*x-(C=C*w+I*b+P*x-L*_)*b-(P=P*w+I*_+L*b-C*x)*_}var z=c(L,C,P,I);z>1e-6?(L/=z,C/=z,P/=z,I/=z):(L=C=P=0,I=1),this.rotation.set(t,L,C,P,I)},h.lookAt=function(t,e,r,n){this.recalcMatrix(t),r=r||this.computedCenter,e=e||this.computedEye,n=n||this.computedUp;var a=this.computedMatrix;i(a,e,r,n);var o=this.computedRotation;s(o,a[0],a[1],a[2],a[4],a[5],a[6],a[8],a[9],a[10]),u(o,o),this.rotation.set(t,o[0],o[1],o[2],o[3]);for(var l=0,c=0;c<3;++c)l+=Math.pow(r[c]-e[c],2);this.radius.set(t,.5*Math.log(Math.max(l,1e-6))),this.center.set(t,r[0],r[1],r[2])},h.translate=function(t,e,r,n){this.center.move(t,e||0,r||0,n||0)},h.setMatrix=function(t,e){var r=this.computedRotation;s(r,e[0],e[1],e[2],e[4],e[5],e[6],e[8],e[9],e[10]),u(r,r),this.rotation.set(t,r[0],r[1],r[2],r[3]);var n=this.computedMatrix;o(n,e);var i=n[15];if(Math.abs(i)>1e-6){var a=n[12]/i,l=n[13]/i,c=n[14]/i;this.recalcMatrix(t);var f=Math.exp(this.computedRadius[0]);this.center.set(t,a-n[2]*f,l-n[6]*f,c-n[10]*f),this.radius.idle(t)}else this.center.idle(t),this.radius.idle(t)},h.setDistance=function(t,e){e>0&&this.radius.set(t,Math.log(e))},h.setDistanceLimits=function(t,e){t=t>0?Math.log(t):-1/0,e=e>0?Math.log(e):1/0,e=Math.max(e,t),this.radius.bounds[0][0]=t,this.radius.bounds[1][0]=e},h.getDistanceLimits=function(t){var e=this.radius.bounds;return t?(t[0]=Math.exp(e[0][0]),t[1]=Math.exp(e[1][0]),t):[Math.exp(e[0][0]),Math.exp(e[1][0])]},h.toJSON=function(){return this.recalcMatrix(this.lastT()),{center:this.computedCenter.slice(),rotation:this.computedRotation.slice(),distance:Math.log(this.computedRadius[0]),zoomMin:this.radius.bounds[0][0],zoomMax:this.radius.bounds[1][0]}},h.fromJSON=function(t){var e=this.lastT(),r=t.center;r&&this.center.set(e,r[0],r[1],r[2]);var n=t.rotation;n&&this.rotation.set(e,n[0],n[1],n[2],n[3]);var i=t.distance;i&&i>0&&this.radius.set(e,Math.log(i)),this.setDistanceLimits(t.zoomMin,t.zoomMax)}},{"./lib/quatFromFrame":262,"filtered-vector":68,"gl-mat4/fromQuat":95,"gl-mat4/invert":98,"gl-mat4/lookAt":99}],264:[function(t,e,r){ +/*! + * pad-left + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT license. + */ +"use strict";var n=t("repeat-string");e.exports=function(t,e,r){return n(r=void 0!==r?r+"":" ",e)+t}},{"repeat-string":277}],265:[function(t,e,r){e.exports=function(t,e){e||(e=[0,""]),t=String(t);var r=parseFloat(t,10);return e[0]=r,e[1]=t.match(/[\d.\-\+]*\s*(.*)/)[1]||"",e}},{}],266:[function(t,e,r){"use strict";e.exports=function(t,e){for(var r=0|e.length,i=t.length,a=[new Array(r),new Array(r)],o=0;o0){o=a[u][r][0],l=u;break}s=o[1^l];for(var f=0;f<2;++f)for(var h=a[f][r],p=0;p0&&(o=d,s=m,l=f)}return i||o&&c(o,l),s}function f(t,r){var i=a[r][t][0],o=[t];c(i,r);for(var s=i[1^r];;){for(;s!==t;)o.push(s),s=u(o[o.length-2],s,!1);if(a[0][t].length+a[1][t].length===0)break;var l=o[o.length-1],f=t,h=o[1],p=u(l,f,!0);if(n(e[l],e[f],e[h],e[p])<0)break;o.push(t),s=u(l,f)}return o}function h(t,e){return e[1]===e[e.length-1]}for(o=0;o0;){a[0][o].length;var m=f(o,p);h(0,m)?d.push.apply(d,m):(d.length>0&&l.push(d),d=m)}d.length>0&&l.push(d)}return l};var n=t("compare-angle")},{"compare-angle":54}],267:[function(t,e,r){"use strict";e.exports=function(t,e){for(var r=n(t,e.length),i=new Array(e.length),a=new Array(e.length),o=[],s=0;s0;){var c=o.pop();i[c]=!1;var u=r[c];for(s=0;s0}))).length,g=new Array(m),v=new Array(m);for(p=0;p0;){var B=R.pop(),N=E[B];l(N,(function(t,e){return t-e}));var j,U=N.length,V=F[B];if(0===V){var H=d[B];j=[H]}for(p=0;p=0))if(F[q]=1^V,R.push(q),0===V)D(H=d[q])||(H.reverse(),j.push(H))}0===V&&r.push(j)}return r};var n=t("edges-to-adjacency-list"),i=t("planar-dual"),a=t("point-in-big-polygon"),o=t("two-product"),s=t("robust-sum"),l=t("uniq"),c=t("./lib/trim-leaves");function u(t,e){for(var r=new Array(t),n=0;n0&&e[i]===r[0]))return 1;a=t[i-1]}for(var s=1;a;){var l=a.key,c=n(r,l[0],l[1]);if(l[0][0]0))return 0;s=-1,a=a.right}else if(c>0)a=a.left;else{if(!(c<0))return 0;s=1,a=a.right}}return s}}(v.slabs,v.coordinates);return 0===a.length?y:function(t,e){return function(r){return t(r[0],r[1])?0:e(r)}}(l(a),y)};var n=t("robust-orientation")[3],i=t("slab-decomposition"),a=t("interval-tree-1d"),o=t("binary-search-bounds");function s(){return!0}function l(t){for(var e={},r=0;r=c?(k=1,y=c+2*h+d):y=h*(k=-h/c)+d):(k=0,p>=0?(A=0,y=d):-p>=f?(A=1,y=f+2*p+d):y=p*(A=-p/f)+d);else if(A<0)A=0,h>=0?(k=0,y=d):-h>=c?(k=1,y=c+2*h+d):y=h*(k=-h/c)+d;else{var M=1/T;y=(k*=M)*(c*k+u*(A*=M)+2*h)+A*(u*k+f*A+2*p)+d}else k<0?(b=f+p)>(x=u+h)?(_=b-x)>=(w=c-2*u+f)?(k=1,A=0,y=c+2*h+d):y=(k=_/w)*(c*k+u*(A=1-k)+2*h)+A*(u*k+f*A+2*p)+d:(k=0,b<=0?(A=1,y=f+2*p+d):p>=0?(A=0,y=d):y=p*(A=-p/f)+d):A<0?(b=c+h)>(x=u+p)?(_=b-x)>=(w=c-2*u+f)?(A=1,k=0,y=f+2*p+d):y=(k=1-(A=_/w))*(c*k+u*A+2*h)+A*(u*k+f*A+2*p)+d:(A=0,b<=0?(k=1,y=c+2*h+d):h>=0?(k=0,y=d):y=h*(k=-h/c)+d):(_=f+p-u-h)<=0?(k=0,A=1,y=f+2*p+d):_>=(w=c-2*u+f)?(k=1,A=0,y=c+2*h+d):y=(k=_/w)*(c*k+u*(A=1-k)+2*h)+A*(u*k+f*A+2*p)+d;var S=1-k-A;for(l=0;l0){var c=t[r-1];if(0===n(s,c)&&a(c)!==l){r-=1;continue}}t[r++]=s}}return t.length=r,t}},{"cell-orientation":47,"compare-cell":56,"compare-oriented-cell":57}],277:[function(t,e,r){ +/*! + * repeat-string + * + * Copyright (c) 2014-2015, Jon Schlinkert. + * Licensed under the MIT License. + */ +"use strict";var n,i="";e.exports=function(t,e){if("string"!=typeof t)throw new TypeError("expected a string");if(1===e)return t;if(2===e)return t+t;var r=t.length*e;if(n!==t||void 0===n)n=t,i="";else if(i.length>=r)return i.substr(0,r);for(;r>i.length&&e>1;)1&e&&(i+=t),e>>=1,t+=t;return i=(i+=t).substr(0,r)}},{}],278:[function(t,e,r){(function(t){(function(){e.exports=t.performance&&t.performance.now?function(){return performance.now()}:Date.now||function(){return+new Date}}).call(this)}).call(this,void 0!==n?n:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}],279:[function(t,e,r){"use strict";e.exports=function(t){for(var e=t.length,r=t[t.length-1],n=e,i=e-2;i>=0;--i){var a=r,o=t[i];(l=o-((r=a+o)-a))&&(t[--n]=r,r=l)}var s=0;for(i=n;i0){if(a<=0)return o;n=i+a}else{if(!(i<0))return o;if(a>=0)return o;n=-(i+a)}var s=33306690738754716e-32*n;return o>=s||o<=-s?o:f(t,e,r)},function(t,e,r,n){var i=t[0]-n[0],a=e[0]-n[0],o=r[0]-n[0],s=t[1]-n[1],l=e[1]-n[1],c=r[1]-n[1],u=t[2]-n[2],f=e[2]-n[2],p=r[2]-n[2],d=a*c,m=o*l,g=o*s,v=i*c,y=i*l,x=a*s,b=u*(d-m)+f*(g-v)+p*(y-x),_=7771561172376103e-31*((Math.abs(d)+Math.abs(m))*Math.abs(u)+(Math.abs(g)+Math.abs(v))*Math.abs(f)+(Math.abs(y)+Math.abs(x))*Math.abs(p));return b>_||-b>_?b:h(t,e,r,n)}];function d(t){var e=p[t.length];return e||(e=p[t.length]=u(t.length)),e.apply(void 0,t)}function m(t,e,r,n,i,a,o){return function(e,r,s,l,c){switch(arguments.length){case 0:case 1:return 0;case 2:return n(e,r);case 3:return i(e,r,s);case 4:return a(e,r,s,l);case 5:return o(e,r,s,l,c)}for(var u=new Array(arguments.length),f=0;f0&&o>0||a<0&&o<0)return!1;var s=n(r,t,e),l=n(i,t,e);if(s>0&&l>0||s<0&&l<0)return!1;if(0===a&&0===o&&0===s&&0===l)return function(t,e,r,n){for(var i=0;i<2;++i){var a=t[i],o=e[i],s=Math.min(a,o),l=Math.max(a,o),c=r[i],u=n[i],f=Math.min(c,u);if(Math.max(c,u)=n?(i=f,(l+=1)=n?(i=f,(l+=1)>1,c=e[2*l+1];if(c===a)return l;a>1,c=e[2*l+1];if(c===a)return l;a>1,c=e[2*l+1];if(c===a)return l;a>1,s=a(t[o],e);s<=0?(0===s&&(i=o),r=o+1):s>0&&(n=o-1)}return i}function u(t,e){for(var r=new Array(t.length),i=0,o=r.length;i=t.length||0!==a(t[g],s)););}return r}function f(t,e){if(e<0)return[];for(var r=[],i=(1<>>u&1&&c.push(i[u]);e.push(c)}return s(e)},r.skeleton=f,r.boundary=function(t){for(var e=[],r=0,n=t.length;r>1:(t>>1)-1}function x(t){for(var e=v(t);;){var r=e,n=2*t+1,i=2*(t+1),a=t;if(n0;){var r=y(t);if(r>=0)if(e0){var t=k[0];return g(0,M-1),M-=1,x(0),t}return-1}function w(t,e){var r=k[t];return c[r]===e?t:(c[r]=-1/0,b(t),_(),c[r]=e,b((M+=1)-1))}function T(t){if(!u[t]){u[t]=!0;var e=s[t],r=l[t];s[r]>=0&&(s[r]=e),l[e]>=0&&(l[e]=r),A[e]>=0&&w(A[e],m(e)),A[r]>=0&&w(A[r],m(r))}}var k=[],A=new Array(a);for(f=0;f>1;f>=0;--f)x(f);for(;;){var S=_();if(S<0||c[S]>r)break;T(S)}var E=[];for(f=0;f=0&&r>=0&&e!==r){var n=A[e],i=A[r];n!==i&&C.push([n,i])}})),i.unique(i.normalize(C)),{positions:E,edges:C}};var n=t("robust-orientation"),i=t("simplicial-complex")},{"robust-orientation":284,"simplicial-complex":295}],298:[function(t,e,r){"use strict";e.exports=function(t,e){var r,a,o,s;if(e[0][0]e[1][0]))return i(e,t);r=e[1],a=e[0]}if(t[0][0]t[1][0]))return-i(t,e);o=t[1],s=t[0]}var l=n(r,a,s),c=n(r,a,o);if(l<0){if(c<=0)return l}else if(l>0){if(c>=0)return l}else if(c)return c;if(l=n(s,o,a),c=n(s,o,r),l<0){if(c<=0)return l}else if(l>0){if(c>=0)return l}else if(c)return c;return a[0]-s[0]};var n=t("robust-orientation");function i(t,e){var r,i,a,o;if(e[0][0]e[1][0])){var s=Math.min(t[0][1],t[1][1]),l=Math.max(t[0][1],t[1][1]),c=Math.min(e[0][1],e[1][1]),u=Math.max(e[0][1],e[1][1]);return lu?s-u:l-u}r=e[1],i=e[0]}t[0][1]0)if(e[0]!==o[1][0])r=t,t=t.right;else{if(l=c(t.right,e))return l;t=t.left}else{if(e[0]!==o[1][0])return t;var l;if(l=c(t.right,e))return l;t=t.left}}return r}function u(t,e,r,n){this.y=t,this.index=e,this.start=r,this.closed=n}function f(t,e,r,n){this.x=t,this.segment=e,this.create=r,this.index=n}s.prototype.castUp=function(t){var e=n.le(this.coordinates,t[0]);if(e<0)return-1;this.slabs[e];var r=c(this.slabs[e],t),i=-1;if(r&&(i=r.value),this.coordinates[e]===t[0]){var s=null;if(r&&(s=r.key),e>0){var u=c(this.slabs[e-1],t);u&&(s?o(u.key,s)>0&&(s=u.key,i=u.value):(i=u.value,s=u.key))}var f=this.horizontal[e];if(f.length>0){var h=n.ge(f,t[1],l);if(h=f.length)return i;p=f[h]}}if(p.start)if(s){var d=a(s[0],s[1],[t[0],p.y]);s[0][0]>s[1][0]&&(d=-d),d>0&&(i=p.index)}else i=p.index;else p.y!==t[1]&&(i=p.index)}}}return i}},{"./lib/order-segments":298,"binary-search-bounds":31,"functional-red-black-tree":69,"robust-orientation":284}],300:[function(t,e,r){"use strict";var n=t("robust-dot-product"),i=t("robust-sum");function a(t,e){var r=i(n(t,e),[e[e.length-1]]);return r[r.length-1]}function o(t,e,r,n){var i=-e/(n-e);i<0?i=0:i>1&&(i=1);for(var a=1-i,o=t.length,s=new Array(o),l=0;l0||i>0&&u<0){var f=o(s,u,l,i);r.push(f),n.push(f.slice())}u<0?n.push(l.slice()):u>0?r.push(l.slice()):(r.push(l.slice()),n.push(l.slice())),i=u}return{positive:r,negative:n}},e.exports.positive=function(t,e){for(var r=[],n=a(t[t.length-1],e),i=t[t.length-1],s=t[0],l=0;l0||n>0&&c<0)&&r.push(o(i,c,s,n)),c>=0&&r.push(s.slice()),n=c}return r},e.exports.negative=function(t,e){for(var r=[],n=a(t[t.length-1],e),i=t[t.length-1],s=t[0],l=0;l0||n>0&&c<0)&&r.push(o(i,c,s,n)),c<=0&&r.push(s.slice()),n=c}return r}},{"robust-dot-product":281,"robust-sum":289}],301:[function(t,e,r){!function(){"use strict";var t={not_string:/[^s]/,not_bool:/[^t]/,not_type:/[^T]/,not_primitive:/[^v]/,number:/[diefg]/,numeric_arg:/[bcdiefguxX]/,json:/[j]/,not_json:/[^j]/,text:/^[^\x25]+/,modulo:/^\x25{2}/,placeholder:/^\x25(?:([1-9]\d*)\$|\(([^)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijostTuvxX])/,key:/^([a-z_][a-z_\d]*)/i,key_access:/^\.([a-z_][a-z_\d]*)/i,index_access:/^\[(\d+)\]/,sign:/^[+-]/};function e(t){return i(o(t),arguments)}function n(t,r){return e.apply(null,[t].concat(r||[]))}function i(r,n){var i,a,o,s,l,c,u,f,h,p=1,d=r.length,m="";for(a=0;a=0),s.type){case"b":i=parseInt(i,10).toString(2);break;case"c":i=String.fromCharCode(parseInt(i,10));break;case"d":case"i":i=parseInt(i,10);break;case"j":i=JSON.stringify(i,null,s.width?parseInt(s.width):0);break;case"e":i=s.precision?parseFloat(i).toExponential(s.precision):parseFloat(i).toExponential();break;case"f":i=s.precision?parseFloat(i).toFixed(s.precision):parseFloat(i);break;case"g":i=s.precision?String(Number(i.toPrecision(s.precision))):parseFloat(i);break;case"o":i=(parseInt(i,10)>>>0).toString(8);break;case"s":i=String(i),i=s.precision?i.substring(0,s.precision):i;break;case"t":i=String(!!i),i=s.precision?i.substring(0,s.precision):i;break;case"T":i=Object.prototype.toString.call(i).slice(8,-1).toLowerCase(),i=s.precision?i.substring(0,s.precision):i;break;case"u":i=parseInt(i,10)>>>0;break;case"v":i=i.valueOf(),i=s.precision?i.substring(0,s.precision):i;break;case"x":i=(parseInt(i,10)>>>0).toString(16);break;case"X":i=(parseInt(i,10)>>>0).toString(16).toUpperCase()}t.json.test(s.type)?m+=i:(!t.number.test(s.type)||f&&!s.sign?h="":(h=f?"+":"-",i=i.toString().replace(t.sign,"")),c=s.pad_char?"0"===s.pad_char?"0":s.pad_char.charAt(1):" ",u=s.width-(h+i).length,l=s.width&&u>0?c.repeat(u):"",m+=s.align?h+i+l:"0"===c?h+l+i:l+h+i)}return m}var a=Object.create(null);function o(e){if(a[e])return a[e];for(var r,n=e,i=[],o=0;n;){if(null!==(r=t.text.exec(n)))i.push(r[0]);else if(null!==(r=t.modulo.exec(n)))i.push("%");else{if(null===(r=t.placeholder.exec(n)))throw new SyntaxError("[sprintf] unexpected placeholder");if(r[2]){o|=1;var s=[],l=r[2],c=[];if(null===(c=t.key.exec(l)))throw new SyntaxError("[sprintf] failed to parse named argument key");for(s.push(c[1]);""!==(l=l.substring(c[0].length));)if(null!==(c=t.key_access.exec(l)))s.push(c[1]);else{if(null===(c=t.index_access.exec(l)))throw new SyntaxError("[sprintf] failed to parse named argument key");s.push(c[1])}r[2]=s}else o|=2;if(3===o)throw new Error("[sprintf] mixing positional and named placeholders is not (yet) supported");i.push({placeholder:r[0],param_no:r[1],keys:r[2],sign:r[3],pad_char:r[4],align:r[5],width:r[6],precision:r[7],type:r[8]})}n=n.substring(r[0].length)}return a[e]=i}void 0!==r&&(r.sprintf=e,r.vsprintf=n),"undefined"!=typeof window&&(window.sprintf=e,window.vsprintf=n)}()},{}],302:[function(t,e,r){"use strict";e.exports=function(t,e){if(t.dimension<=0)return{positions:[],cells:[]};if(1===t.dimension)return function(t,e){for(var r=i(t,e),n=r.length,a=new Array(n),o=new Array(n),s=0;sn|0},vertex:function(t,e,r,n,i,a,o,s,l,c,u,f,h){var p=(o<<0)+(s<<1)+(l<<2)+(c<<3)|0;if(0!==p&&15!==p)switch(p){case 0:u.push([t-.5,e-.5]);break;case 1:u.push([t-.25-.25*(n+r-2*h)/(r-n),e-.25-.25*(i+r-2*h)/(r-i)]);break;case 2:u.push([t-.75-.25*(-n-r+2*h)/(n-r),e-.25-.25*(a+n-2*h)/(n-a)]);break;case 3:u.push([t-.5,e-.5-.5*(i+r+a+n-4*h)/(r-i+n-a)]);break;case 4:u.push([t-.25-.25*(a+i-2*h)/(i-a),e-.75-.25*(-i-r+2*h)/(i-r)]);break;case 5:u.push([t-.5-.5*(n+r+a+i-4*h)/(r-n+i-a),e-.5]);break;case 6:u.push([t-.5-.25*(-n-r+a+i)/(n-r+i-a),e-.5-.25*(-i-r+a+n)/(i-r+n-a)]);break;case 7:u.push([t-.75-.25*(a+i-2*h)/(i-a),e-.75-.25*(a+n-2*h)/(n-a)]);break;case 8:u.push([t-.75-.25*(-a-i+2*h)/(a-i),e-.75-.25*(-a-n+2*h)/(a-n)]);break;case 9:u.push([t-.5-.25*(n+r+-a-i)/(r-n+a-i),e-.5-.25*(i+r+-a-n)/(r-i+a-n)]);break;case 10:u.push([t-.5-.5*(-n-r-a-i+4*h)/(n-r+a-i),e-.5]);break;case 11:u.push([t-.25-.25*(-a-i+2*h)/(a-i),e-.75-.25*(i+r-2*h)/(r-i)]);break;case 12:u.push([t-.5,e-.5-.5*(-i-r-a-n+4*h)/(i-r+a-n)]);break;case 13:u.push([t-.75-.25*(n+r-2*h)/(r-n),e-.25-.25*(-a-n+2*h)/(a-n)]);break;case 14:u.push([t-.25-.25*(-n-r+2*h)/(n-r),e-.25-.25*(-i-r+2*h)/(i-r)]);break;case 15:u.push([t-.5,e-.5])}},cell:function(t,e,r,n,i,a,o,s,l){i?s.push([t,e]):s.push([e,t])}});return function(t,e){var r=[],i=[];return n(t,r,i,e),{positions:r,cells:i}}}};var o={}},{"ndarray-extract-contour":251,"zero-crossings":318}],303:[function(t,e,r){(function(r){(function(){"use strict";e.exports=function t(e,r,i){i=i||{};var o=a[e];o||(o=a[e]={" ":{data:new Float32Array(0),shape:.2}});var s=o[r];if(!s)if(r.length<=1||!/\d/.test(r))s=o[r]=function(t){for(var e=t.cells,r=t.positions,n=new Float32Array(6*e.length),i=0,a=0,o=0;o0&&(f+=.02);var p=new Float32Array(u),d=0,m=-.5*f;for(h=0;hMath.max(r,n)?i[2]=1:r>Math.max(e,n)?i[0]=1:i[1]=1;for(var a=0,o=0,l=0;l<3;++l)a+=t[l]*t[l],o+=i[l]*t[l];for(l=0;l<3;++l)i[l]-=o/a*t[l];return s(i,i),i}function h(t,e,r,i,a,o,s,l){this.center=n(r),this.up=n(i),this.right=n(a),this.radius=n([o]),this.angle=n([s,l]),this.angle.bounds=[[-1/0,-Math.PI/2],[1/0,Math.PI/2]],this.setDistanceLimits(t,e),this.computedCenter=this.center.curve(0),this.computedUp=this.up.curve(0),this.computedRight=this.right.curve(0),this.computedRadius=this.radius.curve(0),this.computedAngle=this.angle.curve(0),this.computedToward=[0,0,0],this.computedEye=[0,0,0],this.computedMatrix=new Array(16);for(var c=0;c<16;++c)this.computedMatrix[c]=.5;this.recalcMatrix(0)}var p=h.prototype;p.setDistanceLimits=function(t,e){t=t>0?Math.log(t):-1/0,e=e>0?Math.log(e):1/0,e=Math.max(e,t),this.radius.bounds[0][0]=t,this.radius.bounds[1][0]=e},p.getDistanceLimits=function(t){var e=this.radius.bounds[0];return t?(t[0]=Math.exp(e[0][0]),t[1]=Math.exp(e[1][0]),t):[Math.exp(e[0][0]),Math.exp(e[1][0])]},p.recalcMatrix=function(t){this.center.curve(t),this.up.curve(t),this.right.curve(t),this.radius.curve(t),this.angle.curve(t);for(var e=this.computedUp,r=this.computedRight,n=0,i=0,a=0;a<3;++a)i+=e[a]*r[a],n+=e[a]*e[a];var l=Math.sqrt(n),u=0;for(a=0;a<3;++a)r[a]-=e[a]*i/n,u+=r[a]*r[a],e[a]/=l;var f=Math.sqrt(u);for(a=0;a<3;++a)r[a]/=f;var h=this.computedToward;o(h,e,r),s(h,h);var p=Math.exp(this.computedRadius[0]),d=this.computedAngle[0],m=this.computedAngle[1],g=Math.cos(d),v=Math.sin(d),y=Math.cos(m),x=Math.sin(m),b=this.computedCenter,_=g*y,w=v*y,T=x,k=-g*x,A=-v*x,M=y,S=this.computedEye,E=this.computedMatrix;for(a=0;a<3;++a){var L=_*r[a]+w*h[a]+T*e[a];E[4*a+1]=k*r[a]+A*h[a]+M*e[a],E[4*a+2]=L,E[4*a+3]=0}var C=E[1],P=E[5],I=E[9],O=E[2],z=E[6],D=E[10],R=P*D-I*z,F=I*O-C*D,B=C*z-P*O,N=c(R,F,B);R/=N,F/=N,B/=N,E[0]=R,E[4]=F,E[8]=B;for(a=0;a<3;++a)S[a]=b[a]+E[2+4*a]*p;for(a=0;a<3;++a){u=0;for(var j=0;j<3;++j)u+=E[a+4*j]*S[j];E[12+a]=-u}E[15]=1},p.getMatrix=function(t,e){this.recalcMatrix(t);var r=this.computedMatrix;if(e){for(var n=0;n<16;++n)e[n]=r[n];return e}return r};var d=[0,0,0];p.rotate=function(t,e,r,n){if(this.angle.move(t,e,r),n){this.recalcMatrix(t);var i=this.computedMatrix;d[0]=i[2],d[1]=i[6],d[2]=i[10];for(var o=this.computedUp,s=this.computedRight,l=this.computedToward,c=0;c<3;++c)i[4*c]=o[c],i[4*c+1]=s[c],i[4*c+2]=l[c];a(i,i,n,d);for(c=0;c<3;++c)o[c]=i[4*c],s[c]=i[4*c+1];this.up.set(t,o[0],o[1],o[2]),this.right.set(t,s[0],s[1],s[2])}},p.pan=function(t,e,r,n){e=e||0,r=r||0,n=n||0,this.recalcMatrix(t);var i=this.computedMatrix,a=(Math.exp(this.computedRadius[0]),i[1]),o=i[5],s=i[9],l=c(a,o,s);a/=l,o/=l,s/=l;var u=i[0],f=i[4],h=i[8],p=u*a+f*o+h*s,d=c(u-=a*p,f-=o*p,h-=s*p),m=(u/=d)*e+a*r,g=(f/=d)*e+o*r,v=(h/=d)*e+s*r;this.center.move(t,m,g,v);var y=Math.exp(this.computedRadius[0]);y=Math.max(1e-4,y+n),this.radius.set(t,Math.log(y))},p.translate=function(t,e,r,n){this.center.move(t,e||0,r||0,n||0)},p.setMatrix=function(t,e,r,n){var a=1;"number"==typeof r&&(a=0|r),(a<0||a>3)&&(a=1);var o=(a+2)%3;e||(this.recalcMatrix(t),e=this.computedMatrix);var s=e[a],l=e[a+4],f=e[a+8];if(n){var h=Math.abs(s),p=Math.abs(l),d=Math.abs(f),m=Math.max(h,p,d);h===m?(s=s<0?-1:1,l=f=0):d===m?(f=f<0?-1:1,s=l=0):(l=l<0?-1:1,s=f=0)}else{var g=c(s,l,f);s/=g,l/=g,f/=g}var v,y,x=e[o],b=e[o+4],_=e[o+8],w=x*s+b*l+_*f,T=c(x-=s*w,b-=l*w,_-=f*w),k=l*(_/=T)-f*(b/=T),A=f*(x/=T)-s*_,M=s*b-l*x,S=c(k,A,M);if(k/=S,A/=S,M/=S,this.center.jump(t,q,G,Y),this.radius.idle(t),this.up.jump(t,s,l,f),this.right.jump(t,x,b,_),2===a){var E=e[1],L=e[5],C=e[9],P=E*x+L*b+C*_,I=E*k+L*A+C*M;v=R<0?-Math.PI/2:Math.PI/2,y=Math.atan2(I,P)}else{var O=e[2],z=e[6],D=e[10],R=O*s+z*l+D*f,F=O*x+z*b+D*_,B=O*k+z*A+D*M;v=Math.asin(u(R)),y=Math.atan2(B,F)}this.angle.jump(t,y,v),this.recalcMatrix(t);var N=e[2],j=e[6],U=e[10],V=this.computedMatrix;i(V,e);var H=V[15],q=V[12]/H,G=V[13]/H,Y=V[14]/H,W=Math.exp(this.computedRadius[0]);this.center.jump(t,q-N*W,G-j*W,Y-U*W)},p.lastT=function(){return Math.max(this.center.lastT(),this.up.lastT(),this.right.lastT(),this.radius.lastT(),this.angle.lastT())},p.idle=function(t){this.center.idle(t),this.up.idle(t),this.right.idle(t),this.radius.idle(t),this.angle.idle(t)},p.flush=function(t){this.center.flush(t),this.up.flush(t),this.right.flush(t),this.radius.flush(t),this.angle.flush(t)},p.setDistance=function(t,e){e>0&&this.radius.set(t,Math.log(e))},p.lookAt=function(t,e,r,n){this.recalcMatrix(t),e=e||this.computedEye,r=r||this.computedCenter;var i=(n=n||this.computedUp)[0],a=n[1],o=n[2],s=c(i,a,o);if(!(s<1e-6)){i/=s,a/=s,o/=s;var l=e[0]-r[0],f=e[1]-r[1],h=e[2]-r[2],p=c(l,f,h);if(!(p<1e-6)){l/=p,f/=p,h/=p;var d=this.computedRight,m=d[0],g=d[1],v=d[2],y=i*m+a*g+o*v,x=c(m-=y*i,g-=y*a,v-=y*o);if(!(x<.01&&(x=c(m=a*h-o*f,g=o*l-i*h,v=i*f-a*l))<1e-6)){m/=x,g/=x,v/=x,this.up.set(t,i,a,o),this.right.set(t,m,g,v),this.center.set(t,r[0],r[1],r[2]),this.radius.set(t,Math.log(p));var b=a*v-o*g,_=o*m-i*v,w=i*g-a*m,T=c(b,_,w),k=i*l+a*f+o*h,A=m*l+g*f+v*h,M=(b/=T)*l+(_/=T)*f+(w/=T)*h,S=Math.asin(u(k)),E=Math.atan2(M,A),L=this.angle._state,C=L[L.length-1],P=L[L.length-2];C%=2*Math.PI;var I=Math.abs(C+2*Math.PI-E),O=Math.abs(C-E),z=Math.abs(C-2*Math.PI-E);I0?r.pop():new ArrayBuffer(t)}function d(t){return new Uint8Array(p(t),0,t)}function m(t){return new Uint16Array(p(2*t),0,t)}function g(t){return new Uint32Array(p(4*t),0,t)}function v(t){return new Int8Array(p(t),0,t)}function y(t){return new Int16Array(p(2*t),0,t)}function x(t){return new Int32Array(p(4*t),0,t)}function b(t){return new Float32Array(p(4*t),0,t)}function _(t){return new Float64Array(p(8*t),0,t)}function w(t){return o?new Uint8ClampedArray(p(t),0,t):d(t)}function T(t){return s?new BigUint64Array(p(8*t),0,t):null}function k(t){return l?new BigInt64Array(p(8*t),0,t):null}function A(t){return new DataView(p(t),0,t)}function M(t){t=n.nextPow2(t);var e=n.log2(t),r=f[e];return r.length>0?r.pop():new a(t)}r.free=function(t){if(a.isBuffer(t))f[n.log2(t.length)].push(t);else{if("[object ArrayBuffer]"!==Object.prototype.toString.call(t)&&(t=t.buffer),!t)return;var e=t.length||t.byteLength,r=0|n.log2(e);u[r].push(t)}},r.freeUint8=r.freeUint16=r.freeUint32=r.freeBigUint64=r.freeInt8=r.freeInt16=r.freeInt32=r.freeBigInt64=r.freeFloat32=r.freeFloat=r.freeFloat64=r.freeDouble=r.freeUint8Clamped=r.freeDataView=function(t){h(t.buffer)},r.freeArrayBuffer=h,r.freeBuffer=function(t){f[n.log2(t.length)].push(t)},r.malloc=function(t,e){if(void 0===e||"arraybuffer"===e)return p(t);switch(e){case"uint8":return d(t);case"uint16":return m(t);case"uint32":return g(t);case"int8":return v(t);case"int16":return y(t);case"int32":return x(t);case"float":case"float32":return b(t);case"double":case"float64":return _(t);case"uint8_clamped":return w(t);case"bigint64":return k(t);case"biguint64":return T(t);case"buffer":return M(t);case"data":case"dataview":return A(t);default:return null}return null},r.mallocArrayBuffer=p,r.mallocUint8=d,r.mallocUint16=m,r.mallocUint32=g,r.mallocInt8=v,r.mallocInt16=y,r.mallocInt32=x,r.mallocFloat32=r.mallocFloat=b,r.mallocFloat64=r.mallocDouble=_,r.mallocUint8Clamped=w,r.mallocBigUint64=T,r.mallocBigInt64=k,r.mallocDataView=A,r.mallocBuffer=M,r.clearCache=function(){for(var t=0;t<32;++t)c.UINT8[t].length=0,c.UINT16[t].length=0,c.UINT32[t].length=0,c.INT8[t].length=0,c.INT16[t].length=0,c.INT32[t].length=0,c.FLOAT[t].length=0,c.DOUBLE[t].length=0,c.BIGUINT64[t].length=0,c.BIGINT64[t].length=0,c.UINT8C[t].length=0,u[t].length=0,f[t].length=0}}).call(this)}).call(this,void 0!==n?n:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"bit-twiddle":32,buffer:3,dup:65}],309:[function(t,e,r){"use strict";function n(t){this.roots=new Array(t),this.ranks=new Array(t);for(var e=0;e0&&(a=n.size),n.lineSpacing&&n.lineSpacing>0&&(o=n.lineSpacing),n.styletags&&n.styletags.breaklines&&(s.breaklines=!!n.styletags.breaklines),n.styletags&&n.styletags.bolds&&(s.bolds=!!n.styletags.bolds),n.styletags&&n.styletags.italics&&(s.italics=!!n.styletags.italics),n.styletags&&n.styletags.subscripts&&(s.subscripts=!!n.styletags.subscripts),n.styletags&&n.styletags.superscripts&&(s.superscripts=!!n.styletags.superscripts));return r.font=[n.fontStyle,n.fontVariant,n.fontWeight,a+"px",n.font].filter((function(t){return t})).join(" "),r.textAlign="start",r.textBaseline="alphabetic",r.direction="ltr",h(function(t,e,r,n,a,o){r=r.replace(/\n/g,""),r=!0===o.breaklines?r.replace(/\/g,"\n"):r.replace(/\/g," ");var s="",l=[];for(p=0;p-1?parseInt(t[1+i]):0,l=a>-1?parseInt(r[1+a]):0;s!==l&&(n=n.replace(S(),"?px "),g*=Math.pow(.75,l-s),n=n.replace("?px ",S())),m+=.25*x*(l-s)}if(!0===o.superscripts){var c=t.indexOf("+"),u=r.indexOf("+"),f=c>-1?parseInt(t[1+c]):0,h=u>-1?parseInt(r[1+u]):0;f!==h&&(n=n.replace(S(),"?px "),g*=Math.pow(.75,h-f),n=n.replace("?px ",S())),m-=.25*x*(h-f)}if(!0===o.bolds){var p=t.indexOf("b|")>-1,d=r.indexOf("b|")>-1;!p&&d&&(n=v?n.replace("italic ","italic bold "):"bold "+n),p&&!d&&(n=n.replace("bold ",""))}if(!0===o.italics){var v=t.indexOf("i|")>-1,y=r.indexOf("i|")>-1;!v&&y&&(n="italic "+n),v&&!y&&(n=n.replace("italic ",""))}e.font=n}for(h=0;h",a="",o=i.length,s=a.length,l="+"===e[0]||"-"===e[0],c=0,u=-s;c>-1&&-1!==(c=r.indexOf(i,c))&&-1!==(u=r.indexOf(a,c+o))&&!(u<=c);){for(var f=c;f=u)n[f]=null,r=r.substr(0,f)+" "+r.substr(f+1);else if(null!==n[f]){var h=n[f].indexOf(e[0]);-1===h?n[f]+=e:l&&(n[f]=n[f].substr(0,h+1)+(1+parseInt(n[f][h+1]))+n[f].substr(h+2))}var p=c+o,d=r.substr(p,u-p).indexOf(i);c=-1!==d?d:u+s}return n}function u(t,e){var r=n(t,128);return e?a(r.cells,r.positions,.25):{edges:r.cells,positions:r.positions}}function f(t,e,r,n){var i=u(t,n),a=function(t,e,r){for(var n=e.textAlign||"start",i=e.textBaseline||"alphabetic",a=[1<<30,1<<30],o=[0,0],s=t.length,l=0;l=0?e[a]:i}))},has___:{value:y((function(e){var n=v(e);return n?r in n:t.indexOf(e)>=0}))},set___:{value:y((function(n,i){var a,o=v(n);return o?o[r]=i:(a=t.indexOf(n))>=0?e[a]=i:(a=t.length,e[a]=i,t[a]=n),this}))},delete___:{value:y((function(n){var i,a,o=v(n);return o?r in o&&delete o[r]:!((i=t.indexOf(n))<0)&&(a=t.length-1,t[i]=void 0,e[i]=e[a],t[i]=t[a],t.length=a,e.length=a,!0)}))}})};d.prototype=Object.create(Object.prototype,{get:{value:function(t,e){return this.get___(t,e)},writable:!0,configurable:!0},has:{value:function(t){return this.has___(t)},writable:!0,configurable:!0},set:{value:function(t,e){return this.set___(t,e)},writable:!0,configurable:!0},delete:{value:function(t){return this.delete___(t)},writable:!0,configurable:!0}}),"function"==typeof r?function(){function n(){this instanceof d||x();var e,n=new r,i=void 0,a=!1;return e=t?function(t,e){return n.set(t,e),n.has(t)||(i||(i=new d),i.set(t,e)),this}:function(t,e){if(a)try{n.set(t,e)}catch(r){i||(i=new d),i.set___(t,e)}else n.set(t,e);return this},Object.create(d.prototype,{get___:{value:y((function(t,e){return i?n.has(t)?n.get(t):i.get___(t,e):n.get(t,e)}))},has___:{value:y((function(t){return n.has(t)||!!i&&i.has___(t)}))},set___:{value:y(e)},delete___:{value:y((function(t){var e=!!n.delete(t);return i&&i.delete___(t)||e}))},permitHostObjects___:{value:y((function(t){if(t!==m)throw new Error("bogus call to permitHostObjects___");a=!0}))}})}t&&"undefined"!=typeof Proxy&&(Proxy=void 0),n.prototype=d.prototype,e.exports=n,Object.defineProperty(WeakMap.prototype,"constructor",{value:WeakMap,enumerable:!1,configurable:!0,writable:!0})}():("undefined"!=typeof Proxy&&(Proxy=void 0),e.exports=d)}function m(t){t.permitHostObjects___&&t.permitHostObjects___(m)}function g(t){return!("weakmap:"==t.substr(0,"weakmap:".length)&&"___"===t.substr(t.length-3))}function v(t){if(t!==Object(t))throw new TypeError("Not an object: "+t);var e=t[l];if(e&&e.key===t)return e;if(s(t)){e={key:t};try{return o(t,l,{value:e,writable:!1,enumerable:!1,configurable:!1}),e}catch(t){return}}}function y(t){return t.prototype=null,Object.freeze(t)}function x(){h||"undefined"==typeof console||(h=!0,console.warn("WeakMap should be invoked as new WeakMap(), not WeakMap(). This will be an error in the future."))}}()},{}],314:[function(t,e,r){var n=t("./hidden-store.js");e.exports=function(){var t={};return function(e){if(("object"!=typeof e||null===e)&&"function"!=typeof e)throw new Error("Weakmap-shim: Key must be object");var r=e.valueOf(t);return r&&r.identity===t?r:n(e,t)}}},{"./hidden-store.js":315}],315:[function(t,e,r){e.exports=function(t,e){var r={identity:e},n=t.valueOf;return Object.defineProperty(t,"valueOf",{value:function(t){return t!==e?n.apply(this,arguments):r},writable:!0}),r}},{}],316:[function(t,e,r){var n=t("./create-store.js");e.exports=function(){var t=n();return{get:function(e,r){var n=t(e);return n.hasOwnProperty("value")?n.value:r},set:function(e,r){return t(e).value=r,this},has:function(e){return"value"in t(e)},delete:function(e){return delete t(e).value}}}},{"./create-store.js":314}],317:[function(t,e,r){"use strict";var n,i=function(){return function(t,e,r,n,i,a){var o=t[0],s=r[0],l=[0],c=s;n|=0;var u=0,f=s;for(u=0;u=0!=p>=0&&i.push(l[0]+.5+.5*(h+p)/(h-p)),n+=f,++l[0]}}};e.exports=(n={funcName:{funcName:"zeroCrossings"}.funcName},function(t){var e={};return function(r,n,i){var a=r.dtype,o=r.order,s=[a,o.join()].join(),l=e[s];return l||(e[s]=l=t([a,o])),l(r.shape.slice(0),r.data,r.stride,0|r.offset,n,i)}}(i.bind(void 0,n)))},{}],318:[function(t,e,r){"use strict";e.exports=function(t,e){var r=[];return e=+e||0,n(t.hi(t.shape[0]-1),r,e),r};var n=t("./lib/zc-core")},{"./lib/zc-core":317}]},{},[6])(6)}))}).call(this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[27])(27)})); diff --git a/hardware-testing/hardware_testing/tools/plot/server.py b/hardware-testing/hardware_testing/tools/plot/server.py index b3bda88917f..72149fc959f 100644 --- a/hardware-testing/hardware_testing/tools/plot/server.py +++ b/hardware-testing/hardware_testing/tools/plot/server.py @@ -2,6 +2,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer import json from pathlib import Path +from time import time from typing import List, Any from hardware_testing.data import create_folder_for_test_data @@ -67,8 +68,9 @@ def _list_file_paths_in_directory( for sub_p in sub_dir_paths: _ret.append(sub_p) # sort newest to oldest - _ret.sort(key=lambda f: f.stem) # name includes timestamp - _ret.reverse() + # NOTE: system time on machines in SZ will randomly switch to the wrong time + # so here we can sort relative to whatever the current system time is + _ret.sort(key=lambda f: abs(time() - f.stat().st_mtime)) return _ret def _respond_to_data_request(self) -> None: From 815ab8e4ec1192c2e66b378ba6d0e1c25025f64a Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:16:14 -0400 Subject: [PATCH 31/65] fix(protocol-designer): loadName in loadLabware is now true loadName (#13903) addressing RESC-161 --- protocol-designer/src/load-file/migration/7_0_0.ts | 6 ++++-- .../src/load-file/migration/__tests__/7_0_0.test.ts | 7 +++---- protocol-designer/src/step-forms/reducers/index.ts | 6 ++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/protocol-designer/src/load-file/migration/7_0_0.ts b/protocol-designer/src/load-file/migration/7_0_0.ts index b3d61ef0466..c1d88c264fb 100644 --- a/protocol-designer/src/load-file/migration/7_0_0.ts +++ b/protocol-designer/src/load-file/migration/7_0_0.ts @@ -173,7 +173,9 @@ export const migrateFile = ( .map(command => { const labwareId = command.params.labwareId const definitionId = labware[labwareId].definitionId - const { namespace, version } = labwareDefinitions[definitionId] + const { namespace, version, parameters } = labwareDefinitions[ + definitionId + ] const labwareLocation = command.params.location let location: LabwareLocation = 'offDeck' if (labwareLocation === 'offDeck') { @@ -188,7 +190,7 @@ export const migrateFile = ( ...command, params: { ...command.params, - loadName: definitionId, + loadName: parameters.loadName, namespace, version, location, diff --git a/protocol-designer/src/load-file/migration/__tests__/7_0_0.test.ts b/protocol-designer/src/load-file/migration/__tests__/7_0_0.test.ts index 4044825af70..b5c13c2af97 100644 --- a/protocol-designer/src/load-file/migration/__tests__/7_0_0.test.ts +++ b/protocol-designer/src/load-file/migration/__tests__/7_0_0.test.ts @@ -69,7 +69,7 @@ describe('v7 migration', () => { '0b44c760-75c7-11ea-b42f-4b64e50f43e5:opentrons/opentrons_96_tiprack_300ul/1', location: { slotName: '2' }, displayName: 'Opentrons 96 Tip Rack 300 µL', - loadName: 'opentrons/opentrons_96_tiprack_300ul/1', + loadName: 'opentrons_96_tiprack_300ul', namespace: 'opentrons', version: 1, }, @@ -84,7 +84,7 @@ describe('v7 migration', () => { moduleId: '0b419310-75c7-11ea-b42f-4b64e50f43e5:magneticModuleType', }, displayName: 'NEST 96 Well Plate 100 µL PCR Full Skirt', - loadName: 'opentrons/nest_96_wellplate_100ul_pcr_full_skirt/1', + loadName: 'nest_96_wellplate_100ul_pcr_full_skirt', namespace: 'opentrons', version: 1, }, @@ -101,8 +101,7 @@ describe('v7 migration', () => { }, namespace: 'opentrons', version: 1, - loadName: - 'opentrons/opentrons_24_aluminumblock_generic_2ml_screwcap/1', + loadName: 'opentrons_24_aluminumblock_generic_2ml_screwcap', displayName: 'Opentrons 24 Well Aluminum Block with Generic 2 mL Screwcap', }, diff --git a/protocol-designer/src/step-forms/reducers/index.ts b/protocol-designer/src/step-forms/reducers/index.ts index 82e0021ea29..87153305e6a 100644 --- a/protocol-designer/src/step-forms/reducers/index.ts +++ b/protocol-designer/src/step-forms/reducers/index.ts @@ -92,6 +92,7 @@ import type { EditProfileStepAction, FormPatch, } from '../../steplist/actions' +import { import type { FormData, StepIdType, @@ -1162,6 +1163,11 @@ export const labwareInvariantProperties: Reducer< labwareDef.namespace === namespace && labwareDef.version === version ) + if (labwareDefinitionMatch == null) { + console.error( + `expected to find labware definition match with loadname ${loadName} but could not` + ) + } const labwareDefURI = labwareDefinitionMatch != null ? labwareDefinitionMatch[0] : '' const id = labwareId ?? '' From cc160b8ebaa41b7d7e30840fac6801f88f12a6dd Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Fri, 3 Nov 2023 17:26:42 -0400 Subject: [PATCH 32/65] fix(protocol-designer): moving labware onto an adapter on the deck (#13914) closes RAUT-847 --- .../top-selectors/labware-locations/index.ts | 1 - .../src/commandCreators/atomic/moveLabware.ts | 52 ++++++++----------- 2 files changed, 21 insertions(+), 32 deletions(-) diff --git a/protocol-designer/src/top-selectors/labware-locations/index.ts b/protocol-designer/src/top-selectors/labware-locations/index.ts index 5db5f8f7509..1ef2640b018 100644 --- a/protocol-designer/src/top-selectors/labware-locations/index.ts +++ b/protocol-designer/src/top-selectors/labware-locations/index.ts @@ -132,7 +132,6 @@ export const getUnocuppiedLabwareLocationOptions: Selector< const labwareOnAdapter = Object.values(labware).find( temporalProperties => temporalProperties.slot === labwareId ) - const adapterSlot = labwareOnDeck.slot const modIdWithAdapter = Object.keys(modules).find( modId => modId === labwareOnDeck.slot diff --git a/step-generation/src/commandCreators/atomic/moveLabware.ts b/step-generation/src/commandCreators/atomic/moveLabware.ts index 3c7c414d0e8..d14814fa3b0 100644 --- a/step-generation/src/commandCreators/atomic/moveLabware.ts +++ b/step-generation/src/commandCreators/atomic/moveLabware.ts @@ -87,45 +87,35 @@ export const moveLabware: CommandCreator = ( newLocation !== 'offDeck' && 'labwareId' in newLocation ? newLocation.labwareId : null - const destModuleIdUnderAdapter = + + const destModuleOrSlotUnderAdapterId = destAdapterId != null ? prevRobotState.labware[destAdapterId].slot : null - const destinationModuleId = - destModuleIdUnderAdapter != null ? destModuleIdUnderAdapter : destModuleId + const destinationModuleIdOrSlot = + destModuleOrSlotUnderAdapterId != null + ? destModuleOrSlotUnderAdapterId + : destModuleId if (newLocation === 'offDeck' && useGripper) { errors.push(errorCreators.labwareOffDeck()) } - if ( - tiprackHasTip && - newLocationInWasteChute && - getHasWasteChute(additionalEquipmentEntities) - ) { - warnings.push(warningCreators.tiprackInWasteChuteHasTips()) - } else if ( - labwareHasLiquid && - newLocationInWasteChute && - getHasWasteChute(additionalEquipmentEntities) + destinationModuleIdOrSlot != null && + prevRobotState.modules[destinationModuleIdOrSlot] != null ) { - warnings.push(warningCreators.labwareInWasteChuteHasLiquid()) - } - - if (destinationModuleId != null) { const destModuleState = - prevRobotState.modules[destinationModuleId]?.moduleState ?? null - if (destModuleState != null) { - if ( - destModuleState.type === THERMOCYCLER_MODULE_TYPE && - destModuleState.lidOpen !== true - ) { - errors.push(errorCreators.thermocyclerLidClosed()) - } else if (destModuleState.type === HEATERSHAKER_MODULE_TYPE) { - if (destModuleState.latchOpen !== true) { - errors.push(errorCreators.heaterShakerLatchClosed()) - } - if (destModuleState.targetSpeed !== null) { - errors.push(errorCreators.heaterShakerIsShaking()) - } + prevRobotState.modules[destinationModuleIdOrSlot].moduleState + + if ( + destModuleState.type === THERMOCYCLER_MODULE_TYPE && + destModuleState.lidOpen !== true + ) { + errors.push(errorCreators.thermocyclerLidClosed()) + } else if (destModuleState.type === HEATERSHAKER_MODULE_TYPE) { + if (destModuleState.latchOpen !== true) { + errors.push(errorCreators.heaterShakerLatchClosed()) + } + if (destModuleState.targetSpeed !== null) { + errors.push(errorCreators.heaterShakerIsShaking()) } } } From bc63525bb783a3b17b8950af6980fe3db4640941 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Wed, 8 Nov 2023 14:32:48 -0500 Subject: [PATCH 33/65] feat(robot-server): Add HTTP endpoints for getting and setting the robot's deck configuration (#13894) Adds placeholder implementations of two new HTTP endpoints PUT /deck_configuration and GET /deck_configuration --- .../deck_configuration/__init__.py | 1 + .../fastapi_dependencies.py | 27 +++ .../robot_server/deck_configuration/models.py | 64 ++++++ .../robot_server/deck_configuration/router.py | 96 +++++++++ .../robot_server/deck_configuration/store.py | 28 +++ .../deck_configuration/validation.py | 114 +++++++++++ .../deck_configuration/validation_mapping.py | 39 ++++ robot-server/robot_server/hardware.py | 9 + .../robot_server/persistence/__init__.py | 2 +- robot-server/robot_server/router.py | 30 ++- .../deck_configuration/test_validation.py | 190 ++++++++++++++++++ robot-server/tests/integration/conftest.py | 1 + .../test_deck_configuration.tavern.yaml | 110 ++++++++++ 13 files changed, 699 insertions(+), 12 deletions(-) create mode 100644 robot-server/robot_server/deck_configuration/__init__.py create mode 100644 robot-server/robot_server/deck_configuration/fastapi_dependencies.py create mode 100644 robot-server/robot_server/deck_configuration/models.py create mode 100644 robot-server/robot_server/deck_configuration/router.py create mode 100644 robot-server/robot_server/deck_configuration/store.py create mode 100644 robot-server/robot_server/deck_configuration/validation.py create mode 100644 robot-server/robot_server/deck_configuration/validation_mapping.py create mode 100644 robot-server/tests/deck_configuration/test_validation.py create mode 100644 robot-server/tests/integration/http_api/test_deck_configuration.tavern.yaml diff --git a/robot-server/robot_server/deck_configuration/__init__.py b/robot-server/robot_server/deck_configuration/__init__.py new file mode 100644 index 00000000000..13bacaf8a4d --- /dev/null +++ b/robot-server/robot_server/deck_configuration/__init__.py @@ -0,0 +1 @@ +"""The HTTP API, and supporting code, for getting and setting the robot's deck configuration.""" diff --git a/robot-server/robot_server/deck_configuration/fastapi_dependencies.py b/robot-server/robot_server/deck_configuration/fastapi_dependencies.py new file mode 100644 index 00000000000..aef59d60548 --- /dev/null +++ b/robot-server/robot_server/deck_configuration/fastapi_dependencies.py @@ -0,0 +1,27 @@ +"""Dependency functions for use with `fastapi.Depends()`.""" + + +import fastapi +from server_utils.fastapi_utils.app_state import ( + AppState, + AppStateAccessor, + get_app_state, +) + +from robot_server.deck_configuration.store import DeckConfigurationStore + + +_accessor = AppStateAccessor[DeckConfigurationStore]("deck_configuration_store") + + +async def get_deck_configuration_store( + app_state: AppState = fastapi.Depends(get_app_state), +) -> DeckConfigurationStore: + """Return the server's singleton `DeckConfigurationStore`.""" + deck_configuration_store = _accessor.get_from(app_state) + if deck_configuration_store is None: + # If this initialization becomes async, we will need to protect it with a lock, + # to protect against the bug described in https://github.com/Opentrons/opentrons/pull/11927. + deck_configuration_store = DeckConfigurationStore() + _accessor.set_on(app_state, deck_configuration_store) + return deck_configuration_store diff --git a/robot-server/robot_server/deck_configuration/models.py b/robot-server/robot_server/deck_configuration/models.py new file mode 100644 index 00000000000..a0f2b6b7114 --- /dev/null +++ b/robot-server/robot_server/deck_configuration/models.py @@ -0,0 +1,64 @@ +"""HTTP-facing JSON models for deck configuration.""" + + +from datetime import datetime +from typing import List, Optional +from typing_extensions import Literal + +import pydantic + +from robot_server.errors import ErrorDetails + + +class CutoutFixture(pydantic.BaseModel): + """A single element of the robot's deck configuration.""" + + # These are deliberately typed as plain strs, instead of Enums or Literals, + # because we want shared-data to be the source of truth. + # + # The downside of this is that to use this HTTP interface, you need to be familiar with deck + # definitions. To make this better, we could perhaps autogenerate OpenAPI / JSON Schema spec + # fragments from shared-data and inject them here. + cutoutFixtureId: str = pydantic.Field( + description=( + "What kind of cutout fixture is mounted onto the deck." + " Valid values are the `id`s of `cutoutFixtures` in the" + " [deck definition](https://github.com/Opentrons/opentrons/tree/edge/shared-data/deck)." + ) + ) + cutoutId: str = pydantic.Field( + description=( + "Where on the deck this cutout fixture is mounted." + " Valid values are the `id`s of `cutouts` in the" + " [deck definition](https://github.com/Opentrons/opentrons/tree/edge/shared-data/deck)." + ) + ) + + +class DeckConfigurationRequest(pydantic.BaseModel): + """A request to set the robot's deck configuration.""" + + cutoutFixtures: List[CutoutFixture] = pydantic.Field( + description="A full list of all the cutout fixtures that are mounted onto the deck." + ) + + +class DeckConfigurationResponse(pydantic.BaseModel): + """A response for the robot's current deck configuration.""" + + cutoutFixtures: List[CutoutFixture] = pydantic.Field( + description="A full list of all the cutout fixtures that are mounted onto the deck." + ) + lastUpdatedAt: Optional[datetime] = pydantic.Field( + description=( + "When the deck configuration was last set over HTTP." + " If that has never happened, this will be `null` or omitted." + ) + ) + + +class InvalidDeckConfiguration(ErrorDetails): + """Error details for when a client supplies an invalid deck configuration.""" + + id: Literal["InvalidDeckConfiguration"] = "InvalidDeckConfiguration" + title: str = "Invalid Deck Configuration" diff --git a/robot-server/robot_server/deck_configuration/router.py b/robot-server/robot_server/deck_configuration/router.py new file mode 100644 index 00000000000..890ed5ba8cb --- /dev/null +++ b/robot-server/robot_server/deck_configuration/router.py @@ -0,0 +1,96 @@ +"""The HTTP API for getting and setting the robot's current deck configuration.""" + + +from datetime import datetime +from typing import Union + +import fastapi +from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY + +from opentrons_shared_data.deck.dev_types import DeckDefinitionV4 + +from robot_server.errors import ErrorBody +from robot_server.hardware import get_deck_definition +from robot_server.service.dependencies import get_current_time +from robot_server.service.json_api import PydanticResponse, RequestModel, SimpleBody + +from . import models +from . import validation +from . import validation_mapping +from .fastapi_dependencies import get_deck_configuration_store +from .store import DeckConfigurationStore + + +router = fastapi.APIRouter() + + +@router.put( + "/deck_configuration", + summary="Set the deck configuration", + description=( + "Inform the robot how its deck is physically set up." + "\n\n" + "When you use the `/runs` and `/maintenance_runs` endpoints to command the robot to move," + " the robot will automatically dodge the obstacles that you declare here." + "\n\n" + "If a run command tries to do something that inherently conflicts with this deck" + " configuration, such as loading a labware into a staging area slot that this deck" + " configuration doesn't provide, the run command will fail with an error." + "\n\n" + "After you set the deck configuration, it will persist, even across reboots," + " until you set it to something else." + ), + responses={ + fastapi.status.HTTP_200_OK: { + "model": SimpleBody[models.DeckConfigurationResponse] + }, + fastapi.status.HTTP_422_UNPROCESSABLE_ENTITY: { + "model": ErrorBody[models.InvalidDeckConfiguration] + }, + }, +) +async def put_deck_configuration( # noqa: D103 + request_body: RequestModel[models.DeckConfigurationRequest], + store: DeckConfigurationStore = fastapi.Depends(get_deck_configuration_store), + last_updated_at: datetime = fastapi.Depends(get_current_time), + deck_definition: DeckDefinitionV4 = fastapi.Depends(get_deck_definition), +) -> PydanticResponse[ + Union[ + SimpleBody[models.DeckConfigurationResponse], + ErrorBody[models.InvalidDeckConfiguration], + ] +]: + placements = validation_mapping.map_in(request_body.data) + validation_errors = validation.get_configuration_errors(deck_definition, placements) + if len(validation_errors) == 0: + success_data = await store.set(request_body.data, last_updated_at) + return await PydanticResponse.create( + content=SimpleBody.construct(data=success_data) + ) + else: + error_data = validation_mapping.map_out(validation_errors) + return await PydanticResponse.create( + content=ErrorBody.construct(errors=error_data), + status_code=HTTP_422_UNPROCESSABLE_ENTITY, + ) + + +@router.get( + "/deck_configuration", + summary="Get the deck configuration", + description=( + "Get the robot's current deck configuration." + " See `PUT /deck_configuration` for background information." + ), + responses={ + fastapi.status.HTTP_200_OK: { + "model": SimpleBody[models.DeckConfigurationResponse] + }, + }, +) +async def get_deck_configuration( # noqa: D103 + store: DeckConfigurationStore = fastapi.Depends(get_deck_configuration_store), +) -> PydanticResponse[SimpleBody[models.DeckConfigurationResponse]]: + return await PydanticResponse.create( + content=SimpleBody.construct(data=await store.get()) + ) diff --git a/robot-server/robot_server/deck_configuration/store.py b/robot-server/robot_server/deck_configuration/store.py new file mode 100644 index 00000000000..0bf63de3f06 --- /dev/null +++ b/robot-server/robot_server/deck_configuration/store.py @@ -0,0 +1,28 @@ +# noqa: D100 + +from datetime import datetime +from typing import List, Optional + +from . import models + + +class DeckConfigurationStore: + """An in-memory stand-in for a persistent store of the robot's deck configuration.""" + + def __init__(self) -> None: + self._cutoutFixtures: List[models.CutoutFixture] = [] + self._last_updated_at: Optional[datetime] = None + + async def set( + self, request: models.DeckConfigurationRequest, last_updated_at: datetime + ) -> models.DeckConfigurationResponse: + """Set the robot's current deck configuration.""" + self._cutoutFixtures = request.cutoutFixtures + self._last_updated_at = last_updated_at + return await self.get() + + async def get(self) -> models.DeckConfigurationResponse: + """Get the robot's current deck configuration.""" + return models.DeckConfigurationResponse.construct( + cutoutFixtures=self._cutoutFixtures, lastUpdatedAt=self._last_updated_at + ) diff --git a/robot-server/robot_server/deck_configuration/validation.py b/robot-server/robot_server/deck_configuration/validation.py new file mode 100644 index 00000000000..681ed4213df --- /dev/null +++ b/robot-server/robot_server/deck_configuration/validation.py @@ -0,0 +1,114 @@ +"""Validate a deck configuration.""" + + +from collections import defaultdict +from dataclasses import dataclass +from typing import DefaultDict, FrozenSet, List, Set, Tuple, Union + +from opentrons_shared_data.deck import dev_types as deck_types + + +@dataclass(frozen=True) +class Placement: + """A placement of a cutout fixture in a cutout.""" + + cutout_id: str + cutout_fixture_id: str + + +@dataclass(frozen=True) +class UnoccupiedCutoutError: + """When a cutout has been left empty--no cutout fixtures mounted to it.""" + + cutout_id: str + + +@dataclass(frozen=True) +class OvercrowdedCutoutError: + """When a cutout has had more than one cutout fixture mounted to it.""" + + cutout_id: str + cutout_fixture_ids: Tuple[str, ...] + """All the conflicting cutout fixtures, in input order.""" + + +@dataclass(frozen=True) +class InvalidLocationError: + """When a cutout fixture has been mounted somewhere it cannot be mounted.""" + + cutout_id: str + cutout_fixture_id: str + allowed_cutout_ids: FrozenSet[str] + + +@dataclass(frozen=True) +class UnrecognizedCutoutFixtureError: + """When an cutout has been mounted that's not defined by the deck definition.""" + + cutout_fixture_id: str + + +ConfigurationError = Union[ + UnoccupiedCutoutError, + OvercrowdedCutoutError, + InvalidLocationError, + UnrecognizedCutoutFixtureError, +] + + +def get_configuration_errors( + deck_definition: deck_types.DeckDefinitionV4, + placements: List[Placement], +) -> Set[ConfigurationError]: + """Return all the problems with the given deck configration. + + If there are no problems, return ``{}``. + """ + errors: Set[ConfigurationError] = set() + fixtures_by_cutout: DefaultDict[str, List[str]] = defaultdict(list) + + for placement in placements: + fixtures_by_cutout[placement.cutout_id].append(placement.cutout_fixture_id) + + expected_cutouts = set(c["id"] for c in deck_definition["locations"]["cutouts"]) + occupied_cutouts = set(fixtures_by_cutout.keys()) + errors.update( + UnoccupiedCutoutError(cutout_id) + for cutout_id in expected_cutouts - occupied_cutouts + ) + + for cutout, fixtures in fixtures_by_cutout.items(): + if len(fixtures) > 1: + errors.add(OvercrowdedCutoutError(cutout, tuple(fixtures))) + + for placement in placements: + found_cutout_fixture = _find_cutout_fixture( + deck_definition, placement.cutout_fixture_id + ) + if isinstance(found_cutout_fixture, UnrecognizedCutoutFixtureError): + errors.add(found_cutout_fixture) + else: + allowed_cutout_ids = frozenset(found_cutout_fixture["mayMountTo"]) + if placement.cutout_id not in allowed_cutout_ids: + errors.add( + InvalidLocationError( + cutout_id=placement.cutout_id, + cutout_fixture_id=placement.cutout_fixture_id, + allowed_cutout_ids=allowed_cutout_ids, + ) + ) + + return errors + + +def _find_cutout_fixture( + deck_definition: deck_types.DeckDefinitionV4, cutout_fixture_id: str +) -> Union[deck_types.CutoutFixture, UnrecognizedCutoutFixtureError]: + try: + return next( + cutout_fixture + for cutout_fixture in deck_definition["cutoutFixtures"] + if cutout_fixture["id"] == cutout_fixture_id + ) + except StopIteration: + return UnrecognizedCutoutFixtureError(cutout_fixture_id=cutout_fixture_id) diff --git a/robot-server/robot_server/deck_configuration/validation_mapping.py b/robot-server/robot_server/deck_configuration/validation_mapping.py new file mode 100644 index 00000000000..10d9b65158a --- /dev/null +++ b/robot-server/robot_server/deck_configuration/validation_mapping.py @@ -0,0 +1,39 @@ +"""Convert between internal types for validation and HTTP-exposed response models.""" + +import dataclasses +from typing import Iterable, List + +from . import models +from . import validation + + +def map_in(request: models.DeckConfigurationRequest) -> List[validation.Placement]: + """Map a request from HTTP to internal types that can be validated.""" + return [ + validation.Placement(cutout_id=p.cutoutId, cutout_fixture_id=p.cutoutFixtureId) + for p in request.cutoutFixtures + ] + + +def map_out( + validation_errors: Iterable[validation.ConfigurationError], +) -> List[models.InvalidDeckConfiguration]: + """Map internal results from validation to HTTP-exposed types.""" + return [_map_out_single_error(e) for e in validation_errors] + + +def _map_out_single_error( + error: validation.ConfigurationError, +) -> models.InvalidDeckConfiguration: + # Expose the error details in a developer-facing, kind of lazy way. + # This format isn't guaranteed by robot-server's HTTP API; + # it's just meant to help app developers debug their deck config requests. + meta = { + "deckConfigurationProblem": error.__class__.__name__, + # Note that this dataclasses.asdict() will break if the internal error + # that we're mapping from is ever not a dataclass. + **dataclasses.asdict(error), + } + return models.InvalidDeckConfiguration( + detail="Invalid deck configuration.", meta=meta + ) diff --git a/robot-server/robot_server/hardware.py b/robot-server/robot_server/hardware.py index 6af230bd9ff..760580fcef2 100644 --- a/robot-server/robot_server/hardware.py +++ b/robot-server/robot_server/hardware.py @@ -16,6 +16,8 @@ from uuid import uuid4 # direct to avoid import cycles in service.dependencies from traceback import format_exception_only, TracebackException from contextlib import contextmanager + +from opentrons_shared_data import deck from opentrons_shared_data.robot.dev_types import RobotType, RobotTypeEnum from opentrons import initialize as initialize_api, should_use_ot3 @@ -284,6 +286,13 @@ async def get_deck_type() -> DeckType: return DeckType(guess_deck_type_from_global_config()) +async def get_deck_definition( + deck_type: DeckType = Depends(get_deck_type), +) -> deck.dev_types.DeckDefinitionV4: + """Return this robot's deck definition.""" + return deck.load(deck_type, version=4) + + async def _postinit_ot2_tasks( hardware: ThreadManagedHardware, app_state: AppState, diff --git a/robot-server/robot_server/persistence/__init__.py b/robot-server/robot_server/persistence/__init__.py index 6a36022788a..e220ec29735 100644 --- a/robot-server/robot_server/persistence/__init__.py +++ b/robot-server/robot_server/persistence/__init__.py @@ -1,4 +1,4 @@ -"""Data access initialization and management.""" +"""Support for persisting data across device reboots.""" from ._database import create_sql_engine, sqlite_rowid diff --git a/robot-server/robot_server/router.py b/robot-server/robot_server/router.py index 0ef30d30a2c..76449fb220a 100644 --- a/robot-server/robot_server/router.py +++ b/robot-server/robot_server/router.py @@ -3,23 +3,25 @@ from .constants import V1_TAG from .errors import LegacyErrorResponse +from .versioning import check_version_header + +from .commands import commands_router +from .deck_configuration.router import router as deck_configuration_router from .health import health_router -from .protocols import protocols_router -from .runs import runs_router +from .instruments import instruments_router from .maintenance_runs.router import maintenance_runs_router -from .commands import commands_router from .modules import modules_router -from .instruments import instruments_router -from .system import system_router -from .versioning import check_version_header +from .protocols import protocols_router +from .robot.router import robot_router +from .runs import runs_router +from .service.labware.router import router as labware_router from .service.legacy.routers import legacy_routes -from .service.session.router import router as deprecated_session_router +from .service.notifications.router import router as notifications_router from .service.pipette_offset.router import router as pip_os_router -from .service.labware.router import router as labware_router +from .service.session.router import router as deprecated_session_router from .service.tip_length.router import router as tl_router -from .service.notifications.router import router as notifications_router from .subsystems.router import subsystems_router -from .robot.router import robot_router +from .system import system_router router = APIRouter() @@ -69,6 +71,12 @@ dependencies=[Depends(check_version_header)], ) +router.include_router( + router=deck_configuration_router, + tags=["Deck Configuration"], + dependencies=[Depends(check_version_header)], +) + router.include_router( router=modules_router, tags=["Attached Modules"], @@ -77,7 +85,7 @@ router.include_router( router=instruments_router, - tags=["Attached instruments"], + tags=["Attached Instruments"], dependencies=[Depends(check_version_header)], ) diff --git a/robot-server/tests/deck_configuration/test_validation.py b/robot-server/tests/deck_configuration/test_validation.py new file mode 100644 index 00000000000..c2024ef5e86 --- /dev/null +++ b/robot-server/tests/deck_configuration/test_validation.py @@ -0,0 +1,190 @@ +"""Unit tests for robot_server.deck_configuration.validation.""" + +from opentrons_shared_data.deck import load as load_deck_definition + +from robot_server.deck_configuration import validation as subject + + +def test_valid() -> None: + """It should return an empty error list if the input is valid.""" + deck_definition = load_deck_definition("ot3_standard", version=4) + cutout_fixtures = [ + subject.Placement(cutout_fixture_id=cutout_fixture_id, cutout_id=cutout_id) + for cutout_fixture_id, cutout_id in [ + ("singleLeftSlot", "cutoutA1"), + ("singleLeftSlot", "cutoutB1"), + ("singleLeftSlot", "cutoutC1"), + ("singleLeftSlot", "cutoutD1"), + ("singleCenterSlot", "cutoutA2"), + ("singleCenterSlot", "cutoutB2"), + ("singleCenterSlot", "cutoutC2"), + ("singleCenterSlot", "cutoutD2"), + ("stagingAreaRightSlot", "cutoutA3"), + ("singleRightSlot", "cutoutB3"), + ("stagingAreaRightSlot", "cutoutC3"), + ("singleRightSlot", "cutoutD3"), + ] + ] + assert subject.get_configuration_errors(deck_definition, cutout_fixtures) == set() + + +def test_invalid_empty_cutouts() -> None: + """It should enforce that every cutout is occupied.""" + deck_definition = load_deck_definition("ot3_standard", version=4) + cutout_fixtures = [ + subject.Placement(cutout_fixture_id=cutout_fixture_id, cutout_id=cutout_id) + for cutout_fixture_id, cutout_id in [ + ("singleLeftSlot", "cutoutA1"), + ("singleLeftSlot", "cutoutB1"), + ("singleLeftSlot", "cutoutC1"), + ("singleLeftSlot", "cutoutD1"), + ("singleCenterSlot", "cutoutA2"), + ("singleCenterSlot", "cutoutB2"), + # Invalid because we haven't placed anything into cutout C2 or D2. + # ("singleCenterSlot", "cutoutC2"), + # ("singleCenterSlot", "cutoutD2"), + ("stagingAreaRightSlot", "cutoutA3"), + ("singleRightSlot", "cutoutB3"), + ("stagingAreaRightSlot", "cutoutC3"), + ("singleRightSlot", "cutoutD3"), + ] + ] + assert subject.get_configuration_errors(deck_definition, cutout_fixtures) == { + subject.UnoccupiedCutoutError(cutout_id="cutoutC2"), + subject.UnoccupiedCutoutError(cutout_id="cutoutD2"), + } + + +def test_invalid_overcrowded_cutouts() -> None: + """It should prevent you from putting multiple things into a single cutout.""" + deck_definition = load_deck_definition("ot3_standard", version=4) + cutout_fixtures = [ + subject.Placement(cutout_fixture_id=cutout_fixture_id, cutout_id=cutout_id) + for cutout_fixture_id, cutout_id in [ + ("singleLeftSlot", "cutoutA1"), + ("singleLeftSlot", "cutoutB1"), + ("singleLeftSlot", "cutoutC1"), + ("singleLeftSlot", "cutoutD1"), + ("singleCenterSlot", "cutoutA2"), + ("singleCenterSlot", "cutoutB2"), + ("singleCenterSlot", "cutoutC2"), + ("singleCenterSlot", "cutoutD2"), + ("stagingAreaRightSlot", "cutoutA3"), + ("singleRightSlot", "cutoutB3"), + # Invalid because we're placing two things in cutout C3... + ("stagingAreaRightSlot", "cutoutC3"), + ("stagingAreaRightSlot", "cutoutC3"), + # ...and two things in cutout D3. + ("wasteChuteRightAdapterNoCover", "cutoutD3"), + ("singleRightSlot", "cutoutD3"), + ] + ] + assert subject.get_configuration_errors(deck_definition, cutout_fixtures) == { + subject.OvercrowdedCutoutError( + cutout_id="cutoutC3", + cutout_fixture_ids=("stagingAreaRightSlot", "stagingAreaRightSlot"), + ), + subject.OvercrowdedCutoutError( + cutout_id="cutoutD3", + cutout_fixture_ids=("wasteChuteRightAdapterNoCover", "singleRightSlot"), + ), + } + + +def test_invalid_cutout_for_fixture() -> None: + """Each fixture must be placed in a location that's valid for that particular fixture.""" + deck_definition = load_deck_definition("ot3_standard", version=4) + cutout_fixtures = [ + subject.Placement(cutout_fixture_id=cutout_fixture_id, cutout_id=cutout_id) + for cutout_fixture_id, cutout_id in [ + ("singleLeftSlot", "cutoutA1"), + ("singleLeftSlot", "cutoutB1"), + ("singleLeftSlot", "cutoutC1"), + ("singleLeftSlot", "cutoutD1"), + ("singleCenterSlot", "cutoutA2"), + ("singleCenterSlot", "cutoutB2"), + # Invalid because wasteChuteRightAdapterNoCover can't be placed in cutout C2... + ("wasteChuteRightAdapterNoCover", "cutoutC2"), + # ...nor can singleLeftSlot be placed in cutout D2. + ("singleLeftSlot", "cutoutD2"), + ("stagingAreaRightSlot", "cutoutA3"), + ("singleRightSlot", "cutoutB3"), + ("stagingAreaRightSlot", "cutoutC3"), + ("singleRightSlot", "cutoutD3"), + ] + ] + assert subject.get_configuration_errors(deck_definition, cutout_fixtures) == { + subject.InvalidLocationError( + cutout_id="cutoutC2", + cutout_fixture_id="wasteChuteRightAdapterNoCover", + allowed_cutout_ids=frozenset(["cutoutD3"]), + ), + subject.InvalidLocationError( + cutout_id="cutoutD2", + cutout_fixture_id="singleLeftSlot", + allowed_cutout_ids=frozenset( + ["cutoutA1", "cutoutB1", "cutoutC1", "cutoutD1"] + ), + ), + } + + +def test_unrecognized_cutout() -> None: + """It should raise a sensible error if you pass a totally nonexistent cutout.""" + deck_definition = load_deck_definition("ot3_standard", version=4) + cutout_fixtures = [ + subject.Placement(cutout_fixture_id=cutout_fixture_id, cutout_id=cutout_id) + for cutout_fixture_id, cutout_id in [ + ("singleLeftSlot", "cutoutA1"), + ("singleLeftSlot", "cutoutB1"), + ("singleLeftSlot", "cutoutC1"), + ("singleLeftSlot", "cutoutD1"), + ("singleCenterSlot", "cutoutA2"), + ("singleCenterSlot", "cutoutB2"), + ("singleCenterSlot", "cutoutC2"), + ("singleCenterSlot", "cutoutD2"), + ("singleRightSlot", "cutoutA3"), + ("singleRightSlot", "cutoutB3"), + ("singleRightSlot", "cutoutC3"), + ("singleRightSlot", "cutoutD3"), + # Invalid because "someUnrecognizedCutout" is not defined by the deck definition. + ("singleRightSlot", "someUnrecognizedCutout"), + ] + ] + assert subject.get_configuration_errors(deck_definition, cutout_fixtures) == { + subject.InvalidLocationError( + cutout_fixture_id="singleRightSlot", + cutout_id="someUnrecognizedCutout", + allowed_cutout_ids=frozenset( + ["cutoutA3", "cutoutB3", "cutoutC3", "cutoutD3"] + ), + ) + } + + +def test_unrecognized_cutout_fixture() -> None: + """It should raise a sensible error if you pass a totally nonexistent cutout fixture.""" + deck_definition = load_deck_definition("ot3_standard", version=4) + cutout_fixtures = [ + subject.Placement(cutout_fixture_id=cutout_fixture_id, cutout_id=cutout_id) + for cutout_fixture_id, cutout_id in [ + ("singleLeftSlot", "cutoutA1"), + ("singleLeftSlot", "cutoutB1"), + ("singleLeftSlot", "cutoutC1"), + ("singleLeftSlot", "cutoutD1"), + ("singleCenterSlot", "cutoutA2"), + ("singleCenterSlot", "cutoutB2"), + ("singleCenterSlot", "cutoutC2"), + ("singleCenterSlot", "cutoutD2"), + ("singleRightSlot", "cutoutA3"), + ("singleRightSlot", "cutoutB3"), + ("singleRightSlot", "cutoutC3"), + # Invalid because "someUnrecognizedCutoutFixture" is not defined by the deck definition. + ("someUnrecognizedCutoutFixture", "cutoutD3"), + ] + ] + assert subject.get_configuration_errors(deck_definition, cutout_fixtures) == { + subject.UnrecognizedCutoutFixtureError( + cutout_fixture_id="someUnrecognizedCutoutFixture" + ) + } diff --git a/robot-server/tests/integration/conftest.py b/robot-server/tests/integration/conftest.py index 669e2cb7655..6ba77ffbe6b 100644 --- a/robot-server/tests/integration/conftest.py +++ b/robot-server/tests/integration/conftest.py @@ -133,6 +133,7 @@ def _wait_until_ready(base_url: str) -> None: time.sleep(0.1) +# TODO(mm, 2023-11-02): This should also restore the server's original deck configuration. def _clean_server_state(base_url: str) -> None: async def _clean_server_state_async() -> None: async with RobotClient.make(base_url=base_url, version="*") as robot_client: diff --git a/robot-server/tests/integration/http_api/test_deck_configuration.tavern.yaml b/robot-server/tests/integration/http_api/test_deck_configuration.tavern.yaml new file mode 100644 index 00000000000..61419b258f0 --- /dev/null +++ b/robot-server/tests/integration/http_api/test_deck_configuration.tavern.yaml @@ -0,0 +1,110 @@ +test_name: Test setting and getting a Flex deck configuration + +marks: + - ot3_only + - usefixtures: + - ot3_server_base_url + +stages: + - name: Set a valid deck configuration + request: + url: '{ot3_server_base_url}/deck_configuration' + method: PUT + json: + data: + cutoutFixtures: &expectedCutoutFixtures + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutA1 + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutB1 + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutC1 + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutD1 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutA2 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutB2 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutC2 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutD2 + # Throw in a weird right-side deck layout + # so we know this won't happen to match the default. + - cutoutFixtureId: stagingAreaRightSlot + cutoutId: cutoutA3 + - cutoutFixtureId: singleRightSlot + cutoutId: cutoutB3 + - cutoutFixtureId: stagingAreaRightSlot + cutoutId: cutoutC3 + - cutoutFixtureId: singleRightSlot + cutoutId: cutoutD3 + + - name: Get the deck configuration + request: + url: '{ot3_server_base_url}/deck_configuration' + response: + json: + data: + lastUpdatedAt: !anystr + cutoutFixtures: *expectedCutoutFixtures + save: + json: + last_updated_at: data.lastUpdatedAt + + - name: Set an invalid deck configuration + request: + url: '{ot3_server_base_url}/deck_configuration' + method: PUT + json: + data: + cutoutFixtures: + # Invalid deck configuration: cutoutA1 is left unoccupied. + # - cutoutFixtureId: singleLeftSlot + # cutoutId: cutoutA1 + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutB1 + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutC1 + - cutoutFixtureId: singleLeftSlot + cutoutId: cutoutD1 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutA2 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutB2 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutC2 + - cutoutFixtureId: singleCenterSlot + cutoutId: cutoutD2 + - cutoutFixtureId: singleRightSlot + cutoutId: cutoutA3 + - cutoutFixtureId: singleRightSlot + cutoutId: cutoutB3 + - cutoutFixtureId: singleRightSlot + cutoutId: cutoutC3 + - cutoutFixtureId: singleRightSlot + cutoutId: cutoutD3 + response: + status_code: 422 + json: + errors: + - id: InvalidDeckConfiguration + title: Invalid Deck Configuration + errorCode: '4000' + detail: Invalid deck configuration. + meta: + deckConfigurationProblem: UnoccupiedCutoutError + cutout_id: cutoutA1 + + - name: Get the deck configuration and make sure it's not the invalid one + request: + url: '{ot3_server_base_url}/deck_configuration' + response: + json: + data: + lastUpdatedAt: '{last_updated_at}' + cutoutFixtures: *expectedCutoutFixtures +# TODO(mm, 2023-11-02): +# +# - Test that the server has a default deck configuration. +# The default configuration will be different between OT-2 and Flex. From 93d83f17750a93be39175ee5f80009b0672d8b5a Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Wed, 8 Nov 2023 14:54:18 -0500 Subject: [PATCH 34/65] refactor(protocol-designer): remove unneeded loadLabware commands from 8_0_0 migration (#13945) --- .../src/load-file/migration/8_0_0.ts | 39 +------------------ 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/protocol-designer/src/load-file/migration/8_0_0.ts b/protocol-designer/src/load-file/migration/8_0_0.ts index c397cea13e9..734f2f9ea46 100644 --- a/protocol-designer/src/load-file/migration/8_0_0.ts +++ b/protocol-designer/src/load-file/migration/8_0_0.ts @@ -37,13 +37,7 @@ interface LabwareLocationUpdate { export const migrateFile = ( appData: ProtocolFileV7 ): ProtocolFile => { - const { - designerApplication, - commands, - robot, - labwareDefinitions, - liquids, - } = appData + const { designerApplication, commands, robot, liquids } = appData if (designerApplication == null || designerApplication.data == null) { throw Error('The designerApplication key in your file is corrupt.') @@ -135,31 +129,6 @@ export const migrateFile = ( filteredSavedStepForms ) - const loadLabwareCommands: LoadLabwareCreateCommand[] = commands - .filter( - (command): command is LoadLabwareCreateCommand => - command.commandType === 'loadLabware' - ) - .map(command => { - // protocols that do multiple migrations through 7.0.0 have a loadName === definitionURI - // this ternary below fixes that - const loadName = - labwareDefinitions[command.params.loadName] != null - ? labwareDefinitions[command.params.loadName].parameters.loadName - : command.params.loadName - return { - ...command, - params: { - ...command.params, - loadName, - }, - } - }) - - const migratedCommandsV8 = commands.filter( - command => command.commandType !== 'loadLabware' - ) - const flexDeckSpec: OT3RobotMixin = { robot: { model: FLEX_ROBOT_TYPE, @@ -216,11 +185,7 @@ export const migrateFile = ( const commandv8Mixin: CommandV8Mixin = { commandSchemaId: 'opentronsCommandSchemaV8', - commands: [ - ...migratedCommandsV8, - ...loadLabwareCommands, - ...trashLoadCommand, - ], + commands: [...commands, ...trashLoadCommand], } const commandAnnotionaV1Mixin: CommandAnnotationV1Mixin = { From 7a781647911931f0c57f15d8a675dc541ec0e60e Mon Sep 17 00:00:00 2001 From: koji Date: Wed, 8 Nov 2023 15:15:34 -0500 Subject: [PATCH 35/65] refactor(app): update deckmap and deck configurator styling (#13946) * refactor(app): update deck configurator styling (#13946) --- .../DeckConfigurator/EmptyConfigFixture.tsx | 37 +++++++++++++++---- .../StagingAreaConfigFixture.tsx | 33 ++++++++++++----- .../TrashBinConfigFixture.tsx | 32 +++++++++++----- .../WasteChuteConfigFixture.tsx | 33 ++++++++++++----- 4 files changed, 100 insertions(+), 35 deletions(-) diff --git a/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx index ef579ea5bda..d53f7d98188 100644 --- a/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { css } from 'styled-components' import { getDeckDefFromRobotType, @@ -71,14 +72,7 @@ export function EmptyConfigFixture( flexProps={{ flex: '1' }} foreignObjectProps={{ flex: '1' }} > - + ) } + +const EMPTY_CONFIG_STYLE = css` + align-items: ${ALIGN_CENTER}; + justify-content: ${JUSTIFY_CENTER}; + background-color: ${COLORS.mediumBlueEnabled}; + border: 3px dashed ${COLORS.blueEnabled}; + border-radius: ${BORDERS.radiusSoftCorners}; + width: 100%; + + &:active { + border: 3px solid ${COLORS.blueEnabled}; + background-color: ${COLORS.mediumBluePressed}; + } + + &:focus { + border: 3px solid ${COLORS.blueEnabled}; + background-color: ${COLORS.mediumBluePressed}; + } + + &:hover { + background-color: ${COLORS.mediumBluePressed}; + } + + &:focus-visible { + border: 3px solid ${COLORS.fundamentalsFocus}; + } +` diff --git a/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx index f8ba5b44e35..6f7013e053f 100644 --- a/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { css } from 'styled-components' import { getDeckDefFromRobotType, @@ -64,15 +65,7 @@ export function StagingAreaConfigFixture( flexProps={{ flex: '1' }} foreignObjectProps={{ flex: '1' }} > - + {stagingAreaDef.metadata.displayName} @@ -89,3 +82,25 @@ export function StagingAreaConfigFixture( ) } + +const STAGING_AREA_CONFIG_STYLE = css` + align-items: ${ALIGN_CENTER}; + background-color: ${COLORS.grey2}; + border-radius: ${BORDERS.borderRadiusSize1}; + color: ${COLORS.white}; + grid-gap: ${SPACING.spacing8}; + justify-content: ${JUSTIFY_CENTER}; + width: 100%; + + &:active { + background-color: ${COLORS.darkBlack90}; + } + + &:hover { + background-color: ${COLORS.grey1}; + } + + &:focus-visible { + border: 3px solid ${COLORS.fundamentalsFocus}; + } +` diff --git a/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx index 0d78b538fb7..5ca41d53c33 100644 --- a/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { css } from 'styled-components' import { getDeckDefFromRobotType, @@ -70,15 +71,7 @@ export function TrashBinConfigFixture( flexProps={{ flex: '1' }} foreignObjectProps={{ flex: '1' }} > - + {trashBinDef.metadata.displayName} @@ -95,3 +88,24 @@ export function TrashBinConfigFixture( ) } + +const TRASH_BIN_CONFIG_STYLE = css` + align-items: ${ALIGN_CENTER}; + background-color: ${COLORS.grey2}; + border-radius: ${BORDERS.borderRadiusSize1}; + color: ${COLORS.white}; + justify-content: ${JUSTIFY_CENTER}; + grid-gap: ${SPACING.spacing8}; + width: 100%; + + &:active { + background-color: ${COLORS.darkBlack90}; + } + + &:hover { + background-color: ${COLORS.grey1}; + } + + &:focus-visible { + } +` diff --git a/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx index da0b9241df7..e43ae7eadfb 100644 --- a/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { css } from 'styled-components' import { getDeckDefFromRobotType, @@ -64,15 +65,7 @@ export function WasteChuteConfigFixture( flexProps={{ flex: '1' }} foreignObjectProps={{ flex: '1' }} > - + {wasteChuteDef.metadata.displayName} @@ -89,3 +82,25 @@ export function WasteChuteConfigFixture( ) } + +const WASTE_CHUTE_CONFIG_STYLE = css` + align-items: ${ALIGN_CENTER}; + background-color: ${COLORS.grey2}; + border-radius: ${BORDERS.borderRadiusSize1}; + color: ${COLORS.white}; + justify-content: ${JUSTIFY_CENTER}; + grid-gap: ${SPACING.spacing8}; + width: 100%; + + &:active { + background-color: ${COLORS.darkBlack90}; + } + + &:hover { + background-color: ${COLORS.grey1}; + } + + &:focus-visible { + border: 3px solid ${COLORS.fundamentalsFocus}; + } +` From 9fb282be8aa9bbdf8303caec60358e29c60ad7b9 Mon Sep 17 00:00:00 2001 From: Frank Sinapi Date: Wed, 8 Nov 2023 15:35:45 -0500 Subject: [PATCH 36/65] fix(hardware): error details should always be strings (#13948) --- .../opentrons_hardware/firmware_bindings/messages/payloads.py | 4 ++-- .../opentrons_hardware/hardware_control/move_group_runner.py | 2 +- hardware/opentrons_hardware/hardware_control/tool_sensors.py | 2 +- hardware/opentrons_hardware/instruments/gripper/serials.py | 2 +- hardware/opentrons_hardware/instruments/pipettes/serials.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py b/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py index 8525b04459a..1e31028957e 100644 --- a/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py +++ b/hardware/opentrons_hardware/firmware_bindings/messages/payloads.py @@ -319,13 +319,13 @@ def __post_init__(self) -> None: raise InternalMessageFormatError( f"FirmwareUpdateData: Data address needs to be doubleword aligned." f" {address} mod 8 equals {address % 8} and should be 0", - detail={"address": address}, + detail={"address": str(address)}, ) if data_length > FirmwareUpdateDataField.NUM_BYTES: raise InternalMessageFormatError( f"FirmwareUpdateData: Data cannot be more than" f" {FirmwareUpdateDataField.NUM_BYTES} bytes got {data_length}.", - detail={"size": data_length}, + detail={"size": str(data_length)}, ) @classmethod diff --git a/hardware/opentrons_hardware/hardware_control/move_group_runner.py b/hardware/opentrons_hardware/hardware_control/move_group_runner.py index 29b6aa89267..e906ea93646 100644 --- a/hardware/opentrons_hardware/hardware_control/move_group_runner.py +++ b/hardware/opentrons_hardware/hardware_control/move_group_runner.py @@ -617,7 +617,7 @@ async def _run_one_group(self, group_id: int, can_messenger: CanMessenger) -> No detail={ "missing-nodes": missing_node_msg, "full-timeout": str(full_timeout), - "expected-time": expected_time, + "expected-time": str(expected_time), "elapsed": str(time.time() - start_time), }, ) diff --git a/hardware/opentrons_hardware/hardware_control/tool_sensors.py b/hardware/opentrons_hardware/hardware_control/tool_sensors.py index 34f18b87542..a0f9fbcd745 100644 --- a/hardware/opentrons_hardware/hardware_control/tool_sensors.py +++ b/hardware/opentrons_hardware/hardware_control/tool_sensors.py @@ -186,7 +186,7 @@ async def capacitive_probe( detail={ "tool": tool.name, "sensor": sensor_id.name, - "threshold": relative_threshold_pf, + "threshold": str(relative_threshold_pf), }, ) LOG.info(f"starting capacitive probe with threshold {threshold.to_float()}") diff --git a/hardware/opentrons_hardware/instruments/gripper/serials.py b/hardware/opentrons_hardware/instruments/gripper/serials.py index 09f41d92dd6..6691aa64fea 100644 --- a/hardware/opentrons_hardware/instruments/gripper/serials.py +++ b/hardware/opentrons_hardware/instruments/gripper/serials.py @@ -70,6 +70,6 @@ def gripper_serial_val_from_parts(model: int, serialval: bytes) -> bytes: except struct.error as e: raise InvalidInstrumentData( message="Invalid serial data", - detail={"model": model, "serial": serialval}, + detail={"model": str(model), "serial": str(serialval)}, wrapping=[PythonException(e)], ) diff --git a/hardware/opentrons_hardware/instruments/pipettes/serials.py b/hardware/opentrons_hardware/instruments/pipettes/serials.py index b7b43cd3b59..e697821373a 100644 --- a/hardware/opentrons_hardware/instruments/pipettes/serials.py +++ b/hardware/opentrons_hardware/instruments/pipettes/serials.py @@ -93,6 +93,6 @@ def serial_val_from_parts(name: PipetteName, model: int, serialval: bytes) -> by except struct.error as e: raise InvalidInstrumentData( message="Invalid pipette serial", - detail={"name": name, "model": model, "serial": str(serialval)}, + detail={"name": str(name), "model": str(model), "serial": str(serialval)}, wrapping=[PythonException(e)], ) From fac2cef2e353d13f3ba7c61e6fb36cbd71e24ccf Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Wed, 8 Nov 2023 15:47:49 -0500 Subject: [PATCH 37/65] fix(app): ODD LPC copy and styling (#13925) closes RQA-1052 closes RQA-1353 closes RQA-1358 Fix copy for preparing space conditional on step index and module presence. Correctly style ExitConfirmation step. Fix button alignment in TipConfirmation. --- .../en/labware_position_check.json | 1 + .../LabwarePositionCheck/CheckItem.tsx | 5 +- .../LabwarePositionCheck/ExitConfirmation.tsx | 46 +++++++++++++++---- .../LabwarePositionCheckComponent.tsx | 11 ++++- .../LabwarePositionCheck/PickUpTip.tsx | 9 +++- .../LabwarePositionCheck/ReturnTip.tsx | 6 ++- .../LabwarePositionCheck/TipConfirmation.tsx | 8 +++- .../__tests__/PickUpTip.test.tsx | 36 ++++++++++++++- .../__tests__/ReturnTip.test.tsx | 19 +++++++- 9 files changed, 124 insertions(+), 17 deletions(-) diff --git a/app/src/assets/localization/en/labware_position_check.json b/app/src/assets/localization/en/labware_position_check.json index be73b09f6b9..58fe6550ddd 100644 --- a/app/src/assets/localization/en/labware_position_check.json +++ b/app/src/assets/localization/en/labware_position_check.json @@ -11,6 +11,7 @@ "check_labware_in_slot_title": "Check Labware {{labware_display_name}} in slot {{slot}}", "check_remaining_labware_with_primary_pipette_section": "Check remaining labware with {{primary_mount}} Pipette and tip", "clear_all_slots": "Clear all deck slots of labware, leaving modules in place", + "clear_all_slots_odd": "Clear all deck slots of labware", "cli_ssh": "Command Line Interface (SSH)", "close_and_apply_offset_data": "Close and apply labware offset data", "confirm_pick_up_tip_modal_title": "Did the pipette pick up a tip successfully?", diff --git a/app/src/organisms/LabwarePositionCheck/CheckItem.tsx b/app/src/organisms/LabwarePositionCheck/CheckItem.tsx index 7cfb76e79d0..aaed13ca607 100644 --- a/app/src/organisms/LabwarePositionCheck/CheckItem.tsx +++ b/app/src/organisms/LabwarePositionCheck/CheckItem.tsx @@ -454,7 +454,10 @@ export const CheckItem = (props: CheckItemProps): JSX.Element | null => { })} body={ } labwareDef={labwareDef} diff --git a/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx b/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx index 5bdb7911af7..23f498392d9 100644 --- a/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx +++ b/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx @@ -16,15 +16,13 @@ import { RESPONSIVENESS, SecondaryButton, JUSTIFY_FLEX_END, + TEXT_ALIGN_CENTER, } from '@opentrons/components' import { StyledText } from '../../atoms/text' -import { NeedHelpLink } from '../CalibrationPanels' import { useSelector } from 'react-redux' import { getIsOnDevice } from '../../redux/config' import { SmallButton } from '../../atoms/buttons' -const LPC_HELP_LINK_URL = - 'https://support.opentrons.com/s/article/How-Labware-Offsets-work-on-the-OT-2' interface ExitConfirmationProps { onGoBack: () => void onConfirmExit: () => void @@ -45,12 +43,28 @@ export const ExitConfirmation = (props: ExitConfirmationProps): JSX.Element => { flexDirection={DIRECTION_COLUMN} justifyContent={JUSTIFY_CENTER} alignItems={ALIGN_CENTER} + paddingX={SPACING.spacing32} > - {t('exit_screen_title')} - - {t('exit_screen_subtitle')} - + {isOnDevice ? ( + <> + + {t('exit_screen_title')} + + + + {t('exit_screen_subtitle')} + + + + ) : ( + <> + {t('exit_screen_title')} + + {t('exit_screen_subtitle')} + + + )} {isOnDevice ? ( { justifyContent={JUSTIFY_SPACE_BETWEEN} alignItems={ALIGN_CENTER} > - {t('shared:go_back')} @@ -97,8 +110,23 @@ export const ExitConfirmation = (props: ExitConfirmationProps): JSX.Element => { const ConfirmationHeader = styled.h1` margin-top: ${SPACING.spacing24}; - ${TYPOGRAPHY.h1Default} + ${TYPOGRAPHY.level3HeaderSemiBold} @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { ${TYPOGRAPHY.level4HeaderSemiBold} } ` + +const ConfirmationHeaderODD = styled.h1` + margin-top: ${SPACING.spacing24}; + ${TYPOGRAPHY.level3HeaderBold} + @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { + ${TYPOGRAPHY.level4HeaderSemiBold} + } +` +const ConfirmationBodyODD = styled.h1` + ${TYPOGRAPHY.level4HeaderRegular} + @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { + ${TYPOGRAPHY.level4HeaderRegular} + } + color: ${COLORS.darkBlack70}; +` diff --git a/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx b/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx index 4a96d8bc2e3..95f9fc02c5e 100644 --- a/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx +++ b/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx @@ -261,6 +261,8 @@ export const LabwarePositionCheckComponent = ( const currentStep = LPCSteps?.[currentStepIndex] if (currentStep == null) return null + const protocolHasModules = protocolData.modules.length > 0 + const handleJog = ( axis: Axis, dir: Sign, @@ -357,7 +359,14 @@ export const LabwarePositionCheckComponent = ( } else if (currentStep.section === 'DETACH_PROBE') { modalContent = } else if (currentStep.section === 'PICK_UP_TIP') { - modalContent = + modalContent = ( + + ) } else if (currentStep.section === 'RETURN_TIP') { modalContent = ( { const { t, i18n } = useTranslation(['labware_position_check', 'shared']) @@ -67,6 +69,8 @@ export const PickUpTip = (props: PickUpTipProps): JSX.Element | null => { setFatalError, adapterId, robotType, + protocolHasModules, + currentStepIndex, } = props const [showTipConfirmation, setShowTipConfirmation] = React.useState(false) const isOnDevice = useSelector(getIsOnDevice) @@ -87,7 +91,10 @@ export const PickUpTip = (props: PickUpTipProps): JSX.Element | null => { ) const labwareDisplayName = getLabwareDisplayName(labwareDef) const instructions = [ - t('clear_all_slots'), + ...(protocolHasModules && currentStepIndex === 1 + ? [t('place_modules')] + : []), + isOnDevice ? t('clear_all_slots_odd') : t('clear_all_slots'), { adapterId, } = props + const isOnDevice = useSelector(getIsOnDevice) + const labwareDef = getLabwareDef(labwareId, protocolData) if (labwareDef == null) return null @@ -60,7 +64,7 @@ export const ReturnTip = (props: ReturnTipProps): JSX.Element | null => { const labwareDisplayName = getLabwareDisplayName(labwareDef) const instructions = [ - t('clear_all_slots'), + isOnDevice ? t('clear_all_slots_odd') : t('clear_all_slots'), - + { existingOffsets: mockExistingOffsets, isRobotMoving: false, robotType: FLEX_ROBOT_TYPE, + protocolHasModules: false, + currentStepIndex: 1, } mockUseProtocolMetaData.mockReturnValue({ robotType: 'OT-3 Standard' }) }) @@ -69,16 +71,46 @@ describe('PickUpTip', () => { jest.resetAllMocks() resetAllWhenMocks() }) - it('renders correct copy when preparing space', () => { + it('renders correct copy when preparing space on desktop if protocol has modules', () => { + props.protocolHasModules = true const { getByText, getByRole } = render(props) getByRole('heading', { name: 'Prepare tip rack in Slot D1' }) + getByText('Place modules on deck') getByText('Clear all deck slots of labware, leaving modules in place') getByText( matchTextWithSpans('Place a full Mock TipRack Definition into Slot D1') ) - getByRole('link', { name: 'Need help?' }) getByRole('button', { name: 'Confirm placement' }) }) + it('renders correct copy when preparing space on touchscreen if protocol has modules', () => { + mockGetIsOnDevice.mockReturnValue(true) + props.protocolHasModules = true + const { getByText, getByRole } = render(props) + getByRole('heading', { name: 'Prepare tip rack in Slot D1' }) + getByText('Place modules on deck') + getByText('Clear all deck slots of labware') + getByText( + matchTextWithSpans('Place a full Mock TipRack Definition into Slot D1') + ) + }) + it('renders correct copy when preparing space on desktop if protocol has no modules', () => { + const { getByText, getByRole } = render(props) + getByRole('heading', { name: 'Prepare tip rack in Slot D1' }) + getByText('Clear all deck slots of labware, leaving modules in place') + getByText( + matchTextWithSpans('Place a full Mock TipRack Definition into Slot D1') + ) + getByRole('button', { name: 'Confirm placement' }) + }) + it('renders correct copy when preparing space on touchscreen if protocol has no modules', () => { + mockGetIsOnDevice.mockReturnValue(true) + const { getByText, getByRole } = render(props) + getByRole('heading', { name: 'Prepare tip rack in Slot D1' }) + getByText('Clear all deck slots of labware') + getByText( + matchTextWithSpans('Place a full Mock TipRack Definition into Slot D1') + ) + }) it('renders correct copy when confirming position on desktop', () => { const { getByText, getByRole } = render({ ...props, diff --git a/app/src/organisms/LabwarePositionCheck/__tests__/ReturnTip.test.tsx b/app/src/organisms/LabwarePositionCheck/__tests__/ReturnTip.test.tsx index 465609db8c4..037d171579a 100644 --- a/app/src/organisms/LabwarePositionCheck/__tests__/ReturnTip.test.tsx +++ b/app/src/organisms/LabwarePositionCheck/__tests__/ReturnTip.test.tsx @@ -7,12 +7,17 @@ import { ReturnTip } from '../ReturnTip' import { SECTIONS } from '../constants' import { mockCompletedAnalysis } from '../__fixtures__' import { useProtocolMetadata } from '../../Devices/hooks' +import { getIsOnDevice } from '../../../redux/config' jest.mock('../../Devices/hooks') +jest.mock('../../../redux/config') const mockUseProtocolMetaData = useProtocolMetadata as jest.MockedFunction< typeof useProtocolMetadata > +const mockGetIsOnDevice = getIsOnDevice as jest.MockedFunction< + typeof getIsOnDevice +> const matchTextWithSpans: (text: string) => MatcherFunction = ( text: string @@ -37,6 +42,7 @@ describe('ReturnTip', () => { beforeEach(() => { mockChainRunCommands = jest.fn().mockImplementation(() => Promise.resolve()) + mockGetIsOnDevice.mockReturnValue(false) props = { section: SECTIONS.RETURN_TIP, pipetteId: mockCompletedAnalysis.pipettes[0].id, @@ -55,7 +61,7 @@ describe('ReturnTip', () => { afterEach(() => { jest.restoreAllMocks() }) - it('renders correct copy', () => { + it('renders correct copy on desktop', () => { const { getByText, getByRole } = render(props) getByRole('heading', { name: 'Return tip rack to Slot D1' }) getByText('Clear all deck slots of labware, leaving modules in place') @@ -66,6 +72,17 @@ describe('ReturnTip', () => { ) getByRole('link', { name: 'Need help?' }) }) + it('renders correct copy on device', () => { + mockGetIsOnDevice.mockReturnValue(true) + const { getByText, getByRole } = render(props) + getByRole('heading', { name: 'Return tip rack to Slot D1' }) + getByText('Clear all deck slots of labware') + getByText( + matchTextWithSpans( + 'Place the Mock TipRack Definition that you used before back into Slot D1. The pipette will return tips to their original location in the rack.' + ) + ) + }) it('executes correct chained commands when CTA is clicked', async () => { const { getByRole } = render(props) await getByRole('button', { name: 'Confirm placement' }).click() From 73258b46887890324cbeac8b585df0a1edacaf5b Mon Sep 17 00:00:00 2001 From: Brian Arthur Cooper Date: Wed, 8 Nov 2023 15:58:39 -0500 Subject: [PATCH 38/65] fix(app, robot_server): allow non-standard tip racks in tip length calibration from dashboard (#13891) Mirror our approach for loading an alternate tip rack into a legacy calibration session from deck/pipette-offset to tip length calibration Closes RAUT-809 --- app/src/organisms/CalibrateDeck/index.tsx | 1 + app/src/organisms/CalibrateTipLength/index.tsx | 6 +++++- app/src/organisms/CalibrateTipLength/types.ts | 1 + .../Introduction/__tests__/Introduction.test.tsx | 3 ++- .../organisms/CalibrationPanels/Introduction/index.tsx | 3 ++- app/src/organisms/CalibrationPanels/types.ts | 1 + .../hooks/useDashboardCalibrateTipLength.tsx | 1 + .../sessions/__fixtures__/tip-length-calibration.ts | 1 + app/src/redux/sessions/tip-length-calibration/types.ts | 3 ++- .../robot/calibration/tip_length/user_flow.py | 9 ++++++++- 10 files changed, 24 insertions(+), 5 deletions(-) diff --git a/app/src/organisms/CalibrateDeck/index.tsx b/app/src/organisms/CalibrateDeck/index.tsx index 5beac8275f3..87d0a65f432 100644 --- a/app/src/organisms/CalibrateDeck/index.tsx +++ b/app/src/organisms/CalibrateDeck/index.tsx @@ -175,6 +175,7 @@ export function CalibrateDeck( supportedCommands={supportedCommands} defaultTipracks={instrument?.defaultTipracks} calInvalidationHandler={offsetInvalidationHandler} + allowChangeTipRack /> )} diff --git a/app/src/organisms/CalibrateTipLength/index.tsx b/app/src/organisms/CalibrateTipLength/index.tsx index bc63d34f134..21016afa1de 100644 --- a/app/src/organisms/CalibrateTipLength/index.tsx +++ b/app/src/organisms/CalibrateTipLength/index.tsx @@ -71,8 +71,10 @@ export function CalibrateTipLength( dispatchRequests, isJogging, offsetInvalidationHandler, + allowChangeTipRack = false, } = props - const { currentStep, instrument, labware } = session?.details ?? {} + const { currentStep, instrument, labware, supportedCommands } = + session?.details ?? {} const queryClient = useQueryClient() const host = useHost() @@ -171,7 +173,9 @@ export function CalibrateTipLength( calBlock={calBlock} currentStep={currentStep} sessionType={session.sessionType} + supportedCommands={supportedCommands} calInvalidationHandler={offsetInvalidationHandler} + allowChangeTipRack={allowChangeTipRack} /> )} diff --git a/app/src/organisms/CalibrateTipLength/types.ts b/app/src/organisms/CalibrateTipLength/types.ts index 48f685343e1..bcb791c5f5d 100644 --- a/app/src/organisms/CalibrateTipLength/types.ts +++ b/app/src/organisms/CalibrateTipLength/types.ts @@ -7,5 +7,6 @@ export interface CalibrateTipLengthParentProps { dispatchRequests: DispatchRequestsType showSpinner: boolean isJogging: boolean + allowChangeTipRack?: boolean offsetInvalidationHandler?: () => void } diff --git a/app/src/organisms/CalibrationPanels/Introduction/__tests__/Introduction.test.tsx b/app/src/organisms/CalibrationPanels/Introduction/__tests__/Introduction.test.tsx index bccf4a9202b..8b0cb221597 100644 --- a/app/src/organisms/CalibrationPanels/Introduction/__tests__/Introduction.test.tsx +++ b/app/src/organisms/CalibrationPanels/Introduction/__tests__/Introduction.test.tsx @@ -52,9 +52,10 @@ describe('Introduction', () => { getByRole('link', { name: 'Need help?' }) expect(queryByRole('button', { name: 'Change tip rack' })).toBe(null) }) - it('renders change tip rack button if deck calibration', () => { + it('renders change tip rack button if allowChangeTipRack', () => { const { getByRole, getByText, queryByRole } = render({ sessionType: Sessions.SESSION_TYPE_DECK_CALIBRATION, + allowChangeTipRack: true, })[0] const button = getByRole('button', { name: 'Change tip rack' }) button.click() diff --git a/app/src/organisms/CalibrationPanels/Introduction/index.tsx b/app/src/organisms/CalibrationPanels/Introduction/index.tsx index 9a70d1ea0ad..5bdc25ce51c 100644 --- a/app/src/organisms/CalibrationPanels/Introduction/index.tsx +++ b/app/src/organisms/CalibrationPanels/Introduction/index.tsx @@ -35,6 +35,7 @@ export function Introduction(props: CalibrationPanelProps): JSX.Element { instruments, supportedCommands, calInvalidationHandler, + allowChangeTipRack = false, } = props const { t } = useTranslation('robot_calibration') @@ -167,7 +168,7 @@ export function Introduction(props: CalibrationPanelProps): JSX.Element { > - {sessionType === Sessions.SESSION_TYPE_DECK_CALIBRATION ? ( + {allowChangeTipRack ? ( setShowChooseTipRack(true)}> {t('change_tip_rack')} diff --git a/app/src/organisms/CalibrationPanels/types.ts b/app/src/organisms/CalibrationPanels/types.ts index 16d9f9d60fd..cc8700aa8be 100644 --- a/app/src/organisms/CalibrationPanels/types.ts +++ b/app/src/organisms/CalibrationPanels/types.ts @@ -32,4 +32,5 @@ export interface CalibrationPanelProps { supportedCommands?: SessionCommandString[] | null defaultTipracks?: LabwareDefinition2[] | null calInvalidationHandler?: () => void + allowChangeTipRack?: boolean } diff --git a/app/src/pages/Devices/CalibrationDashboard/hooks/useDashboardCalibrateTipLength.tsx b/app/src/pages/Devices/CalibrationDashboard/hooks/useDashboardCalibrateTipLength.tsx index f368c4061c0..a26a63ac6f5 100644 --- a/app/src/pages/Devices/CalibrationDashboard/hooks/useDashboardCalibrateTipLength.tsx +++ b/app/src/pages/Devices/CalibrationDashboard/hooks/useDashboardCalibrateTipLength.tsx @@ -180,6 +180,7 @@ export function useDashboardCalibrateTipLength( dispatchRequests={dispatchRequests} isJogging={isJogging} offsetInvalidationHandler={invalidateHandlerRef.current} + allowChangeTipRack={sessionParams.current?.tipRackDefinition == null} /> ) diff --git a/app/src/redux/sessions/__fixtures__/tip-length-calibration.ts b/app/src/redux/sessions/__fixtures__/tip-length-calibration.ts index 8877b9f1c69..fbb433c063b 100644 --- a/app/src/redux/sessions/__fixtures__/tip-length-calibration.ts +++ b/app/src/redux/sessions/__fixtures__/tip-length-calibration.ts @@ -35,6 +35,7 @@ export const mockTipLengthCalibrationSessionDetails: TipLengthCalibrationSession }, currentStep: 'labwareLoaded', labware: [mockTipLengthTipRack, mockTipLengthCalBlock], + supportedCommands: [], } export const mockTipLengthCalibrationSessionParams: TipLengthCalibrationSessionParams = { diff --git a/app/src/redux/sessions/tip-length-calibration/types.ts b/app/src/redux/sessions/tip-length-calibration/types.ts index 7e9980d6af7..16b5eebb865 100644 --- a/app/src/redux/sessions/tip-length-calibration/types.ts +++ b/app/src/redux/sessions/tip-length-calibration/types.ts @@ -8,7 +8,7 @@ import { TIP_LENGTH_STEP_MEASURING_TIP_OFFSET, TIP_LENGTH_STEP_CALIBRATION_COMPLETE, } from '../constants' -import type { CalibrationLabware } from '../types' +import type { CalibrationLabware, SessionCommandString } from '../types' import type { LabwareDefinition2, PipetteModel } from '@opentrons/shared-data' @@ -40,4 +40,5 @@ export interface TipLengthCalibrationSessionDetails { instrument: TipLengthCalibrationInstrument currentStep: TipLengthCalibrationStep labware: CalibrationLabware[] + supportedCommands: SessionCommandString[] } diff --git a/robot-server/robot_server/robot/calibration/tip_length/user_flow.py b/robot-server/robot_server/robot/calibration/tip_length/user_flow.py index 11811ea339a..e771c0def5d 100644 --- a/robot-server/robot_server/robot/calibration/tip_length/user_flow.py +++ b/robot-server/robot_server/robot/calibration/tip_length/user_flow.py @@ -82,6 +82,7 @@ def __init__( cast(List[LabwareUri], self.hw_pipette.liquid_class.default_tipracks) ) self._supported_commands = SupportedCommands(namespace="calibration") + self._supported_commands.loadLabware = True def _set_current_state(self, to_state: State): self._current_state = to_state @@ -168,7 +169,13 @@ async def load_labware( self, tiprackDefinition: Optional[LabwareDefinition] = None, ): - pass + self._supported_commands.loadLabware = False + if tiprackDefinition: + verified_definition = labware.verify_definition(tiprackDefinition) + self._tip_rack = self._get_tip_rack_lw(verified_definition) + if self._deck[TIP_RACK_SLOT]: + del self._deck[TIP_RACK_SLOT] + self._deck[TIP_RACK_SLOT] = self._tip_rack async def move_to_tip_rack(self): await self._move(Location(self.tip_origin, None)) From f74f8146550fe7b9da34c939521610c069773669 Mon Sep 17 00:00:00 2001 From: Brian Arthur Cooper Date: Wed, 8 Nov 2023 15:59:45 -0500 Subject: [PATCH 39/65] fix(app): fix last run protocol sorting on protocol dashboard (#13905) We were incorrectly calculating the last run timestamp of a given protocol, this fixes the logic to report the correct value Closes RAUT-843 --- app/src/pages/ProtocolDashboard/index.tsx | 9 ++++++++- app/src/pages/ProtocolDashboard/utils.ts | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/pages/ProtocolDashboard/index.tsx b/app/src/pages/ProtocolDashboard/index.tsx index 4c64285667d..fd11c3e2192 100644 --- a/app/src/pages/ProtocolDashboard/index.tsx +++ b/app/src/pages/ProtocolDashboard/index.tsx @@ -96,7 +96,14 @@ export function ProtocolDashboard(): JSX.Element { } const runData = runs.data?.data != null ? runs.data?.data : [] - const sortedProtocols = sortProtocols(sortBy, unpinnedProtocols, runData) + const allRunsNewestFirst = runData.sort( + (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + ) + const sortedProtocols = sortProtocols( + sortBy, + unpinnedProtocols, + allRunsNewestFirst + ) const handleProtocolsBySortKey = ( sortKey: ProtocolsOnDeviceSortKey ): void => { diff --git a/app/src/pages/ProtocolDashboard/utils.ts b/app/src/pages/ProtocolDashboard/utils.ts index 74ee9a8f3b7..cdf873b4298 100644 --- a/app/src/pages/ProtocolDashboard/utils.ts +++ b/app/src/pages/ProtocolDashboard/utils.ts @@ -7,17 +7,17 @@ const DUMMY_FOR_NO_DATE_CASE = -8640000000000000 export function sortProtocols( sortBy: ProtocolsOnDeviceSortKey, protocols: ProtocolResource[], - runs: RunData[] + allRunsNewestFirst: RunData[] ): ProtocolResource[] { protocols.sort((a, b) => { const aName = a.metadata.protocolName ?? a.files[0].name const bName = b.metadata.protocolName ?? b.files[0].name const aLastRun = new Date( - runs.find(run => run.protocolId === a.id)?.completedAt ?? + allRunsNewestFirst.find(run => run.protocolId === a.id)?.completedAt ?? new Date(DUMMY_FOR_NO_DATE_CASE) ) const bLastRun = new Date( - runs.find(run => run.protocolId === b.id)?.completedAt ?? + allRunsNewestFirst.find(run => run.protocolId === b.id)?.completedAt ?? new Date(DUMMY_FOR_NO_DATE_CASE) ) const aDate = new Date(a.createdAt) From fd00fe24e4556fb4b21ced0dd1079f23afa4dfc5 Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:21:24 -0500 Subject: [PATCH 40/65] feat(protocol-designer): modal updates and deck map design tweaks (#13900) closes RAUT-807 RAUT-816 RAUT-817 --- .../cypress/integration/migrations.spec.js | 2 +- .../src/components/DeckSetup/DeckSetup.css | 1 + .../components/DeckSetup/FlexModuleTag.tsx | 1 + .../src/components/DeckSetup/index.tsx | 1 - .../components/FileSidebar/FileSidebar.tsx | 12 ++++----- .../__tests__/FileSidebar.test.tsx | 10 +++---- .../AnnouncementModal/announcements.tsx | 25 ++++++++++++++++++ .../src/images/deck_configuration.png | Bin 0 -> 173096 bytes .../src/localization/en/alert.json | 4 +-- protocol-designer/src/tutorial/index.ts | 3 ++- 10 files changed, 43 insertions(+), 16 deletions(-) create mode 100644 protocol-designer/src/images/deck_configuration.png diff --git a/protocol-designer/cypress/integration/migrations.spec.js b/protocol-designer/cypress/integration/migrations.spec.js index ec21b08994e..400e63e5268 100644 --- a/protocol-designer/cypress/integration/migrations.spec.js +++ b/protocol-designer/cypress/integration/migrations.spec.js @@ -130,7 +130,7 @@ describe('Protocol fixtures migrate and match snapshots', () => { cy.get('div') .contains( - 'This protocol can only run on app and robot server version 7.0 or higher' + 'This protocol can only run on app and robot server version 7.1 or higher' ) .should('exist') cy.get('button').contains('continue', { matchCase: false }).click() diff --git a/protocol-designer/src/components/DeckSetup/DeckSetup.css b/protocol-designer/src/components/DeckSetup/DeckSetup.css index f6641390146..ac65e2975a5 100644 --- a/protocol-designer/src/components/DeckSetup/DeckSetup.css +++ b/protocol-designer/src/components/DeckSetup/DeckSetup.css @@ -2,6 +2,7 @@ .deck_wrapper { flex: 1; + margin-top: 1rem; } .deck_header { diff --git a/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx b/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx index 6e9d28cead7..28e82c0c9e2 100644 --- a/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx +++ b/protocol-designer/src/components/DeckSetup/FlexModuleTag.tsx @@ -25,6 +25,7 @@ export function FlexModuleTag(props: FlexModuleTagProps): JSX.Element { padding: SPACING.spacing4, height: '100%', color: COLORS.white, + border: `1px solid ${COLORS.darkGrey}`, }} > diff --git a/protocol-designer/src/components/DeckSetup/index.tsx b/protocol-designer/src/components/DeckSetup/index.tsx index 8197275779a..5109d454526 100644 --- a/protocol-designer/src/components/DeckSetup/index.tsx +++ b/protocol-designer/src/components/DeckSetup/index.tsx @@ -518,7 +518,6 @@ export const DeckSetup = (): JSX.Element => { {drilledDown && }

    ) @@ -325,8 +325,8 @@ export function FileSidebar(props: Props): JSX.Element { content: React.ReactNode } => { return { - hintKey: 'export_v7_protocol_7_0', - content: v7WarningContent, + hintKey: 'export_v8_protocol_7_1', + content: v8WarningContent, } } diff --git a/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx b/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx index 8b15ec934f1..88b9ae98d9a 100644 --- a/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx +++ b/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx @@ -16,7 +16,7 @@ import { } from '@opentrons/shared-data/pipette/fixtures/name' import fixture_tiprack_10_ul from '@opentrons/shared-data/labware/fixtures/2/fixture_tiprack_10_ul.json' import { useBlockingHint } from '../../Hints/useBlockingHint' -import { FileSidebar, v7WarningContent } from '../FileSidebar' +import { FileSidebar, v8WarningContent } from '../FileSidebar' import { FLEX_TRASH_DEF_URI } from '@opentrons/step-generation' jest.mock('../../Hints/useBlockingHint') @@ -273,8 +273,8 @@ describe('FileSidebar', () => { // Before save button is clicked, enabled should be false expect(mockUseBlockingHint).toHaveBeenNthCalledWith(1, { enabled: false, - hintKey: 'export_v7_protocol_7_0', - content: v7WarningContent, + hintKey: 'export_v8_protocol_7_1', + content: v8WarningContent, handleCancel: expect.any(Function), handleContinue: expect.any(Function), }) @@ -285,8 +285,8 @@ describe('FileSidebar', () => { // After save button is clicked, enabled should be true expect(mockUseBlockingHint).toHaveBeenLastCalledWith({ enabled: true, - hintKey: 'export_v7_protocol_7_0', - content: v7WarningContent, + hintKey: 'export_v8_protocol_7_1', + content: v8WarningContent, handleCancel: expect.any(Function), handleContinue: expect.any(Function), }) diff --git a/protocol-designer/src/components/modals/AnnouncementModal/announcements.tsx b/protocol-designer/src/components/modals/AnnouncementModal/announcements.tsx index 512682dd041..b692d4b2cfd 100644 --- a/protocol-designer/src/components/modals/AnnouncementModal/announcements.tsx +++ b/protocol-designer/src/components/modals/AnnouncementModal/announcements.tsx @@ -6,6 +6,7 @@ import { JUSTIFY_SPACE_AROUND, SPACING, } from '@opentrons/components' + import styles from './AnnouncementModal.css' export interface Announcement { @@ -219,4 +220,28 @@ export const announcements: Announcement[] = [ ), }, + { + announcementKey: 'deckConfigAnd96Channel8.0', + image: ( + + + + ), + heading: "We've updated the Protocol Designer", + message: ( + <> +

    + Introducing the Protocol Designer 8.0 with deck configuration and + 96-channel pipette support! +

    +

    + All protocols now require Opentrons App version + 7.1+ to run. +

    + + ), + }, ] diff --git a/protocol-designer/src/images/deck_configuration.png b/protocol-designer/src/images/deck_configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..5a58b5f26e97aeace3e0a5acae5b754a88ffb1ff GIT binary patch literal 173096 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
    • {i18n.t('card.body.data_collected_is_internal')}
    • - {/* TODO: BC 2018-09-26 uncomment when only using fullstory
    • {i18n.t('card.body.data_only_from_pd')}
    • */} +
    • {i18n.t('card.body.data_only_from_pd')}
    • {i18n.t('card.body.opt_out_of_data_collection')}
    diff --git a/protocol-designer/src/initialize.ts b/protocol-designer/src/initialize.ts index 8131c18f072..b69af44bc07 100644 --- a/protocol-designer/src/initialize.ts +++ b/protocol-designer/src/initialize.ts @@ -1,7 +1,6 @@ import { i18n } from './localization' import { selectors as loadFileSelectors } from './load-file' -import { selectors as analyticsSelectors } from './analytics' -import { initializeFullstory } from './analytics/fullstory' + export const initialize = (store: Record): void => { if (process.env.NODE_ENV === 'production') { window.onbeforeunload = (_e: unknown) => { @@ -10,10 +9,5 @@ export const initialize = (store: Record): void => { ? i18n.t('alert.window.confirm_leave') : undefined } - - // Initialize analytics if user has already opted in - if (analyticsSelectors.getHasOptedIn(store.getState())) { - initializeFullstory() - } } } From e376d3e914d5280f9ea613eb59e2115bda937ae3 Mon Sep 17 00:00:00 2001 From: Brian Arthur Cooper Date: Thu, 9 Nov 2023 10:54:35 -0500 Subject: [PATCH 43/65] feat(app): allow multi file upload for labware and protocols (#13898) Within the file browser that launches when importing protocols or labware into the Opentrons App, support multi file select. Closes RAUT-218 --- app-shell/src/dialogs/index.ts | 18 +++++++++++ .../src/labware/__tests__/dispatch.test.ts | 8 ++++- app-shell/src/labware/index.ts | 1 + .../assets/localization/en/protocol_info.json | 2 +- .../__tests__/UploadInput.test.tsx | 4 +-- app/src/molecules/UploadInput/index.tsx | 30 +++++++------------ .../AddCustomLabwareSlideout.test.tsx | 2 +- .../ProtocolsLanding/ProtocolList.tsx | 6 ++-- ...ploadInput.tsx => ProtocolUploadInput.tsx} | 9 +++--- .../ProtocolsLanding/ProtocolsEmptyState.tsx | 4 +-- .../__tests__/UploadInput.test.tsx | 10 +++---- 11 files changed, 57 insertions(+), 37 deletions(-) rename app/src/organisms/ProtocolsLanding/{UploadInput.tsx => ProtocolUploadInput.tsx} (83%) diff --git a/app-shell/src/dialogs/index.ts b/app-shell/src/dialogs/index.ts index 5b2ef9f2b24..92e59defb39 100644 --- a/app-shell/src/dialogs/index.ts +++ b/app-shell/src/dialogs/index.ts @@ -11,6 +11,17 @@ interface BaseDialogOptions { interface FileDialogOptions extends BaseDialogOptions { filters: Array<{ name: string; extensions: string[] }> + properties: Array< + | 'openDirectory' + | 'createDirectory' + | 'openFile' + | 'multiSelections' + | 'showHiddenFiles' + | 'promptToCreate' + | 'noResolveAliases' + | 'treatPackageAsDirectory' + | 'dontAddToRecent' + > } const BASE_DIRECTORY_OPTS = { @@ -55,6 +66,13 @@ export function showOpenFileDialog( openDialogOpts = { ...openDialogOpts, filters: options.filters } } + if (options.properties != null) { + openDialogOpts = { + ...openDialogOpts, + properties: [...(openDialogOpts.properties ?? []), ...options.properties], + } + } + return dialog .showOpenDialog(browserWindow, openDialogOpts) .then((result: OpenDialogReturnValue) => { diff --git a/app-shell/src/labware/__tests__/dispatch.test.ts b/app-shell/src/labware/__tests__/dispatch.test.ts index c7a8e9198d5..f88f271956d 100644 --- a/app-shell/src/labware/__tests__/dispatch.test.ts +++ b/app-shell/src/labware/__tests__/dispatch.test.ts @@ -229,7 +229,13 @@ describe('labware module dispatches', () => { return flush().then(() => { expect(showOpenFileDialog).toHaveBeenCalledWith(mockMainWindow, { defaultPath: '__mock-app-path__', - filters: [{ name: 'JSON Labware Definitions', extensions: ['json'] }], + filters: [ + { + name: 'JSON Labware Definitions', + extensions: ['json'], + }, + ], + properties: ['multiSelections'], }) expect(dispatch).not.toHaveBeenCalled() }) diff --git a/app-shell/src/labware/index.ts b/app-shell/src/labware/index.ts index e7adcc1e4ae..f46f9134527 100644 --- a/app-shell/src/labware/index.ts +++ b/app-shell/src/labware/index.ts @@ -158,6 +158,7 @@ export function registerLabware( filters: [ { name: 'JSON Labware Definitions', extensions: ['json'] }, ], + properties: ['multiSelections' as const], } addLabwareTask = showOpenFileDialog(mainWindow, dialogOptions).then( diff --git a/app/src/assets/localization/en/protocol_info.json b/app/src/assets/localization/en/protocol_info.json index 0fc225e6f65..bbaac1ce9c2 100644 --- a/app/src/assets/localization/en/protocol_info.json +++ b/app/src/assets/localization/en/protocol_info.json @@ -3,7 +3,6 @@ "browse_protocol_library": "Open Protocol Library", "cancel_run": "Cancel Run", "choose_file": "Choose File...", - "choose_protocol_file": "Choose File", "choose_snippet_type": "Choose the Labware Offset Data Python Snippet based on target execution environment.", "continue_proceed_to_calibrate": "Proceed to Calibrate", "continue_verify_calibrations": "Verify pipette and labware calibrations", @@ -86,6 +85,7 @@ "unpin_protocol": "Unpin protocol", "unpinned_protocol": "Unpinned protocol", "update_robot_for_custom_labware": "You have custom labware definitions saved to your app, but this robot needs to be updated before you can use these definitions with Python protocols", + "upload": "Upload", "upload_and_simulate": "Open a protocol to run on {{robot_name}}", "valid_file_types": "Valid file types: Python files (.py) or Protocol Designer files (.json)" } diff --git a/app/src/molecules/UploadInput/__tests__/UploadInput.test.tsx b/app/src/molecules/UploadInput/__tests__/UploadInput.test.tsx index 945dfe756be..9da307296b0 100644 --- a/app/src/molecules/UploadInput/__tests__/UploadInput.test.tsx +++ b/app/src/molecules/UploadInput/__tests__/UploadInput.test.tsx @@ -30,12 +30,12 @@ describe('UploadInput', () => { it('renders correct contents for empty state', () => { const { getByRole } = render() - expect(getByRole('button', { name: 'Choose File' })).toBeTruthy() + expect(getByRole('button', { name: 'Upload' })).toBeTruthy() }) it('opens file select on button click', () => { const { getByRole, getByTestId } = render() - const button = getByRole('button', { name: 'Choose File' }) + const button = getByRole('button', { name: 'Upload' }) const input = getByTestId('file_input') input.click = jest.fn() fireEvent.click(button) diff --git a/app/src/molecules/UploadInput/index.tsx b/app/src/molecules/UploadInput/index.tsx index 81c52e244ec..d3fe7571d93 100644 --- a/app/src/molecules/UploadInput/index.tsx +++ b/app/src/molecules/UploadInput/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { css } from 'styled-components' +import styled, { css } from 'styled-components' import { useTranslation } from 'react-i18next' import { Icon, @@ -16,7 +16,7 @@ import { } from '@opentrons/components' import { StyledText } from '../../atoms/text' -const DROP_ZONE_STYLES = css` +const StyledLabel = styled.label` display: flex; cursor: pointer; flex-direction: ${DIRECTION_COLUMN}; @@ -39,7 +39,7 @@ const DRAG_OVER_STYLES = css` border: 2px dashed ${COLORS.blueEnabled}; ` -const INPUT_STYLES = css` +const StyledInput = styled.input` position: fixed; clip: rect(1px 1px 1px 1px); ` @@ -61,8 +61,7 @@ export function UploadInput(props: UploadInputProps): JSX.Element | null { const handleDrop: React.DragEventHandler = e => { e.preventDefault() e.stopPropagation() - const { files = [] } = 'dataTransfer' in e ? e.dataTransfer : {} - props.onUpload(files[0]) + Array.from(e.dataTransfer.files).forEach(f => props.onUpload(f)) setIsFileOverDropZone(false) } const handleDragEnter: React.DragEventHandler = e => { @@ -85,17 +84,10 @@ export function UploadInput(props: UploadInputProps): JSX.Element | null { } const onChange: React.ChangeEventHandler = event => { - const { files = [] } = event.target ?? {} - files?.[0] != null && props.onUpload(files?.[0]) + ;[...(event.target.files ?? [])].forEach(f => props.onUpload(f)) if ('value' in event.currentTarget) event.currentTarget.value = '' } - const dropZoneStyles = isFileOverDropZone - ? css` - ${DROP_ZONE_STYLES} ${DRAG_OVER_STYLES} - ` - : DROP_ZONE_STYLES - return ( - {t('choose_protocol_file')} + {t('upload')} - + ) } diff --git a/app/src/organisms/AddCustomLabwareSlideout/__tests__/AddCustomLabwareSlideout.test.tsx b/app/src/organisms/AddCustomLabwareSlideout/__tests__/AddCustomLabwareSlideout.test.tsx index a5efa4a80e7..7bf3f23675f 100644 --- a/app/src/organisms/AddCustomLabwareSlideout/__tests__/AddCustomLabwareSlideout.test.tsx +++ b/app/src/organisms/AddCustomLabwareSlideout/__tests__/AddCustomLabwareSlideout.test.tsx @@ -46,7 +46,7 @@ describe('AddCustomLabwareSlideout', () => { const [{ getByText, getByRole }] = render(props) getByText('Import a Custom Labware Definition') getByText('Or choose a file from your computer to upload.') - const btn = getByRole('button', { name: 'Choose File' }) + const btn = getByRole('button', { name: 'Upload' }) fireEvent.click(btn) expect(mockTrackEvent).toHaveBeenCalledWith({ name: ANALYTICS_ADD_CUSTOM_LABWARE, diff --git a/app/src/organisms/ProtocolsLanding/ProtocolList.tsx b/app/src/organisms/ProtocolsLanding/ProtocolList.tsx index d12e6c8fd3a..d812fed10f7 100644 --- a/app/src/organisms/ProtocolsLanding/ProtocolList.tsx +++ b/app/src/organisms/ProtocolsLanding/ProtocolList.tsx @@ -29,7 +29,7 @@ import { StyledText } from '../../atoms/text' import { Slideout } from '../../atoms/Slideout' import { ChooseRobotToRunProtocolSlideout } from '../ChooseRobotToRunProtocolSlideout' import { SendProtocolToOT3Slideout } from '../SendProtocolToOT3Slideout' -import { UploadInput } from './UploadInput' +import { ProtocolUploadInput } from './ProtocolUploadInput' import { ProtocolCard } from './ProtocolCard' import { EmptyStateLinks } from './EmptyStateLinks' import { MenuItem } from '../../atoms/MenuList/MenuItem' @@ -254,7 +254,9 @@ export function ProtocolList(props: ProtocolListProps): JSX.Element | null { onCloseClick={() => setShowImportProtocolSlideout(false)} > - setShowImportProtocolSlideout(false)} /> + setShowImportProtocolSlideout(false)} + /> diff --git a/app/src/organisms/ProtocolsLanding/UploadInput.tsx b/app/src/organisms/ProtocolsLanding/ProtocolUploadInput.tsx similarity index 83% rename from app/src/organisms/ProtocolsLanding/UploadInput.tsx rename to app/src/organisms/ProtocolsLanding/ProtocolUploadInput.tsx index aa454b9d690..181da16300f 100644 --- a/app/src/organisms/ProtocolsLanding/UploadInput.tsx +++ b/app/src/organisms/ProtocolsLanding/ProtocolUploadInput.tsx @@ -10,7 +10,7 @@ import { SPACING, } from '@opentrons/components' import { StyledText } from '../../atoms/text' -import { UploadInput as FileImporter } from '../../molecules/UploadInput' +import { UploadInput } from '../../molecules/UploadInput' import { addProtocol } from '../../redux/protocol-storage' import { useTrackEvent, @@ -24,8 +24,9 @@ export interface UploadInputProps { onUpload?: () => void } -// TODO(bc, 2022-3-21): consider making this generic for any file upload and adding it to molecules/organisms with onUpload taking the files from the event -export function UploadInput(props: UploadInputProps): JSX.Element | null { +export function ProtocolUploadInput( + props: UploadInputProps +): JSX.Element | null { const { t } = useTranslation(['protocol_info', 'shared']) const dispatch = useDispatch() const logger = useLogger(__filename) @@ -49,7 +50,7 @@ export function UploadInput(props: UploadInputProps): JSX.Element | null { alignItems={ALIGN_CENTER} marginY={SPACING.spacing20} > - handleUpload(file)} uploadText={t('valid_file_types')} dragAndDropText={ diff --git a/app/src/organisms/ProtocolsLanding/ProtocolsEmptyState.tsx b/app/src/organisms/ProtocolsLanding/ProtocolsEmptyState.tsx index 8388a075d5f..a6238653e6e 100644 --- a/app/src/organisms/ProtocolsLanding/ProtocolsEmptyState.tsx +++ b/app/src/organisms/ProtocolsLanding/ProtocolsEmptyState.tsx @@ -9,7 +9,7 @@ import { } from '@opentrons/components' import { StyledText } from '../../atoms/text' -import { UploadInput } from './UploadInput' +import { ProtocolUploadInput } from './ProtocolUploadInput' import { EmptyStateLinks } from './EmptyStateLinks' export function ProtocolsEmptyState(): JSX.Element | null { const { t } = useTranslation('protocol_info') @@ -25,7 +25,7 @@ export function ProtocolsEmptyState(): JSX.Element | null { {t('import_a_file')} - + ) diff --git a/app/src/organisms/ProtocolsLanding/__tests__/UploadInput.test.tsx b/app/src/organisms/ProtocolsLanding/__tests__/UploadInput.test.tsx index 83455f3b071..c269696c5ce 100644 --- a/app/src/organisms/ProtocolsLanding/__tests__/UploadInput.test.tsx +++ b/app/src/organisms/ProtocolsLanding/__tests__/UploadInput.test.tsx @@ -8,13 +8,13 @@ import { useTrackEvent, ANALYTICS_IMPORT_PROTOCOL_TO_APP, } from '../../../redux/analytics' -import { UploadInput } from '../UploadInput' +import { ProtocolUploadInput } from '../ProtocolUploadInput' jest.mock('../../../redux/analytics') const mockUseTrackEvent = useTrackEvent as jest.Mock -describe('UploadInput', () => { +describe('ProtocolUploadInput', () => { let onUpload: jest.MockedFunction<() => {}> let trackEvent: jest.MockedFunction let render: () => ReturnType[0] @@ -26,7 +26,7 @@ describe('UploadInput', () => { render = () => { return renderWithProviders( - + , { i18nInstance: i18n, @@ -41,7 +41,7 @@ describe('UploadInput', () => { it('renders correct contents for empty state', () => { const { findByText, getByRole } = render() - getByRole('button', { name: 'Choose File' }) + getByRole('button', { name: 'Upload' }) findByText('Drag and drop or') findByText('your files') findByText( @@ -52,7 +52,7 @@ describe('UploadInput', () => { it('opens file select on button click', () => { const { getByRole, getByTestId } = render() - const button = getByRole('button', { name: 'Choose File' }) + const button = getByRole('button', { name: 'Upload' }) const input = getByTestId('file_input') input.click = jest.fn() fireEvent.click(button) From b31abc59bedfd6e18e2f516d53cbc237c598c39d Mon Sep 17 00:00:00 2001 From: Brian Arthur Cooper Date: Thu, 9 Nov 2023 11:56:36 -0500 Subject: [PATCH 44/65] refactor(app, api-client): add utilities for parsing deck config via addressable areas (#13947) Instead of explicit load fixture commands, extrapolate the simplest possible setup for the deck given the included addressable areas referenced in a set of protocol commands Closes RAUT-853 --- api-client/src/protocols/utils.ts | 58 +++++ .../hooks/getLabwareLocationCombos.ts | 19 +- .../organisms/CommandText/LoadCommandText.tsx | 5 +- .../utils/getLabwareOffsetLocation.ts | 12 +- .../ProtocolRun/utils/getLabwareRenderInfo.ts | 5 +- .../ProtocolRun/utils/getLocationInfoNames.ts | 2 + .../utils/getRunLabwareRenderInfo.ts | 5 +- .../LabwarePositionCheck/utils/labware.ts | 5 +- .../__tests__/ProtocolSetupLabware.test.tsx | 8 - .../__tests__/utils.test.ts | 142 +++++++++++ app/src/resources/deck_configuration/utils.ts | 232 ++++++++++++++++-- .../hardware-sim/Deck/MoveLabwareOnDeck.tsx | 17 +- .../src/labware-ingred/reducers/index.ts | 2 + .../src/load-file/migration/8_0_0.ts | 2 +- shared-data/command/types/setup.ts | 2 + shared-data/deck/index.ts | 1 + shared-data/deck/types/schemaV4.ts | 64 +++++ shared-data/js/helpers/index.ts | 23 +- shared-data/js/index.ts | 1 + shared-data/js/types.ts | 23 +- shared-data/tsconfig.json | 1 + tsconfig-eslint.json | 1 + 22 files changed, 591 insertions(+), 39 deletions(-) create mode 100644 app/src/resources/deck_configuration/__tests__/utils.test.ts create mode 100644 shared-data/deck/index.ts create mode 100644 shared-data/deck/types/schemaV4.ts diff --git a/api-client/src/protocols/utils.ts b/api-client/src/protocols/utils.ts index e8f19c42a7e..4ba88a02e5e 100644 --- a/api-client/src/protocols/utils.ts +++ b/api-client/src/protocols/utils.ts @@ -16,6 +16,7 @@ import type { ModuleModel, PipetteName, RunTimeCommand, + AddressableAreaName, } from '@opentrons/shared-data' interface PipetteNamesByMount { @@ -244,6 +245,63 @@ export function parseInitialLoadedFixturesByCutout( ) } +export function parseAllAddressableAreas( + commands: RunTimeCommand[] +): AddressableAreaName[] { + return commands.reduce((acc, command) => { + if ( + command.commandType === 'moveLabware' && + command.params.newLocation !== 'offDeck' && + 'slotName' in command.params.newLocation && + !acc.includes(command.params.newLocation.slotName as AddressableAreaName) + ) { + return [ + ...acc, + command.params.newLocation.slotName as AddressableAreaName, + ] + } else if ( + command.commandType === 'moveLabware' && + command.params.newLocation !== 'offDeck' && + 'addressableAreaName' in command.params.newLocation && + !acc.includes( + command.params.newLocation.addressableAreaName as AddressableAreaName + ) + ) { + return [ + ...acc, + command.params.newLocation.addressableAreaName as AddressableAreaName, + ] + } else if ( + (command.commandType === 'loadLabware' || + command.commandType === 'loadModule') && + command.params.location !== 'offDeck' && + 'slotName' in command.params.location && + !acc.includes(command.params.location.slotName as AddressableAreaName) + ) { + return [...acc, command.params.location.slotName as AddressableAreaName] + } else if ( + command.commandType === 'loadLabware' && + command.params.location !== 'offDeck' && + 'addressableAreaName' in command.params.location && + !acc.includes( + command.params.location.addressableAreaName as AddressableAreaName + ) + ) { + return [ + ...acc, + command.params.location.addressableAreaName as AddressableAreaName, + ] + } + // TODO(BC, 11/6/23): once moveToAddressableArea command exists add it back here + // else if (command.commandType === 'moveToAddressableArea') { + // ... + // } + else { + return acc + } + }, []) +} + export interface LiquidsById { [liquidId: string]: { displayName: string diff --git a/app/src/organisms/ApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts b/app/src/organisms/ApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts index b297775880f..2555c5e8441 100644 --- a/app/src/organisms/ApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts +++ b/app/src/organisms/ApplyHistoricOffsets/hooks/getLabwareLocationCombos.ts @@ -59,7 +59,12 @@ export function getLabwareLocationCombos( }) } else { return appendLocationComboIfUniq(acc, { - location: command.params.location, + location: { + slotName: + 'addressableAreaName' in command.params.location + ? command.params.location.addressableAreaName + : command.params.location.slotName, + }, definitionUri, labwareId: command.result.labwareId, }) @@ -107,7 +112,12 @@ export function getLabwareLocationCombos( }) } else { return appendLocationComboIfUniq(acc, { - location: command.params.newLocation, + location: { + slotName: + 'addressableAreaName' in command.params.newLocation + ? command.params.newLocation.addressableAreaName + : command.params.newLocation.slotName, + }, definitionUri: labwareEntity.definitionUri, labwareId: command.params.labwareId, }) @@ -191,7 +201,10 @@ function resolveAdapterLocation( } else { adapterOffsetLocation = { definitionUri: labwareDefUri, - slotName: labwareEntity.location.slotName, + slotName: + 'addressableAreaName' in labwareEntity.location + ? labwareEntity.location.addressableAreaName + : labwareEntity.location.slotName, } } return { diff --git a/app/src/organisms/CommandText/LoadCommandText.tsx b/app/src/organisms/CommandText/LoadCommandText.tsx index 5446ad1acc6..52ddc0ec7da 100644 --- a/app/src/organisms/CommandText/LoadCommandText.tsx +++ b/app/src/organisms/CommandText/LoadCommandText.tsx @@ -136,7 +136,10 @@ export const LoadCommandText = ({ ? t('load_labware_info_protocol_setup_off_deck', { labware }) : t('load_labware_info_protocol_setup_no_module', { labware, - slot_name: command.params.location?.slotName, + slot_name: + 'addressableAreaName' in command.params.location + ? command.params.location.addressableAreaName + : command.params.location.slotName, }) } } diff --git a/app/src/organisms/Devices/ProtocolRun/utils/getLabwareOffsetLocation.ts b/app/src/organisms/Devices/ProtocolRun/utils/getLabwareOffsetLocation.ts index e831be067d9..287c5ef1338 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/getLabwareOffsetLocation.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/getLabwareOffsetLocation.ts @@ -39,6 +39,11 @@ export const getLabwareOffsetLocation = ( slotName: adapter.location.slotName, definitionUri: adapter.definitionUri, } + } else if ('addressableAreaName' in adapter.location) { + return { + slotName: adapter.location.addressableAreaName, + definitionUri: adapter.definitionUri, + } } else if ('moduleId' in adapter.location) { const moduleIdUnderAdapter = adapter.location.moduleId const moduleModel = modules.find( @@ -52,7 +57,12 @@ export const getLabwareOffsetLocation = ( return { slotName, moduleModel, definitionUri: adapter.definitionUri } } } else { - return { slotName: labwareLocation.slotName } + return { + slotName: + 'addressableAreaName' in labwareLocation + ? labwareLocation.addressableAreaName + : labwareLocation.slotName, + } } return null } diff --git a/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts b/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts index 86ae0ec6146..f5fcc0ea240 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts @@ -75,7 +75,10 @@ export const getLabwareRenderInfo = ( ) } // TODO(bh, 2023-10-19): convert this to deck definition v4 addressableAreas - const slotName = location.slotName.toString() + const slotName = + 'addressableAreaName' in location + ? location.addressableAreaName + : location.slotName // TODO(bh, 2023-10-19): remove slotPosition when render info no longer relies on directly const slotPosition = getSlotPosition(deckDef, slotName) diff --git a/app/src/organisms/Devices/ProtocolRun/utils/getLocationInfoNames.ts b/app/src/organisms/Devices/ProtocolRun/utils/getLocationInfoNames.ts index ee49db3573e..594d5d37f97 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/getLocationInfoNames.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/getLocationInfoNames.ts @@ -46,6 +46,8 @@ export function getLocationInfoNames( return { slotName: 'Off deck', labwareName } } else if ('slotName' in labwareLocation) { return { slotName: labwareLocation.slotName, labwareName } + } else if ('addressableAreaName' in labwareLocation) { + return { slotName: labwareLocation.addressableAreaName, labwareName } } else if ('moduleId' in labwareLocation) { const loadModuleCommandUnderLabware = loadModuleCommands?.find( command => command.result?.moduleId === labwareLocation.moduleId diff --git a/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts b/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts index 12718b07411..3590d470522 100644 --- a/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts +++ b/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts @@ -36,7 +36,10 @@ export function getRunLabwareRenderInfo( } if (location !== 'offDeck') { - const slotName = location.slotName + const slotName = + 'addressableAreaName' in location + ? location.addressableAreaName + : location.slotName const slotPosition = deckDef.locations.orderedSlots.find(slot => slot.id === slotName) ?.position ?? [] diff --git a/app/src/organisms/LabwarePositionCheck/utils/labware.ts b/app/src/organisms/LabwarePositionCheck/utils/labware.ts index fdaa37ba2ee..bdd6f019aaf 100644 --- a/app/src/organisms/LabwarePositionCheck/utils/labware.ts +++ b/app/src/organisms/LabwarePositionCheck/utils/labware.ts @@ -192,7 +192,10 @@ export const getLabwareIdsInOrder = ( ).location.slotName } } else { - slot = loc.slotName + slot = + 'addressableAreaName' in loc + ? loc.addressableAreaName + : loc.slotName } return [ ...innerAcc, diff --git a/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx b/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx index a9ee4c013a9..9a9c2a9999e 100644 --- a/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx +++ b/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx @@ -7,7 +7,6 @@ import { useModulesQuery, } from '@opentrons/react-api-client' import { renderWithProviders } from '@opentrons/components' -import { getDeckDefFromRobotType } from '@opentrons/shared-data' import ot3StandardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot3_standard.json' import { i18n } from '../../../i18n' @@ -25,7 +24,6 @@ import { } from '../__fixtures__' jest.mock('@opentrons/react-api-client') -jest.mock('@opentrons/shared-data/js/helpers') jest.mock( '../../../organisms/LabwarePositionCheck/useMostRecentCompletedAnalysis' ) @@ -37,9 +35,6 @@ const mockUseCreateLiveCommandMutation = useCreateLiveCommandMutation as jest.Mo const mockUseModulesQuery = useModulesQuery as jest.MockedFunction< typeof useModulesQuery > -const mockGetDeckDefFromRobotType = getDeckDefFromRobotType as jest.MockedFunction< - typeof getDeckDefFromRobotType -> const mockUseMostRecentCompletedAnalysis = useMostRecentCompletedAnalysis as jest.MockedFunction< typeof useMostRecentCompletedAnalysis > @@ -72,9 +67,6 @@ describe('ProtocolSetupLabware', () => { when(mockUseMostRecentCompletedAnalysis) .calledWith(RUN_ID) .mockReturnValue(mockRecentAnalysis) - when(mockGetDeckDefFromRobotType) - .calledWith('OT-3 Standard') - .mockReturnValue(ot3StandardDeckDef as any) when(mockGetProtocolModulesInfo) .calledWith(mockRecentAnalysis, ot3StandardDeckDef as any) .mockReturnValue(mockProtocolModuleInfo) diff --git a/app/src/resources/deck_configuration/__tests__/utils.test.ts b/app/src/resources/deck_configuration/__tests__/utils.test.ts new file mode 100644 index 00000000000..3fd7f03baac --- /dev/null +++ b/app/src/resources/deck_configuration/__tests__/utils.test.ts @@ -0,0 +1,142 @@ +import { RunTimeCommand } from '@opentrons/shared-data' +import { + FLEX_SIMPLEST_DECK_CONFIG, + getSimplestDeckConfigForProtocolCommands, +} from '../utils' + +const RUN_TIME_COMMAND_STUB_MIXIN: Pick< + RunTimeCommand, + 'id' | 'createdAt' | 'startedAt' | 'completedAt' | 'status' +> = { + id: 'fake_id', + createdAt: 'fake_createdAt', + startedAt: 'fake_startedAt', + completedAt: 'fake_createdAt', + status: 'succeeded', +} + +describe('getSimplestDeckConfigForProtocolCommands', () => { + it('returns simplest deck if no commands alter addressable areas', () => { + expect(getSimplestDeckConfigForProtocolCommands([])).toEqual( + FLEX_SIMPLEST_DECK_CONFIG + ) + }) + it('returns staging area fixtures if commands address column 4 areas', () => { + const cutoutConfigs = getSimplestDeckConfigForProtocolCommands([ + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'loadLabware', + params: { + loadName: 'fake_load_name', + location: { slotName: 'A4' }, + version: 1, + namespace: 'fake_namespace', + }, + }, + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'loadLabware', + params: { + loadName: 'fake_load_name', + location: { slotName: 'B4' }, + version: 1, + namespace: 'fake_namespace', + }, + }, + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'loadLabware', + params: { + loadName: 'fake_load_name', + location: { slotName: 'C4' }, + version: 1, + namespace: 'fake_namespace', + }, + }, + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'loadLabware', + params: { + loadName: 'fake_load_name', + location: { slotName: 'D4' }, + version: 1, + namespace: 'fake_namespace', + }, + }, + ]) + expect(cutoutConfigs).toEqual([ + ...FLEX_SIMPLEST_DECK_CONFIG.slice(0, 8), + { + cutoutId: 'cutoutA3', + cutoutFixtureId: 'stagingAreaRightSlot', + requiredAddressableAreas: ['A4'], + }, + { + cutoutId: 'cutoutB3', + cutoutFixtureId: 'stagingAreaRightSlot', + requiredAddressableAreas: ['B4'], + }, + { + cutoutId: 'cutoutC3', + cutoutFixtureId: 'stagingAreaRightSlot', + requiredAddressableAreas: ['C4'], + }, + { + cutoutId: 'cutoutD3', + cutoutFixtureId: 'stagingAreaRightSlot', + requiredAddressableAreas: ['D4'], + }, + ]) + }) + it('returns simplest cutout fixture where many are possible', () => { + const cutoutConfigs = getSimplestDeckConfigForProtocolCommands([ + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'moveLabware', + params: { + newLocation: { addressableAreaName: 'gripperWasteChute' }, + labwareId: 'fake_labwareId', + strategy: 'usingGripper', + }, + }, + ]) + expect(cutoutConfigs).toEqual([ + ...FLEX_SIMPLEST_DECK_CONFIG.slice(0, 11), + { + cutoutId: 'cutoutD3', + cutoutFixtureId: 'wasteChuteRightAdapterNoCover', + requiredAddressableAreas: ['gripperWasteChute'], + }, + ]) + }) + it('returns compatible cutout fixture where multiple addressable requirements present', () => { + const cutoutConfigs = getSimplestDeckConfigForProtocolCommands([ + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'moveLabware', + params: { + newLocation: { addressableAreaName: 'gripperWasteChute' }, + labwareId: 'fake_labwareId', + strategy: 'usingGripper', + }, + }, + { + ...RUN_TIME_COMMAND_STUB_MIXIN, + commandType: 'moveLabware', + params: { + newLocation: { addressableAreaName: 'D4' }, + labwareId: 'fake_labwareId', + strategy: 'usingGripper', + }, + }, + ]) + expect(cutoutConfigs).toEqual([ + ...FLEX_SIMPLEST_DECK_CONFIG.slice(0, 11), + { + cutoutId: 'cutoutD3', + cutoutFixtureId: 'stagingAreaSlotWithWasteChuteRightAdapterNoCover', + requiredAddressableAreas: ['gripperWasteChute', 'D4'], + }, + ]) + }) +}) diff --git a/app/src/resources/deck_configuration/utils.ts b/app/src/resources/deck_configuration/utils.ts index 7acdd5c80ef..fdc59aa539b 100644 --- a/app/src/resources/deck_configuration/utils.ts +++ b/app/src/resources/deck_configuration/utils.ts @@ -1,23 +1,227 @@ -import { v4 as uuidv4 } from 'uuid' +import { parseAllAddressableAreas } from '@opentrons/api-client' +import { + FLEX_ROBOT_TYPE, + getDeckDefFromRobotTypeV4, +} from '@opentrons/shared-data' -import { parseInitialLoadedFixturesByCutout } from '@opentrons/api-client' -import { STANDARD_SLOT_DECK_CONFIG_FIXTURE } from '@opentrons/components' +import type { + CutoutId, + DeckConfiguration, + RunTimeCommand, + Cutout, + CutoutFixtureId, + CutoutFixture, + AddressableAreaName, + FixtureLoadName, +} from '@opentrons/shared-data' -import type { DeckConfiguration, RunTimeCommand } from '@opentrons/shared-data' +interface CutoutConfig { + cutoutId: CutoutId + cutoutFixtureId: CutoutFixtureId + requiredAddressableAreas: AddressableAreaName[] +} -export function getDeckConfigFromProtocolCommands( +export const FLEX_SIMPLEST_DECK_CONFIG: CutoutConfig[] = [ + { + cutoutId: 'cutoutA1', + cutoutFixtureId: 'singleLeftSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutB1', + cutoutFixtureId: 'singleLeftSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutC1', + cutoutFixtureId: 'singleLeftSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutD1', + cutoutFixtureId: 'singleLeftSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutA2', + cutoutFixtureId: 'singleCenterSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutB2', + cutoutFixtureId: 'singleCenterSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutC2', + cutoutFixtureId: 'singleCenterSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutD2', + cutoutFixtureId: 'singleCenterSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutA3', + cutoutFixtureId: 'singleRightSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutB3', + cutoutFixtureId: 'singleRightSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutC3', + cutoutFixtureId: 'singleRightSlot', + requiredAddressableAreas: [], + }, + { + cutoutId: 'cutoutD3', + cutoutFixtureId: 'singleRightSlot', + requiredAddressableAreas: [], + }, +] + +export function getSimplestDeckConfigForProtocolCommands( protocolAnalysisCommands: RunTimeCommand[] +): CutoutConfig[] { + // TODO(BC, 2023-11-06): abstract out the robot type + const deckDef = getDeckDefFromRobotTypeV4(FLEX_ROBOT_TYPE) + + const addressableAreas = parseAllAddressableAreas(protocolAnalysisCommands) + const simplestDeckConfig = addressableAreas.reduce( + (acc, addressableArea) => { + const cutoutFixturesForAddressableArea = getCutoutFixturesForAddressableAreas( + [addressableArea], + deckDef.cutoutFixtures + ) + const cutoutIdForAddressableArea = getCutoutIdForAddressableArea( + addressableArea, + cutoutFixturesForAddressableArea + ) + const cutoutFixturesForCutoutId = + cutoutIdForAddressableArea != null + ? getCutoutFixturesForCutoutId( + cutoutIdForAddressableArea, + deckDef.cutoutFixtures + ) + : null + + const existingCutoutConfig = acc.find( + cutoutConfig => cutoutConfig.cutoutId === cutoutIdForAddressableArea + ) + + if ( + existingCutoutConfig != null && + cutoutFixturesForCutoutId != null && + cutoutIdForAddressableArea != null + ) { + const indexOfExistingFixture = cutoutFixturesForCutoutId.findIndex( + ({ id }) => id === existingCutoutConfig.cutoutFixtureId + ) + const accIndex = acc.findIndex( + ({ cutoutId }) => cutoutId === cutoutIdForAddressableArea + ) + const previousRequiredAAs = acc[accIndex]?.requiredAddressableAreas + const allNextRequiredAddressableAreas = previousRequiredAAs.includes( + addressableArea + ) + ? previousRequiredAAs + : [...previousRequiredAAs, addressableArea] + const nextCompatibleCutoutFixture = getSimplestFixtureForAddressableAreas( + cutoutIdForAddressableArea, + allNextRequiredAddressableAreas, + cutoutFixturesForCutoutId + ) + const indexOfCurrentFixture = cutoutFixturesForCutoutId.findIndex( + ({ id }) => id === nextCompatibleCutoutFixture?.id + ) + + if ( + nextCompatibleCutoutFixture != null && + indexOfCurrentFixture > indexOfExistingFixture + ) { + return [ + ...acc.slice(0, accIndex), + { + cutoutId: cutoutIdForAddressableArea, + cutoutFixtureId: nextCompatibleCutoutFixture.id, + requiredAddressableAreas: allNextRequiredAddressableAreas, + }, + ...acc.slice(accIndex + 1), + ] + } + } + return acc + }, + FLEX_SIMPLEST_DECK_CONFIG + ) + + return simplestDeckConfig +} + +// TODO(BC, 11/7/23): remove this function in favor of getSimplestDeckConfigForProtocolCommands +export function getDeckConfigFromProtocolCommands( + commands: RunTimeCommand[] ): DeckConfiguration { - const loadedFixtureCommands = Object.values( - parseInitialLoadedFixturesByCutout(protocolAnalysisCommands) + return getSimplestDeckConfigForProtocolCommands(commands).map( + ({ cutoutId, cutoutFixtureId }) => ({ + fixtureId: cutoutFixtureId, + fixtureLocation: cutoutId as Cutout, + loadName: cutoutFixtureId as FixtureLoadName, + }) ) +} - const deckConfig = loadedFixtureCommands.map(command => ({ - fixtureId: command.params.fixtureId ?? uuidv4(), - fixtureLocation: command.params.location.cutout, - loadName: command.params.loadName, - })) +function getCutoutFixturesForAddressableAreas( + addressableAreas: AddressableAreaName[], + cutoutFixtures: CutoutFixture[] +): CutoutFixture[] { + return cutoutFixtures.filter(cutoutFixture => + Object.values(cutoutFixture.providesAddressableAreas).some(providedAAs => + addressableAreas.every(aa => providedAAs.includes(aa)) + ) + ) +} - // TODO(bh, 2023-10-18): remove stub when load fixture commands available - return deckConfig.length > 0 ? deckConfig : STANDARD_SLOT_DECK_CONFIG_FIXTURE +function getCutoutFixturesForCutoutId( + cutoutId: CutoutId, + cutoutFixtures: CutoutFixture[] +): CutoutFixture[] { + return cutoutFixtures.filter(cutoutFixture => + cutoutFixture.mayMountTo.some(mayMountTo => mayMountTo.includes(cutoutId)) + ) +} + +function getCutoutIdForAddressableArea( + addressableArea: AddressableAreaName, + cutoutFixtures: CutoutFixture[] +): CutoutId | null { + return cutoutFixtures.reduce((acc, cutoutFixture) => { + const [cutoutId] = + Object.entries( + cutoutFixture.providesAddressableAreas + ).find(([_cutoutId, providedAAs]) => + providedAAs.includes(addressableArea) + ) ?? [] + return (cutoutId as CutoutId) ?? acc + }, null) +} + +function getSimplestFixtureForAddressableAreas( + cutoutId: CutoutId, + requiredAddressableAreas: AddressableAreaName[], + allCutoutFixtures: CutoutFixture[] +): CutoutFixture | null { + const cutoutFixturesForCutoutId = getCutoutFixturesForCutoutId( + cutoutId, + allCutoutFixtures + ) + const nextCompatibleCutoutFixtures = getCutoutFixturesForAddressableAreas( + requiredAddressableAreas, + cutoutFixturesForCutoutId + ) + return nextCompatibleCutoutFixtures?.[0] ?? null } diff --git a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx index 55656526e1b..a93f06ca8ae 100644 --- a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx +++ b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx @@ -85,7 +85,11 @@ function getLabwareCoordinates({ // adapter on deck const loadedAdapterSlot = orderedSlots.find( - s => s.id === loadedAdapterLocation.slotName + s => + s.id === + ('slotName' in loadedAdapterLocation + ? loadedAdapterLocation.slotName + : loadedAdapterLocation.addressableAreaName) ) return loadedAdapterSlot != null ? { @@ -94,6 +98,17 @@ function getLabwareCoordinates({ z: loadedAdapterSlot.position[2], } : null + } else if ('addressableAreaName' in location) { + const slotCoordinateTuple = + orderedSlots.find(s => s.id === location.addressableAreaName)?.position ?? + null + return slotCoordinateTuple != null + ? { + x: slotCoordinateTuple[0], + y: slotCoordinateTuple[1], + z: slotCoordinateTuple[2], + } + : null } else if ('slotName' in location) { const slotCoordinateTuple = orderedSlots.find(s => s.id === location.slotName)?.position ?? null diff --git a/protocol-designer/src/labware-ingred/reducers/index.ts b/protocol-designer/src/labware-ingred/reducers/index.ts index a26e5b1b95f..4d0fd60f10f 100644 --- a/protocol-designer/src/labware-ingred/reducers/index.ts +++ b/protocol-designer/src/labware-ingred/reducers/index.ts @@ -232,6 +232,8 @@ export const savedLabware: Reducer = handleActions( slot = location.moduleId } else if ('labwareId' in location) { slot = location.labwareId + } else if ('addressableAreaName' in location) { + slot = location.addressableAreaName } else { slot = location.slotName } diff --git a/protocol-designer/src/load-file/migration/8_0_0.ts b/protocol-designer/src/load-file/migration/8_0_0.ts index 734f2f9ea46..c7afb0bbffe 100644 --- a/protocol-designer/src/load-file/migration/8_0_0.ts +++ b/protocol-designer/src/load-file/migration/8_0_0.ts @@ -18,12 +18,12 @@ import type { CommandV8Mixin, LabwareV2Mixin, LiquidV1Mixin, - LoadLabwareCreateCommand, OT2RobotMixin, OT3RobotMixin, ProtocolBase, ProtocolFile, } from '@opentrons/shared-data/protocol/types/schemaV8' +import type { LoadLabwareCreateCommand } from '@opentrons/shared-data/protocol/types/schemaV7' import type { DesignerApplicationData } from './utils/getLoadLiquidCommands' // NOTE: this migration is to schema v8 and updates fixed trash by diff --git a/shared-data/command/types/setup.ts b/shared-data/command/types/setup.ts index fd43093d16c..f8fb78752e5 100644 --- a/shared-data/command/types/setup.ts +++ b/shared-data/command/types/setup.ts @@ -92,11 +92,13 @@ export type LabwareLocation = | { slotName: string } | { moduleId: string } | { labwareId: string } + | { addressableAreaName: string } export type NonStackedLocation = | 'offDeck' | { slotName: string } | { moduleId: string } + | { addressableAreaName: string } export interface ModuleLocation { slotName: string diff --git a/shared-data/deck/index.ts b/shared-data/deck/index.ts new file mode 100644 index 00000000000..f05ccb33b7f --- /dev/null +++ b/shared-data/deck/index.ts @@ -0,0 +1 @@ +export * from './types/schemaV4' diff --git a/shared-data/deck/types/schemaV4.ts b/shared-data/deck/types/schemaV4.ts new file mode 100644 index 00000000000..f81029da61e --- /dev/null +++ b/shared-data/deck/types/schemaV4.ts @@ -0,0 +1,64 @@ +export type FlexAddressableAreaName = + | 'D1' + | 'D2' + | 'D3' + | 'C1' + | 'C2' + | 'C3' + | 'B1' + | 'B2' + | 'B3' + | 'A1' + | 'A2' + | 'A3' + | 'A4' + | 'B4' + | 'C4' + | 'D4' + | 'movableTrash' + | '1and8ChannelWasteChute' + | '96ChannelWasteChute' + | 'gripperWasteChute' + +export type OT2AddressableAreaName = + | '1' + | '2' + | '3' + | '4' + | '5' + | '6' + | '7' + | '8' + | '9' + | '10' + | '11' + | 'fixedTrash' + +export type AddressableAreaName = + | FlexAddressableAreaName + | OT2AddressableAreaName + +export type CutoutId = + | 'cutoutD1' + | 'cutoutD2' + | 'cutoutD3' + | 'cutoutC1' + | 'cutoutC2' + | 'cutoutC3' + | 'cutoutB1' + | 'cutoutB2' + | 'cutoutB3' + | 'cutoutA1' + | 'cutoutA2' + | 'cutoutA3' + +export type CutoutFixtureId = + | 'singleLeftSlot' + | 'singleCenterSlot' + | 'singleRightSlot' + | 'stagingAreaRightSlot' + | 'trashBinAdapter' + | 'wasteChuteRightAdapterCovered' + | 'wasteChuteRightAdapterNoCover' + | 'stagingAreaSlotWithWasteChuteRightAdapterCovered' + | 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' diff --git a/shared-data/js/helpers/index.ts b/shared-data/js/helpers/index.ts index 7c6cebc3847..c686898f9bc 100644 --- a/shared-data/js/helpers/index.ts +++ b/shared-data/js/helpers/index.ts @@ -2,8 +2,10 @@ import assert from 'assert' import uniq from 'lodash/uniq' import { OPENTRONS_LABWARE_NAMESPACE } from '../constants' -import standardDeckDefOt2 from '../../deck/definitions/3/ot2_standard.json' -import standardDeckDefOt3 from '../../deck/definitions/3/ot3_standard.json' +import standardOt2DeckDefv3 from '../../deck/definitions/3/ot2_standard.json' +import standardFlexDeckDefv3 from '../../deck/definitions/3/ot3_standard.json' +import standardOt2DeckDef from '../../deck/definitions/4/ot2_standard.json' +import standardFlexDeckDef from '../../deck/definitions/4/ot3_standard.json' import type { DeckDefinition, LabwareDefinition2, @@ -224,7 +226,7 @@ export const getAreSlotsHorizontallyAdjacent = ( if (isNaN(slotBNumber) || isNaN(slotANumber)) { return false } - const orderedSlots = standardDeckDefOt2.locations.orderedSlots + const orderedSlots = standardOt2DeckDefv3.locations.orderedSlots // intentionally not substracting by 1 because trash (slot 12) should not count const numSlots = orderedSlots.length @@ -260,7 +262,7 @@ export const getAreSlotsVerticallyAdjacent = ( if (isNaN(slotBNumber) || isNaN(slotANumber)) { return false } - const orderedSlots = standardDeckDefOt2.locations.orderedSlots + const orderedSlots = standardOt2DeckDefv3.locations.orderedSlots // intentionally not substracting by 1 because trash (slot 12) should not count const numSlots = orderedSlots.length @@ -349,5 +351,16 @@ export const getDeckDefFromRobotType = ( 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' ? standardDeckDefOt3 : standardDeckDefOt2 + return robotType === 'OT-3 Standard' + ? standardFlexDeckDefv3 + : standardOt2DeckDefv3 +} + +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 } diff --git a/shared-data/js/index.ts b/shared-data/js/index.ts index 61fe3babedf..ce7335fa426 100644 --- a/shared-data/js/index.ts +++ b/shared-data/js/index.ts @@ -8,6 +8,7 @@ export * from './modules' export * from './fixtures' export * from './gripper' export * from '../protocol' +export * from '../deck' export * from './titleCase' export * from './errors' export * from './fixtures' diff --git a/shared-data/js/types.ts b/shared-data/js/types.ts index 07b5302b63d..28b509a7f26 100644 --- a/shared-data/js/types.ts +++ b/shared-data/js/types.ts @@ -30,9 +30,9 @@ import { WASTE_CHUTE_LOAD_NAME, } from './constants' import type { INode } from 'svgson' -import type { RunTimeCommand } from '../command/types' +import type { RunTimeCommand, LabwareLocation } from '../command/types' import type { PipetteName } from './pipettes' -import type { LabwareLocation } from '../protocol/types/schemaV7/command/setup' +import type { AddressableAreaName, CutoutFixtureId, CutoutId } from '../deck' export type RobotType = 'OT-2 Standard' | 'OT-3 Standard' @@ -284,10 +284,28 @@ export interface DeckCalibrationPoint { displayName: string } +export interface CutoutFixture { + id: CutoutFixtureId + mayMountTo: CutoutId[] + displayName: string + providesAddressableAreas: Record +} + +export interface AddressableArea { + id: AddressableAreaName + areaType: 'slot' | 'movableTrash' | 'fixedTrash' | 'wasteChute' + matingSurfaceUnitVector: UnitVectorTuple + offsetFromCutoutFixture: UnitVectorTuple + boundingBox: Dimensions + displayName: string + compatibleModuleTypes: ModuleType[] +} + export interface DeckLocations { orderedSlots: DeckSlot[] calibrationPoints: DeckCalibrationPoint[] fixtures: DeckFixture[] + addressableAreas: AddressableArea[] } export interface DeckMetadata { @@ -300,6 +318,7 @@ export interface DeckDefinition { cornerOffsetFromOrigin: CoordinateTuple dimensions: CoordinateTuple robot: DeckRobot + cutoutFixtures: CutoutFixture[] locations: DeckLocations metadata: DeckMetadata layers: INode[] diff --git a/shared-data/tsconfig.json b/shared-data/tsconfig.json index 1b1c50493db..bfeef7fb684 100644 --- a/shared-data/tsconfig.json +++ b/shared-data/tsconfig.json @@ -9,6 +9,7 @@ "include": [ "js", "protocol", + "deck", "command/types", "liquid/types", "commandAnnotation/types" diff --git a/tsconfig-eslint.json b/tsconfig-eslint.json index 555566fb1f5..11672e612c6 100644 --- a/tsconfig-eslint.json +++ b/tsconfig-eslint.json @@ -19,6 +19,7 @@ "labware-designer/typings", "labware-library/src", "labware-library/typings", + "shared-data/deck", "shared-data/js", "shared-data/protocol", "shared-data/pipette", From cc8cf3cc7234a67b2a6de11d8025008b51ba573b Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Thu, 9 Nov 2023 12:50:20 -0500 Subject: [PATCH 45/65] feat(protocol-designer): wire up unused equipment logic for waste chute (#13957) closes RAUT-814 --- .../components/FileSidebar/FileSidebar.tsx | 3 +- ...Areas.ts => getUnusedStagingAreas.test.ts} | 0 .../utils/__tests__/getUnusedTrash.test.ts | 45 +++++++++++++++++-- .../FileSidebar/utils/getUnusedTrash.ts | 19 ++++++-- 4 files changed, 59 insertions(+), 8 deletions(-) rename protocol-designer/src/components/FileSidebar/utils/__tests__/{getUnusedStagingAreas.ts => getUnusedStagingAreas.test.ts} (100%) diff --git a/protocol-designer/src/components/FileSidebar/FileSidebar.tsx b/protocol-designer/src/components/FileSidebar/FileSidebar.tsx index 2b3e1c1daf5..a5f563888c7 100644 --- a/protocol-designer/src/components/FileSidebar/FileSidebar.tsx +++ b/protocol-designer/src/components/FileSidebar/FileSidebar.tsx @@ -256,13 +256,12 @@ export function FileSidebar(props: Props): JSX.Element { ) const { trashBinUnused, wasteChuteUnused } = getUnusedTrash( labwareOnDeck, - // additionalEquipment, + additionalEquipment, fileData?.commands ) const fixtureWithoutStep: Fixture = { trashBin: trashBinUnused, - // TODO(jr, 10/30/23): wire this up later when we know waste chute commands wasteChute: wasteChuteUnused, stagingAreaSlots: getUnusedStagingAreas( additionalEquipment, diff --git a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.ts b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts similarity index 100% rename from protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.ts rename to protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts diff --git a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts index 474a2f9d733..3d66dec7c66 100644 --- a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts +++ b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedTrash.test.ts @@ -2,6 +2,7 @@ import { FLEX_TRASH_DEF_URI } from '../../../../constants' import { getUnusedTrash } from '../getUnusedTrash' import type { CreateCommand } from '@opentrons/shared-data' import type { InitialDeckSetup } from '../../../../step-forms' +import type { AdditionalEquipment } from '../../FileSidebar' describe('getUnusedTrash', () => { it('returns true for unused trash bin', () => { @@ -10,7 +11,7 @@ describe('getUnusedTrash', () => { [labwareId]: { labwareDefURI: FLEX_TRASH_DEF_URI, id: labwareId }, } as unknown) as InitialDeckSetup['labware'] - expect(getUnusedTrash(mockTrash, [])).toEqual({ + expect(getUnusedTrash(mockTrash, {}, [])).toEqual({ trashBinUnused: true, wasteChuteUnused: false, }) @@ -29,10 +30,48 @@ describe('getUnusedTrash', () => { }, ] as unknown) as CreateCommand[] - expect(getUnusedTrash(mockTrash, mockCommand)).toEqual({ + expect(getUnusedTrash(mockTrash, {}, mockCommand)).toEqual({ trashBinUnused: true, wasteChuteUnused: false, }) }) - // TODO(jr, 10/30/23): add test coverage for waste chute + it('returns true for unused waste chute', () => { + const wasteChute = 'wasteChuteId' + const mockAdditionalEquipment = { + [wasteChute]: { + name: 'wasteChute', + id: wasteChute, + location: 'cutoutD3', + }, + } as AdditionalEquipment + expect(getUnusedTrash({}, mockAdditionalEquipment, [])).toEqual({ + trashBinUnused: false, + wasteChuteUnused: true, + }) + }) + it('returns false for unused waste chute', () => { + const wasteChute = 'wasteChuteId' + const mockAdditionalEquipment = { + [wasteChute]: { + name: 'wasteChute', + id: wasteChute, + location: 'cutoutD3', + }, + } as AdditionalEquipment + const mockCommand = ([ + { + labwareId: { + commandType: 'moveToAddressableArea', + params: { + pipetteId: 'mockId', + addressableAreaName: '1and8ChannelWasteChute', + }, + }, + }, + ] as unknown) as CreateCommand[] + expect(getUnusedTrash({}, mockAdditionalEquipment, mockCommand)).toEqual({ + trashBinUnused: false, + wasteChuteUnused: true, + }) + }) }) diff --git a/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts b/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts index 2585b2c75eb..90cf88e6ada 100644 --- a/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts +++ b/protocol-designer/src/components/FileSidebar/utils/getUnusedTrash.ts @@ -11,9 +11,9 @@ interface UnusedTrash { wasteChuteUnused: boolean } -// TODO(jr, 10/30/23): plug in waste chute logic when we know the commands! export const getUnusedTrash = ( labwareOnDeck: InitialDeckSetup['labware'], + additionalEquipment: InitialDeckSetup['additionalEquipmentOnDeck'], commands?: CreateCommand[] ): UnusedTrash => { const trashBin = Object.values(labwareOnDeck).find( @@ -21,7 +21,6 @@ export const getUnusedTrash = ( labware.labwareDefURI === FLEX_TRASH_DEF_URI || labware.labwareDefURI === OT_2_TRASH_DEF_URI ) - const hasTrashBinCommands = trashBin != null ? commands?.some( @@ -32,8 +31,22 @@ export const getUnusedTrash = ( command.params.labwareId === trashBin.id) ) : null + const wasteChute = Object.values(additionalEquipment).find( + aE => aE.name === 'wasteChute' + ) + const hasWasteChuteCommands = + wasteChute != null + ? commands?.some( + command => + command.commandType === 'moveToAddressableArea' && + (command.params.addressableAreaName === '1and8ChannelWasteChute' || + command.params.addressableAreaName === 'gripperWasteChute' || + command.params.addressableAreaName === '96ChannelWasteChute') + ) + : null + return { trashBinUnused: trashBin != null && !hasTrashBinCommands, - wasteChuteUnused: false, + wasteChuteUnused: wasteChute != null && !hasWasteChuteCommands, } } From 5db88638e717df44e82b2cd5ec6fd2dd87bc4879 Mon Sep 17 00:00:00 2001 From: Alise Au <20424172+ahiuchingau@users.noreply.github.com> Date: Thu, 9 Nov 2023 13:19:26 -0500 Subject: [PATCH 46/65] fix origin & target for fast home should not include other axes (#13955) --- api/src/opentrons/hardware_control/ot3api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/opentrons/hardware_control/ot3api.py b/api/src/opentrons/hardware_control/ot3api.py index 11b9682805c..1842d26152d 100644 --- a/api/src/opentrons/hardware_control/ot3api.py +++ b/api/src/opentrons/hardware_control/ot3api.py @@ -1397,9 +1397,9 @@ async def _retrieve_home_position( self, axis: Axis ) -> Tuple[OT3AxisMap[float], OT3AxisMap[float]]: origin = await self._backend.update_position() - target_pos = {ax: pos for ax, pos in origin.items()} - target_pos.update({axis: self._backend.home_position()[axis]}) - return origin, target_pos + origin_pos = {axis: origin[axis]} + target_pos = {axis: self._backend.home_position()[axis]} + return origin_pos, target_pos @_adjust_high_throughput_z_current async def _home_axis(self, axis: Axis) -> None: From 66cd8fc67881db001c696fe4f9d18853b356d227 Mon Sep 17 00:00:00 2001 From: Sarah Breen Date: Thu, 9 Nov 2023 13:45:40 -0500 Subject: [PATCH 47/65] feat(app): final copy and animations for golden tip LPC probe screens (#13941) fix RAUT-810, RAUT-811 --- .../images/lpc_level_probe_with_labware.svg | 315 ++++++++++++++++++ .../images/lpc_level_probe_with_tip.svg | 127 +++++++ .../en/labware_position_check.json | 21 +- .../LabwarePositionCheck/AttachProbe.tsx | 138 +++++--- .../LabwarePositionCheck/CheckItem.tsx | 15 +- .../LabwarePositionCheck/DetachProbe.tsx | 27 +- .../LabwarePositionCheck/ExitConfirmation.tsx | 23 +- .../IntroScreen/index.tsx | 29 +- .../LabwarePositionCheck/JogToWell.tsx | 10 +- .../LabwarePositionCheckComponent.tsx | 18 +- .../LabwarePositionCheck/PickUpTip.tsx | 9 +- .../__tests__/CheckItem.test.tsx | 1 + .../__tests__/ExitConfirmation.test.tsx | 17 +- .../PipetteWizardFlows/AttachProbe.tsx | 75 +---- .../PipetteWizardFlows/ProbeNotAttached.tsx | 101 ++++++ 15 files changed, 785 insertions(+), 141 deletions(-) create mode 100644 app/src/assets/images/lpc_level_probe_with_labware.svg create mode 100644 app/src/assets/images/lpc_level_probe_with_tip.svg create mode 100644 app/src/organisms/PipetteWizardFlows/ProbeNotAttached.tsx diff --git a/app/src/assets/images/lpc_level_probe_with_labware.svg b/app/src/assets/images/lpc_level_probe_with_labware.svg new file mode 100644 index 00000000000..5e75128d9fc --- /dev/null +++ b/app/src/assets/images/lpc_level_probe_with_labware.svg @@ -0,0 +1,315 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/assets/images/lpc_level_probe_with_tip.svg b/app/src/assets/images/lpc_level_probe_with_tip.svg new file mode 100644 index 00000000000..799e78dd3d1 --- /dev/null +++ b/app/src/assets/images/lpc_level_probe_with_tip.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/assets/localization/en/labware_position_check.json b/app/src/assets/localization/en/labware_position_check.json index 58fe6550ddd..f08c465f7fa 100644 --- a/app/src/assets/localization/en/labware_position_check.json +++ b/app/src/assets/localization/en/labware_position_check.json @@ -6,22 +6,27 @@ "applied_offset_data": "Applied Labware Offset data", "apply_offset_data": "Apply labware offset data", "apply_offsets": "apply offsets", - "attach_probe": "Attach probe to pipette", + "attach_probe": "Attach calibration probe", + "backmost": "backmost", + "calibration_probe": "calibration probe", "check_item_in_location": "Check {{item}} in {{location}}", "check_labware_in_slot_title": "Check Labware {{labware_display_name}} in slot {{slot}}", "check_remaining_labware_with_primary_pipette_section": "Check remaining labware with {{primary_mount}} Pipette and tip", + "check_tip_location": "the top of the tip in the A1 position", + "check_well_location": "well A1 on the labware", "clear_all_slots": "Clear all deck slots of labware, leaving modules in place", "clear_all_slots_odd": "Clear all deck slots of labware", "cli_ssh": "Command Line Interface (SSH)", "close_and_apply_offset_data": "Close and apply labware offset data", + "confirm_detached": "Confirm removal", "confirm_pick_up_tip_modal_title": "Did the pipette pick up a tip successfully?", "confirm_pick_up_tip_modal_try_again_text": "No, try again", "confirm_position_and_move": "Confirm position, move to slot {{next_slot}}", "confirm_position_and_pick_up_tip": "Confirm position, pick up tip", "confirm_position_and_return_tip": "Confirm position, return tip to Slot {{next_slot}} and home", - "ensure_nozzle_is_above_tip_odd": "Ensure that the pipette nozzle furthest from you is centered above and level with the top of the tip in the A1 position. If it isn't, tap Move pipette and then jog the pipette until it is properly aligned.", - "ensure_nozzle_is_above_tip_desktop": "Ensure that the pipette nozzle furthest from you is centered above and level with the top of the tip in the A1 position. If it isn't, use the controls below or your keyboard to jog the pipette until it is properly aligned.", - "ensure_tip_is_above_well": "Ensure that the pipette tip furthest from you is centered above and level with well A1 on the labware.", + "detach_probe": "Remove calibration probe", + "ensure_nozzle_position_odd": "Ensure that the {{tip_type}} is centered above and level with {{item_location}}. If it isn't, tap Move pipette and then jog the pipette until it is properly aligned.", + "ensure_nozzle_position_desktop": "Ensure that the {{tip_type}} is centered above and level with {{item_location}}. If it isn't, use the controls below or your keyboard to jog the pipette until it is properly aligned.", "error_modal_header": "Something went wrong", "error_modal_problem_in_app": "There was an error performing Labware Position Check. Please restart the app. If the problem persists, please contact Opentrons Support", "error_modal_problem_on_robot": "There was an error processing your request on the robot", @@ -30,8 +35,7 @@ "exit_screen_subtitle": "If you exit now, all labware offsets will be discarded. This cannot be undone.", "exit_screen_title": "Exit before completing Labware Position Check?", "get_labware_offset_data": "Get Labware Offset Data", - "install_probe_8_channel": "Take the calibration probe from its storage location. Ensure its collar is unlocked. Push the pipette ejector up and press the probe firmly onto the backmost pipette nozzle. Twist the collar to lock the probe. Test that the probe is secure by gently pulling it back and forth.", - "install_probe_96_channel": "Take the calibration probe from its storage location. Ensure its collar is unlocked. Push the pipette ejector up and press the probe firmly onto the A1 (back left corner) pipette nozzle. Twist the collar to lock the probe. Test that the probe is secure by gently pulling it back and forth.", + "install_probe": "Take the calibration probe from its storage location. Ensure its collar is fully unlocked. Push the pipette ejector up and press the probe firmly onto the {{location}} pipette nozzle as far as it can go. Twist the collar to lock the probe. Test that the probe is secure by gently pulling it back and forth.", "jog_controls_adjustment": "Need to make an adjustment?", "jupyter_notebook": "Jupyter Notebook", "labware_display_location_text": "Deck Slot {{slot}}", @@ -70,6 +74,7 @@ "move_to_a1_position": "Move the pipette to line up in the A1 position", "moving_to_slot_title": "Moving to slot {{slot}}", "new_labware_offset_data": "New labware offset data", + "ninety_six_probe_location": "A1 (back left corner)", "no_labware_offsets": "No Labware Offset", "no_offset_data_available": "No labware offset data available", "no_offset_data_on_robot": "This robot has no useable labware offset data for this run.", @@ -77,6 +82,7 @@ "offsets": "offsets", "pick_up_tip_from_rack_in_location": "Pick up tip from tip rack in {{location}}", "picking_up_tip_title": "Picking up tip in slot {{slot}}", + "pipette_nozzle": "pipette nozzle furthest from you", "place_a_full_tip_rack_in_location": "Place a full {{tip_rack}} into {{location}}", "place_labware_in_adapter_in_location": "Place a {{adapter}} followed by a {{labware}} into {{location}}", "place_labware_in_location": "Place a {{labware}} into {{location}}", @@ -85,6 +91,9 @@ "position_check_description": "Labware Position Check is a guided workflow that checks every labware on the deck for an added degree of precision in your protocol.When you check a labware, the OT-2’s pipette nozzle or attached tip will stop at the center of the A1 well. If the pipette nozzle or tip is not centered, you can reveal the OT-2’s jog controls to make an adjustment. This Labware Offset will be applied to the entire labware. Offset data is measured to the nearest 1/10th mm and can be made in the X, Y and/or Z directions.", "prepare_item_in_location": "Prepare {{item}} in {{location}}", "primary_pipette_tipracks_section": "Check tip racks with {{primary_mount}} Pipette and pick up a tip", + "remove_calibration_probe": "Remove calibration probe", + "remove_probe": "Unlock the calibraiton probe, remove it from the nozzle, and return it to its storage location.", + "remove_probe_before_exit": "Remove the calibration probe before exiting", "return_tip_rack_to_location": "Return tip rack to {{location}}", "return_tip_section": "Return tip", "returning_tip_title": "Returning tip in slot {{slot}}", diff --git a/app/src/organisms/LabwarePositionCheck/AttachProbe.tsx b/app/src/organisms/LabwarePositionCheck/AttachProbe.tsx index 5381c23aed5..f54032e48f1 100644 --- a/app/src/organisms/LabwarePositionCheck/AttachProbe.tsx +++ b/app/src/organisms/LabwarePositionCheck/AttachProbe.tsx @@ -1,15 +1,18 @@ import * as React from 'react' import { Trans, useTranslation } from 'react-i18next' import { RESPONSIVENESS, SPACING, TYPOGRAPHY } from '@opentrons/components' -import { css } from 'styled-components' -import { StyledText } from '../../atoms/text' -import { RobotMotionLoader } from './RobotMotionLoader' +import { useInstrumentsQuery } from '@opentrons/react-api-client' import { CompletedProtocolAnalysis, getPipetteNameSpecs, } from '@opentrons/shared-data' +import { css } from 'styled-components' +import { StyledText } from '../../atoms/text' +import { ProbeNotAttached } from '../PipetteWizardFlows/ProbeNotAttached' +import { RobotMotionLoader } from './RobotMotionLoader' import attachProbe1 from '../../assets/videos/pipette-wizard-flows/Pipette_Attach_Probe_1.webm' import attachProbe8 from '../../assets/videos/pipette-wizard-flows/Pipette_Attach_Probe_8.webm' +import attachProbe96 from '../../assets/videos/pipette-wizard-flows/Pipette_Attach_Probe_96.webm' import { useChainRunCommands } from '../../resources/runs/hooks' import { GenericWizardTile } from '../../molecules/GenericWizardTile' @@ -19,7 +22,7 @@ import type { RegisterPositionAction, WorkingOffset, } from './types' -import type { LabwareOffset } from '@opentrons/api-client' +import type { LabwareOffset, PipetteData } from '@opentrons/api-client' interface AttachProbeProps extends AttachProbeStep { protocolData: CompletedProtocolAnalysis @@ -31,7 +34,9 @@ interface AttachProbeProps extends AttachProbeStep { existingOffsets: LabwareOffset[] handleJog: Jog isRobotMoving: boolean + isOnDevice: boolean } + export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { const { t, i18n } = useTranslation(['labware_position_check', 'shared']) const { @@ -41,43 +46,96 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { chainRunCommands, isRobotMoving, setFatalError, + isOnDevice, } = props + const [isPending, setIsPending] = React.useState(false) + const [showUnableToDetect, setShowUnableToDetect] = React.useState( + false + ) const pipette = protocolData.pipettes.find(p => p.id === pipetteId) const pipetteName = pipette?.pipetteName const pipetteChannels = pipetteName != null ? getPipetteNameSpecs(pipetteName)?.channels ?? 1 : 1 - const pipetteMount = pipette?.mount - if (pipetteName == null || pipetteMount == null) return null + let probeVideoSrc = attachProbe1 + let probeLocation = '' + if (pipetteChannels === 8) { + probeLocation = t('backmost') + probeVideoSrc = attachProbe8 + } else if (pipetteChannels === 96) { + probeLocation = t('ninety_six_probe_location') + probeVideoSrc = attachProbe96 + } - const pipetteZMotorAxis: 'leftZ' | 'rightZ' = - pipetteMount === 'left' ? 'leftZ' : 'rightZ' + const pipetteMount = pipette?.mount + const { refetch, data: attachedInstrumentsData } = useInstrumentsQuery({ + enabled: false, + onSettled: () => { + setIsPending(false) + }, + }) + const attachedPipette = attachedInstrumentsData?.data.find( + (instrument): instrument is PipetteData => + instrument.ok && instrument.mount === pipetteMount + ) - const handleProbeAttached = (): void => { + React.useEffect(() => { + // move into correct position for probe attach on mount chainRunCommands( [ { - commandType: 'retractAxis' as const, + commandType: 'calibration/moveToMaintenancePosition' as const, params: { - axis: pipetteZMotorAxis, + mount: pipetteMount ?? 'left', }, }, - { - commandType: 'retractAxis' as const, - params: { axis: 'x' }, - }, - { - commandType: 'retractAxis' as const, - params: { axis: 'y' }, - }, ], false - ) - .then(() => proceed()) - .catch((e: Error) => { - setFatalError( - `AttachProbe failed to move to safe location after probe attach with message: ${e.message}` - ) + ).catch(error => setFatalError(error.message)) + }, []) + + if (pipetteName == null || pipetteMount == null) return null + + const pipetteZMotorAxis: 'leftZ' | 'rightZ' = + pipetteMount === 'left' ? 'leftZ' : 'rightZ' + + const handleProbeAttached = (): void => { + setIsPending(true) + refetch() + .then(() => { + if (attachedPipette?.state?.tipDetected) { + chainRunCommands( + [ + { commandType: 'home', params: { axes: [pipetteZMotorAxis] } }, + { + commandType: 'retractAxis' as const, + params: { + axis: pipetteZMotorAxis, + }, + }, + { + commandType: 'retractAxis' as const, + params: { axis: 'x' }, + }, + { + commandType: 'retractAxis' as const, + params: { axis: 'y' }, + }, + ], + false + ) + .then(() => proceed()) + .catch((e: Error) => { + setFatalError( + `AttachProbe failed to move to safe location after probe attach with message: ${e.message}` + ) + }) + } else { + setShowUnableToDetect(true) + } + }) + .catch(error => { + setFatalError(error.message) }) } @@ -85,11 +143,19 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { return ( ) + else if (showUnableToDetect) + return ( + + ) return ( { loop={true} controls={false} > - 1 ? attachProbe8 : attachProbe1} /> + } bodyText={ - pipetteChannels > 1 ? ( + , - block: , + bold: , }} /> - ) : ( - {t('install_probe')} - ) + } - proceedButtonText={t('begin_calibration')} + proceedButtonText={i18n.format(t('shared:continue'), 'capitalize')} proceed={handleProbeAttached} /> ) diff --git a/app/src/organisms/LabwarePositionCheck/CheckItem.tsx b/app/src/organisms/LabwarePositionCheck/CheckItem.tsx index aaed13ca607..97fe3137690 100644 --- a/app/src/organisms/LabwarePositionCheck/CheckItem.tsx +++ b/app/src/organisms/LabwarePositionCheck/CheckItem.tsx @@ -55,6 +55,7 @@ interface CheckItemProps extends Omit { handleJog: Jog isRobotMoving: boolean robotType: RobotType + shouldUseMetalProbe: boolean } export const CheckItem = (props: CheckItemProps): JSX.Element | null => { const { @@ -73,6 +74,7 @@ export const CheckItem = (props: CheckItemProps): JSX.Element | null => { existingOffsets, setFatalError, robotType, + shouldUseMetalProbe, } = props const { t, i18n } = useTranslation(['labware_position_check', 'shared']) const isOnDevice = useSelector(getIsOnDevice) @@ -431,9 +433,17 @@ export const CheckItem = (props: CheckItemProps): JSX.Element | null => { t={t} i18nKey={ isOnDevice - ? 'ensure_nozzle_is_above_tip_odd' - : 'ensure_nozzle_is_above_tip_desktop' + ? 'ensure_nozzle_position_odd' + : 'ensure_nozzle_position_desktop' } + values={{ + tip_type: shouldUseMetalProbe + ? t('calibration_probe') + : t('pipette_nozzle'), + item_location: isTiprack + ? t('check_tip_location') + : t('check_well_location'), + }} components={{ block: , bold: }} /> } @@ -444,6 +454,7 @@ export const CheckItem = (props: CheckItemProps): JSX.Element | null => { handleJog={handleJog} initialPosition={initialPosition} existingOffset={existingOffset} + shouldUseMetalProbe={shouldUseMetalProbe} /> ) : ( { const pipetteName = pipette?.pipetteName const pipetteChannels = pipetteName != null ? getPipetteNameSpecs(pipetteName)?.channels ?? 1 : 1 + let probeVideoSrc = detachProbe1 + if (pipetteChannels === 8) { + probeVideoSrc = detachProbe8 + } else if (pipetteChannels === 96) { + probeVideoSrc = detachProbe96 + } const pipetteMount = pipette?.mount + + React.useEffect(() => { + // move into correct position for probe detach on mount + chainRunCommands( + [ + { + commandType: 'calibration/moveToMaintenancePosition' as const, + params: { + mount: pipetteMount ?? 'left', + }, + }, + ], + false + ).catch(error => setFatalError(error.message)) + }, []) + if (pipetteName == null || pipetteMount == null) return null const pipetteZMotorAxis: 'leftZ' | 'rightZ' = @@ -76,7 +99,7 @@ export const DetachProbe = (props: DetachProbeProps): JSX.Element | null => { .then(() => proceed()) .catch((e: Error) => { setFatalError( - `DetachProbe failed to move to safe location after probe attach with message: ${e.message}` + `DetachProbe failed to move to safe location after probe detach with message: ${e.message}` ) }) } @@ -101,7 +124,7 @@ export const DetachProbe = (props: DetachProbeProps): JSX.Element | null => { loop={true} controls={false} > - 1 ? detachProbe8 : detachProbe1} /> + } bodyText={ diff --git a/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx b/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx index 23f498392d9..7a86442779b 100644 --- a/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx +++ b/app/src/organisms/LabwarePositionCheck/ExitConfirmation.tsx @@ -26,11 +26,12 @@ import { SmallButton } from '../../atoms/buttons' interface ExitConfirmationProps { onGoBack: () => void onConfirmExit: () => void + shouldUseMetalProbe: boolean } export const ExitConfirmation = (props: ExitConfirmationProps): JSX.Element => { const { i18n, t } = useTranslation(['labware_position_check', 'shared']) - const { onGoBack, onConfirmExit } = props + const { onGoBack, onConfirmExit, shouldUseMetalProbe } = props const isOnDevice = useSelector(getIsOnDevice) return ( { {isOnDevice ? ( <> - {t('exit_screen_title')} + {shouldUseMetalProbe + ? t('remove_probe_before_exit') + : t('exit_screen_title')} @@ -59,7 +62,11 @@ export const ExitConfirmation = (props: ExitConfirmationProps): JSX.Element => { ) : ( <> - {t('exit_screen_title')} + + {shouldUseMetalProbe + ? t('remove_probe_before_exit') + : t('exit_screen_title')} + {t('exit_screen_subtitle')} @@ -80,7 +87,11 @@ export const ExitConfirmation = (props: ExitConfirmationProps): JSX.Element => { /> @@ -99,7 +110,9 @@ export const ExitConfirmation = (props: ExitConfirmationProps): JSX.Element => { onClick={onConfirmExit} textTransform={TYPOGRAPHY.textTransformCapitalize} > - {t('shared:exit')} + {shouldUseMetalProbe + ? t('remove_calibration_probe') + : i18n.format(t('shared:exit'), 'capitalize')} diff --git a/app/src/organisms/LabwarePositionCheck/IntroScreen/index.tsx b/app/src/organisms/LabwarePositionCheck/IntroScreen/index.tsx index b0e112154fe..d5cf8dc0ee6 100644 --- a/app/src/organisms/LabwarePositionCheck/IntroScreen/index.tsx +++ b/app/src/organisms/LabwarePositionCheck/IntroScreen/index.tsx @@ -34,6 +34,7 @@ import { css } from 'styled-components' import { Portal } from '../../../App/portal' import { LegacyModalShell } from '../../../molecules/LegacyModal' import { SmallButton } from '../../../atoms/buttons' +import { CALIBRATION_PROBE } from '../../PipetteWizardFlows/constants' import { TerseOffsetTable } from '../ResultsSummary' import { getLabwareDefinitionsFromCommands } from '../utils/labware' @@ -52,6 +53,7 @@ export const IntroScreen = (props: { isRobotMoving: boolean existingOffsets: LabwareOffset[] protocolName: string + shouldUseMetalProbe: boolean }): JSX.Element | null => { const { proceed, @@ -61,6 +63,7 @@ export const IntroScreen = (props: { setFatalError, existingOffsets, protocolName, + shouldUseMetalProbe, } = props const isOnDevice = useSelector(getIsOnDevice) const { t, i18n } = useTranslation(['labware_position_check', 'shared']) @@ -74,6 +77,19 @@ export const IntroScreen = (props: { ) }) } + const requiredEquipmentList = [ + { + loadName: t('all_modules_and_labware_from_protocol', { + protocol_name: protocolName, + }), + displayName: t('all_modules_and_labware_from_protocol', { + protocol_name: protocolName, + }), + }, + ] + if (shouldUseMetalProbe) { + requiredEquipmentList.push(CALIBRATION_PROBE) + } if (isRobotMoving) { return ( @@ -91,18 +107,7 @@ export const IntroScreen = (props: { /> } rightElement={ - + } footer={ diff --git a/app/src/organisms/LabwarePositionCheck/JogToWell.tsx b/app/src/organisms/LabwarePositionCheck/JogToWell.tsx index c634a2edb3e..4e91343b85a 100644 --- a/app/src/organisms/LabwarePositionCheck/JogToWell.tsx +++ b/app/src/organisms/LabwarePositionCheck/JogToWell.tsx @@ -29,6 +29,8 @@ import { import levelWithTip from '../../assets/images/lpc_level_with_tip.svg' import levelWithLabware from '../../assets/images/lpc_level_with_labware.svg' +import levelProbeWithTip from '../../assets/images/lpc_level_probe_with_tip.svg' +import levelProbeWithLabware from '../../assets/images/lpc_level_probe_with_labware.svg' import { getIsOnDevice } from '../../redux/config' import { Portal } from '../../App/portal' import { LegacyModalShell } from '../../molecules/LegacyModal' @@ -57,6 +59,7 @@ interface JogToWellProps { body: React.ReactNode initialPosition: VectorOffset existingOffset: VectorOffset + shouldUseMetalProbe: boolean } export const JogToWell = (props: JogToWellProps): JSX.Element | null => { const { t } = useTranslation(['labware_position_check', 'shared']) @@ -70,6 +73,7 @@ export const JogToWell = (props: JogToWellProps): JSX.Element | null => { handleJog, initialPosition, existingOffset, + shouldUseMetalProbe, } = props const [joggedPosition, setJoggedPosition] = React.useState( @@ -109,6 +113,10 @@ export const JogToWell = (props: JogToWellProps): JSX.Element | null => { getVectorDifference(joggedPosition, initialPosition) ) const isTipRack = getIsTiprack(labwareDef) + let levelSrc = isTipRack ? levelWithTip : levelWithLabware + if (shouldUseMetalProbe) { + levelSrc = isTipRack ? levelProbeWithTip : levelProbeWithLabware + } return ( { {`level diff --git a/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx b/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx index 95f9fc02c5e..8df5ad42bfa 100644 --- a/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx +++ b/app/src/organisms/LabwarePositionCheck/LabwarePositionCheckComponent.tsx @@ -338,6 +338,7 @@ export const LabwarePositionCheckComponent = ( ) } else if (currentStep.section === 'BEFORE_BEGINNING') { @@ -346,6 +347,7 @@ export const LabwarePositionCheckComponent = ( {...movementStepProps} {...{ existingOffsets }} protocolName={protocolName} + shouldUseMetalProbe={shouldUseMetalProbe} /> ) } else if ( @@ -353,9 +355,21 @@ export const LabwarePositionCheckComponent = ( currentStep.section === 'CHECK_TIP_RACKS' || currentStep.section === 'CHECK_LABWARE' ) { - modalContent = + modalContent = ( + + ) } else if (currentStep.section === 'ATTACH_PROBE') { - modalContent = + modalContent = ( + + ) } else if (currentStep.section === 'DETACH_PROBE') { modalContent = } else if (currentStep.section === 'PICK_UP_TIP') { diff --git a/app/src/organisms/LabwarePositionCheck/PickUpTip.tsx b/app/src/organisms/LabwarePositionCheck/PickUpTip.tsx index 9457fcea6e9..72141eb28ae 100644 --- a/app/src/organisms/LabwarePositionCheck/PickUpTip.tsx +++ b/app/src/organisms/LabwarePositionCheck/PickUpTip.tsx @@ -407,10 +407,14 @@ export const PickUpTip = (props: PickUpTipProps): JSX.Element | null => { t={t} i18nKey={ isOnDevice - ? 'ensure_nozzle_is_above_tip_odd' - : 'ensure_nozzle_is_above_tip_desktop' + ? 'ensure_nozzle_position_odd' + : 'ensure_nozzle_position_desktop' } components={{ block: , bold: }} + values={{ + tip_type: t('pipette_nozzle'), + item_location: t('check_tip_location'), + }} /> } labwareDef={labwareDef} @@ -420,6 +424,7 @@ export const PickUpTip = (props: PickUpTipProps): JSX.Element | null => { handleJog={handleJog} initialPosition={initialPosition} existingOffset={existingOffset} + shouldUseMetalProbe={false} /> ) : ( { existingOffsets: mockExistingOffsets, isRobotMoving: false, robotType: FLEX_ROBOT_TYPE, + shouldUseMetalProbe: false, } }) afterEach(() => { diff --git a/app/src/organisms/LabwarePositionCheck/__tests__/ExitConfirmation.test.tsx b/app/src/organisms/LabwarePositionCheck/__tests__/ExitConfirmation.test.tsx index 61552a0f1cb..3263e098e22 100644 --- a/app/src/organisms/LabwarePositionCheck/__tests__/ExitConfirmation.test.tsx +++ b/app/src/organisms/LabwarePositionCheck/__tests__/ExitConfirmation.test.tsx @@ -17,6 +17,7 @@ describe('ExitConfirmation', () => { props = { onGoBack: jest.fn(), onConfirmExit: jest.fn(), + shouldUseMetalProbe: false, } }) afterEach(() => { @@ -29,14 +30,26 @@ describe('ExitConfirmation', () => { getByText( 'If you exit now, all labware offsets will be discarded. This cannot be undone.' ) - getByRole('button', { name: 'exit' }) + getByRole('button', { name: 'Exit' }) getByRole('button', { name: 'Go back' }) }) it('should invoke callback props when ctas are clicked', () => { const { getByRole } = render(props) getByRole('button', { name: 'Go back' }).click() expect(props.onGoBack).toHaveBeenCalled() - getByRole('button', { name: 'exit' }).click() + getByRole('button', { name: 'Exit' }).click() expect(props.onConfirmExit).toHaveBeenCalled() }) + it('should render correct copy for golden tip LPC', () => { + const { getByText, getByRole } = render({ + ...props, + shouldUseMetalProbe: true, + }) + getByText('Remove the calibration probe before exiting') + getByText( + 'If you exit now, all labware offsets will be discarded. This cannot be undone.' + ) + getByRole('button', { name: 'Remove calibration probe' }) + getByRole('button', { name: 'Go back' }) + }) }) diff --git a/app/src/organisms/PipetteWizardFlows/AttachProbe.tsx b/app/src/organisms/PipetteWizardFlows/AttachProbe.tsx index 881d8e04631..f12c7065661 100644 --- a/app/src/organisms/PipetteWizardFlows/AttachProbe.tsx +++ b/app/src/organisms/PipetteWizardFlows/AttachProbe.tsx @@ -3,19 +3,13 @@ import { css } from 'styled-components' import { Trans, useTranslation } from 'react-i18next' import { Flex, - Btn, - PrimaryButton, TYPOGRAPHY, COLORS, SPACING, RESPONSIVENESS, - JUSTIFY_SPACE_BETWEEN, - ALIGN_FLEX_END, - ALIGN_CENTER, } from '@opentrons/components' import { LEFT, MotorAxes } from '@opentrons/shared-data' import { useInstrumentsQuery } from '@opentrons/react-api-client' -import { SmallButton } from '../../atoms/buttons' import { StyledText } from '../../atoms/text' import { GenericWizardTile } from '../../molecules/GenericWizardTile' import { SimpleWizardBody } from '../../molecules/SimpleWizardBody' @@ -25,6 +19,7 @@ import pipetteProbe8 from '../../assets/videos/pipette-wizard-flows/Pipette_Prob import probing96 from '../../assets/videos/pipette-wizard-flows/Pipette_Probing_96.webm' import { BODY_STYLE, SECTIONS, FLOWS } from './constants' import { getPipetteAnimations } from './utils' +import { ProbeNotAttached } from './ProbeNotAttached' import type { PipetteData } from '@opentrons/api-client' import type { PipetteWizardStepProps } from './types' @@ -43,32 +38,6 @@ const IN_PROGRESS_STYLE = css` } ` -const ALIGN_BUTTONS = css` - align-items: ${ALIGN_FLEX_END}; - - @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { - align-items: ${ALIGN_CENTER}; - } -` -const GO_BACK_BUTTON_STYLE = css` - ${TYPOGRAPHY.pSemiBold}; - color: ${COLORS.darkGreyEnabled}; - padding-left: ${SPACING.spacing32}; - - &:hover { - opacity: 70%; - } - - @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { - font-weight: ${TYPOGRAPHY.fontWeightSemiBold}; - font-size: ${TYPOGRAPHY.fontSize22}; - padding-left: 0rem; - &:hover { - opacity: 100%; - } - } -` - export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { const { proceed, @@ -89,7 +58,6 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { const [showUnableToDetect, setShowUnableToDetect] = React.useState( false ) - const [numberOfTryAgains, setNumberOfTryAgains] = React.useState(0) const pipetteId = attachedPipettes[mount]?.serialNumber const displayName = attachedPipettes[mount]?.displayName @@ -211,41 +179,12 @@ export const AttachProbe = (props: AttachProbeProps): JSX.Element | null => { ) else if (showUnableToDetect) return ( - 2 ? t('something_seems_wrong') : undefined - } - iconColor={COLORS.errorEnabled} - isSuccess={false} - > - - setShowUnableToDetect(false)}> - - {t('shared:go_back')} - - - {isOnDevice ? ( - { - setNumberOfTryAgains(numberOfTryAgains + 1) - handleOnClick() - }} - /> - ) : ( - - {t('try_again')} - - )} - - + ) return errorMessage != null ? ( diff --git a/app/src/organisms/PipetteWizardFlows/ProbeNotAttached.tsx b/app/src/organisms/PipetteWizardFlows/ProbeNotAttached.tsx new file mode 100644 index 00000000000..ffee8350cbc --- /dev/null +++ b/app/src/organisms/PipetteWizardFlows/ProbeNotAttached.tsx @@ -0,0 +1,101 @@ +import * as React from 'react' +import { useTranslation } from 'react-i18next' +import { + Flex, + Btn, + PrimaryButton, + RESPONSIVENESS, + SPACING, + TYPOGRAPHY, + COLORS, + JUSTIFY_SPACE_BETWEEN, + ALIGN_FLEX_END, + ALIGN_CENTER, +} from '@opentrons/components' +import { css } from 'styled-components' +import { SimpleWizardBody } from '../../molecules/SimpleWizardBody' +import { StyledText } from '../../atoms/text' +import { SmallButton } from '../../atoms/buttons' + +interface ProbeNotAttachedProps { + handleOnClick: () => void + setShowUnableToDetect: (ableToDetect: boolean) => void + isOnDevice: boolean + isPending: boolean +} + +export const ProbeNotAttached = ( + props: ProbeNotAttachedProps +): JSX.Element | null => { + const { t, i18n } = useTranslation(['pipette_wizard_flows', 'shared']) + const { isOnDevice, isPending, handleOnClick, setShowUnableToDetect } = props + const [numberOfTryAgains, setNumberOfTryAgains] = React.useState(0) + + return ( + 2 ? t('something_seems_wrong') : undefined} + iconColor={COLORS.errorEnabled} + isSuccess={false} + > + + setShowUnableToDetect(false)}> + + {t('shared:go_back')} + + + {isOnDevice ? ( + { + setNumberOfTryAgains(numberOfTryAgains + 1) + handleOnClick() + }} + /> + ) : ( + { + setNumberOfTryAgains(numberOfTryAgains + 1) + handleOnClick() + }} + > + {i18n.format(t('shared:try_again'), 'capitalize')} + + )} + + + ) +} + +const ALIGN_BUTTONS = css` + align-items: ${ALIGN_FLEX_END}; + + @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { + align-items: ${ALIGN_CENTER}; + } +` +const GO_BACK_BUTTON_STYLE = css` + ${TYPOGRAPHY.pSemiBold}; + color: ${COLORS.darkGreyEnabled}; + padding-left: ${SPACING.spacing32}; + + &:hover { + opacity: 70%; + } + + @media ${RESPONSIVENESS.touchscreenMediaQuerySpecs} { + font-weight: ${TYPOGRAPHY.fontWeightSemiBold}; + font-size: ${TYPOGRAPHY.fontSize22}; + padding-left: 0rem; + &:hover { + opacity: 100%; + } + } +` From c784bbb94a1fa8d32f860684b64206c21046fb7c Mon Sep 17 00:00:00 2001 From: Sarah Breen Date: Thu, 9 Nov 2023 13:58:12 -0500 Subject: [PATCH 48/65] fix(app): module calibration should only use calibrated pipette (#13956) fix RQA-1879 --- app/src/organisms/Devices/InstrumentsAndModules.tsx | 3 ++- app/src/organisms/ModuleWizardFlows/index.tsx | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/src/organisms/Devices/InstrumentsAndModules.tsx b/app/src/organisms/Devices/InstrumentsAndModules.tsx index 523c1cd3510..ef6cb2a7f60 100644 --- a/app/src/organisms/Devices/InstrumentsAndModules.tsx +++ b/app/src/organisms/Devices/InstrumentsAndModules.tsx @@ -105,7 +105,8 @@ export function InstrumentsAndModules({ attachedPipettes?.left ?? null ) const attachPipetteRequired = - attachedLeftPipette == null && attachedRightPipette == null + attachedLeftPipette?.data?.calibratedOffset?.last_modified == null && + attachedRightPipette?.data?.calibratedOffset?.last_modified == null const updatePipetteFWRequired = badLeftPipette != null || badRightPipette != null diff --git a/app/src/organisms/ModuleWizardFlows/index.tsx b/app/src/organisms/ModuleWizardFlows/index.tsx index 65fa45f855e..5361380b226 100644 --- a/app/src/organisms/ModuleWizardFlows/index.tsx +++ b/app/src/organisms/ModuleWizardFlows/index.tsx @@ -60,7 +60,11 @@ export const ModuleWizardFlows = ( const isOnDevice = useSelector(getIsOnDevice) const { t } = useTranslation('module_wizard_flows') const attachedPipettes = useAttachedPipettesFromInstrumentsQuery() - const attachedPipette = attachedPipettes.left ?? attachedPipettes.right + const attachedPipette = + attachedPipettes.left?.data.calibratedOffset?.last_modified != null + ? attachedPipettes.left + : attachedPipettes.right + const moduleCalibrationSteps = getModuleCalibrationSteps() const availableSlotNames = FLEX_SLOT_NAMES_BY_MOD_TYPE[getModuleType(attachedModule.moduleModel)] ?? [] @@ -193,7 +197,11 @@ export const ModuleWizardFlows = ( continuePastCommandFailure ) } - if (currentStep == null || attachedPipette == null) return null + if ( + currentStep == null || + attachedPipette?.data.calibratedOffset?.last_modified == null + ) + return null const maintenanceRunId = maintenanceRunData?.data.id != null && From 411bba3c9ee47fb53633dcf9f23221808cfe2036 Mon Sep 17 00:00:00 2001 From: Brian Arthur Cooper Date: Thu, 9 Nov 2023 14:00:29 -0500 Subject: [PATCH 49/65] refactor(app): remove unused analytics structures (#13893) --- .../Devices/hooks/useRobotAnalyticsData.ts | 11 +- .../analytics/__tests__/make-event.test.ts | 82 ------ .../analytics/__tests__/selectors.test.ts | 6 - app/src/redux/analytics/make-event.ts | 172 +------------ app/src/redux/analytics/selectors.ts | 236 +----------------- 5 files changed, 26 insertions(+), 481 deletions(-) diff --git a/app/src/organisms/Devices/hooks/useRobotAnalyticsData.ts b/app/src/organisms/Devices/hooks/useRobotAnalyticsData.ts index c1289e0da83..6ca8c95fbca 100644 --- a/app/src/organisms/Devices/hooks/useRobotAnalyticsData.ts +++ b/app/src/organisms/Devices/hooks/useRobotAnalyticsData.ts @@ -4,7 +4,6 @@ import { useSelector, useDispatch } from 'react-redux' import { useRobot } from './' import { getAttachedPipettes } from '../../../redux/pipettes' import { getRobotSettings, fetchSettings } from '../../../redux/robot-settings' -import { FF_PREFIX } from '../../../redux/analytics' import { getRobotApiVersion, getRobotFirmwareVersion, @@ -13,6 +12,8 @@ import { import type { State, Dispatch } from '../../../redux/types' import type { RobotAnalyticsData } from '../../../redux/analytics/types' +const FF_PREFIX = 'robotFF_' + /** * * @param {string} robotName @@ -45,10 +46,10 @@ export function useRobotAnalyticsData( }), // @ts-expect-error RobotAnalyticsData type needs boolean values should it be boolean | string { - robotApiServerVersion: getRobotApiVersion(robot) || '', - robotSmoothieVersion: getRobotFirmwareVersion(robot) || '', - robotLeftPipette: pipettes.left?.model || '', - robotRightPipette: pipettes.right?.model || '', + robotApiServerVersion: getRobotApiVersion(robot) ?? '', + robotSmoothieVersion: getRobotFirmwareVersion(robot) ?? '', + robotLeftPipette: pipettes.left?.model ?? '', + robotRightPipette: pipettes.right?.model ?? '', } ) } diff --git a/app/src/redux/analytics/__tests__/make-event.test.ts b/app/src/redux/analytics/__tests__/make-event.test.ts index 6a149c81d87..c7906c72de8 100644 --- a/app/src/redux/analytics/__tests__/make-event.test.ts +++ b/app/src/redux/analytics/__tests__/make-event.test.ts @@ -14,18 +14,6 @@ const getAnalyticsSessionExitDetails = selectors.getAnalyticsSessionExitDetails const getSessionInstrumentAnalyticsData = selectors.getSessionInstrumentAnalyticsData as jest.MockedFunction< typeof selectors.getSessionInstrumentAnalyticsData > -const getAnalyticsHealthCheckData = selectors.getAnalyticsHealthCheckData as jest.MockedFunction< - typeof selectors.getAnalyticsHealthCheckData -> -const getAnalyticsDeckCalibrationData = selectors.getAnalyticsDeckCalibrationData as jest.MockedFunction< - typeof selectors.getAnalyticsDeckCalibrationData -> -const getAnalyticsPipetteCalibrationData = selectors.getAnalyticsPipetteCalibrationData as jest.MockedFunction< - typeof selectors.getAnalyticsPipetteCalibrationData -> -const getAnalyticsTipLengthCalibrationData = selectors.getAnalyticsTipLengthCalibrationData as jest.MockedFunction< - typeof selectors.getAnalyticsTipLengthCalibrationData -> describe('analytics events map', () => { beforeEach(() => { @@ -63,18 +51,10 @@ describe('analytics events map', () => { someStuff: 'some-other-stuff', }, } as any - getAnalyticsPipetteCalibrationData.mockReturnValue({ - markedBad: true, - calibrationExists: true, - pipetteModel: 'my pipette model', - }) return expect(makeEvent(action, state)).resolves.toEqual({ name: 'pipetteOffsetCalibrationStarted', properties: { ...action.payload, - calibrationExists: true, - markedBad: true, - pipetteModel: 'my pipette model', }, }) }) @@ -87,76 +67,14 @@ describe('analytics events map', () => { someStuff: 'some-other-stuff', }, } as any - getAnalyticsTipLengthCalibrationData.mockReturnValue({ - markedBad: true, - calibrationExists: true, - pipetteModel: 'pipette-model', - }) return expect(makeEvent(action, state)).resolves.toEqual({ name: 'tipLengthCalibrationStarted', properties: { ...action.payload, - calibrationExists: true, - markedBad: true, - pipetteModel: 'pipette-model', - }, - }) - }) - - it('sessions:ENSURE_SESSION for deck cal -> deckCalibrationStarted event', () => { - const state = {} as any - const action = { - type: 'sessions:ENSURE_SESSION', - payload: { - sessionType: 'deckCalibration', - }, - } as any - getAnalyticsDeckCalibrationData.mockReturnValue({ - calibrationStatus: 'IDENTITY', - markedBad: true, - pipettes: { left: { model: 'my pipette model' } }, - } as any) - - return expect(makeEvent(action, state)).resolves.toEqual({ - name: 'deckCalibrationStarted', - properties: { - calibrationStatus: 'IDENTITY', - markedBad: true, - pipettes: { left: { model: 'my pipette model' } }, }, }) }) - it('sessions:ENSURE_SESSION for health check -> calibrationHealthCheckStarted event', () => { - const state = {} as any - const action = { - type: 'sessions:ENSURE_SESSION', - payload: { - sessionType: 'calibrationCheck', - }, - } as any - getAnalyticsHealthCheckData.mockReturnValue({ - pipettes: { left: { model: 'my pipette model' } }, - } as any) - return expect(makeEvent(action, state)).resolves.toEqual({ - name: 'calibrationHealthCheckStarted', - properties: { - pipettes: { left: { model: 'my pipette model' } }, - }, - }) - }) - - it('sessions:ENSURE_SESSION for other session -> no event', () => { - const state = {} as any - const action = { - type: 'sessions:ENSURE_SESSION', - payload: { - sessionType: 'some-other-session', - }, - } as any - return expect(makeEvent(action, state)).resolves.toBeNull() - }) - it('sessions:CREATE_SESSION_COMMAND for exit -> {type}Exit', () => { const state = {} as any const action = { diff --git a/app/src/redux/analytics/__tests__/selectors.test.ts b/app/src/redux/analytics/__tests__/selectors.test.ts index 7bbd0b296a7..63b539748d8 100644 --- a/app/src/redux/analytics/__tests__/selectors.test.ts +++ b/app/src/redux/analytics/__tests__/selectors.test.ts @@ -56,12 +56,6 @@ describe('analytics selectors', () => { }) describe('analytics calibration selectors', () => { - describe('getAnalyticsHealthCheckData', () => { - it('should return null if no robot connected', () => { - const mockState: State = {} as any - expect(Selectors.getAnalyticsHealthCheckData(mockState)).toBeNull() - }) - }) describe('getAnalyticsSessionExitDetails', () => { const mockGetRobotSessionById = SessionsSelectors.getRobotSessionById as jest.MockedFunction< typeof SessionsSelectors.getRobotSessionById diff --git a/app/src/redux/analytics/make-event.ts b/app/src/redux/analytics/make-event.ts index 5b38f947073..8fdede1dbf2 100644 --- a/app/src/redux/analytics/make-event.ts +++ b/app/src/redux/analytics/make-event.ts @@ -1,8 +1,4 @@ // redux action types to analytics events map -// TODO(mc, 2022-03-04): large chunks of this module are commented -// out because RPC-based analytics events were not replaced with -// the switch to the HTTP APIs. Commented out code left to aid with -// analytics replacement. import * as CustomLabware from '../custom-labware' import * as SystemInfo from '../system-info' import * as RobotUpdate from '../robot-update/constants' @@ -14,17 +10,12 @@ import * as RobotAdmin from '../robot-admin' import { getBuildrootAnalyticsData, - getAnalyticsPipetteCalibrationData, - getAnalyticsTipLengthCalibrationData, - getAnalyticsHealthCheckData, - getAnalyticsDeckCalibrationData, getAnalyticsSessionExitDetails, getSessionInstrumentAnalyticsData, } from './selectors' import type { State, Action } from '../types' import type { AnalyticsEvent } from './types' -import type { Mount } from '../pipettes/types' const EVENT_APP_UPDATE_DISMISSED = 'appUpdateDismissed' @@ -33,111 +24,6 @@ export function makeEvent( state: State ): Promise { switch (action.type) { - // case 'robot:CONNECT': { - // const robot = getConnectedRobot(state) - - // if (!robot) { - // log.warn('No robot found for connect response') - // return Promise.resolve(null) - // } - - // const data = getRobotAnalyticsData(state) - - // return Promise.resolve({ - // name: 'robotConnect', - // properties: { - // ...data, - // method: robot.local ? 'usb' : 'wifi', - // success: true, - // }, - // }) - // } - - // case 'protocol:LOAD': { - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'protocolUploadRequest', - // properties: { - // ...getRobotAnalyticsData(state), - // ...data, - // }, - // })) - // } - - // case 'robot:SESSION_RESPONSE': - // case 'robot:SESSION_ERROR': { - // // only fire event if we had a protocol upload in flight; we don't want - // // to fire if user connects to robot with protocol already loaded - // const { type: actionType, payload: actionPayload, meta } = action - // if (!meta.freshUpload) return Promise.resolve(null) - - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'protocolUploadResponse', - // properties: { - // ...getRobotAnalyticsData(state), - // ...data, - // success: actionType === 'robot:SESSION_RESPONSE', - // // @ts-expect-error even if we used the in operator, TS cant narrow error to anything more specific than 'unknown' https://github.com/microsoft/TypeScript/issues/25720 - // error: (actionPayload.error && actionPayload.error.message) || '', - // }, - // })) - // } - - // case 'robot:RUN': { - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'runStart', - // properties: { - // ...getRobotAnalyticsData(state), - // ...data, - // }, - // })) - // } - - // TODO(mc, 2019-01-22): we only get this event if the user keeps their app - // open for the entire run. Fixing this is blocked until we can fix - // session.stop from triggering a run error - // case 'robot:RUN_RESPONSE': { - // const runTime = robotSelectors.getRunSeconds(state) - // const success = !action.error - // const error = action.error ? action.payload?.message || '' : '' - - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'runFinish', - // properties: { - // ...getRobotAnalyticsData(state), - // ...data, - // runTime, - // success, - // error, - // }, - // })) - // } - - // case 'robot:PAUSE': { - // const runTime = robotSelectors.getRunSeconds(state) - - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'runPause', - // properties: { ...data, runTime }, - // })) - // } - - // case 'robot:RESUME': { - // const runTime = robotSelectors.getRunSeconds(state) - - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'runResume', - // properties: { ...data, runTime }, - // })) - // } - - // case 'robot:CANCEL': - // const runTime = robotSelectors.getRunSeconds(state) - - // return getProtocolAnalyticsData(state).then(data => ({ - // name: 'runCancel', - // properties: { ...data, runTime }, - // })) - // robot update events case RobotUpdate.ROBOTUPDATE_SET_UPDATE_SEEN: { const data = getBuildrootAnalyticsData(state, action.meta.robotName) @@ -265,7 +151,7 @@ export function makeEvent( const systemInfoProps = SystemInfo.getU2EDeviceAnalyticsProps(state) return Promise.resolve( - systemInfoProps + systemInfoProps != null ? { superProperties: { ...systemInfoProps, @@ -280,43 +166,16 @@ export function makeEvent( ) } - case Sessions.ENSURE_SESSION: { - switch (action.payload.sessionType) { - case Sessions.SESSION_TYPE_DECK_CALIBRATION: - const dcAnalyticsProps = getAnalyticsDeckCalibrationData(state) - return Promise.resolve( - dcAnalyticsProps - ? { - name: 'deckCalibrationStarted', - properties: dcAnalyticsProps, - } - : null - ) - case Sessions.SESSION_TYPE_CALIBRATION_HEALTH_CHECK: - const hcAnalyticsProps = getAnalyticsHealthCheckData(state) - return Promise.resolve( - hcAnalyticsProps - ? { - name: 'calibrationHealthCheckStarted', - properties: hcAnalyticsProps, - } - : null - ) - default: - return Promise.resolve(null) - } - } - case Sessions.CREATE_SESSION_COMMAND: { switch (action.payload.command.command) { - case sharedCalCommands.EXIT: + case sharedCalCommands.EXIT: { const sessionDetails = getAnalyticsSessionExitDetails( state, action.payload.robotName, action.payload.sessionId ) return Promise.resolve( - sessionDetails + sessionDetails != null ? { name: `${sessionDetails.sessionType}Exit`, properties: { @@ -325,25 +184,25 @@ export function makeEvent( } : null ) - case sharedCalCommands.LOAD_LABWARE: + } + case sharedCalCommands.LOAD_LABWARE: { const commandData = action.payload.command.data - if (commandData) { + if (commandData != null) { const instrData = getSessionInstrumentAnalyticsData( state, action.payload.robotName, action.payload.sessionId ) return Promise.resolve( - instrData + instrData != null ? { name: `${instrData.sessionType}TipRackSelect`, properties: { pipetteModel: instrData.pipetteModel, - // @ts-expect-error TODO: use in operator and add test case for no tiprackDefiniton on CommandData - tipRackDisplayName: commandData.tiprackDefinition - ? // @ts-expect-error TODO: use in operator and add test case for no tiprackDefiniton on CommandData - commandData.tiprackDefinition.metadata.displayName - : null, + tipRackDisplayName: + 'tiprackDefinition' in commandData + ? commandData.tiprackDefinition.metadata.displayName + : null, }, } : null @@ -351,6 +210,7 @@ export function makeEvent( } else { return Promise.resolve(null) } + } default: return Promise.resolve(null) } @@ -374,10 +234,6 @@ export function makeEvent( name: 'pipetteOffsetCalibrationStarted', properties: { ...action.payload, - ...getAnalyticsPipetteCalibrationData( - state, - action.payload.mount as Mount - ), }, }) } @@ -387,10 +243,6 @@ export function makeEvent( name: 'tipLengthCalibrationStarted', properties: { ...action.payload, - ...getAnalyticsTipLengthCalibrationData( - state, - action.payload.mount as Mount - ), }, }) } diff --git a/app/src/redux/analytics/selectors.ts b/app/src/redux/analytics/selectors.ts index d0362f77348..fcb9ab18a2d 100644 --- a/app/src/redux/analytics/selectors.ts +++ b/app/src/redux/analytics/selectors.ts @@ -1,16 +1,5 @@ -// import { createSelector } from 'reselect' import * as Sessions from '../sessions' -// import { -// getProtocolType, -// getProtocolCreatorApp, -// getProtocolApiVersion, -// getProtocolName, -// getProtocolSource, -// getProtocolAuthor, -// getProtocolContents, -// } from '../protocol' - import { getViewableRobots, getRobotApiVersion } from '../discovery' import { @@ -22,127 +11,37 @@ import { import { getRobotSessionById } from '../sessions/selectors' -// import { hash } from './hash' - -// import type { Selector } from 'reselect' import type { State } from '../types' -import type { Mount } from '../pipettes/types' import type { AnalyticsConfig, BuildrootAnalyticsData, - PipetteOffsetCalibrationAnalyticsData, - TipLengthCalibrationAnalyticsData, - DeckCalibrationAnalyticsData, - CalibrationHealthCheckAnalyticsData, AnalyticsSessionExitDetails, SessionInstrumentAnalyticsData, } from './types' -export const FF_PREFIX = 'robotFF_' - -// const _getUnhashedProtocolAnalyticsData: Selector< -// State, -// ProtocolAnalyticsData -// > = createSelector( -// getProtocolType, -// getProtocolCreatorApp, -// getProtocolApiVersion, -// getProtocolName, -// getProtocolSource, -// getProtocolAuthor, -// getProtocolContents, -// getPipettes, -// getModules, -// ( -// type, -// app, -// apiVersion, -// name, -// source, -// author, -// contents, -// pipettes, -// modules -// ) => ({ -// protocolType: type || '', -// protocolAppName: app.name || '', -// protocolAppVersion: app.version || '', -// protocolApiVersion: apiVersion || '', -// protocolName: name || '', -// protocolSource: source || '', -// protocolAuthor: author || '', -// protocolText: contents || '', -// pipettes: pipettes.map(p => p.requestedAs ?? p.name).join(','), -// modules: modules.map(m => m.model).join(','), -// }) -// ) - -// export const getProtocolAnalyticsData: ( -// state: State -// ) => Promise = createSelector< -// State, -// ProtocolAnalyticsData, -// Promise -// >(_getUnhashedProtocolAnalyticsData, (data: ProtocolAnalyticsData) => { -// const hashTasks = [hash(data.protocolAuthor), hash(data.protocolText)] - -// return Promise.all(hashTasks).then(([protocolAuthor, protocolText]) => ({ -// ...data, -// protocolAuthor: data.protocolAuthor !== '' ? protocolAuthor : '', -// protocolText: data.protocolText !== '' ? protocolText : '', -// })) -// }) - -// export function getRobotAnalyticsData(state: State): RobotAnalyticsData | null { -// const robot = getConnectedRobot(state) - -// if (robot) { -// const pipettes = getAttachedPipettes(state, robot.name) -// const settings = getRobotSettings(state, robot.name) - -// // @ts-expect-error RobotAnalyticsData type needs boolean values should it be boolean | string -// return settings.reduce( -// (result, setting) => ({ -// ...result, -// [`${FF_PREFIX}${setting.id}`]: !!setting.value, -// }), -// // @ts-expect-error RobotAnalyticsData type needs boolean values should it be boolean | string -// { -// robotApiServerVersion: getRobotApiVersion(robot) || '', -// robotSmoothieVersion: getRobotFirmwareVersion(robot) || '', -// robotLeftPipette: pipettes.left?.model || '', -// robotRightPipette: pipettes.right?.model || '', -// } -// ) -// } - -// return null -// } - export function getBuildrootAnalyticsData( state: State, robotName: string | null = null ): BuildrootAnalyticsData | null { - const updateVersion = robotName - ? getRobotUpdateVersion(state, robotName) - : null + const updateVersion = + robotName != null ? getRobotUpdateVersion(state, robotName) : null const session = getRobotUpdateSession(state) const robot = robotName === null ? getRobotUpdateRobot(state) - : getViewableRobots(state).find(r => r.name === robotName) || null + : getViewableRobots(state).find(r => r.name === robotName) ?? null if (updateVersion === null || robot === null) return null - const currentVersion = getRobotApiVersion(robot) || 'unknown' - const currentSystem = getRobotSystemType(robot) || 'unknown' + const currentVersion = getRobotApiVersion(robot) ?? 'unknown' + const currentSystem = getRobotSystemType(robot) ?? 'unknown' return { currentVersion, currentSystem, updateVersion, - error: session?.error || null, + error: session != null && 'error' in session ? session.error : null, } } @@ -158,132 +57,13 @@ export function getAnalyticsOptInSeen(state: State): boolean { return state.config?.analytics.seenOptIn ?? true } -export function getAnalyticsPipetteCalibrationData( - state: State, - mount: Mount -): PipetteOffsetCalibrationAnalyticsData | null { - // const robot = getConnectedRobot(state) - - // if (robot) { - // const pipcal = - // getAttachedPipetteCalibrations(state, robot.name)[mount]?.offset ?? null - // const pip = getAttachedPipettes(state, robot.name)[mount] - // return { - // calibrationExists: Boolean(pipcal), - // markedBad: pipcal?.status?.markedBad ?? false, - // // @ts-expect-error protect for cases where model is not on pip - // pipetteModel: pip.model, - // } - // } - return null -} - -export function getAnalyticsTipLengthCalibrationData( - state: State, - mount: Mount -): TipLengthCalibrationAnalyticsData | null { - // const robot = getConnectedRobot(state) - - // if (robot) { - // const tipcal = - // getAttachedPipetteCalibrations(state, robot.name)[mount]?.tipLength ?? - // null - // const pip = getAttachedPipettes(state, robot.name)[mount] - // return { - // calibrationExists: Boolean(tipcal), - // markedBad: tipcal?.status?.markedBad ?? false, - // // @ts-expect-error protect for cases where model is not on pip - // pipetteModel: pip.model, - // } - // } - return null -} - -// function getPipetteModels(state: State, robotName: string): ModelsByMount { -// // @ts-expect-error ensure that both mount keys exist on returned object -// return Object.entries( -// getAttachedPipettes(state, robotName) -// ).reduce((obj, [mount, pipData]): ModelsByMount => { -// if (pipData) { -// obj[mount as Mount] = pick(pipData, ['model']) -// } -// return obj -// // @ts-expect-error ensure that both mount keys exist on returned object -// }, {}) -// } - -// function getCalibrationCheckData( -// state: State, -// robotName: string -// ): CalibrationCheckByMount | null { -// const session = getCalibrationCheckSession(state, robotName) -// if (!session) { -// return null -// } -// const { comparisonsByPipette, instruments } = session.details -// return instruments.reduce( -// (obj, instrument: CalibrationCheckInstrument) => { -// const { rank, mount, model } = instrument -// const succeeded = !some( -// Object.keys(comparisonsByPipette[rank]).map(k => -// Boolean( -// comparisonsByPipette[rank][ -// k as keyof CalibrationCheckComparisonsPerCalibration -// ]?.status === 'OUTSIDE_THRESHOLD' -// ) -// ) -// ) -// obj[mount] = { -// comparisons: comparisonsByPipette[rank], -// succeeded: succeeded, -// model: model, -// } -// return obj -// }, -// { left: null, right: null } -// ) -// } - -export function getAnalyticsDeckCalibrationData( - state: State -): DeckCalibrationAnalyticsData | null { - // TODO(va, 08-17-22): this selector was broken and was always returning null because getConnectedRobot - // always returned null, this should be fixed at the epic level in a future ticket RAUT-150 - // const robot = getConnectedRobot(state) - // if (robot) { - // const dcData = getDeckCalibrationData(state, robot.name) - // return { - // calibrationStatus: getDeckCalibrationStatus(state, robot.name), - // markedBad: !Array.isArray(dcData) - // ? dcData?.status?.markedBad || null - // : null, - // pipettes: getPipetteModels(state, robot.name), - // } - // } - return null -} - -export function getAnalyticsHealthCheckData( - state: State -): CalibrationHealthCheckAnalyticsData | null { - // TODO(va, 08-17-22): this selector was broken and was always returning null because getConnectedRobot - // always returned null, this should be fixed at the epic level in a future ticket RAUT-150 - // const robot = getConnectedRobot(state) - // if (robot) { - // return { - // pipettes: getCalibrationCheckData(state, robot.name), - // } - // } - return null -} - export function getAnalyticsSessionExitDetails( state: State, robotName: string, sessionId: string ): AnalyticsSessionExitDetails | null { const session = getRobotSessionById(state, robotName, sessionId) - if (session) { + if (session != null) { return { step: session.details.currentStep, sessionType: session.sessionType, @@ -298,7 +78,7 @@ export function getSessionInstrumentAnalyticsData( sessionId: string ): SessionInstrumentAnalyticsData | null { const session = getRobotSessionById(state, robotName, sessionId) - if (session) { + if (session != null) { const pipModel = session.sessionType === Sessions.SESSION_TYPE_CALIBRATION_HEALTH_CHECK ? session.details.activePipette.model From f4112d3d178576b6a221344cc7b1312f8baf88c0 Mon Sep 17 00:00:00 2001 From: Jamey H Date: Thu, 9 Nov 2023 15:42:16 -0500 Subject: [PATCH 50/65] fix(app): fix step meter tearing by using no animation (#13960) ODD optimizations do not prevent step meter tearing on the physical ODD when step progress regresses. Playing no animation solves the problem until we optimize ODD animations. --- .../StepMeter/__tests__/StepMeter.test.tsx | 17 +++++++++++++++++ app/src/atoms/StepMeter/index.tsx | 12 ++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/app/src/atoms/StepMeter/__tests__/StepMeter.test.tsx b/app/src/atoms/StepMeter/__tests__/StepMeter.test.tsx index 50aa54e4343..faa688df6f1 100644 --- a/app/src/atoms/StepMeter/__tests__/StepMeter.test.tsx +++ b/app/src/atoms/StepMeter/__tests__/StepMeter.test.tsx @@ -51,4 +51,21 @@ describe('StepMeter', () => { const bar = getByTestId('StepMeter_StepMeterBar') expect(bar).toHaveStyle('width: 100%') }) + + it('should transition with style when progressing forward and no style if progressing backward', () => { + props = { + ...props, + currentStep: 2, + } + const { getByTestId } = render(props) + getByTestId('StepMeter_StepMeterContainer') + const bar = getByTestId('StepMeter_StepMeterBar') + expect(bar).toHaveStyle('transition: width 0.5s ease-in-out;') + + props = { + ...props, + currentStep: 1, + } + expect(bar).not.toHaveStyle('transition: ;') + }) }) diff --git a/app/src/atoms/StepMeter/index.tsx b/app/src/atoms/StepMeter/index.tsx index ddaf52565cf..0d9774bd363 100644 --- a/app/src/atoms/StepMeter/index.tsx +++ b/app/src/atoms/StepMeter/index.tsx @@ -16,13 +16,13 @@ interface StepMeterProps { export const StepMeter = (props: StepMeterProps): JSX.Element => { const { totalSteps, currentStep } = props + const prevPercentComplete = React.useRef(0) const progress = currentStep != null ? currentStep : 0 - const percentComplete = `${ + const percentComplete = // this logic puts a cap at 100% percentComplete which we should never run into currentStep != null && currentStep > totalSteps ? 100 : (progress / totalSteps) * 100 - }%` const StepMeterContainer = css` position: ${POSITION_RELATIVE}; @@ -45,11 +45,15 @@ export const StepMeter = (props: StepMeterProps): JSX.Element => { top: 0; height: 100%; background-color: ${COLORS.blueEnabled}; - width: ${percentComplete}; + width: ${percentComplete}%; transform: translateX(0); - transition: width 0.5s ease-in-out; + transition: ${prevPercentComplete.current <= percentComplete + ? 'width 0.5s ease-in-out' + : ''}; ` + prevPercentComplete.current = percentComplete + return ( From 711f48abb23cb2770c0f6174d98bfce5969619a4 Mon Sep 17 00:00:00 2001 From: Jamey H Date: Thu, 9 Nov 2023 16:43:04 -0500 Subject: [PATCH 51/65] fix(app): Fix desktop app update modals (#13935) * feat(app): add release notes button on app & robot update modals * fix(app): fix closing app update modal during robot downgrade When downgrading a robot, users are first prompted if they'd like to update their app. When clicking close, the downgrade should proceed instead of crashing the app. --- .../assets/localization/en/app_settings.json | 1 + .../localization/en/device_settings.json | 1 + .../UpdateBuildroot/UpdateRobotModal.tsx | 66 ++++++++++++------- .../UpdateBuildroot/ViewUpdateModal.tsx | 11 ++-- .../__tests__/UpdateRobotModal.test.tsx | 18 ++++- .../__tests__/UpdateAppModal.test.tsx | 15 ++++- app/src/organisms/UpdateAppModal/index.tsx | 49 +++++++++----- 7 files changed, 116 insertions(+), 45 deletions(-) diff --git a/app/src/assets/localization/en/app_settings.json b/app/src/assets/localization/en/app_settings.json index f717a04bac9..0f5ea5a8609 100644 --- a/app/src/assets/localization/en/app_settings.json +++ b/app/src/assets/localization/en/app_settings.json @@ -70,6 +70,7 @@ "problem_during_update": "This update is taking longer than usual.", "prompt": "Always show the prompt to choose calibration block or trash bin", "receive_alert": "Receive an alert when an Opentrons software update is available.", + "release_notes": "Release notes", "remind_later": "Remind me later", "reset_to_default": "Reset to default", "restart_touchscreen": "Restart touchscreen", diff --git a/app/src/assets/localization/en/device_settings.json b/app/src/assets/localization/en/device_settings.json index 2335abe9bd4..f530ad9f711 100644 --- a/app/src/assets/localization/en/device_settings.json +++ b/app/src/assets/localization/en/device_settings.json @@ -83,6 +83,7 @@ "device_reset_description": "Reset labware calibration, boot scripts, and/or robot calibration to factory settings.", "device_reset_slideout_description": "Select individual settings to only clear specific data types.", "device_resets_cannot_be_undone": "Resets cannot be undone", + "release_notes": "Release notes", "directly_connected_to_this_computer": "Directly connected to this computer.", "disconnect": "Disconnect", "disconnect_from_ssid": "Disconnect from {{ssid}}", diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx index 674c30a480c..3762cdd1955 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/UpdateRobotModal.tsx @@ -7,7 +7,8 @@ import { useHoverTooltip, ALIGN_CENTER, DIRECTION_COLUMN, - JUSTIFY_FLEX_END, + JUSTIFY_SPACE_BETWEEN, + JUSTIFY_SPACE_AROUND, SPACING, Flex, NewPrimaryBtn, @@ -22,7 +23,9 @@ import { UPGRADE, REINSTALL, DOWNGRADE, + getRobotUpdateVersion, } from '../../../../redux/robot-update' +import { ExternalLink } from '../../../../atoms/Link/ExternalLink' import { ReleaseNotes } from '../../../../molecules/ReleaseNotes' import { useIsRobotBusy } from '../../hooks' import { Tooltip } from '../../../../atoms/Tooltip' @@ -33,6 +36,9 @@ import { useDispatchStartRobotUpdate } from '../../../../redux/robot-update/hook import type { State, Dispatch } from '../../../../redux/types' import type { RobotSystemType } from '../../../../redux/robot-update/types' +export const RELEASE_NOTES_URL_BASE = + 'https://github.com/Opentrons/opentrons/releases/tag/v' + const UpdateAppBanner = styled(Banner)` border: none; ` @@ -73,6 +79,10 @@ export function UpdateRobotModal({ return getRobotUpdateDisplayInfo(state, robotName) }) const dispatchStartRobotUpdate = useDispatchStartRobotUpdate() + const robotUpdateVersion = useSelector((state: State) => { + return getRobotUpdateVersion(state, robotName) ?? '' + }) + const isRobotBusy = useIsRobotBusy() const updateDisabled = updateFromFileDisabledReason !== null || isRobotBusy @@ -98,28 +108,40 @@ export function UpdateRobotModal({ } const robotUpdateFooter = ( - - + - {updateType === UPGRADE ? t('remind_me_later') : t('not_now')} - - dispatchStartRobotUpdate(robotName)} - marginRight={SPACING.spacing12} - css={FOOTER_BUTTON_STYLE} - disabled={updateDisabled} - {...updateButtonProps} - > - {t('update_robot_now')} - - {updateDisabled && ( - - {disabledReason} - - )} + {t('release_notes')} + + + + {updateType === UPGRADE ? t('remind_me_later') : t('not_now')} + + dispatchStartRobotUpdate(robotName)} + marginRight={SPACING.spacing12} + css={FOOTER_BUTTON_STYLE} + disabled={updateDisabled} + {...updateButtonProps} + > + {t('update_robot_now')} + + {updateDisabled && ( + + {disabledReason} + + )} + ) diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/ViewUpdateModal.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/ViewUpdateModal.tsx index 7b2207f0bb2..1010313bb1d 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/ViewUpdateModal.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/ViewUpdateModal.tsx @@ -27,6 +27,7 @@ export function ViewUpdateModal( props: ViewUpdateModalProps ): JSX.Element | null { const { robotName, robot, closeModal } = props + const [showAppUpdateModal, setShowAppUpdateModal] = React.useState(true) const updateInfo = useSelector((state: State) => getRobotUpdateInfo(state, robotName) @@ -38,7 +39,9 @@ export function ViewUpdateModal( getRobotUpdateAvailable(state, robot) ) const robotSystemType = getRobotSystemType(robot) - const availableAppUpdateVersion = useSelector(getAvailableShellUpdate) + const availableAppUpdateVersion = Boolean( + useSelector(getAvailableShellUpdate) + ) const [ showMigrationWarning, @@ -51,12 +54,12 @@ export function ViewUpdateModal( } let releaseNotes = '' - if (updateInfo?.releaseNotes) releaseNotes = updateInfo.releaseNotes + if (updateInfo?.releaseNotes != null) releaseNotes = updateInfo.releaseNotes - if (availableAppUpdateVersion) + if (availableAppUpdateVersion && showAppUpdateModal) return ( - + setShowAppUpdateModal(false)} /> ) diff --git a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/UpdateRobotModal.test.tsx b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/UpdateRobotModal.test.tsx index d36aab3d057..7af9f5169f3 100644 --- a/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/UpdateRobotModal.test.tsx +++ b/app/src/organisms/Devices/RobotSettings/UpdateBuildroot/__tests__/UpdateRobotModal.test.tsx @@ -6,9 +6,12 @@ import { fireEvent } from '@testing-library/react' import { renderWithProviders } from '@opentrons/components' import { i18n } from '../../../../../i18n' -import { getRobotUpdateDisplayInfo } from '../../../../../redux/robot-update' +import { + getRobotUpdateDisplayInfo, + getRobotUpdateVersion, +} from '../../../../../redux/robot-update' import { getDiscoverableRobotByName } from '../../../../../redux/discovery' -import { UpdateRobotModal } from '../UpdateRobotModal' +import { UpdateRobotModal, RELEASE_NOTES_URL_BASE } from '../UpdateRobotModal' import type { Store } from 'redux' import type { State } from '../../../../../redux/types' @@ -25,6 +28,9 @@ const mockGetRobotUpdateDisplayInfo = getRobotUpdateDisplayInfo as jest.MockedFu const mockGetDiscoverableRobotByName = getDiscoverableRobotByName as jest.MockedFunction< typeof getDiscoverableRobotByName > +const mockGetRobotUpdateVersion = getRobotUpdateVersion as jest.MockedFunction< + typeof getRobotUpdateVersion +> const render = (props: React.ComponentProps) => { return renderWithProviders(, { @@ -51,6 +57,7 @@ describe('UpdateRobotModal', () => { updateFromFileDisabledReason: 'test', }) when(mockGetDiscoverableRobotByName).mockReturnValue(null) + when(mockGetRobotUpdateVersion).mockReturnValue('7.0.0') }) afterEach(() => { @@ -93,6 +100,13 @@ describe('UpdateRobotModal', () => { expect(props.closeModal).toHaveBeenCalled() }) + it('renders a release notes link pointing to the Github releases page', () => { + const [{ getByText }] = render(props) + + const link = getByText('Release notes') + expect(link).toHaveAttribute('href', RELEASE_NOTES_URL_BASE + '7.0.0') + }) + it('renders proper text when reinstalling', () => { props = { ...props, diff --git a/app/src/organisms/UpdateAppModal/__tests__/UpdateAppModal.test.tsx b/app/src/organisms/UpdateAppModal/__tests__/UpdateAppModal.test.tsx index a7d8069cf1e..939755c8208 100644 --- a/app/src/organisms/UpdateAppModal/__tests__/UpdateAppModal.test.tsx +++ b/app/src/organisms/UpdateAppModal/__tests__/UpdateAppModal.test.tsx @@ -1,11 +1,13 @@ import * as React from 'react' import { when } from 'jest-when' import { fireEvent } from '@testing-library/react' + import { renderWithProviders } from '@opentrons/components' + import { i18n } from '../../../i18n' import * as Shell from '../../../redux/shell' -import { UpdateAppModal, UpdateAppModalProps } from '..' import { useRemoveActiveAppUpdateToast } from '../../Alerts' +import { UpdateAppModal, UpdateAppModalProps, RELEASE_NOTES_URL_BASE } from '..' import type { State } from '../../../redux/types' import type { ShellUpdateState } from '../../../redux/shell/types' @@ -33,6 +35,9 @@ const mockUseRemoveActiveAppUpdateToast = useRemoveActiveAppUpdateToast as jest. const render = (props: React.ComponentProps) => { return renderWithProviders(, { i18nInstance: i18n, + initialState: { + shell: { update: { info: { version: '7.0.0' }, available: true } }, + }, }) } @@ -76,6 +81,14 @@ describe('UpdateAppModal', () => { fireEvent.click(getByText('Remind me later')) expect(closeModal).toHaveBeenCalled() }) + + it('renders a release notes link pointing to the Github releases page', () => { + const [{ getByText }] = render(props) + + const link = getByText('Release notes') + expect(link).toHaveAttribute('href', RELEASE_NOTES_URL_BASE + '7.0.0') + }) + it('shows error modal on error', () => { getShellUpdateState.mockReturnValue({ error: { diff --git a/app/src/organisms/UpdateAppModal/index.tsx b/app/src/organisms/UpdateAppModal/index.tsx index 16f0fc7e517..367a6edc779 100644 --- a/app/src/organisms/UpdateAppModal/index.tsx +++ b/app/src/organisms/UpdateAppModal/index.tsx @@ -8,20 +8,23 @@ import { ALIGN_CENTER, COLORS, DIRECTION_COLUMN, - JUSTIFY_FLEX_END, SPACING, Flex, NewPrimaryBtn, NewSecondaryBtn, BORDERS, + JUSTIFY_SPACE_BETWEEN, + JUSTIFY_SPACE_AROUND, } from '@opentrons/components' import { getShellUpdateState, + getAvailableShellUpdate, downloadShellUpdate, applyShellUpdate, } from '../../redux/shell' +import { ExternalLink } from '../../atoms/Link/ExternalLink' import { ReleaseNotes } from '../../molecules/ReleaseNotes' import { LegacyModal } from '../../molecules/LegacyModal' import { Banner } from '../../atoms/Banner' @@ -56,7 +59,8 @@ const PlaceholderError = ({ ) } - +export const RELEASE_NOTES_URL_BASE = + 'https://github.com/Opentrons/opentrons/releases/tag/v' const UPDATE_ERROR = 'Update Error' const FOOTER_BUTTON_STYLE = css` text-transform: lowercase; @@ -105,6 +109,7 @@ export function UpdateAppModal(props: UpdateAppModalProps): JSX.Element { const { t } = useTranslation('app_settings') const history = useHistory() const { removeActiveAppUpdateToast } = useRemoveActiveAppUpdateToast() + const availableAppUpdateVersion = useSelector(getAvailableShellUpdate) ?? '' if (downloaded) setTimeout(() => dispatch(applyShellUpdate()), RESTART_APP_AFTER_TIME) @@ -117,21 +122,33 @@ export function UpdateAppModal(props: UpdateAppModalProps): JSX.Element { removeActiveAppUpdateToast() const appUpdateFooter = ( - - - {t('remind_later')} - - dispatch(downloadShellUpdate())} - marginRight={SPACING.spacing12} - css={FOOTER_BUTTON_STYLE} + + - {t('update_app_now')} - + {t('release_notes')} + + + + {t('remind_later')} + + dispatch(downloadShellUpdate())} + marginRight={SPACING.spacing12} + css={FOOTER_BUTTON_STYLE} + > + {t('update_app_now')} + + ) From df4b755481f744f7b4eae7497a172b4de69c2b53 Mon Sep 17 00:00:00 2001 From: Shlok Amin Date: Thu, 9 Nov 2023 16:46:18 -0500 Subject: [PATCH 52/65] refactor(app): remove console log on release notes component (#13951) --- app/src/molecules/ReleaseNotes/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/molecules/ReleaseNotes/index.tsx b/app/src/molecules/ReleaseNotes/index.tsx index 3d54e195783..537763bdc94 100644 --- a/app/src/molecules/ReleaseNotes/index.tsx +++ b/app/src/molecules/ReleaseNotes/index.tsx @@ -26,7 +26,6 @@ const DEFAULT_RELEASE_NOTES = 'We recommend upgrading to the latest version.' export function ReleaseNotes(props: ReleaseNotesProps): JSX.Element { const { source } = props - console.log(DEFAULT_RELEASE_NOTES) return (
    {source != null ? ( From 0bd816aa986d402d3fb56712fa91227b7e6d4923 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Thu, 9 Nov 2023 17:05:38 -0500 Subject: [PATCH 53/65] fix(shared-data): Fix the pipette schemas, tests (#13949) The tests that were supposed to ajv the pipette definitions weren't set up properly, and the tests that were supposed to test that the tests were set up properly weren't set up properly, so we weren't testing the schemas so the schemas were wrong. Fix the schema-test setup, the test-setup-schema-test setup, and the schema. --- .../js/__tests__/pipetteSchemaV2.test.ts | 35 ++--- .../schemas/2/pipettePropertiesSchema.json | 129 ++++++++++-------- .../tests/pipette/test_validate_schema.py | 1 + 3 files changed, 85 insertions(+), 80 deletions(-) diff --git a/shared-data/js/__tests__/pipetteSchemaV2.test.ts b/shared-data/js/__tests__/pipetteSchemaV2.test.ts index ae85233ab8c..66845b9cab6 100644 --- a/shared-data/js/__tests__/pipetteSchemaV2.test.ts +++ b/shared-data/js/__tests__/pipetteSchemaV2.test.ts @@ -13,12 +13,12 @@ const allGeometryDefinitions = path.join( const allGeneralDefinitions = path.join( __dirname, - '../../labware/definitions/2/general/**/**/*.json' + '../../pipette/definitions/2/general/**/**/*.json' ) const allLiquidDefinitions = path.join( __dirname, - '../../labware/definitions/2/liquid/**/**/*.json' + '../../pipette/definitions/2/liquid/**/**/*.json' ) const ajv = new Ajv({ allErrors: true, jsonPointers: true }) @@ -29,11 +29,8 @@ const validateGeneralSpecs = ajv.compile(generalSpecsSchema) describe('test schema against all liquid specs definitions', () => { const liquidPaths = glob.sync(allLiquidDefinitions) - - beforeAll(() => { - // Make sure definitions path didn't break, which would give you false positives - expect(liquidPaths.length).toBeGreaterThan(0) - }) + // Make sure definitions path didn't break, which would give you false positives + expect(liquidPaths.length).toBeGreaterThan(0) liquidPaths.forEach(liquidPath => { const liquidDef = require(liquidPath) @@ -45,22 +42,24 @@ describe('test schema against all liquid specs definitions', () => { expect(valid).toBe(true) }) - it(`parent dir matches pipette model: ${liquidPath}`, () => { - expect(['p10', 'p20', 'p50', 'p300', 'p1000']).toContain( + it(`parent dir matches a liquid class: ${liquidPath}`, () => { + expect(['default', 'lowVolumeDefault']).toContain( path.basename(path.dirname(liquidPath)) ) }) + + it(`second parent dir matches pipette model: ${liquidPath}`, () => { + expect(['p10', 'p20', 'p50', 'p300', 'p1000']).toContain( + path.basename(path.dirname(path.dirname(liquidPath))) + ) + }) }) }) describe('test schema against all geometry specs definitions', () => { const geometryPaths = glob.sync(allGeometryDefinitions) - - beforeAll(() => { - // Make sure definitions path didn't break, which would give you false positives - expect(geometryPaths.length).toBeGreaterThan(0) - }) - + // Make sure definitions path didn't break, which would give you false positives + expect(geometryPaths.length).toBeGreaterThan(0) geometryPaths.forEach(geometryPath => { const geometryDef = require(geometryPath) const geometryParentDir = path.dirname(geometryPath) @@ -88,11 +87,7 @@ describe('test schema against all geometry specs definitions', () => { describe('test schema against all general specs definitions', () => { const generalPaths = glob.sync(allGeneralDefinitions) - - beforeAll(() => { - // Make sure definitions path didn't break, which would give you false positives - expect(generalPaths.length).toBeGreaterThan(0) - }) + expect(generalPaths.length).toBeGreaterThan(0) generalPaths.forEach(generalPath => { const generalDef = require(generalPath) diff --git a/shared-data/pipette/schemas/2/pipettePropertiesSchema.json b/shared-data/pipette/schemas/2/pipettePropertiesSchema.json index 810ceade169..d2b2a7c78fa 100644 --- a/shared-data/pipette/schemas/2/pipettePropertiesSchema.json +++ b/shared-data/pipette/schemas/2/pipettePropertiesSchema.json @@ -1,13 +1,13 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "$id": "opentronsPipetteGeometrySchemaV2", + "$id": "opentronsPipettePropertiesSchemaV2", "definitions": { "channels": { "enum": [1, 8, 96, 384] }, "displayCategory": { "type": "string", - "enum": ["GEN1"] + "enum": ["GEN1", "GEN2", "FLEX"] }, "positiveNumber": { "type": "number", @@ -18,33 +18,6 @@ "minimum": 0.01, "maximum": 2.5 }, - "xyzArray": { - "type": "array", - "description": "Array of 3 numbers, [x, y, z]", - "items": { "type": "number" }, - "minItems": 3, - "maxItems": 3 - }, - "linearEquations": { - "description": "Array containing any number of 3-arrays. Each inner 3-array describes a line segment: [boundary, slope, intercept]. So [1, 2, 3] would mean 'where (next_boundary > x >= 1), y = 2x + 3'", - "type": "array", - "items": { - "type": "array", - "items": { "type": "number" }, - "minItems": 3, - "maxItems": 3 - } - }, - "liquidHandlingSpecs": { - "description": "Object containing linear equations for translating between uL of liquid and mm of plunger travel. There is one linear equation for aspiration and one for dispense", - "type": "object", - "required": ["aspirate", "dispense"], - "additionalProperties": false, - "properties": { - "aspirate": { "$ref": "#/definitions/linearEquations" }, - "dispense": { "$ref": "#/definitions/linearEquations" } - } - }, "editConfigurations": { "type": "object", "description": "Object allowing you to modify a config", @@ -57,17 +30,6 @@ "type": { "type": "string" }, "displayName": { "type": "string" } } - }, - "tipConfigurations": { - "type": "object", - "description": "Object containing configurations specific to tip handling", - "required": ["speed"], - "properties": { - "presses": {}, - "speed": { "$ref": "#/definitions/editConfigurations" }, - "increment": {}, - "distance": {} - } } }, "description": "Version-level pipette specifications, which may vary across different versions of the same pipette", @@ -103,20 +65,43 @@ }, "channels": { "$ref": "#/definitions/channels" }, "partialTipConfigurations": { - "type": "object", "description": "Object containing information on partial tip configurations", - "required": ["partialTipSupported"], - "properties": { - "partialTipSupported": { "type": "boolean" }, - "availableConfigurations": { - "type": "array", - "description": "Array of available configurations", - "items": { - "type": "number", - "enum": [1, 2, 3, 4, 5, 6, 7, 8, 12, 96, 384] + "$oneof": [ + { + "type": "object", + "required": ["partialTipSupported"], + "properties": { + "partialTipSupported": { "type": "boolean", "value": true } + } + }, + { + "type": "object", + "required": [ + "partialTipSupported", + "availableConfigurations", + "perTipPickupCurrent" + ], + "properties": { + "partialTipSupported": { "type": "boolean", "value": false }, + "availableConfigurations": { + "type": "array", + "description": "Array of available configurations", + "items": { + "type": "number", + "enum": [1, 2, 3, 4, 5, 6, 7, 8, 12, 96, 384] + }, + "perTipPickupCurrent": { + "type": "object", + "patternProperties": { + "\\d+": { + "$ref": "#/definitions/positiveNumber" + } + } + } + } } } - } + ] }, "availableSensors": { "type": "object", @@ -142,13 +127,20 @@ }, "plungerPositionsConfigurations": { "type": "object", - "description": "Object containing configurations specific to tip handling", - "required": ["top", "bottom", "blowout", "drop"], - "properties": { - "top": { "$ref": "#/definitions/currentRange" }, - "bottom": {}, - "blowout": { "$ref": "#/definitions/editConfigurations" }, - "drop": {} + "description": "Key positions of the plunger, by liquid configuration", + "required": ["default"], + "patternProperties": { + "\\w+": { + "type": "object", + "description": "Plunger positions for this liquid configuration", + "required": ["top", "bottom", "blowout", "drop"], + "properties": { + "top": { "type": "number" }, + "bottom": { "type": "number" }, + "blowout": { "type": "number" }, + "drop": { "type": "number" } + } + } } }, "plungerMotorConfigurations": { @@ -170,10 +162,27 @@ } }, "pickUpTipConfigurations": { - "$ref": "#/definitions/tipConfigurations" + "type": "object", + "description": "Object containing configurations for picking up tips common to all partial configurations", + "required": ["speed"], + "properties": { + "presses": { "$ref": "#/definitions/positiveNumber" }, + "speed": { "$ref": "#/definitions/positiveNumber" }, + "increment": { "$ref": "#/definitions/positiveNumber" }, + "distance": { "$ref": "#/definitions/positiveNumber" } + } }, "dropTipConfigurations": { - "$ref": "#/definitions/tipConfigurations" + "type": "object", + "description": "Object containing configurations specific to dropping tips", + "required": ["current", "speed"], + "properties": { + "current": { "$ref": "#/definitions/currentRange" }, + "presses": {}, + "speed": { "$ref": "#/definitions/positiveNumber" }, + "increment": {}, + "distance": {} + } }, "displayName": { "type": "string", diff --git a/shared-data/python/tests/pipette/test_validate_schema.py b/shared-data/python/tests/pipette/test_validate_schema.py index 1ac8d111a16..df943dceace 100644 --- a/shared-data/python/tests/pipette/test_validate_schema.py +++ b/shared-data/python/tests/pipette/test_validate_schema.py @@ -18,6 +18,7 @@ def test_check_all_models_are_valid() -> None: "ninety_six_channel": "96", "eight_channel": "multi", } + assert os.listdir(paths_to_validate), "You have a path wrong" for channel_dir in os.listdir(paths_to_validate): for model_dir in os.listdir(paths_to_validate / channel_dir): for version_file in os.listdir(paths_to_validate / channel_dir / model_dir): From 90038a8a9d29355b21db8405d2353cad2a63f025 Mon Sep 17 00:00:00 2001 From: Brent Hagen Date: Thu, 9 Nov 2023 20:44:19 -0500 Subject: [PATCH 54/65] refactor(shared-data,app): migrate to deck definition v4 (#13931) changes default OT-2/Flex deck definitions to v4 in shared-data, app, components, and protocol designer closes RAUT-781 --------- Co-authored-by: Brian Cooper --- .../src/deck_configuration/__stubs__/index.ts | 48 +-- .../src/protocols/__tests__/utils.test.ts | 56 +-- api-client/src/protocols/utils.ts | 1 + app/src/molecules/DeckThumbnail/index.tsx | 2 +- .../organisms/CalibrationPanels/DeckSetup.tsx | 1 + .../AddFixtureModal.stories.tsx | 2 +- .../AddFixtureModal.tsx | 17 +- .../__tests__/AddFixtureModal.test.tsx | 12 +- .../DeviceDetailsDeckConfiguration/index.tsx | 6 +- .../Devices/ProtocolRun/ProtocolRunSetup.tsx | 6 +- .../SetupLiquids/SetupLiquidsMap.tsx | 28 +- .../LocationConflictModal.tsx | 9 +- .../__tests__/LocationConflictModal.test.tsx | 6 +- .../__tests__/NotConfiguredModal.test.tsx | 2 +- .../__tests__/SetupFixtureList.test.tsx | 6 +- .../__tests__/SetupModulesAndDeck.test.tsx | 2 +- .../__tests__/getLabwareRenderInfo.test.ts | 2 +- .../__tests__/getProtocolModulesInfo.test.ts | 2 +- .../ProtocolRun/utils/getLabwareRenderInfo.ts | 45 +-- .../utils/getProtocolModulesInfo.ts | 12 +- .../useLabwareRenderInfoForRunById.test.tsx | 2 +- ...seModuleRenderInfoForProtocolById.test.tsx | 9 +- .../DropTipWizard/ChooseLocation.tsx | 29 +- .../MoveLabwareInterventionContent.tsx | 6 +- .../InterventionModal/__tests__/utils.test.ts | 20 +- .../utils/getRunLabwareRenderInfo.ts | 14 +- .../utils/getRunModuleRenderInfo.ts | 14 +- .../ModuleWizardFlows/SelectLocation.tsx | 2 +- app/src/organisms/ProtocolDetails/index.tsx | 2 +- .../ProtocolSetupDeckConfiguration.test.tsx | 2 +- .../ProtocolSetupDeckConfiguration/index.tsx | 2 +- .../__tests__/ProtocolSetupLabware.test.tsx | 2 +- .../FixtureTable.tsx | 9 +- .../__tests__/FixtureTable.test.tsx | 6 +- .../__tests__/DeckConfiguration.test.tsx | 2 +- .../ProtocolDetails/Hardware.tsx | 7 +- .../__tests__/Hardware.test.tsx | 6 +- .../__tests__/ProtocolSetup.test.tsx | 2 +- app/src/pages/Protocols/hooks/index.ts | 6 +- .../__tests__/hooks.test.ts | 20 +- app/src/resources/deck_configuration/utils.ts | 8 +- .../src/hardware-sim/BaseDeck/BaseDeck.tsx | 212 +++++++----- .../BaseDeck/SingleSlotFixture.tsx | 43 +-- .../BaseDeck/StagingAreaFixture.tsx | 14 +- .../BaseDeck/WasteChuteFixture.tsx | 19 +- .../BaseDeck/WasteChuteStagingAreaFixture.tsx | 17 +- .../BaseDeck/__fixtures__/index.ts | 72 ++-- .../{DeckFromData.tsx => DeckFromLayers.tsx} | 26 +- .../src/hardware-sim/Deck/FlexTrash.tsx | 41 ++- .../hardware-sim/Deck/MoveLabwareOnDeck.tsx | 93 ++--- .../src/hardware-sim/Deck/RobotWorkSpace.tsx | 12 +- .../src/hardware-sim/Deck/StyledDeck.tsx | 26 +- .../hardware-sim/Deck/getDeckDefinitions.ts | 2 +- components/src/hardware-sim/Deck/index.tsx | 2 +- .../DeckConfigurator.stories.tsx | 19 +- .../DeckConfigurator/EmptyConfigFixture.tsx | 21 +- .../StagingAreaConfigFixture.tsx | 14 +- .../TrashBinConfigFixture.tsx | 22 +- .../WasteChuteConfigFixture.tsx | 14 +- .../hardware-sim/DeckConfigurator/index.tsx | 26 +- .../hardware-sim/DeckSlotLocation/index.tsx | 2 +- .../RobotCoordinateSpaceWithDOMCoords.tsx | 2 +- components/src/hardware-sim/index.ts | 1 + .../src/hooks/useSelectDeckLocation/index.tsx | 187 +++++----- .../organisms/CreateLabwareSandbox/index.tsx | 25 +- .../LabwareOverlays/AdapterControls.tsx | 24 +- .../LabwareOverlays/LabwareControls.tsx | 9 +- .../LabwareOverlays/SlotControls.tsx | 34 +- .../__tests__/SlotControls.test.tsx | 22 +- .../src/components/DeckSetup/index.tsx | 326 ++++++++++-------- .../fields/LabwareLocationField/index.tsx | 8 +- .../labware/__tests__/utils.test.ts | 4 +- .../src/components/labware/utils.ts | 4 +- .../CreateFileWizard/StagingAreaTile.tsx | 7 +- .../modals/CreateFileWizard/index.tsx | 4 +- .../components/modules/AdditionalItemsRow.tsx | 17 +- .../src/components/modules/FlexSlotMap.tsx | 27 +- .../components/modules/StagingAreasModal.tsx | 5 +- .../components/modules/StagingAreasRow.tsx | 8 +- .../src/components/modules/TrashModal.tsx | 6 +- .../__tests__/AdditionalItemsRow.test.tsx | 3 +- .../__tests__/StagingAreasRow.test.tsx | 2 +- .../modules/__tests__/TrashModal.test.tsx | 4 +- .../src/components/modules/utils.ts | 1 - .../components/steplist/MoveLabwareHeader.tsx | 4 +- protocol-designer/src/labware-ingred/utils.ts | 2 +- .../top-selectors/labware-locations/index.ts | 9 +- protocol-designer/src/tutorial/selectors.ts | 4 +- ...seCreateDeckConfigurationMutation.test.tsx | 4 +- shared-data/deck/types/schemaV4.ts | 13 +- shared-data/js/constants.ts | 121 ++++++- shared-data/js/fixtures.ts | 128 ++++++- .../getDeckDefFromLoadedLabware.test.ts | 4 +- shared-data/js/helpers/index.ts | 15 +- shared-data/js/types.ts | 78 ++++- .../src/__tests__/moveLabware.test.ts | 10 +- .../__tests__/wasteChuteCommandsUtil.test.ts | 4 +- .../src/commandCreators/atomic/moveLabware.ts | 4 +- step-generation/src/constants.ts | 4 +- step-generation/src/utils/misc.ts | 4 +- .../src/utils/modulePipetteCollision.ts | 1 - 101 files changed, 1363 insertions(+), 908 deletions(-) rename components/src/hardware-sim/Deck/{DeckFromData.tsx => DeckFromLayers.tsx} (59%) diff --git a/api-client/src/deck_configuration/__stubs__/index.ts b/api-client/src/deck_configuration/__stubs__/index.ts index 5f2bd147a0e..2197c25baaa 100644 --- a/api-client/src/deck_configuration/__stubs__/index.ts +++ b/api-client/src/deck_configuration/__stubs__/index.ts @@ -10,63 +10,63 @@ import { import type { Fixture } from '@opentrons/shared-data' export const DECK_CONFIG_STUB: { [fixtureLocation: string]: Fixture } = { - A1: { - fixtureLocation: 'A1', + cutoutA1: { + fixtureLocation: 'cutoutA1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - B1: { - fixtureLocation: 'B1', + cutoutB1: { + fixtureLocation: 'cutoutB1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - C1: { - fixtureLocation: 'C1', + cutoutC1: { + fixtureLocation: 'cutoutC1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - D1: { - fixtureLocation: 'D1', + cutoutD1: { + fixtureLocation: 'cutoutD1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - A2: { - fixtureLocation: 'A2', + cutoutA2: { + fixtureLocation: 'cutoutA2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - B2: { - fixtureLocation: 'B2', + cutoutB2: { + fixtureLocation: 'cutoutB2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - C2: { - fixtureLocation: 'C2', + cutoutC2: { + fixtureLocation: 'cutoutC2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - D2: { - fixtureLocation: 'D2', + cutoutD2: { + fixtureLocation: 'cutoutD2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - A3: { - fixtureLocation: 'A3', + cutoutA3: { + fixtureLocation: 'cutoutA3', loadName: TRASH_BIN_LOAD_NAME, fixtureId: uuidv4(), }, - B3: { - fixtureLocation: 'B3', + cutoutB3: { + fixtureLocation: 'cutoutB3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, - C3: { - fixtureLocation: 'C3', + cutoutC3: { + fixtureLocation: 'cutoutC3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, - D3: { - fixtureLocation: 'D3', + cutoutD3: { + fixtureLocation: 'cutoutD3', loadName: WASTE_CHUTE_LOAD_NAME, fixtureId: uuidv4(), }, diff --git a/api-client/src/protocols/__tests__/utils.test.ts b/api-client/src/protocols/__tests__/utils.test.ts index f86532d7359..c9edcae0068 100644 --- a/api-client/src/protocols/__tests__/utils.test.ts +++ b/api-client/src/protocols/__tests__/utils.test.ts @@ -10,17 +10,10 @@ import { parseLiquidsInLoadOrder, parseLabwareInfoByLiquidId, parseInitialLoadedLabwareByAdapter, - parseInitialLoadedFixturesByCutout, } from '../utils' import { simpleAnalysisFileFixture } from '../__fixtures__' -import { - LoadFixtureRunTimeCommand, - RunTimeCommand, - STAGING_AREA_LOAD_NAME, - STANDARD_SLOT_LOAD_NAME, - WASTE_CHUTE_LOAD_NAME, -} from '@opentrons/shared-data' +import { RunTimeCommand } from '@opentrons/shared-data' const mockRunTimeCommands: RunTimeCommand[] = simpleAnalysisFileFixture.commands as any const mockLoadLiquidRunTimeCommands = [ @@ -366,53 +359,6 @@ describe('parseInitialLoadedModulesBySlot', () => { ) }) }) -describe('parseInitialLoadedFixturesByCutout', () => { - it('returns fixtures loaded in cutouts', () => { - const loadFixtureCommands: LoadFixtureRunTimeCommand[] = [ - { - id: 'fakeId1', - commandType: 'loadFixture', - params: { - loadName: STAGING_AREA_LOAD_NAME, - location: { cutout: 'B3' }, - }, - createdAt: 'fake_timestamp', - startedAt: 'fake_timestamp', - completedAt: 'fake_timestamp', - status: 'succeeded', - }, - { - id: 'fakeId2', - commandType: 'loadFixture', - params: { loadName: WASTE_CHUTE_LOAD_NAME, location: { cutout: 'D3' } }, - createdAt: 'fake_timestamp', - startedAt: 'fake_timestamp', - completedAt: 'fake_timestamp', - status: 'succeeded', - }, - { - id: 'fakeId3', - commandType: 'loadFixture', - params: { - loadName: STANDARD_SLOT_LOAD_NAME, - location: { cutout: 'C3' }, - }, - createdAt: 'fake_timestamp', - startedAt: 'fake_timestamp', - completedAt: 'fake_timestamp', - status: 'succeeded', - }, - ] - const expected = { - B3: loadFixtureCommands[0], - D3: loadFixtureCommands[1], - C3: loadFixtureCommands[2], - } - expect(parseInitialLoadedFixturesByCutout(loadFixtureCommands)).toEqual( - expected - ) - }) -}) describe('parseLiquidsInLoadOrder', () => { it('returns liquids in loaded order', () => { const expected = [ diff --git a/api-client/src/protocols/utils.ts b/api-client/src/protocols/utils.ts index 4ba88a02e5e..3ed44a9053a 100644 --- a/api-client/src/protocols/utils.ts +++ b/api-client/src/protocols/utils.ts @@ -229,6 +229,7 @@ export function parseInitialLoadedModulesBySlot( export interface LoadedFixturesBySlot { [slotName: string]: LoadFixtureRunTimeCommand } +// TODO(bh, 2023-11-09): remove this util, there will be no loadFixture command export function parseInitialLoadedFixturesByCutout( commands: RunTimeCommand[] ): LoadedFixturesBySlot { diff --git a/app/src/molecules/DeckThumbnail/index.tsx b/app/src/molecules/DeckThumbnail/index.tsx index a1d0fd06dc6..79df3017cad 100644 --- a/app/src/molecules/DeckThumbnail/index.tsx +++ b/app/src/molecules/DeckThumbnail/index.tsx @@ -87,7 +87,7 @@ export function DeckThumbnail(props: DeckThumbnailProps): JSX.Element | null { const labwareLocations = map( labwareRenderInfo, - ({ labwareDef, displayName, slotName }, labwareId) => { + ({ labwareDef, slotName }, labwareId) => { const labwareInAdapter = initialLoadedLabwareByAdapter[labwareId] // only rendering the labware on top most layer so // either the adapter or the labware are rendered but not both diff --git a/app/src/organisms/CalibrationPanels/DeckSetup.tsx b/app/src/organisms/CalibrationPanels/DeckSetup.tsx index 3b3b208b381..dd19e6254f2 100644 --- a/app/src/organisms/CalibrationPanels/DeckSetup.tsx +++ b/app/src/organisms/CalibrationPanels/DeckSetup.tsx @@ -98,6 +98,7 @@ export function DeckSetup(props: CalibrationPanelProps): JSX.Element { 'fixedTrash', ]} deckDef={deckDef} + showDeckLayers viewBox={`-46 -10 ${488} ${390}`} // TODO: put these in variables > {({ deckSlotsById }) => diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx index 6b618c0fc1e..cc5ddd4f4e7 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.stories.tsx @@ -25,7 +25,7 @@ const Template: Story> = args => ( export const Default = Template.bind({}) Default.args = { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', setShowAddFixtureModal: () => {}, isOnDevice: true, } diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx index a1cb43abb46..9fec31200e9 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/AddFixtureModal.tsx @@ -16,6 +16,7 @@ import { } from '@opentrons/components' import { useUpdateDeckConfigurationMutation } from '@opentrons/react-api-client' import { + getCutoutDisplayName, getFixtureDisplayName, STAGING_AREA_LOAD_NAME, TRASH_BIN_LOAD_NAME, @@ -56,13 +57,17 @@ export function AddFixtureModal({ const { updateDeckConfiguration } = useUpdateDeckConfigurationMutation() const modalHeader: ModalHeaderBaseProps = { - title: t('add_to_slot', { slotName: fixtureLocation }), + title: t('add_to_slot', { + slotName: getCutoutDisplayName(fixtureLocation), + }), hasExitIcon: true, onClick: () => setShowAddFixtureModal(false), } const modalProps: LegacyModalProps = { - title: t('add_to_slot', { slotName: fixtureLocation }), + title: t('add_to_slot', { + slotName: getCutoutDisplayName(fixtureLocation), + }), onClose: () => setShowAddFixtureModal(false), closeOnOutsideClick: true, childrenPadding: SPACING.spacing24, @@ -71,13 +76,13 @@ export function AddFixtureModal({ const availableFixtures: FixtureLoadName[] = [TRASH_BIN_LOAD_NAME] if ( - fixtureLocation === 'A3' || - fixtureLocation === 'B3' || - fixtureLocation === 'C3' + fixtureLocation === 'cutoutA3' || + fixtureLocation === 'cutoutB3' || + fixtureLocation === 'cutoutC3' ) { availableFixtures.push(STAGING_AREA_LOAD_NAME) } - if (fixtureLocation === 'D3') { + if (fixtureLocation === 'cutoutD3') { availableFixtures.push(STAGING_AREA_LOAD_NAME, WASTE_CHUTE_LOAD_NAME) } diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx index e497050c353..f20f887bfd4 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/__tests__/AddFixtureModal.test.tsx @@ -27,7 +27,7 @@ describe('Touchscreen AddFixtureModal', () => { beforeEach(() => { props = { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', setShowAddFixtureModal: mockSetShowAddFixtureModal, setCurrentDeckConfig: mockSetCurrentDeckConfig, isOnDevice: true, @@ -61,7 +61,7 @@ describe('Desktop AddFixtureModal', () => { beforeEach(() => { props = { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', setShowAddFixtureModal: mockSetShowAddFixtureModal, } mockUseUpdateDeckConfigurationMutation.mockReturnValue({ @@ -86,7 +86,7 @@ describe('Desktop AddFixtureModal', () => { }) it('should render text and buttons slot A1', () => { - props = { ...props, fixtureLocation: 'A1' } + props = { ...props, fixtureLocation: 'cutoutA1' } const [{ getByText, getByRole }] = render(props) getByText('Add to slot A1') getByText( @@ -97,7 +97,7 @@ describe('Desktop AddFixtureModal', () => { }) it('should render text and buttons slot B3', () => { - props = { ...props, fixtureLocation: 'B3' } + props = { ...props, fixtureLocation: 'cutoutB3' } const [{ getByText, getAllByRole }] = render(props) getByText('Add to slot B3') getByText( @@ -109,11 +109,11 @@ describe('Desktop AddFixtureModal', () => { }) it('should call a mock function when clicking add button', () => { - props = { ...props, fixtureLocation: 'A1' } + props = { ...props, fixtureLocation: 'cutoutA1' } const [{ getByRole }] = render(props) getByRole('button', { name: 'Add' }).click() expect(mockUpdateDeckConfiguration).toHaveBeenCalledWith({ - fixtureLocation: 'A1', + fixtureLocation: 'cutoutA1', loadName: TRASH_BIN_LOAD_NAME, }) }) diff --git a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx index 69206f577db..c57cef374f8 100644 --- a/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx +++ b/app/src/organisms/DeviceDetailsDeckConfiguration/index.tsx @@ -22,6 +22,7 @@ import { useUpdateDeckConfigurationMutation, } from '@opentrons/react-api-client' import { + getCutoutDisplayName, getFixtureDisplayName, STANDARD_SLOT_LOAD_NAME, } from '@opentrons/shared-data' @@ -70,6 +71,7 @@ export function DeviceDetailsDeckConfiguration({ } const handleClickRemove = (fixtureLocation: Cutout): void => { + console.log('remove fixtureLocation', fixtureLocation) updateDeckConfiguration({ fixtureLocation, loadName: STANDARD_SLOT_LOAD_NAME, @@ -187,7 +189,9 @@ export function DeviceDetailsDeckConfiguration({ width={SIZE_5} css={TYPOGRAPHY.labelRegular} > - {fixture.fixtureLocation} + + {getCutoutDisplayName(fixture.fixtureLocation)} + {getFixtureDisplayName(fixture.loadName)} diff --git a/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx b/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx index 27ca12cdd7c..bf059c06930 100644 --- a/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx +++ b/app/src/organisms/Devices/ProtocolRun/ProtocolRunSetup.tsx @@ -88,7 +88,7 @@ export function ProtocolRunSetup({ params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', @@ -101,7 +101,7 @@ export function ProtocolRunSetup({ params: { fixtureId: 'stubbedFixtureId_2', loadName: STAGING_AREA_LOAD_NAME, - location: { cutout: 'B3' }, + location: { cutout: 'cutoutB3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', @@ -114,7 +114,7 @@ export function ProtocolRunSetup({ params: { fixtureId: 'stubbedFixtureId_3', loadName: TRASH_BIN_LOAD_NAME, - location: { cutout: 'C3' }, + location: { cutout: 'cutoutC3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', diff --git a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx index d639664bdbb..3b718b29d52 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupLiquids/SetupLiquidsMap.tsx @@ -96,6 +96,12 @@ export function SetupLiquidsMap( const topLabwareDisplayName = labwareInAdapterInMod?.params.displayName ?? module.nestedLabwareDisplayName + const nestedLabwareWellFill = getWellFillFromLabwareId( + module.nestedLabwareId ?? '', + liquids, + labwareByLiquidId + ) + const labwareHasLiquid = !isEmpty(nestedLabwareWellFill) return { moduleModel: module.moduleDef.model, @@ -106,18 +112,28 @@ export function SetupLiquidsMap( : {}, nestedLabwareDef: topLabwareDefinition, - moduleChildren: ( - <> - {topLabwareDefinition != null && topLabwareId != null ? ( + nestedLabwareWellFill, + moduleChildren: + topLabwareDefinition != null && topLabwareId != null ? ( + setHoverLabwareId(topLabwareId)} + onMouseLeave={() => setHoverLabwareId('')} + onClick={() => + labwareHasLiquid ? setLiquidDetailsLabwareId(topLabwareId) : null + } + cursor={labwareHasLiquid ? 'pointer' : ''} + > - ) : null} - - ), + + ) : null, } }) diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/LocationConflictModal.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/LocationConflictModal.tsx index c2ac2721c19..c4960344fa3 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/LocationConflictModal.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/LocationConflictModal.tsx @@ -21,6 +21,7 @@ import { BORDERS, } from '@opentrons/components' import { + getCutoutDisplayName, getFixtureDisplayName, getModuleDisplayName, STANDARD_SLOT_LOAD_NAME, @@ -101,7 +102,7 @@ export const LocationConflictModal = ( i18nKey="deck_conflict_info" values={{ currentFixture: currentFixtureDisplayName, - cutout, + cutout: getCutoutDisplayName(cutout), }} components={{ block: , @@ -114,7 +115,7 @@ export const LocationConflictModal = ( fontWeight={TYPOGRAPHY.fontWeightBold} paddingBottom={SPACING.spacing8} > - {t('slot_location', { slotName: cutout })} + {t('slot_location', { slotName: getCutoutDisplayName(cutout) })} , @@ -210,7 +211,7 @@ export const LocationConflictModal = ( fontSize={TYPOGRAPHY.fontSizeH4} fontWeight={TYPOGRAPHY.fontWeightBold} > - {t('slot_location', { slotName: cutout })} + {t('slot_location', { slotName: getCutoutDisplayName(cutout) })} { beforeEach(() => { props = { onCloseClick: jest.fn(), - cutout: 'B3', + cutout: 'cutoutB3', requiredFixture: TRASH_BIN_LOAD_NAME, } mockUseDeckConfigurationQuery.mockReturnValue({ @@ -67,7 +67,7 @@ describe('LocationConflictModal', () => { it('should render the modal information for a module fixture conflict', () => { props = { onCloseClick: jest.fn(), - cutout: 'B3', + cutout: 'cutoutB3', requiredModule: 'heaterShakerModuleV1', } const { getByText, getByRole } = render(props) diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/NotConfiguredModal.test.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/NotConfiguredModal.test.tsx index d18bee369a8..6a000013101 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/NotConfiguredModal.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/NotConfiguredModal.test.tsx @@ -23,7 +23,7 @@ describe('NotConfiguredModal', () => { beforeEach(() => { props = { onCloseClick: jest.fn(), - cutout: 'B3', + cutout: 'cutoutB3', requiredFixture: TRASH_BIN_LOAD_NAME, } mockUseUpdateDeckConfigurationMutation.mockReturnValue({ diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupFixtureList.test.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupFixtureList.test.tsx index 8da24a61675..f35e647914b 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupFixtureList.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupFixtureList.test.tsx @@ -3,7 +3,7 @@ import { renderWithProviders } from '@opentrons/components' import { LoadFixtureRunTimeCommand, WASTE_CHUTE_LOAD_NAME, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { i18n } from '../../../../../i18n' import { useLoadedFixturesConfigStatus } from '../../../../../resources/deck_configuration/hooks' @@ -31,7 +31,7 @@ const mockLoadedFixture = { params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', @@ -74,7 +74,7 @@ describe('SetupFixtureList', () => { getByText('Status') getByText('Waste Chute') getByRole('button', { name: 'View setup instructions' }) - getByText(WASTE_CHUTE_SLOT) + getByText(WASTE_CHUTE_CUTOUT) getByText('Configured') }) it('should render the headers and a fixture with conflicted status', () => { diff --git a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupModulesAndDeck.test.tsx b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupModulesAndDeck.test.tsx index fa44f9b124c..4fd6e703904 100644 --- a/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupModulesAndDeck.test.tsx +++ b/app/src/organisms/Devices/ProtocolRun/SetupModuleAndDeck/__tests__/SetupModulesAndDeck.test.tsx @@ -24,7 +24,7 @@ const mockLoadedFixturesBySlot: LoadedFixturesBySlot = { params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', diff --git a/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getLabwareRenderInfo.test.ts b/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getLabwareRenderInfo.test.ts index f865b679b0c..359e4faad3f 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getLabwareRenderInfo.test.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getLabwareRenderInfo.test.ts @@ -1,5 +1,5 @@ import _protocolWithMagTempTC from '@opentrons/shared-data/protocol/fixtures/6/transferSettings.json' -import _standardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot2_standard.json' +import _standardDeckDef from '@opentrons/shared-data/deck/definitions/4/ot2_standard.json' import { getLabwareRenderInfo } from '../getLabwareRenderInfo' import type { CompletedProtocolAnalysis, diff --git a/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getProtocolModulesInfo.test.ts b/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getProtocolModulesInfo.test.ts index 7b7c2362eb0..f23a369d359 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getProtocolModulesInfo.test.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/__tests__/getProtocolModulesInfo.test.ts @@ -1,6 +1,6 @@ import _protocolWithMagTempTC from '@opentrons/shared-data/protocol/fixtures/6/transferSettings.json' import _protocolWithMultipleTemps from '@opentrons/shared-data/protocol/fixtures/6/multipleTempModules.json' -import _standardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot2_standard.json' +import _standardDeckDef from '@opentrons/shared-data/deck/definitions/4/ot2_standard.json' import { getProtocolModulesInfo } from '../getProtocolModulesInfo' import { getModuleDef2, diff --git a/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts b/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts index f5fcc0ea240..74bf968d144 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/getLabwareRenderInfo.ts @@ -1,4 +1,7 @@ -import { getSlotHasMatingSurfaceUnitVector } from '@opentrons/shared-data' +import { + getPositionFromSlotId, + getSlotHasMatingSurfaceUnitVector, +} from '@opentrons/shared-data' import type { CompletedProtocolAnalysis, DeckDefinition, @@ -7,32 +10,6 @@ import type { ProtocolAnalysisOutput, } from '@opentrons/shared-data' -const getSlotPosition = ( - deckDef: DeckDefinition, - slotName: string -): [number, number, number] => { - let x = 0 - let y = 0 - let z = 0 - const slotPosition = deckDef.locations.orderedSlots.find( - orderedSlot => orderedSlot.id === slotName - )?.position - - if (slotPosition == null) { - console.error( - `expected to find a slot position for slot ${slotName} in ${String( - deckDef.metadata.displayName - )}, but could not` - ) - } else { - x = slotPosition[0] - y = slotPosition[1] - z = slotPosition[2] - } - - return [x, y, z] -} - export interface LabwareRenderInfoById { [labwareId: string]: { x: number @@ -74,13 +51,19 @@ export const getLabwareRenderInfo = ( )} but could not` ) } - // TODO(bh, 2023-10-19): convert this to deck definition v4 addressableAreas + const slotName = 'addressableAreaName' in location ? location.addressableAreaName : location.slotName - // TODO(bh, 2023-10-19): remove slotPosition when render info no longer relies on directly - const slotPosition = getSlotPosition(deckDef, slotName) + const slotPosition = getPositionFromSlotId(slotName, deckDef) + + if (slotPosition == null) { + console.warn( + `expected to find a position for slot ${slotName} in the standard deck definition, but could not` + ) + return acc + } const slotHasMatingSurfaceVector = getSlotHasMatingSurfaceUnitVector( deckDef, @@ -99,5 +82,5 @@ export const getLabwareRenderInfo = ( slotName, }, } - : { ...acc } + : acc }, {}) diff --git a/app/src/organisms/Devices/ProtocolRun/utils/getProtocolModulesInfo.ts b/app/src/organisms/Devices/ProtocolRun/utils/getProtocolModulesInfo.ts index 0b0f3bc23b0..37a5ca93a26 100644 --- a/app/src/organisms/Devices/ProtocolRun/utils/getProtocolModulesInfo.ts +++ b/app/src/organisms/Devices/ProtocolRun/utils/getProtocolModulesInfo.ts @@ -2,6 +2,7 @@ import { SPAN7_8_10_11_SLOT, getModuleDef2, getLoadedLabwareDefinitionsByUri, + getPositionFromSlotId, } from '@opentrons/shared-data' import { getModuleInitialLoadInfo } from './getModuleInitialLoadInfo' import type { @@ -68,13 +69,14 @@ export const getProtocolModulesInfo = ( if (slotName === SPAN7_8_10_11_SLOT) { slotName = '7' } - const slotPosition = - deckDef.locations.orderedSlots.find(slot => slot.id === slotName) - ?.position ?? [] - if (slotPosition.length === 0) { + + const slotPosition = getPositionFromSlotId(slotName, deckDef) + + if (slotPosition == null) { console.warn( - `expected to find a slot position for slot ${slotName} in the standard OT-2 deck definition, but could not` + `expected to find a position for slot ${slotName} in the standard deck definition, but could not` ) + return acc } return [ ...acc, diff --git a/app/src/organisms/Devices/hooks/__tests__/useLabwareRenderInfoForRunById.test.tsx b/app/src/organisms/Devices/hooks/__tests__/useLabwareRenderInfoForRunById.test.tsx index 2f596a43c23..fa6e2ed8996 100644 --- a/app/src/organisms/Devices/hooks/__tests__/useLabwareRenderInfoForRunById.test.tsx +++ b/app/src/organisms/Devices/hooks/__tests__/useLabwareRenderInfoForRunById.test.tsx @@ -1,7 +1,7 @@ import { renderHook } from '@testing-library/react-hooks' import { when, resetAllWhenMocks } from 'jest-when' -import standardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot2_standard.json' +import standardDeckDef from '@opentrons/shared-data/deck/definitions/4/ot2_standard.json' import _heaterShakerCommandsWithResultsKey from '@opentrons/shared-data/protocol/fixtures/6/heaterShakerCommandsWithResultsKey.json' import { useMostRecentCompletedAnalysis } from '../../../LabwarePositionCheck/useMostRecentCompletedAnalysis' diff --git a/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx b/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx index 4946e81aa7d..17d70702dad 100644 --- a/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx +++ b/app/src/organisms/Devices/hooks/__tests__/useModuleRenderInfoForProtocolById.test.tsx @@ -134,7 +134,7 @@ const TEMPERATURE_MODULE_INFO = { const mockFixture = { fixtureId: 'mockId', - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STAGING_AREA_LOAD_NAME, } as Fixture @@ -187,12 +187,15 @@ describe('useModuleRenderInfoForProtocolById hook', () => { ) expect(result.current).toStrictEqual({ magneticModuleId: { - conflictedFixture: mockFixture, + // TODO(bh, 2023-11-09): update this test once conflict logic has been updated to use getSimplestDeckConfigForProtocolCommands or similar + // conflictedFixture: mockFixture, + conflictedFixture: undefined, attachedModuleMatch: mockMagneticModuleGen2, ...MAGNETIC_MODULE_INFO, }, temperatureModuleId: { - conflictedFixture: mockFixture, + // conflictedFixture: mockFixture, + conflictedFixture: undefined, attachedModuleMatch: mockTemperatureModuleGen2, ...TEMPERATURE_MODULE_INFO, }, diff --git a/app/src/organisms/DropTipWizard/ChooseLocation.tsx b/app/src/organisms/DropTipWizard/ChooseLocation.tsx index deaedcc7b0a..72bdf5c1d85 100644 --- a/app/src/organisms/DropTipWizard/ChooseLocation.tsx +++ b/app/src/organisms/DropTipWizard/ChooseLocation.tsx @@ -1,6 +1,7 @@ import * as React from 'react' import { css } from 'styled-components' import { useTranslation } from 'react-i18next' + import { Flex, DIRECTION_COLUMN, @@ -14,13 +15,19 @@ import { SPACING, TYPOGRAPHY, } from '@opentrons/components' +import { + getDeckDefFromRobotType, + getPositionFromSlotId, +} from '@opentrons/shared-data' + +import { SmallButton } from '../../atoms/buttons' import { StyledText } from '../../atoms/text' +import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal' // import { NeedHelpLink } from '../CalibrationPanels' import { TwoUpTileLayout } from '../LabwarePositionCheck/TwoUpTileLayout' -import { InProgressModal } from '../../molecules/InProgressModal/InProgressModal' -import { RobotType, getDeckDefFromRobotType } from '@opentrons/shared-data' + import type { CommandData } from '@opentrons/api-client' -import { SmallButton } from '../../atoms/buttons' +import type { RobotType } from '@opentrons/shared-data' // TODO: get help link article URL // const NEED_HELP_URL = '' @@ -56,13 +63,19 @@ export const ChooseLocation = ( ) const handleConfirmPosition: React.MouseEventHandler = () => { - const deckLocation = deckDef.locations.orderedSlots.find( + const deckSlot = deckDef.locations.addressableAreas.find( l => l.id === selectedLocation.slotName ) - const slotX = deckLocation?.position[0] - const slotY = deckLocation?.position[1] - const xDimension = deckLocation?.boundingBox.xDimension - const yDimension = deckLocation?.boundingBox.yDimension + + const slotPosition = getPositionFromSlotId( + selectedLocation.slotName, + deckDef + ) + + const slotX = slotPosition?.[0] + const slotY = slotPosition?.[1] + const xDimension = deckSlot?.boundingBox.xDimension + const yDimension = deckSlot?.boundingBox.yDimension if ( slotX != null && slotY != null && diff --git a/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx b/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx index aab4b2b359d..19659b7a537 100644 --- a/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx +++ b/app/src/organisms/InterventionModal/MoveLabwareInterventionContent.tsx @@ -196,8 +196,10 @@ export function MoveLabwareInterventionContent({ movedLabwareDef={movedLabwareDef} loadedModules={run.modules} loadedLabware={run.labware} - // TODO(bh, 2023-07-19): read trash slot name from protocol - trashLocation={robotType === 'OT-3 Standard' ? 'A3' : undefined} + // TODO(bh, 2023-07-19): remove when StyledDeck removed from MoveLabwareOnDeck + trashLocation={ + robotType === 'OT-3 Standard' ? 'cutoutA3' : undefined + } backgroundItems={ <> {moduleRenderInfo.map( diff --git a/app/src/organisms/InterventionModal/__tests__/utils.test.ts b/app/src/organisms/InterventionModal/__tests__/utils.test.ts index 8aa5b57b6bb..2e27af4bbac 100644 --- a/app/src/organisms/InterventionModal/__tests__/utils.test.ts +++ b/app/src/organisms/InterventionModal/__tests__/utils.test.ts @@ -1,7 +1,7 @@ import deepClone from 'lodash/cloneDeep' import { getSlotHasMatingSurfaceUnitVector } from '@opentrons/shared-data' -import deckDefFixture from '@opentrons/shared-data/deck/fixtures/3/deckExample.json' +import standardDeckDef from '@opentrons/shared-data/deck/definitions/4/ot2_standard.json' import { mockLabwareDefinition, @@ -141,7 +141,7 @@ describe('getRunLabwareRenderInfo', () => { const res = getRunLabwareRenderInfo( mockRunData, mockLabwareDefinitionsByUri, - deckDefFixture as any + standardDeckDef as any ) const labwareInfo = res[0] expect(labwareInfo).toBeTruthy() @@ -158,7 +158,7 @@ describe('getRunLabwareRenderInfo', () => { const res = getRunLabwareRenderInfo( mockRunData, mockLabwareDefinitionsByUri, - deckDefFixture as any + standardDeckDef as any ) expect(res).toHaveLength(1) // the offdeck labware still gets added because the mating surface doesn't exist for offdeck labware }) @@ -167,7 +167,7 @@ describe('getRunLabwareRenderInfo', () => { const res = getRunLabwareRenderInfo( mockRunData, mockLabwareDefinitionsByUri, - deckDefFixture as any + standardDeckDef as any ) expect(res).toHaveLength(2) const labwareInfo = res.find( @@ -176,7 +176,7 @@ describe('getRunLabwareRenderInfo', () => { expect(labwareInfo).toBeTruthy() expect(labwareInfo?.x).toEqual(0) expect(labwareInfo?.y).toEqual( - deckDefFixture.cornerOffsetFromOrigin[1] - + standardDeckDef.cornerOffsetFromOrigin[1] - mockLabwareDefinition.dimensions.yDimension ) }) @@ -193,7 +193,7 @@ describe('getRunLabwareRenderInfo', () => { const res = getRunLabwareRenderInfo( { labware: [mockBadSlotLabware] } as any, mockLabwareDefinitionsByUri, - deckDefFixture as any + standardDeckDef as any ) expect(res[0].x).toEqual(0) @@ -211,7 +211,7 @@ describe('getCurrentRunModuleRenderInfo', () => { it('returns run module render info with nested labware', () => { const res = getRunModuleRenderInfo( mockRunData, - deckDefFixture as any, + standardDeckDef as any, mockLabwareDefinitionsByUri ) const moduleInfo = res[0] @@ -232,7 +232,7 @@ describe('getCurrentRunModuleRenderInfo', () => { const res = getRunModuleRenderInfo( mockRunDataNoNesting, - deckDefFixture as any, + standardDeckDef as any, mockLabwareDefinitionsByUri ) @@ -249,7 +249,7 @@ describe('getCurrentRunModuleRenderInfo', () => { const res = getRunModuleRenderInfo( mockRunDataWithTC, - deckDefFixture as any, + standardDeckDef as any, mockLabwareDefinitionsByUri ) @@ -274,7 +274,7 @@ describe('getCurrentRunModuleRenderInfo', () => { const res = getRunModuleRenderInfo( mockRunDataWithBadModuleSlot, - deckDefFixture as any, + standardDeckDef as any, mockLabwareDefinitionsByUri ) diff --git a/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts b/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts index 3590d470522..1634e12cc2b 100644 --- a/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts +++ b/app/src/organisms/InterventionModal/utils/getRunLabwareRenderInfo.ts @@ -1,4 +1,7 @@ -import { getSlotHasMatingSurfaceUnitVector } from '@opentrons/shared-data' +import { + getPositionFromSlotId, + getSlotHasMatingSurfaceUnitVector, +} from '@opentrons/shared-data' import type { RunData } from '@opentrons/api-client' import type { @@ -40,19 +43,18 @@ export function getRunLabwareRenderInfo( 'addressableAreaName' in location ? location.addressableAreaName : location.slotName - const slotPosition = - deckDef.locations.orderedSlots.find(slot => slot.id === slotName) - ?.position ?? [] + const slotPosition = getPositionFromSlotId(slotName, deckDef) const slotHasMatingSurfaceVector = getSlotHasMatingSurfaceUnitVector( deckDef, slotName ) + return slotHasMatingSurfaceVector ? [ ...acc, { - x: slotPosition[0] ?? 0, - y: slotPosition[1] ?? 0, + x: slotPosition?.[0] ?? 0, + y: slotPosition?.[1] ?? 0, labwareId: labware.id, labwareDef, }, diff --git a/app/src/organisms/InterventionModal/utils/getRunModuleRenderInfo.ts b/app/src/organisms/InterventionModal/utils/getRunModuleRenderInfo.ts index 0413f60db7e..46c8a04869e 100644 --- a/app/src/organisms/InterventionModal/utils/getRunModuleRenderInfo.ts +++ b/app/src/organisms/InterventionModal/utils/getRunModuleRenderInfo.ts @@ -1,4 +1,8 @@ -import { SPAN7_8_10_11_SLOT, getModuleDef2 } from '@opentrons/shared-data' +import { + SPAN7_8_10_11_SLOT, + getModuleDef2, + getPositionFromSlotId, +} from '@opentrons/shared-data' import type { RunData } from '@opentrons/api-client' import type { @@ -37,16 +41,14 @@ export function getRunModuleRenderInfo( if (slotName === SPAN7_8_10_11_SLOT) { slotName = '7' } - const slotPosition = - deckDef.locations.orderedSlots.find(slot => slot.id === slotName) - ?.position ?? [] + const slotPosition = getPositionFromSlotId(slotName, deckDef) return [ ...acc, { moduleId: module.id, - x: slotPosition[0] ?? 0, - y: slotPosition[1] ?? 0, + x: slotPosition?.[0] ?? 0, + y: slotPosition?.[1] ?? 0, moduleDef, nestedLabwareDef, nestedLabwareId: nestedLabware?.id ?? null, diff --git a/app/src/organisms/ModuleWizardFlows/SelectLocation.tsx b/app/src/organisms/ModuleWizardFlows/SelectLocation.tsx index eb78f2b63aa..107813567e2 100644 --- a/app/src/organisms/ModuleWizardFlows/SelectLocation.tsx +++ b/app/src/organisms/ModuleWizardFlows/SelectLocation.tsx @@ -66,7 +66,7 @@ export const SelectLocation = ( deckDef={deckDef} selectedLocation={{ slotName }} setSelectedLocation={loc => setSlotName(loc.slotName)} - disabledLocations={deckDef.locations.orderedSlots.reduce< + disabledLocations={deckDef.locations.addressableAreas.reduce< ModuleLocation[] >((acc, slot) => { if (availableSlotNames.some(slotName => slotName === slot.id)) diff --git a/app/src/organisms/ProtocolDetails/index.tsx b/app/src/organisms/ProtocolDetails/index.tsx index da13f2147e0..9b017166cb9 100644 --- a/app/src/organisms/ProtocolDetails/index.tsx +++ b/app/src/organisms/ProtocolDetails/index.tsx @@ -244,7 +244,7 @@ export function ProtocolDetails( params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx index 3b9b63a492f..d453c00ded7 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/__tests__/ProtocolSetupDeckConfiguration.test.tsx @@ -51,7 +51,7 @@ describe('ProtocolSetupDeckConfiguration', () => { beforeEach(() => { props = { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', runId: 'mockRunId', setSetupScreen: mockSetSetupScreen, providedFixtureOptions: [], diff --git a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx index 8646070aa09..bb5638ac06a 100644 --- a/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx +++ b/app/src/organisms/ProtocolSetupDeckConfiguration/index.tsx @@ -57,7 +57,7 @@ export function ProtocolSetupDeckConfiguration({ params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', diff --git a/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx b/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx index 9a9c2a9999e..29d134884b9 100644 --- a/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx +++ b/app/src/organisms/ProtocolSetupLabware/__tests__/ProtocolSetupLabware.test.tsx @@ -7,7 +7,7 @@ import { useModulesQuery, } from '@opentrons/react-api-client' import { renderWithProviders } from '@opentrons/components' -import ot3StandardDeckDef from '@opentrons/shared-data/deck/definitions/3/ot3_standard.json' +import ot3StandardDeckDef from '@opentrons/shared-data/deck/definitions/4/ot3_standard.json' import { i18n } from '../../../i18n' import { useMostRecentCompletedAnalysis } from '../../../organisms/LabwarePositionCheck/useMostRecentCompletedAnalysis' diff --git a/app/src/organisms/ProtocolSetupModulesAndDeck/FixtureTable.tsx b/app/src/organisms/ProtocolSetupModulesAndDeck/FixtureTable.tsx index 7f5c0ba2542..ef77aae7f2a 100644 --- a/app/src/organisms/ProtocolSetupModulesAndDeck/FixtureTable.tsx +++ b/app/src/organisms/ProtocolSetupModulesAndDeck/FixtureTable.tsx @@ -14,6 +14,7 @@ import { TYPOGRAPHY, } from '@opentrons/components' import { + getCutoutDisplayName, getFixtureDisplayName, WASTE_CHUTE_LOAD_NAME, } from '@opentrons/shared-data' @@ -56,7 +57,7 @@ export function FixtureTable({ params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', @@ -176,7 +177,11 @@ export function FixtureTable({ - + { } const [{ getByText }] = render(props) getByText('Not configured').click() - expect(mockSetFixtureLocation).toHaveBeenCalledWith('D3') + expect(mockSetFixtureLocation).toHaveBeenCalledWith('cutoutD3') expect(mockSetSetupScreen).toHaveBeenCalledWith('deck configuration') expect(mockSetProvidedFixtureOptions).toHaveBeenCalledWith(['wasteChute']) }) diff --git a/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx b/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx index ebaccbd62a4..d9e7123ab68 100644 --- a/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx +++ b/app/src/pages/DeckConfiguration/__tests__/DeckConfiguration.test.tsx @@ -30,7 +30,7 @@ jest.mock('react-router-dom', () => { const mockDeckConfig = [ { fixtureId: 'mockFixtureIdC3', - fixtureLocation: 'C3', + fixtureLocation: 'cutoutC3', loadName: TRASH_BIN_LOAD_NAME, }, ] diff --git a/app/src/pages/OnDeviceDisplay/ProtocolDetails/Hardware.tsx b/app/src/pages/OnDeviceDisplay/ProtocolDetails/Hardware.tsx index 5ec14ce19ff..44a64485d22 100644 --- a/app/src/pages/OnDeviceDisplay/ProtocolDetails/Hardware.tsx +++ b/app/src/pages/OnDeviceDisplay/ProtocolDetails/Hardware.tsx @@ -14,6 +14,7 @@ import { } from '@opentrons/components' import { GRIPPER_V1, + getCutoutDisplayName, getGripperDisplayName, getModuleDisplayName, getModuleType, @@ -130,7 +131,11 @@ export const Hardware = (props: { protocolId: string }): JSX.Element => { if (hardware.hardwareType === 'module') { location = } else if (hardware.hardwareType === 'fixture') { - location = + location = ( + + ) } return ( diff --git a/app/src/pages/OnDeviceDisplay/ProtocolDetails/__tests__/Hardware.test.tsx b/app/src/pages/OnDeviceDisplay/ProtocolDetails/__tests__/Hardware.test.tsx index 7c538f79bc5..c2f3fab61c5 100644 --- a/app/src/pages/OnDeviceDisplay/ProtocolDetails/__tests__/Hardware.test.tsx +++ b/app/src/pages/OnDeviceDisplay/ProtocolDetails/__tests__/Hardware.test.tsx @@ -3,7 +3,7 @@ import { when, resetAllWhenMocks } from 'jest-when' import { STAGING_AREA_LOAD_NAME, WASTE_CHUTE_LOAD_NAME, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { renderWithProviders } from '@opentrons/components' import { i18n } from '../../../../i18n' @@ -63,13 +63,13 @@ describe('Hardware', () => { { hardwareType: 'fixture', fixtureName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: WASTE_CHUTE_SLOT }, + location: { cutout: WASTE_CHUTE_CUTOUT }, hasSlotConflict: false, }, { hardwareType: 'fixture', fixtureName: STAGING_AREA_LOAD_NAME, - location: { cutout: 'B3' }, + location: { cutout: 'cutoutB3' }, hasSlotConflict: false, }, ], diff --git a/app/src/pages/OnDeviceDisplay/ProtocolSetup/__tests__/ProtocolSetup.test.tsx b/app/src/pages/OnDeviceDisplay/ProtocolSetup/__tests__/ProtocolSetup.test.tsx index 16719381826..32358722ecc 100644 --- a/app/src/pages/OnDeviceDisplay/ProtocolSetup/__tests__/ProtocolSetup.test.tsx +++ b/app/src/pages/OnDeviceDisplay/ProtocolSetup/__tests__/ProtocolSetup.test.tsx @@ -231,7 +231,7 @@ const mockDoorStatus = { } const mockFixture = { fixtureId: 'mockId', - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STAGING_AREA_LOAD_NAME, } as Fixture diff --git a/app/src/pages/Protocols/hooks/index.ts b/app/src/pages/Protocols/hooks/index.ts index c5232d29f24..625f9831bc5 100644 --- a/app/src/pages/Protocols/hooks/index.ts +++ b/app/src/pages/Protocols/hooks/index.ts @@ -146,19 +146,19 @@ export const useRequiredProtocolHardwareFromAnalysis = ( { hardwareType: 'fixture', fixtureName: 'wasteChute', - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, hasSlotConflict: false, }, { hardwareType: 'fixture', fixtureName: 'standardSlot', - location: { cutout: 'C3' }, + location: { cutout: 'cutoutC3' }, hasSlotConflict: false, }, { hardwareType: 'fixture', fixtureName: 'stagingArea', - location: { cutout: 'B3' }, + location: { cutout: 'cutoutB3' }, hasSlotConflict: false, }, ] diff --git a/app/src/resources/deck_configuration/__tests__/hooks.test.ts b/app/src/resources/deck_configuration/__tests__/hooks.test.ts index e4818eb31d0..2ee9eb57add 100644 --- a/app/src/resources/deck_configuration/__tests__/hooks.test.ts +++ b/app/src/resources/deck_configuration/__tests__/hooks.test.ts @@ -30,42 +30,42 @@ const mockUseDeckConfigurationQuery = useDeckConfigurationQuery as jest.MockedFu const MOCK_DECK_CONFIG: DeckConfiguration = [ { - fixtureLocation: 'A1', + fixtureLocation: 'cutoutA1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B1', + fixtureLocation: 'cutoutB1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C1', + fixtureLocation: 'cutoutC1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A3', + fixtureLocation: 'cutoutA3', loadName: TRASH_BIN_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B3', + fixtureLocation: 'cutoutB3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C3', + fixtureLocation: 'cutoutC3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', loadName: WASTE_CHUTE_LOAD_NAME, fixtureId: uuidv4(), }, @@ -77,7 +77,7 @@ const WASTE_CHUTE_LOADED_FIXTURE: LoadFixtureRunTimeCommand = { params: { fixtureId: 'stubbedFixtureId', loadName: WASTE_CHUTE_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', @@ -91,7 +91,7 @@ const STAGING_AREA_LOADED_FIXTURE: LoadFixtureRunTimeCommand = { params: { fixtureId: 'stubbedFixtureId', loadName: STAGING_AREA_LOAD_NAME, - location: { cutout: 'D3' }, + location: { cutout: 'cutoutD3' }, }, createdAt: 'fakeTimestamp', startedAt: 'fakeTimestamp', diff --git a/app/src/resources/deck_configuration/utils.ts b/app/src/resources/deck_configuration/utils.ts index fdc59aa539b..36150586b09 100644 --- a/app/src/resources/deck_configuration/utils.ts +++ b/app/src/resources/deck_configuration/utils.ts @@ -175,7 +175,7 @@ export function getDeckConfigFromProtocolCommands( ) } -function getCutoutFixturesForAddressableAreas( +export function getCutoutFixturesForAddressableAreas( addressableAreas: AddressableAreaName[], cutoutFixtures: CutoutFixture[] ): CutoutFixture[] { @@ -186,7 +186,7 @@ function getCutoutFixturesForAddressableAreas( ) } -function getCutoutFixturesForCutoutId( +export function getCutoutFixturesForCutoutId( cutoutId: CutoutId, cutoutFixtures: CutoutFixture[] ): CutoutFixture[] { @@ -195,7 +195,7 @@ function getCutoutFixturesForCutoutId( ) } -function getCutoutIdForAddressableArea( +export function getCutoutIdForAddressableArea( addressableArea: AddressableAreaName, cutoutFixtures: CutoutFixture[] ): CutoutId | null { @@ -210,7 +210,7 @@ function getCutoutIdForAddressableArea( }, null) } -function getSimplestFixtureForAddressableAreas( +export function getSimplestFixtureForAddressableAreas( cutoutId: CutoutId, requiredAddressableAreas: AddressableAreaName[], allCutoutFixtures: CutoutFixture[] diff --git a/components/src/hardware-sim/BaseDeck/BaseDeck.tsx b/components/src/hardware-sim/BaseDeck/BaseDeck.tsx index 1fe12ccdb91..28d66051393 100644 --- a/components/src/hardware-sim/BaseDeck/BaseDeck.tsx +++ b/components/src/hardware-sim/BaseDeck/BaseDeck.tsx @@ -1,25 +1,23 @@ import * as React from 'react' import { - RobotType, getDeckDefFromRobotType, - ModuleModel, - ModuleLocation, getModuleDef2, - LabwareDefinition2, + getPositionFromSlotId, inferModuleOrientationFromXCoordinate, - LabwareLocation, OT2_ROBOT_TYPE, - STAGING_AREA_LOAD_NAME, - STANDARD_SLOT_LOAD_NAME, - TRASH_BIN_LOAD_NAME, - WASTE_CHUTE_LOAD_NAME, + SINGLE_SLOT_FIXTURES, + STAGING_AREA_RIGHT_SLOT_FIXTURE, + TRASH_BIN_ADAPTER_FIXTURE, + WASTE_CHUTE_CUTOUT, + WASTE_CHUTE_FIXTURES, } from '@opentrons/shared-data' + import { RobotCoordinateSpace } from '../RobotCoordinateSpace' import { Module } from '../Module' import { LabwareRender } from '../Labware' import { FlexTrash } from '../Deck/FlexTrash' -import { DeckFromData } from '../Deck/DeckFromData' +import { DeckFromLayers } from '../Deck/DeckFromLayers' import { SlotLabels } from '../Deck' import { COLORS } from '../../ui-style-constants' @@ -32,10 +30,18 @@ import { StagingAreaFixture } from './StagingAreaFixture' import { WasteChuteFixture } from './WasteChuteFixture' // import { WasteChuteStagingAreaFixture } from './WasteChuteStagingAreaFixture' -import type { DeckConfiguration } from '@opentrons/shared-data' +import type { + DeckConfiguration, + LabwareDefinition2, + LabwareLocation, + ModuleLocation, + ModuleModel, + RobotType, + SingleSlotCutoutFixtureId, + WasteChuteCutoutFixtureId, +} from '@opentrons/shared-data' import type { TrashLocation } from '../Deck/FlexTrash' import type { StagingAreaLocation } from './StagingAreaFixture' -import type { WasteChuteLocation } from './WasteChuteFixture' import type { WellFill } from '../Labware' interface BaseDeckProps { @@ -80,21 +86,26 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element { deckConfig = STANDARD_SLOT_DECK_CONFIG_FIXTURE, showExpansion = true, children, - showSlotLabels = false, + showSlotLabels = true, } = props const deckDef = getDeckDefFromRobotType(robotType) - const singleSlotFixtures = deckConfig.filter( - fixture => fixture.loadName === STANDARD_SLOT_LOAD_NAME + const singleSlotFixtures = deckConfig.filter(fixture => + SINGLE_SLOT_FIXTURES.includes( + fixture.fixtureId as SingleSlotCutoutFixtureId + ) ) const stagingAreaFixtures = deckConfig.filter( - fixture => fixture.loadName === STAGING_AREA_LOAD_NAME + fixture => fixture.fixtureId === STAGING_AREA_RIGHT_SLOT_FIXTURE ) const trashBinFixtures = deckConfig.filter( - fixture => fixture.loadName === TRASH_BIN_LOAD_NAME + fixture => fixture.fixtureId === TRASH_BIN_ADAPTER_FIXTURE ) const wasteChuteFixtures = deckConfig.filter( - fixture => fixture.loadName === WASTE_CHUTE_LOAD_NAME + fixture => + WASTE_CHUTE_FIXTURES.includes( + fixture.fixtureId as WasteChuteCutoutFixtureId + ) && fixture.fixtureLocation === WASTE_CHUTE_CUTOUT ) return ( @@ -102,13 +113,16 @@ export function BaseDeck(props: BaseDeckProps): JSX.Element { viewBox={`${deckDef.cornerOffsetFromOrigin[0]} ${deckDef.cornerOffsetFromOrigin[1]} ${deckDef.dimensions[0]} ${deckDef.dimensions[1]}`} > {robotType === OT2_ROBOT_TYPE ? ( - + ) : ( <> {singleSlotFixtures.map(fixture => ( ( ))} {trashBinFixtures.map(fixture => ( - + ( )} - {moduleLocations.map( - ({ - moduleModel, - moduleLocation, - nestedLabwareDef, - nestedLabwareWellFill, - innerProps, - moduleChildren, - onLabwareClick, - }) => { - const slotDef = deckDef.locations.orderedSlots.find( - s => s.id === moduleLocation.slotName - ) - const moduleDef = getModuleDef2(moduleModel) - return slotDef != null ? ( - - {nestedLabwareDef != null ? ( + <> + {moduleLocations.map( + ({ + moduleModel, + moduleLocation, + nestedLabwareDef, + nestedLabwareWellFill, + innerProps, + moduleChildren, + onLabwareClick, + }) => { + const slotPosition = getPositionFromSlotId( + moduleLocation.slotName, + deckDef + ) + + const moduleDef = getModuleDef2(moduleModel) + return slotPosition != null ? ( + + {nestedLabwareDef != null ? ( + + ) : null} + {moduleChildren} + + ) : null + } + )} + {labwareLocations.map( + ({ + labwareLocation, + definition, + labwareChildren, + wellFill, + onLabwareClick, + }) => { + if ( + labwareLocation === 'offDeck' || + !('slotName' in labwareLocation) + ) { + return null + } + + const slotPosition = getPositionFromSlotId( + labwareLocation.slotName, + deckDef + ) + + return slotPosition != null ? ( + - ) : null} - {moduleChildren} - - ) : null - } - )} - {labwareLocations.map( - ({ - labwareLocation, - definition, - labwareChildren, - wellFill, - onLabwareClick, - }) => { - const slotDef = deckDef.locations.orderedSlots.find( - s => - labwareLocation !== 'offDeck' && - 'slotName' in labwareLocation && - s.id === labwareLocation.slotName - ) - return slotDef != null ? ( - - - {labwareChildren} - - ) : null - } - )} - {showSlotLabels ? ( - - ) : null} + {labwareChildren} + + ) : null + } + )} + {showSlotLabels ? ( + + ) : null} + {children} ) diff --git a/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx b/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx index 7e763a0fb7f..0fe3ff526e6 100644 --- a/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx +++ b/components/src/hardware-sim/BaseDeck/SingleSlotFixture.tsx @@ -3,10 +3,14 @@ import * as React from 'react' import { SlotBase } from './SlotBase' import { SlotClip } from './SlotClip' -import type { Cutout, DeckDefinition, ModuleType } from '@opentrons/shared-data' +import type { + CutoutId, + DeckDefinition, + ModuleType, +} from '@opentrons/shared-data' interface SingleSlotFixtureProps extends React.SVGProps { - cutoutLocation: Cutout + cutoutId: CutoutId deckDefinition: DeckDefinition moduleType?: ModuleType fixtureBaseColor?: React.SVGProps['fill'] @@ -18,7 +22,7 @@ export function SingleSlotFixture( props: SingleSlotFixtureProps ): JSX.Element | null { const { - cutoutLocation, + cutoutId, deckDefinition, fixtureBaseColor, slotClipColor, @@ -26,9 +30,8 @@ export function SingleSlotFixture( ...restProps } = props - // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key - const cutoutDef = deckDefinition?.locations.orderedSlots.find( - s => s.id === cutoutLocation + const cutoutDef = deckDefinition?.locations.cutouts.find( + s => s.id === cutoutId ) if (cutoutDef == null) { console.warn( @@ -38,9 +41,9 @@ export function SingleSlotFixture( } const contentsByCutoutLocation: { - [cutoutLocation in Cutout]: JSX.Element + [cutoutId in CutoutId]: JSX.Element } = { - A1: ( + cutoutA1: ( <> {showExpansion ? ( ), - A2: ( + cutoutA2: ( <> ), - A3: ( + cutoutA3: ( <> ), - B1: ( + cutoutB1: ( <> ), - B2: ( + cutoutB2: ( <> ), - B3: ( + cutoutB3: ( <> ), - C1: ( + cutoutC1: ( <> ), - C2: ( + cutoutC2: ( <> ), - C3: ( + cutoutC3: ( <> ), - D1: ( + cutoutD1: ( <> ), - D2: ( + cutoutD2: ( <> ), - D3: ( + cutoutD3: ( <> {contentsByCutoutLocation[cutoutLocation]} + return {contentsByCutoutLocation[cutoutId]} } diff --git a/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx b/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx index 2b3d8491da6..3e87517110a 100644 --- a/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx +++ b/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx @@ -8,7 +8,7 @@ import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' export type StagingAreaLocation = 'A3' | 'B3' | 'C3' | 'D3' interface StagingAreaFixtureProps extends React.SVGProps { - cutoutLocation: StagingAreaLocation + cutoutId: StagingAreaLocation deckDefinition: DeckDefinition moduleType?: ModuleType fixtureBaseColor?: React.SVGProps['fill'] @@ -20,16 +20,15 @@ export function StagingAreaFixture( props: StagingAreaFixtureProps ): JSX.Element | null { const { - cutoutLocation, + cutoutId, deckDefinition, fixtureBaseColor, slotClipColor, ...restProps } = props - // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key - const cutoutDef = deckDefinition?.locations.orderedSlots.find( - s => s.id === cutoutLocation + const cutoutDef = deckDefinition?.locations.cutouts.find( + s => s.id === cutoutId ) if (cutoutDef == null) { console.warn( @@ -38,9 +37,8 @@ export function StagingAreaFixture( return null } - // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition const contentsByCutoutLocation: { - [cutoutLocation in StagingAreaLocation]: JSX.Element + [cutoutId in StagingAreaLocation]: JSX.Element } = { A3: ( <> @@ -108,5 +106,5 @@ export function StagingAreaFixture( ), } - return {contentsByCutoutLocation[cutoutLocation]} + return {contentsByCutoutLocation[cutoutId]} } diff --git a/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx b/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx index a4ac6673bf5..0ef8b60d848 100644 --- a/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx +++ b/components/src/hardware-sim/BaseDeck/WasteChuteFixture.tsx @@ -1,5 +1,7 @@ import * as React from 'react' +import { WASTE_CHUTE_CUTOUT } from '@opentrons/shared-data' + import { Icon } from '../../icons' import { Flex, Text } from '../../primitives' import { ALIGN_CENTER, DIRECTION_COLUMN, JUSTIFY_CENTER } from '../../styles' @@ -9,11 +11,8 @@ import { SlotBase } from './SlotBase' import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' -// waste chute only in cutout location D3 -export type WasteChuteLocation = 'D3' - interface WasteChuteFixtureProps extends React.SVGProps { - cutoutLocation: WasteChuteLocation + cutoutId: typeof WASTE_CHUTE_CUTOUT deckDefinition: DeckDefinition moduleType?: ModuleType fixtureBaseColor?: React.SVGProps['fill'] @@ -25,23 +24,22 @@ export function WasteChuteFixture( props: WasteChuteFixtureProps ): JSX.Element | null { const { - cutoutLocation, + cutoutId, deckDefinition, fixtureBaseColor = COLORS.light1, slotClipColor = COLORS.darkGreyEnabled, ...restProps } = props - if (cutoutLocation !== 'D3') { + if (cutoutId !== 'cutoutD3') { console.warn( - `cannot render WasteChuteFixture in given cutout location ${cutoutLocation}` + `cannot render WasteChuteFixture in given cutout location ${cutoutId}` ) return null } - // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key - const cutoutDef = deckDefinition?.locations.orderedSlots.find( - s => s.id === cutoutLocation + const cutoutDef = deckDefinition?.locations.cutouts.find( + s => s.id === cutoutId ) if (cutoutDef == null) { console.warn( @@ -50,7 +48,6 @@ export function WasteChuteFixture( return null } - // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition return ( { - cutoutLocation: WasteChuteLocation + cutoutId: typeof WASTE_CHUTE_CUTOUT deckDefinition: DeckDefinition moduleType?: ModuleType fixtureBaseColor?: React.SVGProps['fill'] @@ -22,23 +23,22 @@ export function WasteChuteStagingAreaFixture( props: WasteChuteStagingAreaFixtureProps ): JSX.Element | null { const { - cutoutLocation, + cutoutId, deckDefinition, fixtureBaseColor = COLORS.light1, slotClipColor = COLORS.darkGreyEnabled, ...restProps } = props - if (cutoutLocation !== 'D3') { + if (cutoutId !== WASTE_CHUTE_CUTOUT) { console.warn( - `cannot render WasteChuteStagingAreaFixture in given cutout location ${cutoutLocation}` + `cannot render WasteChuteStagingAreaFixture in given cutout location ${cutoutId}` ) return null } - // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key - const cutoutDef = deckDefinition?.locations.orderedSlots.find( - s => s.id === cutoutLocation + const cutoutDef = deckDefinition?.locations.cutouts.find( + s => s.id === cutoutId ) if (cutoutDef == null) { console.warn( @@ -47,7 +47,6 @@ export function WasteChuteStagingAreaFixture( return null } - // TODO(bh, 2023-10-10): adjust base and clip d values if needed to fit v4 deck definition return ( // TODO: render a "Waste chute" foreign object similar to FlexTrash diff --git a/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts b/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts index e643be8aad2..a994039df34 100644 --- a/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts +++ b/components/src/hardware-sim/BaseDeck/__fixtures__/index.ts @@ -11,62 +11,62 @@ import type { DeckConfiguration } from '@opentrons/shared-data' export const STANDARD_SLOT_DECK_CONFIG_FIXTURE: DeckConfiguration = [ { - fixtureLocation: 'A1', + fixtureLocation: 'cutoutA1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B1', + fixtureLocation: 'cutoutB1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C1', + fixtureLocation: 'cutoutC1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A2', + fixtureLocation: 'cutoutA2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B2', + fixtureLocation: 'cutoutB2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C2', + fixtureLocation: 'cutoutC2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D2', + fixtureLocation: 'cutoutD2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A3', + fixtureLocation: 'cutoutA3', loadName: TRASH_BIN_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B3', + fixtureLocation: 'cutoutB3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C3', + fixtureLocation: 'cutoutC3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, @@ -75,62 +75,62 @@ export const STANDARD_SLOT_DECK_CONFIG_FIXTURE: DeckConfiguration = [ // contains staging area fixtures export const EXTENDED_DECK_CONFIG_FIXTURE: DeckConfiguration = [ { - fixtureLocation: 'A1', + fixtureLocation: 'cutoutA1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B1', + fixtureLocation: 'cutoutB1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C1', + fixtureLocation: 'cutoutC1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A2', + fixtureLocation: 'cutoutA2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B2', + fixtureLocation: 'cutoutB2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C2', + fixtureLocation: 'cutoutC2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D2', + fixtureLocation: 'cutoutD2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A3', + fixtureLocation: 'cutoutA3', loadName: TRASH_BIN_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B3', + fixtureLocation: 'cutoutB3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C3', + fixtureLocation: 'cutoutC3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, @@ -139,62 +139,62 @@ export const EXTENDED_DECK_CONFIG_FIXTURE: DeckConfiguration = [ // contains waste chute fixture export const WASTE_CHUTE_DECK_CONFIG_FIXTURE: DeckConfiguration = [ { - fixtureLocation: 'A1', + fixtureLocation: 'cutoutA1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B1', + fixtureLocation: 'cutoutB1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C1', + fixtureLocation: 'cutoutC1', loadName: TRASH_BIN_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A2', + fixtureLocation: 'cutoutA2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B2', + fixtureLocation: 'cutoutB2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C2', + fixtureLocation: 'cutoutC2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D2', + fixtureLocation: 'cutoutD2', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A3', + fixtureLocation: 'cutoutA3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B3', + fixtureLocation: 'cutoutB3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C3', + fixtureLocation: 'cutoutC3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', loadName: WASTE_CHUTE_LOAD_NAME, fixtureId: uuidv4(), }, diff --git a/components/src/hardware-sim/Deck/DeckFromData.tsx b/components/src/hardware-sim/Deck/DeckFromLayers.tsx similarity index 59% rename from components/src/hardware-sim/Deck/DeckFromData.tsx rename to components/src/hardware-sim/Deck/DeckFromLayers.tsx index 5cd4877a31b..b5dd4c519f0 100644 --- a/components/src/hardware-sim/Deck/DeckFromData.tsx +++ b/components/src/hardware-sim/Deck/DeckFromLayers.tsx @@ -2,11 +2,14 @@ import * as React from 'react' import parseHtml from 'html-react-parser' import { stringify } from 'svgson' +import ot2DeckDefV3 from '@opentrons/shared-data/deck/definitions/3/ot2_standard.json' +import { OT2_ROBOT_TYPE } from '@opentrons/shared-data' + import type { INode } from 'svgson' -import type { DeckDefinition } from '@opentrons/shared-data' +import type { RobotType } from '@opentrons/shared-data' -export interface DeckFromDataProps { - def: DeckDefinition +export interface DeckFromLayersProps { + robotType: RobotType layerBlocklist: string[] } @@ -27,10 +30,21 @@ function filterLayerGroupNodes( }, []) } -export function DeckFromData(props: DeckFromDataProps): JSX.Element { - const { def, layerBlocklist = [] } = props +/** + * a component that renders an OT-2 deck from the V3 deck definition layers property + * takes a robot type prop to protect against an attempted Flex render + */ +export function DeckFromLayers(props: DeckFromLayersProps): JSX.Element | null { + const { robotType, layerBlocklist = [] } = props + + // early return null if not OT-2 + if (robotType !== OT2_ROBOT_TYPE) return null - const layerGroupNodes = filterLayerGroupNodes(def.layers, layerBlocklist) + // get layers from OT-2 deck definition v3 + const layerGroupNodes = filterLayerGroupNodes( + ot2DeckDefV3.layers, + layerBlocklist + ) const groupNodeWrapper = { name: 'g', diff --git a/components/src/hardware-sim/Deck/FlexTrash.tsx b/components/src/hardware-sim/Deck/FlexTrash.tsx index 11c25da03ab..6a2d28ac20c 100644 --- a/components/src/hardware-sim/Deck/FlexTrash.tsx +++ b/components/src/hardware-sim/Deck/FlexTrash.tsx @@ -1,26 +1,30 @@ import * as React from 'react' +import { + FLEX_ROBOT_TYPE, + getDeckDefFromRobotType, +} from '@opentrons/shared-data' + import { Icon } from '../../icons' import { Flex, Text } from '../../primitives' import { ALIGN_CENTER, JUSTIFY_CENTER } from '../../styles' import { BORDERS, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from './RobotCoordsForeignObject' -import { getDeckDefFromRobotType } from '@opentrons/shared-data' import trashDef from '@opentrons/shared-data/labware/definitions/2/opentrons_1_trash_3200ml_fixed/1.json' import type { RobotType } from '@opentrons/shared-data' // only allow edge cutout locations (columns 1 and 3) export type TrashLocation = - | 'A1' - | 'B1' - | 'C1' - | 'D1' - | 'A3' - | 'B3' - | 'C3' - | 'D3' + | 'cutoutA1' + | 'cutoutB1' + | 'cutoutC1' + | 'cutoutD1' + | 'cutoutA3' + | 'cutoutB3' + | 'cutoutC3' + | 'cutoutD3' interface FlexTrashProps { robotType: RobotType @@ -40,19 +44,18 @@ export const FlexTrash = ({ trashLocation, }: FlexTrashProps): JSX.Element | null => { // be sure we don't try to render for an OT-2 - if (robotType !== 'OT-3 Standard') return null + if (robotType !== FLEX_ROBOT_TYPE) return null + + const deckDefinition = getDeckDefFromRobotType(robotType) - const deckDef = getDeckDefFromRobotType(robotType) - // TODO(bh, 2023-10-09): migrate from "orderedSlots" to v4 "cutouts" key - const trashSlot = deckDef.locations.orderedSlots.find( + const trashSlot = deckDefinition.locations.cutouts.find( slot => slot.id === trashLocation ) // retrieve slot x,y positions and dimensions from deck definition for the given trash slot // TODO(bh, 2023-10-09): refactor position, offsets, and rotation after v4 migration const [x = 0, y = 0] = trashSlot?.position ?? [] - const { xDimension: slotXDimension = 0, yDimension: slotYDimension = 0 } = - trashSlot?.boundingBox ?? {} + const [slotXDimension = 0, slotYDimension = 0] = trashSlot?.position ?? [] // adjust for dimensions from trash definition const { x: xAdjustment, y: yAdjustment } = trashDef.cornerOffsetFromSlot @@ -60,10 +63,10 @@ export const FlexTrash = ({ // rotate trash 180 degrees in column 1 const rotateDegrees = - trashLocation === 'A1' || - trashLocation === 'B1' || - trashLocation === 'C1' || - trashLocation === 'D1' + trashLocation === 'cutoutA1' || + trashLocation === 'cutoutB1' || + trashLocation === 'cutoutC1' || + trashLocation === 'cutoutD1' ? '180' : '0' diff --git a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx index a93f06ca8ae..b1926a0467e 100644 --- a/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx +++ b/components/src/hardware-sim/Deck/MoveLabwareOnDeck.tsx @@ -7,6 +7,7 @@ import { LoadedModule, getDeckDefFromRobotType, getModuleDef2, + getPositionFromSlotId, LoadedLabware, } from '@opentrons/shared-data' @@ -19,28 +20,31 @@ import type { LabwareDefinition2, LabwareLocation, RobotType, - DeckSlot, DeckDefinition, } from '@opentrons/shared-data' import type { StyleProps } from '../../primitives' import type { TrashLocation } from './FlexTrash' const getModulePosition = ( - orderedSlots: DeckSlot[], + deckDef: DeckDefinition, moduleId: string, - loadedModules: LoadedModule[], - deckId: DeckDefinition['otId'] + loadedModules: LoadedModule[] ): Coordinates | null => { const loadedModule = loadedModules.find(m => m.id === moduleId) if (loadedModule == null) return null - const modSlot = orderedSlots.find( + const modSlot = deckDef.locations.addressableAreas.find( s => s.id === loadedModule.location.slotName ) if (modSlot == null) return null - const [modX, modY] = modSlot.position + + const modPosition = getPositionFromSlotId(loadedModule.id, deckDef) + if (modPosition == null) return null + const [modX, modY] = modPosition + const deckSpecificAffineTransform = - getModuleDef2(loadedModule.model).slotTransforms?.[deckId]?.[modSlot.id] - ?.labwareOffset ?? IDENTITY_AFFINE_TRANSFORM + getModuleDef2(loadedModule.model).slotTransforms?.[deckDef.otId]?.[ + modSlot.id + ]?.labwareOffset ?? IDENTITY_AFFINE_TRANSFORM const [[labwareX], [labwareY], [labwareZ]] = multiplyMatrices( [[modX], [modY], [1], [1]], deckSpecificAffineTransform @@ -49,15 +53,13 @@ const getModulePosition = ( } function getLabwareCoordinates({ - orderedSlots, + deckDef, location, - deckId, loadedModules, loadedLabware, }: { - orderedSlots: DeckSlot[] + deckDef: DeckDefinition location: LabwareLocation - deckId: DeckDefinition['otId'] loadedModules: LoadedModule[] loadedLabware: LoadedLabware[] }): Coordinates | null { @@ -76,32 +78,31 @@ function getLabwareCoordinates({ // adapter on module if ('moduleId' in loadedAdapterLocation) { return getModulePosition( - orderedSlots, + deckDef, loadedAdapterLocation.moduleId, - loadedModules, - deckId + loadedModules ) } // adapter on deck - const loadedAdapterSlot = orderedSlots.find( - s => - s.id === - ('slotName' in loadedAdapterLocation - ? loadedAdapterLocation.slotName - : loadedAdapterLocation.addressableAreaName) + const loadedAdapterSlotPosition = getPositionFromSlotId( + 'slotName' in loadedAdapterLocation + ? loadedAdapterLocation.slotName + : loadedAdapterLocation.addressableAreaName, + deckDef ) - return loadedAdapterSlot != null + return loadedAdapterSlotPosition != null ? { - x: loadedAdapterSlot.position[0], - y: loadedAdapterSlot.position[1], - z: loadedAdapterSlot.position[2], + x: loadedAdapterSlotPosition[0], + y: loadedAdapterSlotPosition[1], + z: loadedAdapterSlotPosition[2], } : null } else if ('addressableAreaName' in location) { - const slotCoordinateTuple = - orderedSlots.find(s => s.id === location.addressableAreaName)?.position ?? - null + const slotCoordinateTuple = getPositionFromSlotId( + location.addressableAreaName, + deckDef + ) return slotCoordinateTuple != null ? { x: slotCoordinateTuple[0], @@ -110,8 +111,10 @@ function getLabwareCoordinates({ } : null } else if ('slotName' in location) { - const slotCoordinateTuple = - orderedSlots.find(s => s.id === location.slotName)?.position ?? null + const slotCoordinateTuple = getPositionFromSlotId( + location.slotName, + deckDef + ) return slotCoordinateTuple != null ? { x: slotCoordinateTuple[0], @@ -120,12 +123,7 @@ function getLabwareCoordinates({ } : null } else { - return getModulePosition( - orderedSlots, - location.moduleId, - loadedModules, - deckId - ) + return getModulePosition(deckDef, location.moduleId, loadedModules) } } @@ -162,8 +160,20 @@ export function MoveLabwareOnDeck( robotType, ]) + const initialSlotId = + initialLabwareLocation === 'offDeck' || + !('slotName' in initialLabwareLocation) + ? deckDef.locations.addressableAreas[1].id + : initialLabwareLocation.slotName + + const slotPosition = getPositionFromSlotId(initialSlotId, deckDef) ?? [ + 0, + 0, + 0, + ] + const offDeckPosition = { - x: deckDef.locations.orderedSlots[1].position[0], + x: slotPosition[0], y: deckDef.cornerOffsetFromOrigin[1] - movedLabwareDef.dimensions.xDimension - @@ -171,18 +181,16 @@ export function MoveLabwareOnDeck( } const initialPosition = getLabwareCoordinates({ - orderedSlots: deckDef.locations.orderedSlots, + deckDef, location: initialLabwareLocation, loadedModules, - deckId: deckDef.otId, loadedLabware, }) ?? offDeckPosition const finalPosition = getLabwareCoordinates({ - orderedSlots: deckDef.locations.orderedSlots, + deckDef, location: finalLabwareLocation, loadedModules, - deckId: deckDef.otId, loadedLabware, }) ?? offDeckPosition @@ -220,10 +228,11 @@ export function MoveLabwareOnDeck( {...styleProps} > {deckDef != null && ( + // TODO(bh, 2023-11-06): change reference to BaseDeck, pass in deck config as prop, render animation as children )} diff --git a/components/src/hardware-sim/Deck/RobotWorkSpace.tsx b/components/src/hardware-sim/Deck/RobotWorkSpace.tsx index 5f36dababc5..cf3e24e578d 100644 --- a/components/src/hardware-sim/Deck/RobotWorkSpace.tsx +++ b/components/src/hardware-sim/Deck/RobotWorkSpace.tsx @@ -1,4 +1,5 @@ import * as React from 'react' +import { OT2_ROBOT_TYPE } from '@opentrons/shared-data' import { StyleProps, Svg } from '../../primitives' import { StyledDeck } from './StyledDeck' @@ -19,6 +20,8 @@ export interface RobotWorkSpaceProps extends StyleProps { children?: (props: RobotWorkSpaceRenderProps) => React.ReactNode deckFill?: string deckLayerBlocklist?: string[] + // optional boolean to show the OT-2 deck from deck defintion layers + showDeckLayers?: boolean // TODO(bh, 2023-10-09): remove trashSlotName?: TrashLocation trashColor?: string @@ -33,6 +36,7 @@ export function RobotWorkSpace(props: RobotWorkSpaceProps): JSX.Element | null { deckDef, deckFill = '#CCCCCC', deckLayerBlocklist = [], + showDeckLayers = false, trashSlotName, viewBox, trashColor, @@ -65,7 +69,7 @@ export function RobotWorkSpace(props: RobotWorkSpaceProps): JSX.Element | null { const [viewBoxOriginX, viewBoxOriginY] = deckDef.cornerOffsetFromOrigin const [deckXDimension, deckYDimension] = deckDef.dimensions - deckSlotsById = deckDef.locations.orderedSlots.reduce( + deckSlotsById = deckDef.locations.addressableAreas.reduce( (acc, deckSlot) => ({ ...acc, [deckSlot.id]: deckSlot }), {} ) @@ -80,15 +84,15 @@ export function RobotWorkSpace(props: RobotWorkSpaceProps): JSX.Element | null { transform="scale(1, -1)" {...styleProps} > - {deckDef != null && ( + {showDeckLayers ? ( - )} + ) : null} {children?.({ deckSlotsById, getRobotCoordsFromDOMCoords })} ) diff --git a/components/src/hardware-sim/Deck/StyledDeck.tsx b/components/src/hardware-sim/Deck/StyledDeck.tsx index 55e1cbfc3c9..de990cebe3a 100644 --- a/components/src/hardware-sim/Deck/StyledDeck.tsx +++ b/components/src/hardware-sim/Deck/StyledDeck.tsx @@ -1,51 +1,53 @@ import * as React from 'react' import styled from 'styled-components' -import { DeckFromData } from './DeckFromData' +import { DeckFromLayers } from './DeckFromLayers' import { FlexTrash } from './FlexTrash' -import type { DeckFromDataProps } from './DeckFromData' +import type { RobotType } from '@opentrons/shared-data' +import type { DeckFromLayersProps } from './DeckFromLayers' import type { TrashLocation } from './FlexTrash' interface StyledDeckProps { deckFill: string + robotType: RobotType trashColor?: string trashLocation?: TrashLocation } // apply fill to .SLOT_BASE class from ot3_standard deck definition -const StyledG = styled.g` +const StyledG = styled.g>` .SLOT_BASE { fill: ${props => props.deckFill}; } ` export function StyledDeck( - props: StyledDeckProps & DeckFromDataProps + props: StyledDeckProps & DeckFromLayersProps ): JSX.Element { const { deckFill, + robotType, trashLocation, trashColor = '#757070', - ...deckFromDataProps + ...DeckFromLayersProps } = props - - const robotType = deckFromDataProps.def.robot.model ?? 'OT-2 Standard' - const trashSlotClipId = trashLocation != null ? `SLOT_CLIPS_${trashLocation}` : null const trashLayerBlocklist = trashSlotClipId != null - ? deckFromDataProps.layerBlocklist.concat(trashSlotClipId) - : deckFromDataProps.layerBlocklist + ? DeckFromLayersProps.layerBlocklist.concat(trashSlotClipId) + : DeckFromLayersProps.layerBlocklist return ( - + {/* TODO(bh, 2023-11-06): remove trash and trashLocation prop when StyledDeck removed from MoveLabwareOnDeck */} {trashLocation != null ? ( > = args => ( ) -const deckConfig = [ +const deckConfig: Fixture[] = [ { - fixtureLocation: 'A1', + fixtureLocation: 'cutoutA1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B1', + fixtureLocation: 'cutoutB1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C1', + fixtureLocation: 'cutoutC1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D1', + fixtureLocation: 'cutoutD1', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'A3', + fixtureLocation: 'cutoutA3', loadName: TRASH_BIN_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'B3', + fixtureLocation: 'cutoutB3', loadName: STANDARD_SLOT_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'C3', + fixtureLocation: 'cutoutC3', loadName: STAGING_AREA_LOAD_NAME, fixtureId: uuidv4(), }, { - fixtureLocation: 'D3', + fixtureLocation: 'cutoutD3', loadName: WASTE_CHUTE_LOAD_NAME, fixtureId: uuidv4(), }, diff --git a/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx index d53f7d98188..a80fac8112b 100644 --- a/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/EmptyConfigFixture.tsx @@ -1,18 +1,13 @@ import * as React from 'react' import { css } from 'styled-components' -import { - getDeckDefFromRobotType, - FLEX_ROBOT_TYPE, -} from '@opentrons/shared-data' - import { Icon } from '../../icons' import { Btn, Flex } from '../../primitives' import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' -import type { Cutout } from '@opentrons/shared-data' +import type { Cutout, DeckDefinition } from '@opentrons/shared-data' // TODO: replace stubs with JSON definitions when available const standardSlotDef = { @@ -33,6 +28,7 @@ const standardSlotDef = { } interface EmptyConfigFixtureProps { + deckDefinition: DeckDefinition fixtureLocation: Cutout handleClickAdd: (fixtureLocation: Cutout) => void } @@ -40,11 +36,10 @@ interface EmptyConfigFixtureProps { export function EmptyConfigFixture( props: EmptyConfigFixtureProps ): JSX.Element { - const { handleClickAdd, fixtureLocation } = props - const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) + const { deckDefinition, handleClickAdd, fixtureLocation } = props // TODO: migrate to fixture location for v4 - const standardSlot = deckDef.locations.orderedSlots.find( + const standardSlot = deckDefinition.locations.cutouts.find( slot => slot.id === fixtureLocation ) const [xSlotPosition = 0, ySlotPosition = 0] = standardSlot?.position ?? [] @@ -52,10 +47,10 @@ export function EmptyConfigFixture( // TODO: remove adjustment when reading from fixture position // adjust x differently for right side/left side const isLeftSideofDeck = - fixtureLocation === 'A1' || - fixtureLocation === 'B1' || - fixtureLocation === 'C1' || - fixtureLocation === 'D1' + fixtureLocation === 'cutoutA1' || + fixtureLocation === 'cutoutB1' || + fixtureLocation === 'cutoutC1' || + fixtureLocation === 'cutoutD1' const xAdjustment = isLeftSideofDeck ? -101.5 : -17 const x = xSlotPosition + xAdjustment const yAdjustment = -10 diff --git a/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx index 6f7013e053f..d98cfbfdc13 100644 --- a/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/StagingAreaConfigFixture.tsx @@ -1,18 +1,13 @@ import * as React from 'react' import { css } from 'styled-components' -import { - getDeckDefFromRobotType, - FLEX_ROBOT_TYPE, -} from '@opentrons/shared-data' - import { Icon } from '../../icons' import { Btn, Flex, Text } from '../../primitives' import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' -import type { Cutout } from '@opentrons/shared-data' +import type { Cutout, DeckDefinition } from '@opentrons/shared-data' // TODO: replace stubs with JSON definitions when available const stagingAreaDef = { @@ -33,6 +28,7 @@ const stagingAreaDef = { } interface StagingAreaConfigFixtureProps { + deckDefinition: DeckDefinition fixtureLocation: Cutout handleClickRemove?: (fixtureLocation: Cutout) => void } @@ -40,11 +36,9 @@ interface StagingAreaConfigFixtureProps { export function StagingAreaConfigFixture( props: StagingAreaConfigFixtureProps ): JSX.Element { - const { handleClickRemove, fixtureLocation } = props - const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) + const { deckDefinition, handleClickRemove, fixtureLocation } = props - // TODO: migrate to fixture location for v4 - const stagingAreaSlot = deckDef.locations.orderedSlots.find( + const stagingAreaSlot = deckDefinition.locations.cutouts.find( slot => slot.id === fixtureLocation ) const [xSlotPosition = 0, ySlotPosition = 0] = stagingAreaSlot?.position ?? [] diff --git a/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx index 5ca41d53c33..f47132ebe33 100644 --- a/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/TrashBinConfigFixture.tsx @@ -1,18 +1,13 @@ import * as React from 'react' import { css } from 'styled-components' -import { - getDeckDefFromRobotType, - FLEX_ROBOT_TYPE, -} from '@opentrons/shared-data' - import { Icon } from '../../icons' import { Btn, Flex, Text } from '../../primitives' import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' -import type { Cutout } from '@opentrons/shared-data' +import type { Cutout, DeckDefinition } from '@opentrons/shared-data' // TODO: replace stubs with JSON definitions when available const trashBinDef = { @@ -33,6 +28,7 @@ const trashBinDef = { } interface TrashBinConfigFixtureProps { + deckDefinition: DeckDefinition fixtureLocation: Cutout handleClickRemove?: (fixtureLocation: Cutout) => void } @@ -40,21 +36,19 @@ interface TrashBinConfigFixtureProps { export function TrashBinConfigFixture( props: TrashBinConfigFixtureProps ): JSX.Element { - const { handleClickRemove, fixtureLocation } = props - const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) + const { deckDefinition, handleClickRemove, fixtureLocation } = props - // TODO: migrate to fixture location for v4 - const trashBinSlot = deckDef.locations.orderedSlots.find( + const trashBinSlot = deckDefinition.locations.cutouts.find( slot => slot.id === fixtureLocation ) const [xSlotPosition = 0, ySlotPosition = 0] = trashBinSlot?.position ?? [] // TODO: remove adjustment when reading from fixture position // adjust x differently for right side/left side const isLeftSideofDeck = - fixtureLocation === 'A1' || - fixtureLocation === 'B1' || - fixtureLocation === 'C1' || - fixtureLocation === 'D1' + fixtureLocation === 'cutoutA1' || + fixtureLocation === 'cutoutB1' || + fixtureLocation === 'cutoutC1' || + fixtureLocation === 'cutoutD1' const xAdjustment = isLeftSideofDeck ? -101.5 : -17 const x = xSlotPosition + xAdjustment const yAdjustment = -10 diff --git a/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx index e43ae7eadfb..2a2c35308d6 100644 --- a/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx +++ b/components/src/hardware-sim/DeckConfigurator/WasteChuteConfigFixture.tsx @@ -1,18 +1,13 @@ import * as React from 'react' import { css } from 'styled-components' -import { - getDeckDefFromRobotType, - FLEX_ROBOT_TYPE, -} from '@opentrons/shared-data' - import { Icon } from '../../icons' import { Btn, Flex, Text } from '../../primitives' import { ALIGN_CENTER, DISPLAY_FLEX, JUSTIFY_CENTER } from '../../styles' import { BORDERS, COLORS, SPACING, TYPOGRAPHY } from '../../ui-style-constants' import { RobotCoordsForeignObject } from '../Deck/RobotCoordsForeignObject' -import type { Cutout } from '@opentrons/shared-data' +import type { Cutout, DeckDefinition } from '@opentrons/shared-data' // TODO: replace stubs with JSON definitions when available const wasteChuteDef = { @@ -33,6 +28,7 @@ const wasteChuteDef = { } interface WasteChuteConfigFixtureProps { + deckDefinition: DeckDefinition fixtureLocation: Cutout handleClickRemove?: (fixtureLocation: Cutout) => void } @@ -40,11 +36,9 @@ interface WasteChuteConfigFixtureProps { export function WasteChuteConfigFixture( props: WasteChuteConfigFixtureProps ): JSX.Element { - const { handleClickRemove, fixtureLocation } = props - const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) + const { deckDefinition, handleClickRemove, fixtureLocation } = props - // TODO: migrate to fixture location for v4 - const wasteChuteSlot = deckDef.locations.orderedSlots.find( + const wasteChuteSlot = deckDefinition.locations.cutouts.find( slot => slot.id === fixtureLocation ) const [xSlotPosition = 0, ySlotPosition = 0] = wasteChuteSlot?.position ?? [] diff --git a/components/src/hardware-sim/DeckConfigurator/index.tsx b/components/src/hardware-sim/DeckConfigurator/index.tsx index 93d66920614..7eba4ebcac0 100644 --- a/components/src/hardware-sim/DeckConfigurator/index.tsx +++ b/components/src/hardware-sim/DeckConfigurator/index.tsx @@ -45,15 +45,15 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { const deckDef = getDeckDefFromRobotType(FLEX_ROBOT_TYPE) // restrict configuration to certain locations - const configurableFixtureLocations = [ - 'A1', - 'B1', - 'C1', - 'D1', - 'A3', - 'B3', - 'C3', - 'D3', + const configurableFixtureLocations: Cutout[] = [ + 'cutoutA1', + 'cutoutB1', + 'cutoutC1', + 'cutoutD1', + 'cutoutA3', + 'cutoutB3', + 'cutoutC3', + 'cutoutD3', ] const configurableDeckConfig = deckConfig.filter(fixture => configurableFixtureLocations.includes(fixture.fixtureLocation) @@ -81,10 +81,10 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { viewBox={`${deckDef.cornerOffsetFromOrigin[0]} ${deckDef.cornerOffsetFromOrigin[1]} ${deckDef.dimensions[0]} ${deckDef.dimensions[1]}`} > {/* TODO(bh, 2023-10-18): migrate to v4 deck def cutouts */} - {deckDef.locations.orderedSlots.map(slotDef => ( + {deckDef.locations.cutouts.map(slotDef => ( ( @@ -101,6 +102,7 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { {emptyFixtures.map(fixture => ( @@ -108,6 +110,7 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { {wasteChuteFixtures.map(fixture => ( @@ -115,6 +118,7 @@ export function DeckConfigurator(props: DeckConfiguratorProps): JSX.Element { {trashBinFixtures.map(fixture => ( diff --git a/components/src/hardware-sim/DeckSlotLocation/index.tsx b/components/src/hardware-sim/DeckSlotLocation/index.tsx index 162a92df3e0..6f24bebf90f 100644 --- a/components/src/hardware-sim/DeckSlotLocation/index.tsx +++ b/components/src/hardware-sim/DeckSlotLocation/index.tsx @@ -25,7 +25,7 @@ export function DeckSlotLocation( ...restProps } = props - const slotDef = deckDefinition?.locations.orderedSlots.find( + const slotDef = deckDefinition?.locations.addressableAreas.find( s => s.id === slotName ) if (slotDef == null) { diff --git a/components/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpaceWithDOMCoords.tsx b/components/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpaceWithDOMCoords.tsx index cd73a30b371..5ca8396c5be 100644 --- a/components/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpaceWithDOMCoords.tsx +++ b/components/src/hardware-sim/RobotCoordinateSpace/RobotCoordinateSpaceWithDOMCoords.tsx @@ -46,7 +46,7 @@ export function RobotCoordinateSpaceWithDOMCoords( const [viewBoxOriginX, viewBoxOriginY] = deckDef.cornerOffsetFromOrigin const [deckXDimension, deckYDimension] = deckDef.dimensions - deckSlotsById = deckDef.locations.orderedSlots.reduce( + deckSlotsById = deckDef.locations.addressableAreas.reduce( (acc, deckSlot) => ({ ...acc, [deckSlot.id]: deckSlot }), {} ) diff --git a/components/src/hardware-sim/index.ts b/components/src/hardware-sim/index.ts index bf31daf32c7..309cad747d5 100644 --- a/components/src/hardware-sim/index.ts +++ b/components/src/hardware-sim/index.ts @@ -2,6 +2,7 @@ export * from './BaseDeck' export * from './BaseDeck/__fixtures__' export * from './Deck' export * from './DeckConfigurator' +export * from './DeckSlotLocation' export * from './Labware' export * from './Module' export * from './Pipette' diff --git a/components/src/hooks/useSelectDeckLocation/index.tsx b/components/src/hooks/useSelectDeckLocation/index.tsx index f571a5c9603..6a801765a33 100644 --- a/components/src/hooks/useSelectDeckLocation/index.tsx +++ b/components/src/hooks/useSelectDeckLocation/index.tsx @@ -1,15 +1,29 @@ import * as React from 'react' import isEqual from 'lodash/isEqual' -import { DeckDefinition, getDeckDefFromRobotType } from '@opentrons/shared-data' -import { RobotCoordinateSpace } from '../../hardware-sim/RobotCoordinateSpace' -import type { ModuleLocation, RobotType } from '@opentrons/shared-data' -import { COLORS, SPACING } from '../../ui-style-constants' -import { RobotCoordsForeignDiv, SlotLabels } from '../../hardware-sim' +import { + FLEX_CUTOUT_BY_SLOT_ID, + getDeckDefFromRobotType, + getPositionFromSlotId, + isAddressableAreaStandardSlot, +} from '@opentrons/shared-data' + +import { + RobotCoordinateSpace, + RobotCoordsForeignDiv, + SingleSlotFixture, + SlotLabels, +} from '../../hardware-sim' import { Icon } from '../../icons' import { Text } from '../../primitives' import { ALIGN_CENTER, JUSTIFY_CENTER } from '../../styles' -import { DeckSlotLocation } from '../../hardware-sim/DeckSlotLocation' +import { COLORS, SPACING } from '../../ui-style-constants' + +import type { + DeckDefinition, + ModuleLocation, + RobotType, +} from '@opentrons/shared-data' export type DeckLocationSelectThemes = 'default' | 'grey' @@ -26,7 +40,7 @@ export function useDeckLocationSelect( selectedLocation, setSelectedLocation, ] = React.useState({ - slotName: deckDef.locations.orderedSlots[0].id, + slotName: deckDef.locations.addressableAreas[0].id, }) return { DeckLocationSelect: ( @@ -60,82 +74,99 @@ export function DeckLocationSelect({ deckDef.cornerOffsetFromOrigin[1] } ${deckDef.dimensions[0] - X_CROP_MM * 2} ${deckDef.dimensions[1]}`} > - {deckDef.locations.orderedSlots.map(slot => { - const slotLocation = { slotName: slot.id } - const isDisabled = disabledLocations.some( - l => - typeof l === 'object' && 'slotName' in l && l.slotName === slot.id + {deckDef.locations.addressableAreas + // only render standard slot fixture components + .filter(addressableArea => + isAddressableAreaStandardSlot(addressableArea.id, deckDef) ) - const isSelected = isEqual(selectedLocation, slotLocation) - let fill = - theme === 'default' - ? COLORS.highlightPurple2 - : COLORS.lightGreyPressed - if (isSelected) - fill = + .map(slot => { + const slotLocation = { slotName: slot.id } + const isDisabled = disabledLocations.some( + l => + typeof l === 'object' && 'slotName' in l && l.slotName === slot.id + ) + const isSelected = isEqual(selectedLocation, slotLocation) + let fill = theme === 'default' - ? COLORS.highlightPurple1 - : COLORS.darkGreyEnabled - if (isDisabled) fill = COLORS.darkGreyDisabled - if (isSelected && slot.id === 'B1' && isThermocycler) { + ? COLORS.highlightPurple2 + : COLORS.lightGreyPressed + if (isSelected) + fill = + theme === 'default' + ? COLORS.highlightPurple1 + : COLORS.darkGreyEnabled + if (isDisabled) fill = COLORS.darkGreyDisabled + if (isSelected && slot.id === 'B1' && isThermocycler) { + return ( + + + + + + Selected + + + + ) + } else if (slot.id === 'A1' && isThermocycler) { + return null + } + + const slotPosition = getPositionFromSlotId(slot.id, deckDef) + const cutoutId = FLEX_CUTOUT_BY_SLOT_ID[slot.id] + return ( - - + + !isDisabled && + setSelectedLocation != null && + setSelectedLocation(slotLocation) + } + cursor={ + setSelectedLocation == null || isDisabled || isSelected + ? 'default' + : 'pointer' + } + deckDefinition={deckDef} /> - - - - Selected - - - + {isSelected && slotPosition != null ? ( + + + + Selected + + + ) : null} + ) - } else if (slot.id === 'A1' && isThermocycler) { - return null - } - return ( - - - !isDisabled && - setSelectedLocation != null && - setSelectedLocation(slotLocation) - } - cursor={ - setSelectedLocation == null || isDisabled || isSelected - ? 'default' - : 'pointer' - } - deckDefinition={deckDef} - /> - {isSelected ? ( - - - - Selected - - - ) : null} - - ) - })} + })} slot.id) +const SLOT_OPTIONS = standardDeckDef.locations.addressableAreas.map( + slot => slot.id +) const DEFAULT_LABWARE_SLOT = SLOT_OPTIONS[0] const SlotSelect = styled.select` @@ -177,12 +180,20 @@ export function CreateLabwareSandbox(): JSX.Element { {viewOnDeck ? ( - - {({ deckSlotsById }) => { - const lwSlot = deckSlotsById[labwareSlot] + + {() => { + const lwPosition = getPositionFromSlotId( + labwareSlot, + (standardDeckDef as unknown) as DeckDefinition + ) return ( { const { - slot, + slotPosition, + slotBoundingBox, addLabware, selectedTerminalItemId, isOver, @@ -104,18 +106,18 @@ export const AdapterControlsComponents = ( {slotBlocked ? ( ) : ( unknown setDraggedLabware: (labware?: LabwareOnDeck | null) => unknown swapBlocked: boolean @@ -24,7 +25,7 @@ interface LabwareControlsProps { export const LabwareControls = (props: LabwareControlsProps): JSX.Element => { const { labwareOnDeck, - slot, + slotPosition, selectedTerminalItemId, setHoveredLabware, setDraggedLabware, @@ -32,7 +33,7 @@ export const LabwareControls = (props: LabwareControlsProps): JSX.Element => { } = props const canEdit = selectedTerminalItemId === START_TERMINAL_ITEM_ID - const [x, y] = slot.position + const [x, y] = slotPosition const width = labwareOnDeck.def.dimensions.xDimension const height = labwareOnDeck.def.dimensions.yDimension return ( diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx index ca2fb3a9fdd..2af26bf095f 100644 --- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx +++ b/protocol-designer/src/components/DeckSetup/LabwareOverlays/SlotControls.tsx @@ -23,7 +23,9 @@ import { START_TERMINAL_ITEM_ID, TerminalItemId } from '../../../steplist' import { BlockedSlot } from './BlockedSlot' import type { - DeckSlot as DeckSlotDefinition, + AddressableArea, + CoordinateTuple, + Dimensions, ModuleType, } from '@opentrons/shared-data' import type { BaseState, DeckSlot, ThunkDispatch } from '../../../types' @@ -38,7 +40,9 @@ interface DNDP { } interface OP { - slot: DeckSlotDefinition & { id: DeckSlot } // NOTE: Ian 2019-10-22 make slot `id` more restrictive when used in PD + slotPosition: CoordinateTuple | null + slotBoundingBox: Dimensions + slotId: AddressableArea['id'] moduleType: ModuleType | null selectedTerminalItemId?: TerminalItemId | null handleDragHover?: () => unknown @@ -59,7 +63,8 @@ export const SlotControlsComponent = ( props: SlotControlsProps ): JSX.Element | null => { const { - slot, + slotBoundingBox, + slotPosition, addLabware, selectedTerminalItemId, isOver, @@ -71,7 +76,8 @@ export const SlotControlsComponent = ( } = props if ( selectedTerminalItemId !== START_TERMINAL_ITEM_ID || - (itemType !== DND_TYPES.LABWARE && itemType !== null) + (itemType !== DND_TYPES.LABWARE && itemType !== null) || + slotPosition == null ) return null @@ -107,18 +113,18 @@ export const SlotControlsComponent = ( {slotBlocked ? ( ) : ( , ownProps: OP ): DP => ({ - addLabware: () => dispatch(openAddLabwareModal({ slot: ownProps.slot.id })), + addLabware: () => dispatch(openAddLabwareModal({ slot: ownProps.slotId })), moveDeckItem: (sourceSlot, destSlot) => dispatch(moveDeckItem(sourceSlot, destSlot)), }) @@ -155,7 +161,7 @@ const slotTarget = { drop: (props: SlotControlsProps, monitor: DropTargetMonitor) => { const draggedItem = monitor.getItem() if (draggedItem) { - props.moveDeckItem(draggedItem.labwareOnDeck.slot, props.slot.id) + props.moveDeckItem(draggedItem.labwareOnDeck.slot, props.slotId) } }, hover: (props: SlotControlsProps) => { diff --git a/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx b/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx index b6ae460ab10..12ba722b0e3 100644 --- a/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx +++ b/protocol-designer/src/components/DeckSetup/LabwareOverlays/__tests__/SlotControls.test.tsx @@ -2,7 +2,7 @@ import React from 'react' import { shallow } from 'enzyme' import fixture_96_plate from '@opentrons/shared-data/labware/fixtures/2/fixture_96_plate.json' import { - DeckSlot, + CoordinateTuple, LabwareDefinition2, MAGNETIC_MODULE_TYPE, } from '@opentrons/shared-data' @@ -18,16 +18,12 @@ describe('SlotControlsComponent', () => { typeof labwareModuleCompatibility.getLabwareIsCompatible > beforeEach(() => { - const slot: DeckSlot = { - id: 'deckSlot1', - position: [1, 2, 3], - boundingBox: { - xDimension: 10, - yDimension: 20, - zDimension: 40, - }, - displayName: 'slot 1', - compatibleModules: [MAGNETIC_MODULE_TYPE], + const slotId = 'D1' + const slotPosition: CoordinateTuple = [1, 2, 3] + const slotBoundingBox = { + xDimension: 10, + yDimension: 20, + zDimension: 40, } const labwareOnDeck = { @@ -38,7 +34,9 @@ describe('SlotControlsComponent', () => { } props = { - slot, + slotId, + slotPosition, + slotBoundingBox, addLabware: jest.fn(), moveDeckItem: jest.fn(), selectedTerminalItemId: START_TERMINAL_ITEM_ID, diff --git a/protocol-designer/src/components/DeckSetup/index.tsx b/protocol-designer/src/components/DeckSetup/index.tsx index 5109d454526..3b351618d50 100644 --- a/protocol-designer/src/components/DeckSetup/index.tsx +++ b/protocol-designer/src/components/DeckSetup/index.tsx @@ -11,11 +11,10 @@ import { FlexTrash, RobotCoordinateSpaceWithDOMCoords, WasteChuteFixture, - WasteChuteLocation, StagingAreaFixture, StagingAreaLocation, SingleSlotFixture, - DeckFromData, + DeckFromLayers, } from '@opentrons/components' import { AdditionalEquipmentEntity, @@ -25,7 +24,6 @@ import { import { getLabwareHasQuirk, inferModuleOrientationFromSlot, - DeckSlot as DeckDefSlot, getDeckDefFromRobotType, OT2_ROBOT_TYPE, getModuleDef2, @@ -35,16 +33,15 @@ import { DeckDefinition, RobotType, FLEX_ROBOT_TYPE, - Cutout, TRASH_BIN_LOAD_NAME, STAGING_AREA_LOAD_NAME, + WASTE_CHUTE_CUTOUT, WASTE_CHUTE_LOAD_NAME, + AddressableAreaName, + CutoutFixture, + CutoutId, } from '@opentrons/shared-data' -import { - FLEX_TRASH_DEF_URI, - OT_2_TRASH_DEF_URI, - PSEUDO_DECK_SLOTS, -} from '../../constants' +import { FLEX_TRASH_DEF_URI, OT_2_TRASH_DEF_URI } from '../../constants' import { selectors as labwareDefSelectors } from '../../labware-defs' import { selectors as featureFlagSelectors } from '../../feature-flags' @@ -73,10 +70,14 @@ import { import { FlexModuleTag } from './FlexModuleTag' import { Ot2ModuleTag } from './Ot2ModuleTag' import { SlotLabels } from './SlotLabels' -import { DEFAULT_SLOTS } from './constants' import { getHasGen1MultiChannelPipette, getSwapBlocked } from './utils' import styles from './DeckSetup.css' +import { + getAddressableAreaFromSlotId, + getPositionFromSlotId, + isAddressableAreaStandardSlot, +} from '@opentrons/shared-data/js' export const DECK_LAYER_BLOCKLIST = [ 'calibrationMarkings', @@ -88,7 +89,8 @@ export const DECK_LAYER_BLOCKLIST = [ 'screwHoles', ] -type ContentsProps = RobotWorkSpaceRenderProps & { +interface ContentsProps { + getRobotCoordsFromDOMCoords: RobotWorkSpaceRenderProps['getRobotCoordsFromDOMCoords'] activeDeckSetup: InitialDeckSetup selectedTerminalItemId?: TerminalItemId | null showGen1MultichannelCollisionWarnings: boolean @@ -103,7 +105,6 @@ const darkFill = COLORS.darkGreyEnabled export const DeckSetupContents = (props: ContentsProps): JSX.Element => { const { activeDeckSetup, - deckSlotsById, getRobotCoordsFromDOMCoords, showGen1MultichannelCollisionWarnings, deckDef, @@ -140,9 +141,6 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { ) const slotIdsBlockedBySpanning = getSlotIdsBlockedBySpanning(activeDeckSetup) - const deckSlots: DeckDefSlot[] = values(deckSlotsById) - // modules can be on the deck, including pseudo-slots (eg special 'spanning' slot for thermocycler position) - const moduleParentSlots = [...deckSlots, ...values(PSEUDO_DECK_SLOTS)] const allLabware: LabwareOnDeckType[] = Object.keys( activeDeckSetup.labware @@ -156,35 +154,42 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { const allModules: ModuleOnDeck[] = values(activeDeckSetup.modules) // NOTE: naively hard-coded to show warning north of slots 1 or 3 when occupied by any module - const multichannelWarningSlots: DeckDefSlot[] = showGen1MultichannelCollisionWarnings + const multichannelWarningSlotIds: AddressableAreaName[] = showGen1MultichannelCollisionWarnings ? compact([ - (allModules.some( + allModules.some( moduleOnDeck => moduleOnDeck.slot === '1' && - // @ts-expect-error(sa, 2021-6-21): ModuleModel is a super type of the elements in MODULES_WITH_COLLISION_ISSUES MODULES_WITH_COLLISION_ISSUES.includes(moduleOnDeck.model) - ) && - deckSlotsById?.['4']) || - null, - (allModules.some( + ) + ? deckDef.locations.addressableAreas.find(s => s.id === '4')?.id + : null, + allModules.some( moduleOnDeck => moduleOnDeck.slot === '3' && - // @ts-expect-error(sa, 2021-6-21): ModuleModel is a super type of the elements in MODULES_WITH_COLLISION_ISSUES MODULES_WITH_COLLISION_ISSUES.includes(moduleOnDeck.model) - ) && - deckSlotsById?.['6']) || - null, + ) + ? deckDef.locations.addressableAreas.find(s => s.id === '6')?.id + : null, ]) : [] + console.log( + 'AA', + deckDef.locations.addressableAreas.filter(addressableArea => + isAddressableAreaStandardSlot(addressableArea.id, deckDef) + ) + ) return ( <> {/* all modules */} {allModules.map(moduleOnDeck => { - const slot = moduleParentSlots.find( - slot => slot.id === moduleOnDeck.slot - ) - if (slot == null) { + // modules can be on the deck, including pseudo-slots (eg special 'spanning' slot for thermocycler position) + // const moduleParentSlots = [...deckSlots, ...values(PSEUDO_DECK_SLOTS)] + // const slot = moduleParentSlots.find( + // slot => slot.id === moduleOnDeck.slot + // ) + const slotPosition = getPositionFromSlotId(moduleOnDeck.slot, deckDef) + if (slotPosition == null) { console.warn( `no slot ${moduleOnDeck.slot} for module ${moduleOnDeck.id}` ) @@ -225,17 +230,10 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { const shouldHideChildren = moduleOnDeck.moduleState.type === THERMOCYCLER_MODULE_TYPE && moduleOnDeck.moduleState.lidOpen === false - const labwareInterfaceSlotDef: DeckDefSlot = { - displayName: `Labware interface on ${moduleOnDeck.model}`, - id: moduleOnDeck.id, - position: [0, 0, 0], // Module Component already handles nested positioning - matingSurfaceUnitVector: [-1, 1, -1], - boundingBox: { - xDimension: moduleDef.dimensions.labwareInterfaceXDimension ?? 0, - yDimension: moduleDef.dimensions.labwareInterfaceYDimension ?? 0, - zDimension: 0, - }, - compatibleModules: [THERMOCYCLER_MODULE_TYPE], + const labwareInterfaceBoundingBox = { + xDimension: moduleDef.dimensions.labwareInterfaceXDimension ?? 0, + yDimension: moduleDef.dimensions.labwareInterfaceYDimension ?? 0, + zDimension: 0, } const moduleOrientation = inferModuleOrientationFromSlot( @@ -246,15 +244,13 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { labwareLoadedOnModule?.def.metadata.displayCategory === 'adapter' return ( {labwareLoadedOnModule != null && !shouldHideChildren ? ( @@ -265,19 +261,20 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { labwareOnDeck={labwareLoadedOnModule} /> {isAdapter ? ( - // @ts-expect-error + // @ts-expect-error ) : ( { {labwareLoadedOnModule == null && !shouldHideChildren && !isAdapter ? ( - // @ts-expect-error (ce, 2021-06-21) once we upgrade to the react-dnd hooks api, and use react-redux hooks, typing this will be easier + // @ts-expect-error { })} {/* on-deck warnings */} - {multichannelWarningSlots.map(slot => ( - - ))} + {multichannelWarningSlotIds.map(slotId => { + const slotPosition = getPositionFromSlotId(slotId, deckDef) + const slotBoundingBox = getAddressableAreaFromSlotId(slotId, deckDef) + ?.boundingBox + return slotPosition != null && slotBoundingBox != null ? ( + + ) : null + })} {/* SlotControls for all empty deck + module slots */} - {deckSlots + {deckDef.locations.addressableAreas + // only render standard slot fixture components .filter( - slot => - !slotIdsBlockedBySpanning.includes(slot.id) && - getSlotIsEmpty(activeDeckSetup, slot.id) && - slot.id !== trashSlot + addressableArea => + isAddressableAreaStandardSlot(addressableArea.id, deckDef) && + !slotIdsBlockedBySpanning.includes(addressableArea.id) && + getSlotIsEmpty(activeDeckSetup, addressableArea.id) && + addressableArea.id !== trashSlot ) - .map(slot => { + .map(addressableArea => { return ( - // @ts-expect-error (ce, 2021-06-21) once we upgrade to the react-dnd hooks api, and use react-redux hooks, typing this will be easier + // @ts-expect-error ) @@ -363,8 +372,13 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { allLabware.some(lab => lab.id === labware.slot) ) return null - const slot = deckSlots.find(slot => slot.id === labware.slot) - if (slot == null) { + + const slotPosition = getPositionFromSlotId(labware.slot, deckDef) + const slotBoundingBox = getAddressableAreaFromSlotId( + labware.slot, + deckDef + )?.boundingBox + if (slotPosition == null || slotBoundingBox == null) { console.warn(`no slot ${labware.slot} for labware ${labware.id}!`) return null } @@ -373,27 +387,26 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { return ( {labwareIsAdapter ? ( - <> - {/* @ts-expect-error */} - - + // @ts-expect-error + ) : ( { labware.slot === 'offDeck' ) return null - const slotOnDeck = deckSlots.find(slot => slot.id === labware.slot) - if (slotOnDeck != null) { + if ( + deckDef.locations.addressableAreas.some( + addressableArea => addressableArea.id === labware.slot + ) + ) { return null } const slotForOnTheDeck = allLabware.find(lab => lab.id === labware.slot) ?.slot const slotForOnMod = allModules.find(mod => mod.id === slotForOnTheDeck) ?.slot - const deckDefSlot = deckSlots.find( - s => s.id === (slotForOnMod ?? slotForOnTheDeck) - ) - if (deckDefSlot == null) { + let slotPosition = null + if (slotForOnMod != null) { + slotPosition = getPositionFromSlotId(slotForOnMod, deckDef) + } else if (slotForOnTheDeck != null) { + slotPosition = getPositionFromSlotId(slotForOnTheDeck, deckDef) + } + if (slotPosition == null) { console.warn(`no slot ${labware.slot} for labware ${labware.id}!`) return null } return ( { const trashBinFixtures = [ { fixtureId: trash?.id, - fixtureLocation: trash?.slot as Cutout, + fixtureLocation: + trash?.slot != null + ? getCutoutIdForAddressableArea( + trash?.slot as AddressableAreaName, + deckDef.cutoutFixtures + ) + : null, loadName: TRASH_BIN_LOAD_NAME, }, ] @@ -505,12 +530,9 @@ export const DeckSetup = (): JSX.Element => { const stagingAreaFixtures: AdditionalEquipmentEntity[] = Object.values( activeDeckSetup.additionalEquipmentOnDeck ).filter(aE => aE.name === STAGING_AREA_LOAD_NAME) - const locations = Object.values( - activeDeckSetup.additionalEquipmentOnDeck - ).map(aE => aE.location) - const filteredSlots = DEFAULT_SLOTS.filter( - slot => !locations.includes(slot.fixtureLocation) + const filteredAddressableAreas = deckDef.locations.addressableAreas.filter( + aa => isAddressableAreaStandardSlot(aa.id, deckDef) ) return ( @@ -522,55 +544,63 @@ export const DeckSetup = (): JSX.Element => { deckDef={deckDef} viewBox={`${deckDef.cornerOffsetFromOrigin[0]} ${deckDef.cornerOffsetFromOrigin[1]} ${deckDef.dimensions[0]} ${deckDef.dimensions[1]}`} > - {({ deckSlotsById, getRobotCoordsFromDOMCoords }) => ( + {({ getRobotCoordsFromDOMCoords }) => ( <> {robotType === OT2_ROBOT_TYPE ? ( - + ) : ( <> - {filteredSlots.map(fixture => ( - - ))} + {filteredAddressableAreas.map(addressableArea => { + const cutoutId = getCutoutIdForAddressableArea( + addressableArea.id, + deckDef.cutoutFixtures + ) + return cutoutId != null ? ( + + ) : null + })} {stagingAreaFixtures.map(fixture => ( ))} {trash != null - ? trashBinFixtures.map(fixture => ( - - - - - )) + ? trashBinFixtures.map(fixture => + fixture.fixtureLocation != null ? ( + + + + + ) : null + ) : null} {wasteChuteFixtures.map(fixture => ( { selectedTerminalItemId={selectedTerminalItemId} {...{ deckDef, - deckSlotsById, getRobotCoordsFromDOMCoords, showGen1MultichannelCollisionWarnings, }} @@ -601,3 +630,18 @@ export const DeckSetup = (): JSX.Element => {
    ) } + +function getCutoutIdForAddressableArea( + addressableArea: AddressableAreaName, + cutoutFixtures: CutoutFixture[] +): CutoutId | null { + return cutoutFixtures.reduce((acc, cutoutFixture) => { + const [cutoutId] = + Object.entries( + cutoutFixture.providesAddressableAreas + ).find(([_cutoutId, providedAAs]) => + providedAAs.includes(addressableArea) + ) ?? [] + return (cutoutId as CutoutId) ?? acc + }, null) +} diff --git a/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx b/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx index 1879c63a317..7720a52871e 100644 --- a/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx +++ b/protocol-designer/src/components/StepEditForm/fields/LabwareLocationField/index.tsx @@ -1,6 +1,9 @@ import * as React from 'react' import { useSelector } from 'react-redux' -import { getModuleDisplayName, WASTE_CHUTE_SLOT } from '@opentrons/shared-data' +import { + getModuleDisplayName, + WASTE_CHUTE_CUTOUT, +} from '@opentrons/shared-data' import { i18n } from '../../../../localization' import { getAdditionalEquipmentEntities, @@ -37,7 +40,8 @@ export function LabwareLocationField( if (isLabwareOffDeck && hasWasteChute) { unoccupiedLabwareLocationsOptions = unoccupiedLabwareLocationsOptions.filter( - option => option.value !== 'offDeck' && option.value !== WASTE_CHUTE_SLOT + option => + option.value !== 'offDeck' && option.value !== WASTE_CHUTE_CUTOUT ) } else if (useGripper || isLabwareOffDeck) { unoccupiedLabwareLocationsOptions = unoccupiedLabwareLocationsOptions.filter( diff --git a/protocol-designer/src/components/labware/__tests__/utils.test.ts b/protocol-designer/src/components/labware/__tests__/utils.test.ts index bda5fc71096..b5c63951b1b 100644 --- a/protocol-designer/src/components/labware/__tests__/utils.test.ts +++ b/protocol-designer/src/components/labware/__tests__/utils.test.ts @@ -1,4 +1,4 @@ -import { WASTE_CHUTE_SLOT } from '@opentrons/shared-data' +import { WASTE_CHUTE_CUTOUT } from '@opentrons/shared-data' import { getHasWasteChute } from '..' import type { AdditionalEquipmentEntities } from '@opentrons/step-generation' @@ -25,7 +25,7 @@ describe('getHasWasteChute', () => { mockId2: { id: mockId2, name: 'wasteChute', - location: WASTE_CHUTE_SLOT, + location: WASTE_CHUTE_CUTOUT, }, } as AdditionalEquipmentEntities const result = getHasWasteChute(mockAdditionalEquipmentEntities) diff --git a/protocol-designer/src/components/labware/utils.ts b/protocol-designer/src/components/labware/utils.ts index f3f27add66d..1c92ee47186 100644 --- a/protocol-designer/src/components/labware/utils.ts +++ b/protocol-designer/src/components/labware/utils.ts @@ -1,7 +1,7 @@ import reduce from 'lodash/reduce' import { AdditionalEquipmentEntities, AIR } from '@opentrons/step-generation' import { WellFill } from '@opentrons/components' -import { WASTE_CHUTE_SLOT } from '@opentrons/shared-data' +import { WASTE_CHUTE_CUTOUT } from '@opentrons/shared-data' import { swatchColors, MIXED_WELL_COLOR } from '../swatchColors' import { ContentsByWell, WellContents } from '../../labware-ingred/types' @@ -40,7 +40,7 @@ export const getHasWasteChute = ( ): boolean => { return Object.values(additionalEquipmentEntities).some( additionalEquipmentEntity => - additionalEquipmentEntity.location === WASTE_CHUTE_SLOT && + additionalEquipmentEntity.location === WASTE_CHUTE_CUTOUT && additionalEquipmentEntity.name === 'wasteChute' ) } diff --git a/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx b/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx index 24f11c7b5c7..dc552a72d63 100644 --- a/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx +++ b/protocol-designer/src/components/modals/CreateFileWizard/StagingAreaTile.tsx @@ -13,6 +13,7 @@ import { } from '@opentrons/components' import { OT2_ROBOT_TYPE, + STAGING_AREA_CUTOUTS, STAGING_AREA_LOAD_NAME, STANDARD_SLOT_LOAD_NAME, } from '@opentrons/shared-data' @@ -21,11 +22,9 @@ import { getEnableDeckModification } from '../../../feature-flags/selectors' import { GoBack } from './GoBack' import { HandleEnter } from './HandleEnter' -import type { Cutout, DeckConfiguration } from '@opentrons/shared-data' +import type { DeckConfiguration } from '@opentrons/shared-data' import type { WizardTileProps } from './types' -const STAGING_AREA_SLOTS: Cutout[] = ['A3', 'B3', 'C3', 'D3'] - export function StagingAreaTile(props: WizardTileProps): JSX.Element | null { const { values, goBack, proceed, setFieldValue } = props const isOt2 = values.fields.robotType === OT2_ROBOT_TYPE @@ -49,7 +48,7 @@ export function StagingAreaTile(props: WizardTileProps): JSX.Element | null { // NOTE: fixtureId doesn't matter since we don't create // the entity until you complete the create file wizard via createDeckFixture action // fixtureId here is only needed to visually add to the deck configurator - const STANDARD_EMPTY_SLOTS: DeckConfiguration = STAGING_AREA_SLOTS.map( + const STANDARD_EMPTY_SLOTS: DeckConfiguration = STAGING_AREA_CUTOUTS.map( fixtureLocation => ({ fixtureId: `id_${fixtureLocation}`, fixtureLocation, diff --git a/protocol-designer/src/components/modals/CreateFileWizard/index.tsx b/protocol-designer/src/components/modals/CreateFileWizard/index.tsx index 5bb0029d221..da77d891ae2 100644 --- a/protocol-designer/src/components/modals/CreateFileWizard/index.tsx +++ b/protocol-designer/src/components/modals/CreateFileWizard/index.tsx @@ -26,7 +26,7 @@ import { MAGNETIC_MODULE_V2, THERMOCYCLER_MODULE_V2, TEMPERATURE_MODULE_V2, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { actions as stepFormActions, @@ -238,7 +238,7 @@ export function CreateFileWizard(): JSX.Element | null { enableDeckModification && values.additionalEquipment.includes('wasteChute') ) { - dispatch(createDeckFixture('wasteChute', WASTE_CHUTE_SLOT)) + dispatch(createDeckFixture('wasteChute', WASTE_CHUTE_CUTOUT)) } // add staging areas const stagingAreas = values.additionalEquipment.filter(equipment => diff --git a/protocol-designer/src/components/modules/AdditionalItemsRow.tsx b/protocol-designer/src/components/modules/AdditionalItemsRow.tsx index a6686a490f0..69672553acc 100644 --- a/protocol-designer/src/components/modules/AdditionalItemsRow.tsx +++ b/protocol-designer/src/components/modules/AdditionalItemsRow.tsx @@ -1,6 +1,9 @@ import * as React from 'react' import styled from 'styled-components' -import { WASTE_CHUTE_SLOT } from '@opentrons/shared-data' +import { + getCutoutDisplayName, + WASTE_CHUTE_CUTOUT, +} from '@opentrons/shared-data' import { OutlineButton, Flex, @@ -24,6 +27,8 @@ import { FlexSlotMap } from './FlexSlotMap' import styles from './styles.css' +import type { Cutout } from '@opentrons/shared-data' + interface AdditionalItemsRowProps { handleAttachment: () => void isEquipmentAdded: boolean @@ -97,9 +102,11 @@ export function AdditionalItemsRow(
    @@ -107,7 +114,7 @@ export function AdditionalItemsRow( selectedSlots={ name === 'trashBin' ? [trashBinSlot ?? ''] - : [WASTE_CHUTE_SLOT] + : [WASTE_CHUTE_CUTOUT] } />
    diff --git a/protocol-designer/src/components/modules/FlexSlotMap.tsx b/protocol-designer/src/components/modules/FlexSlotMap.tsx index 0f46be8f3a7..507656effb9 100644 --- a/protocol-designer/src/components/modules/FlexSlotMap.tsx +++ b/protocol-designer/src/components/modules/FlexSlotMap.tsx @@ -2,19 +2,22 @@ import * as React from 'react' import { FLEX_ROBOT_TYPE, getDeckDefFromRobotType, + getPositionFromSlotId, } from '@opentrons/shared-data' -import { RobotCoordinateSpace } from '@opentrons/components/src/hardware-sim/RobotCoordinateSpace' -import { DeckSlotLocation } from '@opentrons/components/src/hardware-sim/DeckSlotLocation' import { ALIGN_CENTER, BORDERS, COLORS, Flex, JUSTIFY_CENTER, + RobotCoordinateSpace, RobotCoordsForeignObject, + SingleSlotFixture, SPACING, } from '@opentrons/components' +import type { Cutout } from '@opentrons/shared-data' + const X_ADJUSTMENT_LEFT_SIDE = -101.5 const X_ADJUSTMENT = -17 const X_DIMENSION_MIDDLE_SLOTS = 160.3 @@ -44,20 +47,20 @@ export function FlexSlotMap(props: FlexSlotMapProps): JSX.Element { height="100px" viewBox={`${deckDef.cornerOffsetFromOrigin[0]} ${deckDef.cornerOffsetFromOrigin[1]} ${deckDef.dimensions[0]} ${deckDef.dimensions[1]}`} > - {deckDef.locations.orderedSlots.map(slotDef => ( - ( + ))} {selectedSlots.map((selectedSlot, index) => { - const slot = deckDef.locations.orderedSlots.find( - slot => slot.id === selectedSlot - ) - const [xSlotPosition = 0, ySlotPosition = 0] = slot?.position ?? [] + // if selected slot is passed as a cutout id, trim to define as slot id + const slotFromCutout = selectedSlot.replace('cutout', '') + const [xSlotPosition = 0, ySlotPosition = 0] = + getPositionFromSlotId(slotFromCutout, deckDef) ?? [] const isLeftSideofDeck = selectedSlot === 'A1' || @@ -84,7 +87,7 @@ export function FlexSlotMap(props: FlexSlotMapProps): JSX.Element { return ( ({ fixtureId: `id_${fixtureLocation}`, fixtureLocation: fixtureLocation as Cutout, diff --git a/protocol-designer/src/components/modules/StagingAreasRow.tsx b/protocol-designer/src/components/modules/StagingAreasRow.tsx index dd882953be1..7bdb2a88e78 100644 --- a/protocol-designer/src/components/modules/StagingAreasRow.tsx +++ b/protocol-designer/src/components/modules/StagingAreasRow.tsx @@ -11,6 +11,7 @@ import { TYPOGRAPHY, DIRECTION_ROW, } from '@opentrons/components' +import { getCutoutDisplayName } from '@opentrons/shared-data' import { i18n } from '../../localization' import stagingAreaImage from '../../images/staging_area.png' import { getStagingAreaSlots } from '../../utils' @@ -19,6 +20,7 @@ import { StagingAreasModal } from './StagingAreasModal' import { FlexSlotMap } from './FlexSlotMap' import styles from './styles.css' +import type { Cutout } from '@opentrons/shared-data' import type { AdditionalEquipmentEntity } from '@opentrons/step-generation' interface StagingAreasRowProps { @@ -60,12 +62,14 @@ export function StagingAreasRow(props: StagingAreasRowProps): JSX.Element { className={styles.module_col} style={{ marginLeft: SPACING.spacing32 }} /> - {hasStagingAreas ? ( + {hasStagingAreas && stagingAreaLocations != null ? ( <>
    + getCutoutDisplayName(location as Cutout) + )}`} />
    diff --git a/protocol-designer/src/components/modules/TrashModal.tsx b/protocol-designer/src/components/modules/TrashModal.tsx index fedb02bc905..fb3a1a4762b 100644 --- a/protocol-designer/src/components/modules/TrashModal.tsx +++ b/protocol-designer/src/components/modules/TrashModal.tsx @@ -21,7 +21,7 @@ import { import { FLEX_ROBOT_TYPE, getDeckDefFromRobotType, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { i18n } from '../../localization' import { OUTER_SLOTS_FLEX } from '../../modules' @@ -144,7 +144,7 @@ export const TrashModal = (props: TrashModalProps): JSX.Element => { }) ) } else if (trashName === 'wasteChute') { - dispatch(createDeckFixture('wasteChute', WASTE_CHUTE_SLOT)) + dispatch(createDeckFixture('wasteChute', WASTE_CHUTE_CUTOUT)) } onCloseClick() @@ -154,7 +154,7 @@ export const TrashModal = (props: TrashModalProps): JSX.Element => { diff --git a/protocol-designer/src/components/modules/__tests__/AdditionalItemsRow.test.tsx b/protocol-designer/src/components/modules/__tests__/AdditionalItemsRow.test.tsx index 38221bf9321..19801fbd4e2 100644 --- a/protocol-designer/src/components/modules/__tests__/AdditionalItemsRow.test.tsx +++ b/protocol-designer/src/components/modules/__tests__/AdditionalItemsRow.test.tsx @@ -1,7 +1,6 @@ import * as React from 'react' import i18n from 'i18next' import { renderWithProviders } from '@opentrons/components' -import { WASTE_CHUTE_SLOT } from '@opentrons/shared-data' import { Portal } from '../../portals/TopPortal' import { AdditionalItemsRow } from '../AdditionalItemsRow' @@ -71,7 +70,7 @@ describe('AdditionalItemsRow', () => { getByAltText('Waste Chute') getByText('mock slot map') getByText('Position:') - getByText(`Slot ${WASTE_CHUTE_SLOT}`) + getByText('D3') getByRole('button', { name: 'remove' }).click() expect(props.handleAttachment).toHaveBeenCalled() }) diff --git a/protocol-designer/src/components/modules/__tests__/StagingAreasRow.test.tsx b/protocol-designer/src/components/modules/__tests__/StagingAreasRow.test.tsx index baa7ad21fbe..40e74342714 100644 --- a/protocol-designer/src/components/modules/__tests__/StagingAreasRow.test.tsx +++ b/protocol-designer/src/components/modules/__tests__/StagingAreasRow.test.tsx @@ -42,7 +42,7 @@ describe('StagingAreasRow', () => { const { getByRole, getByText } = render(props) getByText('mock slot map') getByText('Position:') - getByText('Slots B3') + getByText('B3') getByRole('button', { name: 'remove' }).click() expect(props.handleAttachment).toHaveBeenCalled() getByRole('button', { name: 'edit' }).click() diff --git a/protocol-designer/src/components/modules/__tests__/TrashModal.test.tsx b/protocol-designer/src/components/modules/__tests__/TrashModal.test.tsx index a498f587784..04c665c46b7 100644 --- a/protocol-designer/src/components/modules/__tests__/TrashModal.test.tsx +++ b/protocol-designer/src/components/modules/__tests__/TrashModal.test.tsx @@ -12,7 +12,7 @@ import { } from '../../../labware-ingred/actions' import { FLEX_TRASH_DEF_URI } from '../../../constants' import { TrashModal } from '../TrashModal' -import { WASTE_CHUTE_SLOT } from '@opentrons/shared-data' +import { WASTE_CHUTE_CUTOUT } from '@opentrons/shared-data' jest.mock('../../../step-forms') jest.mock('../../../step-forms/selectors') @@ -114,7 +114,7 @@ describe('TrashModal ', () => { await waitFor(() => { expect(mockCreateDeckFixture).toHaveBeenCalledWith( 'wasteChute', - WASTE_CHUTE_SLOT + WASTE_CHUTE_CUTOUT ) }) }) diff --git a/protocol-designer/src/components/modules/utils.ts b/protocol-designer/src/components/modules/utils.ts index ead37eaedf6..06491f2cadb 100644 --- a/protocol-designer/src/components/modules/utils.ts +++ b/protocol-designer/src/components/modules/utils.ts @@ -1,6 +1,5 @@ import { MODULES_WITH_COLLISION_ISSUES } from '@opentrons/step-generation' import { ModuleModel } from '@opentrons/shared-data' export function isModuleWithCollisionIssue(model: ModuleModel): boolean { - // @ts-expect-error(sa, 2021-6-21): ModuleModel is a super type of the elements in MODULES_WITH_COLLISION_ISSUES return MODULES_WITH_COLLISION_ISSUES.includes(model) } diff --git a/protocol-designer/src/components/steplist/MoveLabwareHeader.tsx b/protocol-designer/src/components/steplist/MoveLabwareHeader.tsx index 9d641a34362..bfba5d12886 100644 --- a/protocol-designer/src/components/steplist/MoveLabwareHeader.tsx +++ b/protocol-designer/src/components/steplist/MoveLabwareHeader.tsx @@ -6,7 +6,7 @@ import { Tooltip, useHoverTooltip, TOOLTIP_FIXED } from '@opentrons/components' import { getLabwareDisplayName, getModuleDisplayName, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { getAdditionalEquipmentEntities, @@ -59,7 +59,7 @@ export function MoveLabwareHeader(props: MoveLabwareHeaderProps): JSX.Element { destSlot = getLabwareDisplayName(labwareEntities[destinationSlot].def) } else if ( getHasWasteChute(additionalEquipmentEntities) && - destinationSlot === WASTE_CHUTE_SLOT + destinationSlot === WASTE_CHUTE_CUTOUT ) { destSlot = i18n.t('application.waste_chute_slot') } else { diff --git a/protocol-designer/src/labware-ingred/utils.ts b/protocol-designer/src/labware-ingred/utils.ts index abb598e16ea..685e1bac8e7 100644 --- a/protocol-designer/src/labware-ingred/utils.ts +++ b/protocol-designer/src/labware-ingred/utils.ts @@ -8,7 +8,7 @@ export function getNextAvailableDeckSlot( robotType: RobotType ): DeckSlot | null | undefined { const deckDef = getDeckDefFromRobotType(robotType) - return deckDef.locations.orderedSlots.find(slot => + return deckDef.locations.addressableAreas.find(slot => getSlotIsEmpty(initialDeckSetup, slot.id) )?.id } diff --git a/protocol-designer/src/top-selectors/labware-locations/index.ts b/protocol-designer/src/top-selectors/labware-locations/index.ts index 1ef2640b018..9fad438c2d4 100644 --- a/protocol-designer/src/top-selectors/labware-locations/index.ts +++ b/protocol-designer/src/top-selectors/labware-locations/index.ts @@ -5,7 +5,8 @@ import { getDeckDefFromRobotType, getModuleDisplayName, FLEX_ROBOT_TYPE, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_ADDRESSABLE_AREAS, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { START_TERMINAL_ITEM_ID, @@ -108,7 +109,7 @@ export const getUnocuppiedLabwareLocationOptions: Selector< ) => { const deckDef = getDeckDefFromRobotType(robotType) const trashSlot = robotType === FLEX_ROBOT_TYPE ? 'A3' : '12' - const allSlotIds = deckDef.locations.orderedSlots.map(slot => slot.id) + const allSlotIds = deckDef.locations.addressableAreas.map(slot => slot.id) const hasWasteChute = getHasWasteChute(additionalEquipmentEntities) if (robotState == null) return null @@ -196,13 +197,13 @@ export const getUnocuppiedLabwareLocationOptions: Selector< .map(lw => lw.slot) .includes(slotId) && slotId !== trashSlot && - (hasWasteChute ? slotId !== WASTE_CHUTE_SLOT : true) + (hasWasteChute ? !(slotId in WASTE_CHUTE_ADDRESSABLE_AREAS) : true) ) .map(slotId => ({ name: slotId, value: slotId })) const offDeck = { name: 'Off-deck', value: 'offDeck' } const wasteChuteSlot = { name: 'Waste Chute in D3', - value: WASTE_CHUTE_SLOT, + value: WASTE_CHUTE_CUTOUT, } return hasWasteChute diff --git a/protocol-designer/src/tutorial/selectors.ts b/protocol-designer/src/tutorial/selectors.ts index ec198989d88..a1185dbee77 100644 --- a/protocol-designer/src/tutorial/selectors.ts +++ b/protocol-designer/src/tutorial/selectors.ts @@ -1,7 +1,7 @@ import { createSelector } from 'reselect' import { THERMOCYCLER_MODULE_TYPE, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { timelineFrameBeforeActiveItem } from '../top-selectors/timelineFrames' import { @@ -85,7 +85,7 @@ export const shouldShowWasteChuteHint: Selector = createSelector( return false } const { newLocation } = unsavedForm - if (newLocation === WASTE_CHUTE_SLOT) { + if (newLocation === WASTE_CHUTE_CUTOUT) { return true } diff --git a/react-api-client/src/deck_configuration/__tests__/useCreateDeckConfigurationMutation.test.tsx b/react-api-client/src/deck_configuration/__tests__/useCreateDeckConfigurationMutation.test.tsx index d2e201fc0e0..200b05f9208 100644 --- a/react-api-client/src/deck_configuration/__tests__/useCreateDeckConfigurationMutation.test.tsx +++ b/react-api-client/src/deck_configuration/__tests__/useCreateDeckConfigurationMutation.test.tsx @@ -7,7 +7,7 @@ import { createDeckConfiguration } from '@opentrons/api-client' // import { // TRASH_BIN_LOAD_NAME, // WASTE_CHUTE_LOAD_NAME, -// WASTE_CHUTE_SLOT, +// WASTE_CHUTE_CUTOUT, // } from '@opentrons/shared-data' import { useHost } from '../../api' @@ -27,7 +27,7 @@ const mockUseHost = useHost as jest.MockedFunction // const mockDeckConfiguration = [ // { // fixtureId: 'mockFixtureWasteChuteId', -// fixtureLocation: 'D3', +// fixtureLocation: 'cutoutD3', // loadName: WASTE_CHUTE_LOAD_NAME, // }, // ] as DeckConfiguration diff --git a/shared-data/deck/types/schemaV4.ts b/shared-data/deck/types/schemaV4.ts index f81029da61e..04aeb85cb59 100644 --- a/shared-data/deck/types/schemaV4.ts +++ b/shared-data/deck/types/schemaV4.ts @@ -52,13 +52,20 @@ export type CutoutId = | 'cutoutA2' | 'cutoutA3' -export type CutoutFixtureId = +export type SingleSlotCutoutFixtureId = | 'singleLeftSlot' | 'singleCenterSlot' | 'singleRightSlot' - | 'stagingAreaRightSlot' - | 'trashBinAdapter' + +export type TrashBinAdapterCutoutFixtureId = 'trashBinAdapter' + +export type WasteChuteCutoutFixtureId = | 'wasteChuteRightAdapterCovered' | 'wasteChuteRightAdapterNoCover' | 'stagingAreaSlotWithWasteChuteRightAdapterCovered' | 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' + +export type CutoutFixtureId = + | SingleSlotCutoutFixtureId + | TrashBinAdapterCutoutFixtureId + | WasteChuteCutoutFixtureId diff --git a/shared-data/js/constants.ts b/shared-data/js/constants.ts index 51de83946cc..9ac6327bbcb 100644 --- a/shared-data/js/constants.ts +++ b/shared-data/js/constants.ts @@ -1,4 +1,4 @@ -import type { ModuleType } from './types' +import type { Cutout, ModuleType } from './types' // constants for dealing with robot coordinate system (eg in labwareTools) export const SLOT_LENGTH_MM = 127.76 // along X axis in robot coordinate system @@ -183,9 +183,126 @@ export const TC_MODULE_LOCATION_OT3: 'A1+B1' = 'A1+B1' export const WEIGHT_OF_96_CHANNEL: '~10kg' = '~10kg' -export const WASTE_CHUTE_SLOT: 'D3' = 'D3' +export const STAGING_AREA_CUTOUTS: Cutout[] = [ + 'cutoutA3', + 'cutoutB3', + 'cutoutC3', + 'cutoutD3', +] +export const WASTE_CHUTE_CUTOUT: 'cutoutD3' = 'cutoutD3' export const STAGING_AREA_LOAD_NAME = 'stagingArea' export const STANDARD_SLOT_LOAD_NAME = 'standardSlot' export const TRASH_BIN_LOAD_NAME = 'trashBin' export const WASTE_CHUTE_LOAD_NAME = 'wasteChute' + +export const A1_ADDRESSABLE_AREA: 'A1' = 'A1' +export const A2_ADDRESSABLE_AREA: 'A2' = 'A2' +export const A3_ADDRESSABLE_AREA: 'A3' = 'A3' +export const A4_ADDRESSABLE_AREA: 'A4' = 'A4' +export const B1_ADDRESSABLE_AREA: 'B1' = 'B1' +export const B2_ADDRESSABLE_AREA: 'B2' = 'B2' +export const B3_ADDRESSABLE_AREA: 'B3' = 'B3' +export const B4_ADDRESSABLE_AREA: 'B4' = 'B4' +export const C1_ADDRESSABLE_AREA: 'C1' = 'C1' +export const C2_ADDRESSABLE_AREA: 'C2' = 'C2' +export const C3_ADDRESSABLE_AREA: 'C3' = 'C3' +export const C4_ADDRESSABLE_AREA: 'C4' = 'C4' +export const D1_ADDRESSABLE_AREA: 'D1' = 'D1' +export const D2_ADDRESSABLE_AREA: 'D2' = 'D2' +export const D3_ADDRESSABLE_AREA: 'D3' = 'D3' +export const D4_ADDRESSABLE_AREA: 'D4' = 'D4' + +export const MOVABLE_TRASH_A1_ADDRESSABLE_AREA: 'movableTrashA1' = + 'movableTrashA1' +export const MOVABLE_TRASH_A3_ADDRESSABLE_AREA: 'movableTrashA3' = + 'movableTrashA3' +export const MOVABLE_TRASH_B1_ADDRESSABLE_AREA: 'movableTrashB1' = + 'movableTrashB1' +export const MOVABLE_TRASH_B3_ADDRESSABLE_AREA: 'movableTrashB3' = + 'movableTrashB3' +export const MOVABLE_TRASH_C1_ADDRESSABLE_AREA: 'movableTrashC1' = + 'movableTrashC1' +export const MOVABLE_TRASH_C3_ADDRESSABLE_AREA: 'movableTrashC3' = + 'movableTrashC3' +export const MOVABLE_TRASH_D1_ADDRESSABLE_AREA: 'movableTrashD1' = + 'movableTrashD1' +export const MOVABLE_TRASH_D3_ADDRESSABLE_AREA: 'movableTrashD3' = + 'movableTrashD3' + +export const ONE_AND_EIGHT_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA: '1and8ChannelWasteChute' = + '1and8ChannelWasteChute' +export const NINETY_SIX_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA: '96ChannelWasteChute' = + '96ChannelWasteChute' +export const GRIPPER_WASTE_CHUTE_ADDRESSABLE_AREA: 'gripperWasteChute' = + 'gripperWasteChute' + +export const FLEX_SINGLE_SLOT_ADDRESSABLE_AREAS = [ + A1_ADDRESSABLE_AREA, + A2_ADDRESSABLE_AREA, + A3_ADDRESSABLE_AREA, + B1_ADDRESSABLE_AREA, + B2_ADDRESSABLE_AREA, + B3_ADDRESSABLE_AREA, + C1_ADDRESSABLE_AREA, + C2_ADDRESSABLE_AREA, + C3_ADDRESSABLE_AREA, + D1_ADDRESSABLE_AREA, + D2_ADDRESSABLE_AREA, + D3_ADDRESSABLE_AREA, +] + +export const FLEX_STAGING_AREA_SLOT_ADDRESSABLE_AREAS = [ + A4_ADDRESSABLE_AREA, + B4_ADDRESSABLE_AREA, + C4_ADDRESSABLE_AREA, + D4_ADDRESSABLE_AREA, +] + +export const MOVABLE_TRASH_ADDRESSABLE_AREAS = [ + MOVABLE_TRASH_A1_ADDRESSABLE_AREA, + MOVABLE_TRASH_A3_ADDRESSABLE_AREA, + MOVABLE_TRASH_B1_ADDRESSABLE_AREA, + MOVABLE_TRASH_B3_ADDRESSABLE_AREA, + MOVABLE_TRASH_C1_ADDRESSABLE_AREA, + MOVABLE_TRASH_C3_ADDRESSABLE_AREA, + MOVABLE_TRASH_D1_ADDRESSABLE_AREA, + MOVABLE_TRASH_D3_ADDRESSABLE_AREA, +] + +export const WASTE_CHUTE_ADDRESSABLE_AREAS = [ + ONE_AND_EIGHT_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA, + NINETY_SIX_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA, + GRIPPER_WASTE_CHUTE_ADDRESSABLE_AREA, +] + +export const SINGLE_LEFT_SLOT_FIXTURE: 'singleLeftSlot' = 'singleLeftSlot' +export const SINGLE_CENTER_SLOT_FIXTURE: 'singleCenterSlot' = 'singleCenterSlot' +export const SINGLE_RIGHT_SLOT_FIXTURE: 'singleRightSlot' = 'singleRightSlot' + +export const STAGING_AREA_RIGHT_SLOT_FIXTURE: 'stagingAreaRightSlot' = + 'stagingAreaRightSlot' + +export const TRASH_BIN_ADAPTER_FIXTURE: 'trashBinAdapter' = 'trashBinAdapter' + +export const WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE: 'wasteChuteRightAdapterCovered' = + 'wasteChuteRightAdapterCovered' +export const WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE: 'wasteChuteRightAdapterNoCover' = + 'wasteChuteRightAdapterNoCover' +export const STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE: 'stagingAreaSlotWithWasteChuteRightAdapterCovered' = + 'stagingAreaSlotWithWasteChuteRightAdapterCovered' +export const STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE: 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' = + 'stagingAreaSlotWithWasteChuteRightAdapterNoCover' + +export const SINGLE_SLOT_FIXTURES = [ + SINGLE_LEFT_SLOT_FIXTURE, + SINGLE_CENTER_SLOT_FIXTURE, + SINGLE_RIGHT_SLOT_FIXTURE, +] + +export const WASTE_CHUTE_FIXTURES = [ + WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE, + WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE, + STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_COVERED_FIXTURE, + STAGING_AREA_SLOT_WITH_WASTE_CHUTE_RIGHT_ADAPTER_NO_COVER_FIXTURE, +] diff --git a/shared-data/js/fixtures.ts b/shared-data/js/fixtures.ts index d424464e43d..39ae5b9fe8d 100644 --- a/shared-data/js/fixtures.ts +++ b/shared-data/js/fixtures.ts @@ -1,9 +1,97 @@ import { + FLEX_ROBOT_TYPE, STAGING_AREA_LOAD_NAME, TRASH_BIN_LOAD_NAME, WASTE_CHUTE_LOAD_NAME, } from './constants' -import type { FixtureLoadName } from './types' +import type { + AddressableArea, + CoordinateTuple, + Cutout, + DeckDefinition, + FixtureLoadName, + OT2Cutout, +} from './types' + +export function getCutoutDisplayName(cutout: Cutout): string { + return cutout.replace('cutout', '') +} + +// mapping of OT-2 deck slots to cutouts +export const OT2_CUTOUT_BY_SLOT_ID: { [slotId: string]: OT2Cutout } = { + 1: 'cutout1', + 2: 'cutout2', + 3: 'cutout3', + 4: 'cutout4', + 5: 'cutout5', + 6: 'cutout6', + 7: 'cutout7', + 8: 'cutout8', + 9: 'cutout9', + 10: 'cutout10', + 11: 'cutout11', +} + +// mapping of Flex deck slots to cutouts +export const FLEX_CUTOUT_BY_SLOT_ID: { [slotId: string]: Cutout } = { + A1: 'cutoutA1', + A2: 'cutoutA2', + A3: 'cutoutA3', + A4: 'cutoutA3', + B1: 'cutoutB1', + B2: 'cutoutB2', + B3: 'cutoutB3', + B4: 'cutoutB3', + C1: 'cutoutC1', + C2: 'cutoutC2', + C3: 'cutoutC3', + C4: 'cutoutC3', + D1: 'cutoutD1', + D2: 'cutoutD2', + D3: 'cutoutD3', + D4: 'cutoutD3', +} + +// returns the position associated with a slot id +export function getPositionFromSlotId( + slotId: string, + deckDef: DeckDefinition +): CoordinateTuple | null { + const cutoutWithSlot = + deckDef.robot.model === FLEX_ROBOT_TYPE + ? FLEX_CUTOUT_BY_SLOT_ID[slotId] + : OT2_CUTOUT_BY_SLOT_ID[slotId] + + const cutoutPosition = + deckDef.locations.cutouts.find(cutout => cutout.id === cutoutWithSlot) + ?.position ?? null + + // adjust for offset from cutout + const offsetFromCutoutFixture = getAddressableAreaFromSlotId(slotId, deckDef) + ?.offsetFromCutoutFixture ?? [0, 0, 0] + + const slotPosition: CoordinateTuple | null = + cutoutPosition != null + ? [ + cutoutPosition[0] + offsetFromCutoutFixture[0], + cutoutPosition[1] + offsetFromCutoutFixture[1], + cutoutPosition[2] + offsetFromCutoutFixture[2], + ] + : null + + return slotPosition +} + +export function getAddressableAreaFromSlotId( + slotId: string, + deckDef: DeckDefinition +): AddressableArea | null { + return ( + deckDef.locations.addressableAreas.find( + addressableArea => addressableArea.id === slotId + ) ?? null + ) +} export function getFixtureDisplayName(loadName: FixtureLoadName): string { if (loadName === STAGING_AREA_LOAD_NAME) { @@ -16,3 +104,41 @@ export function getFixtureDisplayName(loadName: FixtureLoadName): string { return 'Slot' } } + +const STANDARD_OT2_SLOTS = [ + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '10', + '11', +] + +const STANDARD_FLEX_SLOTS = [ + 'A1', + 'A2', + 'A3', + 'B1', + 'B2', + 'B3', + 'C1', + 'C2', + 'C3', + 'D1', + 'D2', + 'D3', +] + +export const isAddressableAreaStandardSlot = ( + addressableAreaId: string, + deckDef: DeckDefinition +): boolean => + (deckDef.robot.model === FLEX_ROBOT_TYPE + ? STANDARD_FLEX_SLOTS + : STANDARD_OT2_SLOTS + ).includes(addressableAreaId) diff --git a/shared-data/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts b/shared-data/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts index 8a9609b4baf..840753899ce 100644 --- a/shared-data/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts +++ b/shared-data/js/helpers/__tests__/getDeckDefFromLoadedLabware.test.ts @@ -1,5 +1,5 @@ -import ot2DeckDef from '../../../deck/definitions/3/ot2_standard.json' -import ot3DeckDef from '../../../deck/definitions/3/ot3_standard.json' +import ot2DeckDef from '../../../deck/definitions/4/ot2_standard.json' +import ot3DeckDef from '../../../deck/definitions/4/ot3_standard.json' import { getDeckDefFromRobotType } from '..' describe('getDeckDefFromRobotType', () => { diff --git a/shared-data/js/helpers/index.ts b/shared-data/js/helpers/index.ts index c686898f9bc..a0cb30f9eb9 100644 --- a/shared-data/js/helpers/index.ts +++ b/shared-data/js/helpers/index.ts @@ -2,8 +2,6 @@ import assert from 'assert' import uniq from 'lodash/uniq' import { OPENTRONS_LABWARE_NAMESPACE } from '../constants' -import standardOt2DeckDefv3 from '../../deck/definitions/3/ot2_standard.json' -import standardFlexDeckDefv3 from '../../deck/definitions/3/ot3_standard.json' import standardOt2DeckDef from '../../deck/definitions/4/ot2_standard.json' import standardFlexDeckDef from '../../deck/definitions/4/ot3_standard.json' import type { @@ -206,7 +204,7 @@ export const getSlotHasMatingSurfaceUnitVector = ( deckDef: DeckDefinition, slotNumber: string ): boolean => { - const matingSurfaceUnitVector = deckDef.locations.orderedSlots.find( + const matingSurfaceUnitVector = deckDef.locations.addressableAreas.find( orderedSlot => orderedSlot.id === slotNumber )?.matingSurfaceUnitVector @@ -226,7 +224,8 @@ export const getAreSlotsHorizontallyAdjacent = ( if (isNaN(slotBNumber) || isNaN(slotANumber)) { return false } - const orderedSlots = standardOt2DeckDefv3.locations.orderedSlots + // TODO(bh, 2023-11-03): is this OT-2 only? + const orderedSlots = standardOt2DeckDef.locations.cutouts // intentionally not substracting by 1 because trash (slot 12) should not count const numSlots = orderedSlots.length @@ -262,7 +261,8 @@ export const getAreSlotsVerticallyAdjacent = ( if (isNaN(slotBNumber) || isNaN(slotANumber)) { return false } - const orderedSlots = standardOt2DeckDefv3.locations.orderedSlots + // TODO(bh, 2023-11-03): is this OT-2 only? + const orderedSlots = standardOt2DeckDef.locations.cutouts // intentionally not substracting by 1 because trash (slot 12) should not count const numSlots = orderedSlots.length @@ -352,10 +352,11 @@ export const getDeckDefFromRobotType = ( ): DeckDefinition => { // @ts-expect-error imported JSON not playing nice with TS. see https://github.com/microsoft/TypeScript/issues/32063 return robotType === 'OT-3 Standard' - ? standardFlexDeckDefv3 - : standardOt2DeckDefv3 + ? standardFlexDeckDef + : standardOt2DeckDef } +// TODO(bh, 2023-11-09): delete this function export const getDeckDefFromRobotTypeV4 = ( robotType: RobotType ): DeckDefinition => { diff --git a/shared-data/js/types.ts b/shared-data/js/types.ts index 28b509a7f26..3d0ad89ff3e 100644 --- a/shared-data/js/types.ts +++ b/shared-data/js/types.ts @@ -291,14 +291,20 @@ export interface CutoutFixture { providesAddressableAreas: Record } +type AreaType = 'slot' | 'movableTrash' | 'wasteChute' | 'fixedTrash' + export interface AddressableArea { id: AddressableAreaName - areaType: 'slot' | 'movableTrash' | 'fixedTrash' | 'wasteChute' - matingSurfaceUnitVector: UnitVectorTuple - offsetFromCutoutFixture: UnitVectorTuple + areaType: AreaType + offsetFromCutoutFixture: CoordinateTuple boundingBox: Dimensions displayName: string compatibleModuleTypes: ModuleType[] + ableToDropLabware?: boolean + ableToDropTips?: boolean + dropLabwareOffset?: CoordinateTuple + dropTipsOffset?: CoordinateTuple + matingSurfaceUnitVector?: UnitVectorTuple } export interface DeckLocations { @@ -313,7 +319,7 @@ export interface DeckMetadata { tags: string[] } -export interface DeckDefinition { +export interface DeckDefinitionV3 { otId: string cornerOffsetFromOrigin: CoordinateTuple dimensions: CoordinateTuple @@ -324,6 +330,37 @@ export interface DeckDefinition { layers: INode[] } +export interface DeckCutout { + id: string + position: CoordinateTuple + displayName: string +} + +export interface LegacyFixture { + id: string + // TODO: is this cutout location? + slot: string + labware: string + displayName: string +} + +export interface DeckLocationsV4 { + addressableAreas: AddressableArea[] + calibrationPoints: DeckCalibrationPoint[] + cutouts: DeckCutout[] + legacyFixtures: LegacyFixture[] +} + +export interface DeckDefinition { + otId: string + cornerOffsetFromOrigin: CoordinateTuple + dimensions: CoordinateTuple + robot: DeckRobot + locations: DeckLocationsV4 + metadata: DeckMetadata + cutoutFixtures: CutoutFixture[] +} + export interface ModuleDimensions { bareOverallHeight: number overLabwareHeight: number @@ -550,8 +587,35 @@ export type StatusBarAnimation = export type StatusBarAnimations = StatusBarAnimation[] -// TODO(bh, 2023-09-28): refine types when settled export type Cutout = + | 'cutoutA1' + | 'cutoutB1' + | 'cutoutC1' + | 'cutoutD1' + | 'cutoutA2' + | 'cutoutB2' + | 'cutoutC2' + | 'cutoutD2' + | 'cutoutA3' + | 'cutoutB3' + | 'cutoutC3' + | 'cutoutD3' + +export type OT2Cutout = + | 'cutout1' + | 'cutout2' + | 'cutout3' + | 'cutout4' + | 'cutout5' + | 'cutout6' + | 'cutout7' + | 'cutout8' + | 'cutout9' + | 'cutout10' + | 'cutout11' + | 'cutout12' + +export type FlexSlot = | 'A1' | 'B1' | 'C1' @@ -564,6 +628,10 @@ export type Cutout = | 'B3' | 'C3' | 'D3' + | 'A4' + | 'B4' + | 'C4' + | 'D4' export interface Fixture { fixtureId: string diff --git a/step-generation/src/__tests__/moveLabware.test.ts b/step-generation/src/__tests__/moveLabware.test.ts index b57f3d7d200..f6d8ac69c1f 100644 --- a/step-generation/src/__tests__/moveLabware.test.ts +++ b/step-generation/src/__tests__/moveLabware.test.ts @@ -1,6 +1,6 @@ import { HEATERSHAKER_MODULE_TYPE, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { getInitialRobotStateStandard, @@ -249,7 +249,7 @@ describe('moveLabware', () => { mockWasteChuteId: { name: 'wasteChute', id: mockWasteChuteId, - location: WASTE_CHUTE_SLOT, + location: WASTE_CHUTE_CUTOUT, }, }, } as InvariantContext @@ -266,7 +266,7 @@ describe('moveLabware', () => { commandCreatorFnName: 'moveLabware', labware: TIPRACK_1, useGripper: true, - newLocation: { slotName: WASTE_CHUTE_SLOT }, + newLocation: { slotName: WASTE_CHUTE_CUTOUT }, } as MoveLabwareArgs const result = moveLabware( @@ -288,7 +288,7 @@ describe('moveLabware', () => { mockWasteChuteId: { name: 'wasteChute', id: mockWasteChuteId, - location: WASTE_CHUTE_SLOT, + location: WASTE_CHUTE_CUTOUT, }, }, } as InvariantContext @@ -304,7 +304,7 @@ describe('moveLabware', () => { commandCreatorFnName: 'moveLabware', labware: SOURCE_LABWARE, useGripper: true, - newLocation: { slotName: WASTE_CHUTE_SLOT }, + newLocation: { slotName: WASTE_CHUTE_CUTOUT }, } as MoveLabwareArgs const result = moveLabware( diff --git a/step-generation/src/__tests__/wasteChuteCommandsUtil.test.ts b/step-generation/src/__tests__/wasteChuteCommandsUtil.test.ts index b202fd2e33d..c54134c9288 100644 --- a/step-generation/src/__tests__/wasteChuteCommandsUtil.test.ts +++ b/step-generation/src/__tests__/wasteChuteCommandsUtil.test.ts @@ -1,4 +1,4 @@ -import { WASTE_CHUTE_SLOT } from '@opentrons/shared-data' +import { WASTE_CHUTE_CUTOUT } from '@opentrons/shared-data' import { getInitialRobotStateStandard, makeContext, @@ -44,7 +44,7 @@ describe('wasteChuteCommandsUtil', () => { additionalEquipmentEntities: { [mockWasteChuteId]: { name: 'wasteChute', - location: WASTE_CHUTE_SLOT, + location: WASTE_CHUTE_CUTOUT, id: 'mockId', }, }, diff --git a/step-generation/src/commandCreators/atomic/moveLabware.ts b/step-generation/src/commandCreators/atomic/moveLabware.ts index d14814fa3b0..3f3929ecf81 100644 --- a/step-generation/src/commandCreators/atomic/moveLabware.ts +++ b/step-generation/src/commandCreators/atomic/moveLabware.ts @@ -3,7 +3,7 @@ import { HEATERSHAKER_MODULE_TYPE, LabwareMovementStrategy, THERMOCYCLER_MODULE_TYPE, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import * as errorCreators from '../../errorCreators' import * as warningCreators from '../../warningCreators' @@ -44,7 +44,7 @@ export const moveLabware: CommandCreator = ( const newLocationInWasteChute = newLocation !== 'offDeck' && 'slotName' in newLocation && - newLocation.slotName === WASTE_CHUTE_SLOT + newLocation.slotName === WASTE_CHUTE_CUTOUT if (!labware || !prevRobotState.labware[labware]) { errors.push( diff --git a/step-generation/src/constants.ts b/step-generation/src/constants.ts index 17e278eadc7..d8dfa2142c4 100644 --- a/step-generation/src/constants.ts +++ b/step-generation/src/constants.ts @@ -2,6 +2,8 @@ import { MAGNETIC_MODULE_V1, TEMPERATURE_MODULE_V1, } from '@opentrons/shared-data' +import type { ModuleModel } from '@opentrons/shared-data' + // Temperature statuses export const TEMPERATURE_DEACTIVATED: 'TEMPERATURE_DEACTIVATED' = 'TEMPERATURE_DEACTIVATED' @@ -10,7 +12,7 @@ export const TEMPERATURE_AT_TARGET: 'TEMPERATURE_AT_TARGET' = export const TEMPERATURE_APPROACHING_TARGET: 'TEMPERATURE_APPROACHING_TARGET' = 'TEMPERATURE_APPROACHING_TARGET' export const AIR_GAP_OFFSET_FROM_TOP = 1 -export const MODULES_WITH_COLLISION_ISSUES = [ +export const MODULES_WITH_COLLISION_ISSUES: ModuleModel[] = [ MAGNETIC_MODULE_V1, TEMPERATURE_MODULE_V1, ] diff --git a/step-generation/src/utils/misc.ts b/step-generation/src/utils/misc.ts index 8dd2df669ff..0946cea97ee 100644 --- a/step-generation/src/utils/misc.ts +++ b/step-generation/src/utils/misc.ts @@ -8,7 +8,7 @@ import { getLabwareDefURI, getWellsDepth, getWellNamePerMultiTip, - WASTE_CHUTE_SLOT, + WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import { blowout } from '../commandCreators/atomic/blowout' import { curryCommandCreator } from './curryCommandCreator' @@ -343,7 +343,7 @@ export const getHasWasteChute = ( ): boolean => { return Object.values(additionalEquipmentEntities).some( additionalEquipmentEntity => - additionalEquipmentEntity.location === WASTE_CHUTE_SLOT && + additionalEquipmentEntity.location === WASTE_CHUTE_CUTOUT && additionalEquipmentEntity.name === 'wasteChute' ) } diff --git a/step-generation/src/utils/modulePipetteCollision.ts b/step-generation/src/utils/modulePipetteCollision.ts index 745becfbe02..2ab09bbb109 100644 --- a/step-generation/src/utils/modulePipetteCollision.ts +++ b/step-generation/src/utils/modulePipetteCollision.ts @@ -36,7 +36,6 @@ export const modulePipetteCollision = (args: { const labwareInDangerZone = Object.keys(invariantContext.moduleEntities).some( moduleId => { const moduleModel = invariantContext.moduleEntities[moduleId].model - // @ts-expect-error(SA, 2021-05-03): need to type narrow if (MODULES_WITH_COLLISION_ISSUES.includes(moduleModel)) { const moduleSlot: DeckSlot | null | undefined = prevRobotState.modules[moduleId]?.slot From daf6ea9e53b29a6449585dad75c7aaa3a7c6bdd6 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:20:12 -0500 Subject: [PATCH 55/65] feat(app): add inPlace and moveToAddressableArea command text (#13958) closes RAUT-851 Generate different commands from dropping tips in other locations if we select the waste chute as our drop tip location. For the waste chute, we generate moveToAddressableArea followed by dropTipInPlace commands. --- .../en/protocol_command_text.json | 4 + .../CommandText/PipettingCommandText.tsx | 42 +++++----- .../__tests__/CommandText.test.tsx | 82 +++++++++++++++++++ app/src/organisms/CommandText/index.tsx | 46 ++++++++++- 4 files changed, 151 insertions(+), 23 deletions(-) diff --git a/app/src/assets/localization/en/protocol_command_text.json b/app/src/assets/localization/en/protocol_command_text.json index 8d84b9e341f..167b64c08ed 100644 --- a/app/src/assets/localization/en/protocol_command_text.json +++ b/app/src/assets/localization/en/protocol_command_text.json @@ -3,6 +3,7 @@ "adapter_in_slot": "{{adapter}} in {{slot}}", "aspirate": "Aspirating {{volume}} µL from well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", "blowout": "Blowing out at well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "blowout_in_place": "Blowing out in place at {{flow_rate}} µL/sec", "closing_tc_lid": "Closing Thermocycler lid", "comment": "Comment", "configure_for_volume": "Configure {{pipette}} to aspirate {{volume}} µL", @@ -16,7 +17,9 @@ "disengaging_magnetic_module": "Disengaging Magnetic Module", "dispense_push_out": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec and pushing out {{push_out_volume}} µL", "dispense": "Dispensing {{volume}} µL into well {{well_name}} of {{labware}} in {{labware_location}} at {{flow_rate}} µL/sec", + "dispense_in_place": "Dispensing {{volume}} µL in place at {{flow_rate}} µL/sec", "drop_tip": "Dropping tip in {{well_name}} of {{labware}}", + "drop_tip_in_place": "Dropping tip in place", "engaging_magnetic_module": "Engaging Magnetic Module", "fixed_trash": "Fixed Trash", "home_gantry": "Homing all gantry, pipette, and plunger axes", @@ -31,6 +34,7 @@ "move_to_coordinates": "Moving to (X: {{x}}, Y: {{y}}, Z: {{z}})", "move_to_slot": "Moving to Slot {{slot_name}}", "move_to_well": "Moving to well {{well_name}} of {{labware}} in {{labware_location}}", + "move_to_addressable_area": "Moving to {{addressable_area}} at {{speed}} mm/s at {{height}} mm high", "notes": "notes", "off_deck": "off deck", "offdeck": "offdeck", diff --git a/app/src/organisms/CommandText/PipettingCommandText.tsx b/app/src/organisms/CommandText/PipettingCommandText.tsx index 8aff25b4da3..defd89fbab9 100644 --- a/app/src/organisms/CommandText/PipettingCommandText.tsx +++ b/app/src/organisms/CommandText/PipettingCommandText.tsx @@ -1,15 +1,11 @@ import { useTranslation } from 'react-i18next' + import { CompletedProtocolAnalysis, - AspirateRunTimeCommand, - DispenseRunTimeCommand, - BlowoutRunTimeCommand, - MoveToWellRunTimeCommand, - DropTipRunTimeCommand, - PickUpTipRunTimeCommand, getLabwareDefURI, RobotType, } from '@opentrons/shared-data' + import { getLabwareDefinitionsFromCommands } from '../LabwarePositionCheck/utils/labware' import { getLoadedLabware } from './utils/accessors' import { @@ -18,15 +14,10 @@ import { getFinalLabwareLocation, } from './utils' -type PipettingRunTimeCommmand = - | AspirateRunTimeCommand - | DispenseRunTimeCommand - | BlowoutRunTimeCommand - | MoveToWellRunTimeCommand - | DropTipRunTimeCommand - | PickUpTipRunTimeCommand +import type { PipettingRunTimeCommand } from '@opentrons/shared-data' + interface PipettingCommandTextProps { - command: PipettingRunTimeCommmand + command: PipettingRunTimeCommand robotSideAnalysis: CompletedProtocolAnalysis robotType: RobotType } @@ -38,7 +29,10 @@ export const PipettingCommandText = ({ }: PipettingCommandTextProps): JSX.Element | null => { const { t } = useTranslation('protocol_command_text') - const { labwareId, wellName } = command.params + const labwareId = + 'labwareId' in command.params ? command.params.labwareId : '' + const wellName = 'wellName' in command.params ? command.params.wellName : '' + const allPreviousCommands = robotSideAnalysis.commands.slice( 0, robotSideAnalysis.commands.findIndex(c => c.id === command.id) @@ -95,13 +89,6 @@ export const PipettingCommandText = ({ flow_rate: flowRate, }) } - case 'moveToWell': { - return t('move_to_well', { - well_name: wellName, - labware: getLabwareName(robotSideAnalysis, labwareId), - labware_location: displayLocation, - }) - } case 'dropTip': { const loadedLabware = getLoadedLabware(robotSideAnalysis, labwareId) const labwareDefinitions = getLabwareDefinitionsFromCommands( @@ -128,6 +115,17 @@ export const PipettingCommandText = ({ labware_location: displayLocation, }) } + case 'dropTipInPlace': { + return t('drop_tip_in_place') + } + case 'dispenseInPlace': { + const { volume, flowRate } = command.params + return t('dispense_in_place', { volume: volume, flow_rate: flowRate }) + } + case 'blowOutInPlace': { + const { flowRate } = command.params + return t('blowout_in_place', { flow_rate: flowRate }) + } default: { console.warn( 'PipettingCommandText encountered a command with an unrecognized commandType: ', diff --git a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx index 28ef08f940f..242c6939eb4 100644 --- a/app/src/organisms/CommandText/__tests__/CommandText.test.tsx +++ b/app/src/organisms/CommandText/__tests__/CommandText.test.tsx @@ -1,7 +1,11 @@ import * as React from 'react' import { renderWithProviders } from '@opentrons/components' import { + BlowoutInPlaceRunTimeCommand, + DispenseInPlaceRunTimeCommand, + DropTipInPlaceRunTimeCommand, FLEX_ROBOT_TYPE, + MoveToAddressableAreaRunTimeCommand, PrepareToAspirateRunTimeCommand, } from '@opentrons/shared-data' import { i18n } from '../../../i18n' @@ -85,6 +89,26 @@ describe('CommandText', () => { ) } }) + it('renders correct text for dispenseInPlace', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Dispensing 50 µL in place at 300 µL/sec') + }) it('renders correct text for blowout', () => { const dispenseCommand = mockRobotSideAnalysis.commands.find( c => c.commandType === 'dispense' @@ -108,6 +132,25 @@ describe('CommandText', () => { ) } }) + it('renders correct text for blowOutInPlace', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Blowing out in place at 300 µL/sec') + }) it('renders correct text for moveToWell', () => { const dispenseCommand = mockRobotSideAnalysis.commands.find( c => c.commandType === 'aspirate' @@ -129,6 +172,27 @@ describe('CommandText', () => { getByText('Moving to well A1 of NEST 1 Well Reservoir 195 mL in Slot 5') } }) + it('renders correct text for moveToAddressableArea', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Moving to D3 at 200 mm/s at 100 mm high') + }) it('renders correct text for configureForVolume', () => { const command = { commandType: 'configureForVolume', @@ -204,6 +268,24 @@ describe('CommandText', () => { )[0] getByText('Returning tip to A1 of Opentrons 96 Tip Rack 300 µL in Slot 9') }) + it('renders correct text for dropTipInPlace', () => { + const { getByText } = renderWithProviders( + , + { i18nInstance: i18n } + )[0] + getByText('Dropping tip in place') + }) it('renders correct text for pickUpTip', () => { const command = mockRobotSideAnalysis.commands.find( c => c.commandType === 'pickUpTip' diff --git a/app/src/organisms/CommandText/index.tsx b/app/src/organisms/CommandText/index.tsx index 67e76526ab1..00e9bca5808 100644 --- a/app/src/organisms/CommandText/index.tsx +++ b/app/src/organisms/CommandText/index.tsx @@ -3,6 +3,11 @@ import { useTranslation } from 'react-i18next' import { Flex, DIRECTION_COLUMN, SPACING } from '@opentrons/components' import { getPipetteNameSpecs, RunTimeCommand } from '@opentrons/shared-data' +import { + getLabwareName, + getLabwareDisplayLocation, + getFinalLabwareLocation, +} from './utils' import { StyledText } from '../../atoms/text' import { LoadCommandText } from './LoadCommandText' import { PipettingCommandText } from './PipettingCommandText' @@ -50,9 +55,11 @@ export function CommandText(props: Props): JSX.Element | null { switch (command.commandType) { case 'aspirate': case 'dispense': + case 'dispenseInPlace': case 'blowout': - case 'moveToWell': + case 'blowOutInPlace': case 'dropTip': + case 'dropTipInPlace': case 'pickUpTip': { return ( @@ -138,6 +145,31 @@ export function CommandText(props: Props): JSX.Element | null { ) } + case 'moveToWell': { + const { wellName, labwareId } = command.params + const allPreviousCommands = robotSideAnalysis.commands.slice( + 0, + robotSideAnalysis.commands.findIndex(c => c.id === command.id) + ) + const labwareLocation = getFinalLabwareLocation( + labwareId, + allPreviousCommands + ) + const displayLocation = + labwareLocation != null + ? getLabwareDisplayLocation( + robotSideAnalysis, + labwareLocation, + t, + robotType + ) + : '' + return t('move_to_well', { + well_name: wellName, + labware: getLabwareName(robotSideAnalysis, labwareId), + labware_location: displayLocation, + }) + } case 'moveLabware': { return ( @@ -182,6 +214,18 @@ export function CommandText(props: Props): JSX.Element | null { ) } + case 'moveToAddressableArea': { + const { addressableAreaName, speed, minimumZHeight } = command.params + return ( + + {t('move_to_addressable_area', { + addressable_area: addressableAreaName, + speed: speed, + height: minimumZHeight, + })} + + ) + } case 'touchTip': case 'home': case 'savePosition': From 8e24967977b2c67d46dfe91f849cb7fd79281838 Mon Sep 17 00:00:00 2001 From: Nick Diehl <47604184+ncdiehl11@users.noreply.github.com> Date: Mon, 13 Nov 2023 11:28:53 -0500 Subject: [PATCH 56/65] fix(app): robot settings and wizard required equipment styling (#13928) closes RQA-1635 closes RQA-1639 Add divider above first and below last wizard required equipment element. Add padding between calibration description and download cal logs button --- app/src/molecules/WizardRequiredEquipmentList/index.tsx | 5 ++--- .../RobotSettingsCalibration/CalibrationDataDownload.tsx | 6 +++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/molecules/WizardRequiredEquipmentList/index.tsx b/app/src/molecules/WizardRequiredEquipmentList/index.tsx index 35b87750b4b..4d295203b5c 100644 --- a/app/src/molecules/WizardRequiredEquipmentList/index.tsx +++ b/app/src/molecules/WizardRequiredEquipmentList/index.tsx @@ -83,12 +83,11 @@ export function WizardRequiredEquipmentList( > {t('you_will_need')}
    - {equipmentList.length > 1 ? : null} - {equipmentList.map((requiredEquipmentProps, index) => ( + + {equipmentList.map(requiredEquipmentProps => ( ))} {footer != null ? ( diff --git a/app/src/organisms/RobotSettingsCalibration/CalibrationDataDownload.tsx b/app/src/organisms/RobotSettingsCalibration/CalibrationDataDownload.tsx index 4755352fdee..4a261b331d9 100644 --- a/app/src/organisms/RobotSettingsCalibration/CalibrationDataDownload.tsx +++ b/app/src/organisms/RobotSettingsCalibration/CalibrationDataDownload.tsx @@ -91,7 +91,11 @@ export function CalibrationDataDownload({ } return ( - + {isFlex From 9562fab5768ca082a60a0aeda729a2870ec100f4 Mon Sep 17 00:00:00 2001 From: Shlok Amin Date: Mon, 13 Nov 2023 16:40:24 -0500 Subject: [PATCH 57/65] feat(shared-data): add 8 moveable trashes (#13959) closes RSS-397 --- .../deck/definitions/4/ot3_standard.json | 109 ++++++++++++++++-- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/shared-data/deck/definitions/4/ot3_standard.json b/shared-data/deck/definitions/4/ot3_standard.json index 333fd6d59c3..87ba7e78e14 100644 --- a/shared-data/deck/definitions/4/ot3_standard.json +++ b/shared-data/deck/definitions/4/ot3_standard.json @@ -250,7 +250,98 @@ "compatibleModuleTypes": [] }, { - "id": "movableTrash", + "id": "movableTrashD1", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashC1", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashB1", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashA1", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashD3", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashC3", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashB3", + "areaType": "movableTrash", + "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "boundingBox": { + "xDimension": 246.5, + "yDimension": 91.5, + "zDimension": 40 + }, + "displayName": "Trash Bin", + "ableToDropTips": true, + "dropTipsOffset": [123.25, 45.75, 40.0] + }, + { + "id": "movableTrashA3", "areaType": "movableTrash", "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], "boundingBox": { @@ -433,14 +524,14 @@ ], "displayName": "Slot With Movable Trash", "providesAddressableAreas": { - "cutoutD1": ["movableTrash"], - "cutoutC1": ["movableTrash"], - "cutoutB1": ["movableTrash"], - "cutoutA1": ["movableTrash"], - "cutoutD3": ["movableTrash"], - "cutoutC3": ["movableTrash"], - "cutoutB3": ["movableTrash"], - "cutoutA3": ["movableTrash"] + "cutoutD1": ["movableTrashD1"], + "cutoutC1": ["movableTrashC1"], + "cutoutB1": ["movableTrashB1"], + "cutoutA1": ["movableTrashA1"], + "cutoutD3": ["movableTrashD3"], + "cutoutC3": ["movableTrashC3"], + "cutoutB3": ["movableTrashB3"], + "cutoutA3": ["movableTrashA3"] } }, { From 59eb6773c95d7575319564928b2f5737505fb4b7 Mon Sep 17 00:00:00 2001 From: Max Marrone Date: Mon, 13 Nov 2023 17:37:54 -0500 Subject: [PATCH 58/65] refactor(api): Delete unused opentrons.containers module #13973 --- .../opentrons/config/containers/__init__.py | 0 .../config/containers/default-containers.json | 27097 ---------------- 2 files changed, 27097 deletions(-) delete mode 100644 api/src/opentrons/config/containers/__init__.py delete mode 100644 api/src/opentrons/config/containers/default-containers.json diff --git a/api/src/opentrons/config/containers/__init__.py b/api/src/opentrons/config/containers/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/api/src/opentrons/config/containers/default-containers.json b/api/src/opentrons/config/containers/default-containers.json deleted file mode 100644 index 44824a024a4..00000000000 --- a/api/src/opentrons/config/containers/default-containers.json +++ /dev/null @@ -1,27097 +0,0 @@ -{ - "containers": { - "temperature-plate": { - "origin-offset": { - "x": 11.24, - "y": 14.34, - "z": 97 - }, - "locations":{} - }, - - "tube-rack-5ml-96": { - "locations": { - "A1": { - "y": 0, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B1": { - "y": 0, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C1": { - "y": 0, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D1": { - "y": 0, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E1": { - "y": 0, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F1": { - "y": 0, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G1": { - "y": 0, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H1": { - "y": 0, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A2": { - "y": 18, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B2": { - "y": 18, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C2": { - "y": 18, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D2": { - "y": 18, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E2": { - "y": 18, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F2": { - "y": 18, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G2": { - "y": 18, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H2": { - "y": 18, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A3": { - "y": 36, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B3": { - "y": 36, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C3": { - "y": 36, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D3": { - "y": 36, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E3": { - "y": 36, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F3": { - "y": 36, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G3": { - "y": 36, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H3": { - "y": 36, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A4": { - "y": 54, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B4": { - "y": 54, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C4": { - "y": 54, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D4": { - "y": 54, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E4": { - "y": 54, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F4": { - "y": 54, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G4": { - "y": 54, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H4": { - "y": 54, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A5": { - "y": 72, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B5": { - "y": 72, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C5": { - "y": 72, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D5": { - "y": 72, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E5": { - "y": 72, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F5": { - "y": 72, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G5": { - "y": 72, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H5": { - "y": 72, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A6": { - "y": 90, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B6": { - "y": 90, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C6": { - "y": 90, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D6": { - "y": 90, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E6": { - "y": 90, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F6": { - "y": 90, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G6": { - "y": 90, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H6": { - "y": 90, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A7": { - "y": 108, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B7": { - "y": 108, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C7": { - "y": 108, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D7": { - "y": 108, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E7": { - "y": 108, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F7": { - "y": 108, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G7": { - "y": 108, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H7": { - "y": 108, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A8": { - "y": 126, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B8": { - "y": 126, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C8": { - "y": 126, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D8": { - "y": 126, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E8": { - "y": 126, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F8": { - "y": 126, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G8": { - "y": 126, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H8": { - "y": 126, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A9": { - "y": 144, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B9": { - "y": 144, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C9": { - "y": 144, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D9": { - "y": 144, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E9": { - "y": 144, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F9": { - "y": 144, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G9": { - "y": 144, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H9": { - "y": 144, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A10": { - "y": 162, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B10": { - "y": 162, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C10": { - "y": 162, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D10": { - "y": 162, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E10": { - "y": 162, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F10": { - "y": 162, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G10": { - "y": 162, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H10": { - "y": 162, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A11": { - "y": 180, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B11": { - "y": 180, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C11": { - "y": 180, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D11": { - "y": 180, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E11": { - "y": 180, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F11": { - "y": 180, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G11": { - "y": 180, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H11": { - "y": 180, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - - "A12": { - "y": 198, - "x": 0, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "B12": { - "y": 198, - "x": 18, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "C12": { - "y": 198, - "x": 36, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "D12": { - "y": 198, - "x": 54, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "E12": { - "y": 198, - "x": 72, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "F12": { - "y": 198, - "x": 90, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "G12": { - "y": 198, - "x": 108, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - }, - "H12": { - "y": 198, - "x": 126, - "z": 0, - "depth": 72, - "diameter": 15, - "total-liquid-volume": 5000 - } - - } - }, - - "tube-rack-2ml-9x9": { - "locations": { - "A1": { - "y": 0, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B1": { - "y": 0, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C1": { - "y": 0, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D1": { - "y": 0, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E1": { - "y": 0, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F1": { - "y": 0, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G1": { - "y": 0, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H1": { - "y": 0, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I1": { - "y": 0, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A2": { - "y": 14.75, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B2": { - "y": 14.75, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C2": { - "y": 14.75, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D2": { - "y": 14.75, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E2": { - "y": 14.75, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F2": { - "y": 14.75, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G2": { - "y": 14.75, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H2": { - "y": 14.75, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I2": { - "y": 14.75, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A3": { - "y": 29.5, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B3": { - "y": 29.5, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C3": { - "y": 29.5, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D3": { - "y": 29.5, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E3": { - "y": 29.5, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F3": { - "y": 29.5, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G3": { - "y": 29.5, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H3": { - "y": 29.5, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I3": { - "y": 29.5, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A4": { - "y": 44.25, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B4": { - "y": 44.25, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C4": { - "y": 44.25, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D4": { - "y": 44.25, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E4": { - "y": 44.25, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F4": { - "y": 44.25, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G4": { - "y": 44.25, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H4": { - "y": 44.25, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I4": { - "y": 44.25, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A5": { - "y": 59, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B5": { - "y": 59, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C5": { - "y": 59, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D5": { - "y": 59, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E5": { - "y": 59, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F5": { - "y": 59, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G5": { - "y": 59, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H5": { - "y": 59, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I5": { - "y": 59, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A6": { - "y": 73.75, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B6": { - "y": 73.75, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C6": { - "y": 73.75, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D6": { - "y": 73.75, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E6": { - "y": 73.75, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F6": { - "y": 73.75, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G6": { - "y": 73.75, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H6": { - "y": 73.75, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I6": { - "y": 73.75, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A7": { - "y": 88.5, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B7": { - "y": 88.5, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C7": { - "y": 88.5, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D7": { - "y": 88.5, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E7": { - "y": 88.5, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F7": { - "y": 88.5, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G7": { - "y": 88.5, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H7": { - "y": 88.5, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I7": { - "y": 88.5, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A8": { - "y": 103.25, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B8": { - "y": 103.25, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C8": { - "y": 103.25, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D8": { - "y": 103.25, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E8": { - "y": 103.25, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F8": { - "y": 103.25, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G8": { - "y": 103.25, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H8": { - "y": 103.25, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I8": { - "y": 103.25, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - - "A9": { - "y": 118, - "x": 0, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "B9": { - "y": 118, - "x": 14.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "C9": { - "y": 118, - "x": 29.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "D9": { - "y": 118, - "x": 44.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "E9": { - "y": 118, - "x": 59, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "F9": { - "y": 118, - "x": 73.75, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "G9": { - "y": 118, - "x": 88.5, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "H9": { - "y": 118, - "x": 103.25, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - }, - "I9": { - "y": 118, - "x": 118, - "z": 0, - "depth": 45, - "diameter": 10, - "total-liquid-volume": 2000 - } - } - }, - "96-well-plate-20mm": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 20.2, - "diameter": 5.46, - "total-liquid-volume": 300 - } - } - }, - "6-well-plate": { - "origin-offset": { - "x": 23.16, - "y": 24.76 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 22.5, - "total-liquid-volume": 16800 - }, - "B1": { - "x": 39.12, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 22.5, - "total-liquid-volume": 16800 - }, - "A2": { - "x": 0, - "y": 39.12, - "z": 0, - "depth": 17.4, - "diameter": 22.5, - "total-liquid-volume": 16800 - }, - "B2": { - "x": 39.12, - "y": 39.12, - "z": 0, - "depth": 17.4, - "diameter": 22.5, - "total-liquid-volume": 16800 - }, - "A3": { - "x": 0, - "y": 78.24, - "z": 0, - "depth": 17.4, - "diameter": 22.5, - "total-liquid-volume": 16800 - }, - "B3": { - "x": 39.12, - "y": 78.24, - "z": 0, - "depth": 17.4, - "diameter": 22.5, - "total-liquid-volume": 16800 - } - } - }, - "12-well-plate": { - "origin-offset": { - "x": 16.79, - "y": 24.94 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "B1": { - "x": 26.01, - "y": 0, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "C1": { - "x": 52.02, - "y": 0, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "A2": { - "x": 0, - "y": 26.01, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "B2": { - "x": 26.01, - "y": 26.01, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "C2": { - "x": 52.02, - "y": 26.01, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "A3": { - "x": 0, - "y": 52.02, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "B3": { - "x": 26.01, - "y": 52.02, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "C3": { - "x": 52.02, - "y": 52.02, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "A4": { - "x": 0, - "y": 78.03, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "B4": { - "x": 26.01, - "y": 78.03, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - }, - "C4": { - "x": 52.02, - "y": 78.03, - "z": 0, - "depth": 17.53, - "diameter": 22.5, - "total-liquid-volume": 6900 - } - } - }, - "24-well-plate": { - "origin-offset": { - "x": 13.67, - "y": 15 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "B1": { - "x": 19.3, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "C1": { - "x": 38.6, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "D1": { - "x": 57.9, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "A2": { - "x": 0, - "y": 19.3, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "B2": { - "x": 19.3, - "y": 19.3, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "C2": { - "x": 38.6, - "y": 19.3, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "D2": { - "x": 57.9, - "y": 19.3, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "A3": { - "x": 0, - "y": 38.6, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "B3": { - "x": 19.3, - "y": 38.6, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "C3": { - "x": 38.6, - "y": 38.6, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "D3": { - "x": 57.9, - "y": 38.6, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "A4": { - "x": 0, - "y": 57.9, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "B4": { - "x": 19.3, - "y": 57.9, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "C4": { - "x": 38.6, - "y": 57.9, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "D4": { - "x": 57.9, - "y": 57.9, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "A5": { - "x": 0, - "y": 77.2, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "B5": { - "x": 19.3, - "y": 77.2, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "C5": { - "x": 38.6, - "y": 77.2, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "D5": { - "x": 57.9, - "y": 77.2, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "A6": { - "x": 0, - "y": 96.5, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "B6": { - "x": 19.3, - "y": 96.5, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "C6": { - "x": 38.6, - "y": 96.5, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - }, - "D6": { - "x": 57.9, - "y": 96.5, - "z": 0, - "depth": 17.4, - "diameter": 16, - "total-liquid-volume": 1900 - } - } - }, - "48-well-plate": { - "origin-offset": { - "x": 10.08, - "y": 18.16 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B1": { - "x": 13.08, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C1": { - "x": 26.16, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D1": { - "x": 39.24, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E1": { - "x": 52.32, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F1": { - "x": 65.4, - "y": 0, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A2": { - "x": 0, - "y": 13.08, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B2": { - "x": 13.08, - "y": 13.08, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C2": { - "x": 26.16, - "y": 13.08, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D2": { - "x": 39.24, - "y": 13.08, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E2": { - "x": 52.32, - "y": 13.08, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F2": { - "x": 65.4, - "y": 13.08, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A3": { - "x": 0, - "y": 26.16, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B3": { - "x": 13.08, - "y": 26.16, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C3": { - "x": 26.16, - "y": 26.16, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D3": { - "x": 39.24, - "y": 26.16, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E3": { - "x": 52.32, - "y": 26.16, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F3": { - "x": 65.4, - "y": 26.16, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A4": { - "x": 0, - "y": 39.24, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B4": { - "x": 13.08, - "y": 39.24, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C4": { - "x": 26.16, - "y": 39.24, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D4": { - "x": 39.24, - "y": 39.24, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E4": { - "x": 52.32, - "y": 39.24, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F4": { - "x": 65.4, - "y": 39.24, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A5": { - "x": 0, - "y": 52.32, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B5": { - "x": 13.08, - "y": 52.32, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C5": { - "x": 26.16, - "y": 52.32, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D5": { - "x": 39.24, - "y": 52.32, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E5": { - "x": 52.32, - "y": 52.32, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F5": { - "x": 65.4, - "y": 52.32, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A6": { - "x": 0, - "y": 65.4, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B6": { - "x": 13.08, - "y": 65.4, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C6": { - "x": 26.16, - "y": 65.4, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D6": { - "x": 39.24, - "y": 65.4, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E6": { - "x": 52.32, - "y": 65.4, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F6": { - "x": 65.4, - "y": 65.4, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A7": { - "x": 0, - "y": 78.48, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B7": { - "x": 13.08, - "y": 78.48, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C7": { - "x": 26.16, - "y": 78.48, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D7": { - "x": 39.24, - "y": 78.48, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E7": { - "x": 52.32, - "y": 78.48, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F7": { - "x": 65.4, - "y": 78.48, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "A8": { - "x": 0, - "y": 91.56, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "B8": { - "x": 13.08, - "y": 91.56, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "C8": { - "x": 26.16, - "y": 91.56, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "D8": { - "x": 39.24, - "y": 91.56, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "E8": { - "x": 52.32, - "y": 91.56, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - }, - "F8": { - "x": 65.4, - "y": 91.56, - "z": 0, - "depth": 17.4, - "diameter": 11.25, - "total-liquid-volume": 950 - } - } - }, - "trough-1row-25ml": { - "locations": { - "A1": { - "x": 42.75, - "y": 63.875, - "z": 0, - "depth": 26, - "diameter": 10, - "total-liquid-volume": 25000 - } - } - }, - "trough-1row-test": { - "locations": { - "A1": { - "x": 42.75, - "y": 63.875, - "z": 0, - "depth": 26, - "diameter": 10, - "total-liquid-volume": 25000 - } - } - }, - "hampton-1ml-deep-block": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 38, - "diameter": 7.5, - "total-liquid-volume": 1000 - } - } - }, - - "rigaku-compact-crystallization-plate": { - "origin-offset": { - "x": 9, - "y": 11 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 2.5, - "diameter": 2, - "total-liquid-volume": 6 - }, - - "A13": { - "x": 3.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B13": { - "x": 12.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C13": { - "x": 21.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D13": { - "x": 30.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E13": { - "x": 39.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F13": { - "x": 48.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G13": { - "x": 57.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H13": { - "x": 66.5, - "y": 3.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A14": { - "x": 3.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B14": { - "x": 12.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C14": { - "x": 21.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D14": { - "x": 30.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E14": { - "x": 39.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F14": { - "x": 48.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G14": { - "x": 57.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H14": { - "x": 66.5, - "y": 12.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A15": { - "x": 3.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B15": { - "x": 12.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C15": { - "x": 21.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D15": { - "x": 30.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E15": { - "x": 39.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F15": { - "x": 48.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G15": { - "x": 57.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H15": { - "x": 66.5, - "y": 21.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A16": { - "x": 3.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B16": { - "x": 12.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C16": { - "x": 21.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D16": { - "x": 30.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E16": { - "x": 39.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F16": { - "x": 48.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G16": { - "x": 57.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H16": { - "x": 66.5, - "y": 30.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A17": { - "x": 3.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B17": { - "x": 12.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C17": { - "x": 21.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D17": { - "x": 30.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E17": { - "x": 39.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F17": { - "x": 48.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G17": { - "x": 57.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H17": { - "x": 66.5, - "y": 39.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A18": { - "x": 3.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B18": { - "x": 12.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C18": { - "x": 21.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D18": { - "x": 30.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E18": { - "x": 39.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F18": { - "x": 48.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G18": { - "x": 57.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H18": { - "x": 66.5, - "y": 48.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A19": { - "x": 3.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B19": { - "x": 12.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C19": { - "x": 21.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D19": { - "x": 30.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E19": { - "x": 39.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F19": { - "x": 48.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G19": { - "x": 57.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H19": { - "x": 66.5, - "y": 57.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A20": { - "x": 3.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B20": { - "x": 12.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C20": { - "x": 21.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D20": { - "x": 30.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E20": { - "x": 39.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F20": { - "x": 48.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G20": { - "x": 57.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H20": { - "x": 66.5, - "y": 66.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A21": { - "x": 3.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B21": { - "x": 12.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C21": { - "x": 21.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D21": { - "x": 30.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E21": { - "x": 39.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F21": { - "x": 48.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G21": { - "x": 57.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H21": { - "x": 66.5, - "y": 75.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A22": { - "x": 3.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B22": { - "x": 12.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C22": { - "x": 21.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D22": { - "x": 30.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E22": { - "x": 39.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F22": { - "x": 48.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G22": { - "x": 57.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H22": { - "x": 66.5, - "y": 84.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A23": { - "x": 3.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B23": { - "x": 12.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C23": { - "x": 21.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D23": { - "x": 30.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E23": { - "x": 39.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F23": { - "x": 48.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G23": { - "x": 57.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H23": { - "x": 66.5, - "y": 93.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - - "A24": { - "x": 3.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "B24": { - "x": 12.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "C24": { - "x": 21.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "D24": { - "x": 30.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "E24": { - "x": 39.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "F24": { - "x": 48.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "G24": { - "x": 57.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - }, - "H24": { - "x": 66.5, - "y": 102.5, - "z": -6, - "depth": 6.5, - "diameter": 2.5, - "total-liquid-volume": 300 - } - } - }, - "alum-block-pcr-strips": { - - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A2": { - "x": 0, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B2": { - "x": 9, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C2": { - "x": 18, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D2": { - "x": 27, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E2": { - "x": 36, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F2": { - "x": 45, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G2": { - "x": 54, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H2": { - "x": 63, - "y": 117, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - } - } - }, - "T75-flask": { - "origin-offset": { - "x": 42.75, - "y": 63.875 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 163, - "diameter": 25, - "total-liquid-volume": 75000 - } - } - }, - "T25-flask": { - "origin-offset": { - "x": 42.75, - "y": 63.875 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 99, - "diameter": 18, - "total-liquid-volume": 25000 - } - } - }, - "magdeck": { - "origin-offset": { - "x": 0, - "y": 0 - }, - "locations": { - "A1": { - "x": 63.9, - "y": 42.8, - "z": 0, - "depth": 82.25 - } - } - }, - "tempdeck": { - "origin-offset": { - "x": 0, - "y": 0 - }, - "locations": { - "A1": { - "x": 63.9, - "y": 42.8, - "z": 0, - "depth": 80.09 - } - } - }, - "trash-box": { - "origin-offset": { - "x": 42.75, - "y": 63.875 - }, - "locations": { - "A1": { - "x": 60, - "y": 45, - "z": 0, - "depth": 40 - } - } - }, - "fixed-trash": { - "origin-offset": { - "x": 0, - "y": 0 - }, - "locations": { - "A1": { - "x": 80, - "y": 80, - "z": 5, - "depth": 58 - } - } - }, - "tall-fixed-trash": { - "origin-offset": { - "x": 0, - "y": 0 - }, - "locations": { - "A1": { - "x": 80, - "y": 80, - "z": 5, - "depth": 80 - } - } - }, - "wheaton_vial_rack": { - "origin-offset": { - "x": 9, - "y": 9 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 35, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 70, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 105, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "E1": { - "x": 140, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "F1": { - "x": 175, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "G1": { - "x": 210, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "H1": { - "x": 245, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "I1": { - "x": 280, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "J1": { - "x": 315, - "y": 0, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - - "A2": { - "x": 0, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 35, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 70, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 105, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "E2": { - "x": 140, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "F2": { - "x": 175, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "G2": { - "x": 210, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "H2": { - "x": 245, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "I2": { - "x": 280, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "J2": { - "x": 315, - "y": 35, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - - "A3": { - "x": 0, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 35, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 70, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 105, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "E3": { - "x": 140, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "F3": { - "x": 175, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "G3": { - "x": 210, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "H3": { - "x": 245, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "I3": { - "x": 280, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "J3": { - "x": 315, - "y": 70, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - - "A4": { - "x": 0, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 35, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 70, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 105, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "E4": { - "x": 140, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "F4": { - "x": 175, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "G4": { - "x": 210, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "H4": { - "x": 245, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "I4": { - "x": 280, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "J4": { - "x": 315, - "y": 105, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - - "A5": { - "x": 0, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 35, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 70, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 105, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "E5": { - "x": 140, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "F5": { - "x": 175, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "G5": { - "x": 210, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "H5": { - "x": 245, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "I5": { - "x": 280, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - }, - "J5": { - "x": 315, - "y": 140, - "z": 0, - "depth": 95, - "diameter": 18, - "total-liquid-volume": 2000 - } - } - }, - "tube-rack-80well": { - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 13.2, - "y": 0, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 26.5, - "y": 0, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 39.7, - "y": 0, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E1": { - "x": 52.9, - "y": 0, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 13.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 13.2, - "y": 13.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 26.5, - "y": 13.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 39.7, - "y": 13.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E2": { - "x": 52.9, - "y": 13.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 26.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 13.2, - "y": 26.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 26.5, - "y": 26.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 39.7, - "y": 26.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E3": { - "x": 52.9, - "y": 26.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 39.7, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 13.2, - "y": 39.7, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 26.5, - "y": 39.7, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 39.7, - "y": 39.7, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E4": { - "x": 52.9, - "y": 39.7, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 52.9, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 13.2, - "y": 52.9, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 26.5, - "y": 52.9, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 39.7, - "y": 52.9, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E5": { - "x": 52.9, - "y": 52.9, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 66.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 13.2, - "y": 66.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 26.5, - "y": 66.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 39.7, - "y": 66.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E6": { - "x": 52.9, - "y": 66.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A7": { - "x": 0, - "y": 79.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B7": { - "x": 13.2, - "y": 79.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C7": { - "x": 26.5, - "y": 79.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D7": { - "x": 39.7, - "y": 79.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E7": { - "x": 52.9, - "y": 79.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A8": { - "x": 0, - "y": 92.6, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B8": { - "x": 13.2, - "y": 92.6, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C8": { - "x": 26.5, - "y": 92.6, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D8": { - "x": 39.7, - "y": 92.6, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E8": { - "x": 52.9, - "y": 92.6, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A9": { - "x": 0, - "y": 105.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B9": { - "x": 13.2, - "y": 105.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C9": { - "x": 26.5, - "y": 105.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D9": { - "x": 39.7, - "y": 105.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E9": { - "x": 52.9, - "y": 105.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A10": { - "x": 0, - "y": 119.1, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B10": { - "x": 13.2, - "y": 119.1, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C10": { - "x": 26.5, - "y": 119.1, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D10": { - "x": 39.7, - "y": 119.1, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E10": { - "x": 52.9, - "y": 119.1, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A11": { - "x": 0, - "y": 132.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B11": { - "x": 13.2, - "y": 132.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C11": { - "x": 26.5, - "y": 132.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D11": { - "x": 39.7, - "y": 132.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E11": { - "x": 52.9, - "y": 132.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A12": { - "x": 0, - "y": 145.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B12": { - "x": 13.2, - "y": 145.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C12": { - "x": 26.5, - "y": 145.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D12": { - "x": 39.7, - "y": 145.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E12": { - "x": 52.9, - "y": 145.5, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A13": { - "x": 0, - "y": 158.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B13": { - "x": 13.2, - "y": 158.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C13": { - "x": 26.5, - "y": 158.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D13": { - "x": 39.7, - "y": 158.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E13": { - "x": 52.9, - "y": 158.8, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A14": { - "x": 0, - "y": 172, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B14": { - "x": 13.2, - "y": 172, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C14": { - "x": 26.5, - "y": 172, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D14": { - "x": 39.7, - "y": 172, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E14": { - "x": 52.9, - "y": 172, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A15": { - "x": 0, - "y": 185.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B15": { - "x": 13.2, - "y": 185.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C15": { - "x": 26.5, - "y": 185.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D15": { - "x": 39.7, - "y": 185.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E15": { - "x": 52.9, - "y": 185.2, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A16": { - "x": 0, - "y": 198.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B16": { - "x": 13.2, - "y": 198.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C16": { - "x": 26.5, - "y": 198.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D16": { - "x": 39.7, - "y": 198.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "E16": { - "x": 52.9, - "y": 198.4, - "z": 0, - "depth": 35, - "diameter": 6, - "total-liquid-volume": 2000 - } - } - }, - "point": { - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 0, - "total-liquid-volume": 1 - } - } - }, - "tiprack-10ul": { - "origin-offset": { - "x": 14.24, - "y": 14.54 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 56, - "diameter": 3.5 - } - } - }, - - "tiprack-10ul-H": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 60, - "diameter": 6.4 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 60, - "diameter": 6.4 - } - } - }, - - "tiprack-200ul": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "diameter": 3.5, - "depth": 60 - } - } - }, - "opentrons-tiprack-10ul": { - "origin-offset": { - "x": 10.77, - "y": 11.47 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B1": { - "x": 9, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C1": { - "x": 18, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D1": { - "x": 27, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E1": { - "x": 36, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F1": { - "x": 45, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G1": { - "x": 54, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H1": { - "x": 63, - "y": 0, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A2": { - "x": 0, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B2": { - "x": 9, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C2": { - "x": 18, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D2": { - "x": 27, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E2": { - "x": 36, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F2": { - "x": 45, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G2": { - "x": 54, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H2": { - "x": 63, - "y": 9, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A3": { - "x": 0, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B3": { - "x": 9, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C3": { - "x": 18, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D3": { - "x": 27, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E3": { - "x": 36, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F3": { - "x": 45, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G3": { - "x": 54, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H3": { - "x": 63, - "y": 18, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A4": { - "x": 0, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B4": { - "x": 9, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C4": { - "x": 18, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D4": { - "x": 27, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E4": { - "x": 36, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F4": { - "x": 45, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G4": { - "x": 54, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H4": { - "x": 63, - "y": 27, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A5": { - "x": 0, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B5": { - "x": 9, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C5": { - "x": 18, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D5": { - "x": 27, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E5": { - "x": 36, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F5": { - "x": 45, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G5": { - "x": 54, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H5": { - "x": 63, - "y": 36, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A6": { - "x": 0, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B6": { - "x": 9, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C6": { - "x": 18, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D6": { - "x": 27, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E6": { - "x": 36, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F6": { - "x": 45, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G6": { - "x": 54, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H6": { - "x": 63, - "y": 45, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A7": { - "x": 0, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B7": { - "x": 9, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C7": { - "x": 18, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D7": { - "x": 27, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E7": { - "x": 36, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F7": { - "x": 45, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G7": { - "x": 54, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H7": { - "x": 63, - "y": 54, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A8": { - "x": 0, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B8": { - "x": 9, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C8": { - "x": 18, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D8": { - "x": 27, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E8": { - "x": 36, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F8": { - "x": 45, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G8": { - "x": 54, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H8": { - "x": 63, - "y": 63, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A9": { - "x": 0, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B9": { - "x": 9, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C9": { - "x": 18, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D9": { - "x": 27, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E9": { - "x": 36, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F9": { - "x": 45, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G9": { - "x": 54, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H9": { - "x": 63, - "y": 72, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A10": { - "x": 0, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B10": { - "x": 9, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C10": { - "x": 18, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D10": { - "x": 27, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E10": { - "x": 36, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F10": { - "x": 45, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G10": { - "x": 54, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H10": { - "x": 63, - "y": 81, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A11": { - "x": 0, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B11": { - "x": 9, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C11": { - "x": 18, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D11": { - "x": 27, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E11": { - "x": 36, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F11": { - "x": 45, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G11": { - "x": 54, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H11": { - "x": 63, - "y": 90, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "A12": { - "x": 0, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "B12": { - "x": 9, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "C12": { - "x": 18, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "D12": { - "x": 27, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "E12": { - "x": 36, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "F12": { - "x": 45, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "G12": { - "x": 54, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - }, - "H12": { - "x": 63, - "y": 99, - "z": 25.46, - "diameter": 3.5, - "depth": 39.2 - } - } - }, - "opentrons-tiprack-300ul": { - "origin-offset": { - "x": 12.59, - "y": 14.85 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B1": { - "x": 9, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C1": { - "x": 18, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D1": { - "x": 27, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E1": { - "x": 36, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F1": { - "x": 45, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G1": { - "x": 54, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H1": { - "x": 63, - "y": 0, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A2": { - "x": 0, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B2": { - "x": 9, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C2": { - "x": 18, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D2": { - "x": 27, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E2": { - "x": 36, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F2": { - "x": 45, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G2": { - "x": 54, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H2": { - "x": 63, - "y": 9, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A3": { - "x": 0, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B3": { - "x": 9, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C3": { - "x": 18, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D3": { - "x": 27, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E3": { - "x": 36, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F3": { - "x": 45, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G3": { - "x": 54, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H3": { - "x": 63, - "y": 18, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A4": { - "x": 0, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B4": { - "x": 9, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C4": { - "x": 18, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D4": { - "x": 27, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E4": { - "x": 36, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F4": { - "x": 45, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G4": { - "x": 54, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H4": { - "x": 63, - "y": 27, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A5": { - "x": 0, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B5": { - "x": 9, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C5": { - "x": 18, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D5": { - "x": 27, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E5": { - "x": 36, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F5": { - "x": 45, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G5": { - "x": 54, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H5": { - "x": 63, - "y": 36, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A6": { - "x": 0, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B6": { - "x": 9, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C6": { - "x": 18, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D6": { - "x": 27, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E6": { - "x": 36, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F6": { - "x": 45, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G6": { - "x": 54, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H6": { - "x": 63, - "y": 45, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A7": { - "x": 0, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B7": { - "x": 9, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C7": { - "x": 18, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D7": { - "x": 27, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E7": { - "x": 36, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F7": { - "x": 45, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G7": { - "x": 54, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H7": { - "x": 63, - "y": 54, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A8": { - "x": 0, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B8": { - "x": 9, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C8": { - "x": 18, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D8": { - "x": 27, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E8": { - "x": 36, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F8": { - "x": 45, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G8": { - "x": 54, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H8": { - "x": 63, - "y": 63, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A9": { - "x": 0, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B9": { - "x": 9, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C9": { - "x": 18, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D9": { - "x": 27, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E9": { - "x": 36, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F9": { - "x": 45, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G9": { - "x": 54, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H9": { - "x": 63, - "y": 72, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A10": { - "x": 0, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B10": { - "x": 9, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C10": { - "x": 18, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D10": { - "x": 27, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E10": { - "x": 36, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F10": { - "x": 45, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G10": { - "x": 54, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H10": { - "x": 63, - "y": 81, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A11": { - "x": 0, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B11": { - "x": 9, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C11": { - "x": 18, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D11": { - "x": 27, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E11": { - "x": 36, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F11": { - "x": 45, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G11": { - "x": 54, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H11": { - "x": 63, - "y": 90, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "A12": { - "x": 0, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "B12": { - "x": 9, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "C12": { - "x": 18, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "D12": { - "x": 27, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "E12": { - "x": 36, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "F12": { - "x": 45, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "G12": { - "x": 54, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - }, - "H12": { - "x": 63, - "y": 99, - "z": 6, - "diameter": 3.5, - "depth": 60 - } - } - }, - - "tiprack-1000ul": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "diameter": 6.4, - "depth": 101.0 - } - } - }, - "opentrons-tiprack-1000ul": { - "origin-offset": { - "x": 8.5, - "y": 11.18 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "diameter": 7.62, - "depth": 98.07 - } - } - }, - "tube-rack-.75ml": { - "origin-offset": { - "x": 13.5, - "y": 15, - "z": 55 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "B1": { - "x": 19.5, - "y": 0, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "C1": { - "x": 39, - "y": 0, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "D1": { - "x": 58.5, - "y": 0, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "A2": { - "x": 0, - "y": 19.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "B2": { - "x": 19.5, - "y": 19.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "C2": { - "x": 39, - "y": 19.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "D2": { - "x": 58.5, - "y": 19.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "A3": { - "x": 0, - "y": 39, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "B3": { - "x": 19.5, - "y": 39, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "C3": { - "x": 39, - "y": 39, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "D3": { - "x": 58.5, - "y": 39, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "A4": { - "x": 0, - "y": 58.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "B4": { - "x": 19.5, - "y": 58.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "C4": { - "x": 39, - "y": 58.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "D4": { - "x": 58.5, - "y": 58.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "A5": { - "x": 0, - "y": 78, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "B5": { - "x": 19.5, - "y": 78, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "C5": { - "x": 39, - "y": 78, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "D5": { - "x": 58.5, - "y": 78, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "A6": { - "x": 0, - "y": 97.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "B6": { - "x": 19.5, - "y": 97.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "C6": { - "x": 39, - "y": 97.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - }, - "D6": { - "x": 58.5, - "y": 97.5, - "z": 0, - "depth": 20, - "diameter": 6, - "total-liquid-volume": 750 - } - } - }, - - "tube-rack-2ml": { - "origin-offset": { - "x": 13, - "y": 16, - "z": 52 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 19.5, - "y": 0, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 39, - "y": 0, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 58.5, - "y": 0, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 19.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 19.5, - "y": 19.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 39, - "y": 19.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 58.5, - "y": 19.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 39, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 19.5, - "y": 39, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 39, - "y": 39, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 58.5, - "y": 39, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 58.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 19.5, - "y": 58.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 39, - "y": 58.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 58.5, - "y": 58.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 78, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 19.5, - "y": 78, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 39, - "y": 78, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 58.5, - "y": 78, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 97.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 19.5, - "y": 97.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 39, - "y": 97.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 58.5, - "y": 97.5, - "z": 0, - "depth": 40, - "diameter": 6, - "total-liquid-volume": 2000 - } - } - }, - - "tube-rack-15_50ml": { - "origin-offset": { - "x": 11, - "y": 19 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 5, - "depth": 115, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B1": { - "x": 31.5, - "y": 0, - "z": 5, - "depth": 115, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C1": { - "x": 63, - "y": 0, - "z": 5, - "depth": 115, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "A2": { - "x": 0, - "y": 22.7, - "z": 5, - "depth": 115, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B2": { - "x": 31.5, - "y": 22.7, - "z": 5, - "depth": 115, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C2": { - "x": 63, - "y": 22.7, - "z": 0, - "depth": 115, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "A3": { - "x": 5.9, - "y": 51.26, - "z": 5, - "depth": 115, - "diameter": 30, - "total-liquid-volume": 50000 - }, - "B3": { - "x": 51.26, - "y": 51.26, - "z": 5, - "depth": 115, - "diameter": 30, - "total-liquid-volume": 50000 - }, - "A4": { - "x": 5.9, - "y": 87.1, - "z": 5, - "depth": 115, - "diameter": 30, - "total-liquid-volume": 50000 - }, - "B4": { - "x": 51.26, - "y": 87.1, - "z": 5, - "depth": 115, - "diameter": 30, - "total-liquid-volume": 50000 - } - } - }, - - "trough-12row": { - "origin-offset": { - "x": 7.75, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A2": { - "x": 0, - "y": 9, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A3": { - "x": 0, - "y": 18, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A4": { - "x": 0, - "y": 27, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A5": { - "x": 0, - "y": 36, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A6": { - "x": 0, - "y": 45, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A7": { - "x": 0, - "y": 54, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A8": { - "x": 0, - "y": 63, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A9": { - "x": 0, - "y": 72, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A10": { - "x": 0, - "y": 81, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A11": { - "x": 0, - "y": 90, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - }, - "A12": { - "x": 0, - "y": 99, - "z": 8, - "depth": 38, - "total-liquid-volume": 22000 - } - } - }, - - "trough-12row-short": { - "origin-offset": { - "x": 7.75, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 20, - "total-liquid-volume": 22000 - } - } - }, - - "24-vial-rack": { - "origin-offset": { - "x": 13.67, - "y": 16 - }, - "locations": { - "A1": { - "x": 0.0, - "total-liquid-volume": 3400, - "y": 0.0, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "A2": { - "x": 0.0, - "total-liquid-volume": 3400, - "y": 19.3, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "A3": { - "x": 0.0, - "total-liquid-volume": 3400, - "y": 38.6, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "A4": { - "x": 0.0, - "total-liquid-volume": 3400, - "y": 57.9, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "A5": { - "x": 0.0, - "total-liquid-volume": 3400, - "y": 77.2, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "A6": { - "x": 0.0, - "total-liquid-volume": 3400, - "y": 96.5, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "B1": { - "x": 19.3, - "total-liquid-volume": 3400, - "y": 0.0, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "B2": { - "x": 19.3, - "total-liquid-volume": 3400, - "y": 19.3, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "B3": { - "x": 19.3, - "total-liquid-volume": 3400, - "y": 38.6, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "B4": { - "x": 19.3, - "total-liquid-volume": 3400, - "y": 57.9, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "B5": { - "x": 19.3, - "total-liquid-volume": 3400, - "y": 77.2, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "B6": { - "x": 19.3, - "total-liquid-volume": 3400, - "y": 96.5, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "C1": { - "x": 38.6, - "total-liquid-volume": 3400, - "y": 0.0, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "C2": { - "x": 38.6, - "total-liquid-volume": 3400, - "y": 19.3, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "C3": { - "x": 38.6, - "total-liquid-volume": 3400, - "y": 38.6, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "C4": { - "x": 38.6, - "total-liquid-volume": 3400, - "y": 57.9, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "C5": { - "x": 38.6, - "total-liquid-volume": 3400, - "y": 77.2, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "C6": { - "x": 38.6, - "total-liquid-volume": 3400, - "y": 96.5, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "D1": { - "x": 57.9, - "total-liquid-volume": 3400, - "y": 0.0, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "D2": { - "x": 57.9, - "total-liquid-volume": 3400, - "y": 19.3, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "D3": { - "x": 57.9, - "total-liquid-volume": 3400, - "y": 38.6, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "D4": { - "x": 57.9, - "total-liquid-volume": 3400, - "y": 57.9, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "D5": { - "x": 57.9, - "total-liquid-volume": 3400, - "y": 77.2, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - }, - "D6": { - "x": 57.9, - "total-liquid-volume": 3400, - "y": 96.5, - "depth": 16.2, - "z": 0, - "diameter": 15.62 - } - } - }, - - "96-deep-well": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 33.5, - "diameter": 7.5, - "total-liquid-volume": 2000 - } - } - }, - - "96-PCR-tall": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 15.4, - "diameter": 6.4, - "total-liquid-volume": 300 - } - } - }, - - "96-PCR-flat": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 300 - } - } - }, - - "biorad-hardshell-96-PCR": { - "origin-offset": { - "x": 18.24, - "y": 13.63 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B1": { - "x": 9, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C1": { - "x": 18, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D1": { - "x": 27, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E1": { - "x": 36, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F1": { - "x": 45, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G1": { - "x": 54, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H1": { - "x": 63, - "y": 0, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A2": { - "x": 0, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B2": { - "x": 9, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C2": { - "x": 18, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D2": { - "x": 27, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E2": { - "x": 36, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F2": { - "x": 45, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G2": { - "x": 54, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H2": { - "x": 63, - "y": 9, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A3": { - "x": 0, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B3": { - "x": 9, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C3": { - "x": 18, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D3": { - "x": 27, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E3": { - "x": 36, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F3": { - "x": 45, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G3": { - "x": 54, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H3": { - "x": 63, - "y": 18, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A4": { - "x": 0, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B4": { - "x": 9, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C4": { - "x": 18, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D4": { - "x": 27, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E4": { - "x": 36, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F4": { - "x": 45, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G4": { - "x": 54, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H4": { - "x": 63, - "y": 27, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A5": { - "x": 0, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B5": { - "x": 9, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C5": { - "x": 18, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D5": { - "x": 27, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E5": { - "x": 36, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F5": { - "x": 45, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G5": { - "x": 54, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H5": { - "x": 63, - "y": 36, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A6": { - "x": 0, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B6": { - "x": 9, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C6": { - "x": 18, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D6": { - "x": 27, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E6": { - "x": 36, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F6": { - "x": 45, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G6": { - "x": 54, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H6": { - "x": 63, - "y": 45, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A7": { - "x": 0, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B7": { - "x": 9, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C7": { - "x": 18, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D7": { - "x": 27, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E7": { - "x": 36, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F7": { - "x": 45, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G7": { - "x": 54, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H7": { - "x": 63, - "y": 54, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A8": { - "x": 0, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B8": { - "x": 9, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C8": { - "x": 18, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D8": { - "x": 27, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E8": { - "x": 36, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F8": { - "x": 45, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G8": { - "x": 54, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H8": { - "x": 63, - "y": 63, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A9": { - "x": 0, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B9": { - "x": 9, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C9": { - "x": 18, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D9": { - "x": 27, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E9": { - "x": 36, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F9": { - "x": 45, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G9": { - "x": 54, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H9": { - "x": 63, - "y": 72, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A10": { - "x": 0, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B10": { - "x": 9, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C10": { - "x": 18, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D10": { - "x": 27, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E10": { - "x": 36, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F10": { - "x": 45, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G10": { - "x": 54, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H10": { - "x": 63, - "y": 81, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A11": { - "x": 0, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B11": { - "x": 9, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C11": { - "x": 18, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D11": { - "x": 27, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E11": { - "x": 36, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F11": { - "x": 45, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G11": { - "x": 54, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H11": { - "x": 63, - "y": 90, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A12": { - "x": 0, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B12": { - "x": 9, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C12": { - "x": 18, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D12": { - "x": 27, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E12": { - "x": 36, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F12": { - "x": 45, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G12": { - "x": 54, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H12": { - "x": 63, - "y": 99, - "z": 4.25, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 300 - } - } - }, - - "96-flat": { - "origin-offset": { - "x": 17.64, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B1": { - "x": 9, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C1": { - "x": 18, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D1": { - "x": 27, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E1": { - "x": 36, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F1": { - "x": 45, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G1": { - "x": 54, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H1": { - "x": 63, - "y": 0, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A2": { - "x": 0, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B2": { - "x": 9, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C2": { - "x": 18, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D2": { - "x": 27, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E2": { - "x": 36, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F2": { - "x": 45, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G2": { - "x": 54, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H2": { - "x": 63, - "y": 9, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A3": { - "x": 0, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B3": { - "x": 9, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C3": { - "x": 18, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D3": { - "x": 27, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E3": { - "x": 36, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F3": { - "x": 45, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G3": { - "x": 54, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H3": { - "x": 63, - "y": 18, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A4": { - "x": 0, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B4": { - "x": 9, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C4": { - "x": 18, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D4": { - "x": 27, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E4": { - "x": 36, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F4": { - "x": 45, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G4": { - "x": 54, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H4": { - "x": 63, - "y": 27, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A5": { - "x": 0, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B5": { - "x": 9, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C5": { - "x": 18, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D5": { - "x": 27, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E5": { - "x": 36, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F5": { - "x": 45, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G5": { - "x": 54, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H5": { - "x": 63, - "y": 36, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A6": { - "x": 0, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B6": { - "x": 9, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C6": { - "x": 18, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D6": { - "x": 27, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E6": { - "x": 36, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F6": { - "x": 45, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G6": { - "x": 54, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H6": { - "x": 63, - "y": 45, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A7": { - "x": 0, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B7": { - "x": 9, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C7": { - "x": 18, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D7": { - "x": 27, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E7": { - "x": 36, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F7": { - "x": 45, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G7": { - "x": 54, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H7": { - "x": 63, - "y": 54, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A8": { - "x": 0, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B8": { - "x": 9, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C8": { - "x": 18, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D8": { - "x": 27, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E8": { - "x": 36, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F8": { - "x": 45, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G8": { - "x": 54, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H8": { - "x": 63, - "y": 63, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A9": { - "x": 0, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B9": { - "x": 9, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C9": { - "x": 18, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D9": { - "x": 27, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E9": { - "x": 36, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F9": { - "x": 45, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G9": { - "x": 54, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H9": { - "x": 63, - "y": 72, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A10": { - "x": 0, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B10": { - "x": 9, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C10": { - "x": 18, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D10": { - "x": 27, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E10": { - "x": 36, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F10": { - "x": 45, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G10": { - "x": 54, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H10": { - "x": 63, - "y": 81, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A11": { - "x": 0, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B11": { - "x": 9, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C11": { - "x": 18, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D11": { - "x": 27, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E11": { - "x": 36, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F11": { - "x": 45, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G11": { - "x": 54, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H11": { - "x": 63, - "y": 90, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "A12": { - "x": 0, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "B12": { - "x": 9, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "C12": { - "x": 18, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "D12": { - "x": 27, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "E12": { - "x": 36, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "F12": { - "x": 45, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "G12": { - "x": 54, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - }, - "H12": { - "x": 63, - "y": 99, - "z": 3.85, - "depth": 10.5, - "diameter": 6.4, - "total-liquid-volume": 400 - } - } - }, - - "PCR-strip-tall": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 19.5, - "diameter": 6.4, - "total-liquid-volume": 280 - } - } - }, - - "384-plate": { - "origin-offset": { - "x": 9, - "y": 12.13 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B1": { - "x": 4.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D1": { - "x": 13.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F1": { - "x": 22.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H1": { - "x": 31.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J1": { - "x": 40.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L1": { - "x": 49.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N1": { - "x": 58.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P1": { - "x": 67.5, - "y": 0, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A2": { - "x": 0, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B2": { - "x": 4.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C2": { - "x": 9, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D2": { - "x": 13.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E2": { - "x": 18, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F2": { - "x": 22.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G2": { - "x": 27, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H2": { - "x": 31.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I2": { - "x": 36, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J2": { - "x": 40.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K2": { - "x": 45, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L2": { - "x": 49.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M2": { - "x": 54, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N2": { - "x": 58.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O2": { - "x": 63, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P2": { - "x": 67.5, - "y": 4.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A3": { - "x": 0, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B3": { - "x": 4.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C3": { - "x": 9, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D3": { - "x": 13.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E3": { - "x": 18, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F3": { - "x": 22.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G3": { - "x": 27, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H3": { - "x": 31.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I3": { - "x": 36, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J3": { - "x": 40.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K3": { - "x": 45, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L3": { - "x": 49.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M3": { - "x": 54, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N3": { - "x": 58.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O3": { - "x": 63, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P3": { - "x": 67.5, - "y": 9, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A4": { - "x": 0, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B4": { - "x": 4.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C4": { - "x": 9, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D4": { - "x": 13.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E4": { - "x": 18, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F4": { - "x": 22.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G4": { - "x": 27, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H4": { - "x": 31.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I4": { - "x": 36, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J4": { - "x": 40.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K4": { - "x": 45, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L4": { - "x": 49.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M4": { - "x": 54, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N4": { - "x": 58.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O4": { - "x": 63, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P4": { - "x": 67.5, - "y": 13.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A5": { - "x": 0, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B5": { - "x": 4.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C5": { - "x": 9, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D5": { - "x": 13.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E5": { - "x": 18, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F5": { - "x": 22.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G5": { - "x": 27, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H5": { - "x": 31.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I5": { - "x": 36, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J5": { - "x": 40.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K5": { - "x": 45, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L5": { - "x": 49.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M5": { - "x": 54, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N5": { - "x": 58.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O5": { - "x": 63, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P5": { - "x": 67.5, - "y": 18, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A6": { - "x": 0, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B6": { - "x": 4.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C6": { - "x": 9, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D6": { - "x": 13.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E6": { - "x": 18, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F6": { - "x": 22.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G6": { - "x": 27, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H6": { - "x": 31.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I6": { - "x": 36, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J6": { - "x": 40.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K6": { - "x": 45, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L6": { - "x": 49.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M6": { - "x": 54, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N6": { - "x": 58.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O6": { - "x": 63, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P6": { - "x": 67.5, - "y": 22.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A7": { - "x": 0, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B7": { - "x": 4.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C7": { - "x": 9, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D7": { - "x": 13.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E7": { - "x": 18, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F7": { - "x": 22.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G7": { - "x": 27, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H7": { - "x": 31.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I7": { - "x": 36, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J7": { - "x": 40.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K7": { - "x": 45, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L7": { - "x": 49.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M7": { - "x": 54, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N7": { - "x": 58.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O7": { - "x": 63, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P7": { - "x": 67.5, - "y": 27, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A8": { - "x": 0, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B8": { - "x": 4.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C8": { - "x": 9, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D8": { - "x": 13.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E8": { - "x": 18, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F8": { - "x": 22.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G8": { - "x": 27, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H8": { - "x": 31.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I8": { - "x": 36, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J8": { - "x": 40.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K8": { - "x": 45, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L8": { - "x": 49.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M8": { - "x": 54, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N8": { - "x": 58.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O8": { - "x": 63, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P8": { - "x": 67.5, - "y": 31.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A9": { - "x": 0, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B9": { - "x": 4.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C9": { - "x": 9, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D9": { - "x": 13.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E9": { - "x": 18, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F9": { - "x": 22.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G9": { - "x": 27, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H9": { - "x": 31.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I9": { - "x": 36, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J9": { - "x": 40.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K9": { - "x": 45, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L9": { - "x": 49.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M9": { - "x": 54, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N9": { - "x": 58.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O9": { - "x": 63, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P9": { - "x": 67.5, - "y": 36, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A10": { - "x": 0, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B10": { - "x": 4.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C10": { - "x": 9, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D10": { - "x": 13.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E10": { - "x": 18, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F10": { - "x": 22.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G10": { - "x": 27, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H10": { - "x": 31.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I10": { - "x": 36, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J10": { - "x": 40.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K10": { - "x": 45, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L10": { - "x": 49.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M10": { - "x": 54, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N10": { - "x": 58.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O10": { - "x": 63, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P10": { - "x": 67.5, - "y": 40.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A11": { - "x": 0, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B11": { - "x": 4.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C11": { - "x": 9, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D11": { - "x": 13.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E11": { - "x": 18, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F11": { - "x": 22.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G11": { - "x": 27, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H11": { - "x": 31.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I11": { - "x": 36, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J11": { - "x": 40.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K11": { - "x": 45, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L11": { - "x": 49.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M11": { - "x": 54, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N11": { - "x": 58.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O11": { - "x": 63, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P11": { - "x": 67.5, - "y": 45, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A12": { - "x": 0, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B12": { - "x": 4.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C12": { - "x": 9, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D12": { - "x": 13.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E12": { - "x": 18, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F12": { - "x": 22.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G12": { - "x": 27, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H12": { - "x": 31.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I12": { - "x": 36, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J12": { - "x": 40.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K12": { - "x": 45, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L12": { - "x": 49.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M12": { - "x": 54, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N12": { - "x": 58.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O12": { - "x": 63, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P12": { - "x": 67.5, - "y": 49.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A13": { - "x": 0, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B13": { - "x": 4.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C13": { - "x": 9, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D13": { - "x": 13.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E13": { - "x": 18, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F13": { - "x": 22.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G13": { - "x": 27, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H13": { - "x": 31.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I13": { - "x": 36, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J13": { - "x": 40.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K13": { - "x": 45, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L13": { - "x": 49.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M13": { - "x": 54, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N13": { - "x": 58.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O13": { - "x": 63, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P13": { - "x": 67.5, - "y": 54, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A14": { - "x": 0, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B14": { - "x": 4.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C14": { - "x": 9, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D14": { - "x": 13.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E14": { - "x": 18, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F14": { - "x": 22.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G14": { - "x": 27, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H14": { - "x": 31.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I14": { - "x": 36, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J14": { - "x": 40.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K14": { - "x": 45, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L14": { - "x": 49.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M14": { - "x": 54, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N14": { - "x": 58.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O14": { - "x": 63, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P14": { - "x": 67.5, - "y": 58.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A15": { - "x": 0, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B15": { - "x": 4.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C15": { - "x": 9, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D15": { - "x": 13.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E15": { - "x": 18, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F15": { - "x": 22.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G15": { - "x": 27, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H15": { - "x": 31.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I15": { - "x": 36, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J15": { - "x": 40.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K15": { - "x": 45, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L15": { - "x": 49.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M15": { - "x": 54, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N15": { - "x": 58.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O15": { - "x": 63, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P15": { - "x": 67.5, - "y": 63, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A16": { - "x": 0, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B16": { - "x": 4.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C16": { - "x": 9, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D16": { - "x": 13.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E16": { - "x": 18, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F16": { - "x": 22.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G16": { - "x": 27, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H16": { - "x": 31.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I16": { - "x": 36, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J16": { - "x": 40.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K16": { - "x": 45, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L16": { - "x": 49.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M16": { - "x": 54, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N16": { - "x": 58.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O16": { - "x": 63, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P16": { - "x": 67.5, - "y": 67.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A17": { - "x": 0, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B17": { - "x": 4.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C17": { - "x": 9, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D17": { - "x": 13.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E17": { - "x": 18, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F17": { - "x": 22.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G17": { - "x": 27, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H17": { - "x": 31.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I17": { - "x": 36, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J17": { - "x": 40.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K17": { - "x": 45, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L17": { - "x": 49.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M17": { - "x": 54, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N17": { - "x": 58.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O17": { - "x": 63, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P17": { - "x": 67.5, - "y": 72, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A18": { - "x": 0, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B18": { - "x": 4.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C18": { - "x": 9, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D18": { - "x": 13.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E18": { - "x": 18, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F18": { - "x": 22.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G18": { - "x": 27, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H18": { - "x": 31.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I18": { - "x": 36, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J18": { - "x": 40.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K18": { - "x": 45, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L18": { - "x": 49.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M18": { - "x": 54, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N18": { - "x": 58.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O18": { - "x": 63, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P18": { - "x": 67.5, - "y": 76.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A19": { - "x": 0, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B19": { - "x": 4.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C19": { - "x": 9, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D19": { - "x": 13.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E19": { - "x": 18, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F19": { - "x": 22.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G19": { - "x": 27, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H19": { - "x": 31.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I19": { - "x": 36, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J19": { - "x": 40.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K19": { - "x": 45, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L19": { - "x": 49.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M19": { - "x": 54, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N19": { - "x": 58.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O19": { - "x": 63, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P19": { - "x": 67.5, - "y": 81, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A20": { - "x": 0, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B20": { - "x": 4.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C20": { - "x": 9, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D20": { - "x": 13.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E20": { - "x": 18, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F20": { - "x": 22.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G20": { - "x": 27, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H20": { - "x": 31.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I20": { - "x": 36, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J20": { - "x": 40.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K20": { - "x": 45, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L20": { - "x": 49.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M20": { - "x": 54, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N20": { - "x": 58.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O20": { - "x": 63, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P20": { - "x": 67.5, - "y": 85.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A21": { - "x": 0, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B21": { - "x": 4.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C21": { - "x": 9, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D21": { - "x": 13.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E21": { - "x": 18, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F21": { - "x": 22.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G21": { - "x": 27, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H21": { - "x": 31.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I21": { - "x": 36, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J21": { - "x": 40.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K21": { - "x": 45, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L21": { - "x": 49.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M21": { - "x": 54, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N21": { - "x": 58.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O21": { - "x": 63, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P21": { - "x": 67.5, - "y": 90, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A22": { - "x": 0, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B22": { - "x": 4.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C22": { - "x": 9, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D22": { - "x": 13.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E22": { - "x": 18, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F22": { - "x": 22.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G22": { - "x": 27, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H22": { - "x": 31.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I22": { - "x": 36, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J22": { - "x": 40.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K22": { - "x": 45, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L22": { - "x": 49.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M22": { - "x": 54, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N22": { - "x": 58.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O22": { - "x": 63, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P22": { - "x": 67.5, - "y": 94.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A23": { - "x": 0, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B23": { - "x": 4.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C23": { - "x": 9, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D23": { - "x": 13.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E23": { - "x": 18, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F23": { - "x": 22.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G23": { - "x": 27, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H23": { - "x": 31.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I23": { - "x": 36, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J23": { - "x": 40.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K23": { - "x": 45, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L23": { - "x": 49.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M23": { - "x": 54, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N23": { - "x": 58.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O23": { - "x": 63, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P23": { - "x": 67.5, - "y": 99, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A24": { - "x": 0, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B24": { - "x": 4.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C24": { - "x": 9, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D24": { - "x": 13.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E24": { - "x": 18, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F24": { - "x": 22.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G24": { - "x": 27, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H24": { - "x": 31.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I24": { - "x": 36, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J24": { - "x": 40.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K24": { - "x": 45, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L24": { - "x": 49.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M24": { - "x": 54, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N24": { - "x": 58.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O24": { - "x": 63, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P24": { - "x": 67.5, - "y": 103.5, - "z": 0, - "depth": 9.5, - "diameter": 3.1, - "total-liquid-volume": 55 - } - } - }, - - "MALDI-plate": { - "origin-offset": { - "x": 9, - "y": 12 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B1": { - "x": 4.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D1": { - "x": 13.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F1": { - "x": 22.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H1": { - "x": 31.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J1": { - "x": 40.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L1": { - "x": 49.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N1": { - "x": 58.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P1": { - "x": 67.5, - "y": 0, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A2": { - "x": 0, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B2": { - "x": 4.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C2": { - "x": 9, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D2": { - "x": 13.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E2": { - "x": 18, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F2": { - "x": 22.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G2": { - "x": 27, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H2": { - "x": 31.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I2": { - "x": 36, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J2": { - "x": 40.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K2": { - "x": 45, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L2": { - "x": 49.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M2": { - "x": 54, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N2": { - "x": 58.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O2": { - "x": 63, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P2": { - "x": 67.5, - "y": 4.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A3": { - "x": 0, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B3": { - "x": 4.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C3": { - "x": 9, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D3": { - "x": 13.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E3": { - "x": 18, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F3": { - "x": 22.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G3": { - "x": 27, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H3": { - "x": 31.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I3": { - "x": 36, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J3": { - "x": 40.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K3": { - "x": 45, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L3": { - "x": 49.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M3": { - "x": 54, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N3": { - "x": 58.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O3": { - "x": 63, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P3": { - "x": 67.5, - "y": 9, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A4": { - "x": 0, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B4": { - "x": 4.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C4": { - "x": 9, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D4": { - "x": 13.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E4": { - "x": 18, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F4": { - "x": 22.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G4": { - "x": 27, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H4": { - "x": 31.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I4": { - "x": 36, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J4": { - "x": 40.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K4": { - "x": 45, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L4": { - "x": 49.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M4": { - "x": 54, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N4": { - "x": 58.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O4": { - "x": 63, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P4": { - "x": 67.5, - "y": 13.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A5": { - "x": 0, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B5": { - "x": 4.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C5": { - "x": 9, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D5": { - "x": 13.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E5": { - "x": 18, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F5": { - "x": 22.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G5": { - "x": 27, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H5": { - "x": 31.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I5": { - "x": 36, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J5": { - "x": 40.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K5": { - "x": 45, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L5": { - "x": 49.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M5": { - "x": 54, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N5": { - "x": 58.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O5": { - "x": 63, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P5": { - "x": 67.5, - "y": 18, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A6": { - "x": 0, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B6": { - "x": 4.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C6": { - "x": 9, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D6": { - "x": 13.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E6": { - "x": 18, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F6": { - "x": 22.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G6": { - "x": 27, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H6": { - "x": 31.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I6": { - "x": 36, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J6": { - "x": 40.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K6": { - "x": 45, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L6": { - "x": 49.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M6": { - "x": 54, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N6": { - "x": 58.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O6": { - "x": 63, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P6": { - "x": 67.5, - "y": 22.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A7": { - "x": 0, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B7": { - "x": 4.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C7": { - "x": 9, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D7": { - "x": 13.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E7": { - "x": 18, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F7": { - "x": 22.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G7": { - "x": 27, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H7": { - "x": 31.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I7": { - "x": 36, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J7": { - "x": 40.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K7": { - "x": 45, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L7": { - "x": 49.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M7": { - "x": 54, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N7": { - "x": 58.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O7": { - "x": 63, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P7": { - "x": 67.5, - "y": 27, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A8": { - "x": 0, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B8": { - "x": 4.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C8": { - "x": 9, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D8": { - "x": 13.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E8": { - "x": 18, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F8": { - "x": 22.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G8": { - "x": 27, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H8": { - "x": 31.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I8": { - "x": 36, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J8": { - "x": 40.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K8": { - "x": 45, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L8": { - "x": 49.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M8": { - "x": 54, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N8": { - "x": 58.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O8": { - "x": 63, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P8": { - "x": 67.5, - "y": 31.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A9": { - "x": 0, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B9": { - "x": 4.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C9": { - "x": 9, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D9": { - "x": 13.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E9": { - "x": 18, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F9": { - "x": 22.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G9": { - "x": 27, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H9": { - "x": 31.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I9": { - "x": 36, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J9": { - "x": 40.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K9": { - "x": 45, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L9": { - "x": 49.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M9": { - "x": 54, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N9": { - "x": 58.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O9": { - "x": 63, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P9": { - "x": 67.5, - "y": 36, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A10": { - "x": 0, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B10": { - "x": 4.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C10": { - "x": 9, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D10": { - "x": 13.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E10": { - "x": 18, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F10": { - "x": 22.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G10": { - "x": 27, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H10": { - "x": 31.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I10": { - "x": 36, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J10": { - "x": 40.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K10": { - "x": 45, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L10": { - "x": 49.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M10": { - "x": 54, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N10": { - "x": 58.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O10": { - "x": 63, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P10": { - "x": 67.5, - "y": 40.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A11": { - "x": 0, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B11": { - "x": 4.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C11": { - "x": 9, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D11": { - "x": 13.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E11": { - "x": 18, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F11": { - "x": 22.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G11": { - "x": 27, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H11": { - "x": 31.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I11": { - "x": 36, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J11": { - "x": 40.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K11": { - "x": 45, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L11": { - "x": 49.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M11": { - "x": 54, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N11": { - "x": 58.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O11": { - "x": 63, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P11": { - "x": 67.5, - "y": 45, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A12": { - "x": 0, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B12": { - "x": 4.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C12": { - "x": 9, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D12": { - "x": 13.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E12": { - "x": 18, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F12": { - "x": 22.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G12": { - "x": 27, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H12": { - "x": 31.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I12": { - "x": 36, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J12": { - "x": 40.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K12": { - "x": 45, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L12": { - "x": 49.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M12": { - "x": 54, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N12": { - "x": 58.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O12": { - "x": 63, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P12": { - "x": 67.5, - "y": 49.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A13": { - "x": 0, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B13": { - "x": 4.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C13": { - "x": 9, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D13": { - "x": 13.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E13": { - "x": 18, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F13": { - "x": 22.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G13": { - "x": 27, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H13": { - "x": 31.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I13": { - "x": 36, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J13": { - "x": 40.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K13": { - "x": 45, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L13": { - "x": 49.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M13": { - "x": 54, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N13": { - "x": 58.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O13": { - "x": 63, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P13": { - "x": 67.5, - "y": 54, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A14": { - "x": 0, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B14": { - "x": 4.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C14": { - "x": 9, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D14": { - "x": 13.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E14": { - "x": 18, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F14": { - "x": 22.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G14": { - "x": 27, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H14": { - "x": 31.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I14": { - "x": 36, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J14": { - "x": 40.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K14": { - "x": 45, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L14": { - "x": 49.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M14": { - "x": 54, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N14": { - "x": 58.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O14": { - "x": 63, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P14": { - "x": 67.5, - "y": 58.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A15": { - "x": 0, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B15": { - "x": 4.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C15": { - "x": 9, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D15": { - "x": 13.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E15": { - "x": 18, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F15": { - "x": 22.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G15": { - "x": 27, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H15": { - "x": 31.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I15": { - "x": 36, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J15": { - "x": 40.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K15": { - "x": 45, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L15": { - "x": 49.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M15": { - "x": 54, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N15": { - "x": 58.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O15": { - "x": 63, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P15": { - "x": 67.5, - "y": 63, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A16": { - "x": 0, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B16": { - "x": 4.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C16": { - "x": 9, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D16": { - "x": 13.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E16": { - "x": 18, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F16": { - "x": 22.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G16": { - "x": 27, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H16": { - "x": 31.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I16": { - "x": 36, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J16": { - "x": 40.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K16": { - "x": 45, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L16": { - "x": 49.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M16": { - "x": 54, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N16": { - "x": 58.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O16": { - "x": 63, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P16": { - "x": 67.5, - "y": 67.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A17": { - "x": 0, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B17": { - "x": 4.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C17": { - "x": 9, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D17": { - "x": 13.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E17": { - "x": 18, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F17": { - "x": 22.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G17": { - "x": 27, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H17": { - "x": 31.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I17": { - "x": 36, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J17": { - "x": 40.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K17": { - "x": 45, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L17": { - "x": 49.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M17": { - "x": 54, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N17": { - "x": 58.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O17": { - "x": 63, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P17": { - "x": 67.5, - "y": 72, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A18": { - "x": 0, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B18": { - "x": 4.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C18": { - "x": 9, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D18": { - "x": 13.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E18": { - "x": 18, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F18": { - "x": 22.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G18": { - "x": 27, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H18": { - "x": 31.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I18": { - "x": 36, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J18": { - "x": 40.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K18": { - "x": 45, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L18": { - "x": 49.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M18": { - "x": 54, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N18": { - "x": 58.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O18": { - "x": 63, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P18": { - "x": 67.5, - "y": 76.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A19": { - "x": 0, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B19": { - "x": 4.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C19": { - "x": 9, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D19": { - "x": 13.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E19": { - "x": 18, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F19": { - "x": 22.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G19": { - "x": 27, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H19": { - "x": 31.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I19": { - "x": 36, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J19": { - "x": 40.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K19": { - "x": 45, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L19": { - "x": 49.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M19": { - "x": 54, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N19": { - "x": 58.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O19": { - "x": 63, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P19": { - "x": 67.5, - "y": 81, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A20": { - "x": 0, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B20": { - "x": 4.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C20": { - "x": 9, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D20": { - "x": 13.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E20": { - "x": 18, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F20": { - "x": 22.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G20": { - "x": 27, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H20": { - "x": 31.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I20": { - "x": 36, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J20": { - "x": 40.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K20": { - "x": 45, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L20": { - "x": 49.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M20": { - "x": 54, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N20": { - "x": 58.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O20": { - "x": 63, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P20": { - "x": 67.5, - "y": 85.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A21": { - "x": 0, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B21": { - "x": 4.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C21": { - "x": 9, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D21": { - "x": 13.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E21": { - "x": 18, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F21": { - "x": 22.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G21": { - "x": 27, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H21": { - "x": 31.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I21": { - "x": 36, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J21": { - "x": 40.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K21": { - "x": 45, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L21": { - "x": 49.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M21": { - "x": 54, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N21": { - "x": 58.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O21": { - "x": 63, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P21": { - "x": 67.5, - "y": 90, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A22": { - "x": 0, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B22": { - "x": 4.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C22": { - "x": 9, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D22": { - "x": 13.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E22": { - "x": 18, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F22": { - "x": 22.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G22": { - "x": 27, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H22": { - "x": 31.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I22": { - "x": 36, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J22": { - "x": 40.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K22": { - "x": 45, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L22": { - "x": 49.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M22": { - "x": 54, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N22": { - "x": 58.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O22": { - "x": 63, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P22": { - "x": 67.5, - "y": 94.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A23": { - "x": 0, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B23": { - "x": 4.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C23": { - "x": 9, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D23": { - "x": 13.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E23": { - "x": 18, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F23": { - "x": 22.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G23": { - "x": 27, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H23": { - "x": 31.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I23": { - "x": 36, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J23": { - "x": 40.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K23": { - "x": 45, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L23": { - "x": 49.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M23": { - "x": 54, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N23": { - "x": 58.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O23": { - "x": 63, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P23": { - "x": 67.5, - "y": 99, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "A24": { - "x": 0, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "B24": { - "x": 4.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "C24": { - "x": 9, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "D24": { - "x": 13.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "E24": { - "x": 18, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "F24": { - "x": 22.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "G24": { - "x": 27, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "H24": { - "x": 31.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "I24": { - "x": 36, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "J24": { - "x": 40.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "K24": { - "x": 45, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "L24": { - "x": 49.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "M24": { - "x": 54, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "N24": { - "x": 58.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "O24": { - "x": 63, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - }, - "P24": { - "x": 67.5, - "y": 103.5, - "z": 0, - "depth": 0, - "diameter": 3.1, - "total-liquid-volume": 55 - } - } - }, - - "48-vial-plate": { - "origin-offset": { - "x": 10.5, - "y": 18 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 13, - "y": 0, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 26, - "y": 0, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 39, - "y": 0, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E1": { - "x": 52, - "y": 0, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F1": { - "x": 65, - "y": 0, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A2": { - "x": 0, - "y": 13, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 13, - "y": 13, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 26, - "y": 13, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 39, - "y": 13, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E2": { - "x": 52, - "y": 13, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F2": { - "x": 65, - "y": 13, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A3": { - "x": 0, - "y": 26, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 13, - "y": 26, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 26, - "y": 26, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 39, - "y": 26, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E3": { - "x": 52, - "y": 26, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F3": { - "x": 65, - "y": 26, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A4": { - "x": 0, - "y": 39, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 13, - "y": 39, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 26, - "y": 39, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 39, - "y": 39, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E4": { - "x": 52, - "y": 39, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F4": { - "x": 65, - "y": 39, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A5": { - "x": 0, - "y": 52, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 13, - "y": 52, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 26, - "y": 52, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 39, - "y": 52, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E5": { - "x": 52, - "y": 52, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F5": { - "x": 65, - "y": 52, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A6": { - "x": 0, - "y": 65, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 13, - "y": 65, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 26, - "y": 65, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 39, - "y": 65, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E6": { - "x": 52, - "y": 65, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F6": { - "x": 65, - "y": 65, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A7": { - "x": 0, - "y": 78, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B7": { - "x": 13, - "y": 78, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C7": { - "x": 26, - "y": 78, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D7": { - "x": 39, - "y": 78, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E7": { - "x": 52, - "y": 78, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F7": { - "x": 65, - "y": 78, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - - "A8": { - "x": 0, - "y": 91, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "B8": { - "x": 13, - "y": 91, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "C8": { - "x": 26, - "y": 91, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "D8": { - "x": 39, - "y": 91, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "E8": { - "x": 52, - "y": 91, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - }, - "F8": { - "x": 65, - "y": 91, - "z": 0, - "depth": 30, - "diameter": 11.5, - "total-liquid-volume": 2000 - } - } - }, - - "e-gelgol": { - "origin-offset": { - "x": 11.24, - "y": 14.34 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B1": { - "x": 9, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C1": { - "x": 18, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D1": { - "x": 27, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E1": { - "x": 36, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F1": { - "x": 45, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G1": { - "x": 54, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H1": { - "x": 63, - "y": 0, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A2": { - "x": 0, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B2": { - "x": 9, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C2": { - "x": 18, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D2": { - "x": 27, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E2": { - "x": 36, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F2": { - "x": 45, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G2": { - "x": 54, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H2": { - "x": 63, - "y": 9, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A3": { - "x": 0, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B3": { - "x": 9, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C3": { - "x": 18, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D3": { - "x": 27, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E3": { - "x": 36, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F3": { - "x": 45, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G3": { - "x": 54, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H3": { - "x": 63, - "y": 18, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A4": { - "x": 0, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B4": { - "x": 9, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C4": { - "x": 18, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D4": { - "x": 27, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E4": { - "x": 36, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F4": { - "x": 45, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G4": { - "x": 54, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H4": { - "x": 63, - "y": 27, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A5": { - "x": 0, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B5": { - "x": 9, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C5": { - "x": 18, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D5": { - "x": 27, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E5": { - "x": 36, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F5": { - "x": 45, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G5": { - "x": 54, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H5": { - "x": 63, - "y": 36, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A6": { - "x": 0, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B6": { - "x": 9, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C6": { - "x": 18, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D6": { - "x": 27, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E6": { - "x": 36, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F6": { - "x": 45, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G6": { - "x": 54, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H6": { - "x": 63, - "y": 45, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A7": { - "x": 0, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B7": { - "x": 9, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C7": { - "x": 18, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D7": { - "x": 27, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E7": { - "x": 36, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F7": { - "x": 45, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G7": { - "x": 54, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H7": { - "x": 63, - "y": 54, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A8": { - "x": 0, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B8": { - "x": 9, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C8": { - "x": 18, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D8": { - "x": 27, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E8": { - "x": 36, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F8": { - "x": 45, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G8": { - "x": 54, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H8": { - "x": 63, - "y": 63, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A9": { - "x": 0, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B9": { - "x": 9, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C9": { - "x": 18, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D9": { - "x": 27, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E9": { - "x": 36, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F9": { - "x": 45, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G9": { - "x": 54, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H9": { - "x": 63, - "y": 72, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A10": { - "x": 0, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B10": { - "x": 9, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C10": { - "x": 18, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D10": { - "x": 27, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E10": { - "x": 36, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F10": { - "x": 45, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G10": { - "x": 54, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H10": { - "x": 63, - "y": 81, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A11": { - "x": 0, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B11": { - "x": 9, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C11": { - "x": 18, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D11": { - "x": 27, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E11": { - "x": 36, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F11": { - "x": 45, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G11": { - "x": 54, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H11": { - "x": 63, - "y": 90, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "A12": { - "x": 0, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "B12": { - "x": 9, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "C12": { - "x": 18, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "D12": { - "x": 27, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "E12": { - "x": 36, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "F12": { - "x": 45, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "G12": { - "x": 54, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - }, - "H12": { - "x": 63, - "y": 99, - "z": 0, - "depth": 2, - "diameter": 1, - "total-liquid-volume": 2 - } - } - }, - - "5ml-3x4": { - "origin-offset": { - "x": 18, - "y": 19 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "B1": { - "x": 25, - "y": 0, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "C1": { - "x": 50, - "y": 0, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "A2": { - "x": 0, - "y": 30, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "B2": { - "x": 25, - "y": 30, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "C2": { - "x": 50, - "y": 30, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "A3": { - "x": 0, - "y": 60, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "B3": { - "x": 25, - "y": 60, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "C3": { - "x": 50, - "y": 60, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "A4": { - "x": 0, - "y": 90, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "B4": { - "x": 25, - "y": 90, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - }, - "C4": { - "x": 50, - "y": 90, - "z": 0, - "depth": 55, - "diameter": 14, - "total-liquid-volume": 50000 - } - } - }, - - "small_vial_rack_16x45": { - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "B1": { - "x": 40, - "y": 0, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "C1": { - "x": 80, - "y": 0, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "D1": { - "x": 120, - "y": 0, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "A2": { - "x": 0, - "y": 20, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "B2": { - "x": 40, - "y": 20, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "C2": { - "x": 80, - "y": 20, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "D2": { - "x": 120, - "y": 20, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "A3": { - "x": 0, - "y": 40, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "B3": { - "x": 40, - "y": 40, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "C3": { - "x": 80, - "y": 40, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "D3": { - "x": 120, - "y": 40, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "A4": { - "x": 0, - "y": 60, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "B4": { - "x": 40, - "y": 60, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "C4": { - "x": 80, - "y": 60, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "D4": { - "x": 120, - "y": 60, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "A5": { - "x": 0, - "y": 80, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "B5": { - "x": 40, - "y": 80, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "C5": { - "x": 80, - "y": 80, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "D5": { - "x": 120, - "y": 80, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "A6": { - "x": 0, - "y": 100, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "B6": { - "x": 40, - "y": 100, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "C6": { - "x": 80, - "y": 100, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - }, - "D6": { - "x": 120, - "y": 100, - "z": 0, - "depth": 45, - "diameter": 16, - "total-liquid-volume": 10000 - } - } - }, - - "opentrons-tuberack-15ml": { - "origin-offset": { - "x": 34.375, - "y": 13.5 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B1": { - "x": 25, - "y": 0, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C1": { - "x": 50, - "y": 0, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "A2": { - "x": 0, - "y": 25, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B2": { - "x": 25, - "y": 25, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C2": { - "x": 50, - "y": 25, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "A3": { - "x": 0, - "y": 50, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B3": { - "x": 25, - "y": 50, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C3": { - "x": 50, - "y": 50, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "A4": { - "x": 0, - "y": 75, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B4": { - "x": 25, - "y": 75, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C4": { - "x": 50, - "y": 75, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "A5": { - "x": 0, - "y": 100, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "B5": { - "x": 25, - "y": 100, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - }, - "C5": { - "x": 50, - "y": 100, - "z": 6.78, - "depth": 117.98, - "diameter": 17, - "total-liquid-volume": 15000 - } - } - }, - - "opentrons-tuberack-50ml": { - "origin-offset": { - "x": 39.875, - "y": 37 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 6.95, - "depth": 112.85, - "diameter": 17, - "total-liquid-volume": 50000 - }, - "B1": { - "x": 35, - "y": 0, - "z": 6.95, - "depth": 112.85, - "diameter": 17, - "total-liquid-volume": 50000 - }, - "A2": { - "x": 0, - "y": 35, - "z": 6.95, - "depth": 112.85, - "diameter": 17, - "total-liquid-volume": 50000 - }, - "B2": { - "x": 35, - "y": 35, - "z": 6.95, - "depth": 112.85, - "diameter": 17, - "total-liquid-volume": 50000 - }, - "A3": { - "x": 0, - "y": 70, - "z": 6.95, - "depth": 112.85, - "diameter": 17, - "total-liquid-volume": 50000 - }, - "B3": { - "x": 35, - "y": 70, - "z": 6.95, - "depth": 112.85, - "diameter": 17, - "total-liquid-volume": 50000 - } - } - }, - - "opentrons-tuberack-15_50ml": { - "origin-offset": { - "x": 32.75, - "y": 14.875 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 6.78, - "depth": 117.98, - "diameter": 14.5, - "total-liquid-volume": 15000 - }, - "B1": { - "x": 25, - "y": 0, - "z": 6.78, - "depth": 117.98, - "diameter": 14.5, - "total-liquid-volume": 15000 - }, - "C1": { - "x": 50, - "y": 0, - "z": 6.78, - "depth": 117.98, - "diameter": 14.5, - "total-liquid-volume": 15000 - }, - "A2": { - "x": 0, - "y": 25, - "z": 6.78, - "depth": 117.98, - "diameter": 14.5, - "total-liquid-volume": 15000 - }, - "B2": { - "x": 25, - "y": 25, - "z": 6.78, - "depth": 117.98, - "diameter": 14.5, - "total-liquid-volume": 15000 - }, - "C2": { - "x": 50, - "y": 25, - "z": 6.78, - "depth": 117.98, - "diameter": 14.5, - "total-liquid-volume": 15000 - }, - "A3": { - "x": 18.25, - "y": 57.5, - "z": 6.95, - "depth": 112.85, - "diameter": 26.45, - "total-liquid-volume": 50000 - }, - "B3": { - "x": 53.25, - "y": 57.5, - "z": 6.95, - "depth": 112.85, - "diameter": 26.45, - "total-liquid-volume": 50000 - }, - "A4": { - "x": 18.25, - "y": 92.5, - "z": 6.95, - "depth": 112.85, - "diameter": 26.45, - "total-liquid-volume": 50000 - }, - "B4": { - "x": 53.25, - "y": 92.5, - "z": 6.95, - "depth": 112.85, - "diameter": 26.45, - "total-liquid-volume": 50000 - } - } - }, - - "opentrons-tuberack-2ml-eppendorf": { - "origin-offset": { - "x": 21.07, - "y": 18.21 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 19.28, - "y": 0, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 38.56, - "y": 0, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 57.84, - "y": 0, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 19.89, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 19.28, - "y": 19.89, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 38.56, - "y": 19.89, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 57.84, - "y": 19.89, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 39.78, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 19.28, - "y": 39.78, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 38.56, - "y": 39.78, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 57.84, - "y": 39.78, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 59.67, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 19.28, - "y": 59.67, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 38.56, - "y": 59.67, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 57.84, - "y": 59.67, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 79.56, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 19.28, - "y": 79.56, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 38.56, - "y": 79.56, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 57.84, - "y": 79.56, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 99.45, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 19.28, - "y": 99.45, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 38.56, - "y": 99.45, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 57.84, - "y": 99.45, - "z": 43.3, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - } - } - }, - - "opentrons-tuberack-2ml-screwcap": { - "origin-offset": { - "x": 21.07, - "y": 18.21 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 19.28, - "y": 0, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 38.56, - "y": 0, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 57.84, - "y": 0, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 19.89, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 19.28, - "y": 19.89, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 38.56, - "y": 19.89, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 57.84, - "y": 19.89, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 39.78, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 19.28, - "y": 39.78, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 38.56, - "y": 39.78, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 57.84, - "y": 39.78, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 59.67, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 19.28, - "y": 59.67, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 38.56, - "y": 59.67, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 57.84, - "y": 59.67, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 79.56, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 19.28, - "y": 79.56, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 38.56, - "y": 79.56, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 57.84, - "y": 79.56, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 99.45, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 19.28, - "y": 99.45, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 38.56, - "y": 99.45, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 57.84, - "y": 99.45, - "z": 45.2, - "depth": 42, - "diameter": 8.5, - "total-liquid-volume": 2000 - } - } - }, - - "opentrons-tuberack-1.5ml-eppendorf": { - "origin-offset": { - "x": 21.07, - "y": 18.21 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "B1": { - "x": 19.28, - "y": 0, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "C1": { - "x": 38.56, - "y": 0, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "D1": { - "x": 57.84, - "y": 0, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "A2": { - "x": 0, - "y": 19.89, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "B2": { - "x": 19.28, - "y": 19.89, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "C2": { - "x": 38.56, - "y": 19.89, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "D2": { - "x": 57.84, - "y": 19.89, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "A3": { - "x": 0, - "y": 39.78, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "B3": { - "x": 19.28, - "y": 39.78, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "C3": { - "x": 38.56, - "y": 39.78, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "D3": { - "x": 57.84, - "y": 39.78, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "A4": { - "x": 0, - "y": 59.67, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "B4": { - "x": 19.28, - "y": 59.67, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "C4": { - "x": 38.56, - "y": 59.67, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "D4": { - "x": 57.84, - "y": 59.67, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "A5": { - "x": 0, - "y": 79.56, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "B5": { - "x": 19.28, - "y": 79.56, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "C5": { - "x": 38.56, - "y": 79.56, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "D5": { - "x": 57.84, - "y": 79.56, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "A6": { - "x": 0, - "y": 99.45, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "B6": { - "x": 19.28, - "y": 99.45, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "C6": { - "x": 38.56, - "y": 99.45, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - }, - "D6": { - "x": 57.84, - "y": 99.45, - "z": 43.3, - "depth": 37.0, - "diameter": 9, - "total-liquid-volume": 1500 - } - } - }, - - "opentrons-aluminum-block-2ml-eppendorf": { - "origin-offset": { - "x": 25.88, - "y": 20.75 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 17.25, - "y": 0, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 34.5, - "y": 0, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 51.75, - "y": 0, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 17.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 17.25, - "y": 17.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 34.5, - "y": 17.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 51.75, - "y": 17.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 34.5, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 17.25, - "y": 34.5, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 34.5, - "y": 34.5, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 51.75, - "y": 34.5, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 51.75, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 17.25, - "y": 51.75, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 34.5, - "y": 51.75, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 51.75, - "y": 51.75, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 69, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 17.25, - "y": 69, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 34.5, - "y": 69, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 51.75, - "y": 69, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 86.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 17.25, - "y": 86.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 34.5, - "y": 86.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 51.75, - "y": 86.25, - "z": 5.5, - "depth": 38.5, - "diameter": 9, - "total-liquid-volume": 2000 - } - } - }, - "opentrons-aluminum-block-2ml-screwcap": { - "origin-offset": { - "x": 25.88, - "y": 20.75 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B1": { - "x": 17.25, - "y": 0, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C1": { - "x": 34.5, - "y": 0, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D1": { - "x": 51.75, - "y": 0, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A2": { - "x": 0, - "y": 17.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B2": { - "x": 17.25, - "y": 17.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C2": { - "x": 34.5, - "y": 17.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D2": { - "x": 51.75, - "y": 17.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A3": { - "x": 0, - "y": 34.5, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B3": { - "x": 17.25, - "y": 34.5, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C3": { - "x": 34.5, - "y": 34.5, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D3": { - "x": 51.75, - "y": 34.5, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A4": { - "x": 0, - "y": 51.75, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B4": { - "x": 17.25, - "y": 51.75, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C4": { - "x": 34.5, - "y": 51.75, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D4": { - "x": 51.75, - "y": 51.75, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A5": { - "x": 0, - "y": 69, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B5": { - "x": 17.25, - "y": 69, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C5": { - "x": 34.5, - "y": 69, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D5": { - "x": 51.75, - "y": 69, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "A6": { - "x": 0, - "y": 86.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "B6": { - "x": 17.25, - "y": 86.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "C6": { - "x": 34.5, - "y": 86.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - }, - "D6": { - "x": 51.75, - "y": 86.25, - "z": 6.5, - "depth": 42, - "diameter": 9, - "total-liquid-volume": 2000 - } - } - }, - "opentrons-aluminum-block-96-PCR-plate": { - "origin-offset": { - "x": 17.25, - "y": 13.38 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B1": { - "x": 9, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C1": { - "x": 18, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D1": { - "x": 27, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E1": { - "x": 36, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F1": { - "x": 45, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G1": { - "x": 54, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H1": { - "x": 63, - "y": 0, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A2": { - "x": 0, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B2": { - "x": 9, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C2": { - "x": 18, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D2": { - "x": 27, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E2": { - "x": 36, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F2": { - "x": 45, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G2": { - "x": 54, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H2": { - "x": 63, - "y": 9, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A3": { - "x": 0, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B3": { - "x": 9, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C3": { - "x": 18, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D3": { - "x": 27, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E3": { - "x": 36, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F3": { - "x": 45, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G3": { - "x": 54, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H3": { - "x": 63, - "y": 18, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A4": { - "x": 0, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B4": { - "x": 9, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C4": { - "x": 18, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D4": { - "x": 27, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E4": { - "x": 36, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F4": { - "x": 45, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G4": { - "x": 54, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H4": { - "x": 63, - "y": 27, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A5": { - "x": 0, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B5": { - "x": 9, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C5": { - "x": 18, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D5": { - "x": 27, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E5": { - "x": 36, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F5": { - "x": 45, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G5": { - "x": 54, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H5": { - "x": 63, - "y": 36, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A6": { - "x": 0, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B6": { - "x": 9, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C6": { - "x": 18, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D6": { - "x": 27, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E6": { - "x": 36, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F6": { - "x": 45, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G6": { - "x": 54, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H6": { - "x": 63, - "y": 45, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A7": { - "x": 0, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B7": { - "x": 9, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C7": { - "x": 18, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D7": { - "x": 27, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E7": { - "x": 36, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F7": { - "x": 45, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G7": { - "x": 54, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H7": { - "x": 63, - "y": 54, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A8": { - "x": 0, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B8": { - "x": 9, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C8": { - "x": 18, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D8": { - "x": 27, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E8": { - "x": 36, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F8": { - "x": 45, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G8": { - "x": 54, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H8": { - "x": 63, - "y": 63, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A9": { - "x": 0, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B9": { - "x": 9, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C9": { - "x": 18, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D9": { - "x": 27, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E9": { - "x": 36, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F9": { - "x": 45, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G9": { - "x": 54, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H9": { - "x": 63, - "y": 72, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A10": { - "x": 0, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B10": { - "x": 9, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C10": { - "x": 18, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D10": { - "x": 27, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E10": { - "x": 36, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F10": { - "x": 45, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G10": { - "x": 54, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H10": { - "x": 63, - "y": 81, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A11": { - "x": 0, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B11": { - "x": 9, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C11": { - "x": 18, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D11": { - "x": 27, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E11": { - "x": 36, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F11": { - "x": 45, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G11": { - "x": 54, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H11": { - "x": 63, - "y": 90, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "A12": { - "x": 0, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "B12": { - "x": 9, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "C12": { - "x": 18, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "D12": { - "x": 27, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "E12": { - "x": 36, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "F12": { - "x": 45, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "G12": { - "x": 54, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - }, - "H12": { - "x": 63, - "y": 99, - "z": 7.44, - "depth": 14.81, - "diameter": 5.4, - "total-liquid-volume": 200 - } - } - }, - "opentrons-aluminum-block-PCR-strips-200ul": { - "origin-offset": { - "x": 17.25, - "y": 13.38 - }, - "locations": { - "A1": { - "x": 0, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B1": { - "x": 9, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C1": { - "x": 18, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D1": { - "x": 27, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E1": { - "x": 36, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F1": { - "x": 45, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G1": { - "x": 54, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H1": { - "x": 63, - "y": 0, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A2": { - "x": 0, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B2": { - "x": 9, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C2": { - "x": 18, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D2": { - "x": 27, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E2": { - "x": 36, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F2": { - "x": 45, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G2": { - "x": 54, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H2": { - "x": 63, - "y": 9, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A3": { - "x": 0, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B3": { - "x": 9, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C3": { - "x": 18, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D3": { - "x": 27, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E3": { - "x": 36, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F3": { - "x": 45, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G3": { - "x": 54, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H3": { - "x": 63, - "y": 18, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A4": { - "x": 0, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B4": { - "x": 9, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C4": { - "x": 18, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D4": { - "x": 27, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E4": { - "x": 36, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F4": { - "x": 45, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G4": { - "x": 54, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H4": { - "x": 63, - "y": 27, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A5": { - "x": 0, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B5": { - "x": 9, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C5": { - "x": 18, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D5": { - "x": 27, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E5": { - "x": 36, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F5": { - "x": 45, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G5": { - "x": 54, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H5": { - "x": 63, - "y": 36, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A6": { - "x": 0, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B6": { - "x": 9, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C6": { - "x": 18, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D6": { - "x": 27, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E6": { - "x": 36, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F6": { - "x": 45, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G6": { - "x": 54, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H6": { - "x": 63, - "y": 45, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A7": { - "x": 0, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B7": { - "x": 9, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C7": { - "x": 18, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D7": { - "x": 27, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E7": { - "x": 36, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F7": { - "x": 45, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G7": { - "x": 54, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H7": { - "x": 63, - "y": 54, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A8": { - "x": 0, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B8": { - "x": 9, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C8": { - "x": 18, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D8": { - "x": 27, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E8": { - "x": 36, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F8": { - "x": 45, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G8": { - "x": 54, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H8": { - "x": 63, - "y": 63, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A9": { - "x": 0, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B9": { - "x": 9, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C9": { - "x": 18, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D9": { - "x": 27, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E9": { - "x": 36, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F9": { - "x": 45, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G9": { - "x": 54, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H9": { - "x": 63, - "y": 72, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A10": { - "x": 0, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B10": { - "x": 9, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C10": { - "x": 18, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D10": { - "x": 27, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E10": { - "x": 36, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F10": { - "x": 45, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G10": { - "x": 54, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H10": { - "x": 63, - "y": 81, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A11": { - "x": 0, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B11": { - "x": 9, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C11": { - "x": 18, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D11": { - "x": 27, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E11": { - "x": 36, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F11": { - "x": 45, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G11": { - "x": 54, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H11": { - "x": 63, - "y": 90, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "A12": { - "x": 0, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "B12": { - "x": 9, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "C12": { - "x": 18, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "D12": { - "x": 27, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "E12": { - "x": 36, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "F12": { - "x": 45, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "G12": { - "x": 54, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - }, - "H12": { - "x": 63, - "y": 99, - "z": 4.19, - "depth": 20.30, - "diameter": 5.4, - "total-liquid-volume": 300 - } - } - } - } -} From abdf902c65eade8da8c7e864568aad442417704c Mon Sep 17 00:00:00 2001 From: Shlok Amin Date: Mon, 13 Nov 2023 17:40:44 -0500 Subject: [PATCH 59/65] refactor(shared-data): update movable trash offset from cutout fixture (#13976) --- shared-data/deck/definitions/4/ot3_standard.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared-data/deck/definitions/4/ot3_standard.json b/shared-data/deck/definitions/4/ot3_standard.json index 87ba7e78e14..728f9743299 100644 --- a/shared-data/deck/definitions/4/ot3_standard.json +++ b/shared-data/deck/definitions/4/ot3_standard.json @@ -252,7 +252,7 @@ { "id": "movableTrashD1", "areaType": "movableTrash", - "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "offsetFromCutoutFixture": [-101.5, -2.75, 0.0], "boundingBox": { "xDimension": 246.5, "yDimension": 91.5, @@ -265,7 +265,7 @@ { "id": "movableTrashC1", "areaType": "movableTrash", - "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "offsetFromCutoutFixture": [-101.5, -2.75, 0.0], "boundingBox": { "xDimension": 246.5, "yDimension": 91.5, @@ -278,7 +278,7 @@ { "id": "movableTrashB1", "areaType": "movableTrash", - "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "offsetFromCutoutFixture": [-101.5, -2.75, 0.0], "boundingBox": { "xDimension": 246.5, "yDimension": 91.5, @@ -291,7 +291,7 @@ { "id": "movableTrashA1", "areaType": "movableTrash", - "offsetFromCutoutFixture": [-17.0, -2.75, 0.0], + "offsetFromCutoutFixture": [-101.5, -2.75, 0.0], "boundingBox": { "xDimension": 246.5, "yDimension": 91.5, From d8c8ffce11ab562f131284ef55c208aa7db6280f Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Tue, 14 Nov 2023 08:23:04 -0500 Subject: [PATCH 60/65] feat(step-generation): wire up moveLabware into waste chute (#13950) closes RAUT-778 --- .../src/load-file/migration/8_0_0.ts | 2 +- .../src/localization/en/alert.json | 4 ++ .../src/steplist/fieldLevel/index.ts | 18 ++++++ .../ui/labware/__tests__/selectors.test.ts | 9 ++- protocol-designer/src/ui/labware/selectors.ts | 28 ++++++-- shared-data/js/types.ts | 2 +- .../src/__tests__/moveLabware.test.ts | 64 ++++++++++++++++++- .../src/commandCreators/atomic/moveLabware.ts | 25 +++++++- step-generation/src/errorCreators.ts | 7 ++ .../forMoveLabware.ts | 2 + step-generation/src/types.ts | 1 + 11 files changed, 148 insertions(+), 14 deletions(-) diff --git a/protocol-designer/src/load-file/migration/8_0_0.ts b/protocol-designer/src/load-file/migration/8_0_0.ts index c7afb0bbffe..734f2f9ea46 100644 --- a/protocol-designer/src/load-file/migration/8_0_0.ts +++ b/protocol-designer/src/load-file/migration/8_0_0.ts @@ -18,12 +18,12 @@ import type { CommandV8Mixin, LabwareV2Mixin, LiquidV1Mixin, + LoadLabwareCreateCommand, OT2RobotMixin, OT3RobotMixin, ProtocolBase, ProtocolFile, } from '@opentrons/shared-data/protocol/types/schemaV8' -import type { LoadLabwareCreateCommand } from '@opentrons/shared-data/protocol/types/schemaV7' import type { DesignerApplicationData } from './utils/getLoadLiquidCommands' // NOTE: this migration is to schema v8 and updates fixed trash by diff --git a/protocol-designer/src/localization/en/alert.json b/protocol-designer/src/localization/en/alert.json index bf391dfa358..d4412ea07a8 100644 --- a/protocol-designer/src/localization/en/alert.json +++ b/protocol-designer/src/localization/en/alert.json @@ -163,6 +163,10 @@ "ADDITIONAL_EQUIPMENT_DOES_NOT_EXIST": { "title": "{{additionalEquipment}} does not exist", "body": "Attempting to interact with an unknown entity." + }, + "GRIPPER_REQUIRED": { + "title": "A gripper is required to complete this action", + "body": "Attempting to move a labware without a gripper into the waste chute. Please add a gripper to this step." } }, "warning": { diff --git a/protocol-designer/src/steplist/fieldLevel/index.ts b/protocol-designer/src/steplist/fieldLevel/index.ts index 0eae673ff73..d9a86262b12 100644 --- a/protocol-designer/src/steplist/fieldLevel/index.ts +++ b/protocol-designer/src/steplist/fieldLevel/index.ts @@ -42,6 +42,7 @@ import { PipetteEntity, InvariantContext, LabwareEntities, + AdditionalEquipmentEntities, } from '@opentrons/step-generation' import { StepFieldName } from '../../form-types' import type { LabwareLocation } from '@opentrons/shared-data' @@ -64,6 +65,14 @@ const getIsAdapterLocation = ( labwareEntities[newLocation].def.allowedRoles?.includes('adapter') ?? false ) } +const getIsWasteChuteLocation = ( + newLocation: string, + additionalEquipmentEntities: AdditionalEquipmentEntities +): boolean => + Object.values(additionalEquipmentEntities).find( + aE => aE.location === newLocation && aE.name === 'wasteChute' + ) != null + const getLabwareLocation = ( state: InvariantContext, newLocationString: string @@ -77,6 +86,15 @@ const getLabwareLocation = ( getIsAdapterLocation(newLocationString, state.labwareEntities) ) { return { labwareId: newLocationString } + } else if ( + getIsWasteChuteLocation( + newLocationString, + state.additionalEquipmentEntities + ) + ) { + return { + addressableAreaName: 'gripperWasteChute', + } } else { return { slotName: newLocationString } } diff --git a/protocol-designer/src/ui/labware/__tests__/selectors.test.ts b/protocol-designer/src/ui/labware/__tests__/selectors.test.ts index c3388d91825..2e3ba647add 100644 --- a/protocol-designer/src/ui/labware/__tests__/selectors.test.ts +++ b/protocol-designer/src/ui/labware/__tests__/selectors.test.ts @@ -149,6 +149,7 @@ describe('labware selectors', () => { names, initialDeckSetup, {}, + {}, {} ) ).toEqual([ @@ -179,6 +180,7 @@ describe('labware selectors', () => { names, initialDeckSetup, presavedStepForm, + {}, {} ) ).toEqual([ @@ -261,6 +263,7 @@ describe('labware selectors', () => { nicknames, initialDeckSetup, {}, + {}, {} ) ).toEqual([ @@ -317,11 +320,13 @@ describe('labware selectors', () => { labwareEntities, nicknames, initialDeckSetup, - savedStep + {}, + savedStep, + {} ) ).toEqual([ { name: 'Trash', value: mockTrash }, - { name: 'Well Plate in Magnetic Module', value: 'wellPlateId' }, + { name: 'Well Plate', value: 'wellPlateId' }, ]) }) }) diff --git a/protocol-designer/src/ui/labware/selectors.ts b/protocol-designer/src/ui/labware/selectors.ts index 7ee927c1ff7..f14923369a0 100644 --- a/protocol-designer/src/ui/labware/selectors.ts +++ b/protocol-designer/src/ui/labware/selectors.ts @@ -48,14 +48,20 @@ export const getLabwareOptions: Selector = createSelector( stepFormSelectors.getInitialDeckSetup, stepFormSelectors.getPresavedStepForm, stepFormSelectors.getSavedStepForms, + stepFormSelectors.getAdditionalEquipmentEntities, ( labwareEntities, nicknamesById, initialDeckSetup, presavedStepForm, - savedStepForms + savedStepForms, + additionalEquipmentEntities ) => { const moveLabwarePresavedStep = presavedStepForm?.stepType === 'moveLabware' + const wasteChuteLocation = Object.values(additionalEquipmentEntities).find( + aE => aE.name === 'wasteChute' + )?.location + const options = reduce( labwareEntities, ( @@ -63,6 +69,13 @@ export const getLabwareOptions: Selector = createSelector( labwareEntity: LabwareEntity, labwareId: string ): Options => { + const isLabwareInWasteChute = Object.values(savedStepForms).find( + form => + form.stepType === 'moveLabware' && + form.labware === labwareId && + form.newLocation === wasteChuteLocation + ) + const isAdapter = labwareEntity.def.allowedRoles?.includes('adapter') const isOffDeck = getLabwareOffDeck( initialDeckSetup, @@ -94,7 +107,11 @@ export const getLabwareOptions: Selector = createSelector( } if (!moveLabwarePresavedStep) { - return getIsTiprack(labwareEntity.def) || isAdapter + // filter out tip racks, adapters, and labware in waste chute + // for aspirating/dispensing/mixing into + return getIsTiprack(labwareEntity.def) || + isAdapter || + isLabwareInWasteChute ? acc : [ ...acc, @@ -104,8 +121,11 @@ export const getLabwareOptions: Selector = createSelector( }, ] } else { - // filter out moving trash for now in MoveLabware step type - return nickName === TRASH || isAdapterOrAluminumBlock + // filter out moving trash, aluminum blocks, adapters and labware in + // waste chute for moveLabware + return nickName === TRASH || + isAdapterOrAluminumBlock || + isLabwareInWasteChute ? acc : [ ...acc, diff --git a/shared-data/js/types.ts b/shared-data/js/types.ts index 3d0ad89ff3e..79e84d2af33 100644 --- a/shared-data/js/types.ts +++ b/shared-data/js/types.ts @@ -31,8 +31,8 @@ import { } from './constants' import type { INode } from 'svgson' import type { RunTimeCommand, LabwareLocation } from '../command/types' -import type { PipetteName } from './pipettes' import type { AddressableAreaName, CutoutFixtureId, CutoutId } from '../deck' +import type { PipetteName } from './pipettes' export type RobotType = 'OT-2 Standard' | 'OT-3 Standard' diff --git a/step-generation/src/__tests__/moveLabware.test.ts b/step-generation/src/__tests__/moveLabware.test.ts index f6d8ac69c1f..12ecf2e46a8 100644 --- a/step-generation/src/__tests__/moveLabware.test.ts +++ b/step-generation/src/__tests__/moveLabware.test.ts @@ -17,6 +17,7 @@ import { moveLabware, MoveLabwareArgs } from '..' import type { InvariantContext, RobotState } from '../types' const mockWasteChuteId = 'mockWasteChuteId' +const mockGripperId = 'mockGripperId' describe('moveLabware', () => { let robotState: RobotState @@ -24,6 +25,16 @@ describe('moveLabware', () => { beforeEach(() => { invariantContext = makeContext() robotState = getInitialRobotStateStandard(invariantContext) + + invariantContext = { + ...invariantContext, + additionalEquipmentEntities: { + mockGripperId: { + name: 'gripper', + id: mockGripperId, + }, + }, + } }) afterEach(() => { jest.resetAllMocks() @@ -129,7 +140,7 @@ describe('moveLabware', () => { const params = { commandCreatorFnName: 'moveLabware', labware: SOURCE_LABWARE, - useGripper: true, + useGripper: false, newLocation: { moduleId: thermocyclerId }, } as MoveLabwareArgs @@ -246,6 +257,7 @@ describe('moveLabware', () => { const wasteChuteInvariantContext = { ...invariantContext, additionalEquipmentEntities: { + ...invariantContext.additionalEquipmentEntities, mockWasteChuteId: { name: 'wasteChute', id: mockWasteChuteId, @@ -266,7 +278,7 @@ describe('moveLabware', () => { commandCreatorFnName: 'moveLabware', labware: TIPRACK_1, useGripper: true, - newLocation: { slotName: WASTE_CHUTE_CUTOUT }, + newLocation: { addressableAreaName: 'gripperWasteChute' }, } as MoveLabwareArgs const result = moveLabware( @@ -285,6 +297,7 @@ describe('moveLabware', () => { const wasteChuteInvariantContext = { ...invariantContext, additionalEquipmentEntities: { + ...invariantContext.additionalEquipmentEntities, mockWasteChuteId: { name: 'wasteChute', id: mockWasteChuteId, @@ -304,7 +317,7 @@ describe('moveLabware', () => { commandCreatorFnName: 'moveLabware', labware: SOURCE_LABWARE, useGripper: true, - newLocation: { slotName: WASTE_CHUTE_CUTOUT }, + newLocation: { addressableAreaName: 'gripperWasteChute' }, } as MoveLabwareArgs const result = moveLabware( @@ -319,4 +332,49 @@ describe('moveLabware', () => { }, ]) }) + it('should return an error when trying to move with gripper when there is no gripper', () => { + invariantContext = { + ...invariantContext, + additionalEquipmentEntities: {}, + } as InvariantContext + + const params = { + commandCreatorFnName: 'moveLabware', + labware: SOURCE_LABWARE, + useGripper: true, + newLocation: { slotName: 'A1' }, + } as MoveLabwareArgs + + const result = moveLabware(params, invariantContext, robotState) + expect(getErrorResult(result).errors).toHaveLength(1) + expect(getErrorResult(result).errors[0]).toMatchObject({ + type: 'GRIPPER_REQUIRED', + }) + }) + it('should return an error when trying to move into the waste chute when useGripper is not selected', () => { + invariantContext = { + ...invariantContext, + additionalEquipmentEntities: { + ...invariantContext.additionalEquipmentEntities, + mockWasteChuteId: { + name: 'wasteChute', + id: mockWasteChuteId, + location: WASTE_CHUTE_CUTOUT, + }, + }, + } as InvariantContext + + const params = { + commandCreatorFnName: 'moveLabware', + labware: SOURCE_LABWARE, + useGripper: false, + newLocation: { addressableAreaName: 'gripperWasteChute' }, + } as MoveLabwareArgs + + const result = moveLabware(params, invariantContext, robotState) + expect(getErrorResult(result).errors).toHaveLength(1) + expect(getErrorResult(result).errors[0]).toMatchObject({ + type: 'GRIPPER_REQUIRED', + }) + }) }) diff --git a/step-generation/src/commandCreators/atomic/moveLabware.ts b/step-generation/src/commandCreators/atomic/moveLabware.ts index 3f3929ecf81..46962e1bb76 100644 --- a/step-generation/src/commandCreators/atomic/moveLabware.ts +++ b/step-generation/src/commandCreators/atomic/moveLabware.ts @@ -3,7 +3,6 @@ import { HEATERSHAKER_MODULE_TYPE, LabwareMovementStrategy, THERMOCYCLER_MODULE_TYPE, - WASTE_CHUTE_CUTOUT, } from '@opentrons/shared-data' import * as errorCreators from '../../errorCreators' import * as warningCreators from '../../warningCreators' @@ -28,6 +27,7 @@ export const moveLabware: CommandCreator = ( ) => { const { labware, useGripper, newLocation } = args const { additionalEquipmentEntities } = invariantContext + const hasWasteChute = getHasWasteChute(additionalEquipmentEntities) const tiprackHasTip = prevRobotState.tipState != null ? getTiprackHasTips(prevRobotState.tipState, labware) @@ -43,8 +43,12 @@ export const moveLabware: CommandCreator = ( const newLocationInWasteChute = newLocation !== 'offDeck' && - 'slotName' in newLocation && - newLocation.slotName === WASTE_CHUTE_CUTOUT + 'addressableAreaName' in newLocation && + newLocation.addressableAreaName === 'gripperWasteChute' + + const hasGripper = Object.values(additionalEquipmentEntities).find( + aE => aE.name === 'gripper' + ) if (!labware || !prevRobotState.labware[labware]) { errors.push( @@ -57,6 +61,13 @@ export const moveLabware: CommandCreator = ( errors.push(errorCreators.labwareOffDeck()) } + if ( + (newLocationInWasteChute && hasGripper && !useGripper) || + (!hasGripper && useGripper) + ) { + errors.push(errorCreators.gripperRequired()) + } + const initialLabwareSlot = prevRobotState.labware[labware]?.slot const initialAdapterSlot = prevRobotState.labware[initialLabwareSlot]?.slot const initialSlot = @@ -98,6 +109,13 @@ export const moveLabware: CommandCreator = ( if (newLocation === 'offDeck' && useGripper) { errors.push(errorCreators.labwareOffDeck()) } + + if (tiprackHasTip && newLocationInWasteChute && hasWasteChute) { + warnings.push(warningCreators.tiprackInWasteChuteHasTips()) + } else if (labwareHasLiquid && newLocationInWasteChute && hasWasteChute) { + warnings.push(warningCreators.labwareInWasteChuteHasLiquid()) + } + if ( destinationModuleIdOrSlot != null && prevRobotState.modules[destinationModuleIdOrSlot] != null @@ -139,6 +157,7 @@ export const moveLabware: CommandCreator = ( params, }, ] + return { commands, warnings: warnings.length > 0 ? warnings : undefined, diff --git a/step-generation/src/errorCreators.ts b/step-generation/src/errorCreators.ts index be1407c2b97..f3364dc8b8e 100644 --- a/step-generation/src/errorCreators.ts +++ b/step-generation/src/errorCreators.ts @@ -211,3 +211,10 @@ export const additionalEquipmentDoesNotExist = (args: { message: `The ${args.additionalEquipment} does not exist`, } } + +export const gripperRequired = (): CommandCreatorError => { + return { + type: 'GRIPPER_REQUIRED', + message: 'The gripper is required to fulfill this action', + } +} diff --git a/step-generation/src/getNextRobotStateAndWarnings/forMoveLabware.ts b/step-generation/src/getNextRobotStateAndWarnings/forMoveLabware.ts index 56ddf85115e..389860d302b 100644 --- a/step-generation/src/getNextRobotStateAndWarnings/forMoveLabware.ts +++ b/step-generation/src/getNextRobotStateAndWarnings/forMoveLabware.ts @@ -18,6 +18,8 @@ export function forMoveLabware( newLocationString = newLocation.slotName } else if ('labwareId' in newLocation) { newLocationString = newLocation.labwareId + } else if ('addressableAreaName' in newLocation) { + newLocationString = newLocation.addressableAreaName } robotState.labware[labwareId].slot = newLocationString diff --git a/step-generation/src/types.ts b/step-generation/src/types.ts index 4d5fdfe5340..dcc18666ad3 100644 --- a/step-generation/src/types.ts +++ b/step-generation/src/types.ts @@ -492,6 +492,7 @@ export interface RobotState { export type ErrorType = | 'ADDITIONAL_EQUIPMENT_DOES_NOT_EXIST' | 'DROP_TIP_LOCATION_DOES_NOT_EXIST' + | 'GRIPPER_REQUIRED' | 'HEATER_SHAKER_EAST_WEST_LATCH_OPEN' | 'HEATER_SHAKER_EAST_WEST_MULTI_CHANNEL' | 'HEATER_SHAKER_IS_SHAKING' From 0498609ee1047f0f178f562cfc9aa9f36829e4d8 Mon Sep 17 00:00:00 2001 From: Jethary Rader <66035149+jerader@users.noreply.github.com> Date: Tue, 14 Nov 2023 11:15:11 -0500 Subject: [PATCH 61/65] feat(protocol-designer): deck v4 touchups and staging area support (#13965) closes RAUT-787, RAUT-805, RAUT-806, RAUT-850 --- .../BaseDeck/StagingAreaFixture.tsx | 14 +- .../components/DeckSetup/FlexModuleTag.tsx | 2 +- .../LabwareOverlays/SlotControls.tsx | 4 +- .../__tests__/FlexModuleTag.test.tsx | 4 +- .../src/components/DeckSetup/index.tsx | 96 +++++++----- .../__tests__/FileSidebar.test.tsx | 6 +- .../__tests__/getUnusedStagingAreas.test.ts | 24 ++- .../utils/getUnusedStagingAreas.ts | 22 +-- .../CreateFileWizard/__tests__/utils.test.tsx | 10 +- .../modals/CreateFileWizard/types.ts | 8 +- .../modals/CreateFileWizard/utils.ts | 18 +-- .../src/components/modules/ModuleRow.tsx | 8 +- .../components/modules/StagingAreasModal.tsx | 9 +- .../src/components/modules/TrashModal.tsx | 2 +- .../modules/__tests__/ModuleRow.test.tsx | 2 +- protocol-designer/src/constants.ts | 2 + .../src/file-data/selectors/fileCreator.ts | 28 ---- .../src/step-forms/reducers/index.ts | 139 ++++++++++++------ .../src/step-forms/utils/index.ts | 17 ++- .../top-selectors/labware-locations/index.ts | 44 +++++- protocol-designer/src/ui/labware/selectors.ts | 22 +++ protocol-designer/src/utils/index.ts | 27 +++- shared-data/deck/types/schemaV4.ts | 10 +- shared-data/js/constants.ts | 5 +- shared-data/js/helpers/index.ts | 7 +- .../src/__tests__/aspirate.test.ts | 23 +++ .../src/__tests__/dispense.test.ts | 13 ++ .../src/__tests__/moveToWell.test.ts | 21 +++ .../src/commandCreators/atomic/aspirate.ts | 5 + .../src/commandCreators/atomic/blowout.ts | 15 +- .../src/commandCreators/atomic/dispense.ts | 5 + .../src/commandCreators/atomic/moveToWell.ts | 7 + .../src/commandCreators/atomic/replaceTip.ts | 6 + step-generation/src/constants.ts | 2 + step-generation/src/errorCreators.ts | 9 ++ step-generation/src/types.ts | 1 + 36 files changed, 451 insertions(+), 186 deletions(-) diff --git a/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx b/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx index 3e87517110a..107da94b8c2 100644 --- a/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx +++ b/components/src/hardware-sim/BaseDeck/StagingAreaFixture.tsx @@ -5,7 +5,11 @@ import { SlotClip } from './SlotClip' import type { DeckDefinition, ModuleType } from '@opentrons/shared-data' -export type StagingAreaLocation = 'A3' | 'B3' | 'C3' | 'D3' +export type StagingAreaLocation = + | 'cutoutA3' + | 'cutoutB3' + | 'cutoutC3' + | 'cutoutD3' interface StagingAreaFixtureProps extends React.SVGProps { cutoutId: StagingAreaLocation @@ -40,7 +44,7 @@ export function StagingAreaFixture( const contentsByCutoutLocation: { [cutoutId in StagingAreaLocation]: JSX.Element } = { - A3: ( + cutoutA3: ( <> ), - B3: ( + cutoutB3: ( <> ), - C3: ( + cutoutC3: ( <> ), - D3: ( + cutoutD3: ( <> unknown diff --git a/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx b/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx index f1945aac1c9..6c8cb890003 100644 --- a/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx +++ b/protocol-designer/src/components/DeckSetup/__tests__/FlexModuleTag.test.tsx @@ -28,7 +28,7 @@ describe('FlexModuleTag', () => { .calledWith( partialComponentPropsMatcher({ width: 5, - height: 16, + height: 20, }) ) .mockImplementation(({ children }) => ( @@ -48,7 +48,7 @@ describe('FlexModuleTag', () => { .calledWith( partialComponentPropsMatcher({ width: 5, - height: 16, + height: 20, }) ) .mockImplementation(({ children }) => ( diff --git a/protocol-designer/src/components/DeckSetup/index.tsx b/protocol-designer/src/components/DeckSetup/index.tsx index 3b351618d50..ed443435e00 100644 --- a/protocol-designer/src/components/DeckSetup/index.tsx +++ b/protocol-designer/src/components/DeckSetup/index.tsx @@ -3,18 +3,18 @@ import { useDispatch, useSelector } from 'react-redux' import compact from 'lodash/compact' import values from 'lodash/values' import { - useOnClickOutside, - RobotWorkSpaceRenderProps, - Module, COLORS, - TrashLocation, + DeckFromLayers, FlexTrash, + Module, RobotCoordinateSpaceWithDOMCoords, - WasteChuteFixture, + RobotWorkSpaceRenderProps, + SingleSlotFixture, StagingAreaFixture, StagingAreaLocation, - SingleSlotFixture, - DeckFromLayers, + TrashLocation, + useOnClickOutside, + WasteChuteFixture, } from '@opentrons/components' import { AdditionalEquipmentEntity, @@ -22,29 +22,28 @@ import { ModuleTemporalProperties, } from '@opentrons/step-generation' import { - getLabwareHasQuirk, - inferModuleOrientationFromSlot, + FLEX_ROBOT_TYPE, + getAddressableAreaFromSlotId, getDeckDefFromRobotType, - OT2_ROBOT_TYPE, + getLabwareHasQuirk, getModuleDef2, + getModuleDisplayName, + getPositionFromSlotId, + inferModuleOrientationFromSlot, inferModuleOrientationFromXCoordinate, + isAddressableAreaStandardSlot, + OT2_ROBOT_TYPE, + STAGING_AREA_LOAD_NAME, THERMOCYCLER_MODULE_TYPE, - getModuleDisplayName, - DeckDefinition, - RobotType, - FLEX_ROBOT_TYPE, TRASH_BIN_LOAD_NAME, - STAGING_AREA_LOAD_NAME, WASTE_CHUTE_CUTOUT, WASTE_CHUTE_LOAD_NAME, - AddressableAreaName, - CutoutFixture, - CutoutId, } from '@opentrons/shared-data' import { FLEX_TRASH_DEF_URI, OT_2_TRASH_DEF_URI } from '../../constants' import { selectors as labwareDefSelectors } from '../../labware-defs' import { selectors as featureFlagSelectors } from '../../feature-flags' +import { getStagingAreaAddressableAreas } from '../../utils' import { getSlotIdsBlockedBySpanning, getSlotIsEmpty, @@ -72,12 +71,15 @@ import { Ot2ModuleTag } from './Ot2ModuleTag' import { SlotLabels } from './SlotLabels' import { getHasGen1MultiChannelPipette, getSwapBlocked } from './utils' +import type { + AddressableAreaName, + CutoutFixture, + CutoutId, + DeckDefinition, + RobotType, +} from '@opentrons/shared-data' + import styles from './DeckSetup.css' -import { - getAddressableAreaFromSlotId, - getPositionFromSlotId, - isAddressableAreaStandardSlot, -} from '@opentrons/shared-data/js' export const DECK_LAYER_BLOCKLIST = [ 'calibrationMarkings', @@ -89,6 +91,16 @@ export const DECK_LAYER_BLOCKLIST = [ 'screwHoles', ] +const OT2_STANDARD_DECK_VIEW_LAYER_BLOCK_LIST: string[] = [ + 'calibrationMarkings', + 'fixedBase', + 'doorStops', + 'metalFrame', + 'removalHandle', + 'removableDeckOutline', + 'screwHoles', +] + interface ContentsProps { getRobotCoordsFromDOMCoords: RobotWorkSpaceRenderProps['getRobotCoordsFromDOMCoords'] activeDeckSetup: InitialDeckSetup @@ -96,6 +108,7 @@ interface ContentsProps { showGen1MultichannelCollisionWarnings: boolean deckDef: DeckDefinition robotType: RobotType + stagingAreaCutoutIds: CutoutId[] trashSlot: string | null } @@ -110,6 +123,7 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { deckDef, robotType, trashSlot, + stagingAreaCutoutIds, } = props // NOTE: handling module<>labware compat when moving labware to empty module // is handled by SlotControls. @@ -173,12 +187,6 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { ]) : [] - console.log( - 'AA', - deckDef.locations.addressableAreas.filter(addressableArea => - isAddressableAreaStandardSlot(addressableArea.id, deckDef) - ) - ) return ( <> {/* all modules */} @@ -300,6 +308,7 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { selectedTerminalItemId={props.selectedTerminalItemId} moduleType={moduleOnDeck.type} handleDragHover={handleHoverEmptySlot} + slotId={moduleOnDeck.id} /> ) : null} {robotType === FLEX_ROBOT_TYPE ? ( @@ -336,16 +345,22 @@ export const DeckSetupContents = (props: ContentsProps): JSX.Element => { ) : null })} - {/* SlotControls for all empty deck + module slots */} + {/* SlotControls for all empty deck */} {deckDef.locations.addressableAreas - // only render standard slot fixture components - .filter( - addressableArea => - isAddressableAreaStandardSlot(addressableArea.id, deckDef) && + .filter(addressableArea => { + const stagingAreaAddressableAreas = getStagingAreaAddressableAreas( + stagingAreaCutoutIds + ) + const addressableAreas = + isAddressableAreaStandardSlot(addressableArea.id, deckDef) || + stagingAreaAddressableAreas.includes(addressableArea.id) + return ( + addressableAreas && !slotIdsBlockedBySpanning.includes(addressableArea.id) && getSlotIsEmpty(activeDeckSetup, addressableArea.id) && addressableArea.id !== trashSlot - ) + ) + }) .map(addressableArea => { return ( // @ts-expect-error @@ -534,7 +549,6 @@ export const DeckSetup = (): JSX.Element => { const filteredAddressableAreas = deckDef.locations.addressableAreas.filter( aa => isAddressableAreaStandardSlot(aa.id, deckDef) ) - return (
    {drilledDown && } @@ -547,7 +561,10 @@ export const DeckSetup = (): JSX.Element => { {({ getRobotCoordsFromDOMCoords }) => ( <> {robotType === OT2_ROBOT_TYPE ? ( - + ) : ( <> {filteredAddressableAreas.map(addressableArea => { @@ -613,6 +630,11 @@ export const DeckSetup = (): JSX.Element => { robotType={robotType} activeDeckSetup={activeDeckSetup} selectedTerminalItemId={selectedTerminalItemId} + stagingAreaCutoutIds={stagingAreaFixtures.map( + // TODO(jr, 11/13/23): fix this type since AdditionalEquipment['location'] is type string + // instead of CutoutId + areas => areas.location as CutoutId + )} {...{ deckDef, getRobotCoordsFromDOMCoords, diff --git a/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx b/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx index 88b9ae98d9a..2a19aab1d42 100644 --- a/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx +++ b/protocol-designer/src/components/FileSidebar/__tests__/FileSidebar.test.tsx @@ -165,7 +165,11 @@ describe('FileSidebar', () => { // @ts-expect-error(sa, 2021-6-22): props.fileData might be null props.fileData.commands = commands props.additionalEquipment = { - [stagingArea]: { name: 'stagingArea', id: stagingArea, location: 'A3' }, + [stagingArea]: { + name: 'stagingArea', + id: stagingArea, + location: 'cutoutA3', + }, } const wrapper = shallow() diff --git a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts index 333a6aee456..e95f2c06d3f 100644 --- a/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts +++ b/protocol-designer/src/components/FileSidebar/utils/__tests__/getUnusedStagingAreas.test.ts @@ -6,7 +6,11 @@ describe('getUnusedStagingAreas', () => { it('returns true for unused staging area', () => { const stagingArea = 'stagingAreaId' const mockAdditionalEquipment = { - [stagingArea]: { name: 'stagingArea', id: stagingArea, location: 'A3' }, + [stagingArea]: { + name: 'stagingArea', + id: stagingArea, + location: 'cutoutA3', + }, } as AdditionalEquipment expect(getUnusedStagingAreas(mockAdditionalEquipment, [])).toEqual(['A4']) @@ -15,8 +19,16 @@ describe('getUnusedStagingAreas', () => { const stagingArea = 'stagingAreaId' const stagingArea2 = 'stagingAreaId2' const mockAdditionalEquipment = { - [stagingArea]: { name: 'stagingArea', id: stagingArea, location: 'A3' }, - [stagingArea2]: { name: 'stagingArea', id: stagingArea2, location: 'B3' }, + [stagingArea]: { + name: 'stagingArea', + id: stagingArea, + location: 'cutoutA3', + }, + [stagingArea2]: { + name: 'stagingArea', + id: stagingArea2, + location: 'cutoutB3', + }, } as AdditionalEquipment expect(getUnusedStagingAreas(mockAdditionalEquipment, [])).toEqual([ @@ -27,7 +39,11 @@ describe('getUnusedStagingAreas', () => { it('returns false for unused staging area', () => { const stagingArea = 'stagingAreaId' const mockAdditionalEquipment = { - [stagingArea]: { name: 'stagingArea', id: stagingArea, location: 'A3' }, + [stagingArea]: { + name: 'stagingArea', + id: stagingArea, + location: 'cutoutA3', + }, } as AdditionalEquipment const mockCommand = ([ { diff --git a/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts b/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts index a701858a9eb..ea68068390c 100644 --- a/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts +++ b/protocol-designer/src/components/FileSidebar/utils/getUnusedStagingAreas.ts @@ -1,11 +1,12 @@ -import type { CreateCommand } from '@opentrons/shared-data' +import { getStagingAreaAddressableAreas } from '../../../utils' +import type { CreateCommand, CutoutId } from '@opentrons/shared-data' import type { AdditionalEquipment } from '../FileSidebar' export const getUnusedStagingAreas = ( additionalEquipment: AdditionalEquipment, commands?: CreateCommand[] ): string[] => { - const stagingAreaSlots = Object.values(additionalEquipment) + const stagingAreaCutoutIds = Object.values(additionalEquipment) .filter(equipment => equipment?.name === 'stagingArea') .map(equipment => { if (equipment.location == null) { @@ -16,19 +17,12 @@ export const getUnusedStagingAreas = ( return equipment.location ?? '' }) - const corresponding4thColumnSlots = stagingAreaSlots.map(slot => { - const letter = slot.charAt(0) - const correspondingLocation = stagingAreaSlots.find(slot => - slot.startsWith(letter) - ) - if (correspondingLocation) { - return letter + '4' - } - - return slot - }) + const stagingAreaAddressableAreaNames = getStagingAreaAddressableAreas( + // TODO(jr, 11/13/23): fix AdditionalEquipment['location'] from type string to CutoutId + stagingAreaCutoutIds as CutoutId[] + ) - const stagingAreaCommandSlots: string[] = corresponding4thColumnSlots.filter( + const stagingAreaCommandSlots: string[] = stagingAreaAddressableAreaNames.filter( location => commands?.filter( command => diff --git a/protocol-designer/src/components/modals/CreateFileWizard/__tests__/utils.test.tsx b/protocol-designer/src/components/modals/CreateFileWizard/__tests__/utils.test.tsx index fff9f9c446b..756142495e1 100644 --- a/protocol-designer/src/components/modals/CreateFileWizard/__tests__/utils.test.tsx +++ b/protocol-designer/src/components/modals/CreateFileWizard/__tests__/utils.test.tsx @@ -55,10 +55,10 @@ describe('getLastCheckedEquipment', () => { ...MOCK_FORM_STATE, additionalEquipment: [ 'trashBin', - 'stagingArea_A3', - 'stagingArea_B3', - 'stagingArea_C3', - 'stagingArea_D3', + 'stagingArea_cutoutA3', + 'stagingArea_cutoutB3', + 'stagingArea_cutoutC3', + 'stagingArea_cutoutD3', ], modulesByType: { ...MOCK_FORM_STATE.modulesByType, @@ -83,7 +83,7 @@ describe('getTrashSlot', () => { it('should return B3 when there is a staging area in slot A3', () => { MOCK_FORM_STATE = { ...MOCK_FORM_STATE, - additionalEquipment: ['stagingArea_A3'], + additionalEquipment: ['stagingArea_cutoutA3'], } const result = getTrashSlot(MOCK_FORM_STATE) expect(result).toBe('B3') diff --git a/protocol-designer/src/components/modals/CreateFileWizard/types.ts b/protocol-designer/src/components/modals/CreateFileWizard/types.ts index 8eb99fa5dba..1c15b081f9a 100644 --- a/protocol-designer/src/components/modals/CreateFileWizard/types.ts +++ b/protocol-designer/src/components/modals/CreateFileWizard/types.ts @@ -10,10 +10,10 @@ export type AdditionalEquipment = | 'gripper' | 'wasteChute' | 'trashBin' - | 'stagingArea_A3' - | 'stagingArea_B3' - | 'stagingArea_C3' - | 'stagingArea_D3' + | 'stagingArea_cutoutA3' + | 'stagingArea_cutoutB3' + | 'stagingArea_cutoutC3' + | 'stagingArea_cutoutD3' export interface FormState { fields: NewProtocolFields pipettesByMount: FormPipettesByMount diff --git a/protocol-designer/src/components/modals/CreateFileWizard/utils.ts b/protocol-designer/src/components/modals/CreateFileWizard/utils.ts index 84e5b585c99..ef367349783 100644 --- a/protocol-designer/src/components/modals/CreateFileWizard/utils.ts +++ b/protocol-designer/src/components/modals/CreateFileWizard/utils.ts @@ -4,6 +4,7 @@ import { TEMPERATURE_MODULE_TYPE, THERMOCYCLER_MODULE_TYPE, } from '@opentrons/shared-data' +import { COLUMN_3_SLOTS } from '../../../constants' import { OUTER_SLOTS_FLEX } from '../../../modules' import { isModuleWithCollisionIssue } from '../../modules' import { @@ -81,12 +82,14 @@ export const getTrashBinOptionDisabled = (values: FormState): boolean => { } export const getTrashSlot = (values: FormState): string => { - const stagingAreaLocations = values.additionalEquipment - .filter(equipment => equipment.includes('stagingArea')) - .map(stagingArea => stagingArea.split('_')[1]) + const stagingAddressableAreas = values.additionalEquipment.filter(equipment => + equipment.includes('stagingArea') + ) + const cutouts = stagingAddressableAreas.flatMap(aa => + COLUMN_3_SLOTS.filter(cutout => aa.includes(cutout)) + ) - // return default trash slot A3 if staging area is not on slot - if (!stagingAreaLocations.includes(FLEX_TRASH_DEFAULT_SLOT)) { + if (!cutouts.includes(FLEX_TRASH_DEFAULT_SLOT)) { return FLEX_TRASH_DEFAULT_SLOT } @@ -103,11 +106,8 @@ export const getTrashSlot = (values: FormState): string => { }, [] ) - const unoccupiedSlot = OUTER_SLOTS_FLEX.find( - slot => - !stagingAreaLocations.includes(slot.value) && - !moduleSlots.includes(slot.value) + slot => !cutouts.includes(slot.value) && !moduleSlots.includes(slot.value) ) if (unoccupiedSlot == null) { console.error( diff --git a/protocol-designer/src/components/modules/ModuleRow.tsx b/protocol-designer/src/components/modules/ModuleRow.tsx index 08c1c2ca9f3..073082878b3 100644 --- a/protocol-designer/src/components/modules/ModuleRow.tsx +++ b/protocol-designer/src/components/modules/ModuleRow.tsx @@ -23,11 +23,11 @@ import { DEFAULT_MODEL_FOR_MODULE_TYPE, } from '../../constants' import { ModuleDiagram } from './ModuleDiagram' +import { FlexSlotMap } from './FlexSlotMap' import { isModuleWithCollisionIssue } from './utils' import styles from './styles.css' import type { ModuleType, RobotType } from '@opentrons/shared-data' -import { FlexSlotMap } from './FlexSlotMap' interface Props { robotType?: RobotType @@ -68,17 +68,17 @@ export function ModuleRow(props: Props): JSX.Element { // If this module is in a deck slot + is not TC spanning Slot // add to occupiedSlots if (slot && slot !== SPAN7_8_10_11_SLOT) { - slotDisplayName = `Slot ${slot}` + slotDisplayName = slot occupiedSlotsForMap = [slot] } // If this Module is a TC deck slot and spanning // populate all 4 slots individually if (slot === SPAN7_8_10_11_SLOT) { - slotDisplayName = 'Slot 7,8,10,11' + slotDisplayName = '7,8,10,11' occupiedSlotsForMap = ['7', '8', '10', '11'] // TC on Flex } else if (isFlex && type === THERMOCYCLER_MODULE_TYPE && slot === 'B1') { - slotDisplayName = 'Slot A1+B1' + slotDisplayName = 'A1+B1' occupiedSlotsForMap = ['A1', 'B1'] } // If collisionSlots are populated, check which slot is occupied diff --git a/protocol-designer/src/components/modules/StagingAreasModal.tsx b/protocol-designer/src/components/modules/StagingAreasModal.tsx index 7bfc762bb29..79725aa5147 100644 --- a/protocol-designer/src/components/modules/StagingAreasModal.tsx +++ b/protocol-designer/src/components/modules/StagingAreasModal.tsx @@ -47,7 +47,14 @@ const StagingAreasModalComponent = ( const areSlotsEmpty = values.selectedSlots.map(slot => getSlotIsEmpty(initialDeckSetup, slot) ) - const hasConflictedSlot = areSlotsEmpty.includes(false) + const hasWasteChute = + Object.values(initialDeckSetup.additionalEquipmentOnDeck).find( + aE => aE.name === 'wasteChute' + ) != null + const hasConflictedSlot = + hasWasteChute && values.selectedSlots.find(slot => slot === 'cutoutD3') + ? false + : areSlotsEmpty.includes(false) const mappedStagingAreas = stagingAreas.flatMap(area => { return [ diff --git a/protocol-designer/src/components/modules/TrashModal.tsx b/protocol-designer/src/components/modules/TrashModal.tsx index fb3a1a4762b..f9e33cd75be 100644 --- a/protocol-designer/src/components/modules/TrashModal.tsx +++ b/protocol-designer/src/components/modules/TrashModal.tsx @@ -154,7 +154,7 @@ export const TrashModal = (props: TrashModalProps): JSX.Element => { diff --git a/protocol-designer/src/components/modules/__tests__/ModuleRow.test.tsx b/protocol-designer/src/components/modules/__tests__/ModuleRow.test.tsx index ebb5ab60f17..2b240aae6ef 100644 --- a/protocol-designer/src/components/modules/__tests__/ModuleRow.test.tsx +++ b/protocol-designer/src/components/modules/__tests__/ModuleRow.test.tsx @@ -151,7 +151,7 @@ describe('ModuleRow', () => { ).toBe('GEN1') expect( wrapper.find(LabeledValue).filter({ label: 'Position' }).prop('value') - ).toBe('Slot 1') + ).toBe('1') }) it('does not display module model and slot when module has not been added to protocol', () => { diff --git a/protocol-designer/src/constants.ts b/protocol-designer/src/constants.ts index 92b2ba2d5df..e5b5bb6fe4e 100644 --- a/protocol-designer/src/constants.ts +++ b/protocol-designer/src/constants.ts @@ -159,3 +159,5 @@ export const THERMOCYCLER_PROFILE: 'thermocyclerProfile' = 'thermocyclerProfile' export const OT_2_TRASH_DEF_URI = 'opentrons/opentrons_1_trash_1100ml_fixed/1' export const FLEX_TRASH_DEF_URI = 'opentrons/opentrons_1_trash_3200ml_fixed/1' + +export const COLUMN_3_SLOTS = ['A3', 'B3', 'C3', 'D3'] diff --git a/protocol-designer/src/file-data/selectors/fileCreator.ts b/protocol-designer/src/file-data/selectors/fileCreator.ts index ed5aaa56638..89eba6b230e 100644 --- a/protocol-designer/src/file-data/selectors/fileCreator.ts +++ b/protocol-designer/src/file-data/selectors/fileCreator.ts @@ -41,16 +41,13 @@ import type { LabwareEntities, PipetteEntities, RobotState, - AdditionalEquipmentEntity, } from '@opentrons/step-generation' import type { CommandAnnotationV1Mixin, CommandV8Mixin, CreateCommand, - Cutout, LabwareV2Mixin, LiquidV1Mixin, - LoadFixtureCreateCommand, LoadLabwareCreateCommand, LoadModuleCreateCommand, LoadPipetteCreateCommand, @@ -300,30 +297,6 @@ export const createFile: Selector = createSelector( [] ) - // TODO(jr, 10/31/23): update to loadAddressableArea - const loadFixtureCommands = reduce< - AdditionalEquipmentEntity, - LoadFixtureCreateCommand[] - >( - Object.values(additionalEquipmentEntities), - (acc, additionalEquipment): LoadFixtureCreateCommand[] => { - if (additionalEquipment.name === 'gripper') return acc - - const loadFixtureCommands = { - key: uuid(), - commandType: 'loadFixture' as const, - params: { - fixtureId: additionalEquipment.id, - location: { cutout: additionalEquipment.location as Cutout }, - loadName: additionalEquipment.name, - }, - } - - return [...acc, loadFixtureCommands] - }, - [] - ) - const loadLiquidCommands = getLoadLiquidCommands( ingredients, ingredLocations @@ -356,7 +329,6 @@ export const createFile: Selector = createSelector( labwareDefsByURI ) const loadCommands: CreateCommand[] = [ - ...loadFixtureCommands, ...loadPipetteCommands, ...loadModuleCommands, ...loadAdapterCommands, diff --git a/protocol-designer/src/step-forms/reducers/index.ts b/protocol-designer/src/step-forms/reducers/index.ts index 87153305e6a..4a49a7f340a 100644 --- a/protocol-designer/src/step-forms/reducers/index.ts +++ b/protocol-designer/src/step-forms/reducers/index.ts @@ -20,9 +20,10 @@ import { MAGNETIC_MODULE_V1, PipetteName, THERMOCYCLER_MODULE_TYPE, - LoadFixtureCreateCommand, - STANDARD_SLOT_LOAD_NAME, - TRASH_BIN_LOAD_NAME, + WASTE_CHUTE_ADDRESSABLE_AREAS, + getDeckDefFromRobotTypeV4, + AddressableAreaName, + CutoutId, } from '@opentrons/shared-data' import type { RootState as LabwareDefsRootState } from '../../labware-defs' import { rootReducer as labwareDefsRootReducer } from '../../labware-defs' @@ -43,6 +44,7 @@ import { getLabwareOnModule } from '../../ui/modules/utils' import { nestedCombineReducers } from './nestedCombineReducers' import { PROFILE_CYCLE, PROFILE_STEP } from '../../form-types' import { + COLUMN_4_SLOTS, NormalizedAdditionalEquipmentById, NormalizedPipetteById, } from '@opentrons/step-generation' @@ -1329,58 +1331,111 @@ export const additionalEquipmentInvariantProperties = handleActions { const { file } = action.payload - const gripperCommands = Object.values(file.commands).filter( + const isFlex = file.robot.model === FLEX_ROBOT_TYPE + const deckDef = getDeckDefFromRobotTypeV4(FLEX_ROBOT_TYPE) + const cutoutFixtures = deckDef.cutoutFixtures + const providesAddressableAreasForAddressableArea = cutoutFixtures.find( + cutoutFixture => cutoutFixture.id.includes('stagingAreaRightSlot') + )?.providesAddressableAreas + + const hasGripperCommands = Object.values(file.commands).some( (command): command is MoveLabwareCreateCommand => command.commandType === 'moveLabware' && command.params.strategy === 'usingGripper' ) - const fixtureCommands = Object.values(file.commands).filter( - (command): command is LoadFixtureCreateCommand => - command.commandType === 'loadFixture' + const hasWasteChuteCommands = Object.values(file.commands).some( + command => + (command.commandType === 'moveToAddressableArea' && + WASTE_CHUTE_ADDRESSABLE_AREAS.includes( + command.params.addressableAreaName + )) || + (command.commandType === 'moveLabware' && + command.params.newLocation !== 'offDeck' && + 'addressableAreaName' in command.params.newLocation && + WASTE_CHUTE_ADDRESSABLE_AREAS.includes( + command.params.addressableAreaName + )) ) - const fixtures = fixtureCommands.reduce( - ( - acc: NormalizedAdditionalEquipmentById, - command: LoadFixtureCreateCommand - ) => { - const { fixtureId, loadName, location } = command.params - const id = fixtureId ?? '' - if ( - loadName === STANDARD_SLOT_LOAD_NAME || - loadName === TRASH_BIN_LOAD_NAME - ) { - return acc - } - return { - ...acc, - [id]: { - id: id, - name: loadName, - location: location.cutout, + const wasteChuteId = `${uuid()}:wasteChute` + const wasteChute = hasWasteChuteCommands + ? { + [wasteChuteId]: { + name: 'wasteChute' as const, + id: wasteChuteId, + location: 'cutoutD3', }, } - }, - {} - ) - const hasGripper = gripperCommands.length > 0 - const isFlex = file.robot.model === FLEX_ROBOT_TYPE - const gripperId = `${uuid()}:gripper` - const gripper = { - [gripperId]: { - name: 'gripper' as const, - id: gripperId, - }, + : {} + + const getStagingAreaSlotNames = ( + commandType: 'moveLabware' | 'loadLabware', + locationKey: 'newLocation' | 'location' + ): AddressableAreaName[] => { + return Object.values(file.commands) + .filter( + command => + command.commandType === commandType && + command.params[locationKey] !== 'offDeck' && + 'slotName' in command.params[locationKey] && + COLUMN_4_SLOTS.includes(command.params[locationKey].slotName) + ) + .map(command => command.params[locationKey].slotName) } - if (isFlex) { - if (hasGripper) { - return { ...state, ...gripper, ...fixtures } - } else { - return { ...state, ...fixtures } + + const stagingAreaSlotNames = [ + ...new Set([ + ...getStagingAreaSlotNames('moveLabware', 'newLocation'), + ...getStagingAreaSlotNames('loadLabware', 'location'), + ]), + ] + + const findCutoutIdByAddressableArea = ( + addressableAreaName: AddressableAreaName + ): CutoutId | null => { + if (providesAddressableAreasForAddressableArea != null) { + for (const cutoutId in providesAddressableAreasForAddressableArea) { + if ( + providesAddressableAreasForAddressableArea[ + cutoutId as keyof typeof providesAddressableAreasForAddressableArea + ].includes(addressableAreaName) + ) { + return cutoutId as CutoutId + } + } + } + return null + } + + const stagingAreas = stagingAreaSlotNames.reduce((acc, slot) => { + const stagingAreaId = `${uuid()}:stagingArea` + const cutoutId = findCutoutIdByAddressableArea(slot) + return { + ...acc, + [stagingAreaId]: { + name: 'stagingArea' as const, + id: stagingAreaId, + location: cutoutId, + }, } + }, {}) + + const gripperId = `${uuid()}:gripper` + const gripper = hasGripperCommands + ? { + [gripperId]: { + name: 'gripper' as const, + id: gripperId, + }, + } + : {} + + if (isFlex) { + return { ...state, ...gripper, ...wasteChute, ...stagingAreas } } else { return { ...state } } }, + TOGGLE_IS_GRIPPER_REQUIRED: ( state: NormalizedAdditionalEquipmentById ): NormalizedAdditionalEquipmentById => { diff --git a/protocol-designer/src/step-forms/utils/index.ts b/protocol-designer/src/step-forms/utils/index.ts index b6b09bdeea7..139ff2f6e64 100644 --- a/protocol-designer/src/step-forms/utils/index.ts +++ b/protocol-designer/src/step-forms/utils/index.ts @@ -123,23 +123,24 @@ export const getSlotIsEmpty = ( } const filteredAdditionalEquipmentOnDeck = includeStagingAreas - ? values(initialDeckSetup.additionalEquipmentOnDeck).filter( - (additionalEquipment: AdditionalEquipmentOnDeck) => - additionalEquipment.location === slot + ? values( + initialDeckSetup.additionalEquipmentOnDeck + ).filter((additionalEquipment: AdditionalEquipmentOnDeck) => + additionalEquipment.location?.includes(slot) ) : values(initialDeckSetup.additionalEquipmentOnDeck).filter( (additionalEquipment: AdditionalEquipmentOnDeck) => - additionalEquipment.location === slot && + additionalEquipment.location?.includes(slot) && additionalEquipment.name !== 'stagingArea' ) return ( [ - ...values(initialDeckSetup.modules).filter( - (moduleOnDeck: ModuleOnDeck) => moduleOnDeck.slot === slot + ...values(initialDeckSetup.modules).filter((moduleOnDeck: ModuleOnDeck) => + slot.includes(moduleOnDeck.slot) ), - ...values(initialDeckSetup.labware).filter( - (labware: LabwareOnDeckType) => labware.slot === slot + ...values(initialDeckSetup.labware).filter((labware: LabwareOnDeckType) => + slot.includes(labware.slot) ), ...filteredAdditionalEquipmentOnDeck, ].length === 0 diff --git a/protocol-designer/src/top-selectors/labware-locations/index.ts b/protocol-designer/src/top-selectors/labware-locations/index.ts index 9fad438c2d4..94384f44c7f 100644 --- a/protocol-designer/src/top-selectors/labware-locations/index.ts +++ b/protocol-designer/src/top-selectors/labware-locations/index.ts @@ -7,7 +7,12 @@ import { FLEX_ROBOT_TYPE, WASTE_CHUTE_ADDRESSABLE_AREAS, WASTE_CHUTE_CUTOUT, + CutoutId, + STAGING_AREA_RIGHT_SLOT_FIXTURE, + isAddressableAreaStandardSlot, + MOVABLE_TRASH_ADDRESSABLE_AREAS, } from '@opentrons/shared-data' +import { COLUMN_4_SLOTS } from '@opentrons/step-generation' import { START_TERMINAL_ITEM_ID, END_TERMINAL_ITEM_ID, @@ -108,9 +113,13 @@ export const getUnocuppiedLabwareLocationOptions: Selector< additionalEquipmentEntities ) => { const deckDef = getDeckDefFromRobotType(robotType) - const trashSlot = robotType === FLEX_ROBOT_TYPE ? 'A3' : '12' + const cutoutFixtures = deckDef.cutoutFixtures const allSlotIds = deckDef.locations.addressableAreas.map(slot => slot.id) const hasWasteChute = getHasWasteChute(additionalEquipmentEntities) + const stagingAreaCutoutIds = Object.values(additionalEquipmentEntities) + .filter(aE => aE.name === 'stagingArea') + // TODO(jr, 11/13/23): fix AdditionalEquipment['location'] from type string to CutoutId + .map(aE => aE.location as CutoutId) if (robotState == null) return null @@ -189,16 +198,39 @@ export const getUnocuppiedLabwareLocationOptions: Selector< [] ) + const stagingAreaAddressableAreaNames = stagingAreaCutoutIds + .flatMap(cutoutId => { + const addressableAreasOnCutout = cutoutFixtures.find( + cutoutFixture => cutoutFixture.id === STAGING_AREA_RIGHT_SLOT_FIXTURE + )?.providesAddressableAreas[cutoutId] + return addressableAreasOnCutout ?? [] + }) + .filter(aa => !isAddressableAreaStandardSlot(aa, deckDef)) + + // TODO(jr, 11/13/23): update COLUMN_4_SLOTS usage to FLEX_STAGING_AREA_SLOT_ADDRESSABLE_AREAS + const notSelectedStagingAreaAddressableAreas = COLUMN_4_SLOTS.filter(slot => + stagingAreaAddressableAreaNames.every( + addressableArea => addressableArea !== slot + ) + ) + const unoccupiedSlotOptions = allSlotIds - .filter( - slotId => + .filter(slotId => { + const isTrashSlot = + robotType === FLEX_ROBOT_TYPE + ? MOVABLE_TRASH_ADDRESSABLE_AREAS.includes(slotId) + : slotId === 'fixedTrash' + + return ( !slotIdsOccupiedByModules.includes(slotId) && !Object.values(labware) .map(lw => lw.slot) .includes(slotId) && - slotId !== trashSlot && - (hasWasteChute ? !(slotId in WASTE_CHUTE_ADDRESSABLE_AREAS) : true) - ) + !isTrashSlot && + !WASTE_CHUTE_ADDRESSABLE_AREAS.includes(slotId) && + !notSelectedStagingAreaAddressableAreas.includes(slotId) + ) + }) .map(slotId => ({ name: slotId, value: slotId })) const offDeck = { name: 'Off-deck', value: 'offDeck' } const wasteChuteSlot = { diff --git a/protocol-designer/src/ui/labware/selectors.ts b/protocol-designer/src/ui/labware/selectors.ts index f14923369a0..128d5831580 100644 --- a/protocol-designer/src/ui/labware/selectors.ts +++ b/protocol-designer/src/ui/labware/selectors.ts @@ -6,6 +6,7 @@ import { getLabwareDisplayName, getLabwareHasQuirk, } from '@opentrons/shared-data' +import { COLUMN_4_SLOTS } from '@opentrons/step-generation' import { i18n } from '../../localization' import * as stepFormSelectors from '../../step-forms/selectors' import { selectors as labwareIngredSelectors } from '../../labware-ingred/selectors' @@ -82,9 +83,28 @@ export const getLabwareOptions: Selector = createSelector( savedStepForms ?? {}, labwareId ) + const isStartingInColumn4 = COLUMN_4_SLOTS.includes( + initialDeckSetup.labware[labwareId]?.slot + ) + + const isInColumn4 = + savedStepForms != null + ? Object.values(savedStepForms) + ?.reverse() + .some( + form => + form.stepType === 'moveLabware' && + form.labware === labwareId && + (COLUMN_4_SLOTS.includes(form.newLocation) || + (isStartingInColumn4 && + !COLUMN_4_SLOTS.includes(form.newLocation))) + ) + : false + const isAdapterOrAluminumBlock = isAdapter || labwareEntity.def.metadata.displayCategory === 'aluminumBlock' + const moduleOnDeck = getModuleUnderLabware( initialDeckSetup, savedStepForms ?? {}, @@ -104,6 +124,8 @@ export const getLabwareOptions: Selector = createSelector( nickName = `Off-deck - ${nicknamesById[labwareId]}` } else if (nickName === 'Opentrons Fixed Trash') { nickName = TRASH + } else if (isInColumn4) { + nickName = `${nicknamesById[labwareId]} in staging area slot` } if (!moveLabwarePresavedStep) { diff --git a/protocol-designer/src/utils/index.ts b/protocol-designer/src/utils/index.ts index 210016ffa45..eb6fd018728 100644 --- a/protocol-designer/src/utils/index.ts +++ b/protocol-designer/src/utils/index.ts @@ -1,5 +1,14 @@ import uuidv1 from 'uuid/v4' -import { WellSetHelpers, makeWellSetHelpers } from '@opentrons/shared-data' +import { + WellSetHelpers, + makeWellSetHelpers, + AddressableAreaName, + getDeckDefFromRobotTypeV4, + FLEX_ROBOT_TYPE, + CutoutId, + STAGING_AREA_RIGHT_SLOT_FIXTURE, + isAddressableAreaStandardSlot, +} from '@opentrons/shared-data' import { i18n } from '../localization' import { WellGroup } from '@opentrons/components' import { BoundingRect, GenericRect } from '../collision-types' @@ -132,3 +141,19 @@ export const getStagingAreaSlots = ( export const getHas96Channel = (pipettes: PipetteEntities): boolean => { return Object.values(pipettes).some(pip => pip.spec.channels === 96) } + +export const getStagingAreaAddressableAreas = ( + cutoutIds: CutoutId[] +): AddressableAreaName[] => { + const deckDef = getDeckDefFromRobotTypeV4(FLEX_ROBOT_TYPE) + const cutoutFixtures = deckDef.cutoutFixtures + + return cutoutIds + .flatMap(cutoutId => { + const addressableAreasOnCutout = cutoutFixtures.find( + cutoutFixture => cutoutFixture.id === STAGING_AREA_RIGHT_SLOT_FIXTURE + )?.providesAddressableAreas[cutoutId] + return addressableAreasOnCutout ?? [] + }) + .filter(aa => !isAddressableAreaStandardSlot(aa, deckDef)) +} diff --git a/shared-data/deck/types/schemaV4.ts b/shared-data/deck/types/schemaV4.ts index 04aeb85cb59..ecf6bb51d26 100644 --- a/shared-data/deck/types/schemaV4.ts +++ b/shared-data/deck/types/schemaV4.ts @@ -15,7 +15,14 @@ export type FlexAddressableAreaName = | 'B4' | 'C4' | 'D4' - | 'movableTrash' + | 'movableTrashA1' + | 'movableTrashA3' + | 'movableTrashB1' + | 'movableTrashB3' + | 'movableTrashC1' + | 'movableTrashC3' + | 'movableTrashD1' + | 'movableTrashD3' | '1and8ChannelWasteChute' | '96ChannelWasteChute' | 'gripperWasteChute' @@ -69,3 +76,4 @@ export type CutoutFixtureId = | SingleSlotCutoutFixtureId | TrashBinAdapterCutoutFixtureId | WasteChuteCutoutFixtureId + | 'stagingAreaRightSlot' diff --git a/shared-data/js/constants.ts b/shared-data/js/constants.ts index 9ac6327bbcb..b31a67b958d 100644 --- a/shared-data/js/constants.ts +++ b/shared-data/js/constants.ts @@ -1,3 +1,4 @@ +import { AddressableAreaName } from '.' import type { Cutout, ModuleType } from './types' // constants for dealing with robot coordinate system (eg in labwareTools) @@ -259,7 +260,7 @@ export const FLEX_STAGING_AREA_SLOT_ADDRESSABLE_AREAS = [ D4_ADDRESSABLE_AREA, ] -export const MOVABLE_TRASH_ADDRESSABLE_AREAS = [ +export const MOVABLE_TRASH_ADDRESSABLE_AREAS: AddressableAreaName[] = [ MOVABLE_TRASH_A1_ADDRESSABLE_AREA, MOVABLE_TRASH_A3_ADDRESSABLE_AREA, MOVABLE_TRASH_B1_ADDRESSABLE_AREA, @@ -270,7 +271,7 @@ export const MOVABLE_TRASH_ADDRESSABLE_AREAS = [ MOVABLE_TRASH_D3_ADDRESSABLE_AREA, ] -export const WASTE_CHUTE_ADDRESSABLE_AREAS = [ +export const WASTE_CHUTE_ADDRESSABLE_AREAS: AddressableAreaName[] = [ ONE_AND_EIGHT_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA, NINETY_SIX_CHANNEL_WASTE_CHUTE_ADDRESSABLE_AREA, GRIPPER_WASTE_CHUTE_ADDRESSABLE_AREA, diff --git a/shared-data/js/helpers/index.ts b/shared-data/js/helpers/index.ts index a0cb30f9eb9..cdc79967cf7 100644 --- a/shared-data/js/helpers/index.ts +++ b/shared-data/js/helpers/index.ts @@ -220,15 +220,12 @@ export const getAreSlotsHorizontallyAdjacent = ( } const slotANumber = parseInt(slotNameA) const slotBNumber = parseInt(slotNameB) - if (isNaN(slotBNumber) || isNaN(slotANumber)) { return false } - // TODO(bh, 2023-11-03): is this OT-2 only? const orderedSlots = standardOt2DeckDef.locations.cutouts // intentionally not substracting by 1 because trash (slot 12) should not count const numSlots = orderedSlots.length - if (slotBNumber > numSlots || slotANumber > numSlots) { return false } @@ -261,7 +258,6 @@ export const getAreSlotsVerticallyAdjacent = ( if (isNaN(slotBNumber) || isNaN(slotANumber)) { return false } - // TODO(bh, 2023-11-03): is this OT-2 only? const orderedSlots = standardOt2DeckDef.locations.cutouts // intentionally not substracting by 1 because trash (slot 12) should not count const numSlots = orderedSlots.length @@ -286,6 +282,9 @@ export const getAreSlotsVerticallyAdjacent = ( return areSlotsVerticallyAdjacent } +// TODO(jr, 11/12/23): rename this utility to mention that it +// is only used in the OT-2, same with getAreSlotsHorizontallyAdjacent +// and getAreSlotsVerticallyAdjacent export const getAreSlotsAdjacent = ( slotNameA?: string | null, slotNameB?: string | null diff --git a/step-generation/src/__tests__/aspirate.test.ts b/step-generation/src/__tests__/aspirate.test.ts index 4c6b3ab8911..ab9b7869327 100644 --- a/step-generation/src/__tests__/aspirate.test.ts +++ b/step-generation/src/__tests__/aspirate.test.ts @@ -198,6 +198,29 @@ describe('aspirate', () => { type: 'LABWARE_DOES_NOT_EXIST', }) }) + it('should return an error when aspirating from the 4th column', () => { + robotStateWithTip = { + ...robotStateWithTip, + labware: { + [SOURCE_LABWARE]: { slot: 'A4' }, + }, + } + const result = aspirate( + { + ...flowRateAndOffsets, + pipette: DEFAULT_PIPETTE, + volume: 50, + labware: SOURCE_LABWARE, + well: 'A1', + } as AspDispAirgapParams, + invariantContext, + robotStateWithTip + ) + expect(getErrorResult(result).errors).toHaveLength(1) + expect(getErrorResult(result).errors[0]).toMatchObject({ + type: 'PIPETTING_INTO_COLUMN_4', + }) + }) it('should return an error when aspirating from labware off deck', () => { initialRobotState = getInitialRobotStateWithOffDeckLabwareStandard( invariantContext diff --git a/step-generation/src/__tests__/dispense.test.ts b/step-generation/src/__tests__/dispense.test.ts index b1399c54c4a..d66fae15b5e 100644 --- a/step-generation/src/__tests__/dispense.test.ts +++ b/step-generation/src/__tests__/dispense.test.ts @@ -141,6 +141,19 @@ describe('dispense', () => { type: 'LABWARE_DOES_NOT_EXIST', }) }) + it('should return an error when dispensing from the 4th column', () => { + robotStateWithTip = { + ...robotStateWithTip, + labware: { + [SOURCE_LABWARE]: { slot: 'A4' }, + }, + } + const result = dispense(params, invariantContext, robotStateWithTip) + expect(getErrorResult(result).errors).toHaveLength(1) + expect(getErrorResult(result).errors[0]).toMatchObject({ + type: 'PIPETTING_INTO_COLUMN_4', + }) + }) it('should return an error when dispensing into thermocycler with pipette collision', () => { mockThermocyclerPipetteCollision.mockImplementationOnce( ( diff --git a/step-generation/src/__tests__/moveToWell.test.ts b/step-generation/src/__tests__/moveToWell.test.ts index 0906d8f8629..4020cc52e08 100644 --- a/step-generation/src/__tests__/moveToWell.test.ts +++ b/step-generation/src/__tests__/moveToWell.test.ts @@ -160,6 +160,27 @@ describe('moveToWell', () => { type: 'LABWARE_OFF_DECK', }) }) + it('should return an error when dispensing from the 4th column', () => { + robotStateWithTip = { + ...robotStateWithTip, + labware: { + [SOURCE_LABWARE]: { slot: 'A4' }, + }, + } + const result = moveToWell( + { + pipette: DEFAULT_PIPETTE, + labware: SOURCE_LABWARE, + well: 'A1', + }, + invariantContext, + robotStateWithTip + ) + expect(getErrorResult(result).errors).toHaveLength(1) + expect(getErrorResult(result).errors[0]).toMatchObject({ + type: 'PIPETTING_INTO_COLUMN_4', + }) + }) it('should return an error when moving to well in a thermocycler with pipette collision', () => { mockThermocyclerPipetteCollision.mockImplementationOnce( ( diff --git a/step-generation/src/commandCreators/atomic/aspirate.ts b/step-generation/src/commandCreators/atomic/aspirate.ts index e32c017ef2a..efc734275f9 100644 --- a/step-generation/src/commandCreators/atomic/aspirate.ts +++ b/step-generation/src/commandCreators/atomic/aspirate.ts @@ -12,6 +12,7 @@ import { getIsHeaterShakerNorthSouthOfNonTiprackWithMultiChannelPipette, uuid, } from '../../utils' +import { COLUMN_4_SLOTS } from '../../constants' import type { CreateCommand } from '@opentrons/shared-data' import type { AspirateParams } from '@opentrons/shared-data/protocol/types/schemaV3' import type { CommandCreator, CommandCreatorError } from '../../types' @@ -64,6 +65,10 @@ export const aspirate: CommandCreator = ( errors.push(errorCreators.labwareOffDeck()) } + if (COLUMN_4_SLOTS.includes(slotName)) { + errors.push(errorCreators.pipettingIntoColumn4({ typeOfStep: actionName })) + } + if ( modulePipetteCollision({ pipette, diff --git a/step-generation/src/commandCreators/atomic/blowout.ts b/step-generation/src/commandCreators/atomic/blowout.ts index 7fbd13a56df..5c18b8d654c 100644 --- a/step-generation/src/commandCreators/atomic/blowout.ts +++ b/step-generation/src/commandCreators/atomic/blowout.ts @@ -1,8 +1,9 @@ -import { uuid } from '../../utils' +import { uuid, getLabwareSlot } from '../../utils' +import { COLUMN_4_SLOTS } from '../../constants' import * as errorCreators from '../../errorCreators' +import type { CreateCommand } from '@opentrons/shared-data' import type { BlowoutParams } from '@opentrons/shared-data/protocol/types/schemaV3' import type { CommandCreatorError, CommandCreator } from '../../types' -import { CreateCommand } from '@opentrons/shared-data' export const blowout: CommandCreator = ( args, @@ -14,7 +15,11 @@ export const blowout: CommandCreator = ( const actionName = 'blowout' const errors: CommandCreatorError[] = [] const pipetteData = prevRobotState.pipettes[pipette] - + const slotName = getLabwareSlot( + labware, + prevRobotState.labware, + prevRobotState.modules + ) // TODO Ian 2018-04-30 this logic using command creator args + robotstate to push errors // is duplicated across several command creators (eg aspirate & blowout overlap). // You can probably make higher-level error creator util fns to be more DRY @@ -49,6 +54,10 @@ export const blowout: CommandCreator = ( errors.push(errorCreators.labwareOffDeck()) } + if (COLUMN_4_SLOTS.includes(slotName)) { + errors.push(errorCreators.pipettingIntoColumn4({ typeOfStep: actionName })) + } + if (errors.length > 0) { return { errors, diff --git a/step-generation/src/commandCreators/atomic/dispense.ts b/step-generation/src/commandCreators/atomic/dispense.ts index c8ddfe1dc96..7d52d5c5eb3 100644 --- a/step-generation/src/commandCreators/atomic/dispense.ts +++ b/step-generation/src/commandCreators/atomic/dispense.ts @@ -11,6 +11,7 @@ import { getIsHeaterShakerNorthSouthOfNonTiprackWithMultiChannelPipette, uuid, } from '../../utils' +import { COLUMN_4_SLOTS } from '../../constants' import type { CreateCommand } from '@opentrons/shared-data' import type { DispenseParams } from '@opentrons/shared-data/protocol/types/schemaV3' import type { CommandCreator, CommandCreatorError } from '../../types' @@ -84,6 +85,10 @@ export const dispense: CommandCreator = ( errors.push(errorCreators.labwareOffDeck()) } + if (COLUMN_4_SLOTS.includes(slotName)) { + errors.push(errorCreators.pipettingIntoColumn4({ typeOfStep: actionName })) + } + if ( thermocyclerPipetteCollision( prevRobotState.modules, diff --git a/step-generation/src/commandCreators/atomic/moveToWell.ts b/step-generation/src/commandCreators/atomic/moveToWell.ts index bf2369509cc..e16f1cff417 100644 --- a/step-generation/src/commandCreators/atomic/moveToWell.ts +++ b/step-generation/src/commandCreators/atomic/moveToWell.ts @@ -11,6 +11,7 @@ import { getIsHeaterShakerNorthSouthOfNonTiprackWithMultiChannelPipette, uuid, } from '../../utils' +import { COLUMN_4_SLOTS } from '../../constants' import type { CreateCommand } from '@opentrons/shared-data' import type { MoveToWellParams as v5MoveToWellParams } from '@opentrons/shared-data/protocol/types/schemaV5' import type { MoveToWellParams as v6MoveToWellParams } from '@opentrons/shared-data/protocol/types/schemaV6/command/gantry' @@ -58,6 +59,12 @@ export const moveToWell: CommandCreator = ( errors.push(errorCreators.labwareOffDeck()) } + if (COLUMN_4_SLOTS.includes(slotName)) { + errors.push( + errorCreators.pipettingIntoColumn4({ typeOfStep: 'move to well' }) + ) + } + if ( modulePipetteCollision({ pipette, diff --git a/step-generation/src/commandCreators/atomic/replaceTip.ts b/step-generation/src/commandCreators/atomic/replaceTip.ts index d469efdfb18..55e3348b78d 100644 --- a/step-generation/src/commandCreators/atomic/replaceTip.ts +++ b/step-generation/src/commandCreators/atomic/replaceTip.ts @@ -1,5 +1,6 @@ import { getNextTiprack } from '../../robotStateSelectors' import * as errorCreators from '../../errorCreators' +import { COLUMN_4_SLOTS } from '../../constants' import { dropTip } from './dropTip' import { curryCommandCreator, @@ -38,6 +39,11 @@ const _pickUpTip: CommandCreator = ( if (adapterId == null && pipetteName === 'p1000_96') { errors.push(errorCreators.missingAdapter()) } + if (COLUMN_4_SLOTS.includes(tiprackSlot)) { + errors.push( + errorCreators.pipettingIntoColumn4({ typeOfStep: 'pick up tip' }) + ) + } if (errors.length > 0) { return { errors } diff --git a/step-generation/src/constants.ts b/step-generation/src/constants.ts index d8dfa2142c4..63e0f0d4018 100644 --- a/step-generation/src/constants.ts +++ b/step-generation/src/constants.ts @@ -20,3 +20,5 @@ export const FIXED_TRASH_ID: 'fixedTrash' = 'fixedTrash' export const OT_2_TRASH_DEF_URI = 'opentrons/opentrons_1_trash_1100ml_fixed/1' export const FLEX_TRASH_DEF_URI = 'opentrons/opentrons_1_trash_3200ml_fixed/1' + +export const COLUMN_4_SLOTS = ['A4', 'B4', 'C4', 'D4'] diff --git a/step-generation/src/errorCreators.ts b/step-generation/src/errorCreators.ts index f3364dc8b8e..3d6cadc5c57 100644 --- a/step-generation/src/errorCreators.ts +++ b/step-generation/src/errorCreators.ts @@ -218,3 +218,12 @@ export const gripperRequired = (): CommandCreatorError => { message: 'The gripper is required to fulfill this action', } } + +export const pipettingIntoColumn4 = (args: { + typeOfStep: string +}): CommandCreatorError => { + return { + type: 'PIPETTING_INTO_COLUMN_4', + message: `Cannot ${args.typeOfStep} into a column 4 slot.`, + } +} diff --git a/step-generation/src/types.ts b/step-generation/src/types.ts index dcc18666ad3..26dbf13368a 100644 --- a/step-generation/src/types.ts +++ b/step-generation/src/types.ts @@ -512,6 +512,7 @@ export type ErrorType = | 'NO_TIP_ON_PIPETTE' | 'PIPETTE_DOES_NOT_EXIST' | 'PIPETTE_VOLUME_EXCEEDED' + | 'PIPETTING_INTO_COLUMN_4' | 'TALL_LABWARE_EAST_WEST_OF_HEATER_SHAKER' | 'THERMOCYCLER_LID_CLOSED' | 'TIP_VOLUME_EXCEEDED' From 327f9b358bd5495548ea1568de0bb2aa0e4e22a2 Mon Sep 17 00:00:00 2001 From: Jamey H Date: Tue, 14 Nov 2023 11:21:20 -0500 Subject: [PATCH 62/65] fix(app): fix protocol slideout whitescreen (#13977) Closes RQA-1887, RQA-1888 * fix(app): fix all ProtocolSlideout deck thumbnails displaying the same deckmap * fix(app): fix white-screen when selecting failed analysis protocol in protocol slideout --- .../__tests__/DeckThumbnail.test.tsx | 15 +++++++++++++++ app/src/molecules/DeckThumbnail/index.tsx | 2 +- .../organisms/ChooseProtocolSlideout/index.tsx | 10 ++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/app/src/molecules/DeckThumbnail/__tests__/DeckThumbnail.test.tsx b/app/src/molecules/DeckThumbnail/__tests__/DeckThumbnail.test.tsx index d1d5fe35282..2c47a31532e 100644 --- a/app/src/molecules/DeckThumbnail/__tests__/DeckThumbnail.test.tsx +++ b/app/src/molecules/DeckThumbnail/__tests__/DeckThumbnail.test.tsx @@ -188,6 +188,21 @@ describe('DeckThumbnail', () => { getByText('mock BaseDeck') }) + it('returns null when there is no protocolAnalysis or the protocolAnalysis contains an error', () => { + const { queryByText } = render({ + protocolAnalysis: null, + }) + expect(queryByText('mock BaseDeck')).not.toBeInTheDocument() + + render({ + protocolAnalysis: { + ...protocolAnalysis, + errors: 'test error', + }, + }) + expect(queryByText('mock BaseDeck')).not.toBeInTheDocument() + }) + it('renders an OT-3 deck view when the protocol is an OT-3 protocol', () => { // ToDo (kk:11/06/2023) update this test later // const mockLabwareLocations = [ diff --git a/app/src/molecules/DeckThumbnail/index.tsx b/app/src/molecules/DeckThumbnail/index.tsx index 79df3017cad..f4295fa8dd9 100644 --- a/app/src/molecules/DeckThumbnail/index.tsx +++ b/app/src/molecules/DeckThumbnail/index.tsx @@ -35,7 +35,7 @@ export function DeckThumbnail(props: DeckThumbnailProps): JSX.Element | null { const { protocolAnalysis, showSlotLabels = false, ...styleProps } = props const attachedModules = useAttachedModules() - if (protocolAnalysis == null) return null + if (protocolAnalysis == null || protocolAnalysis.errors.length) return null const robotType = getRobotTypeFromLoadedLabware(protocolAnalysis.labware) const deckDef = getDeckDefFromRobotType(robotType) diff --git a/app/src/organisms/ChooseProtocolSlideout/index.tsx b/app/src/organisms/ChooseProtocolSlideout/index.tsx index 67a4148d54e..ab3b201318b 100644 --- a/app/src/organisms/ChooseProtocolSlideout/index.tsx +++ b/app/src/organisms/ChooseProtocolSlideout/index.tsx @@ -36,7 +36,6 @@ import { useCreateRunFromProtocol } from '../ChooseRobotToRunProtocolSlideout/us import { ApplyHistoricOffsets } from '../ApplyHistoricOffsets' import { useOffsetCandidatesForAnalysis } from '../ApplyHistoricOffsets/hooks/useOffsetCandidatesForAnalysis' -import { ProtocolAnalysisOutput } from '@opentrons/shared-data' import type { Robot } from '../../redux/discovery/types' import type { StoredProtocolData } from '../../redux/protocol-storage' import type { State } from '../../redux/types' @@ -163,7 +162,6 @@ export function ChooseProtocolSlideoutComponent( }} robotName={robot.name} {...{ selectedProtocol, runCreationError, runCreationErrorCode }} - protocolAnalysis={selectedProtocol?.mostRecentAnalysis} /> ) : null} @@ -182,7 +180,6 @@ interface StoredProtocolListProps { runCreationError: string | null runCreationErrorCode: number | null robotName: string - protocolAnalysis?: ProtocolAnalysisOutput | null } function StoredProtocolList(props: StoredProtocolListProps): JSX.Element { @@ -192,7 +189,6 @@ function StoredProtocolList(props: StoredProtocolListProps): JSX.Element { runCreationError, runCreationErrorCode, robotName, - protocolAnalysis, } = props const { t } = useTranslation(['device_details', 'shared']) const storedProtocols = useSelector((state: State) => @@ -227,8 +223,10 @@ function StoredProtocolList(props: StoredProtocolListProps): JSX.Element { height="4.25rem" width="4.75rem" > - {protocolAnalysis != null ? ( - + {storedProtocol.mostRecentAnalysis != null ? ( + ) : null} Date: Tue, 14 Nov 2023 11:32:58 -0500 Subject: [PATCH 63/65] ci(labware-library): add build timeout of 30 minutes (#13978) --- .github/workflows/ll-test-build-deploy.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ll-test-build-deploy.yaml b/.github/workflows/ll-test-build-deploy.yaml index 75e907af97f..e2e33d54146 100644 --- a/.github/workflows/ll-test-build-deploy.yaml +++ b/.github/workflows/ll-test-build-deploy.yaml @@ -116,6 +116,7 @@ jobs: build-ll: name: 'build labware library artifact' needs: ['js-unit-test'] + timeout-minutes: 30 runs-on: 'ubuntu-20.04' if: github.event_name != 'pull_request' steps: From eeb81621666de7781f51f2832da774d9c62c2d52 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Thu, 9 Nov 2023 09:48:52 -0500 Subject: [PATCH 64/65] initial tests --- app/src/organisms/CommandText/PipettingCommandText.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/organisms/CommandText/PipettingCommandText.tsx b/app/src/organisms/CommandText/PipettingCommandText.tsx index defd89fbab9..2a1ec9347e2 100644 --- a/app/src/organisms/CommandText/PipettingCommandText.tsx +++ b/app/src/organisms/CommandText/PipettingCommandText.tsx @@ -55,7 +55,7 @@ export const PipettingCommandText = ({ const { volume, flowRate } = command.params return t('aspirate', { well_name: wellName, - labware: getLabwareName(robotSideAnalysis, labwareId), + labware: getLabwareName(robotSideAnalysis, labwareId ?? ''), labware_location: displayLocation, volume: volume, flow_rate: flowRate, From 538283a2ffaaf47b1e1c66b56649fbee98af57a2 Mon Sep 17 00:00:00 2001 From: ncdiehl11 Date: Tue, 14 Nov 2023 14:51:07 -0500 Subject: [PATCH 65/65] update wasteChute location in tests to be cutoutD3 to reflect deck def v4 --- step-generation/src/__tests__/replaceTip.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/step-generation/src/__tests__/replaceTip.test.ts b/step-generation/src/__tests__/replaceTip.test.ts index 6dfc0978583..c1044d38432 100644 --- a/step-generation/src/__tests__/replaceTip.test.ts +++ b/step-generation/src/__tests__/replaceTip.test.ts @@ -145,7 +145,7 @@ describe('replaceTip', () => { wasteChuteId: { name: 'wasteChute', id: wasteChuteId, - location: 'D3', + location: 'cutoutD3', }, }, } @@ -257,7 +257,7 @@ describe('replaceTip', () => { wasteChuteId: { name: 'wasteChute', id: wasteChuteId, - location: 'D3', + location: 'cutoutD3', }, }, }

    3b{y(wjv;hCF)mtiwPdfw!qkvBT? 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 LALc!H{QUm_Powo1 literal 0 HcmV?d00001 diff --git a/protocol-designer/src/localization/en/alert.json b/protocol-designer/src/localization/en/alert.json index 475e45012f2..bf391dfa358 100644 --- a/protocol-designer/src/localization/en/alert.json +++ b/protocol-designer/src/localization/en/alert.json @@ -49,10 +49,10 @@ "title": "Missing labware", "body": "Your module has no labware on it. We recommend you add labware before proceeding." }, - "export_v7_protocol_7_0": { + "export_v8_protocol_7_1": { "title": "Robot and app update may be required", "body1": "This protocol can only run on app and robot server version", - "body2": "7.0 or higher", + "body2": "7.1 or higher", "body3": ". Please ensure your robot is updated to the correct version." }, "change_magnet_module_model": { diff --git a/protocol-designer/src/tutorial/index.ts b/protocol-designer/src/tutorial/index.ts index e5a1a71d97a..a0eee9ffff3 100644 --- a/protocol-designer/src/tutorial/index.ts +++ b/protocol-designer/src/tutorial/index.ts @@ -10,7 +10,7 @@ type HintKey = // normal hints | 'waste_chute_warning' // blocking hints | 'custom_labware_with_modules' - | 'export_v7_protocol_7_0' + | 'export_v8_protocol_7_1' | 'change_magnet_module_model' // DEPRECATED HINTS (keep a record to avoid name collisions with old persisted dismissal states) // 'export_v4_protocol' @@ -18,5 +18,6 @@ type HintKey = // normal hints // | 'export_v5_protocol_3_20' // | 'export_v6_protocol_6_10' // | 'export_v6_protocol_6_20' +// | 'export_v7_protocol_7_0' export { actions, rootReducer, selectors } export type { RootState, HintKey } From 9c5843837db3f622d31e09e96f77a24506259a8a Mon Sep 17 00:00:00 2001 From: Caila Marashaj <98041399+caila-marashaj@users.noreply.github.com> Date: Wed, 8 Nov 2023 16:57:10 -0500 Subject: [PATCH 41/65] fix(shared-data): remove requirement for current entry to TipHandlingConfigurations (#13944) --- .../pipette/schemas/2/pipettePropertiesSchema.json | 3 +-- .../pipette/pipette_definition.py | 14 +++++++++++--- .../pipette/scripts/build_json_script.py | 5 ----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/shared-data/pipette/schemas/2/pipettePropertiesSchema.json b/shared-data/pipette/schemas/2/pipettePropertiesSchema.json index 94c6482f155..810ceade169 100644 --- a/shared-data/pipette/schemas/2/pipettePropertiesSchema.json +++ b/shared-data/pipette/schemas/2/pipettePropertiesSchema.json @@ -61,9 +61,8 @@ "tipConfigurations": { "type": "object", "description": "Object containing configurations specific to tip handling", - "required": ["current", "speed"], + "required": ["speed"], "properties": { - "current": { "$ref": "#/definitions/currentRange" }, "presses": {}, "speed": { "$ref": "#/definitions/editConfigurations" }, "increment": {}, diff --git a/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py b/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py index 2893d0c39fe..7a58e1b61b2 100644 --- a/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py +++ b/shared-data/python/opentrons_shared_data/pipette/pipette_definition.py @@ -142,18 +142,26 @@ class PlungerPositions(BaseModel): class PlungerHomingConfigurations(BaseModel): current: float = Field( default=0.0, - description="Either the z motor current needed for picking up tip or the plunger motor current for dropping tip off the nozzle.", + description="The current to move the plunger axis for homing.", ) speed: float = Field( ..., - description="The speed to move the z or plunger axis for tip pickup or drop off.", + description="The speed to move the plunger axis for homing.", ) -class TipHandlingConfigurations(PlungerHomingConfigurations): +class TipHandlingConfigurations(BaseModel): presses: int = Field( default=0.0, description="The number of tries required to force pick up a tip." ) + current: float = Field( + default=0.0, + description="The current to use for tip drop-off.", + ) + speed: float = Field( + ..., + description="The speed to move the z or plunger axis for tip pickup or drop off.", + ) increment: float = Field( default=0.0, description="The increment to move the pipette down for force tip pickup retries.", diff --git a/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py b/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py index 90c7757b6a7..fa0c4956e30 100644 --- a/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py +++ b/shared-data/python/opentrons_shared_data/pipette/scripts/build_json_script.py @@ -40,14 +40,12 @@ def _build_tip_handling_configurations( increment = 0 distance = 0.0 if tip_handling_type == "pickup" and model_configurations: - current = model_configurations["pickUpCurrent"]["value"] speed = model_configurations["pickUpSpeed"]["value"] presses = model_configurations["pickUpPresses"]["value"] increment = int(model_configurations["pickUpIncrement"]["value"]) distance = model_configurations["pickUpDistance"]["value"] elif tip_handling_type == "pickup": print("Handling pick up tip configurations\n") - current = float(input("please provide the current\n")) speed = float(input("please provide the speed\n")) presses = int(input("please provide the number of presses for force pick up\n")) increment = int( @@ -59,14 +57,11 @@ def _build_tip_handling_configurations( input("please provide the starting distance for pick up tip\n") ) elif tip_handling_type == "drop" and model_configurations: - current = model_configurations["dropTipCurrent"]["value"] speed = model_configurations["dropTipSpeed"]["value"] elif tip_handling_type == "drop": print("Handling drop tip configurations\n") - current = float(input("please provide the current\n")) speed = float(input("please provide the speed\n")) return TipHandlingConfigurations( - current=current, speed=speed, presses=presses, increment=increment, From 3d8407c3fe1bd8a3cf4daddca2801d8eaa8762b0 Mon Sep 17 00:00:00 2001 From: Brian Arthur Cooper Date: Thu, 9 Nov 2023 10:52:43 -0500 Subject: [PATCH 42/65] chore(protocol-designer, labware-library): remove unused full story integration (#13892) --- labware-library/README.md | 1 - labware-library/src/analytics/fullstory.ts | 88 ------------------ labware-library/src/analytics/index.ts | 2 - .../src/analytics/initializeFullstory.ts | 64 ------------- labware-library/src/analytics/utils.ts | 6 -- labware-library/typings/fullstory.d.ts | 42 --------- protocol-designer/README.md | 4 - protocol-designer/src/analytics/actions.ts | 3 - protocol-designer/src/analytics/fullstory.ts | 91 ------------------- .../src/components/modals/GateModal/index.tsx | 2 +- protocol-designer/src/initialize.ts | 8 +- 11 files changed, 2 insertions(+), 309 deletions(-) delete mode 100644 labware-library/src/analytics/fullstory.ts delete mode 100644 labware-library/src/analytics/initializeFullstory.ts delete mode 100644 labware-library/typings/fullstory.d.ts delete mode 100644 protocol-designer/src/analytics/fullstory.ts diff --git a/labware-library/README.md b/labware-library/README.md index 21fa0e5c6f1..b0971e0eb93 100644 --- a/labware-library/README.md +++ b/labware-library/README.md @@ -80,7 +80,6 @@ Certain environment variables, when set, will affect the artifact output. | variable | value | description | | --------------------- | ------------------------------------ | --------------------------------------------------------- | | NODE_ENV | production, development, test | Optimizes output for a specific environment | -| OT_LL_FULLSTORY_ORG | some string ID | Fullstory organization ID. | | OT_LL_MIXPANEL_ID | some string ID | Mixpanel token for prod environment. | | OT_LL_MIXPANEL_DEV_ID | some string ID | Mixpanel token for dev environment. | | OT_LL_VERSION | semver string eg "1.2.3" | reported to analytics. Read from package.json by default. | diff --git a/labware-library/src/analytics/fullstory.ts b/labware-library/src/analytics/fullstory.ts deleted file mode 100644 index 5430065ae17..00000000000 --- a/labware-library/src/analytics/fullstory.ts +++ /dev/null @@ -1,88 +0,0 @@ -import uniq from 'lodash/uniq' - -const LL_VERSION = process.env.OT_LL_VERSION -const LL_BUILD_DATE = new Date(process.env.OT_LL_BUILD_DATE) - -const _getFullstory = (): FullStory.FullStory | null => { - const namespace = global._fs_namespace - const fs = namespace ? global[namespace] : null - return fs || null -} - -export const shutdownFullstory = (): void => { - console.debug('shutting down Fullstory') - const fs = _getFullstory() - if (fs && fs.shutdown) { - fs.shutdown() - } - if (global._fs_namespace && global[global._fs_namespace]) { - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete global[global._fs_namespace] - } -} - -export const inferFsKeyWithSuffix = ( - key: string, - value: unknown -): string | null => { - // semi-hacky way to provide FS with type suffix for keys in FS `properties` - if (typeof value === 'boolean') return 'bool' - if (Number.isInteger(value)) return 'int' - if (typeof value === 'number') return 'real' - if (value instanceof Date) return '' - if (typeof value === 'string') return 'str' - - // flat array - if (Array.isArray(value) && value.every(x => !Array.isArray(x))) { - const recursiveContents = value.map(x => inferFsKeyWithSuffix(key, x)) - // homogenously-typed array - if (uniq(recursiveContents).length === 1 && recursiveContents[0] != null) { - // add 's' to suffix to denote array of type (eg 'bools') - return `${recursiveContents[0]}s` - } - } - - // NOTE: nested objects are valid in FS properties, - // but not yet supported by this fn - console.info(`could not determine Fullstory key suffix for key "${key}"`) - - return null -} - -export const fullstoryEvent = ( - name: string, - parameters: Record = {} -): void => { - // NOTE: make sure user has opted in before calling this fn - const fs = _getFullstory() - if (fs && fs.event) { - // NOTE: fullstory requires property names to have type suffix - // https://help.fullstory.com/hc/en-us/articles/360020623234#Custom%20Property%20Name%20Requirements - const _parameters = Object.keys(parameters).reduce((acc, key) => { - const value = parameters[key] - const suffix = inferFsKeyWithSuffix(key, value) - const name: string = suffix === null ? key : `${key}_${suffix}` - return { ...acc, [name]: value } - }, {}) - fs.event(name, _parameters) - } -} - -export const _setAnalyticsTags = (): void => { - const fs = _getFullstory() - // NOTE: fullstory expects the keys 'displayName' and 'email' verbatim - // though all other key names must be fit the schema described here - // https://help.fullstory.com/hc/en-us/articles/360020623294 - if (fs && fs.setUserVars) { - // eslint-disable-next-line @typescript-eslint/naming-convention - const version_str = LL_VERSION - // eslint-disable-next-line @typescript-eslint/naming-convention - const buildDate_date = LL_BUILD_DATE - - fs.setUserVars({ - ot_application_name_str: 'labware-library', // NOTE: to distinguish from other apps using the FULLSTORY_ORG - version_str, - buildDate_date, - }) - } -} diff --git a/labware-library/src/analytics/index.ts b/labware-library/src/analytics/index.ts index 58321499aa6..78a0760ea83 100644 --- a/labware-library/src/analytics/index.ts +++ b/labware-library/src/analytics/index.ts @@ -1,6 +1,5 @@ import { getAnalyticsState } from './utils' import { trackWithMixpanel } from './mixpanel' -import { fullstoryEvent } from './fullstory' import type { AnalyticsEvent } from './types' // NOTE: right now we report with only mixpanel, this fn is meant @@ -13,6 +12,5 @@ export const reportEvent = (event: AnalyticsEvent): void => { console.debug('Trackable event', { event, optedIn }) if (optedIn) { trackWithMixpanel(event.name, event.properties) - fullstoryEvent(event.name, event.properties) } } diff --git a/labware-library/src/analytics/initializeFullstory.ts b/labware-library/src/analytics/initializeFullstory.ts deleted file mode 100644 index 28991f6feab..00000000000 --- a/labware-library/src/analytics/initializeFullstory.ts +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-nocheck -'use strict' -import { _setAnalyticsTags } from './fullstory' -const FULLSTORY_NAMESPACE = 'FS' -const FULLSTORY_ORG = process.env.OT_LL_FULLSTORY_ORG -export const initializeFullstory = (): void => { - console.debug('initializing Fullstory') - // NOTE: this code snippet is distributed by Fullstory, last updated 2019-10-04 - global._fs_debug = false - global._fs_host = 'fullstory.com' - global._fs_org = FULLSTORY_ORG - global._fs_namespace = FULLSTORY_NAMESPACE - ;(function (m, n, e, t, l, o, g, y) { - if (e in m) { - if (m.console && m.console.log) { - m.console.log( - 'FullStory namespace conflict. Please set window["_fs_namespace"].' - ) - } - return - } - g = m[e] = function (a, b, s) { - g.q ? g.q.push([a, b, s]) : g._api(a, b, s) - } - g.q = [] - o = n.createElement(t) - o.async = 1 - o.crossOrigin = 'anonymous' - o.src = 'https://' + global._fs_host + '/s/fs.js' - y = n.getElementsByTagName(t)[0] - y.parentNode.insertBefore(o, y) - g.identify = function (i, v, s) { - g(l, { uid: i }, s) - if (v) g(l, v, s) - } - g.setUserVars = function (v, s) { - g(l, v, s) - } - g.event = function (i, v, s) { - g('event', { n: i, p: v }, s) - } - g.shutdown = function () { - g('rec', !1) - } - g.restart = function () { - g('rec', !0) - } - g.log = function (a, b) { - g('log', [a, b]) - } - g.consent = function (a) { - g('consent', !arguments.length || a) - } - g.identifyAccount = function (i, v) { - o = 'account' - v = v || {} - v.acctId = i - g(o, v) - } - g.clearUserCookie = function () {} - })(global, global.document, global._fs_namespace, 'script', 'user') - - _setAnalyticsTags() -} diff --git a/labware-library/src/analytics/utils.ts b/labware-library/src/analytics/utils.ts index bf6ba2b5ee9..6b7e11e31aa 100644 --- a/labware-library/src/analytics/utils.ts +++ b/labware-library/src/analytics/utils.ts @@ -1,8 +1,6 @@ import cookie from 'cookie' import { initializeMixpanel, mixpanelOptIn, mixpanelOptOut } from './mixpanel' -import { initializeFullstory } from './initializeFullstory' -import { shutdownFullstory } from './fullstory' import type { AnalyticsState } from './types' const COOKIE_KEY_NAME = 'ot_ll_analytics' // NOTE: cookie is named "LL" but only LC uses it now @@ -62,16 +60,12 @@ export const getAnalyticsState = (): AnalyticsState => { return state } -// NOTE: Fullstory has no opt-in/out, control by adding/removing it completely - export const persistAnalyticsState = (state: AnalyticsState): void => { persistAnalyticsCookie(state) if (state.optedIn) { mixpanelOptIn() - initializeFullstory() } else { mixpanelOptOut() - shutdownFullstory() } } diff --git a/labware-library/typings/fullstory.d.ts b/labware-library/typings/fullstory.d.ts deleted file mode 100644 index 1fbc7c9b6ed..00000000000 --- a/labware-library/typings/fullstory.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -// TODO(mc, 2021-03-31): migrate to @fullstory/browser npm package -// adapted from https://github.com/fullstorydev/fullstory-browser-sdk/blob/master/src/index.d.ts - -declare namespace FullStory { - interface SnippetOptions { - orgId: string - namespace?: string - debug?: boolean - host?: string - script?: string - recordCrossDomainIFrames?: boolean - recordOnlyThisIFrame?: boolean // see README for details - devMode?: boolean - } - - interface UserVars { - displayName?: string - email?: string - [key: string]: any - } - - type LogLevel = 'log' | 'info' | 'warn' | 'error' | 'debug' - - interface FullStory { - anonymize: () => void - consent: (userConsents?: boolean) => void - event: (eventName: string, eventProperties: { [key: string]: any }) => void - identify: (uid: string, customVars?: UserVars) => void - init: (options: SnippetOptions) => void - log: ((level: LogLevel, msg: string) => void) & ((msg: string) => void) - restart: () => void - setUserVars: (customVars: UserVars) => void - shutdown: () => void - } -} - -declare module NodeJS { - interface Global { - _fs_namespace: 'FS' | undefined - FS: FullStory.FullStory | undefined - } -} diff --git a/protocol-designer/README.md b/protocol-designer/README.md index efc3c811b3b..c7bf1b3983a 100644 --- a/protocol-designer/README.md +++ b/protocol-designer/README.md @@ -53,10 +53,6 @@ Used for analytics segmentation. Also saved in protocol file at `designer-applic Used for analytics segmentation. In Travis CI, this is fed by `$TRAVIS_COMMIT`. -### `OT_PD_FULLSTORY_ORG` - -Used for FullStory. Should be provided in the Travis build. - ### `OT_PD_MIXPANEL_ID` Used for Mixpanel in prod. Should be provided in the CI build. diff --git a/protocol-designer/src/analytics/actions.ts b/protocol-designer/src/analytics/actions.ts index 05a6466be06..eee86cd900a 100644 --- a/protocol-designer/src/analytics/actions.ts +++ b/protocol-designer/src/analytics/actions.ts @@ -1,4 +1,3 @@ -import { initializeFullstory, shutdownFullstory } from './fullstory' import { setMixpanelTracking, AnalyticsEvent } from './mixpanel' export interface SetOptIn { @@ -9,10 +8,8 @@ export interface SetOptIn { const _setOptIn = (payload: SetOptIn['payload']): SetOptIn => { // side effects if (payload) { - initializeFullstory() setMixpanelTracking(true) } else { - shutdownFullstory() setMixpanelTracking(false) } diff --git a/protocol-designer/src/analytics/fullstory.ts b/protocol-designer/src/analytics/fullstory.ts deleted file mode 100644 index 023bccec7a1..00000000000 --- a/protocol-designer/src/analytics/fullstory.ts +++ /dev/null @@ -1,91 +0,0 @@ -// @ts-nocheck -import cookie from 'cookie' - -export const shutdownFullstory = (): void => { - if (window[window._fs_namespace]) { - window[window._fs_namespace].shutdown() - } - // eslint-disable-next-line @typescript-eslint/no-dynamic-delete - delete window[window._fs_namespace] -} - -const _setAnalyticsTags = (): void => { - const cookies = cookie.parse(global.document.cookie) - const { ot_email: email, ot_name: displayName } = cookies - const commit_str = process.env.OT_PD_COMMIT_HASH - const version_str = process.env.OT_PD_VERSION - const buildDate_date = new Date(process.env.OT_PD_BUILD_DATE as any) - - // NOTE: fullstory expects the keys 'displayName' and 'email' verbatim - // though all other key names must be fit the schema described here - // https://help.fullstory.com/develop-js/137380 - if (window[window._fs_namespace]) { - window[window._fs_namespace].setUserVars({ - displayName, - email, - commit_str, - version_str, - buildDate_date, - ot_application_name_str: 'protocol-designer', // NOTE: to distinguish from other apps using the org - }) - } -} - -// NOTE: this code snippet is distributed by Fullstory and formatting has been maintained -window._fs_debug = false -window._fs_host = 'fullstory.com' -window._fs_org = process.env.OT_PD_FULLSTORY_ORG -window._fs_namespace = 'FS' - -export const initializeFullstory = (): void => { - ;(function (m, n, e, t, l, o, g: any, y: any) { - if (e in m) { - if (m.console && m.console.log) { - m.console.log( - 'Fullstory namespace conflict. Please set window["_fs_namespace"].' - ) - } - return - } - g = m[e] = function (a, b, s) { - g.q ? g.q.push([a, b, s]) : g._api(a, b, s) - } - g.q = [] - o = n.createElement(t) - o.async = 1 - o.crossOrigin = 'anonymous' - o.src = 'https://' + global._fs_host + '/s/fs.js' - y = n.getElementsByTagName(t)[0] - y.parentNode.insertBefore(o, y) - g.identify = function (i, v, s) { - g(l, { uid: i }, s) - if (v) g(l, v, s) - } - g.setUserVars = function (v, s) { - g(l, v, s) - } - g.event = function (i, v, s) { - g('event', { n: i, p: v }, s) - } - g.shutdown = function () { - g('rec', !1) - } - g.restart = function () { - g('rec', !0) - } - g.log = function (a, b) { - g('log', [a, b]) - } - g.consent = function (a) { - g('consent', !arguments.length || a) - } - g.identifyAccount = function (i, v) { - o = 'account' - v = v || {} - v.acctId = i - g(o, v) - } - g.clearUserCookie = function () {} - })(global, global.document, global._fs_namespace, 'script', 'user') - _setAnalyticsTags() -} diff --git a/protocol-designer/src/components/modals/GateModal/index.tsx b/protocol-designer/src/components/modals/GateModal/index.tsx index df0fec43c71..eb70c0ed0f6 100644 --- a/protocol-designer/src/components/modals/GateModal/index.tsx +++ b/protocol-designer/src/components/modals/GateModal/index.tsx @@ -46,7 +46,7 @@ class GateModalComponent extends React.Component {