Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added more customization options in heatmap library #25

30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,11 @@ This method allows you to customize the label options for your visualization. Al
- `labelOptions.columnLabelSlintAngle` (`number`, optional): slant angle for column labels (default: 0)
- `labelOptions.rowLabelFontSize` (`string | number`, optional): font size for row labels (default: 7px)
- `labelOptions.columnLabelFontSize` (`string | number`, optional): font size for column labels (default: 7px)

**Example**:
- `labelOptions.rowLabelsSvgXOffset` (`number`, optional): x offset for row labels (default: -1.05)
- `labelOptions.rowLabelsSvgYOffset` (`number`, optional): y offset for row labels (default: -1.02)
- `labelOptions.columnLabelsSvgXOffset` (`number`, optional): x offset for column labels (default: -1.02)
- `labelOptions.columnLabelsSvgYOffset` (`number`, optional): y offset for column labels (default: 1.05)
**Example**:

```javascript
plot.setLabelOptions({
Expand All @@ -134,6 +137,29 @@ plot.setLabelOptions({
});
```

#### Customizing Margins with `setMargins`

This method allows you to customize the margins for your visualization. All parameters are optional, providing you the flexibility to specify the options that best suit your needs.

**Parameters**:

- `margins` (`object`): an object containing the margin options
- `margins.top` (`number`, optional): top margin (default: 25px)
- `margins.bottom` (`number`, optional): bottom margin (default: 50px)
- `margins.left` (`number`, optional): left margin (default: 50px)
- `margins.right` (`number`, optional): right margin (default: 10px)

**Example**:

```javascript
plot.setMargins({
top: 10,
bottom: 10,
left: 10,
right: 10,
});
```

#### Grouping Bars and Labels for Rows and Columns

This feature allows users to add grouping bars and labels to both rows and columns of the heatmap. It provides a convenient way to visually represent different groups in your heatmap data.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "epiviz.heatmap.gl",
"version": "0.0.18",
"version": "0.0.19",
"repository": "https://github.com/jkanche/epiviz.heatmap.gl",
"homepage": "https://github.com/jkanche/epiviz.heatmap.gl",
"author": {
Expand Down
73 changes: 64 additions & 9 deletions src/BaseGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
INTENSITY_LEGEND_GRADIENT_SIZE_IN_PX,
INTENSITY_LEGEND_SIZE_IN_PX,
GROUPING_LEGEND_SIZE_IN_PX,
DEFAULT_MARGINS,
} from "./constants";

/**
Expand Down Expand Up @@ -75,8 +76,14 @@ class BaseGL {
ygap: 0.3,
};

this.margins = DEFAULT_MARGINS;

//Default Data for labelOptions
this.labelOptions = {
rowLabelsSvgXOffset: -1.05,
rowLabelsSvgYOffset: -1.02,
columnLabelsSvgXOffset: -1.02,
columnLabelsSvgYOffset: 1.05,
rowLabelMaxCharacters: DEFAULT_ROW_MAX_LABEL_LENGTH_ALLOWED,
columnLabelMaxCharacters: DEFAULT_COLUMN_MAX_LABEL_LENGTH_ALLOWED,
rowLabelSlintAngle: DEFAULT_ROW_LABEL_SLINT_ANGLE,
Expand Down Expand Up @@ -183,6 +190,10 @@ class BaseGL {

_generateSpecForLabels(spec) {
const {
rowLabelsSvgXOffset,
rowLabelsSvgYOffset,
columnLabelsSvgXOffset,
columnLabelsSvgYOffset,
rowLabelMaxCharacters,
columnLabelMaxCharacters,
rowLabelSlintAngle,
Expand Down Expand Up @@ -212,8 +223,8 @@ class BaseGL {

maxWidth = Math.max(maxWidth, truncatedLabelWidth);
labels.push({
x: -1.02 + (2 * ilx + 1) / xlabels_len,
y: 1.05,
x: columnLabelsSvgXOffset + (2 * ilx + 1) / xlabels_len,
y: columnLabelsSvgYOffset,
type: "row",
index: ilx,
text: truncatedLabel,
Expand Down Expand Up @@ -246,8 +257,8 @@ class BaseGL {
);
maxWidth = Math.max(maxWidth, truncatedLabelWidth);
labels.push({
x: -1.05,
y: -1.02 + (2 * ily + 1) / ylabels_len,
x: rowLabelsSvgXOffset,
y: rowLabelsSvgYOffset + (2 * ily + 1) / ylabels_len,
type: "column",
index: ily,
text: truncatedLabel,
Expand All @@ -269,7 +280,7 @@ class BaseGL {
...spec["margins"],
top: `${topMarginToAccountForLabels}px`,
left: `${leftMarginToAccountForLabels}px`,
right: "20px",
right: `${GROUPING_LEGEND_SIZE_IN_PX}px`,
};
}

Expand Down Expand Up @@ -498,6 +509,10 @@ class BaseGL {
* @memberof BaseGL
* @example
* this.labelOptions = {
* rowLabelsSvgXOffset: 0,
* rowLabelsSvgYOffset: 0,
* columnLabelsSvgXOffset: 0,
* columnLabelsSvgYOffset: 0,
* rowLabelMaxCharacters: 10,
* columnLabelMaxCharacters: 10,
* rowLabelSlintAngle: 0,
Expand All @@ -507,8 +522,12 @@ class BaseGL {
* }
* @example
* this.setLabelOptions({
* rowLabelsSvgXOffset: 0,
* rowLabelsSvgYOffset: 0,
* columnLabelsSvgXOffset: 0,
* columnLabelsSvgYOffset: 0,
* rowLabelMaxCharacters: 10,
* columnLabelMaxCharacters: 10,
* columnLabelMaxCharacters: 10,
* rowLabelSlintAngle: 0,
* columnLabelSlintAngle: 0,
* rowLabelFontSize: "7px",
Expand All @@ -522,6 +541,30 @@ class BaseGL {
};
}

/**
* Set the margins for the visualization.
* all properties are optional, if not provided, the default values will be used.
* @param {object} margins, an object containing the margins
* @param {number} margins.top, top margin
* @param {number} margins.bottom, bottom margin
* @param {number} margins.left, left margin
* @param {number} margins.right, right margin
* @memberof BaseGL
* @example
* this.setMargins({
* top: '10px',
* bottom: '10px',
* left: '10px',
* right: '10px',
* })
**/
setMargins(margins) {
this.margins = {
...this.margins,
...margins,
};
}

