-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created Computations and Data Manager Experimental (#1946)
# Pull Request ## 🤨 Rationale Created new computations experimental component with changed scales and diesTable iteration for finding the bounding box until arquero fixes. The new scales will be able to be inverted without the need to create separate scales for the hover handler. ## 👩💻 Implementation changed the scales and iteration over the diesTable integrated the changes and the strategy swap with the wafermap and the experimental hover ## 🧪 Testing copied spec classes for the new experimental modules. updated hover handler spec. adapted the data manager to the previous renderer for visual tests in storybook. ## ✅ Checklist <!--- Review the list and put an x in the boxes that apply or ~~strike through~~ around items that don't (along with an explanation). --> - [x] I have updated the project documentation to reflect my changes or determined no changes are needed.
- Loading branch information
1 parent
e7f9887
commit c6d99d8
Showing
14 changed files
with
796 additions
and
99 deletions.
There are no files selected for viewing
7 changes: 7 additions & 0 deletions
7
change/@ni-nimble-components-a395f7f8-e46b-414d-ac9c-800e43462953.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "patch", | ||
"comment": "Created new computations experimental module and tested it, created new data manager experimental and integrated with hover and old renderer", | ||
"packageName": "@ni/nimble-components", | ||
"email": "[email protected]", | ||
"dependentChangeType": "patch" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
231 changes: 231 additions & 0 deletions
231
packages/nimble-components/src/wafer-map/modules/experimental/computations.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,231 @@ | ||
import { scaleLinear, ScaleLinear } from 'd3-scale'; | ||
import type { WaferMap } from '../..'; | ||
import { Dimensions, Margin, WaferMapOriginLocation } from '../../types'; | ||
|
||
interface GridDimensions { | ||
origin: { | ||
x: number, | ||
y: number | ||
}; | ||
rows: number; | ||
cols: number; | ||
} | ||
|
||
/** | ||
* Computations calculates and stores different measures which are used in the Wafermap | ||
*/ | ||
export class Computations { | ||
public get containerDimensions(): Dimensions { | ||
return this._containerDimensions; | ||
} | ||
|
||
public get dieDimensions(): Dimensions { | ||
return this._dieDimensions; | ||
} | ||
|
||
public get margin(): Margin { | ||
return this._margin; | ||
} | ||
|
||
public get horizontalScale(): ScaleLinear<number, number> { | ||
return this._horizontalScale; | ||
} | ||
|
||
public get verticalScale(): ScaleLinear<number, number> { | ||
return this._verticalScale; | ||
} | ||
|
||
private _containerDimensions!: Dimensions; | ||
private _dieDimensions!: Dimensions; | ||
private _margin!: Margin; | ||
private _horizontalScale!: ScaleLinear<number, number>; | ||
private _verticalScale!: ScaleLinear<number, number>; | ||
private readonly defaultPadding = 0; | ||
private readonly baseMarginPercentage = 0.04; | ||
|
||
public constructor(private readonly wafermap: WaferMap) {} | ||
|
||
public updateContainerDimensions(): void { | ||
const canvasDimensions = { | ||
width: this.wafermap.canvasWidth, | ||
height: this.wafermap.canvasHeight | ||
}; | ||
const canvasDiameter = Math.min( | ||
canvasDimensions.width, | ||
canvasDimensions.height | ||
); | ||
const canvasMargin = { | ||
top: (canvasDimensions.height - canvasDiameter) / 2, | ||
right: (canvasDimensions.width - canvasDiameter) / 2, | ||
bottom: (canvasDimensions.height - canvasDiameter) / 2, | ||
left: (canvasDimensions.width - canvasDiameter) / 2 | ||
}; | ||
const baseMargin = { | ||
top: canvasDiameter * this.baseMarginPercentage, | ||
right: canvasDiameter * this.baseMarginPercentage, | ||
bottom: canvasDiameter * this.baseMarginPercentage, | ||
left: canvasDiameter * this.baseMarginPercentage | ||
}; | ||
this._margin = this.calculateMarginAddition(baseMargin, canvasMargin); | ||
this._containerDimensions = this.calculateContainerDimensions( | ||
canvasDimensions, | ||
this._margin | ||
); | ||
this.updateScales(); | ||
} | ||
|
||
public updateScales(): void { | ||
const containerDiameter = Math.min( | ||
this._containerDimensions.width, | ||
this._containerDimensions.height | ||
); | ||
const gridDimensions = this.gridDimensionsValidAndDefined() | ||
? this.calculateGridDimensionsFromBoundingBox() | ||
: this.calculateGridDimensionsFromDies(); | ||
// this scale is used for positioning the dies on the canvas | ||
const originLocation = this.wafermap.originLocation; | ||
this._horizontalScale = this.createHorizontalScale( | ||
originLocation, | ||
gridDimensions, | ||
containerDiameter | ||
); | ||
// this scale is used for positioning the dies on the canvas | ||
this._verticalScale = this.createVerticalScale( | ||
originLocation, | ||
gridDimensions, | ||
containerDiameter | ||
); | ||
this._dieDimensions = { | ||
width: Math.abs( | ||
this._horizontalScale(0) - this._horizontalScale(1) | ||
), | ||
height: Math.abs(this._verticalScale(0) - this._verticalScale(1)) | ||
}; | ||
} | ||
|
||
private gridDimensionsValidAndDefined(): boolean { | ||
return ( | ||
!this.wafermap.validity.invalidGridDimensions | ||
&& typeof this.wafermap.gridMinX === 'number' | ||
&& typeof this.wafermap.gridMinY === 'number' | ||
&& typeof this.wafermap.gridMaxX === 'number' | ||
&& typeof this.wafermap.gridMinX === 'number' | ||
); | ||
} | ||
|
||
private calculateGridDimensionsFromBoundingBox(): GridDimensions { | ||
const gridDimensions = { origin: { x: 0, y: 0 }, rows: 0, cols: 0 }; | ||
if ( | ||
typeof this.wafermap.gridMaxY === 'number' | ||
&& typeof this.wafermap.gridMinY === 'number' | ||
&& typeof this.wafermap.gridMaxX === 'number' | ||
&& typeof this.wafermap.gridMinX === 'number' | ||
) { | ||
gridDimensions.origin.x = this.wafermap.gridMinX; | ||
gridDimensions.origin.y = this.wafermap.gridMinY; | ||
gridDimensions.rows = this.wafermap.gridMaxY - this.wafermap.gridMinY + 1; | ||
gridDimensions.cols = this.wafermap.gridMaxX - this.wafermap.gridMinX + 1; | ||
} | ||
return gridDimensions; | ||
} | ||
|
||
private calculateGridDimensionsFromDies(): GridDimensions { | ||
if (this.wafermap.diesTable === undefined) { | ||
return { origin: { x: 0, y: 0 }, rows: 0, cols: 0 }; | ||
} | ||
|
||
const colIndex = this.wafermap.diesTable | ||
.getChild('colIndex')! | ||
.toArray(); | ||
const rowIndex = this.wafermap.diesTable | ||
.getChild('rowIndex')! | ||
.toArray(); | ||
|
||
const minPoint = { x: colIndex[0]!, y: rowIndex[0]! }; | ||
const maxPoint = { x: colIndex[0]!, y: rowIndex[0]! }; | ||
|
||
// will replace iterating with arquero after fixing issues: https://github.com/uwdata/arquero/pull/346 | ||
for (let i = 0; i < colIndex.length; i++) { | ||
if (colIndex[i]! < minPoint.x) { | ||
minPoint.x = colIndex[i]!; | ||
} | ||
if (colIndex[i]! > maxPoint.x) { | ||
maxPoint.x = colIndex[i]!; | ||
} | ||
if (rowIndex[i]! < minPoint.y) { | ||
minPoint.y = rowIndex[i]!; | ||
} | ||
if (rowIndex[i]! > maxPoint.y) { | ||
maxPoint.y = rowIndex[i]!; | ||
} | ||
} | ||
|
||
return { | ||
origin: minPoint, | ||
rows: maxPoint.y - minPoint.y + 1, | ||
cols: maxPoint.x - minPoint.x + 1 | ||
}; | ||
} | ||
|
||
private calculateContainerDimensions( | ||
canvasDimensions: Dimensions, | ||
margin: Margin | ||
): Dimensions { | ||
return { | ||
width: canvasDimensions.width - margin.left - margin.right, | ||
height: canvasDimensions.height - margin.top - margin.bottom | ||
}; | ||
} | ||
|
||
private createHorizontalScale( | ||
originLocation: WaferMapOriginLocation, | ||
grid: GridDimensions, | ||
containerWidth: number | ||
): ScaleLinear<number, number> { | ||
const scale = scaleLinear<number, number>(); | ||
if ( | ||
originLocation === WaferMapOriginLocation.bottomLeft | ||
|| originLocation === WaferMapOriginLocation.topLeft | ||
) { | ||
return scale | ||
.domain([grid.origin.x, grid.origin.x + grid.cols]) | ||
.range([0, containerWidth]); | ||
} | ||
return scale | ||
.domain([grid.origin.x - 1, grid.origin.x + grid.cols - 1]) | ||
.range([containerWidth, 0]); | ||
} | ||
|
||
private createVerticalScale( | ||
originLocation: WaferMapOriginLocation, | ||
grid: GridDimensions, | ||
containerHeight: number | ||
): ScaleLinear<number, number> { | ||
const scale = scaleLinear<number, number>(); | ||
// html canvas has top-left origin https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes#the_grid | ||
// we need to flip the vertical scale | ||
if ( | ||
originLocation === WaferMapOriginLocation.bottomLeft | ||
|| originLocation === WaferMapOriginLocation.bottomRight | ||
) { | ||
return scale | ||
.domain([grid.origin.y - 1, grid.origin.y + grid.rows - 1]) | ||
.range([containerHeight, 0]); | ||
} | ||
return scale | ||
.domain([grid.origin.y, grid.origin.y + grid.rows]) | ||
.range([0, containerHeight]); | ||
} | ||
|
||
private calculateMarginAddition( | ||
baseMargin: Margin, | ||
addedMargin: Margin | ||
): Margin { | ||
return { | ||
top: baseMargin.top + addedMargin.top, | ||
right: baseMargin.right + addedMargin.right, | ||
bottom: baseMargin.bottom + addedMargin.bottom, | ||
left: baseMargin.left + addedMargin.left | ||
}; | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
packages/nimble-components/src/wafer-map/modules/experimental/data-manager.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import type { ScaleLinear } from 'd3-scale'; | ||
import { Computations } from './computations'; | ||
import { Prerendering } from '../prerendering'; | ||
import type { WaferMap } from '../..'; | ||
import type { | ||
Dimensions, | ||
Margin, | ||
DieRenderInfo, | ||
WaferMapDie, | ||
PointCoordinates | ||
} 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<number, number> { | ||
return this.computations.horizontalScale; | ||
} | ||
|
||
public get verticalScale(): ScaleLinear<number, number> { | ||
return this.computations.verticalScale; | ||
} | ||
|
||
public get labelsFontSize(): number { | ||
return this.prerendering.labelsFontSize; | ||
} | ||
|
||
public get diesRenderInfo(): DieRenderInfo[] { | ||
return this.prerendering.diesRenderInfo; | ||
} | ||
|
||
public get data(): Map<string, WaferMapDie> { | ||
return this.dataMap; | ||
} | ||
|
||
private readonly computations: Computations; | ||
private readonly prerendering: Prerendering; | ||
private dataMap!: Map<string, WaferMapDie>; | ||
|
||
public constructor(private readonly wafermap: WaferMap) { | ||
this.computations = new Computations(wafermap); | ||
this.prerendering = new Prerendering(wafermap); | ||
} | ||
|
||
public updateContainerDimensions(): void { | ||
this.computations.updateContainerDimensions(); | ||
this.updateDataMap(); | ||
this.updateLabelsFontSize(); | ||
} | ||
|
||
public updateScales(): void { | ||
this.computations.updateScales(); | ||
this.updateDataMap(); | ||
this.updateLabelsFontSize(); | ||
} | ||
|
||
public updateLabelsFontSize(): void { | ||
this.prerendering.updateLabelsFontSize(); | ||
} | ||
|
||
public updateDiesRenderInfo(): void { | ||
this.prerendering.updateDiesRenderInfo(); | ||
} | ||
|
||
public getWaferMapDie(point: PointCoordinates): WaferMapDie | undefined { | ||
return this.dataMap.get(`${point.x}_${point.y}`); | ||
} | ||
|
||
private updateDataMap(): void { | ||
this.dataMap = new Map( | ||
this.wafermap.dies.map(die => [`${die.x}_${die.y}`, die]) | ||
); | ||
} | ||
} |
Oops, something went wrong.