@milaboratories/miplots4 1.0.146 → 1.0.147

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"Dendrograms.d.ts","sourceRoot":"","sources":["../../../src/heatmap/components/Dendrograms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAE,mBAAmB,EAAW,mBAAmB,EAAC,MAAM,SAAS,CAAC;AAEjG,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AA0C3C,UAAU,eAAe;IACrB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,mBAAmB,CAAC,mBAAmB,CAAC,CAAC;IAC5D,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACvD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACvD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,mBAAmB,CAAC;CAClC;AAED,wBAAgB,WAAW,CAAC,EAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAC,EAAE,eAAe,2CA0FzI"}
1
+ {"version":3,"file":"Dendrograms.d.ts","sourceRoot":"","sources":["../../../src/heatmap/components/Dendrograms.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,gBAAgB,EAAE,mBAAmB,EAAW,mBAAmB,EAAC,MAAM,SAAS,CAAC;AAEjG,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AA4C3C,UAAU,eAAe;IACrB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,EAAE,mBAAmB,CAAC,mBAAmB,CAAC,CAAC;IAC5D,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACvD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACvD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,mBAAmB,CAAC;CAClC;AAED,wBAAgB,WAAW,CAAC,EAAC,WAAW,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAC,EAAE,eAAe,2CA0FzI"}
@@ -1,87 +1,87 @@
1
1
  import { j as a } from "../../node_modules/react/jsx-runtime.js";
2
- import { isColumnName as N } from "../../utils/index.js";
3
- import { getLineShape as S } from "../../utils/getLineShape.js";
4
- import { getPointShape as B } from "../../utils/getPointShape.js";
5
- function L(n, i = "top") {
6
- const { source: e, target: r } = n;
7
- return i === "top" || i === "bottom" ? `M ${e.x},${e.y} L ${r.x},${e.y} L${r.x},${r.y}` : `M ${e.x},${e.y} L ${e.x},${r.y} L${r.x},${r.y}`;
2
+ import { isColumnName as X } from "../../utils/index.js";
3
+ import { getLineShape as B } from "../../utils/getLineShape.js";
4
+ import { getPointShape as L } from "../../utils/getPointShape.js";
5
+ function v(s, i = "top") {
6
+ const { source: r, target: n } = s;
7
+ return i === "top" || i === "bottom" ? `M ${r.x},${r.y} L ${n.x},${r.y} L${n.x},${n.y}` : `M ${r.x},${r.y} L ${r.x},${n.y} L${n.x},${n.y}`;
8
8
  }
9
- function v(n, i, e, r, m) {
10
- if (!e)
9
+ function N(s, i, r, n, l, f) {
10
+ if (!r)
11
11
  return "";
12
- const l = e.aes[n];
13
- if (!N(l))
14
- return l;
15
- const y = l.value, o = m[y], s = r[y][i.data.keys[0]];
16
- return i.data.keys.every((d) => s === r[y][d]) ? o(String(s))[n] : o.unknown()[n];
12
+ const d = r.aes[s];
13
+ if (!X(d))
14
+ return d;
15
+ const e = d.value, o = f[e], m = n[i.data.indexes[0]], y = l[e][m];
16
+ return i.data.indexes.every((c) => y === l[e][n[c]]) ? o(String(y))[s] : o.unknown()[s];
17
17
  }
18
- const G = { x: 0, y: 0 };
19
- function C({ dendrograms: n, sideElementBBoxes: i, xDataByKeys: e, yDataByKeys: r, xGroupKeys: m, yGroupKeys: l, aesScales: y }) {
20
- const o = n.x.data, s = n.y.data, d = o ? i[o.position].dendro : G, j = s ? i[s.position].dendro : G;
21
- function p(c, u) {
22
- return v(c, u, o, e, y);
18
+ const W = { x: 0, y: 0 };
19
+ function F({ dendrograms: s, sideElementBBoxes: i, xDataByKeys: r, yDataByKeys: n, xGroupKeys: l, yGroupKeys: f, aesScales: d }) {
20
+ const e = s.x.data, o = s.y.data, m = e ? i[e.position].dendro : W, y = o ? i[o.position].dendro : W;
21
+ function c(u, $) {
22
+ return N(u, $, e, l, r, d);
23
23
  }
24
- function h(c, u) {
25
- return v(c, u, s, r, y);
24
+ function p(u, $) {
25
+ return N(u, $, o, f, n, d);
26
26
  }
27
27
  return /* @__PURE__ */ a.jsxs("g", { children: [
28
- /* @__PURE__ */ a.jsx("g", { transform: `translate(${d.x},${d.y})`, children: o && !o.hidden && m.map((c, u) => {
29
- const x = n.x.treesByGroupKey[c];
28
+ /* @__PURE__ */ a.jsx("g", { transform: `translate(${m.x},${m.y})`, children: e && !e.hidden && l.map((u, $) => {
29
+ const x = s.x.treesByGroupKey[u];
30
30
  if (!x)
31
31
  return null;
32
- const f = x.links(), g = x.descendants();
32
+ const g = x.links(), j = x.descendants();
33
33
  return /* @__PURE__ */ a.jsxs("g", { children: [
34
- f.map((t) => {
35
- const $ = o.edgeInheritance === "up" ? t.source : t.target;
34
+ g.map((t, h) => {
35
+ const S = e.edgeInheritance === "up" ? t.source : t.target;
36
36
  return /* @__PURE__ */ a.jsx(
37
37
  "path",
38
38
  {
39
- d: L(t, o.position),
40
- stroke: p("lineColor", $),
41
- strokeWidth: p("lineWidth", $),
42
- strokeDasharray: S(p("lineShape", $)),
39
+ d: v(t, e.position),
40
+ stroke: c("lineColor", S),
41
+ strokeWidth: c("lineWidth", S),
42
+ strokeDasharray: B(c("lineShape", S)),
43
43
  fill: "none"
44
44
  },
45
- `${t.source.x},${t.source.y},${t.target.x},${t.target.y}`
45
+ `${t.source.x},${t.source.y},${t.target.x},${t.target.y},${h}`
46
46
  );
47
47
  }),
48
- o.showNodes && g.map((t) => /* @__PURE__ */ a.jsx("g", { transform: `translate(${t.x},${t.y})`, children: B(
49
- p("dotShape", t),
50
- p("dotSize", t),
51
- p("dotFill", t)
52
- ) }, `${t.x},${t.y}`))
53
- ] }, u);
48
+ e.showNodes && j.map((t, h) => /* @__PURE__ */ a.jsx("g", { transform: `translate(${t.x},${t.y})`, children: L(
49
+ c("dotShape", t),
50
+ c("dotSize", t),
51
+ c("dotFill", t)
52
+ ) }, `${t.x},${t.y},${h}}`))
53
+ ] }, $);
54
54
  }) }),
55
- /* @__PURE__ */ a.jsx("g", { transform: `translate(${j.x},${j.y})`, children: s && !s.hidden && l.map((c, u) => {
56
- const x = n.y.treesByGroupKey[c];
55
+ /* @__PURE__ */ a.jsx("g", { transform: `translate(${y.x},${y.y})`, children: o && !o.hidden && f.map((u, $) => {
56
+ const x = s.y.treesByGroupKey[u];
57
57
  if (!x)
58
58
  return null;
59
- const f = x.links(), g = x.descendants();
59
+ const g = x.links(), j = x.descendants();
60
60
  return /* @__PURE__ */ a.jsxs("g", { children: [
61
- f.map((t) => {
62
- const $ = s.edgeInheritance === "up" ? t.source : t.target;
61
+ g.map((t) => {
62
+ const h = o.edgeInheritance === "up" ? t.source : t.target;
63
63
  return /* @__PURE__ */ a.jsx(
64
64
  "path",
65
65
  {
66
- d: L(t, s.position),
67
- stroke: h("lineColor", $),
68
- strokeWidth: h("lineWidth", $),
69
- strokeDasharray: S(h("lineShape", $)),
66
+ d: v(t, o.position),
67
+ stroke: p("lineColor", h),
68
+ strokeWidth: p("lineWidth", h),
69
+ strokeDasharray: B(p("lineShape", h)),
70
70
  fill: "none"
71
71
  },
72
72
  `${t.source.x},${t.source.y},${t.target.x},${t.target.y}`
73
73
  );
74
74
  }),
75
- s.showNodes && g.map((t) => /* @__PURE__ */ a.jsx("g", { transform: `translate(${t.x},${t.y})`, children: B(
76
- h("dotShape", t),
77
- h("dotSize", t),
78
- h("dotFill", t)
75
+ o.showNodes && j.map((t) => /* @__PURE__ */ a.jsx("g", { transform: `translate(${t.x},${t.y})`, children: L(
76
+ p("dotShape", t),
77
+ p("dotSize", t),
78
+ p("dotFill", t)
79
79
  ) }, `${t.x},${t.y}`))
80
- ] }, u);
80
+ ] }, $);
81
81
  }) })
82
82
  ] });
83
83
  }
84
84
  export {
85
- C as Dendrograms
85
+ F as Dendrograms
86
86
  };
87
87
  //# sourceMappingURL=Dendrograms.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dendrograms.js","sources":["../../../src/heatmap/components/Dendrograms.tsx"],"sourcesContent":["import type {ChartDendrograms, ChartDimensionsData, Cluster, DendrogramAesScales} from './types';\nimport type {HeatmapDendrogramSettings, HeatmapSettingsImpl} from '../HeatmapSettingsImpl';\nimport type {DataValue} from '../../types';\nimport type {LineShape, PointShape} from '../../types';\nimport {isColumnName} from '../../utils';\nimport {getLineShape} from '../../utils/getLineShape';\nimport {getPointShape} from '../../utils/getPointShape';\nimport type {HierarchyPointLink, HierarchyPointNode} from 'd3-hierarchy';\nimport React from 'react';\n\nfunction getLinkPath(link: HierarchyPointLink<Cluster>, position = 'top'): string {\n const {source, target} = link;\n if (position === 'top' || position === 'bottom') {\n return `M ${source.x},${source.y} L ${target.x},${source.y} L${target.x},${target.y}`;\n }\n return `M ${source.x},${source.y} L ${source.x},${target.y} L${target.x},${target.y}`;\n}\n\nfunction getAes<ValueType>(\n field: keyof HeatmapDendrogramSettings['aes'],\n node: HierarchyPointNode<Cluster>,\n dendrogram: HeatmapSettingsImpl['dendrogramX' | 'dendrogramY'],\n data: Record<string, Record<string, DataValue>>,\n aesScales: DendrogramAesScales\n): ValueType {\n if (!dendrogram) {\n return '' as ValueType;\n }\n const value = dendrogram.aes[field];\n if (!isColumnName(value)) {\n return value as ValueType;\n }\n const columnName = value.value;\n const scale = aesScales[columnName];\n const valueByFirstKey = data[columnName][node.data.keys[0]];\n if (node.data.keys.every(key => valueByFirstKey === data[columnName][key])) {\n return scale(String(valueByFirstKey))[field] as ValueType;\n } else {\n return scale.unknown()[field] as ValueType;\n }\n}\n\nconst EMPTY_BBOX = {x: 0, y: 0, width: 0, height: 0};\n\ninterface DendrogramProps {\n dendrograms: ChartDendrograms;\n sideElementBBoxes: ChartDimensionsData['sideElementBBoxes'];\n xDataByKeys: Record<string, Record<string, DataValue>>;\n yDataByKeys: Record<string, Record<string, DataValue>>;\n xGroupKeys: string[];\n yGroupKeys: string[];\n aesScales: DendrogramAesScales;\n}\n\nexport function Dendrograms({dendrograms, sideElementBBoxes, xDataByKeys, yDataByKeys, xGroupKeys, yGroupKeys, aesScales}: DendrogramProps) {\n const dataX = dendrograms.x.data;\n const dataY = dendrograms.y.data;\n const dendroXBBox = dataX ? sideElementBBoxes[dataX.position].dendro : EMPTY_BBOX;\n const dendroYBBox = dataY ? sideElementBBoxes[dataY.position].dendro : EMPTY_BBOX;\n\n function aesGetterX<ValueType>(field: keyof HeatmapDendrogramSettings['aes'], node: HierarchyPointNode<Cluster>) {\n return getAes<ValueType>(field, node, dataX, xDataByKeys, aesScales);\n }\n function aesGetterY<ValueType>(field: keyof HeatmapDendrogramSettings['aes'], node: HierarchyPointNode<Cluster>) {\n return getAes<ValueType>(field, node, dataY, yDataByKeys, aesScales);\n }\n return (\n <g>\n <g transform={`translate(${dendroXBBox.x},${dendroXBBox.y})`}>\n {dataX && !dataX.hidden && xGroupKeys.map((xKey, idx) => {\n const root = dendrograms.x.treesByGroupKey[xKey];\n if (!root) {\n return null;\n }\n const links = root.links();\n const nodes = root.descendants();\n return (\n <g key={idx}>\n {links.map(link => {\n const node = dataX.edgeInheritance === 'up' ? link.source : link.target;\n return (\n <path\n key={`${link.source.x},${link.source.y},${link.target.x},${link.target.y}`}\n d={getLinkPath(link, dataX.position)}\n stroke={aesGetterX<string>('lineColor', node)}\n strokeWidth={aesGetterX<number>('lineWidth', node)}\n strokeDasharray={getLineShape(aesGetterX<LineShape>('lineShape', node))}\n fill=\"none\"\n />\n );\n })}\n {dataX.showNodes &&\n nodes.map(node => (\n <g key={`${node.x},${node.y}`} transform={`translate(${node.x},${node.y})`}>\n {getPointShape(\n aesGetterX<PointShape>('dotShape', node),\n aesGetterX<number>('dotSize', node),\n aesGetterX<string>('dotFill', node)\n )}\n </g>\n ))}\n </g>\n );\n })}\n </g>\n <g transform={`translate(${dendroYBBox.x},${dendroYBBox.y})`}>\n {dataY && !dataY.hidden && yGroupKeys.map((yKey, idx) => {\n const root = dendrograms.y.treesByGroupKey[yKey];\n if (!root) {\n return null;\n }\n const links = root.links();\n const nodes = root.descendants();\n return (\n <g key={idx}>\n {links.map(link => {\n const node = dataY.edgeInheritance === 'up' ? link.source : link.target;\n return (\n <path\n key={`${link.source.x},${link.source.y},${link.target.x},${link.target.y}`}\n d={getLinkPath(link, dataY.position)}\n stroke={aesGetterY<string>('lineColor', node)}\n strokeWidth={aesGetterY<number>('lineWidth', node)}\n strokeDasharray={getLineShape(aesGetterY<LineShape>('lineShape', node))}\n fill=\"none\"\n />\n );\n })}\n {dataY.showNodes &&\n nodes.map(node => (\n <g key={`${node.x},${node.y}`} transform={`translate(${node.x},${node.y})`}>\n {getPointShape(\n aesGetterY<PointShape>('dotShape', node),\n aesGetterY<number>('dotSize', node),\n aesGetterY<string>('dotFill', node)\n )}\n </g>\n ))}\n </g>\n );\n })}\n </g>\n </g>\n );\n}\n"],"names":["getLinkPath","link","position","source","target","getAes","field","node","dendrogram","data","aesScales","value","isColumnName","columnName","scale","valueByFirstKey","key","EMPTY_BBOX","Dendrograms","dendrograms","sideElementBBoxes","xDataByKeys","yDataByKeys","xGroupKeys","yGroupKeys","dataX","dataY","dendroXBBox","dendroYBBox","aesGetterX","aesGetterY","jsx","xKey","idx","root","links","nodes","getLineShape","getPointShape","yKey"],"mappings":"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"}
1
+ {"version":3,"file":"Dendrograms.js","sources":["../../../src/heatmap/components/Dendrograms.tsx"],"sourcesContent":["import type {ChartDendrograms, ChartDimensionsData, Cluster, DendrogramAesScales} from './types';\nimport type {HeatmapDendrogramSettings, HeatmapSettingsImpl} from '../HeatmapSettingsImpl';\nimport type {DataValue} from '../../types';\nimport type {LineShape, PointShape} from '../../types';\nimport {isColumnName} from '../../utils';\nimport {getLineShape} from '../../utils/getLineShape';\nimport {getPointShape} from '../../utils/getPointShape';\nimport type {HierarchyPointLink, HierarchyPointNode} from 'd3-hierarchy';\nimport React from 'react';\n\nfunction getLinkPath(link: HierarchyPointLink<Cluster>, position = 'top'): string {\n const {source, target} = link;\n if (position === 'top' || position === 'bottom') {\n return `M ${source.x},${source.y} L ${target.x},${source.y} L${target.x},${target.y}`;\n }\n return `M ${source.x},${source.y} L ${source.x},${target.y} L${target.x},${target.y}`;\n}\n\nfunction getAes<ValueType>(\n field: keyof HeatmapDendrogramSettings['aes'],\n node: HierarchyPointNode<Cluster>,\n dendrogram: HeatmapSettingsImpl['dendrogramX' | 'dendrogramY'],\n keys: string[],\n data: Record<string, Record<string, DataValue>>,\n aesScales: DendrogramAesScales\n): ValueType {\n if (!dendrogram) {\n return '' as ValueType;\n }\n const value = dendrogram.aes[field];\n if (!isColumnName(value)) {\n return value as ValueType;\n }\n const columnName = value.value;\n const scale = aesScales[columnName];\n const firstKey = keys[node.data.indexes[0]];\n const valueByFirstKey = data[columnName][firstKey];\n if (node.data.indexes.every(index => valueByFirstKey === data[columnName][keys[index]])) {\n return scale(String(valueByFirstKey))[field] as ValueType;\n } else {\n return scale.unknown()[field] as ValueType;\n }\n}\n\nconst EMPTY_BBOX = {x: 0, y: 0, width: 0, height: 0};\n\ninterface DendrogramProps {\n dendrograms: ChartDendrograms;\n sideElementBBoxes: ChartDimensionsData['sideElementBBoxes'];\n xDataByKeys: Record<string, Record<string, DataValue>>;\n yDataByKeys: Record<string, Record<string, DataValue>>;\n xGroupKeys: string[];\n yGroupKeys: string[];\n aesScales: DendrogramAesScales;\n}\n\nexport function Dendrograms({dendrograms, sideElementBBoxes, xDataByKeys, yDataByKeys, xGroupKeys, yGroupKeys, aesScales}: DendrogramProps) {\n const dataX = dendrograms.x.data;\n const dataY = dendrograms.y.data;\n const dendroXBBox = dataX ? sideElementBBoxes[dataX.position].dendro : EMPTY_BBOX;\n const dendroYBBox = dataY ? sideElementBBoxes[dataY.position].dendro : EMPTY_BBOX;\n\n function aesGetterX<ValueType>(field: keyof HeatmapDendrogramSettings['aes'], node: HierarchyPointNode<Cluster>) {\n return getAes<ValueType>(field, node, dataX, xGroupKeys, xDataByKeys, aesScales);\n }\n function aesGetterY<ValueType>(field: keyof HeatmapDendrogramSettings['aes'], node: HierarchyPointNode<Cluster>) {\n return getAes<ValueType>(field, node, dataY, yGroupKeys, yDataByKeys, aesScales);\n }\n return (\n <g>\n <g transform={`translate(${dendroXBBox.x},${dendroXBBox.y})`}>\n {dataX && !dataX.hidden && xGroupKeys.map((xKey, idx) => {\n const root = dendrograms.x.treesByGroupKey[xKey];\n if (!root) {\n return null;\n }\n const links = root.links();\n const nodes = root.descendants();\n return (\n <g key={idx}>\n {links.map((link, idx) => {\n const node = dataX.edgeInheritance === 'up' ? link.source : link.target;\n return (\n <path\n key={`${link.source.x},${link.source.y},${link.target.x},${link.target.y},${idx}`}\n d={getLinkPath(link, dataX.position)}\n stroke={aesGetterX<string>('lineColor', node)}\n strokeWidth={aesGetterX<number>('lineWidth', node)}\n strokeDasharray={getLineShape(aesGetterX<LineShape>('lineShape', node))}\n fill=\"none\"\n />\n );\n })}\n {dataX.showNodes &&\n nodes.map((node, idx) => (\n <g key={`${node.x},${node.y},${idx}}`} transform={`translate(${node.x},${node.y})`}>\n {getPointShape(\n aesGetterX<PointShape>('dotShape', node),\n aesGetterX<number>('dotSize', node),\n aesGetterX<string>('dotFill', node)\n )}\n </g>\n ))}\n </g>\n );\n })}\n </g>\n <g transform={`translate(${dendroYBBox.x},${dendroYBBox.y})`}>\n {dataY && !dataY.hidden && yGroupKeys.map((yKey, idx) => {\n const root = dendrograms.y.treesByGroupKey[yKey];\n if (!root) {\n return null;\n }\n const links = root.links();\n const nodes = root.descendants();\n return (\n <g key={idx}>\n {links.map(link => {\n const node = dataY.edgeInheritance === 'up' ? link.source : link.target;\n return (\n <path\n key={`${link.source.x},${link.source.y},${link.target.x},${link.target.y}`}\n d={getLinkPath(link, dataY.position)}\n stroke={aesGetterY<string>('lineColor', node)}\n strokeWidth={aesGetterY<number>('lineWidth', node)}\n strokeDasharray={getLineShape(aesGetterY<LineShape>('lineShape', node))}\n fill=\"none\"\n />\n );\n })}\n {dataY.showNodes &&\n nodes.map(node => (\n <g key={`${node.x},${node.y}`} transform={`translate(${node.x},${node.y})`}>\n {getPointShape(\n aesGetterY<PointShape>('dotShape', node),\n aesGetterY<number>('dotSize', node),\n aesGetterY<string>('dotFill', node)\n )}\n </g>\n ))}\n </g>\n );\n })}\n </g>\n </g>\n );\n}\n"],"names":["getLinkPath","link","position","source","target","getAes","field","node","dendrogram","keys","data","aesScales","value","isColumnName","columnName","scale","firstKey","valueByFirstKey","index","EMPTY_BBOX","Dendrograms","dendrograms","sideElementBBoxes","xDataByKeys","yDataByKeys","xGroupKeys","yGroupKeys","dataX","dataY","dendroXBBox","dendroYBBox","aesGetterX","aesGetterY","jsx","xKey","idx","root","links","nodes","getLineShape","getPointShape","yKey"],"mappings":"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"}
@@ -69,7 +69,6 @@ export interface ChartDimensionsData {
69
69
  export type Cluster = {
70
70
  height: number;
71
71
  indexes: number[];
72
- keys: string[];
73
72
  children: Cluster[];
74
73
  };
75
74
  export type ChartDendrograms = {
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/heatmap/components/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAO,KAAK,EAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAC,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,MAAM,WAAW,OAAO;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IAEtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAExB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IACxB,CAAC,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,YAAY;IAEzB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;CACvC;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CACtC,MAAM,EACJ;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAC,GACxD;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;CAAC,CACpE,CAAC;AAGF,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAExF,MAAM,WAAW,mBAAmB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,EAAE;QACH,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,OAAO,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,iBAAiB,EAAE,uBAAuB,CAAC;IAC3C,cAAc,EAAE,CAAC,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;CAC3D;AAED,MAAM,MAAM,OAAO,GAAG;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,QAAQ,EAAE,OAAO,EAAE,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,CAAC,EAAE;QACC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,IAAI,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAC;KAC5C,CAAC;IACF,CAAC,EAAE;QACC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7D,IAAI,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAA;KAC3C,CAAC;CACL,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC3B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACtB,CAAA;AACD,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACvC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACxC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC5C,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAChC,YAAY,EAAE,IAAI,CAAC;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;IACtB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QACF,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAA;KACjB,CAAC;IACF,MAAM,EAAE,UAAU,CAAA;CACrB,CAAA"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/heatmap/components/types.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,86 @@
1
1
  import { Cluster } from './components/types';
2
2
  import { DendrogramDistance, DendrogramLinkage } from '../types';
3
+ /**
4
+ * Calculate squared Euclidean distance between two vectors
5
+ * This is faster than regular Euclidean distance since it avoids the square root
6
+ * Formula: Σ(p[i] - q[i])²
7
+ * @param p First vector
8
+ * @param q Second vector
9
+ * @returns Squared distance (always positive)
10
+ */
3
11
  export declare function squaredEuclidean(p: number[], q: number[]): number;
12
+ /**
13
+ * Calculate Euclidean distance between two vectors
14
+ * This is the standard geometric distance in n-dimensional space
15
+ * Formula: √(Σ(p[i] - q[i])²)
16
+ * @param p First vector
17
+ * @param q Second vector
18
+ * @returns Euclidean distance
19
+ */
4
20
  export declare function euclidean(p: number[], q: number[]): number;
5
- export declare const averageLinkage: (setA: number[], setB: number[], distances: number[][]) => number;
6
- export declare const completeLinkage: (setA: number[], setB: number[], distances: number[][]) => number;
7
- export declare const singleLinkage: (setA: number[], setB: number[], distances: number[][]) => number;
8
- export declare function getClusters(dataKeys: string[] | undefined, dataValues: number[][], distanceType?: DendrogramDistance, linkageType?: DendrogramLinkage): Cluster;
21
+ /**
22
+ * Average Linkage
23
+ * Calculates the average distance between all pairs of points in the two clusters
24
+ * This is the most commonly used linkage method as it balances between single and complete linkage
25
+ * @param setA Indexes of points in first cluster
26
+ * @param setB Indexes of points in second cluster
27
+ * @param getDistance Function to get distance between two point indexes
28
+ * @returns Average distance between clusters
29
+ */
30
+ export declare const averageLinkage: (setA: number[], setB: number[], getDistance: (i: number, j: number) => number) => number;
31
+ /**
32
+ * Complete Linkage (Maximum Linkage)
33
+ * Uses the maximum distance between any pair of points in the two clusters
34
+ * Tends to create compact, well-separated clusters
35
+ * Formula: max{d(a,b)} for all a in A, b in B
36
+ * @param setA Indexes of points in first cluster
37
+ * @param setB Indexes of points in second cluster
38
+ * @param getDistance Function to get distance between two point indexes
39
+ * @returns Maximum distance between clusters
40
+ */
41
+ export declare const completeLinkage: (setA: number[], setB: number[], getDistance: (i: number, j: number) => number) => number;
42
+ /**
43
+ * Single Linkage (Minimum Linkage)
44
+ * Uses the minimum distance between any pair of points in the two clusters
45
+ * Tends to create elongated, chain-like clusters
46
+ * Formula: min{d(a,b)} for all a in A, b in B
47
+ * @param setA Indexes of points in first cluster
48
+ * @param setB Indexes of points in second cluster
49
+ * @param getDistance Function to get distance between two point indexes
50
+ * @returns Minimum distance between clusters
51
+ */
52
+ export declare const singleLinkage: (setA: number[], setB: number[], getDistance: (i: number, j: number) => number) => number;
53
+ /**
54
+ * Extract indexes from a cluster hierarchy in the correct hierarchical order
55
+ * This function traverses the cluster tree and collects all indexes in the order
56
+ * they appear in the dendrogram (left-to-right traversal)
57
+ * @param cluster The root cluster to extract indexes from
58
+ * @returns Array of indexes in hierarchical order
59
+ */
60
+ export declare function extractOrderedIndexes(cluster: Cluster): number[];
61
+ export declare function getClustersApproximate(dataValues: number[][], distanceType?: DendrogramDistance, linkageType?: DendrogramLinkage): Cluster;
62
+ /**
63
+ * Main hierarchical clustering function using agglomerative approach
64
+ *
65
+ * This implements the standard agglomerative hierarchical clustering algorithm:
66
+ * 1. Start with each point as its own cluster
67
+ * 2. Compute pairwise distances between all points
68
+ * 3. Iteratively merge the two closest clusters
69
+ * 4. Continue until only one cluster remains
70
+ *
71
+ * Algorithm complexity:
72
+ * - Time: O(n³) - for each of n-1 iterations, scan all n² cluster pairs
73
+ * - Space: O(n²) - store upper triangular distance matrix
74
+ *
75
+ * Memory optimization:
76
+ * - Uses upper triangular matrix storage (50% memory reduction)
77
+ * - Only stores distances where i < j since distance matrix is symmetric
78
+ *
79
+ * @param dataKeys Labels for each data point
80
+ * @param dataValues Feature vectors for each data point (n×d matrix)
81
+ * @param distanceType Distance metric to use between points
82
+ * @param linkageType Linkage method to use between clusters
83
+ * @returns Root cluster containing the complete hierarchy
84
+ */
85
+ export declare function getClusters(dataValues: number[][], distanceType?: DendrogramDistance, linkageType?: DendrogramLinkage): Cluster;
9
86
  //# sourceMappingURL=getClusters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getClusters.d.ts","sourceRoot":"","sources":["../../src/heatmap/getClusters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAC,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,UAAU,CAAC;AAGpE,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,UAMxD;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,UAEjD;AAID,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,MAAM,EAAE,EAAE,WAAW,MAAM,EAAE,EAAE,WAOnF,CAAC;AACF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,MAAM,EAAE,EAAE,WAAW,MAAM,EAAE,EAAE,WAOpF,CAAC;AACF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,MAAM,EAAE,EAAE,WAAW,MAAM,EAAE,EAAE,WAOlF,CAAC;AAmBF,wBAAgB,WAAW,CAAC,QAAQ,EAAC,MAAM,EAAE,YAAK,EAAE,UAAU,EAAC,MAAM,EAAE,EAAE,EAAE,YAAY,GAAC,kBAAgC,EAAE,WAAW,GAAC,iBAA6B,GAAE,OAAO,CA6D3K"}
1
+ {"version":3,"file":"getClusters.d.ts","sourceRoot":"","sources":["../../src/heatmap/getClusters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAKtE;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,UAOxD;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,UAEjD;AAID;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,WAS3G,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,WAQ5G,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,EAAE,MAAM,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,WAQ1G,CAAC;AAiCF;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,CAiBhE;AAKD,wBAAgB,sBAAsB,CAClC,UAAU,EAAE,MAAM,EAAE,EAAE,EACtB,YAAY,GAAE,kBAAgC,EAC9C,WAAW,GAAE,iBAA6B,GAC3C,OAAO,CAqBT;AAwFD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,GAAE,kBAAgC,EAAE,WAAW,GAAE,iBAA6B,GAAG,OAAO,CA6FvJ"}
@@ -1,80 +1,169 @@
1
- function m(e, t) {
2
- let s = 0;
1
+ import F from "../node_modules/d3-random/src/lcg.js";
2
+ function S(e, s) {
3
+ let o = 0;
3
4
  for (let n = 0; n < e.length; n++)
4
- s += (e[n] - t[n]) * (e[n] - t[n]);
5
- return s;
5
+ o += (e[n] - s[n]) * (e[n] - s[n]);
6
+ return o;
6
7
  }
7
- function h(e, t) {
8
- return Math.sqrt(m(e, t));
8
+ function I(e, s) {
9
+ return Math.sqrt(S(e, s));
9
10
  }
10
- const k = (e, t, s) => {
11
+ const M = (e, s, o) => {
11
12
  let n = 0;
12
- for (const i of e)
13
- for (const c of t) n += s[i][c];
14
- return n / e.length / t.length;
15
- }, w = (e, t, s) => {
13
+ for (const l of e)
14
+ for (const r of s) n += o(l, r);
15
+ return n / e.length / s.length;
16
+ }, L = (e, s, o) => {
16
17
  let n = 0;
17
- for (const i of e)
18
- for (const c of t) n = Math.max(n, s[i][c]);
18
+ for (const l of e)
19
+ for (const r of s) n = Math.max(n, o(l, r));
19
20
  return n;
20
- }, M = (e, t, s) => {
21
+ }, b = (e, s, o) => {
21
22
  let n = 1 / 0;
22
- for (const i of e)
23
- for (const c of t) n = Math.min(n, s[i][c]);
23
+ for (const l of e)
24
+ for (const r of s) n = Math.min(n, o(l, r));
24
25
  return n;
25
26
  };
26
- function b(e) {
27
+ function A(e) {
27
28
  switch (e) {
28
29
  case "average":
29
- return k;
30
+ return M;
30
31
  case "complete":
31
- return w;
32
+ return L;
32
33
  case "single":
33
- return M;
34
+ return b;
34
35
  default:
35
- return k;
36
+ return M;
36
37
  }
37
38
  }
38
- function y(e) {
39
+ function v(e) {
39
40
  switch (e) {
40
41
  case "euclidean":
41
- return h;
42
+ return I;
42
43
  case "squaredEuclidean":
43
- return m;
44
+ return S;
44
45
  default:
45
- return h;
46
+ return I;
47
+ }
48
+ }
49
+ function k(e) {
50
+ const s = [], o = (n) => {
51
+ if (n.children.length === 0)
52
+ s.push(...n.indexes);
53
+ else
54
+ for (const l of n.children)
55
+ o(l);
56
+ };
57
+ return o(e), s;
58
+ }
59
+ const w = 2e3;
60
+ function R(e, s = "euclidean", o = "average") {
61
+ if (e.length <= w)
62
+ return C(e, s, o);
63
+ const n = e.length, l = F(1), r = /* @__PURE__ */ new Set();
64
+ for (; r.size < w; )
65
+ r.add(Math.floor(l() * n));
66
+ const d = Array.from(r), i = d.map((c) => e[c]), a = C(i, s, o);
67
+ return E(a, e, d, s);
68
+ }
69
+ function E(e, s, o, n) {
70
+ const l = v(n), r = new Set(o), d = /* @__PURE__ */ new Map();
71
+ for (let i = 0; i < s.length; i++) {
72
+ if (r.has(i)) continue;
73
+ let a = 1 / 0, c = -1;
74
+ for (const h of o) {
75
+ const t = l(s[i], s[h]);
76
+ t < a && (a = t, c = h);
77
+ }
78
+ d.set(i, c);
79
+ }
80
+ return y(e, d, o);
81
+ }
82
+ function y(e, s, o) {
83
+ const n = /* @__PURE__ */ new Map(), l = (i) => {
84
+ i.indexes.length === 1 && n.set(o[i.indexes[0]], i);
85
+ for (const a of i.children)
86
+ l(a);
87
+ };
88
+ l(e);
89
+ const r = /* @__PURE__ */ new Map();
90
+ for (const [i, a] of s) {
91
+ const c = n.get(a);
92
+ if (c) {
93
+ r.has(c) || r.set(c, []);
94
+ const h = r.get(c);
95
+ h && h.push(i);
96
+ }
46
97
  }
98
+ const d = (i) => {
99
+ i.indexes = i.indexes.map((a) => o[a]);
100
+ for (const a of i.children)
101
+ d(a);
102
+ };
103
+ d(e);
104
+ for (const [i, a] of r)
105
+ i.indexes = [...i.indexes, ...a];
106
+ return {
107
+ ...e,
108
+ indexes: k(e)
109
+ };
47
110
  }
48
- function F(e = [], t, s = "euclidean", n = "average") {
49
- const i = y(s), c = b(n), x = t.map((a) => t.map((o) => i(a, o))), r = e.map((a, o) => ({
111
+ function C(e, s = "euclidean", o = "average") {
112
+ const n = v(s), l = A(o), r = e.length, d = [], i = (t, f) => {
113
+ if (t === f) return 0;
114
+ t > f && ([t, f] = [f, t]);
115
+ const u = t * r - t * (t + 1) / 2 + (f - t - 1);
116
+ return d[u];
117
+ }, a = (t, f, u) => {
118
+ t > f && ([t, f] = [f, t]);
119
+ const g = t * r - t * (t + 1) / 2 + (f - t - 1);
120
+ d[g] = u;
121
+ };
122
+ for (let t = 0; t < r; t++)
123
+ for (let f = t + 1; f < r; f++) {
124
+ const u = n(e[t], e[f]);
125
+ a(t, f, u);
126
+ }
127
+ const c = e.map((t, f) => ({
50
128
  height: 0,
51
- keys: [a],
52
- indexes: [o],
129
+ // Height 0 for leaf nodes
130
+ indexes: [f],
131
+ // Single index per cluster initially
53
132
  children: []
133
+ // No children for leaf nodes
54
134
  }));
55
- for (let a = 0; a < e.length && !(a >= e.length - 1); a++) {
56
- let o = 1 / 0, l = 0, u = 0;
57
- for (let f = 0; f < r.length; f++)
58
- for (let g = f + 1; g < r.length; g++) {
59
- const d = c(r[f].indexes, r[g].indexes, x);
60
- d < o && (o = d, l = f, u = g);
135
+ for (let t = 0; t < r && !(t >= r - 1); t++) {
136
+ let f = 1 / 0, u = 0, g = 0;
137
+ for (let x = 0; x < c.length; x++)
138
+ for (let m = x + 1; m < c.length; m++) {
139
+ const p = l(c[x].indexes, c[m].indexes, i);
140
+ p < f && (f = p, u = x, g = m);
61
141
  }
62
- const p = {
63
- keys: [...r[l].keys, ...r[u].keys],
64
- indexes: [...r[l].indexes, ...r[u].indexes],
65
- height: o,
66
- children: [r[l], r[u]]
142
+ const D = {
143
+ indexes: [...c[u].indexes, ...c[g].indexes],
144
+ // Combine all indexes
145
+ height: f,
146
+ // Height is the distance at which clusters were merged
147
+ children: [c[u], c[g]]
148
+ // Store the two merged clusters as children
67
149
  };
68
- r.splice(Math.max(l, u), 1), r.splice(Math.min(l, u), 1), r.push(p);
150
+ c.splice(Math.max(u, g), 1), c.splice(Math.min(u, g), 1), c.push(D);
69
151
  }
70
- return r[0];
152
+ const h = c[0];
153
+ return {
154
+ ...h,
155
+ indexes: k(h)
156
+ // Ensure indexes are in hierarchical order
157
+ };
71
158
  }
72
159
  export {
73
- k as averageLinkage,
74
- w as completeLinkage,
75
- h as euclidean,
76
- F as getClusters,
77
- M as singleLinkage,
78
- m as squaredEuclidean
160
+ M as averageLinkage,
161
+ L as completeLinkage,
162
+ I as euclidean,
163
+ k as extractOrderedIndexes,
164
+ C as getClusters,
165
+ R as getClustersApproximate,
166
+ b as singleLinkage,
167
+ S as squaredEuclidean
79
168
  };
80
169
  //# sourceMappingURL=getClusters.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getClusters.js","sources":["../../src/heatmap/getClusters.ts"],"sourcesContent":["import type {Cluster} from './components/types';\nimport type {DendrogramDistance, DendrogramLinkage} from '../types';\n\n/* distance - between 2 vectors */\nexport function squaredEuclidean(p: number[], q: number[]) {\n let d = 0;\n for (let i = 0; i < p.length; i++) {\n d += (p[i] - q[i]) * (p[i] - q[i]);\n }\n return d;\n}\n\nexport function euclidean(p: number[], q: number[]) {\n return Math.sqrt(squaredEuclidean(p, q));\n}\n\n/* linkage - between 2 clusters */\n// get average distance between sets of indexes, given distance matrix\nexport const averageLinkage = (setA: number[], setB: number[], distances: number[][]) => {\n let distance = 0;\n for (const a of setA) {\n for (const b of setB) distance += distances[a][b];\n }\n\n return distance / setA.length / setB.length;\n};\nexport const completeLinkage = (setA: number[], setB: number[], distances: number[][]) => {\n let distance = 0;\n for (const a of setA) {\n for (const b of setB) distance = Math.max(distance, distances[a][b]);\n }\n\n return distance;\n};\nexport const singleLinkage = (setA: number[], setB: number[], distances: number[][]) => {\n let distance = Infinity;\n for (const a of setA) {\n for (const b of setB) distance = Math.min(distance, distances[a][b]);\n }\n\n return distance;\n};\n\nfunction getLinkageFn (linkage:DendrogramLinkage) {\n switch (linkage) {\n case 'average': return averageLinkage;\n case 'complete': return completeLinkage;\n case 'single': return singleLinkage;\n default: return averageLinkage;\n }\n}\nfunction getDistanceFn(distance:DendrogramDistance) {\n switch (distance) {\n case 'euclidean': return euclidean;\n case 'squaredEuclidean': return squaredEuclidean;\n default: return euclidean;\n }\n}\n\n// the main clustering function\nexport function getClusters(dataKeys:string[] = [], dataValues:number[][], distanceType:DendrogramDistance = 'euclidean', linkageType:DendrogramLinkage = 'average'):Cluster {\n const distanceFn = getDistanceFn(distanceType);\n const linkageFn = getLinkageFn(linkageType);\n // compute distance between each data point and every other data point\n // N x N matrix where N = data.length\n const distances = dataValues.map(datum => {\n // get distance between datum and other datum\n return dataValues.map(otherDatum => distanceFn(datum, otherDatum));\n });\n\n // initialize clusters to match data\n const clusters:Cluster[] = dataKeys.map((datum, index) => ({\n height: 0,\n keys: [datum],\n indexes: [index],\n children: []\n }));\n\n // iterate through data\n for (let iteration = 0; iteration < dataKeys.length; iteration++) {\n // dont find clusters to merge when only one cluster left\n if (iteration >= dataKeys.length - 1) break;\n\n // initialize smallest distance\n let nearestDistance = Infinity;\n let nearestRow = 0;\n let nearestCol = 0;\n\n // upper triangular matrix of clusters\n for (let row = 0; row < clusters.length; row++) {\n for (let col = row + 1; col < clusters.length; col++) {\n // calculate distance between clusters\n const distance = linkageFn(clusters[row].indexes, clusters[col].indexes, distances);\n // update smallest distance\n if (distance < nearestDistance) {\n nearestDistance = distance;\n nearestRow = row;\n nearestCol = col;\n }\n }\n }\n\n // merge nearestRow and nearestCol clusters together\n const newCluster = {\n keys: [...clusters[nearestRow].keys, ...clusters[nearestCol].keys],\n indexes: [...clusters[nearestRow].indexes, ...clusters[nearestCol].indexes],\n height: nearestDistance,\n children: [clusters[nearestRow], clusters[nearestCol]],\n };\n\n // remove nearestRow and nearestCol clusters\n // splice higher index first so it doesn't affect second splice\n clusters.splice(Math.max(nearestRow, nearestCol), 1);\n clusters.splice(Math.min(nearestRow, nearestCol), 1);\n\n // add new merged cluster\n clusters.push(newCluster);\n }\n\n // return root\n return clusters[0];\n}\n"],"names":["squaredEuclidean","p","q","d","i","euclidean","averageLinkage","setA","setB","distances","distance","a","b","completeLinkage","singleLinkage","getLinkageFn","linkage","getDistanceFn","getClusters","dataKeys","dataValues","distanceType","linkageType","distanceFn","linkageFn","datum","otherDatum","clusters","index","iteration","nearestDistance","nearestRow","nearestCol","row","col","newCluster"],"mappings":"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"}
1
+ {"version":3,"file":"getClusters.js","sources":["../../src/heatmap/getClusters.ts"],"sourcesContent":["import type { Cluster } from './components/types';\nimport type { DendrogramDistance, DendrogramLinkage } from '../types';\nimport { randomLcg } from 'd3-random';\n\n/* DISTANCE FUNCTIONS - Calculate similarity between two data points */\n\n/**\n * Calculate squared Euclidean distance between two vectors\n * This is faster than regular Euclidean distance since it avoids the square root\n * Formula: Σ(p[i] - q[i])²\n * @param p First vector\n * @param q Second vector\n * @returns Squared distance (always positive)\n */\nexport function squaredEuclidean(p: number[], q: number[]) {\n let d = 0;\n // Sum the squared differences for each dimension\n for (let i = 0; i < p.length; i++) {\n d += (p[i] - q[i]) * (p[i] - q[i]);\n }\n return d;\n}\n\n/**\n * Calculate Euclidean distance between two vectors\n * This is the standard geometric distance in n-dimensional space\n * Formula: √(Σ(p[i] - q[i])²)\n * @param p First vector\n * @param q Second vector\n * @returns Euclidean distance\n */\nexport function euclidean(p: number[], q: number[]) {\n return Math.sqrt(squaredEuclidean(p, q));\n}\n\n/* LINKAGE FUNCTIONS - Define how to measure distance between two clusters */\n\n/**\n * Average Linkage\n * Calculates the average distance between all pairs of points in the two clusters\n * This is the most commonly used linkage method as it balances between single and complete linkage\n * @param setA Indexes of points in first cluster\n * @param setB Indexes of points in second cluster \n * @param getDistance Function to get distance between two point indexes\n * @returns Average distance between clusters\n */\nexport const averageLinkage = (setA: number[], setB: number[], getDistance: (i: number, j: number) => number) => {\n let distance = 0;\n // Sum all pairwise distances between clusters\n for (const a of setA) {\n for (const b of setB) distance += getDistance(a, b);\n }\n\n // Return average distance\n return distance / setA.length / setB.length;\n};\n\n/**\n * Complete Linkage (Maximum Linkage)\n * Uses the maximum distance between any pair of points in the two clusters\n * Tends to create compact, well-separated clusters\n * Formula: max{d(a,b)} for all a in A, b in B\n * @param setA Indexes of points in first cluster\n * @param setB Indexes of points in second cluster\n * @param getDistance Function to get distance between two point indexes\n * @returns Maximum distance between clusters\n */\nexport const completeLinkage = (setA: number[], setB: number[], getDistance: (i: number, j: number) => number) => {\n let distance = 0;\n // Find maximum distance between any pair of points\n for (const a of setA) {\n for (const b of setB) distance = Math.max(distance, getDistance(a, b));\n }\n\n return distance;\n};\n\n/**\n * Single Linkage (Minimum Linkage)\n * Uses the minimum distance between any pair of points in the two clusters\n * Tends to create elongated, chain-like clusters\n * Formula: min{d(a,b)} for all a in A, b in B\n * @param setA Indexes of points in first cluster\n * @param setB Indexes of points in second cluster\n * @param getDistance Function to get distance between two point indexes\n * @returns Minimum distance between clusters\n */\nexport const singleLinkage = (setA: number[], setB: number[], getDistance: (i: number, j: number) => number) => {\n let distance = Infinity;\n // Find minimum distance between any pair of points\n for (const a of setA) {\n for (const b of setB) distance = Math.min(distance, getDistance(a, b));\n }\n\n return distance;\n};\n\n/* HELPER FUNCTIONS - Factory functions for distance and linkage methods */\n\n/**\n * Get the appropriate linkage function based on the linkage type\n * @param linkage Type of linkage method to use\n * @returns Function that calculates distance between two clusters\n */\nfunction getLinkageFn(linkage: DendrogramLinkage) {\n switch (linkage) {\n case 'average': return averageLinkage;\n case 'complete': return completeLinkage;\n case 'single': return singleLinkage;\n default: return averageLinkage; // Default to average linkage\n }\n}\n\n/**\n * Get the appropriate distance function based on the distance type\n * @param distance Type of distance metric to use\n * @returns Function that calculates distance between two points\n */\nfunction getDistanceFn(distance: DendrogramDistance) {\n switch (distance) {\n case 'euclidean': return euclidean;\n case 'squaredEuclidean': return squaredEuclidean;\n default: return euclidean; // Default to euclidean distance\n }\n}\n\n/* UTILITY FUNCTIONS - Helper functions for cluster manipulation and sorting */\n\n/**\n * Extract indexes from a cluster hierarchy in the correct hierarchical order\n * This function traverses the cluster tree and collects all indexes in the order\n * they appear in the dendrogram (left-to-right traversal)\n * @param cluster The root cluster to extract indexes from\n * @returns Array of indexes in hierarchical order\n */\nexport function extractOrderedIndexes(cluster: Cluster): number[] {\n const orderedIndexes: number[] = [];\n \n const traverse = (c: Cluster) => {\n if (c.children.length === 0) {\n // Leaf node - add all indexes from this cluster\n orderedIndexes.push(...c.indexes);\n } else {\n // Internal node - traverse children in order (left to right)\n for (const child of c.children) {\n traverse(child);\n }\n }\n };\n \n traverse(cluster);\n return orderedIndexes;\n}\n\nconst MAX_CLUSTER_SIZE = 2000;\n\n// Approximate clustering using sampling for very large datasets\nexport function getClustersApproximate(\n dataValues: number[][], \n distanceType: DendrogramDistance = 'euclidean', \n linkageType: DendrogramLinkage = 'average',\n): Cluster { \n if (dataValues.length <= MAX_CLUSTER_SIZE) {\n return getClusters(dataValues, distanceType, linkageType);\n }\n \n const N = dataValues.length;\n const getRandom = randomLcg(1);\n // Step 1: Random sampling\n const sampleIndices = new Set<number>();\n while (sampleIndices.size < MAX_CLUSTER_SIZE) {\n sampleIndices.add(Math.floor(getRandom() * N));\n }\n \n const sampleIndicesArray = Array.from(sampleIndices);\n const sampleValues = sampleIndicesArray.map(i => dataValues[i]);\n \n // Step 2: Cluster the sample\n const sampleCluster = getClusters(sampleValues, distanceType, linkageType);\n \n // Step 3: Assign remaining points to nearest cluster\n return assignRemainingPoints(sampleCluster, dataValues, sampleIndicesArray, distanceType);\n}\n\n// Assign remaining points to the nearest cluster from the sample\nfunction assignRemainingPoints(\n sampleCluster: Cluster, \n dataValues: number[][], \n sampleIndices: number[],\n distanceType: DendrogramDistance\n): Cluster {\n // console.log('assignRemainingPoints');\n\n const distanceFn = getDistanceFn(distanceType);\n const sampleSet = new Set(sampleIndices);\n \n // Assign each non-sample point to nearest sample point\n const assignments = new Map<number, number>(); // point -> sample point\n for (let i = 0; i < dataValues.length; i++) {\n if (sampleSet.has(i)) continue;\n \n let minDistance = Infinity;\n let nearestSample = -1;\n \n for (const sampleIdx of sampleIndices) {\n const distance = distanceFn(dataValues[i], dataValues[sampleIdx]);\n if (distance < minDistance) {\n minDistance = distance;\n nearestSample = sampleIdx;\n }\n }\n \n assignments.set(i, nearestSample);\n }\n // Reconstruct cluster with all points\n return reconstructWithAssignments(sampleCluster, assignments, sampleIndices);\n}\n\n// Reconstruct cluster hierarchy with assigned points\nfunction reconstructWithAssignments(\n sampleCluster: Cluster, \n assignments: Map<number, number>, \n sampleIndices: number[]\n): Cluster {\n // Create a map of sample indices to their clusters\n const sampleToCluster = new Map<number, Cluster>();\n const findSampleClusters = (cluster: Cluster) => {\n if (cluster.indexes.length === 1) {\n sampleToCluster.set(sampleIndices[cluster.indexes[0]], cluster);\n }\n for (const child of cluster.children) {\n findSampleClusters(child);\n }\n };\n findSampleClusters(sampleCluster);\n \n // Group assigned points by their sample cluster\n const assignedPointsByCluster = new Map<Cluster, number[]>();\n for (const [pointIdx, sampleIdx] of assignments) {\n const sampleCluster = sampleToCluster.get(sampleIdx);\n if (sampleCluster) {\n if (!assignedPointsByCluster.has(sampleCluster)) {\n assignedPointsByCluster.set(sampleCluster, []);\n }\n const cluster = assignedPointsByCluster.get(sampleCluster);\n if (cluster) {\n cluster.push(pointIdx);\n }\n }\n }\n\n const fillCorrectIndexes = (c: Cluster) => {\n c.indexes = c.indexes.map(i => sampleIndices[i]);\n for (const child of c.children) {\n fillCorrectIndexes(child);\n }\n };\n fillCorrectIndexes(sampleCluster);\n for (const [cluster, assignedPoints] of assignedPointsByCluster) {\n cluster.indexes = [...cluster.indexes, ...assignedPoints];\n }\n \n return {\n ...sampleCluster,\n indexes: extractOrderedIndexes(sampleCluster)\n };\n}\n\n/* MAIN HIERARCHICAL CLUSTERING FUNCTION - Standard agglomerative clustering */\n\n/**\n * Main hierarchical clustering function using agglomerative approach\n * \n * This implements the standard agglomerative hierarchical clustering algorithm:\n * 1. Start with each point as its own cluster\n * 2. Compute pairwise distances between all points\n * 3. Iteratively merge the two closest clusters\n * 4. Continue until only one cluster remains\n * \n * Algorithm complexity:\n * - Time: O(n³) - for each of n-1 iterations, scan all n² cluster pairs\n * - Space: O(n²) - store upper triangular distance matrix\n * \n * Memory optimization:\n * - Uses upper triangular matrix storage (50% memory reduction)\n * - Only stores distances where i < j since distance matrix is symmetric\n * \n * @param dataKeys Labels for each data point\n * @param dataValues Feature vectors for each data point (n×d matrix)\n * @param distanceType Distance metric to use between points\n * @param linkageType Linkage method to use between clusters\n * @returns Root cluster containing the complete hierarchy\n */\nexport function getClusters(dataValues: number[][], distanceType: DendrogramDistance = 'euclidean', linkageType: DendrogramLinkage = 'average'): Cluster {\n const distanceFn = getDistanceFn(distanceType);\n const linkageFn = getLinkageFn(linkageType);\n \n const N = dataValues.length;\n \n // STEP 1: Precompute pairwise distances using upper triangular matrix\n // This reduces memory usage from O(n²) to O(n²/2) by only storing upper triangle\n // Since distance matrix is symmetric: d(i,j) = d(j,i)\n const distances: number[] = [];\n \n // Helper function to access distances in upper triangular matrix\n // Maps 2D coordinates (i,j) to 1D array index\n const getDistance = (i: number, j: number): number => {\n if (i === j) return 0; // Distance to self is always 0\n if (i > j) [i, j] = [j, i]; // Swap to ensure i < j (upper triangular)\n const index = i * N - (i * (i + 1)) / 2 + (j - i - 1);\n return distances[index];\n };\n \n // Helper function to set distances in upper triangular matrix\n const setDistance = (i: number, j: number, value: number): void => {\n if (i > j) [i, j] = [j, i]; // Swap to ensure i < j (upper triangular)\n const index = i * N - (i * (i + 1)) / 2 + (j - i - 1);\n distances[index] = value;\n };\n \n // Calculate all pairwise distances (only upper triangular)\n // This is the most expensive step: O(n²) distance calculations\n for (let i1 = 0; i1 < N; i1++) {\n for (let i2 = i1 + 1; i2 < N; i2++) {\n const v = distanceFn(dataValues[i1], dataValues[i2]);\n setDistance(i1, i2, v);\n } \n }\n\n // STEP 2: Initialize clusters - each point starts as its own cluster\n // This creates the leaf nodes of the dendrogram\n const clusters: Cluster[] = dataValues.map((_, index) => ({\n height: 0, // Height 0 for leaf nodes\n indexes: [index], // Single index per cluster initially\n children: [] // No children for leaf nodes\n }));\n\n // STEP 3: Agglomerative clustering - merge clusters iteratively\n // This is the main clustering loop that builds the hierarchy\n for (let iteration = 0; iteration < N; iteration++) {\n // Stop when only one cluster remains (root of dendrogram)\n if (iteration >= N - 1) break;\n\n // Find the two closest clusters using the selected linkage method\n let nearestDistance = Infinity;\n let nearest1 = 0;\n let nearest2 = 0;\n\n // Check all pairs of clusters (upper triangular to avoid duplicates)\n for (let clusterIdx1 = 0; clusterIdx1 < clusters.length; clusterIdx1++) {\n for (let clusterIdx2 = clusterIdx1 + 1; clusterIdx2 < clusters.length; clusterIdx2++) {\n // Calculate distance between clusters using linkage method\n const distance = linkageFn(clusters[clusterIdx1].indexes, clusters[clusterIdx2].indexes, getDistance);\n \n // Keep track of the closest pair\n if (distance < nearestDistance) {\n nearestDistance = distance;\n nearest1 = clusterIdx1;\n nearest2 = clusterIdx2;\n }\n }\n }\n\n // STEP 4: Merge the two closest clusters\n // Create a new cluster that combines the two closest clusters\n const newCluster = {\n indexes: [...clusters[nearest1].indexes, ...clusters[nearest2].indexes], // Combine all indexes\n height: nearestDistance, // Height is the distance at which clusters were merged\n children: [clusters[nearest1], clusters[nearest2]], // Store the two merged clusters as children\n };\n\n // STEP 5: Update cluster list\n // Remove the two merged clusters and add the new merged cluster\n // Remove higher index first to avoid index shifting issues\n clusters.splice(Math.max(nearest1, nearest2), 1);\n clusters.splice(Math.min(nearest1, nearest2), 1);\n clusters.push(newCluster);\n }\n\n // STEP 6: Return the root cluster with properly ordered keys and indexes\n // The root cluster contains the complete hierarchy\n const rootCluster = clusters[0];\n return {\n ...rootCluster,\n indexes: extractOrderedIndexes(rootCluster) // Ensure indexes are in hierarchical order\n };\n}\n"],"names":["squaredEuclidean","p","q","d","i","euclidean","averageLinkage","setA","setB","getDistance","distance","a","b","completeLinkage","singleLinkage","getLinkageFn","linkage","getDistanceFn","extractOrderedIndexes","cluster","orderedIndexes","traverse","c","child","MAX_CLUSTER_SIZE","getClustersApproximate","dataValues","distanceType","linkageType","getClusters","N","getRandom","randomLcg","sampleIndices","sampleIndicesArray","sampleValues","sampleCluster","assignRemainingPoints","distanceFn","sampleSet","assignments","minDistance","nearestSample","sampleIdx","reconstructWithAssignments","sampleToCluster","findSampleClusters","assignedPointsByCluster","pointIdx","fillCorrectIndexes","assignedPoints","linkageFn","distances","j","index","setDistance","value","i1","i2","v","clusters","_","iteration","nearestDistance","nearest1","nearest2","clusterIdx1","clusterIdx2","newCluster","rootCluster"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"getDendrograms.d.ts","sourceRoot":"","sources":["../../src/heatmap/getDendrograms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,uBAAuB,CAAC;AAE/D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAGhD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE;IACzC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;CAC7D,CAAC,CAAA;AAEF,wBAAgB,cAAc,CAC1B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,EAC/C,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,EAC/C,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC,GACpD,eAAe,CAwDjB"}
1
+ {"version":3,"file":"getDendrograms.d.ts","sourceRoot":"","sources":["../../src/heatmap/getDendrograms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAEjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE;IACzC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;CAC7D,CAAC,CAAA;AAIF,wBAAgB,cAAc,CAC1B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,EAC/C,WAAW,EAAE,mBAAmB,CAAC,aAAa,CAAC,EAC/C,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC,GACpD,eAAe,CAwEjB"}
@@ -1,48 +1,46 @@
1
- import { getClusters as x } from "./getClusters.js";
2
- import B from "../node_modules/d3-hierarchy/src/hierarchy/index.js";
3
- function w(e, o, a, K) {
4
- const { facetKeys: G, xGroupKeys: k, yGroupKeys: m } = e.meta, p = {};
5
- if (o && K.sharedX)
1
+ import { getClustersApproximate as K } from "./getClusters.js";
2
+ import m from "../node_modules/d3-hierarchy/src/hierarchy/index.js";
3
+ function b(t, y, p, B) {
4
+ const { facetKeys: G, xGroupKeys: w, yGroupKeys: E } = t.meta, x = {};
5
+ if (y && B.sharedX)
6
6
  throw Error("Dendrogram on X axis is not available with shared by facets X axis");
7
- return G.forEach((y) => {
8
- const n = {
7
+ return G.forEach((c) => {
8
+ const u = {
9
9
  hierarchyByGroupX: {},
10
10
  hierarchyByGroupY: {}
11
- }, c = e.facets[y];
12
- if (o) {
13
- const r = [];
14
- k.forEach((s) => {
15
- const i = c.xKeysByGroups[s], u = c.yKeys, t = x(
16
- i,
17
- i.map((f) => u.map((l) => {
11
+ }, o = t.facets[c];
12
+ if (y) {
13
+ const i = [];
14
+ w.forEach((s) => {
15
+ const r = o.xKeysByGroups[s], f = o.yKeys, n = K(
16
+ r.map((e) => f.map((l) => {
18
17
  var h;
19
- return ((h = c.cells[f][l]) == null ? void 0 : h.normalizedValue) ?? o.fillNA;
18
+ return ((h = o.cells[e][l]) == null ? void 0 : h.normalizedValue) ?? y.fillNA;
20
19
  })),
21
- o.distance,
22
- o.linkage
23
- );
24
- e.facets[y].xKeysByGroups[s] = t.keys, r.push(...t.keys), n.hierarchyByGroupX[s] = B(t);
25
- }), e.facets[y].xKeys = r;
20
+ y.distance,
21
+ y.linkage
22
+ ), a = n.indexes.map((e) => r[e]);
23
+ t.facets[c].xKeysByGroups[s] = a, i.push(...a), u.hierarchyByGroupX[s] = m(n);
24
+ }), t.facets[c].xKeys = i;
26
25
  }
27
- if (a) {
28
- const r = [];
29
- m.forEach((s) => {
30
- const i = c.yKeysByGroups[s], u = c.xKeys, t = x(
31
- i,
32
- i.map((f) => u.map((l) => {
26
+ if (p) {
27
+ const i = [];
28
+ E.forEach((s) => {
29
+ const r = o.yKeysByGroups[s], f = o.xKeys, n = K(
30
+ r.map((e) => f.map((l) => {
33
31
  var h;
34
- return ((h = c.cells[l][f]) == null ? void 0 : h.normalizedValue) ?? a.fillNA;
32
+ return ((h = o.cells[l][e]) == null ? void 0 : h.normalizedValue) ?? p.fillNA;
35
33
  })),
36
- a.distance,
37
- a.linkage
38
- );
39
- e.facets[y].yKeysByGroups[s] = t.keys, r.push(...t.keys), n.hierarchyByGroupY[s] = B(t);
40
- }), e.facets[y].yKeys = r;
34
+ p.distance,
35
+ p.linkage
36
+ ), a = n.indexes.map((e) => r[e]);
37
+ t.facets[c].yKeysByGroups[s] = a, i.push(...a), u.hierarchyByGroupY[s] = m(n);
38
+ }), t.facets[c].yKeys = i;
41
39
  }
42
- p[y] = n;
43
- }), p;
40
+ x[c] = u;
41
+ }), x;
44
42
  }
45
43
  export {
46
- w as getDendrograms
44
+ b as getDendrograms
47
45
  };
48
46
  //# sourceMappingURL=getDendrograms.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getDendrograms.js","sources":["../../src/heatmap/getDendrograms.ts"],"sourcesContent":["import type {Cluster} from './components/types';\nimport type {GroupedCellsData} from './getCells';\nimport type {HeatmapSettingsImpl} from './HeatmapSettingsImpl';\nimport {getClusters} from './getClusters';\nimport type {HierarchyNode} from 'd3-hierarchy';\nimport {hierarchy} from 'd3-hierarchy';\n\nexport type DendrogramsData = Record<string, {\n hierarchyByGroupX: Record<string, HierarchyNode<Cluster>>;\n hierarchyByGroupY: Record<string, HierarchyNode<Cluster>>;\n}>\n\nexport function getDendrograms(\n groupedCellsData: GroupedCellsData,\n dendrogramX: HeatmapSettingsImpl['dendrogramX'],\n dendrogramY: HeatmapSettingsImpl['dendrogramY'],\n facetSettings: HeatmapSettingsImpl['facetSettings']\n): DendrogramsData {\n const {facetKeys, xGroupKeys, yGroupKeys} = groupedCellsData.meta;\n const result:DendrogramsData = {};\n\n if (dendrogramX && facetSettings.sharedX) {\n throw Error('Dendrogram on X axis is not available with shared by facets X axis');\n }\n\n facetKeys.forEach(facetKey => {\n const facetResult: DendrogramsData[string] = {\n hierarchyByGroupX: {},\n hierarchyByGroupY: {},\n };\n const cellsGroup = groupedCellsData.facets[facetKey];\n if (dendrogramX) {\n const updatedXKeys:string[] = [];\n xGroupKeys.forEach(xGroupKey => {\n const xKeys = cellsGroup.xKeysByGroups[xGroupKey];\n const yKeys = cellsGroup.yKeys;\n const rootCluster = getClusters(\n xKeys,\n xKeys.map(x => yKeys.map(y => (cellsGroup.cells[x][y]?.normalizedValue ?? dendrogramX.fillNA) as number)),\n dendrogramX.distance,\n dendrogramX.linkage\n );\n //set sorted group keys\n groupedCellsData.facets[facetKey].xKeysByGroups[xGroupKey] = rootCluster.keys;\n updatedXKeys.push(...rootCluster.keys);\n facetResult.hierarchyByGroupX[xGroupKey] = hierarchy(rootCluster);\n });\n // set sorted group keys of all groups\n groupedCellsData.facets[facetKey].xKeys = updatedXKeys;\n }\n if (dendrogramY) {\n const updatedYKeys:string[] = [];\n yGroupKeys.forEach(yGroupKey => {\n const yKeys = cellsGroup.yKeysByGroups[yGroupKey];\n const xKeys = cellsGroup.xKeys;\n const rootCluster = getClusters(\n yKeys,\n yKeys.map(y => xKeys.map(x => (cellsGroup.cells[x][y]?.normalizedValue ?? dendrogramY.fillNA) as number)),\n dendrogramY.distance,\n dendrogramY.linkage\n );\n //set sorted group keys\n groupedCellsData.facets[facetKey].yKeysByGroups[yGroupKey] = rootCluster.keys;\n updatedYKeys.push(...rootCluster.keys);\n facetResult.hierarchyByGroupY[yGroupKey] = hierarchy(rootCluster);\n });\n // set sorted group keys of all groups\n groupedCellsData.facets[facetKey].yKeys = updatedYKeys;\n }\n result[facetKey] = facetResult;\n });\n\n return result;\n}\n"],"names":["getDendrograms","groupedCellsData","dendrogramX","dendrogramY","facetSettings","facetKeys","xGroupKeys","yGroupKeys","result","facetKey","facetResult","cellsGroup","updatedXKeys","xGroupKey","xKeys","yKeys","rootCluster","getClusters","x","y","_a","hierarchy","updatedYKeys","yGroupKey"],"mappings":";;AAYO,SAASA,EACZC,GACAC,GACAC,GACAC,GACe;AACf,QAAM,EAAC,WAAAC,GAAW,YAAAC,GAAY,YAAAC,EAAA,IAAcN,EAAiB,MACvDO,IAAyB,CAAA;AAE/B,MAAIN,KAAeE,EAAc;AAC7B,UAAM,MAAM,oEAAoE;AAGpF,SAAAC,EAAU,QAAQ,CAAAI,MAAY;AAC1B,UAAMC,IAAuC;AAAA,MACzC,mBAAmB,CAAA;AAAA,MACnB,mBAAmB,CAAA;AAAA,IAAC,GAElBC,IAAaV,EAAiB,OAAOQ,CAAQ;AACnD,QAAIP,GAAa;AACb,YAAMU,IAAwB,CAAA;AAC9B,MAAAN,EAAW,QAAQ,CAAAO,MAAa;AAC5B,cAAMC,IAAQH,EAAW,cAAcE,CAAS,GAC1CE,IAAQJ,EAAW,OACnBK,IAAcC;AAAA,UAChBH;AAAA,UACAA,EAAM,IAAI,CAAAI,MAAKH,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAC,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,gBAAAC,EAAwB,oBAAmBlB,EAAY;AAAA,WAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA;AAGhB,QAAAD,EAAiB,OAAOQ,CAAQ,EAAE,cAAcI,CAAS,IAAIG,EAAY,MACzEJ,EAAa,KAAK,GAAGI,EAAY,IAAI,GACrCN,EAAY,kBAAkBG,CAAS,IAAIQ,EAAUL,CAAW;AAAA,MACpE,CAAC,GAEDf,EAAiB,OAAOQ,CAAQ,EAAE,QAAQG;AAAA,IAC9C;AACA,QAAIT,GAAa;AACb,YAAMmB,IAAwB,CAAA;AAC9B,MAAAf,EAAW,QAAQ,CAAAgB,MAAa;AAC5B,cAAMR,IAAQJ,EAAW,cAAcY,CAAS,GAC1CT,IAAQH,EAAW,OACnBK,IAAcC;AAAA,UAChBF;AAAA,UACAA,EAAM,IAAI,CAAAI,MAAKL,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAE,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,gBAAAC,EAAwB,oBAAmBjB,EAAY;AAAA,WAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA;AAGhB,QAAAF,EAAiB,OAAOQ,CAAQ,EAAE,cAAcc,CAAS,IAAIP,EAAY,MACzEM,EAAa,KAAK,GAAGN,EAAY,IAAI,GACrCN,EAAY,kBAAkBa,CAAS,IAAIF,EAAUL,CAAW;AAAA,MACpE,CAAC,GAEDf,EAAiB,OAAOQ,CAAQ,EAAE,QAAQa;AAAA,IAC9C;AACA,IAAAd,EAAOC,CAAQ,IAAIC;AAAA,EACvB,CAAC,GAEMF;AACX;"}
1
+ {"version":3,"file":"getDendrograms.js","sources":["../../src/heatmap/getDendrograms.ts"],"sourcesContent":["import type { Cluster } from './components/types';\nimport type { GroupedCellsData } from './getCells';\nimport type { HeatmapSettingsImpl } from './HeatmapSettingsImpl';\nimport { getClustersApproximate } from './getClusters';\nimport type { HierarchyNode } from 'd3-hierarchy';\nimport { hierarchy } from 'd3-hierarchy';\n\nexport type DendrogramsData = Record<string, {\n hierarchyByGroupX: Record<string, HierarchyNode<Cluster>>;\n hierarchyByGroupY: Record<string, HierarchyNode<Cluster>>;\n}>\n\nconst DEBUG = false;\n\nexport function getDendrograms(\n groupedCellsData: GroupedCellsData,\n dendrogramX: HeatmapSettingsImpl['dendrogramX'],\n dendrogramY: HeatmapSettingsImpl['dendrogramY'],\n facetSettings: HeatmapSettingsImpl['facetSettings']\n): DendrogramsData {\n const { facetKeys, xGroupKeys, yGroupKeys } = groupedCellsData.meta;\n const result: DendrogramsData = {};\n\n if (dendrogramX && facetSettings.sharedX) {\n throw Error('Dendrogram on X axis is not available with shared by facets X axis');\n }\n\n facetKeys.forEach(facetKey => {\n const facetResult: DendrogramsData[string] = {\n hierarchyByGroupX: {},\n hierarchyByGroupY: {},\n };\n const cellsGroup = groupedCellsData.facets[facetKey];\n if (DEBUG) {\n // eslint-disable-next-line no-console\n console.time('start x');\n }\n if (dendrogramX) {\n const updatedXKeys: string[] = [];\n xGroupKeys.forEach(xGroupKey => {\n const xKeys = cellsGroup.xKeysByGroups[xGroupKey];\n const yKeys = cellsGroup.yKeys;\n if(DEBUG) {\n // eslint-disable-next-line no-console\n console.log('xKeys source', xKeys.length);\n }\n const rootCluster = getClustersApproximate(\n xKeys.map(x => yKeys.map(y => (cellsGroup.cells[x][y]?.normalizedValue ?? dendrogramX.fillNA) as number)),\n dendrogramX.distance,\n dendrogramX.linkage\n );\n if (DEBUG) {\n // eslint-disable-next-line no-console\n console.log('rootCluster', rootCluster);\n }\n //set sorted group keys\n const newXKeys = rootCluster.indexes.map(i => xKeys[i]);\n groupedCellsData.facets[facetKey].xKeysByGroups[xGroupKey] = newXKeys;\n updatedXKeys.push(...newXKeys);\n facetResult.hierarchyByGroupX[xGroupKey] = hierarchy(rootCluster);\n });\n // set sorted group keys of all groups\n groupedCellsData.facets[facetKey].xKeys = updatedXKeys;\n }\n if (DEBUG) {\n // eslint-disable-next-line no-console\n console.timeEnd('start x');\n }\n if (dendrogramY) {\n const updatedYKeys: string[] = [];\n yGroupKeys.forEach(yGroupKey => {\n const yKeys = cellsGroup.yKeysByGroups[yGroupKey];\n const xKeys = cellsGroup.xKeys;\n const rootCluster = getClustersApproximate(\n yKeys.map(y => xKeys.map(x => (cellsGroup.cells[x][y]?.normalizedValue ?? dendrogramY.fillNA) as number)),\n dendrogramY.distance,\n dendrogramY.linkage\n );\n const newYKeys = rootCluster.indexes.map(i => yKeys[i]);\n //set sorted group keys\n groupedCellsData.facets[facetKey].yKeysByGroups[yGroupKey] = newYKeys;\n updatedYKeys.push(...newYKeys);\n facetResult.hierarchyByGroupY[yGroupKey] = hierarchy(rootCluster);\n });\n // set sorted group keys of all groups\n groupedCellsData.facets[facetKey].yKeys = updatedYKeys;\n }\n result[facetKey] = facetResult;\n });\n\n return result;\n}\n"],"names":["getDendrograms","groupedCellsData","dendrogramX","dendrogramY","facetSettings","facetKeys","xGroupKeys","yGroupKeys","result","facetKey","facetResult","cellsGroup","updatedXKeys","xGroupKey","xKeys","yKeys","rootCluster","getClustersApproximate","x","y","_a","newXKeys","i","hierarchy","updatedYKeys","yGroupKey","newYKeys"],"mappings":";;AAcO,SAASA,EACZC,GACAC,GACAC,GACAC,GACe;AACf,QAAM,EAAE,WAAAC,GAAW,YAAAC,GAAY,YAAAC,EAAA,IAAeN,EAAiB,MACzDO,IAA0B,CAAA;AAEhC,MAAIN,KAAeE,EAAc;AAC7B,UAAM,MAAM,oEAAoE;AAGpF,SAAAC,EAAU,QAAQ,CAAAI,MAAY;AAC1B,UAAMC,IAAuC;AAAA,MACzC,mBAAmB,CAAA;AAAA,MACnB,mBAAmB,CAAA;AAAA,IAAC,GAElBC,IAAaV,EAAiB,OAAOQ,CAAQ;AAKnD,QAAIP,GAAa;AACb,YAAMU,IAAyB,CAAA;AAC/B,MAAAN,EAAW,QAAQ,CAAAO,MAAa;AAC5B,cAAMC,IAAQH,EAAW,cAAcE,CAAS,GAC1CE,IAAQJ,EAAW,OAKnBK,IAAcC;AAAA,UAChBH,EAAM,IAAI,CAAAI,MAAKH,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAC,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,gBAAAC,EAAwB,oBAAmBlB,EAAY;AAAA,WAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA,GAOVmB,IAAWL,EAAY,QAAQ,IAAI,CAAAM,MAAKR,EAAMQ,CAAC,CAAC;AACtD,QAAArB,EAAiB,OAAOQ,CAAQ,EAAE,cAAcI,CAAS,IAAIQ,GAC7DT,EAAa,KAAK,GAAGS,CAAQ,GAC7BX,EAAY,kBAAkBG,CAAS,IAAIU,EAAUP,CAAW;AAAA,MACpE,CAAC,GAEDf,EAAiB,OAAOQ,CAAQ,EAAE,QAAQG;AAAA,IAC9C;AAKA,QAAIT,GAAa;AACb,YAAMqB,IAAyB,CAAA;AAC/B,MAAAjB,EAAW,QAAQ,CAAAkB,MAAa;AAC5B,cAAMV,IAAQJ,EAAW,cAAcc,CAAS,GAC1CX,IAAQH,EAAW,OACnBK,IAAcC;AAAA,UAChBF,EAAM,IAAI,CAAAI,MAAKL,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAE,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,gBAAAC,EAAwB,oBAAmBjB,EAAY;AAAA,WAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA,GAEVuB,IAAWV,EAAY,QAAQ,IAAI,CAAAM,MAAKP,EAAMO,CAAC,CAAC;AAEtD,QAAArB,EAAiB,OAAOQ,CAAQ,EAAE,cAAcgB,CAAS,IAAIC,GAC7DF,EAAa,KAAK,GAAGE,CAAQ,GAC7BhB,EAAY,kBAAkBe,CAAS,IAAIF,EAAUP,CAAW;AAAA,MACpE,CAAC,GAEDf,EAAiB,OAAOQ,CAAQ,EAAE,QAAQe;AAAA,IAC9C;AACA,IAAAhB,EAAOC,CAAQ,IAAIC;AAAA,EACvB,CAAC,GAEMF;AACX;"}
@@ -1,4 +1,4 @@
1
- import { __module as e } from "../../_virtual/index2.js";
1
+ import { __module as e } from "../../_virtual/index3.js";
2
2
  import { __require as o } from "./cjs/react.production.min.js";
3
3
  import { __require as t } from "./cjs/react.development.js";
4
4
  var r;
@@ -1,4 +1,4 @@
1
- import { __module as r } from "../../_virtual/index3.js";
1
+ import { __module as r } from "../../_virtual/index2.js";
2
2
  import { __require as _ } from "./cjs/react-dom.production.min.js";
3
3
  import { __require as t } from "./cjs/react-dom.development.js";
4
4
  function e() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/miplots4",
3
- "version": "1.0.146",
3
+ "version": "1.0.147",
4
4
  "description": "Data visualization library",
5
5
  "author": "erohinaelena",
6
6
  "license": "ISC",