From f4b59f9e4e9127aa2af097946e6b7388f6bb7927 Mon Sep 17 00:00:00 2001 From: mxposed Date: Thu, 16 Jan 2025 02:19:07 +0000 Subject: [PATCH] =?UTF-8?q?Deploy=20preview=20for=20PR=2026=20=F0=9F=9B=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pr-preview/pr-26/columns.js.html | 2 +- pr-preview/pr-26/global.html | 2 +- pr-preview/pr-26/main.js.html | 2 +- pr-preview/pr-26/module-columns.html | 2 +- pr-preview/pr-26/scIB.c9996616.js.map | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pr-preview/pr-26/columns.js.html b/pr-preview/pr-26/columns.js.html index 67c4428..dc182f6 100644 --- a/pr-preview/pr-26/columns.js.html +++ b/pr-preview/pr-26/columns.js.html @@ -167,7 +167,7 @@

columns.js

/** * @typedef {Object} ColumnInfo - * @description Information about dataframe column and how to display it. + * @description Information about a dataframe column and how to display it. * @property {string} id - column id in the dataset. Required. */ diff --git a/pr-preview/pr-26/global.html b/pr-preview/pr-26/global.html index 35cad36..e8a06f3 100644 --- a/pr-preview/pr-26/global.html +++ b/pr-preview/pr-26/global.html @@ -787,7 +787,7 @@
Example
{
-  'model: ['Toyota Corolla', 'Fiat 128', 'Honda Civic'],
+  'model': ['Toyota Corolla', 'Fiat 128', 'Honda Civic'],
   'mpg': [33.9, 32.4, 30.4],
   'weight': [1.835, 2.2, 1.615]
 }
diff --git a/pr-preview/pr-26/main.js.html b/pr-preview/pr-26/main.js.html index d889941..3e2315c 100644 --- a/pr-preview/pr-26/main.js.html +++ b/pr-preview/pr-26/main.js.html @@ -177,7 +177,7 @@

main.js