/**
* resize the plot, without having to send the data to the GPU.
*
Expand Down Expand Up @@ -1023,22 +1066,34 @@ class BaseGL {
* @param {string} orientation - The orientation of the grouping labels
* @returns {void}
**/
renderGroupingLabels(parentElement, groupingRowData, orientation) {
renderGroupingLabels(parentElement, groupingData, orientation) {
// Filter out duplicate labels in the grouping data
groupingData = groupingData.reduce(
(acc, obj) => {
if (!acc.seen[obj.label]) {
acc.seen[obj.label] = true;
acc.result.push(obj);
}
return acc;
},
{ seen: {}, result: [] }
).result;

const parent = select(parentElement);
const svg = parent.append("svg");

svg.attr("width", "100%").style("overflow", "inherit");
if (orientation === "horizontal") {
svg.attr("height", 25);
} else {
svg.attr("height", groupingRowData.length * 25);
svg.attr("height", groupingData.length * 25);
}

const labelHeight = 25;
let xOffset = 0;
let yOffset = 0;

groupingRowData.forEach((data) => {
groupingData.forEach((data) => {
const group = svg.append("g");

group
Expand Down
18 changes: 10 additions & 8 deletions src/DotplotGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
getMinMax,
getScaledRadiusForDotplot,
parseMargins,
mapArrayOrTypedArray,
} from "./utils";

/**
Expand Down Expand Up @@ -98,16 +99,17 @@ class DotplotGL extends BaseGL {
const [, maxY] = getMinMax(this.input.y);
let xlen = maxX + 1,
ylen = maxY + 1;
spec_inputs.x = this.input.x.map((e, i) => -1 + (2 * e + 1) / xlen);
spec_inputs.y = this.input.y.map((e, i) => -1 + (2 * e + 1) / ylen);
spec_inputs.x = mapArrayOrTypedArray(
this.input.x,
(e, i) => -1 + (2 * e + 1) / xlen
);
spec_inputs.y = mapArrayOrTypedArray(
this.input.y,
(e, i) => -1 + (2 * e + 1) / ylen
);

let spec = {
margins: {
top: "25px",
bottom: "50px",
left: "50px",
right: "10px",
},
margins: this.margins,
defaultData: {
x: spec_inputs.x,
y: spec_inputs.y,
Expand Down
23 changes: 12 additions & 11 deletions src/RectplotGL.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import BaseGL from "./BaseGL";
import { getMinMax } from "./utils";
import { getMinMax, mapArrayOrTypedArray } from "./utils";

/**
* Class to create traditional heatmap plots
Expand Down Expand Up @@ -53,22 +53,23 @@ class RectplotGL extends BaseGL {
};

let spec_inputs = {};
spec_inputs.x = this.input.x.map((e, i) => String(e));
spec_inputs.y = this.input.y.map((e, i) => String(e));
spec_inputs.x = mapArrayOrTypedArray(this.input.x, (e, i) => String(e));
spec_inputs.y = mapArrayOrTypedArray(this.input.y, (e, i) => String(e));

let default_width = 198 / (getMinMax(this.input.x)[1] + 1);
let default_height = 198 / (getMinMax(this.input.y)[1] + 1);

spec_inputs.width = this.input.x.map((e, i) => default_width - xGaps(i));
spec_inputs.height = this.input.y.map((e, i) => default_height - yGaps(i));
spec_inputs.width = mapArrayOrTypedArray(
this.input.x,
(e, i) => default_width - xGaps(i)
);
spec_inputs.height = mapArrayOrTypedArray(
this.input.y,
(e, i) => default_height - yGaps(i)
);

let spec = {
margins: {
top: "25px",
bottom: "50px",
left: "50px",
right: "10px",
},
margins: this.margins,
defaultData: {
x: spec_inputs.x,
y: spec_inputs.y,
Expand Down
7 changes: 1 addition & 6 deletions src/TickplotGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,7 @@ class TickplotGL extends BaseGL {
}

let spec = {
margins: {
top: "25px",
bottom: "50px",
left: "50px",
right: "10px",
},
margins: this.margins,
defaultData: {
x: this.input.x,
y: this.input.y,
Expand Down
7 changes: 7 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,10 @@ export const DEFAULT_SIZE_LEGEND_CIRCLE_TEXT_GAP = 10;

export const DEFAULT_MIN_RADIUS_FOR_DOTPLOT = 3;
export const DEFAULT_MARGIN_BETWEEN_DOTS = 2;

export const DEFAULT_MARGINS = {
top: "25px",
bottom: "50px",
left: "50px",
right: "10px",
};
Loading