From 123fd6c8d82d1510c399d6c6c51fa92d4f0d1060 Mon Sep 17 00:00:00 2001 From: Ossama Rafique Date: Wed, 15 Nov 2023 18:56:12 -0500 Subject: [PATCH] Adapting Hardcoded Data Normalization to Dynamic Ranges in Visualization (#30) * Uptated the plots to make the grouping bars dependent on actual ranges * Bump up lib version * Made xAxisRange Dynamic --- package.json | 2 +- src/BaseGL.js | 26 ++++++++++++++++++-------- src/DotplotGL.js | 9 +++++++-- src/RectplotGL.js | 5 +++++ src/TickplotGL.js | 8 ++++++-- src/constants.js | 1 - 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 9491159..9f0c8a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "epiviz.heatmap.gl", - "version": "0.0.19", + "version": "0.0.20", "repository": "https://github.com/jkanche/epiviz.heatmap.gl", "homepage": "https://github.com/jkanche/epiviz.heatmap.gl", "author": { diff --git a/src/BaseGL.js b/src/BaseGL.js index 73c5a4f..f1cfa48 100644 --- a/src/BaseGL.js +++ b/src/BaseGL.js @@ -17,7 +17,6 @@ import { DEFAULT_ROW_LABEL_FONT_SIZE, DEFAULT_ROW_LABEL_SLINT_ANGLE, DEFAULT_ROW_MAX_LABEL_LENGTH_ALLOWED, - DEFAULT_VISIBLE_RANGE, LABELS_MARGIN_BUFFER_IN_PX, INTENSITY_LEGEND_LABEL_SIZE_IN_PX, INTENSITY_LEGEND_GRADIENT_SIZE_IN_PX, @@ -67,6 +66,10 @@ class BaseGL { ylabels: null, }; + // Plot domain + this.xAxisRange = null; + this.yAxisRange = null; + // state this.state = { size: 20, @@ -893,7 +896,7 @@ class BaseGL { **/ renderRowGroupingLegend() { const position = this.rowGroupingLegendPosition; - const visibleRange = this.viewport?.yRange || DEFAULT_VISIBLE_RANGE; + const visibleRange = this.viewport?.yRange || this.yAxisRange; if ( !this.rowGroupingLegendDomElement || @@ -927,10 +930,13 @@ class BaseGL { const yScale = scaleLinear() .domain(visibleRange) // Input range is currently visible range .range([svgHeight, 0]); // Output range is SVG height + const maxYRange = this.yAxisRange[1] - this.yAxisRange[0]; + const minY = this.yAxisRange[0]; this.groupingRowData.forEach((group, idx) => { - const normalizedStart = (group.startIndex * 2) / totalData - 1; - const normalizedEnd = ((group.endIndex + 1) * 2) / totalData - 1; + const normalizedStart = (group.startIndex / totalData) * maxYRange + minY; + const normalizedEnd = + ((group.endIndex + 1) / totalData) * maxYRange + minY; if ( normalizedEnd >= visibleRange[0] && @@ -973,7 +979,7 @@ class BaseGL { * */ renderColumnGroupingLegend() { const position = this.columnGroupingLegendPosition; // should be 'top' or 'bottom' - const visibleRange = this.viewport?.xRange || DEFAULT_VISIBLE_RANGE; + const visibleRange = this.viewport?.xRange || this.xAxisRange; // Only render the legend if we have the legend data, the dom element, // the position is either 'top' or 'bottom' and visibleRange exists @@ -1013,9 +1019,13 @@ class BaseGL { .domain(visibleRange) // Input range is currently visible range .range([0, svgWidth]); // Output range is SVG width - this.groupingColumnData.forEach((group, idx) => { - const normalizedStart = (group.startIndex * 2) / totalData - 1; - const normalizedEnd = ((group.endIndex + 1) * 2) / totalData - 1; + const maxXRange = this.xAxisRange[1] - this.xAxisRange[0]; + const minX = this.xAxisRange[0]; + + this.groupingRowData.forEach((group, idx) => { + const normalizedStart = (group.startIndex / totalData) * maxXRange + minX; + const normalizedEnd = + ((group.endIndex + 1) / totalData) * maxXRange + minX; if ( normalizedEnd >= visibleRange[0] && diff --git a/src/DotplotGL.js b/src/DotplotGL.js index d810e88..13290cb 100644 --- a/src/DotplotGL.js +++ b/src/DotplotGL.js @@ -99,6 +99,7 @@ class DotplotGL extends BaseGL { const [, maxY] = getMinMax(this.input.y); let xlen = maxX + 1, ylen = maxY + 1; + spec_inputs.x = mapArrayOrTypedArray( this.input.x, (e, i) => -1 + (2 * e + 1) / xlen @@ -108,6 +109,10 @@ class DotplotGL extends BaseGL { (e, i) => -1 + (2 * e + 1) / ylen ); + // Setting X and Y Axis Domains + this.xAxisRange = spec_inputs.x; + this.yAxisRange = spec_inputs.y; + let spec = { margins: this.margins, defaultData: { @@ -122,12 +127,12 @@ class DotplotGL extends BaseGL { x: { attribute: "x", type: "quantitative", - domain: [-1, 1], + domain: this.xAxisRange, }, y: { attribute: "y", type: "quantitative", - domain: [-1, 1], + domain: this.yAxisRange, }, opacity: { value: this.state.opacity }, }, diff --git a/src/RectplotGL.js b/src/RectplotGL.js index 530cd22..3913ca6 100644 --- a/src/RectplotGL.js +++ b/src/RectplotGL.js @@ -53,6 +53,11 @@ class RectplotGL extends BaseGL { }; let spec_inputs = {}; + + // Setting X and Y Axis Domains to [-1, 1] + this.xAxisRange = [-1, 1]; + this.yAxisRange = [-1, 1]; + spec_inputs.x = mapArrayOrTypedArray(this.input.x, (e, i) => String(e)); spec_inputs.y = mapArrayOrTypedArray(this.input.y, (e, i) => String(e)); diff --git a/src/TickplotGL.js b/src/TickplotGL.js index 0692dfe..976bc3d 100644 --- a/src/TickplotGL.js +++ b/src/TickplotGL.js @@ -76,6 +76,10 @@ class TickplotGL extends BaseGL { } } + // Setting X and Y Axis Domains + this.xAxisRange = getMinMax(this.input.x); + this.yAxisRange = getMinMax(this.input.y); + let spec = { margins: this.margins, defaultData: { @@ -90,12 +94,12 @@ class TickplotGL extends BaseGL { x: { attribute: "x", type: "quantitative", - domain: getMinMax(this.input.x), + domain: this.xAxisRange, }, y: { attribute: "y", type: "quantitative", - domain: getMinMax(this.input.y), + domain: this.yAxisRange, }, opacity: { value: this.state.opacity }, width: { value: default_width }, diff --git a/src/constants.js b/src/constants.js index b65fd3a..1750595 100644 --- a/src/constants.js +++ b/src/constants.js @@ -4,7 +4,6 @@ export const DEFAULT_ROW_LABEL_SLINT_ANGLE = 0; export const DEFAULT_COLUMN_LABEL_SLINT_ANGLE = 0; export const DEFAULT_ROW_LABEL_FONT_SIZE = "7px"; export const DEFAULT_COLUMN_LABEL_FONT_SIZE = "7px"; -export const DEFAULT_VISIBLE_RANGE = [-1, 1]; export const LABELS_MARGIN_BUFFER_IN_PX = 20; export const INTENSITY_LEGEND_LABEL_SIZE_IN_PX = 25;