* array. All columns are of the same length. * @example * { - * 'model: ['Toyota Corolla', 'Fiat 128', 'Honda Civic'], + * 'model': ['Toyota Corolla', 'Fiat 128', 'Honda Civic'], * 'mpg': [33.9, 32.4, 30.4], * 'weight': [1.835, 2.2, 1.615] * } diff --git a/pr-preview/pr-26/module-columns.html b/pr-preview/pr-26/module-columns.html index eee5e05..64cb5e8 100644 --- a/pr-preview/pr-26/module-columns.html +++ b/pr-preview/pr-26/module-columns.html @@ -663,7 +663,7 @@

-

Information about dataframe column and how to display it.

+

Information about a dataframe column and how to display it.

diff --git a/pr-preview/pr-26/scIB.c9996616.js.map b/pr-preview/pr-26/scIB.c9996616.js.map index 41887e3..89704c7 100644 --- a/pr-preview/pr-26/scIB.c9996616.js.map +++ b/pr-preview/pr-26/scIB.c9996616.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["d3.js","src/main.js","_.js","src/input_util.js","src/columns.js","src/palettes.js","src/legends.js","src/geoms.js"],"sourcesContent":["module.exports=d3;","import * as d3 from 'd3';\nimport * as _ from 'lodash';\n\nimport { ensureRowData } from './input_util';\nimport { buildColumnInfo, buildColumnGroups, Column } from './columns';\nimport { assignPalettes } from './palettes';\nimport { prepareLegends } from './legends';\nimport { GEOMS } from './geoms';\n\n\n/**\n * @typedef {Object} ColumnData\n * @description A dataframe in column-based format. Each property is a column, represented as an\n * array. All columns are of the same length.\n * @example\n * {\n * 'model: ['Toyota Corolla', 'Fiat 128', 'Honda Civic'],\n * 'mpg': [33.9, 32.4, 30.4],\n * 'weight': [1.835, 2.2, 1.615]\n * }\n */\n\n/**\n * @typedef {Object[]} RowData\n * @description A dataframe in row-based format. Each element is an object with properties. All\n * objects have the same properties.\n * @example\n * [\n * {model: 'Toyota Corolla', mpg: 33.9, weight: 1.835},\n * {model: 'Fiat 128', mpg: 32.4, weight: 2.2},\n * {model: 'Honda Civic', mpg: 30.4, weight: 1.615}\n * ]\n */\n\n/**\n * @typedef {Object} HeatmapOptions\n */\nconst DEFAULT_OPTIONS = {\n legendFontSize: 12,\n legendTicks: [0, 0.2, 0.4, 0.6, 0.8, 1],\n labelGroupsAbc: false,\n colorByRank: false,\n theme: {\n oddRowBackground: 'white',\n evenRowBackground: '#eee',\n textColor: 'black',\n strokeColor: '#555',\n headerColor: 'black',\n hoverColor: '#1385cb'\n }\n};\n\nconst DEFAULT_POSITION_ARGS = {\n rowHeight: 24,\n rowSpace: 0.1,\n rowBigspace: 1,\n colWidth: 24,\n colSpace: 0.1,\n colBigspace: 1,\n colAnnotOffset: 10,\n colAnnotAngle: 30,\n padding: 5,\n minGeomSize: 0.25,\n funkyMidpoint: 0.8\n}\n\n/**\n * Positional options for the heatmap.\n *\n * Configurable options:\n * @property {number} rowHeight - height of a heatmap row, in pixels\n * @property {number} rowSpace - space between rows, as a fraction of rowHeight. Twice the padding\n * @property {number} rowBigspace - space between groups of rows, as a fraction of rowHeight\n * @property {number} colSpace - space between columns, as a fraction of rowHeight. Twice the\n * padding\n * @property {number} colAnnotOffset - offset of column groups from column labels, in pixels\n * @property {number} colAnnotAngle - angle of column labels, in degrees\n * @property {number} padding - padding used in certain places. TODO: document\n * @property {number} minGeomSize - minimum size of a heatmap element, in pixels\n * @property {number} funkyMidpoint - midpoint for funkyrect geom\n *\n * Calculated options:\n * @property {number} rowSpacePx - space between rows, in pixels\n * @property {number} rowBigspacePx - space between groups of rows, in pixels\n * @property {number} colSpacePx - space between columns, in pixels\n * @property {number} geomSize - size of a heatmap element, in pixels\n * @property {number} geomPadding - padding around heatmap elements, in pixels\n * @property {number} geomPaddingX - padding around heatmap elements in the x direction, in pixels\n * @property {number} bodyHeight - height of the heatmap body, in pixels\n * @property {number} bodyWidth - width of the heatmap body, in pixels\n * @property {number} width - width of the heatmap, in pixels, including header and footer\n * @property {number} headerHeight - height of the header, in pixels\n * @property {number} footerHeight - height of the footer, in pixels\n * @property {number} footerOffset - offset of the footer from the left edge of the heatmap, in pixels\n */\nclass PositionArgs {\n /**\n * @param {Object} args - object with positional options\n * @param {number} [args.rowHeight=24] - height of a heatmap row, in pixels\n * @param {number} [args.rowSpace=0.1] - space between rows, as a fraction of rowHeight.\n * Twice the padding\n * @param {number} [args.rowBigspace=1] - space between groups of rows, as a fraction of\n * rowHeight\n * @param {number} [args.colWidth=24] - width of a heatmap column, in pixels.\n * Deprecated, has no effect\n * @param {number} [args.colSpace=0.1] - space between columns, as a fraction of rowHeight.\n * Twice the padding\n * @param {number} [args.colBigspace=1] - space between groups of columns, as a fraction of\n * rowHeight. Currently not used\n * @param {number} [args.colAnnotOffset=3] - offset of column groups from column labels,\n * in pixels\n * @param {number} [args.colAnnotAngle=30] - angle of column labels, in degrees\n * @param {number} [args.padding=5] - padding around heatmap elements, in pixels\n * @param {number} [args.minGeomSize=0.25] - minimum size of a heatmap element, in pixels\n * @param {number} [args.funkyMidpoint=0.8] - midpoint for funkyrect geom\n */\n constructor(args) {\n _.extend(this, DEFAULT_POSITION_ARGS);\n _.extend(this, args);\n let underscoreDeprecatedArgs = [];\n let deprecatedArgs = [];\n for (let key of Object.getOwnPropertyNames(args)) {\n let underscore = key.indexOf('_');\n if (underscore > -1) {\n let newKey;\n while (underscore > -1) {\n newKey = key.slice(0, underscore) + key[underscore + 1].toUpperCase() + key.slice(underscore + 2);\n underscore = key.indexOf('_', underscore + 1);\n }\n this[newKey] = args[key];\n underscoreDeprecatedArgs.push(key);\n key = newKey;\n }\n if (key.startsWith('expand') || key == 'colWidth') {\n deprecatedArgs.push(key);\n }\n }\n if (underscoreDeprecatedArgs.length > 0) {\n let msg = 'Position arguments with underscores were accepted, but are deprecated. Use camelCase instead.';\n msg += ` Found: ${underscoreDeprecatedArgs.join(', ')}`;\n console.warn(msg);\n }\n if (deprecatedArgs.length > 0) {\n let msg = 'The following position arguments are deprecated and have no effect: ';\n msg += deprecatedArgs.join(', ');\n console.warn(msg);\n }\n this.calculate();\n }\n\n /**\n * Pre-calculate needed values based on the options.\n */\n calculate() {\n this.rowSpacePx = this.rowHeight * this.rowSpace;\n this.rowBigspacePx = this.rowHeight * this.rowBigspace;\n this.colSpacePx = this.rowHeight * this.colSpace;\n // assuming square\n this.geomSize = this.rowHeight - this.rowSpacePx;\n this.geomPadding = this.rowSpacePx / 2;\n this.geomPaddingX = this.colSpacePx / 2;\n }\n}\n\n/**\n * Heatmap class\n * @property {PositionArgs} positionArgs\n */\nclass FunkyHeatmap {\n constructor(\n data,\n columnInfo,\n columnGroups,\n rowInfo,\n rowGroups,\n palettes,\n legends,\n positionArgs,\n options,\n svg\n ) {\n this.rowGroupKey = '__group';\n\n this.data = data;\n this.columnInfo = columnInfo;\n this.columnGroups = d3.index(columnGroups, group => group.group);\n this.rowInfo = rowInfo;\n this.rowGroups = d3.index(rowGroups, group => group.group);\n this.palettes = palettes;\n this.legends = legends;\n this.positionArgs = new PositionArgs(positionArgs);\n this.options = _.merge(DEFAULT_OPTIONS, options);\n this.calculateOptions();\n this.svg = svg;\n }\n\n calculateOptions() {\n this.renderGroups = false;\n\n this.rowGroupOrder = [];\n // if we don't have row groups, put all rows in unnamed group\n if (this.rowInfo.length === 0 || this.rowInfo[0].group === undefined) {\n this.rowInfo = this.data.map(_ => { return {group: ''} });\n }\n\n this.data.forEach((d, i) => {\n const group = this.rowInfo[i].group;\n d[this.rowGroupKey] = group;\n if (this.rowGroupOrder.indexOf(group) === -1) {\n this.rowGroupOrder.push(group);\n }\n });\n const group = this.rowInfo[0].group\n const groupInfo = this.rowGroups.get(group);\n if (groupInfo !== undefined && groupInfo.Group !== undefined) {\n this.renderGroups = true;\n }\n }\n\n renderStripedRows() {\n const O = this.options;\n const P = this.positionArgs;\n\n let rowGroup, nGroups = 0, colorCounter = 0;\n this.data.forEach((d, i) => {\n if (this.renderGroups && d[this.rowGroupKey] !== rowGroup) {\n nGroups += 1;\n colorCounter = 0;\n }\n rowGroup = d[this.rowGroupKey];\n this.body.append('rect')\n .classed('row', true)\n .attr('height', P.rowHeight)\n .attr('x', 0)\n .attr('y', (i + nGroups) * P.rowHeight)\n .attr('fill', colorCounter % 2 === 0\n ? O.theme.evenRowBackground\n : O.theme.oddRowBackground);\n colorCounter += 1;\n });\n }\n\n renderData() {\n const O = this.options;\n const P = this.positionArgs;\n\n let offset = 0;\n P.bodyHeight = this.data.length * P.rowHeight;\n if (this.renderGroups) {\n P.bodyHeight += this.rowGroups.size * P.rowHeight;\n }\n let prevColGroup;\n\n this.columnInfo.forEach((column, i) => {\n let maxWidth = 0;\n let padding = P.geomPaddingX;\n let firstColumn = i === 0;\n if (column.geom === 'text' || column.geom === 'bar') {\n padding = P.padding;\n }\n offset += padding;\n if (prevColGroup && column.group && prevColGroup !== column.group) {\n offset += 2 * P.padding;\n }\n let rankedData;\n if (O.colorByRank && column.numeric) {\n rankedData = d3.rank(this.data, item => +item[column.id]);\n }\n let rowGroup, nGroups = 0;\n this.data.forEach((item, j) => {\n let width = 0;\n if (this.renderGroups && item[this.rowGroupKey] !== rowGroup) {\n nGroups += 1;\n }\n if (this.renderGroups && firstColumn && item[this.rowGroupKey] !== rowGroup) {\n let groupName = GEOMS.text(\n this.rowGroups.get(item[this.rowGroupKey]).Group,\n null,\n column,\n O,\n P\n );\n groupName\n .attr('transform', `translate(${offset - padding}, ${(j + nGroups - 1) * P.rowHeight})`)\n .attr('font-weight', 'bold')\n .attr('dominant-baseline', 'hanging');\n this.body.append(() => groupName.node());\n width = groupName.node().getBBox().width;\n }\n rowGroup = item[this.rowGroupKey];\n let value = item[column.id];\n if (value === undefined || value === null || (isNaN(value) && column.numeric)) {\n return;\n }\n let colorValue = value;\n let label;\n if (column.numeric) {\n value = +value;\n }\n if (O.colorByRank && column.numeric) {\n colorValue = rankedData[j];\n }\n if (column.label) {\n label = item[column.label];\n }\n if (GEOMS[column.geom] === undefined) {\n throw `Geom ${column.geom} not implemented. Use one of ${Object.keys(GEOMS).join(', ')}.`;\n }\n let el = GEOMS[column.geom](value, colorValue, column, O, P);\n if (label) {\n const labelColor = d3.hsl(column.palette(colorValue)).l > 0.5\n ? 'black'\n : 'white';\n const g = d3.create('svg:g')\n .classed('fh-geom', true);\n g.append(() => el.classed('fh-geom', false).classed('fh-orig-geom', true).node());\n g.append('text')\n .attr('x', P.rowHeight / 2)\n .attr('y', P.rowHeight / 2)\n .attr('text-anchor', 'middle')\n .attr('dominant-baseline', 'central')\n .attr('fill', labelColor)\n .text(label);\n el = g;\n }\n el.attr('transform', `translate(${offset}, ${(j + nGroups) * P.rowHeight})`);\n if (column.numeric && !label) {\n let tooltip = (+value).toFixed(4);\n tooltip = tooltip.replace(/\\.?0+$/, '');\n el.datum({tooltip: tooltip});\n }\n if (column.geom === 'pie') {\n const s = 'margin: 5px; border-top: 1px solid #aaa; border-left: 1px solid #aaa; font-size: 80%';\n const s2 = 'padding: 2px 4px; border-bottom: 1px solid #aaa; border-right: 1px solid #aaa';\n let tooltip = `${column.palette.colorNames.map((colorName, i) => {\n return ``;\n }).join('')}
${colorName}:${value[i]}
`;\n el.datum({tooltip: tooltip});\n }\n this.body.append(() => el.node());\n let elWidth;\n if (label) {\n elWidth = el.select('.fh-orig-geom').node().getBBox().width;\n } else {\n elWidth = el.node().getBBox().width;\n }\n if (column.geom === 'image') {\n elWidth = column.width;\n }\n if (elWidth > width) {\n width = elWidth;\n }\n if (width > maxWidth) {\n maxWidth = width;\n }\n if (label) {\n label = el.select('text');\n let fontSize = 100;\n for (let q = 0; q < 8; q++) {\n const { width } = label.node().getBBox();\n if (width > P.geomSize - P.geomPaddingX * 2) {\n fontSize -= 5;\n label.attr('font-size', `${fontSize}%`);\n } else {\n break;\n }\n }\n }\n });\n if (column.geom === 'bar') {\n maxWidth = P.geomSize * column.width + P.geomPadding;\n this.body.append('line')\n .attr('x1', offset + maxWidth)\n .attr('x2', offset + maxWidth)\n .attr('y1', this.renderGroups ? P.rowHeight : 0)\n .attr('y2', P.bodyHeight)\n .attr('stroke', O.theme.strokeColor)\n .attr('stroke-dasharray', '5 5')\n .attr('opacity', 0.5);\n }\n column.widthPx = Math.max(maxWidth, P.rowHeight);\n column.widthPx = Math.round(column.widthPx);\n column.offset = offset;\n offset += column.widthPx + padding;\n prevColGroup = column.group;\n });\n P.bodyWidth = offset + P.colSpacePx;\n }\n\n renderHeader() {\n const O = this.options;\n const P = this.positionArgs;\n\n let headerHeight = 0;\n let bodyWidth = 0;\n let nonZeroRotate = false;\n const groups = this.header.append('g');\n const labels = this.header.append('g')\n .attr('transform', `translate(0, ${P.rowHeight + P.colAnnotOffset})`);\n\n const columnGroups = d3.group(this.columnInfo, column => column.group);\n let abcCounter = 0;\n columnGroups.forEach((group, groupName) => {\n if (!groupName) {\n return;\n }\n const groupInfo = this.columnGroups.get(groupName);\n const column = new Column({\n id: '_group',\n palette: groupInfo.palette\n }, 1);\n column.maybeCalculateStats(null, false);\n assignPalettes([column], this.palettes);\n const lastCol = group[group.length - 1];\n const groupStart = group[0].offset;\n const groupEnd = lastCol.offset + lastCol.widthPx + P.geomPadding;\n const fill = column.palette == 'none' && 'transparent' || column.palette(0.5);\n groups.append('rect')\n .attr('x', groupStart)\n .attr('y', 0)\n .attr('width', groupEnd - groupStart)\n .attr('height', P.rowHeight)\n .attr('fill', fill)\n .attr('opacity', 0.25);\n const text = groups.append('text')\n .attr('x', groupStart + (groupEnd - groupStart) / 2)\n .attr('y', P.rowHeight / 2)\n .attr('text-anchor', 'middle')\n .attr('dominant-baseline', 'central')\n .attr('fill', O.theme.headerColor)\n .text(groupInfo.level1);\n if (O.fontSize) {\n text.attr('font-size', O.fontSize);\n }\n if (O.labelGroupsAbc) {\n const letter = String.fromCharCode(\"a\".charCodeAt(0) + abcCounter);\n const text = groups.append('text')\n .attr('x', groupStart + P.padding)\n .attr('y', P.rowHeight / 2)\n .attr('dominant-baseline', 'central')\n .attr('fill', O.theme.headerColor)\n .text(`${letter})`);\n if (O.fontSize) {\n text.attr('font-size', O.fontSize);\n }\n }\n abcCounter += 1;\n });\n\n this.columnInfo.forEach((column, i) => {\n const el = labels.append('g')\n .attr('transform', `rotate(${-P.colAnnotAngle})`)\n .classed(`column-${i}`, true);\n el.append('text')\n .attr('x', 0)\n .attr('y', 0)\n .attr('font-size', O.fontSize)\n .style('fill', O.theme.textColor)\n .style('cursor', 'pointer')\n .datum(column)\n .on('click', this.onColumnClick.bind(this))\n .on('mouseenter', () => {\n el.style('text-decoration', 'underline dashed')\n .style('fill', O.theme.hoverColor)\n })\n .on('mouseleave', () => {\n el.style('text-decoration', '').style('fill', O.theme.textColor)\n })\n .text(column.name);\n const nativeWidth = el.node().getBBox().width;\n if (!nonZeroRotate && nativeWidth < column.widthPx - 2 * P.padding) {\n column.rotate = false;\n } else {\n column.rotate = true;\n nonZeroRotate = true;\n }\n const { width, height } = el.node().getBoundingClientRect();\n if (height > headerHeight) {\n headerHeight = height;\n }\n if (column.offset + column.widthPx / 2 + width > bodyWidth) {\n bodyWidth = column.offset + column.widthPx / 2 + width + P.padding;\n }\n });\n this.columnInfo.forEach((column, i) => {\n let center = column.offset + column.widthPx / 2;\n let rotate = column.rotate ? -P.colAnnotAngle : 0;\n this.header.select(`.column-${i}`)\n .attr(\n 'transform',\n `translate(${center}, ${headerHeight - 2 * P.padding}) rotate(${rotate})`\n );\n if (!column.rotate) {\n labels.select(`.column-${i} text`)\n .attr('text-anchor', 'middle');\n } else {\n labels.append('line')\n .attr('x1', center)\n .attr('x2', center)\n .attr('y1', headerHeight - 2)\n .attr('y2', headerHeight - 2 - P.padding)\n .attr('stroke', O.theme.strokeColor);\n }\n });\n P.width = bodyWidth;\n P.headerHeight = headerHeight + P.rowHeight + P.colAnnotOffset;\n }\n\n renderLegends() {\n const O = this.options;\n const P = this.positionArgs;\n\n // go through this.legends and render them sequentially\n\n let footerHeight = 0;\n const legendEl = this.footer.append('g');\n let legendXOffset = 0;\n let offset = 0;\n let funkyrectPresent = false;\n\n this.legends.forEach(legend => {\n if (!legend.enabled) {\n return;\n }\n const rowHeight = O.legendFontSize;\n let offsetY = rowHeight * 2 + P.padding;\n const el = legendEl.append('g');\n el.attr('transform', `translate(${offset}, 0)`);\n el.append('text')\n .attr('x', 0)\n .attr('y', offsetY)\n .attr('font-size', O.legendFontSize)\n .style('fill', O.theme.textColor)\n .text(legend.title);\n\n if (legend.geom === 'text') {\n let labelsWidth = 0;\n legend.labels.forEach((label, i) => {\n const txt = el.append('text')\n .attr('x', P.padding)\n .attr('y', offsetY + (i + 1) * (rowHeight + P.padding))\n .attr('font-size', O.legendFontSize)\n .style('fill', O.theme.textColor)\n .text(label);\n const { width } = txt.node().getBBox();\n if (width > labelsWidth) {\n labelsWidth = width;\n }\n });\n legend.values.forEach((value, i) => {\n el.append('text')\n .attr('x', P.padding * 2 + labelsWidth)\n .attr('y', offsetY + (i + 1) * (rowHeight + P.padding))\n .attr('font-size', O.legendFontSize)\n .style('fill', O.theme.textColor)\n .text(value);\n });\n }\n if (legend.geom === 'rect') {\n let myOffset = 0;\n legend.values.forEach((colorValue, i) => {\n const label = legend.labels[i];\n const size = legend.size[i];\n const geom = GEOMS.rect(size, colorValue, legend, O, P);\n geom.attr('transform', `translate(${myOffset}, ${offsetY + P.padding})`);\n el.append(() => geom.node());\n el.append('text')\n .attr('x', myOffset + P.rowHeight / 2)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n myOffset += size * P.geomSize + P.padding;\n });\n }\n if (legend.geom === 'funkyrect') {\n let myOffset = 0;\n legend.labels.forEach((label, i) => {\n const colorValue = legend.values[i];\n const size = legend.size[i];\n const geom = GEOMS.funkyrect(size, colorValue, legend, O, P);\n el.append(() => geom.node());\n const { width: geomWidth, height: geomHeight } = geom.node().getBBox();\n geom.attr(\n 'transform',\n `translate(${myOffset}, ${offsetY + P.rowHeight / 2 - geomHeight / 2})`\n );\n el.append('text')\n .attr('x', myOffset + P.rowHeight / 2)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n myOffset += geomWidth + P.padding;\n });\n }\n if (legend.geom === 'circle') {\n let myOffset = 0;\n legend.labels.forEach((label, i) => {\n const colorValue = legend.values[i];\n const size = legend.size[i];\n const geom = GEOMS.circle(size, colorValue, legend, O, P);\n el.append(() => geom.node());\n const { width: geomWidth, height: geomHeight } = geom.node().getBBox();\n geom.attr(\n 'transform',\n `translate(${myOffset}, ${offsetY + P.rowHeight / 2 - geomHeight / 2})`\n );\n el.append('text')\n .attr('x', myOffset + P.rowHeight / 2)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n myOffset += geomWidth + P.padding;\n });\n }\n if (legend.geom === 'bar') {\n const colors = legend.palette.range();\n\n const grad = this.svg.append('defs')\n .append('linearGradient')\n .attr('id', `grad_${legend.paletteName}`)\n .attr('x1', '0%')\n .attr('x2', '100%')\n .attr('y1', '0%')\n .attr('y2', '0%');\n\n grad.selectAll('stop')\n .data(colors)\n .enter()\n .append('stop')\n .style('stop-color', function(d) { return d; })\n .attr('offset', function(d, i) {\n return 100 * (i / (colors.length - 1)) + '%';\n });\n\n // A bit ugly to get the width of the column mapped to this legend\n const col = this.columnInfo.filter((column) =>\n column.geom === 'bar' && column.paletteName === legend.paletteName\n )[0];\n\n el.append('rect')\n .attr('x', P.padding)\n .attr('y', offsetY + P.padding)\n .attr('width', col.widthPx)\n .attr('height', P.rowHeight)\n .style('fill', `url(#grad_${legend.paletteName})`)\n .attr('stroke', 'black')\n .attr('stroke-width', 0.5);\n\n legend.labels.forEach((label, i) => {\n if (label === '') {\n return;\n }\n const value = legend.values[i];\n const xPos = P.padding + col.widthPx * value;\n if (value > 0 && value < 1) {\n el.append('line')\n .attr('x1', xPos)\n .attr('x2', xPos)\n .attr('y1', offsetY + P.rowHeight + P.padding)\n .attr('y2', offsetY + P.rowHeight)\n .attr('stroke', 'black')\n .attr('stroke-width', 0.5);\n }\n el.append('text')\n .attr('x', xPos)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n });\n }\n if (legend.geom === 'image') {\n legend.values.forEach((value, i) => {\n const label = legend.labels[i];\n const img = GEOMS.image(value, null, {width: legend.size[i]}, O, P);\n img.attr('transform', `translate(0, ${offsetY + P.padding})`);\n el.append(() => img.node());\n const { width: imgWidth, height: imgHeight } = img.node().getBBox();\n el.append('text')\n .attr('x', imgWidth + P.padding)\n .attr('y', offsetY + P.padding + imgHeight / 2)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'left')\n .attr('dominant-baseline', 'central')\n .style('fill', O.theme.textColor)\n .text(label);\n offsetY += imgHeight + P.padding;\n });\n }\n if (legend.geom === 'pie') {\n const arcs = d3.pie().endAngle(Math.PI)(Array(legend.palette.colorNames.length).fill(1));\n const g = el.append('g');\n g.attr('transform', `translate(0, ${offsetY + P.padding + P.rowHeight})`);\n g.selectAll('arcs')\n .data(arcs)\n .enter()\n .append('path')\n .attr('d', d3.arc().innerRadius(0).outerRadius(P.geomSize / 2))\n .attr('fill', (_, i) => {\n return legend.palette(i);\n })\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .attr('transform', `translate(${P.geomSize / 2 + P.geomPadding - 0.5}, 0)`);\n\n g.selectAll('text')\n .data(arcs)\n .enter()\n .append('text')\n .text((_, i) => legend.palette.colorNames[i])\n .attr('font-size', O.legendFontSize)\n .attr('dominant-baseline', 'central')\n .style('fill', O.theme.textColor)\n .attr('transform', d => {\n const p = d3.arc().innerRadius(P.geomSize / 2).outerRadius(P.geomSize).centroid(d);\n p[0] += P.geomSize / 2 + 4 * P.geomPadding;\n return `translate(${p})`;\n });\n\n g.selectAll('lines')\n .data(arcs)\n .enter()\n .append('path')\n .attr('d', d => {\n const p1 = d3.arc().innerRadius(P.geomSize / 2).outerRadius(P.geomSize / 2 + 5).centroid(d);\n const p2 = d3.arc().innerRadius(P.geomSize / 2).outerRadius(P.geomSize - 5).centroid(d);\n p1[0] += P.geomSize / 2 + P.geomPadding;\n p2[0] += P.geomSize / 2 + 3 * P.geomPadding;\n return d3.line()([p1, p2]);\n })\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 0.5);\n }\n\n const { width } = el.node().getBBox();\n offset += width + P.padding * 2;\n });\n\n const { height } = legendEl.node().getBBox();\n if (height > footerHeight) {\n footerHeight = height;\n }\n let legendWidth = offset - P.padding;\n if (funkyrectPresent) {\n legendWidth += P.geomSize;\n }\n if (legendXOffset + legendWidth > P.width) {\n if (legendWidth <= P.width) { // try to right-justify the legend\n legendXOffset = P.width - legendWidth;\n } else {\n legendXOffset = 0;\n P.width = offset;\n }\n }\n P.footerOffset = legendXOffset;\n P.footerHeight = footerHeight + P.rowHeight;\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style(\"display\", \"none\");\n }\n }\n\n showTooltip(mouse, text) {\n if (this.tooltip === undefined) {\n this.tooltip = d3.select(\"body\")\n .append(\"div\")\n .style(\"z-index\", 2000)\n .style(\"position\", \"absolute\")\n .style(\"background-color\", \"#333\")\n .style(\"color\", \"white\")\n .style(\"border\", \"solid\")\n .style(\"border-width\", \"1px\")\n .style(\"border-radius\", \"5px\")\n .style(\"padding\", \"3px 5px\")\n .style(\"display\", \"none\");\n }\n\n const offset = 10;\n this.tooltip\n .html(text)\n .style(\"top\", mouse[1] + 2 * offset + \"px\")\n .style(\"left\", mouse[0] + offset + \"px\")\n .style(\"display\", \"block\");\n }\n\n onMouseMove(e) {\n if (e.target) {\n let el = d3.select(e.target);\n while (el.classed('fh-geom') === false && el.node() != this.svg.node()) {\n el = d3.select(el.node().parentNode);\n }\n const d = el.datum();\n if (d && d.tooltip) {\n const mouse = d3.pointer(e, document.body);\n this.showTooltip(mouse, d.tooltip);\n return;\n }\n }\n this.hideTooltip();\n }\n\n onColumnClick(e) {\n const el = d3.select(e.target);\n const elBox = el.node().getBBox();\n const column = el.datum();\n const comparator = column.sort();\n let data = d3.group(this.data, d => d[this.rowGroupKey]);\n data = [].concat(...this.rowGroupOrder.map(group => d3.sort(data.get(group), (a, b) => {\n [a, b] = [a[column.id], b[column.id]];\n if (column.numeric) {\n [a, b] = [+a, +b];\n }\n return comparator(a, b);\n })));\n this.data = data;\n this.svg.selectChildren().remove();\n this.render();\n\n this.indicateSort(column, elBox);\n }\n\n indicateSort(column, labelBox) {\n const O = this.options;\n const P = this.positionArgs;\n\n this.sortIndicator = this.header.append(\"text\")\n .attr('font-size', 12)\n .attr('fill', O.theme.hoverColor);\n if (column.sortState === \"asc\") {\n this.sortIndicator.text('↑');\n } else {\n this.sortIndicator.text('↓');\n }\n this.sortIndicator\n .attr('text-anchor', 'right')\n .attr('dominant-baseline', 'text-bottom');\n let x = column.offset + column.widthPx / 2 - 2 * P.padding;\n let y = P.headerHeight - P.padding;\n if (!column.rotate) {\n x -= labelBox.width / 2;\n y -= labelBox.height / 2;\n this.sortIndicator.attr('dominant-baseline', 'central');\n }\n this.sortIndicator\n .attr('x', x)\n .attr('y', y);\n }\n\n render() {\n this.header = this.svg.append(\"g\");\n this.body = this.svg.append(\"g\");\n this.footer = this.svg.append(\"g\");\n\n this.renderStripedRows();\n this.renderData();\n this.renderHeader();\n this.renderLegends();\n\n const O = this.options;\n const P = this.positionArgs;\n\n this.svg.attr('width', P.width);\n this.svg.attr('height', P.bodyHeight + P.headerHeight + P.footerHeight);\n if (this.renderGroups) {\n this.header.attr('transform', `translate(0, ${P.rowHeight})`);\n }\n this.body.selectAll('.row').attr('width', P.bodyWidth);\n this.body.attr(\"transform\", `translate(0, ${P.headerHeight})`);\n this.footer.attr('transform', `translate(${P.footerOffset}, ${P.headerHeight + P.bodyHeight})`);\n this.svg.attr('style', '');\n if (O.rootStyle) {\n this.svg.attr('style', O.rootStyle);\n }\n }\n\n listen() {\n this.svg.on(\"mousemove\", this.onMouseMove.bind(this));\n }\n};\n\n\n/**\n * The main entry point for the library. Takes data and various configuration options and returns\n * an SVG element with the heatmap.\n *\n * @param {ColumnData|RowData} data - data to plot, usually d3-fetch output.\n * @param {ColumnData|module:columns~ColumnInfo[]} columnInfo - information about how the columns\n * should be displayed. If not specified, all columns from `data` will be displayed.\n * See {@link module:columns~ColumnInfo}, {@link module:columns.Column}.\n * @param {ColumnData|RowData} rowInfo - information about how the rows should be displayed\n * @param {ColumnData|RowData} columnGroups - information about how to group columns\n * @param {ColumnData|RowData} rowGroups - information about how to group rows\n * @param {Object} palettes - mapping of names to palette colors, see {@link module:palettes.assignPalettes}\n * @param {ColumnData|RowData} legends - a list of legends to add to the plot\n * @param {Object} positionArgs - positioning arguments, see {@link PositionArgs}\n * @param {Object} options - options for the heatmap, see {@link HeatmapOptions}\n * @param {boolean} scaleColumn - whether to apply min-max scaling to numerical\n * columns. Defaults to true\n *\n * @returns {SVGElement} - the SVG element containing the heatmap\n *\n */\nfunction funkyheatmap(\n data,\n columnInfo,\n rowInfo = [],\n columnGroups = [],\n rowGroups = [],\n palettes = {},\n legends = [],\n positionArgs = {},\n options = {},\n scaleColumn = true\n) {\n [data, columnInfo, columnGroups, rowInfo, rowGroups, legends] = ensureRowData(\n data, columnInfo, columnGroups, rowInfo, rowGroups, legends\n );\n columnInfo = buildColumnInfo(data, columnInfo, scaleColumn, options.colorByRank);\n columnGroups = buildColumnGroups(columnGroups, columnInfo);\n legends = prepareLegends(legends, palettes, columnInfo);\n assignPalettes(columnInfo, palettes);\n assignPalettes(legends, palettes);\n\n const svg = d3.select('body')\n .append('svg')\n .classed('funkyheatmap', true)\n .style('visibility', 'hidden')\n .style('position', 'absolute')\n .style('left', '-2000px');\n const heatmap = new FunkyHeatmap(\n data,\n columnInfo,\n columnGroups,\n rowInfo,\n rowGroups,\n palettes,\n legends,\n positionArgs,\n options,\n svg\n );\n heatmap.render();\n heatmap.listen();\n heatmap.svg.remove();\n\n return heatmap.svg.node();\n}\n\nexport default funkyheatmap;\n","module.exports=_;","/** @module */\n\n/**\n * Converts object-based dataframe to array-based dataframe.\n *\n * @param {ColumnData} data - an object with each property representing dataframe column as an array.\n * Columns are of the same length\n * @returns {RowData} - array of objects with properties corresponding to columns\n */\nexport function colToRowData(data) {\n const columns = Object.getOwnPropertyNames(data);\n const size = data[columns[0]].length;\n const result = [];\n for (let i = 0; i < size; i++) {\n let item = {};\n for (let column of columns) {\n item[column] = data[column][i];\n }\n result.push(item);\n }\n return result;\n};\n\n/**\n * Converts array-based dataframe to object-based dataframe.\n *\n * @param {RowData} data - an array of objects with properties\n * @returns {ColumnData} - object with each property representing dataframe column as an array,\n * values are preserved in the same order as in the input array\n */\nexport function rowToColData(data) {\n const result = {};\n const columns = Object.getOwnPropertyNames(data[0]);\n for (let column of columns) {\n result[column] = data.map(item => item[column]);\n }\n return result;\n};\n\n/**\n * Convenience function to convert potential column-based dataframes to row-based dataframes.\n *\n * @param {Object[]} objects - potential objects to convert to row-based dataframes. Only converts\n * objects, skips arrays\n * @returns {Object[]} - array of converted objects\n */\nexport function ensureRowData(...objects) {\n return objects.map(obj => {\n if (obj && !Array.isArray(obj)) {\n obj = convertDataframe(obj);\n }\n return obj;\n });\n};\n","/** @module */\n\nimport * as d3 from 'd3';\n\n/**\n * @typedef {Object} ColumnInfo\n * @description Information about dataframe column and how to display it.\n * @property {string} id - column id in the dataset. Required.\n */\n\n/**\n * @class\n */\nexport class Column {\n constructor(info, value) {\n ({\n id: this.id,\n name: this.name,\n geom: this.geom,\n group: this.group,\n palette: this.palette,\n width: this.width,\n label: this.label,\n overlay: this.overlay,\n options: this.options\n } = info);\n\n let type = typeof value;\n // geom text is always categorical\n if (isNumeric(value) && this.geom !== 'text') {\n type = 'number';\n this.numeric = true;\n this.categorical = false;\n } else {\n this.numeric = false;\n this.categorical = true;\n }\n\n if (this.name === undefined) {\n this.name = this.id;\n }\n\n if (this.options === undefined) {\n this.options = {};\n }\n\n if (this.options.width !== undefined && this.width === undefined) {\n this.width = this.options.width;\n }\n if (this.options.palette !== undefined && this.palette === undefined) {\n this.palette = this.options.palette;\n }\n\n if (this.geom === undefined) {\n if (type === 'number') {\n this.geom = 'funkyrect';\n } else {\n this.geom = 'text';\n }\n }\n\n if (this.palette === undefined) {\n if (this.geom === 'pie') {\n this.palette = 'categorical';\n }\n if (this.numeric) {\n this.palette = 'numerical';\n }\n }\n\n if (this.width === undefined) {\n if (this.geom === 'bar') {\n this.width = 4;\n }\n }\n\n if (this.geom === 'image' && this.width === undefined) {\n throw `Please, specify width for column with geom=image`;\n }\n\n this.sortState = null;\n }\n\n maybeCalculateStats(data, scaleColumn, colorByRank) {\n let extent = [0, 1];\n if (scaleColumn) {\n extent = d3.extent(data, i => +i[this.id]);\n }\n [this.min, this.max] = extent;\n this.range = this.max - this.min;\n this.scale = d3.scaleLinear().domain(extent);\n if (colorByRank) {\n this.colorScale = d3.scaleLinear().domain([0, data.length - 1]);\n }\n }\n\n sort() {\n if (this.sortState === \"desc\") {\n this.sortState = \"asc\";\n return d3.ascending;\n }\n this.sortState = \"desc\";\n return d3.descending;\n }\n}\n\n/**\n * Assemble all column information needed for drawing\n *\n * @param {RowData} data - dataset\n * @param {module:columns~ColumnInfo[]} columnInfo - properties of the columns for drawing, which we will modify\n * @param {boolean} scaleColumn - whether to min-max scale data per column\n * @param {boolean} colorByRank - whether to color by rank per column instead of by value\n */\nexport function buildColumnInfo(data, columnInfo, scaleColumn, colorByRank) {\n const item = data[0];\n if (columnInfo === undefined || columnInfo.length === 0) {\n console.info(\"No column info specified, assuming all columns are to be displayed.\");\n columnInfo = Object.getOwnPropertyNames(item).map(id => {\n return {id: id}\n });\n }\n return columnInfo.map(info => {\n let column = info.id;\n if (column === undefined) {\n throw \"Column info must have id field corresponding to the column in the data\";\n }\n column = new Column(info, item[column]);\n column.maybeCalculateStats(data, scaleColumn, colorByRank);\n return column;\n });\n};\n\n/**\n * Check and prepare column group information\n *\n * @param {Object[]} columnGroups - information about column groups, empty array if not specified\n * @param {Object[]} columnInfo - information about columns, to crosscheck\n * @returns {Object[]} - column groups with defaults filled in, if necessary\n */\nexport function buildColumnGroups(columnGroups, columnInfo) {\n if (columnGroups.length === 0 && columnInfo.some(i => i.group)) {\n console.info(\"No column groups specified, but some columns have group, building automatically\");\n columnGroups = columnInfo\n .filter(i => i.group)\n .map(i => i.group);\n columnGroups = [...new Set(columnGroups)];\n columnGroups = columnGroups.map(group => {\n return {group: group}\n });\n }\n if (columnGroups.length === 0) {\n return [];\n }\n columnInfo.forEach(i => {\n if (i.group && !columnGroups.some(g => g.group === i.group)) {\n throw `Column group ${i.group} is not specified in columnGroups`;\n }\n });\n let allGroups = columnInfo.filter(i => i.group).map(i => i.group);\n let unused = columnGroups.filter(i => !allGroups.includes(i.group));\n if (unused.length > 0) {\n console.warn(`Unused column groups: ${unused.map(i => i.group).join(', ')}`);\n }\n\n if (columnGroups[0].palette === undefined) {\n console.info(\"Column groups did not specify `palette`. Assuming no colours\")\n columnGroups.forEach(i => {\n i.palette = 'none';\n });\n }\n columnGroups.forEach(i => {\n if (i.palette === undefined) {\n throw `Column group ${i.group} did not specify palette`;\n }\n });\n\n if (columnGroups[0].level1 === undefined) {\n console.info(\"Column groups did not specify `level1`. Using group id as level1\")\n columnGroups.forEach(i => {\n i.level1 = i.group.charAt(0).toUpperCase() + i.group.slice(1);\n });\n }\n\n return columnGroups;\n};\n\nfunction isNumeric(str) {\n if (typeof str === 'number') return true;\n if (typeof str !== 'string') return false;\n // use type coercion to parse the _entirety_ of the string\n // (`parseFloat` alone does not do this)...\n return !Number.isNaN(str)\n && !Number.isNaN(parseFloat(str)); // ...and ensure strings of whitespace fail\n}\n","/** @module */\n\nimport * as d3 from 'd3';\n\n/**\n * Default palettes for numerical and categorical data. See source for the colors.\n * @constant {Object}\n * @property {Object} numerical - palettes for numerical data. Default is Blues\n * @property {Object} categorical - palettes for categorical data. Default is Set1\n */\nconst defaultPalettes = {\n numerical: {\n Blues: [\n \"#011636\", \"#08306B\", \"#08519C\", \"#2171B5\", \"#4292C6\", \"#6BAED6\", \"#9ECAE1\", \"#C6DBEF\",\n \"#DEEBF7\", \"#F7FBFF\"\n ],\n Greens: [\n \"#00250f\", \"#00441B\", \"#006D2C\", \"#238B45\", \"#41AB5D\", \"#74C476\", \"#A1D99B\", \"#C7E9C0\",\n \"#E5F5E0\"\n ],\n Greys: [\n \"#000000\", \"#252525\", \"#525252\", \"#737373\", \"#969696\", \"#BDBDBD\", \"#D9D9D9\", \"#F0F0F0\"\n ],\n Reds: [\n \"#CB181D\", \"#EF3B2C\", \"#FB6A4A\", \"#FC9272\", \"#FCBBA1\", \"#FEE0D2\", \"#FFF5F0\"\n ],\n YlOrBr: [\n \"#EC7014\", \"#FE9929\", \"#FEC44F\", \"#FEE391\", \"#FFF7BC\", \"#FFFFE5\"\n ]\n },\n categorical: {\n Set1: [\n \"#E41A1C\",\"#377EB8\",\"#4DAF4A\",\"#984EA3\",\"#FF7F00\",\"#FFFF33\",\"#A65628\",\"#F781BF\",\n \"#999999\"\n ],\n Set2: [\n \"#66C2A5\",\"#FC8D62\",\"#8DA0CB\",\"#E78AC3\",\"#A6D854\",\"#FFD92F\",\"#E5C494\",\"#B3B3B3\"\n ],\n Set3: [\n \"#8DD3C7\", \"#FFFFB3\", \"#BEBADA\", \"#FB8072\", \"#80B1D3\", \"#FDB462\", \"#B3DE69\", \"#FCCDE5\",\n \"#D9D9D9\", \"#BC80BD\", \"#CCEBC5\", \"#FFED6F\"\n ],\n Dark2: [\n \"#1B9E77\",\"#D95F02\",\"#7570B3\",\"#E7298A\",\"#66A61E\",\"#E6AB02\",\"#A6761D\",\"#666666\"\n ]\n }\n};\n\n/**\n *\n * @param {module:columns.Column[]} columnInfo - list of Column objects with information\n * @param {Object} palettes - mapping of names to palette colors\n * possible options for the palette colors are:\n * - name of a built-in palette (e.g. Blues, Set1…)\n * - `Array` of colors as strings\n * - `Object` with keys `colors` and `names` - important for categorical data\n */\nexport function assignPalettes(columnInfo, palettes) {\n palettes = { numerical: \"Blues\", categorical: \"Set1\", ...palettes };\n columnInfo.forEach(column => {\n if (column.palette && column.palette != 'none') {\n column.paletteName = column.palette;\n let name = palettes[column.palette];\n if (name === undefined) { // fallback\n name = column.palette;\n }\n let colors;\n let colorNames;\n if (defaultPalettes.numerical[name]) {\n colors = defaultPalettes.numerical[name];\n } else if (defaultPalettes.categorical[name]) {\n colors = defaultPalettes.categorical[name];\n } else if (Array.isArray(name)) {\n const item = name[0];\n if (typeof item === 'string' || item instanceof String) {\n colors = name;\n } else {\n throw `Palette definition ${name} is not recognized. Expected are: array of colors, array of color-name pairs.`;\n }\n } else if (Array.isArray(name.colors) && Array.isArray(name.names)) {\n colors = name.colors;\n colorNames = name.names;\n } else {\n const names = [\n ...Object.getOwnPropertyNames(defaultPalettes.numerical),\n ...Object.getOwnPropertyNames(defaultPalettes.categorical)\n ];\n throw `Palette ${name} not defined. Use one of ${names.join(', ')}.`;\n }\n\n if (column.numeric) {\n let scale = column.scale;\n if (column.colorScale) {\n scale = column.colorScale;\n }\n const [min, max] = scale.domain();\n const step = (max - min) / (colors.length - 1);\n const domain = [...d3.range(min, max, step), max];\n column.palette = d3.scaleLinear().domain(domain).range(colors);\n }\n // TODO: replace with categorical\n if (column.geom === 'pie' || column.geom === 'text') {\n const domain = d3.range(colors.length);\n column.palette = d3.scaleOrdinal().domain(domain).range(colors);\n column.palette.colors = colors;\n column.palette.colorNames = colorNames;\n }\n }\n });\n};\n","/** @module */\n\nimport * as _ from 'lodash';\n\n/**\n *\n * @param {Object[]|undefined} legends - user provided legend configuration\n * @param {Object} palettes - mapping of names to palette colors\n * @param {Object[]} columnInfo - user provided information on columns\n */\nexport function prepareLegends(legends, palettes, columnInfo) {\n if (legends === undefined) {\n console.info('No legends provided, will infer automatically');\n legends = [];\n }\n\n const colInfoPalettes = [];\n columnInfo.forEach(i => {\n if (i.palette && colInfoPalettes.indexOf(i.palette) === -1) {\n colInfoPalettes.push(i.palette);\n }\n });\n const legendPalettes = [];\n legends.forEach(l => {\n if (l.palette && legendPalettes.indexOf(l.palette) === -1) {\n legendPalettes.push(l.palette);\n }\n });\n\n const missingPalettes = _.difference(colInfoPalettes, legendPalettes);\n if (missingPalettes.length > 0) {\n let msg = 'These palettes are missing in legends, adding legends for them: ';\n msg += missingPalettes.join(', ');\n console.info(msg);\n missingPalettes.forEach(p => {\n legends.push({\n title: p,\n palette: p,\n enabled: true,\n });\n });\n }\n\n legends.forEach(legend => {\n if (legend.enabled === undefined) {\n legend.enabled = true;\n }\n if (legend.title === undefined) {\n legend.title = legend.palette;\n }\n if (legend.geom === undefined) {\n console.info(`Legend \\`${legend.title}\\` did not specify geom, copying from column info`);\n const col = columnInfo.find(i => i.palette === legend.palette);\n legend.geom = col.geom;\n }\n if (legend.labels === undefined) {\n console.info(`Legend \\`${legend.title}\\` did not specify labels, inferring from column info`);\n if (legend.geom === 'pie') {\n const pal = palettes[legend.palette];\n if (pal.names === undefined) {\n console.warn(`Cannot infer labels for legend \\`${legend.title}\\`, please provide color names in palette. Disabling this legend`);\n legend.enabled = false;\n }\n legend.labels = palettes[legend.palette].names;\n } else if (['circle', 'rect', 'funkyrect', 'bar'].includes(legend.geom)) {\n // TODO: get from default options\n legend.labels = ['0', '', '0.2', '', '0.4', '', '0.6', '', '0.8', '', '1'];\n } else if (legend.geom === 'text' || legend.geom === 'image') {\n console.warn(`Cannot infer labels for legend \\`${legend.title}\\` of type ${legend.geom}, please provide labels. Disabling this legend`);\n legend.enabled = false;\n }\n }\n if (legend.size === undefined) {\n console.info(`Legend \\`${legend.title}\\` did not specify size, inferring from column info`);\n if (legend.geom === 'circle' || legend.geom === 'funkyrect') {\n legend.size = [...d3.range(0, legend.labels.length - 1).map(\n (i) => i / (legend.labels.length - 1)\n ), 1];\n } else if (legend.geom === 'rect' || legend.geom === 'bar') {\n legend.size = 1;\n } else if (legend.geom === 'image') {\n throw `Please specify size (width) for image legend \\`${legend.title}\\``;\n }\n }\n if (legend.values === undefined) {\n if (['circle', 'rect', 'funkyrect', 'bar'].includes(legend.geom)) {\n legend.values = [...d3.range(0, legend.labels.length - 1).map(\n (i) => i / (legend.labels.length - 1)\n ), 1];\n }\n if (legend.enabled && (legend.geom === 'image' || legend.geom === 'text')) {\n console.warn(`Cannot infer values for legend \\`${legend.title}\\` of type ${legend.geom}, please provide values. Disabling this legend`);\n legend.enabled = false;\n }\n }\n if (_.isNumber(legend.size)) {\n legend.size = Array(legend.labels.length).fill(legend.size);\n }\n // TODO: make legend class descend from Column\n if (['circle', 'rect', 'funkyrect', 'bar'].includes(legend.geom)) {\n legend.numeric = true;\n let extent = [0, 1];\n [legend.min, legend.max] = extent;\n legend.range = legend.max - legend.min;\n legend.scale = d3.scaleLinear().domain(extent);\n }\n });\n return legends;\n}\n","/** @module */\n\nimport * as d3 from 'd3';\n\n\nexport const GEOMS = {\n text: (value, _, column, O, P) => {\n let fill = O.theme.textColor;\n if (column.palette) {\n fill = column.palette(value);\n }\n const el = d3.create('svg:text')\n .attr('dominant-baseline', 'middle')\n .attr('y', P.rowHeight / 2)\n .style('fill', fill)\n .text(value);\n if (O.fontSize) {\n el.attr('font-size', O.fontSize);\n }\n return el;\n },\n\n bar: (value, colorValue, column, O, P) => {\n const fill = column.palette(colorValue);\n value = column.scale(value);\n let width = value * column.width * P.geomSize;\n if (width === 0) {\n width = P.minGeomSize;\n }\n return d3.create('svg:rect')\n .classed('fh-geom', true)\n .attr('x', P.geomPaddingX)\n .attr('y', P.geomPadding)\n .attr('width', width.toFixed(2))\n .attr('height', P.geomSize)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill);\n },\n\n circle: (value, colorValue, column, O, P) => {\n const fill = column.palette(colorValue);\n value = column.scale(value);\n let radius = value * P.geomSize / 2;\n if (radius === 0) {\n radius = P.minGeomSize;\n }\n return d3.create('svg:circle')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('cx', P.rowHeight / 2)\n .attr('cy', P.rowHeight / 2)\n .attr('r', radius.toFixed(2));\n },\n\n rect: (value, colorValue, column, O, P) => {\n const fill = column.palette(colorValue);\n value = column.scale(value);\n return d3.create('svg:rect')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('x', P.geomPaddingX)\n .attr('y', P.geomPadding)\n .attr('width', P.geomSize)\n .attr('height', P.geomSize);\n },\n\n funkyrect: (value, colorValue, column, O, P) => {\n let scaled = column.scale(value);\n const fill = column.palette(colorValue);\n if (scaled < P.funkyMidpoint) {\n // transform value to a 0.0 .. 0.5 range\n value = column.scale.copy()\n .range([0, 0.5])\n .domain([column.min, column.min + column.range * P.funkyMidpoint])(value);\n let radius = (value * 0.9 + 0.1) * P.geomSize - P.geomPadding; // 0.5 for stroke\n if (radius <= 0) {\n radius = P.minGeomSize;\n }\n return d3.create('svg:circle')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('cx', P.rowHeight / 2)\n .attr('cy', P.rowHeight / 2)\n .attr('r', radius.toFixed(2));\n }\n // transform value to a 0.5 .. 1.0 range\n value = column.scale\n .copy()\n .range([0.5, 1])\n .domain([column.min + column.range * P.funkyMidpoint, column.max])(value);\n const cornerSize = (0.9 - 0.8 * value) * P.geomSize;\n return d3.create('svg:rect')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('x', P.geomPaddingX)\n .attr('y', P.geomPadding)\n .attr('width', P.geomSize)\n .attr('height', P.geomSize)\n .attr('rx', cornerSize.toFixed(2))\n .attr('ry', cornerSize.toFixed(2));\n },\n\n pie: (value, _, column, O, P) => {\n let nonZero = 0;\n let nonZeroIdx = 0;\n value.forEach((x, i) => {\n if (x > 0) {\n nonZero += 1;\n nonZeroIdx = i;\n }\n });\n if (nonZero === 1) {\n const fill = column.palette(nonZeroIdx);\n return d3.create('svg:circle')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('cx', P.rowHeight / 2)\n .attr('cy', P.rowHeight / 2)\n .attr('r', P.geomSize / 2);\n }\n\n const arcs = d3.pie().sortValues(null)(value);\n const g = d3.create('svg:g');\n g.classed('fh-geom', true);\n g.selectAll('arcs')\n .data(arcs)\n .enter()\n .append('path')\n .attr('d', d3.arc().innerRadius(0).outerRadius(P.geomSize / 2))\n .attr('fill', (_, i) => {\n return column.palette(i);\n })\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .attr('transform', `translate(${P.rowHeight / 2}, ${P.rowHeight / 2})`);\n return g;\n },\n\n image: function(value, _, column, O, P) {\n return d3.create('svg:image')\n .attr('y', P.geomPadding)\n .attr('href', value)\n .attr('height', P.geomSize)\n .attr('width', column.width)\n .attr('preserveAspectRatio', 'xMidYMid');\n }\n};\n"],"names":["module","exports","d3","$3gsfO","parcelRequire","$2b6e161c9edcf319$var$DEFAULT_OPTIONS","legendFontSize","legendTicks","labelGroupsAbc","colorByRank","theme","oddRowBackground","evenRowBackground","textColor","strokeColor","headerColor","hoverColor","$2b6e161c9edcf319$var$DEFAULT_POSITION_ARGS","rowHeight","rowSpace","rowBigspace","colWidth","colSpace","colBigspace","colAnnotOffset","colAnnotAngle","padding","minGeomSize","funkyMidpoint","$2b6e161c9edcf319$var$PositionArgs","constructor","args","$32BwG","extend","this","underscoreDeprecatedArgs","deprecatedArgs","key","Object","getOwnPropertyNames","underscore","indexOf","newKey","slice","toUpperCase","push","startsWith","length","msg","join","console","warn","calculate","rowSpacePx","rowBigspacePx","colSpacePx","geomSize","geomPadding","geomPaddingX","$2b6e161c9edcf319$var$FunkyHeatmap","data","columnInfo","columnGroups","rowInfo","rowGroups","palettes","legends","positionArgs","options","svg","rowGroupKey","index","group","merge","calculateOptions","renderGroups","rowGroupOrder","undefined","map","_","forEach","d","i","groupInfo","get","Group","renderStripedRows","O","P","rowGroup","nGroups","colorCounter","body","append","classed","attr","renderData","prevColGroup","offset","bodyHeight","size","column","rankedData","maxWidth","firstColumn","geom","numeric","rank","item","id","j","width","groupName","$7SRQm","GEOMS","text","node","getBBox","value","isNaN","label","colorValue","keys","elWidth","el","labelColor","hsl","palette","l","g","create","tooltip","toFixed","replace","datum","s2","colorNames","colorName","select","fontSize","q","widthPx","Math","max","round","bodyWidth","renderHeader","headerHeight","nonZeroRotate","groups","header","labels","abcCounter","$dwZfM","Column","maybeCalculateStats","$lG5F2","assignPalettes","lastCol","groupStart","groupEnd","fill","level1","letter","String","fromCharCode","charCodeAt","style","on","onColumnClick","bind","name","nativeWidth","rotate","height","getBoundingClientRect","center","renderLegends","footerHeight","legendEl","footer","legendXOffset","legend","enabled","offsetY","title","labelsWidth","txt","values","myOffset","rect","funkyrect","geomWidth","geomHeight","circle","colors","range","paletteName","selectAll","enter","col","filter","xPos","img","image","imgWidth","imgHeight","arcs","pie","endAngle","PI","Array","arc","innerRadius","outerRadius","p","centroid","p1","p2","line","legendWidth","footerOffset","hideTooltip","showTooltip","mouse","html","onMouseMove","e","target","parentNode","pointer","document","elBox","comparator","sort","concat","a","b","selectChildren","remove","render","indicateSort","labelBox","sortIndicator","sortState","x","y","rootStyle","listen","$2b6e161c9edcf319$export$2e2bcd8739ae039","scaleColumn","$kwarp","ensureRowData","buildColumnInfo","buildColumnGroups","$afEFj","prepareLegends","heatmap","$eefee52b0cc720a2$export$7154591d43bbde2b","result","columns","$eefee52b0cc720a2$export$3ce631e14ef22c91","objects","obj","isArray","convertDataframe","$9d9dc732a89d186b$export$816b5d811295e6bc","info","overlay","type","str","Number","parseFloat","categorical","extent","min","scale","scaleLinear","domain","colorScale","ascending","descending","$9d9dc732a89d186b$export$caf19947cd7e65b5","$9d9dc732a89d186b$export$e33aac0e3b4702d0","some","Set","allGroups","unused","includes","charAt","$fc81e95648bdd3b9$var$defaultPalettes","numerical","Blues","Greens","Greys","Reds","YlOrBr","Set1","Set2","Set3","Dark2","$fc81e95648bdd3b9$export$e66d39924afea2dc","names","step","scaleOrdinal","$776ad961d55bdd86$export$ba7a034cabddb75f","colInfoPalettes","legendPalettes","missingPalettes","difference","find","isNumber","$5bd757c5633cec0d$export$848bef37f8dddb4a","bar","radius","scaled","copy","cornerSize","nonZero","nonZeroIdx","sortValues"],"version":3,"file":"scIB.c9996616.js.map"} \ No newline at end of file +{"mappings":"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","sources":["d3.js","src/main.js","_.js","src/input_util.js","src/columns.js","src/palettes.js","src/legends.js","src/geoms.js"],"sourcesContent":["module.exports=d3;","import * as d3 from 'd3';\nimport * as _ from 'lodash';\n\nimport { ensureRowData } from './input_util';\nimport { buildColumnInfo, buildColumnGroups, Column } from './columns';\nimport { assignPalettes } from './palettes';\nimport { prepareLegends } from './legends';\nimport { GEOMS } from './geoms';\n\n\n/**\n * @typedef {Object} ColumnData\n * @description A dataframe in column-based format. Each property is a column, represented as an\n * array. All columns are of the same length.\n * @example\n * {\n * 'model': ['Toyota Corolla', 'Fiat 128', 'Honda Civic'],\n * 'mpg': [33.9, 32.4, 30.4],\n * 'weight': [1.835, 2.2, 1.615]\n * }\n */\n\n/**\n * @typedef {Object[]} RowData\n * @description A dataframe in row-based format. Each element is an object with properties. All\n * objects have the same properties.\n * @example\n * [\n * {model: 'Toyota Corolla', mpg: 33.9, weight: 1.835},\n * {model: 'Fiat 128', mpg: 32.4, weight: 2.2},\n * {model: 'Honda Civic', mpg: 30.4, weight: 1.615}\n * ]\n */\n\n/**\n * @typedef {Object} HeatmapOptions\n */\nconst DEFAULT_OPTIONS = {\n legendFontSize: 12,\n legendTicks: [0, 0.2, 0.4, 0.6, 0.8, 1],\n labelGroupsAbc: false,\n colorByRank: false,\n theme: {\n oddRowBackground: 'white',\n evenRowBackground: '#eee',\n textColor: 'black',\n strokeColor: '#555',\n headerColor: 'black',\n hoverColor: '#1385cb'\n }\n};\n\nconst DEFAULT_POSITION_ARGS = {\n rowHeight: 24,\n rowSpace: 0.1,\n rowBigspace: 1,\n colWidth: 24,\n colSpace: 0.1,\n colBigspace: 1,\n colAnnotOffset: 10,\n colAnnotAngle: 30,\n padding: 5,\n minGeomSize: 0.25,\n funkyMidpoint: 0.8\n}\n\n/**\n * Positional options for the heatmap.\n *\n * Configurable options:\n * @property {number} rowHeight - height of a heatmap row, in pixels\n * @property {number} rowSpace - space between rows, as a fraction of rowHeight. Twice the padding\n * @property {number} rowBigspace - space between groups of rows, as a fraction of rowHeight\n * @property {number} colSpace - space between columns, as a fraction of rowHeight. Twice the\n * padding\n * @property {number} colAnnotOffset - offset of column groups from column labels, in pixels\n * @property {number} colAnnotAngle - angle of column labels, in degrees\n * @property {number} padding - padding used in certain places. TODO: document\n * @property {number} minGeomSize - minimum size of a heatmap element, in pixels\n * @property {number} funkyMidpoint - midpoint for funkyrect geom\n *\n * Calculated options:\n * @property {number} rowSpacePx - space between rows, in pixels\n * @property {number} rowBigspacePx - space between groups of rows, in pixels\n * @property {number} colSpacePx - space between columns, in pixels\n * @property {number} geomSize - size of a heatmap element, in pixels\n * @property {number} geomPadding - padding around heatmap elements, in pixels\n * @property {number} geomPaddingX - padding around heatmap elements in the x direction, in pixels\n * @property {number} bodyHeight - height of the heatmap body, in pixels\n * @property {number} bodyWidth - width of the heatmap body, in pixels\n * @property {number} width - width of the heatmap, in pixels, including header and footer\n * @property {number} headerHeight - height of the header, in pixels\n * @property {number} footerHeight - height of the footer, in pixels\n * @property {number} footerOffset - offset of the footer from the left edge of the heatmap, in pixels\n */\nclass PositionArgs {\n /**\n * @param {Object} args - object with positional options\n * @param {number} [args.rowHeight=24] - height of a heatmap row, in pixels\n * @param {number} [args.rowSpace=0.1] - space between rows, as a fraction of rowHeight.\n * Twice the padding\n * @param {number} [args.rowBigspace=1] - space between groups of rows, as a fraction of\n * rowHeight\n * @param {number} [args.colWidth=24] - width of a heatmap column, in pixels.\n * Deprecated, has no effect\n * @param {number} [args.colSpace=0.1] - space between columns, as a fraction of rowHeight.\n * Twice the padding\n * @param {number} [args.colBigspace=1] - space between groups of columns, as a fraction of\n * rowHeight. Currently not used\n * @param {number} [args.colAnnotOffset=3] - offset of column groups from column labels,\n * in pixels\n * @param {number} [args.colAnnotAngle=30] - angle of column labels, in degrees\n * @param {number} [args.padding=5] - padding around heatmap elements, in pixels\n * @param {number} [args.minGeomSize=0.25] - minimum size of a heatmap element, in pixels\n * @param {number} [args.funkyMidpoint=0.8] - midpoint for funkyrect geom\n */\n constructor(args) {\n _.extend(this, DEFAULT_POSITION_ARGS);\n _.extend(this, args);\n let underscoreDeprecatedArgs = [];\n let deprecatedArgs = [];\n for (let key of Object.getOwnPropertyNames(args)) {\n let underscore = key.indexOf('_');\n if (underscore > -1) {\n let newKey;\n while (underscore > -1) {\n newKey = key.slice(0, underscore) + key[underscore + 1].toUpperCase() + key.slice(underscore + 2);\n underscore = key.indexOf('_', underscore + 1);\n }\n this[newKey] = args[key];\n underscoreDeprecatedArgs.push(key);\n key = newKey;\n }\n if (key.startsWith('expand') || key == 'colWidth') {\n deprecatedArgs.push(key);\n }\n }\n if (underscoreDeprecatedArgs.length > 0) {\n let msg = 'Position arguments with underscores were accepted, but are deprecated. Use camelCase instead.';\n msg += ` Found: ${underscoreDeprecatedArgs.join(', ')}`;\n console.warn(msg);\n }\n if (deprecatedArgs.length > 0) {\n let msg = 'The following position arguments are deprecated and have no effect: ';\n msg += deprecatedArgs.join(', ');\n console.warn(msg);\n }\n this.calculate();\n }\n\n /**\n * Pre-calculate needed values based on the options.\n */\n calculate() {\n this.rowSpacePx = this.rowHeight * this.rowSpace;\n this.rowBigspacePx = this.rowHeight * this.rowBigspace;\n this.colSpacePx = this.rowHeight * this.colSpace;\n // assuming square\n this.geomSize = this.rowHeight - this.rowSpacePx;\n this.geomPadding = this.rowSpacePx / 2;\n this.geomPaddingX = this.colSpacePx / 2;\n }\n}\n\n/**\n * Heatmap class\n * @property {PositionArgs} positionArgs\n */\nclass FunkyHeatmap {\n constructor(\n data,\n columnInfo,\n columnGroups,\n rowInfo,\n rowGroups,\n palettes,\n legends,\n positionArgs,\n options,\n svg\n ) {\n this.rowGroupKey = '__group';\n\n this.data = data;\n this.columnInfo = columnInfo;\n this.columnGroups = d3.index(columnGroups, group => group.group);\n this.rowInfo = rowInfo;\n this.rowGroups = d3.index(rowGroups, group => group.group);\n this.palettes = palettes;\n this.legends = legends;\n this.positionArgs = new PositionArgs(positionArgs);\n this.options = _.merge(DEFAULT_OPTIONS, options);\n this.calculateOptions();\n this.svg = svg;\n }\n\n calculateOptions() {\n this.renderGroups = false;\n\n this.rowGroupOrder = [];\n // if we don't have row groups, put all rows in unnamed group\n if (this.rowInfo.length === 0 || this.rowInfo[0].group === undefined) {\n this.rowInfo = this.data.map(_ => { return {group: ''} });\n }\n\n this.data.forEach((d, i) => {\n const group = this.rowInfo[i].group;\n d[this.rowGroupKey] = group;\n if (this.rowGroupOrder.indexOf(group) === -1) {\n this.rowGroupOrder.push(group);\n }\n });\n const group = this.rowInfo[0].group\n const groupInfo = this.rowGroups.get(group);\n if (groupInfo !== undefined && groupInfo.Group !== undefined) {\n this.renderGroups = true;\n }\n }\n\n renderStripedRows() {\n const O = this.options;\n const P = this.positionArgs;\n\n let rowGroup, nGroups = 0, colorCounter = 0;\n this.data.forEach((d, i) => {\n if (this.renderGroups && d[this.rowGroupKey] !== rowGroup) {\n nGroups += 1;\n colorCounter = 0;\n }\n rowGroup = d[this.rowGroupKey];\n this.body.append('rect')\n .classed('row', true)\n .attr('height', P.rowHeight)\n .attr('x', 0)\n .attr('y', (i + nGroups) * P.rowHeight)\n .attr('fill', colorCounter % 2 === 0\n ? O.theme.evenRowBackground\n : O.theme.oddRowBackground);\n colorCounter += 1;\n });\n }\n\n renderData() {\n const O = this.options;\n const P = this.positionArgs;\n\n let offset = 0;\n P.bodyHeight = this.data.length * P.rowHeight;\n if (this.renderGroups) {\n P.bodyHeight += this.rowGroups.size * P.rowHeight;\n }\n let prevColGroup;\n\n this.columnInfo.forEach((column, i) => {\n let maxWidth = 0;\n let padding = P.geomPaddingX;\n let firstColumn = i === 0;\n if (column.geom === 'text' || column.geom === 'bar') {\n padding = P.padding;\n }\n offset += padding;\n if (prevColGroup && column.group && prevColGroup !== column.group) {\n offset += 2 * P.padding;\n }\n let rankedData;\n if (O.colorByRank && column.numeric) {\n rankedData = d3.rank(this.data, item => +item[column.id]);\n }\n let rowGroup, nGroups = 0;\n this.data.forEach((item, j) => {\n let width = 0;\n if (this.renderGroups && item[this.rowGroupKey] !== rowGroup) {\n nGroups += 1;\n }\n if (this.renderGroups && firstColumn && item[this.rowGroupKey] !== rowGroup) {\n let groupName = GEOMS.text(\n this.rowGroups.get(item[this.rowGroupKey]).Group,\n null,\n column,\n O,\n P\n );\n groupName\n .attr('transform', `translate(${offset - padding}, ${(j + nGroups - 1) * P.rowHeight})`)\n .attr('font-weight', 'bold')\n .attr('dominant-baseline', 'hanging');\n this.body.append(() => groupName.node());\n width = groupName.node().getBBox().width;\n }\n rowGroup = item[this.rowGroupKey];\n let value = item[column.id];\n if (value === undefined || value === null || (isNaN(value) && column.numeric)) {\n return;\n }\n let colorValue = value;\n let label;\n if (column.numeric) {\n value = +value;\n }\n if (O.colorByRank && column.numeric) {\n colorValue = rankedData[j];\n }\n if (column.label) {\n label = item[column.label];\n }\n if (GEOMS[column.geom] === undefined) {\n throw `Geom ${column.geom} not implemented. Use one of ${Object.keys(GEOMS).join(', ')}.`;\n }\n let el = GEOMS[column.geom](value, colorValue, column, O, P);\n if (label) {\n const labelColor = d3.hsl(column.palette(colorValue)).l > 0.5\n ? 'black'\n : 'white';\n const g = d3.create('svg:g')\n .classed('fh-geom', true);\n g.append(() => el.classed('fh-geom', false).classed('fh-orig-geom', true).node());\n g.append('text')\n .attr('x', P.rowHeight / 2)\n .attr('y', P.rowHeight / 2)\n .attr('text-anchor', 'middle')\n .attr('dominant-baseline', 'central')\n .attr('fill', labelColor)\n .text(label);\n el = g;\n }\n el.attr('transform', `translate(${offset}, ${(j + nGroups) * P.rowHeight})`);\n if (column.numeric && !label) {\n let tooltip = (+value).toFixed(4);\n tooltip = tooltip.replace(/\\.?0+$/, '');\n el.datum({tooltip: tooltip});\n }\n if (column.geom === 'pie') {\n const s = 'margin: 5px; border-top: 1px solid #aaa; border-left: 1px solid #aaa; font-size: 80%';\n const s2 = 'padding: 2px 4px; border-bottom: 1px solid #aaa; border-right: 1px solid #aaa';\n let tooltip = `${column.palette.colorNames.map((colorName, i) => {\n return ``;\n }).join('')}
${colorName}:${value[i]}
`;\n el.datum({tooltip: tooltip});\n }\n this.body.append(() => el.node());\n let elWidth;\n if (label) {\n elWidth = el.select('.fh-orig-geom').node().getBBox().width;\n } else {\n elWidth = el.node().getBBox().width;\n }\n if (column.geom === 'image') {\n elWidth = column.width;\n }\n if (elWidth > width) {\n width = elWidth;\n }\n if (width > maxWidth) {\n maxWidth = width;\n }\n if (label) {\n label = el.select('text');\n let fontSize = 100;\n for (let q = 0; q < 8; q++) {\n const { width } = label.node().getBBox();\n if (width > P.geomSize - P.geomPaddingX * 2) {\n fontSize -= 5;\n label.attr('font-size', `${fontSize}%`);\n } else {\n break;\n }\n }\n }\n });\n if (column.geom === 'bar') {\n maxWidth = P.geomSize * column.width + P.geomPadding;\n this.body.append('line')\n .attr('x1', offset + maxWidth)\n .attr('x2', offset + maxWidth)\n .attr('y1', this.renderGroups ? P.rowHeight : 0)\n .attr('y2', P.bodyHeight)\n .attr('stroke', O.theme.strokeColor)\n .attr('stroke-dasharray', '5 5')\n .attr('opacity', 0.5);\n }\n column.widthPx = Math.max(maxWidth, P.rowHeight);\n column.widthPx = Math.round(column.widthPx);\n column.offset = offset;\n offset += column.widthPx + padding;\n prevColGroup = column.group;\n });\n P.bodyWidth = offset + P.colSpacePx;\n }\n\n renderHeader() {\n const O = this.options;\n const P = this.positionArgs;\n\n let headerHeight = 0;\n let bodyWidth = 0;\n let nonZeroRotate = false;\n const groups = this.header.append('g');\n const labels = this.header.append('g')\n .attr('transform', `translate(0, ${P.rowHeight + P.colAnnotOffset})`);\n\n const columnGroups = d3.group(this.columnInfo, column => column.group);\n let abcCounter = 0;\n columnGroups.forEach((group, groupName) => {\n if (!groupName) {\n return;\n }\n const groupInfo = this.columnGroups.get(groupName);\n const column = new Column({\n id: '_group',\n palette: groupInfo.palette\n }, 1);\n column.maybeCalculateStats(null, false);\n assignPalettes([column], this.palettes);\n const lastCol = group[group.length - 1];\n const groupStart = group[0].offset;\n const groupEnd = lastCol.offset + lastCol.widthPx + P.geomPadding;\n const fill = column.palette == 'none' && 'transparent' || column.palette(0.5);\n groups.append('rect')\n .attr('x', groupStart)\n .attr('y', 0)\n .attr('width', groupEnd - groupStart)\n .attr('height', P.rowHeight)\n .attr('fill', fill)\n .attr('opacity', 0.25);\n const text = groups.append('text')\n .attr('x', groupStart + (groupEnd - groupStart) / 2)\n .attr('y', P.rowHeight / 2)\n .attr('text-anchor', 'middle')\n .attr('dominant-baseline', 'central')\n .attr('fill', O.theme.headerColor)\n .text(groupInfo.level1);\n if (O.fontSize) {\n text.attr('font-size', O.fontSize);\n }\n if (O.labelGroupsAbc) {\n const letter = String.fromCharCode(\"a\".charCodeAt(0) + abcCounter);\n const text = groups.append('text')\n .attr('x', groupStart + P.padding)\n .attr('y', P.rowHeight / 2)\n .attr('dominant-baseline', 'central')\n .attr('fill', O.theme.headerColor)\n .text(`${letter})`);\n if (O.fontSize) {\n text.attr('font-size', O.fontSize);\n }\n }\n abcCounter += 1;\n });\n\n this.columnInfo.forEach((column, i) => {\n const el = labels.append('g')\n .attr('transform', `rotate(${-P.colAnnotAngle})`)\n .classed(`column-${i}`, true);\n el.append('text')\n .attr('x', 0)\n .attr('y', 0)\n .attr('font-size', O.fontSize)\n .style('fill', O.theme.textColor)\n .style('cursor', 'pointer')\n .datum(column)\n .on('click', this.onColumnClick.bind(this))\n .on('mouseenter', () => {\n el.style('text-decoration', 'underline dashed')\n .style('fill', O.theme.hoverColor)\n })\n .on('mouseleave', () => {\n el.style('text-decoration', '').style('fill', O.theme.textColor)\n })\n .text(column.name);\n const nativeWidth = el.node().getBBox().width;\n if (!nonZeroRotate && nativeWidth < column.widthPx - 2 * P.padding) {\n column.rotate = false;\n } else {\n column.rotate = true;\n nonZeroRotate = true;\n }\n const { width, height } = el.node().getBoundingClientRect();\n if (height > headerHeight) {\n headerHeight = height;\n }\n if (column.offset + column.widthPx / 2 + width > bodyWidth) {\n bodyWidth = column.offset + column.widthPx / 2 + width + P.padding;\n }\n });\n this.columnInfo.forEach((column, i) => {\n let center = column.offset + column.widthPx / 2;\n let rotate = column.rotate ? -P.colAnnotAngle : 0;\n this.header.select(`.column-${i}`)\n .attr(\n 'transform',\n `translate(${center}, ${headerHeight - 2 * P.padding}) rotate(${rotate})`\n );\n if (!column.rotate) {\n labels.select(`.column-${i} text`)\n .attr('text-anchor', 'middle');\n } else {\n labels.append('line')\n .attr('x1', center)\n .attr('x2', center)\n .attr('y1', headerHeight - 2)\n .attr('y2', headerHeight - 2 - P.padding)\n .attr('stroke', O.theme.strokeColor);\n }\n });\n P.width = bodyWidth;\n P.headerHeight = headerHeight + P.rowHeight + P.colAnnotOffset;\n }\n\n renderLegends() {\n const O = this.options;\n const P = this.positionArgs;\n\n // go through this.legends and render them sequentially\n\n let footerHeight = 0;\n const legendEl = this.footer.append('g');\n let legendXOffset = 0;\n let offset = 0;\n let funkyrectPresent = false;\n\n this.legends.forEach(legend => {\n if (!legend.enabled) {\n return;\n }\n const rowHeight = O.legendFontSize;\n let offsetY = rowHeight * 2 + P.padding;\n const el = legendEl.append('g');\n el.attr('transform', `translate(${offset}, 0)`);\n el.append('text')\n .attr('x', 0)\n .attr('y', offsetY)\n .attr('font-size', O.legendFontSize)\n .style('fill', O.theme.textColor)\n .text(legend.title);\n\n if (legend.geom === 'text') {\n let labelsWidth = 0;\n legend.labels.forEach((label, i) => {\n const txt = el.append('text')\n .attr('x', P.padding)\n .attr('y', offsetY + (i + 1) * (rowHeight + P.padding))\n .attr('font-size', O.legendFontSize)\n .style('fill', O.theme.textColor)\n .text(label);\n const { width } = txt.node().getBBox();\n if (width > labelsWidth) {\n labelsWidth = width;\n }\n });\n legend.values.forEach((value, i) => {\n el.append('text')\n .attr('x', P.padding * 2 + labelsWidth)\n .attr('y', offsetY + (i + 1) * (rowHeight + P.padding))\n .attr('font-size', O.legendFontSize)\n .style('fill', O.theme.textColor)\n .text(value);\n });\n }\n if (legend.geom === 'rect') {\n let myOffset = 0;\n legend.values.forEach((colorValue, i) => {\n const label = legend.labels[i];\n const size = legend.size[i];\n const geom = GEOMS.rect(size, colorValue, legend, O, P);\n geom.attr('transform', `translate(${myOffset}, ${offsetY + P.padding})`);\n el.append(() => geom.node());\n el.append('text')\n .attr('x', myOffset + P.rowHeight / 2)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n myOffset += size * P.geomSize + P.padding;\n });\n }\n if (legend.geom === 'funkyrect') {\n let myOffset = 0;\n legend.labels.forEach((label, i) => {\n const colorValue = legend.values[i];\n const size = legend.size[i];\n const geom = GEOMS.funkyrect(size, colorValue, legend, O, P);\n el.append(() => geom.node());\n const { width: geomWidth, height: geomHeight } = geom.node().getBBox();\n geom.attr(\n 'transform',\n `translate(${myOffset}, ${offsetY + P.rowHeight / 2 - geomHeight / 2})`\n );\n el.append('text')\n .attr('x', myOffset + P.rowHeight / 2)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n myOffset += geomWidth + P.padding;\n });\n }\n if (legend.geom === 'circle') {\n let myOffset = 0;\n legend.labels.forEach((label, i) => {\n const colorValue = legend.values[i];\n const size = legend.size[i];\n const geom = GEOMS.circle(size, colorValue, legend, O, P);\n el.append(() => geom.node());\n const { width: geomWidth, height: geomHeight } = geom.node().getBBox();\n geom.attr(\n 'transform',\n `translate(${myOffset}, ${offsetY + P.rowHeight / 2 - geomHeight / 2})`\n );\n el.append('text')\n .attr('x', myOffset + P.rowHeight / 2)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n myOffset += geomWidth + P.padding;\n });\n }\n if (legend.geom === 'bar') {\n const colors = legend.palette.range();\n\n const grad = this.svg.append('defs')\n .append('linearGradient')\n .attr('id', `grad_${legend.paletteName}`)\n .attr('x1', '0%')\n .attr('x2', '100%')\n .attr('y1', '0%')\n .attr('y2', '0%');\n\n grad.selectAll('stop')\n .data(colors)\n .enter()\n .append('stop')\n .style('stop-color', function(d) { return d; })\n .attr('offset', function(d, i) {\n return 100 * (i / (colors.length - 1)) + '%';\n });\n\n // A bit ugly to get the width of the column mapped to this legend\n const col = this.columnInfo.filter((column) =>\n column.geom === 'bar' && column.paletteName === legend.paletteName\n )[0];\n\n el.append('rect')\n .attr('x', P.padding)\n .attr('y', offsetY + P.padding)\n .attr('width', col.widthPx)\n .attr('height', P.rowHeight)\n .style('fill', `url(#grad_${legend.paletteName})`)\n .attr('stroke', 'black')\n .attr('stroke-width', 0.5);\n\n legend.labels.forEach((label, i) => {\n if (label === '') {\n return;\n }\n const value = legend.values[i];\n const xPos = P.padding + col.widthPx * value;\n if (value > 0 && value < 1) {\n el.append('line')\n .attr('x1', xPos)\n .attr('x2', xPos)\n .attr('y1', offsetY + P.rowHeight + P.padding)\n .attr('y2', offsetY + P.rowHeight)\n .attr('stroke', 'black')\n .attr('stroke-width', 0.5);\n }\n el.append('text')\n .attr('x', xPos)\n .attr('y', offsetY + P.rowHeight + rowHeight + P.padding)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'middle')\n .style('fill', O.theme.textColor)\n .text(label);\n });\n }\n if (legend.geom === 'image') {\n legend.values.forEach((value, i) => {\n const label = legend.labels[i];\n const img = GEOMS.image(value, null, {width: legend.size[i]}, O, P);\n img.attr('transform', `translate(0, ${offsetY + P.padding})`);\n el.append(() => img.node());\n const { width: imgWidth, height: imgHeight } = img.node().getBBox();\n el.append('text')\n .attr('x', imgWidth + P.padding)\n .attr('y', offsetY + P.padding + imgHeight / 2)\n .attr('font-size', O.legendFontSize)\n .attr('text-anchor', 'left')\n .attr('dominant-baseline', 'central')\n .style('fill', O.theme.textColor)\n .text(label);\n offsetY += imgHeight + P.padding;\n });\n }\n if (legend.geom === 'pie') {\n const arcs = d3.pie().endAngle(Math.PI)(Array(legend.palette.colorNames.length).fill(1));\n const g = el.append('g');\n g.attr('transform', `translate(0, ${offsetY + P.padding + P.rowHeight})`);\n g.selectAll('arcs')\n .data(arcs)\n .enter()\n .append('path')\n .attr('d', d3.arc().innerRadius(0).outerRadius(P.geomSize / 2))\n .attr('fill', (_, i) => {\n return legend.palette(i);\n })\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .attr('transform', `translate(${P.geomSize / 2 + P.geomPadding - 0.5}, 0)`);\n\n g.selectAll('text')\n .data(arcs)\n .enter()\n .append('text')\n .text((_, i) => legend.palette.colorNames[i])\n .attr('font-size', O.legendFontSize)\n .attr('dominant-baseline', 'central')\n .style('fill', O.theme.textColor)\n .attr('transform', d => {\n const p = d3.arc().innerRadius(P.geomSize / 2).outerRadius(P.geomSize).centroid(d);\n p[0] += P.geomSize / 2 + 4 * P.geomPadding;\n return `translate(${p})`;\n });\n\n g.selectAll('lines')\n .data(arcs)\n .enter()\n .append('path')\n .attr('d', d => {\n const p1 = d3.arc().innerRadius(P.geomSize / 2).outerRadius(P.geomSize / 2 + 5).centroid(d);\n const p2 = d3.arc().innerRadius(P.geomSize / 2).outerRadius(P.geomSize - 5).centroid(d);\n p1[0] += P.geomSize / 2 + P.geomPadding;\n p2[0] += P.geomSize / 2 + 3 * P.geomPadding;\n return d3.line()([p1, p2]);\n })\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 0.5);\n }\n\n const { width } = el.node().getBBox();\n offset += width + P.padding * 2;\n });\n\n const { height } = legendEl.node().getBBox();\n if (height > footerHeight) {\n footerHeight = height;\n }\n let legendWidth = offset - P.padding;\n if (funkyrectPresent) {\n legendWidth += P.geomSize;\n }\n if (legendXOffset + legendWidth > P.width) {\n if (legendWidth <= P.width) { // try to right-justify the legend\n legendXOffset = P.width - legendWidth;\n } else {\n legendXOffset = 0;\n P.width = offset;\n }\n }\n P.footerOffset = legendXOffset;\n P.footerHeight = footerHeight + P.rowHeight;\n }\n\n hideTooltip() {\n if (this.tooltip) {\n this.tooltip.style(\"display\", \"none\");\n }\n }\n\n showTooltip(mouse, text) {\n if (this.tooltip === undefined) {\n this.tooltip = d3.select(\"body\")\n .append(\"div\")\n .style(\"z-index\", 2000)\n .style(\"position\", \"absolute\")\n .style(\"background-color\", \"#333\")\n .style(\"color\", \"white\")\n .style(\"border\", \"solid\")\n .style(\"border-width\", \"1px\")\n .style(\"border-radius\", \"5px\")\n .style(\"padding\", \"3px 5px\")\n .style(\"display\", \"none\");\n }\n\n const offset = 10;\n this.tooltip\n .html(text)\n .style(\"top\", mouse[1] + 2 * offset + \"px\")\n .style(\"left\", mouse[0] + offset + \"px\")\n .style(\"display\", \"block\");\n }\n\n onMouseMove(e) {\n if (e.target) {\n let el = d3.select(e.target);\n while (el.classed('fh-geom') === false && el.node() != this.svg.node()) {\n el = d3.select(el.node().parentNode);\n }\n const d = el.datum();\n if (d && d.tooltip) {\n const mouse = d3.pointer(e, document.body);\n this.showTooltip(mouse, d.tooltip);\n return;\n }\n }\n this.hideTooltip();\n }\n\n onColumnClick(e) {\n const el = d3.select(e.target);\n const elBox = el.node().getBBox();\n const column = el.datum();\n const comparator = column.sort();\n let data = d3.group(this.data, d => d[this.rowGroupKey]);\n data = [].concat(...this.rowGroupOrder.map(group => d3.sort(data.get(group), (a, b) => {\n [a, b] = [a[column.id], b[column.id]];\n if (column.numeric) {\n [a, b] = [+a, +b];\n }\n return comparator(a, b);\n })));\n this.data = data;\n this.svg.selectChildren().remove();\n this.render();\n\n this.indicateSort(column, elBox);\n }\n\n indicateSort(column, labelBox) {\n const O = this.options;\n const P = this.positionArgs;\n\n this.sortIndicator = this.header.append(\"text\")\n .attr('font-size', 12)\n .attr('fill', O.theme.hoverColor);\n if (column.sortState === \"asc\") {\n this.sortIndicator.text('↑');\n } else {\n this.sortIndicator.text('↓');\n }\n this.sortIndicator\n .attr('text-anchor', 'right')\n .attr('dominant-baseline', 'text-bottom');\n let x = column.offset + column.widthPx / 2 - 2 * P.padding;\n let y = P.headerHeight - P.padding;\n if (!column.rotate) {\n x -= labelBox.width / 2;\n y -= labelBox.height / 2;\n this.sortIndicator.attr('dominant-baseline', 'central');\n }\n this.sortIndicator\n .attr('x', x)\n .attr('y', y);\n }\n\n render() {\n this.header = this.svg.append(\"g\");\n this.body = this.svg.append(\"g\");\n this.footer = this.svg.append(\"g\");\n\n this.renderStripedRows();\n this.renderData();\n this.renderHeader();\n this.renderLegends();\n\n const O = this.options;\n const P = this.positionArgs;\n\n this.svg.attr('width', P.width);\n this.svg.attr('height', P.bodyHeight + P.headerHeight + P.footerHeight);\n if (this.renderGroups) {\n this.header.attr('transform', `translate(0, ${P.rowHeight})`);\n }\n this.body.selectAll('.row').attr('width', P.bodyWidth);\n this.body.attr(\"transform\", `translate(0, ${P.headerHeight})`);\n this.footer.attr('transform', `translate(${P.footerOffset}, ${P.headerHeight + P.bodyHeight})`);\n this.svg.attr('style', '');\n if (O.rootStyle) {\n this.svg.attr('style', O.rootStyle);\n }\n }\n\n listen() {\n this.svg.on(\"mousemove\", this.onMouseMove.bind(this));\n }\n};\n\n\n/**\n * The main entry point for the library. Takes data and various configuration options and returns\n * an SVG element with the heatmap.\n *\n * @param {ColumnData|RowData} data - data to plot, usually d3-fetch output.\n * @param {ColumnData|module:columns~ColumnInfo[]} columnInfo - information about how the columns\n * should be displayed. If not specified, all columns from `data` will be displayed.\n * See {@link module:columns~ColumnInfo}, {@link module:columns.Column}.\n * @param {ColumnData|RowData} rowInfo - information about how the rows should be displayed\n * @param {ColumnData|RowData} columnGroups - information about how to group columns\n * @param {ColumnData|RowData} rowGroups - information about how to group rows\n * @param {Object} palettes - mapping of names to palette colors, see {@link module:palettes.assignPalettes}\n * @param {ColumnData|RowData} legends - a list of legends to add to the plot\n * @param {Object} positionArgs - positioning arguments, see {@link PositionArgs}\n * @param {Object} options - options for the heatmap, see {@link HeatmapOptions}\n * @param {boolean} scaleColumn - whether to apply min-max scaling to numerical\n * columns. Defaults to true\n *\n * @returns {SVGElement} - the SVG element containing the heatmap\n *\n */\nfunction funkyheatmap(\n data,\n columnInfo,\n rowInfo = [],\n columnGroups = [],\n rowGroups = [],\n palettes = {},\n legends = [],\n positionArgs = {},\n options = {},\n scaleColumn = true\n) {\n [data, columnInfo, columnGroups, rowInfo, rowGroups, legends] = ensureRowData(\n data, columnInfo, columnGroups, rowInfo, rowGroups, legends\n );\n columnInfo = buildColumnInfo(data, columnInfo, scaleColumn, options.colorByRank);\n columnGroups = buildColumnGroups(columnGroups, columnInfo);\n legends = prepareLegends(legends, palettes, columnInfo);\n assignPalettes(columnInfo, palettes);\n assignPalettes(legends, palettes);\n\n const svg = d3.select('body')\n .append('svg')\n .classed('funkyheatmap', true)\n .style('visibility', 'hidden')\n .style('position', 'absolute')\n .style('left', '-2000px');\n const heatmap = new FunkyHeatmap(\n data,\n columnInfo,\n columnGroups,\n rowInfo,\n rowGroups,\n palettes,\n legends,\n positionArgs,\n options,\n svg\n );\n heatmap.render();\n heatmap.listen();\n heatmap.svg.remove();\n\n return heatmap.svg.node();\n}\n\nexport default funkyheatmap;\n","module.exports=_;","/** @module */\n\n/**\n * Converts object-based dataframe to array-based dataframe.\n *\n * @param {ColumnData} data - an object with each property representing dataframe column as an array.\n * Columns are of the same length\n * @returns {RowData} - array of objects with properties corresponding to columns\n */\nexport function colToRowData(data) {\n const columns = Object.getOwnPropertyNames(data);\n const size = data[columns[0]].length;\n const result = [];\n for (let i = 0; i < size; i++) {\n let item = {};\n for (let column of columns) {\n item[column] = data[column][i];\n }\n result.push(item);\n }\n return result;\n};\n\n/**\n * Converts array-based dataframe to object-based dataframe.\n *\n * @param {RowData} data - an array of objects with properties\n * @returns {ColumnData} - object with each property representing dataframe column as an array,\n * values are preserved in the same order as in the input array\n */\nexport function rowToColData(data) {\n const result = {};\n const columns = Object.getOwnPropertyNames(data[0]);\n for (let column of columns) {\n result[column] = data.map(item => item[column]);\n }\n return result;\n};\n\n/**\n * Convenience function to convert potential column-based dataframes to row-based dataframes.\n *\n * @param {Object[]} objects - potential objects to convert to row-based dataframes. Only converts\n * objects, skips arrays\n * @returns {Object[]} - array of converted objects\n */\nexport function ensureRowData(...objects) {\n return objects.map(obj => {\n if (obj && !Array.isArray(obj)) {\n obj = convertDataframe(obj);\n }\n return obj;\n });\n};\n","/** @module */\n\nimport * as d3 from 'd3';\n\n/**\n * @typedef {Object} ColumnInfo\n * @description Information about a dataframe column and how to display it.\n * @property {string} id - column id in the dataset. Required.\n */\n\n/**\n * @class\n */\nexport class Column {\n constructor(info, value) {\n ({\n id: this.id,\n name: this.name,\n geom: this.geom,\n group: this.group,\n palette: this.palette,\n width: this.width,\n label: this.label,\n overlay: this.overlay,\n options: this.options\n } = info);\n\n let type = typeof value;\n // geom text is always categorical\n if (isNumeric(value) && this.geom !== 'text') {\n type = 'number';\n this.numeric = true;\n this.categorical = false;\n } else {\n this.numeric = false;\n this.categorical = true;\n }\n\n if (this.name === undefined) {\n this.name = this.id;\n }\n\n if (this.options === undefined) {\n this.options = {};\n }\n\n if (this.options.width !== undefined && this.width === undefined) {\n this.width = this.options.width;\n }\n if (this.options.palette !== undefined && this.palette === undefined) {\n this.palette = this.options.palette;\n }\n\n if (this.geom === undefined) {\n if (type === 'number') {\n this.geom = 'funkyrect';\n } else {\n this.geom = 'text';\n }\n }\n\n if (this.palette === undefined) {\n if (this.geom === 'pie') {\n this.palette = 'categorical';\n }\n if (this.numeric) {\n this.palette = 'numerical';\n }\n }\n\n if (this.width === undefined) {\n if (this.geom === 'bar') {\n this.width = 4;\n }\n }\n\n if (this.geom === 'image' && this.width === undefined) {\n throw `Please, specify width for column with geom=image`;\n }\n\n this.sortState = null;\n }\n\n maybeCalculateStats(data, scaleColumn, colorByRank) {\n let extent = [0, 1];\n if (scaleColumn) {\n extent = d3.extent(data, i => +i[this.id]);\n }\n [this.min, this.max] = extent;\n this.range = this.max - this.min;\n this.scale = d3.scaleLinear().domain(extent);\n if (colorByRank) {\n this.colorScale = d3.scaleLinear().domain([0, data.length - 1]);\n }\n }\n\n sort() {\n if (this.sortState === \"desc\") {\n this.sortState = \"asc\";\n return d3.ascending;\n }\n this.sortState = \"desc\";\n return d3.descending;\n }\n}\n\n/**\n * Assemble all column information needed for drawing\n *\n * @param {RowData} data - dataset\n * @param {module:columns~ColumnInfo[]} columnInfo - properties of the columns for drawing, which we will modify\n * @param {boolean} scaleColumn - whether to min-max scale data per column\n * @param {boolean} colorByRank - whether to color by rank per column instead of by value\n */\nexport function buildColumnInfo(data, columnInfo, scaleColumn, colorByRank) {\n const item = data[0];\n if (columnInfo === undefined || columnInfo.length === 0) {\n console.info(\"No column info specified, assuming all columns are to be displayed.\");\n columnInfo = Object.getOwnPropertyNames(item).map(id => {\n return {id: id}\n });\n }\n return columnInfo.map(info => {\n let column = info.id;\n if (column === undefined) {\n throw \"Column info must have id field corresponding to the column in the data\";\n }\n column = new Column(info, item[column]);\n column.maybeCalculateStats(data, scaleColumn, colorByRank);\n return column;\n });\n};\n\n/**\n * Check and prepare column group information\n *\n * @param {Object[]} columnGroups - information about column groups, empty array if not specified\n * @param {Object[]} columnInfo - information about columns, to crosscheck\n * @returns {Object[]} - column groups with defaults filled in, if necessary\n */\nexport function buildColumnGroups(columnGroups, columnInfo) {\n if (columnGroups.length === 0 && columnInfo.some(i => i.group)) {\n console.info(\"No column groups specified, but some columns have group, building automatically\");\n columnGroups = columnInfo\n .filter(i => i.group)\n .map(i => i.group);\n columnGroups = [...new Set(columnGroups)];\n columnGroups = columnGroups.map(group => {\n return {group: group}\n });\n }\n if (columnGroups.length === 0) {\n return [];\n }\n columnInfo.forEach(i => {\n if (i.group && !columnGroups.some(g => g.group === i.group)) {\n throw `Column group ${i.group} is not specified in columnGroups`;\n }\n });\n let allGroups = columnInfo.filter(i => i.group).map(i => i.group);\n let unused = columnGroups.filter(i => !allGroups.includes(i.group));\n if (unused.length > 0) {\n console.warn(`Unused column groups: ${unused.map(i => i.group).join(', ')}`);\n }\n\n if (columnGroups[0].palette === undefined) {\n console.info(\"Column groups did not specify `palette`. Assuming no colours\")\n columnGroups.forEach(i => {\n i.palette = 'none';\n });\n }\n columnGroups.forEach(i => {\n if (i.palette === undefined) {\n throw `Column group ${i.group} did not specify palette`;\n }\n });\n\n if (columnGroups[0].level1 === undefined) {\n console.info(\"Column groups did not specify `level1`. Using group id as level1\")\n columnGroups.forEach(i => {\n i.level1 = i.group.charAt(0).toUpperCase() + i.group.slice(1);\n });\n }\n\n return columnGroups;\n};\n\nfunction isNumeric(str) {\n if (typeof str === 'number') return true;\n if (typeof str !== 'string') return false;\n // use type coercion to parse the _entirety_ of the string\n // (`parseFloat` alone does not do this)...\n return !Number.isNaN(str)\n && !Number.isNaN(parseFloat(str)); // ...and ensure strings of whitespace fail\n}\n","/** @module */\n\nimport * as d3 from 'd3';\n\n/**\n * Default palettes for numerical and categorical data. See source for the colors.\n * @constant {Object}\n * @property {Object} numerical - palettes for numerical data. Default is Blues\n * @property {Object} categorical - palettes for categorical data. Default is Set1\n */\nconst defaultPalettes = {\n numerical: {\n Blues: [\n \"#011636\", \"#08306B\", \"#08519C\", \"#2171B5\", \"#4292C6\", \"#6BAED6\", \"#9ECAE1\", \"#C6DBEF\",\n \"#DEEBF7\", \"#F7FBFF\"\n ],\n Greens: [\n \"#00250f\", \"#00441B\", \"#006D2C\", \"#238B45\", \"#41AB5D\", \"#74C476\", \"#A1D99B\", \"#C7E9C0\",\n \"#E5F5E0\"\n ],\n Greys: [\n \"#000000\", \"#252525\", \"#525252\", \"#737373\", \"#969696\", \"#BDBDBD\", \"#D9D9D9\", \"#F0F0F0\"\n ],\n Reds: [\n \"#CB181D\", \"#EF3B2C\", \"#FB6A4A\", \"#FC9272\", \"#FCBBA1\", \"#FEE0D2\", \"#FFF5F0\"\n ],\n YlOrBr: [\n \"#EC7014\", \"#FE9929\", \"#FEC44F\", \"#FEE391\", \"#FFF7BC\", \"#FFFFE5\"\n ]\n },\n categorical: {\n Set1: [\n \"#E41A1C\",\"#377EB8\",\"#4DAF4A\",\"#984EA3\",\"#FF7F00\",\"#FFFF33\",\"#A65628\",\"#F781BF\",\n \"#999999\"\n ],\n Set2: [\n \"#66C2A5\",\"#FC8D62\",\"#8DA0CB\",\"#E78AC3\",\"#A6D854\",\"#FFD92F\",\"#E5C494\",\"#B3B3B3\"\n ],\n Set3: [\n \"#8DD3C7\", \"#FFFFB3\", \"#BEBADA\", \"#FB8072\", \"#80B1D3\", \"#FDB462\", \"#B3DE69\", \"#FCCDE5\",\n \"#D9D9D9\", \"#BC80BD\", \"#CCEBC5\", \"#FFED6F\"\n ],\n Dark2: [\n \"#1B9E77\",\"#D95F02\",\"#7570B3\",\"#E7298A\",\"#66A61E\",\"#E6AB02\",\"#A6761D\",\"#666666\"\n ]\n }\n};\n\n/**\n *\n * @param {module:columns.Column[]} columnInfo - list of Column objects with information\n * @param {Object} palettes - mapping of names to palette colors\n * possible options for the palette colors are:\n * - name of a built-in palette (e.g. Blues, Set1…)\n * - `Array` of colors as strings\n * - `Object` with keys `colors` and `names` - important for categorical data\n */\nexport function assignPalettes(columnInfo, palettes) {\n palettes = { numerical: \"Blues\", categorical: \"Set1\", ...palettes };\n columnInfo.forEach(column => {\n if (column.palette && column.palette != 'none') {\n column.paletteName = column.palette;\n let name = palettes[column.palette];\n if (name === undefined) { // fallback\n name = column.palette;\n }\n let colors;\n let colorNames;\n if (defaultPalettes.numerical[name]) {\n colors = defaultPalettes.numerical[name];\n } else if (defaultPalettes.categorical[name]) {\n colors = defaultPalettes.categorical[name];\n } else if (Array.isArray(name)) {\n const item = name[0];\n if (typeof item === 'string' || item instanceof String) {\n colors = name;\n } else {\n throw `Palette definition ${name} is not recognized. Expected are: array of colors, array of color-name pairs.`;\n }\n } else if (Array.isArray(name.colors) && Array.isArray(name.names)) {\n colors = name.colors;\n colorNames = name.names;\n } else {\n const names = [\n ...Object.getOwnPropertyNames(defaultPalettes.numerical),\n ...Object.getOwnPropertyNames(defaultPalettes.categorical)\n ];\n throw `Palette ${name} not defined. Use one of ${names.join(', ')}.`;\n }\n\n if (column.numeric) {\n let scale = column.scale;\n if (column.colorScale) {\n scale = column.colorScale;\n }\n const [min, max] = scale.domain();\n const step = (max - min) / (colors.length - 1);\n const domain = [...d3.range(min, max, step), max];\n column.palette = d3.scaleLinear().domain(domain).range(colors);\n }\n // TODO: replace with categorical\n if (column.geom === 'pie' || column.geom === 'text') {\n const domain = d3.range(colors.length);\n column.palette = d3.scaleOrdinal().domain(domain).range(colors);\n column.palette.colors = colors;\n column.palette.colorNames = colorNames;\n }\n }\n });\n};\n","/** @module */\n\nimport * as _ from 'lodash';\n\n/**\n *\n * @param {Object[]|undefined} legends - user provided legend configuration\n * @param {Object} palettes - mapping of names to palette colors\n * @param {Object[]} columnInfo - user provided information on columns\n */\nexport function prepareLegends(legends, palettes, columnInfo) {\n if (legends === undefined) {\n console.info('No legends provided, will infer automatically');\n legends = [];\n }\n\n const colInfoPalettes = [];\n columnInfo.forEach(i => {\n if (i.palette && colInfoPalettes.indexOf(i.palette) === -1) {\n colInfoPalettes.push(i.palette);\n }\n });\n const legendPalettes = [];\n legends.forEach(l => {\n if (l.palette && legendPalettes.indexOf(l.palette) === -1) {\n legendPalettes.push(l.palette);\n }\n });\n\n const missingPalettes = _.difference(colInfoPalettes, legendPalettes);\n if (missingPalettes.length > 0) {\n let msg = 'These palettes are missing in legends, adding legends for them: ';\n msg += missingPalettes.join(', ');\n console.info(msg);\n missingPalettes.forEach(p => {\n legends.push({\n title: p,\n palette: p,\n enabled: true,\n });\n });\n }\n\n legends.forEach(legend => {\n if (legend.enabled === undefined) {\n legend.enabled = true;\n }\n if (legend.title === undefined) {\n legend.title = legend.palette;\n }\n if (legend.geom === undefined) {\n console.info(`Legend \\`${legend.title}\\` did not specify geom, copying from column info`);\n const col = columnInfo.find(i => i.palette === legend.palette);\n legend.geom = col.geom;\n }\n if (legend.labels === undefined) {\n console.info(`Legend \\`${legend.title}\\` did not specify labels, inferring from column info`);\n if (legend.geom === 'pie') {\n const pal = palettes[legend.palette];\n if (pal.names === undefined) {\n console.warn(`Cannot infer labels for legend \\`${legend.title}\\`, please provide color names in palette. Disabling this legend`);\n legend.enabled = false;\n }\n legend.labels = palettes[legend.palette].names;\n } else if (['circle', 'rect', 'funkyrect', 'bar'].includes(legend.geom)) {\n // TODO: get from default options\n legend.labels = ['0', '', '0.2', '', '0.4', '', '0.6', '', '0.8', '', '1'];\n } else if (legend.geom === 'text' || legend.geom === 'image') {\n console.warn(`Cannot infer labels for legend \\`${legend.title}\\` of type ${legend.geom}, please provide labels. Disabling this legend`);\n legend.enabled = false;\n }\n }\n if (legend.size === undefined) {\n console.info(`Legend \\`${legend.title}\\` did not specify size, inferring from column info`);\n if (legend.geom === 'circle' || legend.geom === 'funkyrect') {\n legend.size = [...d3.range(0, legend.labels.length - 1).map(\n (i) => i / (legend.labels.length - 1)\n ), 1];\n } else if (legend.geom === 'rect' || legend.geom === 'bar') {\n legend.size = 1;\n } else if (legend.geom === 'image') {\n throw `Please specify size (width) for image legend \\`${legend.title}\\``;\n }\n }\n if (legend.values === undefined) {\n if (['circle', 'rect', 'funkyrect', 'bar'].includes(legend.geom)) {\n legend.values = [...d3.range(0, legend.labels.length - 1).map(\n (i) => i / (legend.labels.length - 1)\n ), 1];\n }\n if (legend.enabled && (legend.geom === 'image' || legend.geom === 'text')) {\n console.warn(`Cannot infer values for legend \\`${legend.title}\\` of type ${legend.geom}, please provide values. Disabling this legend`);\n legend.enabled = false;\n }\n }\n if (_.isNumber(legend.size)) {\n legend.size = Array(legend.labels.length).fill(legend.size);\n }\n // TODO: make legend class descend from Column\n if (['circle', 'rect', 'funkyrect', 'bar'].includes(legend.geom)) {\n legend.numeric = true;\n let extent = [0, 1];\n [legend.min, legend.max] = extent;\n legend.range = legend.max - legend.min;\n legend.scale = d3.scaleLinear().domain(extent);\n }\n });\n return legends;\n}\n","/** @module */\n\nimport * as d3 from 'd3';\n\n\nexport const GEOMS = {\n text: (value, _, column, O, P) => {\n let fill = O.theme.textColor;\n if (column.palette) {\n fill = column.palette(value);\n }\n const el = d3.create('svg:text')\n .attr('dominant-baseline', 'middle')\n .attr('y', P.rowHeight / 2)\n .style('fill', fill)\n .text(value);\n if (O.fontSize) {\n el.attr('font-size', O.fontSize);\n }\n return el;\n },\n\n bar: (value, colorValue, column, O, P) => {\n const fill = column.palette(colorValue);\n value = column.scale(value);\n let width = value * column.width * P.geomSize;\n if (width === 0) {\n width = P.minGeomSize;\n }\n return d3.create('svg:rect')\n .classed('fh-geom', true)\n .attr('x', P.geomPaddingX)\n .attr('y', P.geomPadding)\n .attr('width', width.toFixed(2))\n .attr('height', P.geomSize)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill);\n },\n\n circle: (value, colorValue, column, O, P) => {\n const fill = column.palette(colorValue);\n value = column.scale(value);\n let radius = value * P.geomSize / 2;\n if (radius === 0) {\n radius = P.minGeomSize;\n }\n return d3.create('svg:circle')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('cx', P.rowHeight / 2)\n .attr('cy', P.rowHeight / 2)\n .attr('r', radius.toFixed(2));\n },\n\n rect: (value, colorValue, column, O, P) => {\n const fill = column.palette(colorValue);\n value = column.scale(value);\n return d3.create('svg:rect')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('x', P.geomPaddingX)\n .attr('y', P.geomPadding)\n .attr('width', P.geomSize)\n .attr('height', P.geomSize);\n },\n\n funkyrect: (value, colorValue, column, O, P) => {\n let scaled = column.scale(value);\n const fill = column.palette(colorValue);\n if (scaled < P.funkyMidpoint) {\n // transform value to a 0.0 .. 0.5 range\n value = column.scale.copy()\n .range([0, 0.5])\n .domain([column.min, column.min + column.range * P.funkyMidpoint])(value);\n let radius = (value * 0.9 + 0.1) * P.geomSize - P.geomPadding; // 0.5 for stroke\n if (radius <= 0) {\n radius = P.minGeomSize;\n }\n return d3.create('svg:circle')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('cx', P.rowHeight / 2)\n .attr('cy', P.rowHeight / 2)\n .attr('r', radius.toFixed(2));\n }\n // transform value to a 0.5 .. 1.0 range\n value = column.scale\n .copy()\n .range([0.5, 1])\n .domain([column.min + column.range * P.funkyMidpoint, column.max])(value);\n const cornerSize = (0.9 - 0.8 * value) * P.geomSize;\n return d3.create('svg:rect')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('x', P.geomPaddingX)\n .attr('y', P.geomPadding)\n .attr('width', P.geomSize)\n .attr('height', P.geomSize)\n .attr('rx', cornerSize.toFixed(2))\n .attr('ry', cornerSize.toFixed(2));\n },\n\n pie: (value, _, column, O, P) => {\n let nonZero = 0;\n let nonZeroIdx = 0;\n value.forEach((x, i) => {\n if (x > 0) {\n nonZero += 1;\n nonZeroIdx = i;\n }\n });\n if (nonZero === 1) {\n const fill = column.palette(nonZeroIdx);\n return d3.create('svg:circle')\n .classed('fh-geom', true)\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .style('fill', fill)\n .attr('cx', P.rowHeight / 2)\n .attr('cy', P.rowHeight / 2)\n .attr('r', P.geomSize / 2);\n }\n\n const arcs = d3.pie().sortValues(null)(value);\n const g = d3.create('svg:g');\n g.classed('fh-geom', true);\n g.selectAll('arcs')\n .data(arcs)\n .enter()\n .append('path')\n .attr('d', d3.arc().innerRadius(0).outerRadius(P.geomSize / 2))\n .attr('fill', (_, i) => {\n return column.palette(i);\n })\n .style('stroke', O.theme.strokeColor)\n .style('stroke-width', 1)\n .attr('transform', `translate(${P.rowHeight / 2}, ${P.rowHeight / 2})`);\n return g;\n },\n\n image: function(value, _, column, O, P) {\n return d3.create('svg:image')\n .attr('y', P.geomPadding)\n .attr('href', value)\n .attr('height', P.geomSize)\n .attr('width', column.width)\n .attr('preserveAspectRatio', 'xMidYMid');\n }\n};\n"],"names":["module","exports","d3","$3gsfO","parcelRequire","$2b6e161c9edcf319$var$DEFAULT_OPTIONS","legendFontSize","legendTicks","labelGroupsAbc","colorByRank","theme","oddRowBackground","evenRowBackground","textColor","strokeColor","headerColor","hoverColor","$2b6e161c9edcf319$var$DEFAULT_POSITION_ARGS","rowHeight","rowSpace","rowBigspace","colWidth","colSpace","colBigspace","colAnnotOffset","colAnnotAngle","padding","minGeomSize","funkyMidpoint","$2b6e161c9edcf319$var$PositionArgs","constructor","args","$32BwG","extend","this","underscoreDeprecatedArgs","deprecatedArgs","key","Object","getOwnPropertyNames","underscore","indexOf","newKey","slice","toUpperCase","push","startsWith","length","msg","join","console","warn","calculate","rowSpacePx","rowBigspacePx","colSpacePx","geomSize","geomPadding","geomPaddingX","$2b6e161c9edcf319$var$FunkyHeatmap","data","columnInfo","columnGroups","rowInfo","rowGroups","palettes","legends","positionArgs","options","svg","rowGroupKey","index","group","merge","calculateOptions","renderGroups","rowGroupOrder","undefined","map","_","forEach","d","i","groupInfo","get","Group","renderStripedRows","O","P","rowGroup","nGroups","colorCounter","body","append","classed","attr","renderData","prevColGroup","offset","bodyHeight","size","column","rankedData","maxWidth","firstColumn","geom","numeric","rank","item","id","j","width","groupName","$7SRQm","GEOMS","text","node","getBBox","value","isNaN","label","colorValue","keys","elWidth","el","labelColor","hsl","palette","l","g","create","tooltip","toFixed","replace","datum","s2","colorNames","colorName","select","fontSize","q","widthPx","Math","max","round","bodyWidth","renderHeader","headerHeight","nonZeroRotate","groups","header","labels","abcCounter","$dwZfM","Column","maybeCalculateStats","$lG5F2","assignPalettes","lastCol","groupStart","groupEnd","fill","level1","letter","String","fromCharCode","charCodeAt","style","on","onColumnClick","bind","name","nativeWidth","rotate","height","getBoundingClientRect","center","renderLegends","footerHeight","legendEl","footer","legendXOffset","legend","enabled","offsetY","title","labelsWidth","txt","values","myOffset","rect","funkyrect","geomWidth","geomHeight","circle","colors","range","paletteName","selectAll","enter","col","filter","xPos","img","image","imgWidth","imgHeight","arcs","pie","endAngle","PI","Array","arc","innerRadius","outerRadius","p","centroid","p1","p2","line","legendWidth","footerOffset","hideTooltip","showTooltip","mouse","html","onMouseMove","e","target","parentNode","pointer","document","elBox","comparator","sort","concat","a","b","selectChildren","remove","render","indicateSort","labelBox","sortIndicator","sortState","x","y","rootStyle","listen","$2b6e161c9edcf319$export$2e2bcd8739ae039","scaleColumn","$kwarp","ensureRowData","buildColumnInfo","buildColumnGroups","$afEFj","prepareLegends","heatmap","$eefee52b0cc720a2$export$7154591d43bbde2b","result","columns","$eefee52b0cc720a2$export$3ce631e14ef22c91","objects","obj","isArray","convertDataframe","$9d9dc732a89d186b$export$816b5d811295e6bc","info","overlay","type","str","Number","parseFloat","categorical","extent","min","scale","scaleLinear","domain","colorScale","ascending","descending","$9d9dc732a89d186b$export$caf19947cd7e65b5","$9d9dc732a89d186b$export$e33aac0e3b4702d0","some","Set","allGroups","unused","includes","charAt","$fc81e95648bdd3b9$var$defaultPalettes","numerical","Blues","Greens","Greys","Reds","YlOrBr","Set1","Set2","Set3","Dark2","$fc81e95648bdd3b9$export$e66d39924afea2dc","names","step","scaleOrdinal","$776ad961d55bdd86$export$ba7a034cabddb75f","colInfoPalettes","legendPalettes","missingPalettes","difference","find","isNumber","$5bd757c5633cec0d$export$848bef37f8dddb4a","bar","radius","scaled","copy","cornerSize","nonZero","nonZeroIdx","sortValues"],"version":3,"file":"scIB.c9996616.js.map"} \ No newline at end of file