diff --git a/change/@ni-nimble-components-2fd7a846-f023-4377-8d09-96c6b0d96f2a.json b/change/@ni-nimble-components-2fd7a846-f023-4377-8d09-96c6b0d96f2a.json new file mode 100644 index 0000000000..1d7899a1e4 --- /dev/null +++ b/change/@ni-nimble-components-2fd7a846-f023-4377-8d09-96c6b0d96f2a.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Refactored experimental structure and update strategy for wafer map component", + "packageName": "@ni/nimble-components", + "email": "33986780+munteannatan@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/nimble-components/build/generate-workers/index.ts b/packages/nimble-components/build/generate-workers/index.ts index 126256529b..e7df262369 100644 --- a/packages/nimble-components/build/generate-workers/index.ts +++ b/packages/nimble-components/build/generate-workers/index.ts @@ -23,12 +23,15 @@ function writeFile(filePath: string, content: string): void { } const renderModuleName: string = '../bundle/matrix-renderer.js'; +const workerTypes: string = '../esm/source/types.d.ts'; const workersDirectory: string = path.resolve('./src/wafer-map/workers'); prepareDirectory(workersDirectory); const modulePath: string = resolveModulePath(renderModuleName); const sourceCode: string = fs.readFileSync(modulePath, 'utf-8'); +const workerTypesPath: string = resolveModulePath(workerTypes); +const typesCode: string = fs.readFileSync(workerTypesPath, 'utf-8'); const fileContent: string = `// eslint-disable-next-line no-template-curly-in-string export const workerCode = ${JSON.stringify(sourceCode)}; @@ -39,4 +42,7 @@ const renderFilePath: string = path.resolve( 'matrix-renderer.ts' ); +const workersFilePath: string = path.resolve(workersDirectory, 'types.ts'); + writeFile(renderFilePath, fileContent); +writeFile(workersFilePath, typesCode); diff --git a/packages/nimble-components/build/generate-workers/source/matrix-renderer.ts b/packages/nimble-components/build/generate-workers/source/matrix-renderer.ts index b03c305cf4..5ae77e8076 100644 --- a/packages/nimble-components/build/generate-workers/source/matrix-renderer.ts +++ b/packages/nimble-components/build/generate-workers/source/matrix-renderer.ts @@ -1,10 +1,5 @@ import { expose } from 'comlink'; -import type { - Dimensions, - Transform, - WaferMapMatrix, - WaferMapTypedMatrix -} from './types'; +import type { Dimensions, RenderConfig, TransformConfig } from './types'; /** * MatrixRenderer class is meant to be used within a Web Worker context, @@ -14,111 +9,102 @@ import type { * This setup is used in the wafer-map component to perform heavy computational duties */ export class MatrixRenderer { - public columnIndexes = Int32Array.from([]); - public rowIndexes = Int32Array.from([]); public values = Float64Array.from([]); - public scaledColumnIndex = Float64Array.from([]); - public scaledRowIndex = Float64Array.from([]); - public columnIndexPositions = Int32Array.from([]); + public scaledColumnIndices = Float64Array.from([]); + public scaledRowIndices = Float64Array.from([]); + public columnIndicesPositions = Int32Array.from([]); public canvas!: OffscreenCanvas; public context!: OffscreenCanvasRenderingContext2D; - private scaleX: number = 1; - private scaleY: number = 1; - private baseX: number = 1; - private baseY: number = 1; - private dieDimensions: Dimensions = { width: 1, height: 1 }; - private transform: Transform = { k: 1, x: 0, y: 0 }; - private topLeftCanvasCorner!: { x: number; y: number }; - private bottomRightCanvasCorner!: { x: number; y: number }; - private readonly smallestMarginPossible: number = 20; - private margin: { - top: number; - right: number; - bottom: number; - left: number; - } = { - top: this.smallestMarginPossible, - right: this.smallestMarginPossible, - bottom: this.smallestMarginPossible, - left: this.smallestMarginPossible - }; + private renderConfig: RenderConfig = { + dieDimensions: { + width: 0, + height: 0 + }, + margin: { + top: 0, + right: 0, + bottom: 0, + left: 0 + }, + verticalCoefficient: 1, + horizontalCoefficient: 1, + horizontalConstant: 0, + verticalConstant: 0, + labelsFontSize: 0, + colorScale: [] + }; + + private transformConfig: TransformConfig = { + transform: { + k: 1, + x: 0, + y: 0 + }, + topLeftCanvasCorner: { + x: 0, + y: 0 + }, + bottomRightCanvasCorner: { + x: 0, + y: 0 + } + }; - public calculateXScaledIndex(columnIndex: number): number { - return this.scaleX * columnIndex + this.baseX + this.margin.left; + private calculateHorizontalScaledIndices(columnIndex: number): number { + return ( + this.renderConfig.horizontalCoefficient! * columnIndex + + this.renderConfig.horizontalConstant! + + this.renderConfig.margin!.left + ); } - public calculateYScaledIndex(rowIndex: number): number { - return this.scaleY * rowIndex + this.baseY + this.margin.top; + private calculateVerticalScaledIndices(rowIndex: number): number { + return ( + this.renderConfig.verticalCoefficient! * rowIndex + + this.renderConfig.verticalConstant! + + this.renderConfig.margin!.top + ); } - public setColumnIndexes(columnIndexes: Int32Array): void { - this.columnIndexes = columnIndexes; - if (columnIndexes.length === 0 || this.columnIndexes[0] === undefined) { + public setColumnIndices(columnIndices: Int32Array): void { + if (columnIndices.length === 0 || columnIndices[0] === undefined) { return; } const scaledColumnIndex = [ - this.calculateXScaledIndex(this.columnIndexes[0]) + this.calculateHorizontalScaledIndices(columnIndices[0]) ]; const columnPositions = [0]; - let prev = this.columnIndexes[0]; - for (let i = 1; i < this.columnIndexes.length; i++) { - const xIndex = this.columnIndexes[i]; + let prev = columnIndices[0]; + for (let i = 1; i < columnIndices.length; i++) { + const xIndex = columnIndices[i]; if (xIndex && xIndex !== prev) { - const scaledX = this.calculateXScaledIndex( - this.columnIndexes[i]! + const scaledX = this.calculateHorizontalScaledIndices( + columnIndices[i]! ); scaledColumnIndex.push(scaledX); columnPositions.push(i); prev = xIndex; } } - this.scaledColumnIndex = Float64Array.from(scaledColumnIndex); - this.columnIndexPositions = Int32Array.from(columnPositions); + this.scaledColumnIndices = Float64Array.from(scaledColumnIndex); + this.columnIndicesPositions = Int32Array.from(columnPositions); } - public setRowIndexes(rowIndexesBuffer: Int32Array): void { - this.rowIndexes = rowIndexesBuffer; - this.scaledRowIndex = new Float64Array(this.rowIndexes.length); - for (let i = 0; i < this.rowIndexes.length; i++) { - this.scaledRowIndex[i] = this.calculateYScaledIndex( - this.rowIndexes[i]! + public setRowIndices(rowIndices: Int32Array): void { + this.scaledRowIndices = new Float64Array(rowIndices.length); + for (let i = 0; i < rowIndices.length; i++) { + this.scaledRowIndices[i] = this.calculateVerticalScaledIndices( + rowIndices[i]! ); } } - public setMargin(margin: { - top: number; - right: number; - bottom: number; - left: number; - }): void { - this.margin = margin; - } - - public setCanvasCorners( - topLeft: { x: number; y: number }, - bottomRight: { x: number; y: number } - ): void { - this.topLeftCanvasCorner = topLeft; - this.bottomRightCanvasCorner = bottomRight; - } - - public setDiesDimensions(data: Dimensions): void { - this.dieDimensions = { width: data.width, height: data.height }; - } - - public setScaling(scaleX: number, scaleY: number): void { - this.scaleX = scaleX; - this.scaleY = scaleY; - } - - public setBases(baseX: number, baseY: number): void { - this.baseX = baseX; - this.baseY = baseY; + public setRenderConfig(renderConfig: RenderConfig): void { + this.renderConfig = renderConfig; } - public setTransform(transform: Transform): void { - this.transform = transform; + public setTransformConfig(transformData: TransformConfig): void { + this.transformConfig = transformData; } public setCanvas(canvas: OffscreenCanvas): void { @@ -126,29 +112,15 @@ export class MatrixRenderer { this.context = canvas.getContext('2d')!; } - public getMatrix(): WaferMapTypedMatrix { - return { - columnIndexes: this.columnIndexes, - rowIndexes: this.rowIndexes, - values: this.values - }; - } - - public emptyMatrix(): void { - this.columnIndexes = Int32Array.from([]); - this.rowIndexes = Int32Array.from([]); - this.values = Float64Array.from([]); - } - public scaleCanvas(): void { - this.context.translate(this.transform.x, this.transform.y); - this.context.scale(this.transform.k, this.transform.k); - } - - public updateMatrix(data: WaferMapMatrix): void { - this.columnIndexes = Int32Array.from(data.columnIndexes); - this.rowIndexes = Int32Array.from(data.rowIndexes); - this.values = Float64Array.from(data.values); + this.context.translate( + this.transformConfig.transform.x, + this.transformConfig.transform.y + ); + this.context.scale( + this.transformConfig.transform.k, + this.transformConfig.transform.k + ); } public setCanvasDimensions(data: Dimensions): void { @@ -172,18 +144,12 @@ export class MatrixRenderer { this.context.save(); this.clearCanvas(); this.scaleCanvas(); - if ( - this.topLeftCanvasCorner === undefined - || this.bottomRightCanvasCorner === undefined - ) { - throw new Error('Canvas corners are not set'); - } - for (let i = 0; i < this.scaledColumnIndex.length; i++) { - const scaledX = this.scaledColumnIndex[i]!; + for (let i = 0; i < this.scaledColumnIndices.length; i++) { + const scaledX = this.scaledColumnIndices[i]!; if ( !( - scaledX >= this.topLeftCanvasCorner.x - && scaledX < this.bottomRightCanvasCorner.x + scaledX >= this.transformConfig.topLeftCanvasCorner.x + && scaledX < this.transformConfig.bottomRightCanvasCorner.x ) ) { continue; @@ -191,20 +157,20 @@ export class MatrixRenderer { // columnIndexPositions is used to get chunks to determine the start and end index of the column, it looks something like [0, 1, 4, 9, 12] // This means that the first column has a start index of 0 and an end index of 1, the second column has a start index of 1 and an end index of 4, and so on - // scaledRowIndex is used when we reach the end of the columnIndexPositions, when columnIndexPositions is [0, 1, 4, 9, 12], scaledRowIndex is 13 - const columnEndIndex = this.columnIndexPositions[i + 1] !== undefined - ? this.columnIndexPositions[i + 1]! - : this.scaledRowIndex.length; + // scaledRowIndices is used when we reach the end of the columnIndexPositions, when columnIndexPositions is [0, 1, 4, 9, 12], scaledRowIndices is 13 + const columnEndIndex = this.columnIndicesPositions[i + 1] !== undefined + ? this.columnIndicesPositions[i + 1]! + : this.scaledRowIndices.length; for ( - let columnStartIndex = this.columnIndexPositions[i]!; + let columnStartIndex = this.columnIndicesPositions[i]!; columnStartIndex < columnEndIndex; columnStartIndex++ ) { - const scaledY = this.scaledRowIndex[columnStartIndex]!; + const scaledY = this.scaledRowIndices[columnStartIndex]!; if ( !( - scaledY >= this.topLeftCanvasCorner.y - && scaledY < this.bottomRightCanvasCorner.y + scaledY >= this.transformConfig.topLeftCanvasCorner.y + && scaledY < this.transformConfig.bottomRightCanvasCorner.y ) ) { continue; @@ -214,8 +180,8 @@ export class MatrixRenderer { this.context.fillRect( scaledX, scaledY, - this.dieDimensions.width, - this.dieDimensions.height + this.renderConfig.dieDimensions.width, + this.renderConfig.dieDimensions.height ); } } diff --git a/packages/nimble-components/build/generate-workers/source/tests/matrix-renderer.spec.ts b/packages/nimble-components/build/generate-workers/source/tests/matrix-renderer.spec.ts index fe2b0c1c75..b71b0454fb 100644 --- a/packages/nimble-components/build/generate-workers/source/tests/matrix-renderer.spec.ts +++ b/packages/nimble-components/build/generate-workers/source/tests/matrix-renderer.spec.ts @@ -1,61 +1,11 @@ import { Remote, expose, transfer, wrap } from 'comlink'; import { MatrixRenderer } from '../matrix-renderer'; -describe('MatrixRenderer with MessageChannel', () => { - let matrixRenderer: Remote; - const testData = { - columnIndexes: [4, 1, 2], - rowIndexes: [54, 54, 62], - values: [8.12, 9.0, 0.32] - }; - - beforeEach(async () => { - const { port1, port2 } = new MessageChannel(); - const worker = new MatrixRenderer(); - expose(worker, port1); - matrixRenderer = await wrap(port2); - }); - - it('updateMatrix should update the dieMatrix', async () => { - await matrixRenderer.updateMatrix(testData); - - const updatedMatrix = await matrixRenderer.getMatrix(); - expect(updatedMatrix).toEqual({ - columnIndexes: Int32Array.from(testData.columnIndexes), - rowIndexes: Int32Array.from(testData.rowIndexes), - values: Float64Array.from(testData.values) - }); - }); - - it('emptyMatrix should empty the dieMatrix', async () => { - await matrixRenderer.emptyMatrix(); - - const updatedMatrix = await matrixRenderer.getMatrix(); - expect( - updatedMatrix.columnIndexes.length - + updatedMatrix.rowIndexes.length - + updatedMatrix.values.length - ).toEqual(0); - }); - - it('calculateYScaledIndex should compute the scaleY index', async () => { - await matrixRenderer.setBases(2, 2); - await matrixRenderer.setScaling(0.5, 0.5); - expect(await matrixRenderer.calculateYScaledIndex(100)).toEqual(72); - }); - - it('calculateXScaledIndex should compute the scaleX index', async () => { - await matrixRenderer.setBases(3, 3); - await matrixRenderer.setScaling(1, 1); - expect(await matrixRenderer.calculateXScaledIndex(100)).toEqual(123); - }); -}); - describe('MatrixRenderer with MessageChannel needing canvas context', () => { let matrixRenderer: Remote; const testData = { - columnIndexes: [4, 1, 2], - rowIndexes: [54, 54, 62], + columnIndices: [4, 1, 2], + rowIndices: [54, 54, 62], values: [8.12, 9.0, 0.32] }; @@ -66,6 +16,39 @@ describe('MatrixRenderer with MessageChannel needing canvas context', () => { matrixRenderer = await wrap(port2); const offscreenCanvas = new OffscreenCanvas(300, 300); matrixRenderer.setCanvas(transfer(offscreenCanvas, [offscreenCanvas])); + await matrixRenderer.setRenderConfig({ + dieDimensions: { + width: 10, + height: 10 + }, + margin: { + top: 0, + right: 0, + bottom: 0, + left: 0 + }, + verticalCoefficient: 1, + horizontalCoefficient: 1, + horizontalConstant: 0, + verticalConstant: 0, + labelsFontSize: 0, + colorScale: [] + }); + await matrixRenderer.setTransformConfig({ + transform: { + k: 1, + x: 1, + y: 1 + }, + topLeftCanvasCorner: { + x: 0, + y: 0 + }, + bottomRightCanvasCorner: { + x: 0, + y: 0 + } + }); }); it('setCanvasDimensions should set the canvas dimensions', async () => { @@ -76,27 +59,17 @@ describe('MatrixRenderer with MessageChannel needing canvas context', () => { }); }); - it('indexes should be set', async () => { - const typedColumnIndexes = Int32Array.from(testData.columnIndexes); - const typedRowIndexes = Int32Array.from(testData.rowIndexes); - - await matrixRenderer.setColumnIndexes( - transfer(typedColumnIndexes, [typedColumnIndexes.buffer]) - ); - await matrixRenderer.setRowIndexes( - transfer(typedRowIndexes, [typedRowIndexes.buffer]) - ); + it('scaled Indices should be computed', async () => { + const typedColumnIndices = Int32Array.from(testData.columnIndices); + const typedRowIndices = Int32Array.from(testData.rowIndices); - const columnIndexes = await matrixRenderer.columnIndexes; - const rowIndexes = await matrixRenderer.rowIndexes; + await matrixRenderer.setColumnIndices(typedColumnIndices); + await matrixRenderer.setRowIndices(typedRowIndices); - expect(columnIndexes).toEqual(Int32Array.from([4, 1, 2])); - expect(rowIndexes).toEqual(Int32Array.from([54, 54, 62])); - }); + const scaledColumnIndex = await matrixRenderer.scaledColumnIndices; + const scaledRowIndex = await matrixRenderer.scaledRowIndices; - it('should throw error calling drawWafer if canvas corners are not set', async () => { - await expectAsync(matrixRenderer.drawWafer()).toBeRejectedWithError( - 'Canvas corners are not set' - ); + expect(scaledColumnIndex).toEqual(Float64Array.from([4, 1, 2])); + expect(scaledRowIndex).toEqual(Float64Array.from([54, 54, 62])); }); }); diff --git a/packages/nimble-components/build/generate-workers/source/types.ts b/packages/nimble-components/build/generate-workers/source/types.ts index ea148ccfc8..6391b3dc94 100644 --- a/packages/nimble-components/build/generate-workers/source/types.ts +++ b/packages/nimble-components/build/generate-workers/source/types.ts @@ -1,15 +1,3 @@ -export interface WaferMapTypedMatrix { - columnIndexes: Int32Array; - rowIndexes: Int32Array; - values: Float64Array; -} - -export interface WaferMapMatrix { - columnIndexes: number[]; - rowIndexes: number[]; - values: number[]; -} - export interface Transform { k: number; x: number; @@ -20,3 +8,37 @@ export interface Dimensions { width: number; height: number; } + +export interface Position { + x: number; + y: number; +} +export interface Margin { + readonly top: number; + readonly right: number; + readonly bottom: number; + readonly left: number; +} +export interface IColorScaleMarker { + color: string; + value: number; +} + +export type ColorScale = IColorScaleMarker[]; + +export interface RenderConfig { + dieDimensions: Dimensions; + margin: Margin; + verticalCoefficient: number; + horizontalCoefficient: number; + horizontalConstant: number; + verticalConstant: number; + labelsFontSize: number; + colorScale: ColorScale; +} + +export interface TransformConfig { + transform: Transform; + topLeftCanvasCorner: Position; + bottomRightCanvasCorner: Position; +} diff --git a/packages/nimble-components/src/wafer-map/modules/experimental/computations.ts b/packages/nimble-components/src/wafer-map/experimental/computations.ts similarity index 67% rename from packages/nimble-components/src/wafer-map/modules/experimental/computations.ts rename to packages/nimble-components/src/wafer-map/experimental/computations.ts index b141bba94d..c6e2deb302 100644 --- a/packages/nimble-components/src/wafer-map/modules/experimental/computations.ts +++ b/packages/nimble-components/src/wafer-map/experimental/computations.ts @@ -1,6 +1,8 @@ import { scaleLinear, ScaleLinear } from 'd3-scale'; -import type { WaferMap } from '../..'; -import { Dimensions, Margin, WaferMapOriginLocation } from '../../types'; +import { ticks } from 'd3-array'; +import type { WaferMap } from '..'; +import { WaferMapColorScaleMode, WaferMapOriginLocation } from '../types'; +import type { ColorScale, Dimensions, Margin } from '../workers/types'; interface GridDimensions { origin: { @@ -15,6 +17,14 @@ interface GridDimensions { * Computations calculates and stores different measures which are used in the Wafermap */ export class Computations { + public get horizontalScale(): ScaleLinear { + return this._horizontalScale; + } + + public get verticalScale(): ScaleLinear { + return this._verticalScale; + } + public get containerDimensions(): Dimensions { return this._containerDimensions; } @@ -27,25 +37,49 @@ export class Computations { return this._margin; } - public get horizontalScale(): ScaleLinear { - return this._horizontalScale; + public get verticalCoefficient(): number { + return this._verticalCoefficient; } - public get verticalScale(): ScaleLinear { - return this._verticalScale; + public get horizontalCoefficient(): number { + return this._horizontalCoefficient; + } + + public get horizontalConstant(): number { + return this._horizontalConstant; + } + + public get verticalConstant(): number { + return this._verticalConstant; + } + + public get labelsFontSize(): number { + return this._labelsFontSize; + } + + public get colorScale(): ColorScale { + return this._colorScale; } + private _horizontalScale!: ScaleLinear; + private _verticalScale!: ScaleLinear; private _containerDimensions!: Dimensions; private _dieDimensions!: Dimensions; private _margin!: Margin; - private _horizontalScale!: ScaleLinear; - private _verticalScale!: ScaleLinear; - private readonly defaultPadding = 0; + private _verticalCoefficient!: number; + private _horizontalCoefficient!: number; + private _horizontalConstant!: number; + private _verticalConstant!: number; + private _labelsFontSize!: number; + private _colorScale!: ColorScale; + private readonly baseMarginPercentage = 0.04; + private readonly fontSizeFactor = 0.8; + private readonly colorScaleResolution = 10; public constructor(private readonly wafermap: WaferMap) {} - public update(): void { + public componentResizeUpdate(): void { const canvasDimensions = { width: this.wafermap.canvasWidth, height: this.wafermap.canvasHeight @@ -69,8 +103,16 @@ export class Computations { this._margin = this.calculateMarginAddition(baseMargin, canvasMargin); this._containerDimensions = this.calculateContainerDimensions( canvasDimensions, - this._margin + this.margin ); + this.inputDataUpdate(); + } + + public inputDataUpdate(): void { + if (this._containerDimensions === undefined) { + this.componentResizeUpdate(); + return; + } const containerDiameter = Math.min( this._containerDimensions.width, this._containerDimensions.height @@ -91,12 +133,30 @@ export class Computations { gridDimensions, containerDiameter ); + this._horizontalCoefficient = this._horizontalScale(1) - this._horizontalScale(0); + this._verticalCoefficient = this._verticalScale(1) - this._verticalScale(0); + this._horizontalConstant = this._horizontalScale(0); + this._verticalConstant = this._verticalScale(0); + this._dieDimensions = { width: Math.abs( this._horizontalScale(0) - this._horizontalScale(1) ), height: Math.abs(this._verticalScale(0) - this._verticalScale(1)) }; + this.colorAndTextUpdate(); + } + + public colorAndTextUpdate(): void { + if (this._dieDimensions === undefined) { + this.inputDataUpdate(); + return; + } + this._labelsFontSize = this.calculateLabelsFontSize( + this._dieDimensions, + this.wafermap.maxCharacters + ); + this._colorScale = this.calculateColorScale(); } private gridDimensionsValidAndDefined(): boolean { @@ -224,4 +284,55 @@ export class Computations { left: baseMargin.left + addedMargin.left }; } + + private calculateColorScale(): ColorScale { + if (this.wafermap.colorScaleMode === WaferMapColorScaleMode.linear) { + const values = this.wafermap.colorScale.values.map(item => +item); + const d3ColorScale = scaleLinear() + .domain(values) + .range(this.wafermap.colorScale.colors); + let min = values[0]!; + let max = values[0]!; + values.forEach(value => { + if (value < min) { + min = value; + } + if (value > max) { + max = value; + } + }); + // the linear color scale will not be infinite but will be limited by the color scale resolution + const valueSamples = ticks( + min, + max, + values.length * this.colorScaleResolution + ); + return valueSamples.map(value => { + return { + color: d3ColorScale(value), + value + }; + }); + } + // ordinal color categories have to be sorted by value + return this.wafermap.colorScale.colors + .map((color, index) => { + return { + color, + value: +this.wafermap.colorScale.values[index]! + }; + }) + .sort((a, b) => a.value - b.value); + } + + private calculateLabelsFontSize( + dieDimensions: Dimensions, + maxCharacters: number + ): number { + return Math.min( + dieDimensions.height, + (dieDimensions.width / (Math.max(2, maxCharacters) * 0.5)) + * this.fontSizeFactor + ); + } } diff --git a/packages/nimble-components/src/wafer-map/modules/experimental/hover-handler.ts b/packages/nimble-components/src/wafer-map/experimental/hover-handler.ts similarity index 86% rename from packages/nimble-components/src/wafer-map/modules/experimental/hover-handler.ts rename to packages/nimble-components/src/wafer-map/experimental/hover-handler.ts index 402c45a372..e78da34cc9 100644 --- a/packages/nimble-components/src/wafer-map/modules/experimental/hover-handler.ts +++ b/packages/nimble-components/src/wafer-map/experimental/hover-handler.ts @@ -1,5 +1,5 @@ -import type { WaferMap } from '../..'; -import { PointCoordinates, WaferMapOriginLocation } from '../../types'; +import type { WaferMap } from '..'; +import { PointCoordinates, WaferMapOriginLocation } from '../types'; /** * HoverHandler deals with user interactions and events like hovering @@ -83,15 +83,13 @@ export class HoverHandler { : Math.floor; // go to x and y scale to get the x,y values of the die. const x = xRoundFunction( - this.wafermap.experimentalDataManager.horizontalScale.invert( - mousePosition.x - - this.wafermap.experimentalDataManager.margin.left + this.wafermap.computations.horizontalScale.invert( + mousePosition.x - this.wafermap.computations.margin.left ) ); const y = yRoundFunction( - this.wafermap.experimentalDataManager.verticalScale.invert( - mousePosition.y - - this.wafermap.experimentalDataManager.margin.top + this.wafermap.computations.verticalScale.invert( + mousePosition.y - this.wafermap.computations.margin.top ) ); return { x, y }; diff --git a/packages/nimble-components/src/wafer-map/experimental/worker-renderer.ts b/packages/nimble-components/src/wafer-map/experimental/worker-renderer.ts new file mode 100644 index 0000000000..3064733103 --- /dev/null +++ b/packages/nimble-components/src/wafer-map/experimental/worker-renderer.ts @@ -0,0 +1,102 @@ +import { type Remote, transfer } from 'comlink'; +import type { ZoomTransform } from 'd3-zoom'; +import type { WaferMap } from '..'; +import { HoverDieOpacity } from '../types'; +import { createMatrixRenderer } from '../modules/create-matrix-renderer'; +import type { MatrixRenderer } from '../../../build/generate-workers/dist/esm/source/matrix-renderer'; +import type { Dimensions, RenderConfig } from '../workers/types'; + +/** + * Responsible for drawing the dies inside the wafer map, adding dieText and scaling the canvas + */ +export class WorkerRenderer { + private matrixRenderer!: Remote; + + public constructor(private readonly wafermap: WaferMap) {} + + public async setupWafer(snapshot: { + canvasDimensions: Dimensions, + renderConfig: RenderConfig, + columnIndices: Int32Array, + rowIndices: Int32Array + }): Promise { + if (this.matrixRenderer === undefined) { + const { matrixRenderer } = await createMatrixRenderer(); + this.matrixRenderer = matrixRenderer; + const offscreenCanvas = this.wafermap.workerCanvas.transferControlToOffscreen(); + await this.matrixRenderer.setCanvas( + transfer(offscreenCanvas, [offscreenCanvas]) + ); + } + await this.matrixRenderer.setCanvasDimensions( + snapshot.canvasDimensions + ); + await this.matrixRenderer.setRenderConfig(snapshot.renderConfig); + await this.matrixRenderer.setColumnIndices(snapshot.columnIndices); + await this.matrixRenderer.setRowIndices(snapshot.rowIndices); + } + + public async drawWafer(snapshot: { + canvasDimensions: Dimensions, + dieDimensions: Dimensions, + transform: ZoomTransform + }): Promise { + const topLeftCanvasCorner = snapshot.transform.invert([0, 0]); + const bottomRightCanvasCorner = snapshot.transform.invert([ + snapshot.canvasDimensions.width, + snapshot.canvasDimensions.height + ]); + await this.matrixRenderer.setTransformConfig({ + transform: snapshot.transform, + topLeftCanvasCorner: { + x: topLeftCanvasCorner[0] - snapshot.dieDimensions.width, + y: topLeftCanvasCorner[1] - snapshot.dieDimensions.height + }, + bottomRightCanvasCorner: { + x: bottomRightCanvasCorner[0], + y: bottomRightCanvasCorner[1] + } + }); + await this.matrixRenderer.drawWafer(); + } + + public renderHover(): void { + if ( + this.wafermap.computations.dieDimensions === undefined + || this.wafermap.transform === undefined + ) { + return; + } + this.wafermap.hoverWidth = this.wafermap.computations.dieDimensions.width + * this.wafermap.transform.k; + this.wafermap.hoverHeight = this.wafermap.computations.dieDimensions.height + * this.wafermap.transform.k; + this.wafermap.hoverOpacity = this.wafermap.hoverDie === undefined + ? HoverDieOpacity.hide + : HoverDieOpacity.show; + this.wafermap.hoverTransform = this.calculateHoverTransform(); + } + + private calculateHoverTransform(): string { + if (this.wafermap.hoverDie !== undefined) { + const scaledX = this.wafermap.computations.horizontalScale( + this.wafermap.hoverDie.x + ); + if (scaledX === undefined) { + return ''; + } + const scaledY = this.wafermap.computations.verticalScale( + this.wafermap.hoverDie.y + ); + if (scaledY === undefined) { + return ''; + } + const transformedPoint = this.wafermap.transform.apply([ + scaledX + this.wafermap.computations.margin.left, + scaledY + this.wafermap.computations.margin.top + ]); + return `translate(${transformedPoint[0]}, ${transformedPoint[1]})`; + } + return ''; + } +} diff --git a/packages/nimble-components/src/wafer-map/index.ts b/packages/nimble-components/src/wafer-map/index.ts index 68386420c0..202becfff8 100644 --- a/packages/nimble-components/src/wafer-map/index.ts +++ b/packages/nimble-components/src/wafer-map/index.ts @@ -9,7 +9,6 @@ import type { Table } from 'apache-arrow'; import { template } from './template'; import { styles } from './styles'; import { DataManager } from './modules/data-manager'; -import { DataManager as ExperimentalDataManager } from './modules/experimental/data-manager'; import { RenderingModule } from './modules/rendering'; import { HoverDie, @@ -24,10 +23,12 @@ import { } from './types'; import { WaferMapUpdateTracker } from './modules/wafer-map-update-tracker'; import { WaferMapValidator } from './modules/wafer-map-validator'; -import { WorkerRenderer } from './modules/experimental/worker-renderer'; +import { WorkerRenderer } from './experimental/worker-renderer'; import { HoverHandler } from './modules/hover-handler'; -import { HoverHandler as ExperimentalHoverHandler } from './modules/experimental/hover-handler'; +import { HoverHandler as ExperimentalHoverHandler } from './experimental/hover-handler'; import { ZoomHandler } from './modules/zoom-handler'; +import { Computations } from './experimental/computations'; +import type { Dimensions, RenderConfig } from './workers/types'; declare global { interface HTMLElementTagNameMap { @@ -102,7 +103,9 @@ export class WaferMap< */ public readonly zoomContainer!: HTMLElement; - public readonly experimentalDataManager: ExperimentalDataManager = new ExperimentalDataManager(this.asRequiredFieldsWaferMap); + public readonly computations: Computations = new Computations( + this.asRequiredFieldsWaferMap + ); public dataManager: DataManager = new DataManager( this.asRequiredFieldsWaferMap @@ -216,27 +219,21 @@ export class WaferMap< if (this.validity.invalidDiesTableSchema) { return; } - if (this.waferMapUpdateTracker.requiresEventsUpdate) { - if ( - this.waferMapUpdateTracker.requiresContainerDimensionsUpdate - || this.waferMapUpdateTracker.requiresScalesUpdate - ) { - this.experimentalDataManager.updateComputations(); - await this.workerRenderer.setupWafer(); - await this.workerRenderer.drawWafer(); - } else if ( - this.waferMapUpdateTracker.requiresLabelsFontSizeUpdate - || this.waferMapUpdateTracker.requiresDiesRenderInfoUpdate - ) { - this.experimentalDataManager.updatePrerendering(); - await this.workerRenderer.drawWafer(); - } else if (this.waferMapUpdateTracker.requiresDrawnWaferUpdate) { - await this.workerRenderer.drawWafer(); + if (this.waferMapUpdateTracker.requiresComponentResizeUpdate) { + this.computations.componentResizeUpdate(); + } else if (this.waferMapUpdateTracker.requiresInputDataUpdate) { + this.computations.inputDataUpdate(); + } else if (this.waferMapUpdateTracker.requiresColorAndTextUpdate) { + this.computations.colorAndTextUpdate(); } - } else if (this.waferMapUpdateTracker.requiresRenderHoverUpdate) { - this.workerRenderer.renderHover(); + const snapshot = this.createSnapshot(); + if (this.waferMapUpdateTracker.requiresWorkerWaferSetup) { + await this.workerRenderer.setupWafer(snapshot); + } + await this.workerRenderer.drawWafer(snapshot); } + this.workerRenderer.renderHover(); } /** @@ -285,6 +282,53 @@ export class WaferMap< return this.diesTable !== undefined; } + private createSnapshot(): { + canvasDimensions: Dimensions, + renderConfig: RenderConfig, + dieDimensions: Dimensions, + transform: ZoomTransform, + columnIndices: Int32Array, + rowIndices: Int32Array + } { + const canvasDimensions = { + width: this.canvasWidth ?? 0, + height: this.canvasHeight ?? 0 + }; + const renderConfig: RenderConfig = { + dieDimensions: this.computations.dieDimensions, + margin: this.computations.margin, + verticalCoefficient: this.computations.verticalCoefficient, + horizontalCoefficient: this.computations.horizontalCoefficient, + horizontalConstant: this.computations.horizontalConstant, + verticalConstant: this.computations.verticalConstant, + labelsFontSize: this.computations.labelsFontSize, + colorScale: this.computations.colorScale + }; + const dieDimensions = this.computations.dieDimensions; + const transform = this.transform; + if (this.diesTable === undefined) { + return { + canvasDimensions, + renderConfig, + dieDimensions, + transform, + columnIndices: Int32Array.from([]), + rowIndices: Int32Array.from([]) + }; + } + const columnIndices = this.diesTable.getChild('colIndex')!.toArray(); + + const rowIndices = this.diesTable.getChild('rowIndex')!.toArray(); + return { + canvasDimensions, + renderConfig, + columnIndices, + rowIndices, + dieDimensions, + transform + }; + } + private validate(): void { this.waferMapValidator.validateGridDimensions(); this.waferMapValidator.validateDiesTableSchema(); diff --git a/packages/nimble-components/src/wafer-map/modules/computations.ts b/packages/nimble-components/src/wafer-map/modules/computations.ts index 0569ea9ac2..0975098eb2 100644 --- a/packages/nimble-components/src/wafer-map/modules/computations.ts +++ b/packages/nimble-components/src/wafer-map/modules/computations.ts @@ -2,7 +2,8 @@ import { range } from 'd3-array'; import { ScaleBand, scaleBand, scaleQuantile, ScaleQuantile } from 'd3-scale'; import type { WaferMap } from '..'; import type { WaferMapDie } from '../types'; -import { Dimensions, Margin, WaferMapOriginLocation } from '../types'; +import { WaferMapOriginLocation } from '../types'; +import type { Dimensions, Margin } from '../workers/types'; interface GridDimensions { origin: { diff --git a/packages/nimble-components/src/wafer-map/modules/data-manager.ts b/packages/nimble-components/src/wafer-map/modules/data-manager.ts index b098683bfd..b89456c94d 100644 --- a/packages/nimble-components/src/wafer-map/modules/data-manager.ts +++ b/packages/nimble-components/src/wafer-map/modules/data-manager.ts @@ -2,13 +2,8 @@ import type { ScaleBand, ScaleQuantile } from 'd3-scale'; import { Computations } from './computations'; import { Prerendering } from './prerendering'; import type { WaferMap } from '..'; -import type { - Dimensions, - Margin, - DieRenderInfo, - WaferMapDie, - PointCoordinates -} from '../types'; +import type { DieRenderInfo, WaferMapDie, PointCoordinates } from '../types'; +import type { Dimensions, Margin } from '../workers/types'; /** * Data Manager uses Computations and Prerendering modules in order and exposes the results diff --git a/packages/nimble-components/src/wafer-map/modules/experimental/data-manager.ts b/packages/nimble-components/src/wafer-map/modules/experimental/data-manager.ts deleted file mode 100644 index 8bb9b0cd3e..0000000000 --- a/packages/nimble-components/src/wafer-map/modules/experimental/data-manager.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { ScaleLinear } from 'd3-scale'; -import { Computations } from './computations'; -import { Prerendering } from './prerendering'; -import type { WaferMap } from '../..'; -import type { ColorScale, Dimensions, Margin } from '../../types'; - -/** - * Data Manager uses Computations and Prerendering modules in order and exposes the results - */ -export class DataManager { - public get containerDimensions(): Dimensions { - return this.computations.containerDimensions; - } - - public get dieDimensions(): Dimensions { - return this.computations.dieDimensions; - } - - public get margin(): Margin { - return this.computations.margin; - } - - public get horizontalScale(): ScaleLinear { - return this.computations.horizontalScale; - } - - public get verticalScale(): ScaleLinear { - return this.computations.verticalScale; - } - - public get labelsFontSize(): number { - return this.prerendering.labelsFontSize; - } - - public get colorScale(): ColorScale { - return this.prerendering.colorScale; - } - - private readonly computations: Computations; - private readonly prerendering: Prerendering; - - public constructor(private readonly wafermap: WaferMap) { - this.computations = new Computations(wafermap); - this.prerendering = new Prerendering(wafermap); - } - - public updateComputations(): void { - this.computations.update(); - this.prerendering.update(); - } - - public updatePrerendering(): void { - this.prerendering.update(); - } -} diff --git a/packages/nimble-components/src/wafer-map/modules/experimental/prerendering.ts b/packages/nimble-components/src/wafer-map/modules/experimental/prerendering.ts deleted file mode 100644 index b7b324f2f7..0000000000 --- a/packages/nimble-components/src/wafer-map/modules/experimental/prerendering.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { scaleLinear } from 'd3-scale'; -import { ticks } from 'd3-array'; -import { WaferMapColorScaleMode } from '../../types'; -import type { ColorScale, Dimensions } from '../../types'; -import type { WaferMap } from '../..'; - -/** - * Prerendering prepares render-ready dies data to be used by the rendering module - */ -export class Prerendering { - public get labelsFontSize(): number { - return this._labelsFontSize; - } - - public get colorScale(): ColorScale { - return this._colorScale; - } - - private _colorScale!: ColorScale; - - private _labelsFontSize!: number; - - private readonly fontSizeFactor = 0.8; - private readonly colorScaleResolution = 10; - - public constructor(private readonly wafermap: WaferMap) {} - - public update(): void { - this._labelsFontSize = this.calculateLabelsFontSize( - this.wafermap.experimentalDataManager.dieDimensions, - this.wafermap.maxCharacters - ); - this._colorScale = this.calculateColorScale(); - } - - private calculateColorScale(): ColorScale { - if (this.wafermap.colorScaleMode === WaferMapColorScaleMode.linear) { - const values = this.wafermap.colorScale.values.map(item => +item); - const d3ColorScale = scaleLinear() - .domain(values) - .range(this.wafermap.colorScale.colors); - let min = values[0]!; - let max = values[0]!; - values.forEach(value => { - if (value < min) { - min = value; - } - if (value > max) { - max = value; - } - }); - // the linear color scale will not be infinite but will be limited by the color scale resolution - const valueSamples = ticks( - min, - max, - values.length * this.colorScaleResolution - ); - return valueSamples.map(value => { - return { - color: d3ColorScale(value), - value - }; - }); - } - // ordinal color categories have to be sorted by value - return this.wafermap.colorScale.colors - .map((color, index) => { - return { - color, - value: +this.wafermap.colorScale.values[index]! - }; - }) - .sort((a, b) => a.value - b.value); - } - - private calculateLabelsFontSize( - dieDimensions: Dimensions, - maxCharacters: number - ): number { - return Math.min( - dieDimensions.height, - (dieDimensions.width / (Math.max(2, maxCharacters) * 0.5)) - * this.fontSizeFactor - ); - } -} diff --git a/packages/nimble-components/src/wafer-map/modules/experimental/worker-renderer.ts b/packages/nimble-components/src/wafer-map/modules/experimental/worker-renderer.ts deleted file mode 100644 index d38540d977..0000000000 --- a/packages/nimble-components/src/wafer-map/modules/experimental/worker-renderer.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { type Remote, transfer } from 'comlink'; -import type { WaferMap } from '../..'; -import { HoverDieOpacity } from '../../types'; -import { createMatrixRenderer } from '../create-matrix-renderer'; -import type { MatrixRenderer } from '../../../../build/generate-workers/dist/esm/source/matrix-renderer'; - -/** - * Responsible for drawing the dies inside the wafer map, adding dieText and scaling the canvas - */ -export class WorkerRenderer { - private matrixRenderer!: Remote; - - public constructor(private readonly wafermap: WaferMap) {} - - public async setupWafer(): Promise { - if (this.matrixRenderer === undefined) { - const { matrixRenderer } = await createMatrixRenderer(); - this.matrixRenderer = matrixRenderer; - const offscreenCanvas = this.wafermap.workerCanvas.transferControlToOffscreen(); - await this.matrixRenderer.setCanvas( - transfer(offscreenCanvas, [offscreenCanvas]) - ); - } - - await this.matrixRenderer.setCanvasDimensions({ - width: this.wafermap.canvasWidth ?? 0, - height: this.wafermap.canvasHeight ?? 0 - }); - await this.matrixRenderer.setDiesDimensions( - this.wafermap.experimentalDataManager.dieDimensions - ); - const scaleX = this.wafermap.experimentalDataManager.horizontalScale(1)! - - this.wafermap.experimentalDataManager.horizontalScale(0)!; - const scaleY = this.wafermap.experimentalDataManager.verticalScale(1)! - - this.wafermap.experimentalDataManager.verticalScale(0)!; - await this.matrixRenderer.setScaling(scaleX, scaleY); - await this.matrixRenderer.setBases( - this.wafermap.experimentalDataManager.horizontalScale(0)!, - this.wafermap.experimentalDataManager.verticalScale(0)! - ); - await this.matrixRenderer.setMargin( - this.wafermap.experimentalDataManager.margin - ); - - if (this.wafermap.diesTable === undefined) { - await this.matrixRenderer.setColumnIndexes(Int32Array.from([])); - await this.matrixRenderer.setRowIndexes(Int32Array.from([])); - return; - } - - const columnIndexes = this.wafermap.diesTable - .getChild('colIndex')! - .toArray(); - await this.matrixRenderer.setColumnIndexes(columnIndexes); - - const rowIndexes = this.wafermap.diesTable - .getChild('rowIndex')! - .toArray(); - await this.matrixRenderer.setRowIndexes(rowIndexes); - } - - public async drawWafer(): Promise { - await this.matrixRenderer.setTransform(this.wafermap.transform); - const topLeftCanvasCorner = this.wafermap.transform.invert([0, 0]); - const bottomRightCanvasCorner = this.wafermap.transform.invert([ - this.wafermap.canvasWidth, - this.wafermap.canvasHeight - ]); - await this.matrixRenderer.setCanvasCorners( - { - x: - topLeftCanvasCorner[0] - - this.wafermap.experimentalDataManager.dieDimensions.width, - y: - topLeftCanvasCorner[1] - - this.wafermap.experimentalDataManager.dieDimensions.height - }, - { - x: bottomRightCanvasCorner[0], - y: bottomRightCanvasCorner[1] - } - ); - await this.matrixRenderer.drawWafer(); - this.renderHover(); - } - - public renderHover(): void { - if ( - this.wafermap.experimentalDataManager.dieDimensions === undefined - || this.wafermap.transform === undefined - ) { - return; - } - this.wafermap.hoverWidth = this.wafermap.experimentalDataManager.dieDimensions.width - * this.wafermap.transform.k; - this.wafermap.hoverHeight = this.wafermap.experimentalDataManager.dieDimensions.height - * this.wafermap.transform.k; - this.wafermap.hoverOpacity = this.wafermap.hoverDie === undefined - ? HoverDieOpacity.hide - : HoverDieOpacity.show; - this.wafermap.hoverTransform = this.calculateHoverTransform(); - } - - private calculateHoverTransform(): string { - if (this.wafermap.hoverDie !== undefined) { - const scaledX = this.wafermap.experimentalDataManager.horizontalScale( - this.wafermap.hoverDie.x - ); - if (scaledX === undefined) { - return ''; - } - const scaledY = this.wafermap.experimentalDataManager.verticalScale( - this.wafermap.hoverDie.y - ); - if (scaledY === undefined) { - return ''; - } - const transformedPoint = this.wafermap.transform.apply([ - scaledX + this.wafermap.experimentalDataManager.margin.left, - scaledY + this.wafermap.experimentalDataManager.margin.top - ]); - return `translate(${transformedPoint[0]}, ${transformedPoint[1]})`; - } - return ''; - } -} diff --git a/packages/nimble-components/src/wafer-map/modules/prerendering.ts b/packages/nimble-components/src/wafer-map/modules/prerendering.ts index 9485b77589..506b81a01a 100644 --- a/packages/nimble-components/src/wafer-map/modules/prerendering.ts +++ b/packages/nimble-components/src/wafer-map/modules/prerendering.ts @@ -1,13 +1,9 @@ import { ScaleLinear, scaleLinear, ScaleOrdinal, scaleOrdinal } from 'd3-scale'; import { ColorRGBA64, parseColor } from '@microsoft/fast-colors'; import { WaferMapColorScaleMode } from '../types'; -import type { - Dimensions, - DieRenderInfo, - WaferMapColorScale, - WaferMapDie -} from '../types'; +import type { DieRenderInfo, WaferMapColorScale, WaferMapDie } from '../types'; import type { WaferMap } from '..'; +import type { Dimensions } from '../workers/types'; /** * Prerendering prepares render-ready dies data to be used by the rendering module diff --git a/packages/nimble-components/src/wafer-map/modules/wafer-map-update-tracker.ts b/packages/nimble-components/src/wafer-map/modules/wafer-map-update-tracker.ts index 2e131e2b40..b0f430fbdc 100644 --- a/packages/nimble-components/src/wafer-map/modules/wafer-map-update-tracker.ts +++ b/packages/nimble-components/src/wafer-map/modules/wafer-map-update-tracker.ts @@ -33,8 +33,7 @@ export class WaferMapUpdateTracker extends UpdateTracker { public get requiresEventsUpdate(): boolean { return ( - this.isTracked('highlightedTags') - || this.isTracked('canvasWidth') + this.isTracked('canvasWidth') || this.isTracked('canvasHeight') || this.isTracked('originLocation') || this.isTracked('gridMinX') @@ -43,6 +42,7 @@ export class WaferMapUpdateTracker extends UpdateTracker { || this.isTracked('gridMaxY') || this.isTracked('dies') || this.isTracked('maxCharacters') + || this.isTracked('highlightedTags') || this.isTracked('colorScale') || this.isTracked('colorScaleMode') || this.isTracked('dieLabelsHidden') @@ -51,10 +51,33 @@ export class WaferMapUpdateTracker extends UpdateTracker { ); } + public get requiresWorkerWaferSetup(): boolean { + return ( + this.isTracked('canvasWidth') + || this.isTracked('canvasHeight') + || this.isTracked('originLocation') + || this.isTracked('gridMinX') + || this.isTracked('gridMaxX') + || this.isTracked('gridMinY') + || this.isTracked('gridMaxY') + || this.isTracked('dies') + || this.isTracked('maxCharacters') + || this.isTracked('highlightedTags') + || this.isTracked('colorScale') + || this.isTracked('colorScaleMode') + || this.isTracked('dieLabelsHidden') + || this.isTracked('dieLabelsSuffix') + ); + } + public get requiresContainerDimensionsUpdate(): boolean { return this.isTracked('canvasWidth') || this.isTracked('canvasHeight'); } + public get requiresComponentResizeUpdate(): boolean { + return this.isTracked('canvasWidth') || this.isTracked('canvasHeight'); + } + public get requiresScalesUpdate(): boolean { return ( this.isTracked('originLocation') @@ -66,6 +89,17 @@ export class WaferMapUpdateTracker extends UpdateTracker { ); } + public get requiresInputDataUpdate(): boolean { + return ( + this.isTracked('originLocation') + || this.isTracked('gridMinX') + || this.isTracked('gridMaxX') + || this.isTracked('gridMinY') + || this.isTracked('gridMaxY') + || this.isTracked('dies') + ); + } + public get requiresLabelsFontSizeUpdate(): boolean { return this.isTracked('maxCharacters'); } @@ -80,6 +114,17 @@ export class WaferMapUpdateTracker extends UpdateTracker { ); } + public get requiresColorAndTextUpdate(): boolean { + return ( + this.isTracked('maxCharacters') + || this.isTracked('highlightedTags') + || this.isTracked('colorScale') + || this.isTracked('colorScaleMode') + || this.isTracked('dieLabelsHidden') + || this.isTracked('dieLabelsSuffix') + ); + } + public get requiresDrawnWaferUpdate(): boolean { return this.isTracked('transform'); } diff --git a/packages/nimble-components/src/wafer-map/tests/computations.spec.ts b/packages/nimble-components/src/wafer-map/tests/computations.spec.ts index 0f0ead89ef..3079d65150 100644 --- a/packages/nimble-components/src/wafer-map/tests/computations.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/computations.spec.ts @@ -1,5 +1,6 @@ import { Computations } from '../modules/computations'; -import { Margin, WaferMapOriginLocation } from '../types'; +import { WaferMapOriginLocation } from '../types'; +import type { Margin } from '../workers/types'; import { getWaferMapMockComputations, getWaferMapDies } from './utilities'; describe('Wafermap Computations module', () => { @@ -49,12 +50,12 @@ describe('Wafermap Computations module', () => { expect(computationsModule.margin).toEqual(expectedMargin); }); - it('should have horizontal domain containing all column indexes', () => { + it('should have horizontal domain containing all column Indices', () => { expect(computationsModule.horizontalScale.domain()).toEqual([ 2, 3, 4, 5, 6 ]); }); - it('should have vertical domain containing all row indexes, ', () => { + it('should have vertical domain containing all row Indices, ', () => { expect(computationsModule.verticalScale.domain()).toEqual([ 1, 2, 3, 4, 5, 6 ]); diff --git a/packages/nimble-components/src/wafer-map/tests/create-matrix-renderer.spec.ts b/packages/nimble-components/src/wafer-map/tests/create-matrix-renderer.spec.ts index dcf279e3a9..c975886757 100644 --- a/packages/nimble-components/src/wafer-map/tests/create-matrix-renderer.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/create-matrix-renderer.spec.ts @@ -6,8 +6,8 @@ describe('MatrixRenderer worker', () => { let matrixRenderer: Remote; let terminate: () => void; const testData = { - columnIndexes: [4, 1, 2], - rowIndexes: [54, 54, 62], + columnIndices: [4, 1, 2], + rowIndices: [54, 54, 62], values: [8.12, 9.0, 0.32] }; @@ -22,52 +22,44 @@ describe('MatrixRenderer worker', () => { matrixRenderer = undefined!; }); - it('updateMatrix should update the dieMatrix', async () => { - await matrixRenderer.updateMatrix(testData); - const resolvedDieMatrix = await matrixRenderer.getMatrix(); - - expect(resolvedDieMatrix.columnIndexes).toEqual( - Int32Array.from(testData.columnIndexes) - ); - expect(resolvedDieMatrix.rowIndexes).toEqual( - Int32Array.from(testData.rowIndexes) - ); - expect(resolvedDieMatrix.values).toEqual( - Float64Array.from(testData.values) - ); - }); - - it('emptyMatrix should empty the dieMatrix', async () => { - await matrixRenderer.updateMatrix(testData); - await matrixRenderer.emptyMatrix(); - const resolvedDieMatrix = await matrixRenderer.getMatrix(); - expect( - resolvedDieMatrix.columnIndexes.length - + resolvedDieMatrix.rowIndexes.length - + resolvedDieMatrix.values.length - ).toEqual(0); - }); - - it('indexes should be set', async () => { + it('scaled Indices should be computed', async () => { const offscreenCanvas = new OffscreenCanvas(300, 300); + const typedColumnIndices = Int32Array.from(testData.columnIndices); + const typedRowIndices = Int32Array.from(testData.rowIndices); + await matrixRenderer.setCanvas( transfer(offscreenCanvas, [offscreenCanvas]) ); + await matrixRenderer.setCanvasDimensions({ + width: 300, + height: 300 + }); + await matrixRenderer.setRenderConfig({ + dieDimensions: { + width: 0, + height: 0 + }, + margin: { + top: 0, + right: 0, + bottom: 0, + left: 0 + }, + verticalCoefficient: 1, + horizontalCoefficient: 1, + horizontalConstant: 0, + verticalConstant: 0, + labelsFontSize: 0, + colorScale: [] + }); - const typedColumnIndexes = Int32Array.from(testData.columnIndexes); - const typedRowIndexes = Int32Array.from(testData.rowIndexes); - - await matrixRenderer.setColumnIndexes( - transfer(typedColumnIndexes, [typedColumnIndexes.buffer]) - ); - await matrixRenderer.setRowIndexes( - transfer(typedRowIndexes, [typedRowIndexes.buffer]) - ); + await matrixRenderer.setColumnIndices(typedColumnIndices); + await matrixRenderer.setRowIndices(typedRowIndices); - const columnIndexes = await matrixRenderer.columnIndexes; - const rowIndexes = await matrixRenderer.rowIndexes; + const scaledColumnIndex = await matrixRenderer.scaledColumnIndices; + const scaledRowIndex = await matrixRenderer.scaledRowIndices; - expect(columnIndexes).toEqual(Int32Array.from([4, 1, 2])); - expect(rowIndexes).toEqual(Int32Array.from([54, 54, 62])); + expect(scaledColumnIndex).toEqual(Float64Array.from([4, 1, 2])); + expect(scaledRowIndex).toEqual(Float64Array.from([54, 54, 62])); }); }); diff --git a/packages/nimble-components/src/wafer-map/tests/data-manager.spec.ts b/packages/nimble-components/src/wafer-map/tests/data-manager.spec.ts index 454c0f4a79..e0f43cc4cc 100644 --- a/packages/nimble-components/src/wafer-map/tests/data-manager.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/data-manager.spec.ts @@ -4,17 +4,13 @@ import { fixture, Fixture } from '../../utilities/tests/fixture'; import { processUpdates } from '../../testing/async-helpers'; import type { DataManager } from '../modules/data-manager'; import type { WaferMap } from '..'; -import { - Dimensions, - Margin, - WaferMapColorScaleMode, - WaferMapOriginLocation -} from '../types'; +import { WaferMapColorScaleMode, WaferMapOriginLocation } from '../types'; import { getColorScale, getHighlightedTags, getWaferMapDies } from './utilities'; +import type { Dimensions, Margin } from '../workers/types'; async function setup(): Promise> { return fixture(html``); diff --git a/packages/nimble-components/src/wafer-map/tests/experimantal-prerendering.spec.ts b/packages/nimble-components/src/wafer-map/tests/experimantal-prerendering.spec.ts deleted file mode 100644 index 0af5c5f342..0000000000 --- a/packages/nimble-components/src/wafer-map/tests/experimantal-prerendering.spec.ts +++ /dev/null @@ -1,278 +0,0 @@ -import { Prerendering } from '../modules/experimental/prerendering'; -import { WaferMapColorScaleMode } from '../types'; -import { - getExperimentalDataManagerMock, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale, - getWaferMapDies, - getExperimentalWaferMapMockPrerendering -} from './utilities'; - -describe('Wafermap Experimental Prerendering module', () => { - let prerenderingModule: Prerendering; - - it('with die input and small die height should not have labelsFontSize larger than the die height', () => { - const dieDimensions = { width: 10, height: 1 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = false; - const maxCharacters = 2; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { colors: [], values: [] }, - highlightedTags, - WaferMapColorScaleMode.linear, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - - expect(prerenderingModule.labelsFontSize).toBeLessThanOrEqual( - dieDimensions.height - ); - }); - - it('with small width and one character at maximum should not have labelsFontSize larger than the die width', () => { - const dieDimensions = { width: 1, height: 10 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = false; - const maxCharacters = 1; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { colors: [], values: [] }, - highlightedTags, - WaferMapColorScaleMode.linear, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - - expect(prerenderingModule.labelsFontSize).toBeLessThan( - dieDimensions.width - ); - }); - - describe('with linear color scale', () => { - const colorScaleMode = WaferMapColorScaleMode.linear; - - it('and only one color value pair should have undefined color category', () => { - const dieDimensions = { width: 10, height: 10 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = true; - const maxCharacters = 2; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { colors: ['red'], values: ['1'] }, - highlightedTags, - colorScaleMode, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - const expectedValues = Array(1).fill(undefined); - - const actualValues = prerenderingModule.colorScale.map( - colorCategory => colorCategory.color - ); - - expect(actualValues).toEqual( - jasmine.arrayWithExactContents(expectedValues) - ); - }); - - it('and only one duplicated color value pair should have a single color category', () => { - const dieDimensions = { width: 10, height: 10 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = true; - const maxCharacters = 2; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { - colors: ['red', 'red'], - values: ['1', '1'] - }, - highlightedTags, - colorScaleMode, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - - const expectedValues = Array(1).fill('rgb(255, 0, 0)'); - const actualValues = prerenderingModule.colorScale.map( - colorCategory => colorCategory.color - ); - expect(actualValues).toEqual( - jasmine.arrayWithExactContents(expectedValues) - ); - }); - - it('and color value pairs for the scale ends should have the colors equally distributed', () => { - const dieDimensions = { width: 10, height: 10 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = true; - const maxCharacters = 2; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { - colors: ['black', 'red'], - values: ['1', '18'] - }, - highlightedTags, - colorScaleMode, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - const waferMapDies = getWaferMapDies(); - const expectedValues = waferMapDies - .sort((a, b) => +a.value - +b.value) - .map(waferMapDie => { - return `rgb(${(+waferMapDie.value - 1) * 15}, 0, 0)`; - }); - const actualValues = prerenderingModule.colorScale.map( - colorCategory => colorCategory.color - ); - expect(actualValues).toEqual( - jasmine.arrayWithExactContents(expectedValues) - ); - }); - }); - - describe('with ordinal color scale', () => { - const colorScaleMode = WaferMapColorScaleMode.ordinal; - - it('and only one color value pair should have a single color category', () => { - const dieDimensions = { width: 10, height: 10 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = true; - const maxCharacters = 2; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { colors: ['red'], values: ['1'] }, - highlightedTags, - colorScaleMode, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - const expectedValues = Array(1).fill('red'); - const actualValues = prerenderingModule.colorScale.map( - colorCategory => colorCategory.color - ); - expect(actualValues).toEqual( - jasmine.arrayWithExactContents(expectedValues) - ); - }); - - it('and two colors should have two color categories', () => { - const dieDimensions = { width: 10, height: 10 }; - const dieLabelsSuffix = ''; - const dieLabelsHidden = true; - const maxCharacters = 2; - const highlightedTags: string[] = []; - const margin = { top: 0, right: 0, bottom: 0, left: 0 }; - - const dataManagerMock = getExperimentalDataManagerMock( - dieDimensions, - margin, - defaultExperimentalHorizontalScale, - defaultExperimentalVerticalScale - ); - const waferMock = getExperimentalWaferMapMockPrerendering( - getWaferMapDies(), - { - colors: ['black', 'red'], - values: [] - }, - highlightedTags, - colorScaleMode, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - dataManagerMock - ); - prerenderingModule = new Prerendering(waferMock); - prerenderingModule.update(); - - const expectedValues = ['black', 'red']; - const actualValues = prerenderingModule.colorScale.map( - colorCategory => colorCategory.color - ); - expect(actualValues).toEqual( - jasmine.arrayWithExactContents(expectedValues) - ); - }); - }); -}); diff --git a/packages/nimble-components/src/wafer-map/tests/experimental-computations.spec.ts b/packages/nimble-components/src/wafer-map/tests/experimental-computations.spec.ts index 481dfe4587..ef312014fe 100644 --- a/packages/nimble-components/src/wafer-map/tests/experimental-computations.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/experimental-computations.spec.ts @@ -1,13 +1,16 @@ import { parameterizeSpec } from '@ni/jasmine-parameterized'; -import { Computations } from '../modules/experimental/computations'; -import { Margin, WaferMapOriginLocation } from '../types'; +import { Computations } from '../experimental/computations'; +import { WaferMapColorScaleMode, WaferMapOriginLocation } from '../types'; import { getWaferMapMockComputationsExperimental, - getWaferMapDiesTable + getWaferMapDies } from './utilities'; +import type { WaferMap } from '..'; +import type { Margin } from '../workers/types'; describe('Wafermap Experimental Computations module', () => { let computationsModule: Computations; + let waferMock: WaferMap; describe('with 100 square canvas', () => { const expectedMargin: Margin = { @@ -17,14 +20,11 @@ describe('Wafermap Experimental Computations module', () => { left: 4 }; beforeEach(() => { - const waferMock = getWaferMapMockComputationsExperimental( - getWaferMapDiesTable(), - WaferMapOriginLocation.topLeft, - 100, - 100 - ); + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.canvasWidth = 100; + waferMock.canvasHeight = 100; computationsModule = new Computations(waferMock); - computationsModule.update(); + computationsModule.componentResizeUpdate(); }); it('should have expected square container', () => { @@ -49,24 +49,21 @@ describe('Wafermap Experimental Computations module', () => { expect(computationsModule.margin).toEqual(expectedMargin); }); - it('should have horizontal domain containing min and max column indexes', () => { + it('should have horizontal domain containing min and max column Indices', () => { expect(computationsModule.horizontalScale.domain()).toEqual([2, 7]); }); - it('should have vertical domain containing min and max row indexes, ', () => { + it('should have vertical domain containing min and max row Indices, ', () => { expect(computationsModule.verticalScale.domain()).toEqual([1, 7]); }); }); describe('with rectangular canvas', () => { beforeEach(() => { - const waferMock = getWaferMapMockComputationsExperimental( - getWaferMapDiesTable(), - WaferMapOriginLocation.topLeft, - 200, - 100 - ); + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.canvasWidth = 200; + waferMock.canvasHeight = 100; computationsModule = new Computations(waferMock); - computationsModule.update(); + computationsModule.componentResizeUpdate(); }); it('should have adjusted square container', () => { @@ -124,14 +121,12 @@ describe('Wafermap Experimental Computations module', () => { spec( `with ${name} originLocation should have expected horizontal range and vertical range`, () => { - const waferMock = getWaferMapMockComputationsExperimental( - getWaferMapDiesTable(), - value.name, - 100, - 100 - ); + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.originLocation = value.name; + waferMock.canvasWidth = 100; + waferMock.canvasHeight = 100; computationsModule = new Computations(waferMock); - computationsModule.update(); + computationsModule.componentResizeUpdate(); expect(computationsModule.horizontalScale.range()).toEqual( value.horizontalRange ); @@ -141,4 +136,136 @@ describe('Wafermap Experimental Computations module', () => { } ); }); + + it('with die input and small die height should not have labelsFontSize larger than the die height', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.canvasWidth = 50; + waferMock.canvasHeight = 41; + waferMock.maxCharacters = 2; + computationsModule = new Computations(waferMock); + computationsModule.componentResizeUpdate(); + + expect(computationsModule.labelsFontSize).toBeLessThanOrEqual( + computationsModule.dieDimensions.height + ); + }); + + it('with small width and one character at maximum should not have labelsFontSize larger than the die width', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.maxCharacters = 1; + waferMock.canvasWidth = 41; + waferMock.canvasHeight = 50; + computationsModule = new Computations(waferMock); + computationsModule.componentResizeUpdate(); + + expect(computationsModule.labelsFontSize).toBeLessThan( + computationsModule.dieDimensions.width + ); + }); + + describe('with linear color scale', () => { + const colorScaleMode = WaferMapColorScaleMode.linear; + + it('and only one color value pair should have undefined color category', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.colorScale = { colors: ['red'], values: ['1'] }; + waferMock.colorScaleMode = colorScaleMode; + waferMock.maxCharacters = 2; + computationsModule = new Computations(waferMock); + computationsModule.colorAndTextUpdate(); + const expectedValues = Array(1).fill(undefined); + + const actualValues = computationsModule.colorScale.map( + colorCategory => colorCategory.color + ); + + expect(actualValues).toEqual( + jasmine.arrayWithExactContents(expectedValues) + ); + }); + + it('and only one duplicated color value pair should have a single color category', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.colorScale = { + colors: ['red', 'red'], + values: ['1', '1'] + }; + waferMock.colorScaleMode = colorScaleMode; + waferMock.maxCharacters = 2; + computationsModule = new Computations(waferMock); + computationsModule.colorAndTextUpdate(); + + const expectedValues = Array(1).fill('rgb(255, 0, 0)'); + const actualValues = computationsModule.colorScale.map( + colorCategory => colorCategory.color + ); + expect(actualValues).toEqual( + jasmine.arrayWithExactContents(expectedValues) + ); + }); + + it('and color value pairs for the scale ends should have the colors equally distributed', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.colorScale = { + colors: ['black', 'red'], + values: ['1', '18'] + }; + waferMock.colorScaleMode = colorScaleMode; + waferMock.maxCharacters = 2; + computationsModule = new Computations(waferMock); + computationsModule.colorAndTextUpdate(); + const waferMapDies = getWaferMapDies(); + const expectedValues = waferMapDies + .sort((a, b) => +a.value - +b.value) + .map(waferMapDie => { + return `rgb(${(+waferMapDie.value - 1) * 15}, 0, 0)`; + }); + const actualValues = computationsModule.colorScale.map( + colorCategory => colorCategory.color + ); + expect(actualValues).toEqual( + jasmine.arrayWithExactContents(expectedValues) + ); + }); + }); + + describe('with ordinal color scale', () => { + const colorScaleMode = WaferMapColorScaleMode.ordinal; + + it('and only one color value pair should have a single color category', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.colorScale = { colors: ['red'], values: ['1'] }; + waferMock.colorScaleMode = colorScaleMode; + waferMock.maxCharacters = 2; + computationsModule = new Computations(waferMock); + computationsModule.colorAndTextUpdate(); + const expectedValues = Array(1).fill('red'); + const actualValues = computationsModule.colorScale.map( + colorCategory => colorCategory.color + ); + expect(actualValues).toEqual( + jasmine.arrayWithExactContents(expectedValues) + ); + }); + + it('and two colors should have two color categories', () => { + waferMock = getWaferMapMockComputationsExperimental(); + waferMock.colorScale = { + colors: ['black', 'red'], + values: [] + }; + waferMock.colorScaleMode = colorScaleMode; + waferMock.maxCharacters = 2; + computationsModule = new Computations(waferMock); + computationsModule.colorAndTextUpdate(); + + const expectedValues = ['black', 'red']; + const actualValues = computationsModule.colorScale.map( + colorCategory => colorCategory.color + ); + expect(actualValues).toEqual( + jasmine.arrayWithExactContents(expectedValues) + ); + }); + }); }); diff --git a/packages/nimble-components/src/wafer-map/tests/experimental-data-manager.spec.ts b/packages/nimble-components/src/wafer-map/tests/experimental-data-manager.spec.ts deleted file mode 100644 index b6028def25..0000000000 --- a/packages/nimble-components/src/wafer-map/tests/experimental-data-manager.spec.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { html } from '@microsoft/fast-element'; - -import { fixture, Fixture } from '../../utilities/tests/fixture'; -import { processUpdates } from '../../testing/async-helpers'; -import type { DataManager } from '../modules/experimental/data-manager'; -import type { WaferMap } from '..'; -import { - Margin, - WaferMapColorScaleMode, - WaferMapOriginLocation -} from '../types'; -import { getColorScale, getWaferMapDiesTable } from './utilities'; - -async function setup(): Promise> { - return fixture(html``); -} - -describe('Wafermap Experimental Data Manager', () => { - let dataManagerModule: DataManager; - const dieLabelsSuffix = '%'; - const canvasWidth = 200; - const canvasHeight = 100; - const expectedMargin: Margin = { - top: 4, - right: 54, - bottom: 4, - left: 54 - }; - - let element: WaferMap; - let connect: () => Promise; - let disconnect: () => Promise; - - beforeEach(async () => { - ({ element, connect, disconnect } = await setup()); - await connect(); - element.diesTable = getWaferMapDiesTable(); - element.colorScale = getColorScale(); - element.originLocation = WaferMapOriginLocation.bottomLeft; - element.dieLabelsSuffix = dieLabelsSuffix; - element.dieLabelsHidden = false; - element.maxCharacters = 3; - element.colorScaleMode = WaferMapColorScaleMode.ordinal; - element.canvasWidth = canvasWidth; - element.canvasHeight = canvasHeight; - - processUpdates(); - - dataManagerModule = element.experimentalDataManager; - }); - - afterEach(async () => { - await disconnect(); - }); - - it('computes the correct containerDimensions', () => { - expect(dataManagerModule.containerDimensions).toEqual({ - width: 92, - height: 92 - }); - }); - - it('computes the correct dieDimensions', () => { - const computedDimensions = { - width: Math.ceil(dataManagerModule.dieDimensions.width), - height: Math.ceil(dataManagerModule.dieDimensions.height) - }; - expect(computedDimensions).toEqual({ - width: 19, - height: 16 - }); - }); - - it('should have expected margin', () => { - expect(dataManagerModule.margin).toEqual(expectedMargin); - }); - - it('should have increasing horizontal range', () => { - expect(dataManagerModule.horizontalScale.range()).toEqual([0, 92]); - }); - - it('should have decreasing vertical range', () => { - // because the canvas has top-left origin location we need to flip the vertical scale - expect(dataManagerModule.verticalScale.range()).toEqual([92, 0]); - }); - - it('should not have labelsFontSize larger than the die height', () => { - expect(dataManagerModule.labelsFontSize).toBeLessThanOrEqual( - dataManagerModule.dieDimensions.height - ); - }); - - it('should not have labelsFontSize larger than the die width', () => { - expect(dataManagerModule.labelsFontSize).toBeLessThanOrEqual( - dataManagerModule.dieDimensions.width - ); - }); - - it('should have the same color categories', () => { - const expectedValues = getColorScale().colors; - const actualValues = dataManagerModule.colorScale.map( - colorCategory => colorCategory.color - ); - expect(actualValues).toEqual( - jasmine.arrayWithExactContents(expectedValues) - ); - }); -}); diff --git a/packages/nimble-components/src/wafer-map/tests/utilities.ts b/packages/nimble-components/src/wafer-map/tests/utilities.ts index 5db3f3ebd0..dd5db36dc0 100644 --- a/packages/nimble-components/src/wafer-map/tests/utilities.ts +++ b/packages/nimble-components/src/wafer-map/tests/utilities.ts @@ -9,9 +9,7 @@ import { import { type Table, tableFromArrays } from 'apache-arrow'; import type { ZoomTransform } from 'd3-zoom'; import { - Dimensions, HoverDie, - Margin, WaferMapColorScale, WaferMapColorScaleMode, WaferMapDie, @@ -20,8 +18,8 @@ import { WaferRequiredFields } from '../types'; import type { DataManager } from '../modules/data-manager'; -import type { DataManager as ExperimentalDataManager } from '../modules/experimental/data-manager'; import type { WaferMap } from '..'; +import type { Dimensions, Margin } from '../workers/types'; export function getWaferMapDies(): WaferMapDie[] { return [ @@ -134,23 +132,6 @@ export function getDataManagerMock( }; return dataManagerMock as DataManager; } -export function getExperimentalDataManagerMock( - dieDimensions: Dimensions, - margin: Margin, - horizontalScale: ScaleLinear = getScaleLinear([], []), - verticalScale: ScaleLinear = getScaleLinear([], []) -): ExperimentalDataManager { - const dataManagerMock: Pick< - ExperimentalDataManager, - 'horizontalScale' | 'verticalScale' | 'dieDimensions' | 'margin' - > = { - horizontalScale, - verticalScale, - dieDimensions, - margin - }; - return dataManagerMock as ExperimentalDataManager; -} export function getDataManagerMockForHover( margin: Margin, @@ -174,38 +155,6 @@ export function getDataManagerMockForHover( return dataManagerMock as DataManager; } -export function getExperimentalWaferMapMockPrerendering( - dies: WaferMapDie[] = getWaferMapDies(), - colorScale: WaferMapColorScale = { colors: [], values: [] }, - highlightedTags: string[] = [], - colorScaleMode: WaferMapColorScaleMode = WaferMapColorScaleMode.linear, - dieLabelsHidden = true, - dieLabelsSuffix = '', - maxCharacters = 4, - experimentalDataManager = {} as ExperimentalDataManager -): WaferMap { - const waferMapMock: Pick< - WaferMap, - | 'dies' - | 'colorScale' - | 'highlightedTags' - | 'colorScaleMode' - | 'dieLabelsHidden' - | 'dieLabelsSuffix' - | 'maxCharacters' - | 'experimentalDataManager' - > = { - dies, - colorScale, - highlightedTags, - colorScaleMode, - dieLabelsHidden, - dieLabelsSuffix, - maxCharacters, - experimentalDataManager - }; - return waferMapMock as WaferMap; -} export function getWaferMapMockPrerendering( dies: WaferMapDie[] = getWaferMapDies(), colorScale: WaferMapColorScale = { colors: [], values: [] }, @@ -288,29 +237,31 @@ export function getWaferMapMockComputations( return waferMapMock as WaferMap; } export function getWaferMapMockComputationsExperimental( - diesTable: Table = getWaferMapDiesTable(), - originLocation: WaferMapOriginLocation, - canvasWidth: number, - canvasHeight: number, - validity: WaferMapValidity = { - invalidGridDimensions: false, - invalidDiesTableSchema: false + props = { + diesTable: getWaferMapDiesTable(), + originLocation: WaferMapOriginLocation.topLeft, + colorScale: { colors: [], values: [] }, + colorScaleMode: WaferMapColorScaleMode.linear, + maxCharacters: 4, + canvasWidth: 0, + canvasHeight: 0, + validity: { + invalidGridDimensions: false, + invalidDiesTableSchema: false + } } ): WaferMap { const waferMapMock: Pick< WaferMap, | 'diesTable' + | 'colorScale' + | 'colorScaleMode' + | 'maxCharacters' | 'originLocation' | 'canvasWidth' | 'canvasHeight' | 'validity' - > = { - diesTable, - originLocation, - canvasWidth, - canvasHeight, - validity - }; + > = props; return waferMapMock as WaferMap; } diff --git a/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts b/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts index 3ad4893e96..a3d242bcc4 100644 --- a/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts @@ -329,10 +329,9 @@ describe('WaferMap', () => { await waitForUpdatesAsync(); }); - // Disabled due to intermittency: https://github.com/ni/nimble/issues/2104 - xit('will have hover rectangle with no dimensions', () => { - expect(element.hoverHeight).toEqual(0); - expect(element.hoverWidth).toEqual(0); + it('will have hover rectangle with numeric dimensions', () => { + expect(element.hoverHeight).not.toBeNaN(); + expect(element.hoverWidth).not.toBeNaN(); }); }); }); diff --git a/packages/nimble-components/src/wafer-map/types.ts b/packages/nimble-components/src/wafer-map/types.ts index bd9a4ac975..76c8031150 100644 --- a/packages/nimble-components/src/wafer-map/types.ts +++ b/packages/nimble-components/src/wafer-map/types.ts @@ -56,18 +56,6 @@ export interface WaferMapColorScale { values: string[]; } -export interface Dimensions { - readonly width: number; - readonly height: number; -} - -export interface Margin { - readonly top: number; - readonly right: number; - readonly bottom: number; - readonly left: number; -} - export interface DieRenderInfo { readonly x: number; readonly y: number; @@ -100,10 +88,3 @@ export type WaferRequiredFields = { rowIndex: Int32, value: Float64 }; - -interface IColorScaleMarker { - color: string; - value: number; -} - -export type ColorScale = IColorScaleMarker[];