@milaboratories/graph-maker 1.1.161 → 1.1.162

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":"getClusters.js","sources":["../../../../../../node_modules/@milaboratories/miplots4/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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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"getClusters.js","sources":["../../../../../../node_modules/@milaboratories/miplots4/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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","x_google_ignoreList":[0]}
@@ -1,48 +1,46 @@
1
- import { getClusters as m } from "./getClusters.js";
2
- import d from "../node_modules/d3-hierarchy/src/hierarchy/index.js";
3
- function v(s, t, n, G) {
4
- const { facetKeys: K, xGroupKeys: x, yGroupKeys: B } = s.meta, f = {};
5
- if (t && G.sharedX)
1
+ import { getClustersApproximate as d } from "./getClusters.js";
2
+ import x from "../node_modules/d3-hierarchy/src/hierarchy/index.js";
3
+ function X(a, i, c, G) {
4
+ const { facetKeys: K, xGroupKeys: B, yGroupKeys: g } = a.meta, m = {};
5
+ if (i && G.sharedX)
6
6
  throw Error("Dendrogram on X axis is not available with shared by facets X axis");
7
- return K.forEach((a) => {
8
- const u = {
7
+ return K.forEach((s) => {
8
+ const f = {
9
9
  hierarchyByGroupX: {},
10
10
  hierarchyByGroupY: {}
11
- }, o = s.facets[a];
12
- if (t) {
13
- const y = [];
14
- x.forEach((r) => {
15
- const i = o.xKeysByGroups[r], l = o.yKeys, e = m(
16
- i,
17
- i.map((p) => l.map((h) => {
18
- var c;
19
- return ((c = o.cells[p][h]) == null ? void 0 : c.normalizedValue) ?? t.fillNA;
11
+ }, o = a.facets[s];
12
+ if (i) {
13
+ const n = [];
14
+ B.forEach((e) => {
15
+ const t = o.xKeysByGroups[e], p = o.yKeys, y = d(
16
+ t.map((r) => p.map((h) => {
17
+ var l;
18
+ return ((l = o.cells[r][h]) == null ? void 0 : l.normalizedValue) ?? i.fillNA;
20
19
  })),
21
- t.distance,
22
- t.linkage
23
- );
24
- s.facets[a].xKeysByGroups[r] = e.keys, y.push(...e.keys), u.hierarchyByGroupX[r] = d(e);
25
- }), s.facets[a].xKeys = y;
20
+ i.distance,
21
+ i.linkage
22
+ ), u = y.indexes.map((r) => t[r]);
23
+ a.facets[s].xKeysByGroups[e] = u, n.push(...u), f.hierarchyByGroupX[e] = x(y);
24
+ }), a.facets[s].xKeys = n;
26
25
  }
27
- if (n) {
28
- const y = [];
29
- B.forEach((r) => {
30
- const i = o.yKeysByGroups[r], l = o.xKeys, e = m(
31
- i,
32
- i.map((p) => l.map((h) => {
33
- var c;
34
- return ((c = o.cells[h][p]) == null ? void 0 : c.normalizedValue) ?? n.fillNA;
26
+ if (c) {
27
+ const n = [];
28
+ g.forEach((e) => {
29
+ const t = o.yKeysByGroups[e], p = o.xKeys, y = d(
30
+ t.map((r) => p.map((h) => {
31
+ var l;
32
+ return ((l = o.cells[h][r]) == null ? void 0 : l.normalizedValue) ?? c.fillNA;
35
33
  })),
36
- n.distance,
37
- n.linkage
38
- );
39
- s.facets[a].yKeysByGroups[r] = e.keys, y.push(...e.keys), u.hierarchyByGroupY[r] = d(e);
40
- }), s.facets[a].yKeys = y;
34
+ c.distance,
35
+ c.linkage
36
+ ), u = y.indexes.map((r) => t[r]);
37
+ a.facets[s].yKeysByGroups[e] = u, n.push(...u), f.hierarchyByGroupY[e] = x(y);
38
+ }), a.facets[s].yKeys = n;
41
39
  }
42
- f[a] = u;
43
- }), f;
40
+ m[s] = f;
41
+ }), m;
44
42
  }
45
43
  export {
46
- v as getDendrograms
44
+ X as getDendrograms
47
45
  };
48
46
  //# sourceMappingURL=getDendrograms.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getDendrograms.js","sources":["../../../../../../node_modules/@milaboratories/miplots4/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,MAAcN,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,IAAA,GAEjBC,IAAaV,EAAiB,OAAOQ,CAAQ;AACnD,QAAIP,GAAa;AACb,YAAMU,IAAwB,CAAA;AAC9BN,MAAAA,EAAW,QAAQ,CAAAO,MAAa;AAC5B,cAAMC,IAAQH,EAAW,cAAcE,CAAS,GAC1CE,IAAQJ,EAAW,OACnBK,IAAcC;AAAAA,UAChBH;AAAAA,UACAA,EAAM,IAAI,CAAAI,MAAKH,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAC,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,OAAA,SAAAC,EAAwB,oBAAmBlB,EAAY;AAAA,UAAA,CAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA;AAGhBD,QAAAA,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;AAAAA,IAC9C;AACA,QAAIT,GAAa;AACb,YAAMmB,IAAwB,CAAA;AAC9Bf,MAAAA,EAAW,QAAQ,CAAAgB,MAAa;AAC5B,cAAMR,IAAQJ,EAAW,cAAcY,CAAS,GAC1CT,IAAQH,EAAW,OACnBK,IAAcC;AAAAA,UAChBF;AAAAA,UACAA,EAAM,IAAI,CAAAI,MAAKL,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAE,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,OAAA,SAAAC,EAAwB,oBAAmBjB,EAAY;AAAA,UAAA,CAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA;AAGhBF,QAAAA,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;AAAAA,IAC9C;AACAd,IAAAA,EAAOC,CAAQ,IAAIC;AAAAA,EACvB,CAAC,GAEMF;AACX;","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"getDendrograms.js","sources":["../../../../../../node_modules/@milaboratories/miplots4/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,MAAeN,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,IAAA,GAEjBC,IAAaV,EAAiB,OAAOQ,CAAQ;AAKnD,QAAIP,GAAa;AACb,YAAMU,IAAyB,CAAA;AAC/BN,MAAAA,EAAW,QAAQ,CAAAO,MAAa;AAC5B,cAAMC,IAAQH,EAAW,cAAcE,CAAS,GAC1CE,IAAQJ,EAAW,OAKnBK,IAAcC;AAAAA,UAChBH,EAAM,IAAI,CAAAI,MAAKH,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAC,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,OAAA,SAAAC,EAAwB,oBAAmBlB,EAAY;AAAA,UAAA,CAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA,GAOVmB,IAAWL,EAAY,QAAQ,IAAI,CAAAM,MAAKR,EAAMQ,CAAC,CAAC;AACtDrB,QAAAA,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;AAAAA,IAC9C;AAKA,QAAIT,GAAa;AACb,YAAMqB,IAAyB,CAAA;AAC/BjB,MAAAA,EAAW,QAAQ,CAAAkB,MAAa;AAC5B,cAAMV,IAAQJ,EAAW,cAAcc,CAAS,GAC1CX,IAAQH,EAAW,OACnBK,IAAcC;AAAAA,UAChBF,EAAM,IAAI,CAAAI,MAAKL,EAAM,IAAI,CAAAI,MAAA;;AAAM,qBAAAE,IAAAT,EAAW,MAAMO,CAAC,EAAEC,CAAC,MAArB,OAAA,SAAAC,EAAwB,oBAAmBjB,EAAY;AAAA,UAAA,CAAiB,CAAC;AAAA,UACxGA,EAAY;AAAA,UACZA,EAAY;AAAA,QAAA,GAEVuB,IAAWV,EAAY,QAAQ,IAAI,CAAAM,MAAKP,EAAMO,CAAC,CAAC;AAEtDrB,QAAAA,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;AAAAA,IAC9C;AACAhB,IAAAA,EAAOC,CAAQ,IAAIC;AAAAA,EACvB,CAAC,GAEMF;AACX;","x_google_ignoreList":[0]}
@@ -51,8 +51,8 @@ class at extends H {
51
51
  dendrogramX: Y,
52
52
  dendrogramY: E,
53
53
  normalization: _,
54
- NAValueAs: w
55
- } = e, k = Object.values(((a = t.dendrogramX) == null ? void 0 : a.aes) || {}).filter(
54
+ NAValueAs: k
55
+ } = e, w = Object.values(((a = t.dendrogramX) == null ? void 0 : a.aes) || {}).filter(
56
56
  x
57
57
  ), N = Object.values((Y == null ? void 0 : Y.aes) || {}).filter(x), T = Object.values(((r = t.dendrogramY) == null ? void 0 : r.aes) || {}).filter(
58
58
  x
@@ -63,7 +63,7 @@ class at extends H {
63
63
  return t.xColumn.value !== p.value || t.yColumn.value !== D.value || t.valueColumn.value !== f.value || y(t.xGroupBy, A) || y(t.yGroupBy, X) || y(t.facetBy, b) || y(
64
64
  t.annotations.map((C) => C.valueColumn),
65
65
  S.map((C) => C.valueColumn)
66
- ) || y(k, N) || y(T, U) || (e.dendrogramX || t.dendrogramX) && (((n = t.dendrogramX) == null ? void 0 : n.distance) !== ((o = e.dendrogramX) == null ? void 0 : o.distance) || ((s = t.dendrogramX) == null ? void 0 : s.linkage) !== ((m = e.dendrogramX) == null ? void 0 : m.linkage)) || (e.dendrogramY || t.dendrogramY) && (((c = t.dendrogramY) == null ? void 0 : c.distance) !== ((i = e.dendrogramY) == null ? void 0 : i.distance) || ((d = t.dendrogramY) == null ? void 0 : d.linkage) !== ((g = e.dendrogramY) == null ? void 0 : g.linkage)) || t.chartSettings.valueType !== u.valueType || t.facetSettings.sharedX !== G.sharedX || t.facetSettings.sharedY !== G.sharedY || ((l = t.normalization) == null ? void 0 : l.method) !== (_ == null ? void 0 : _.method) || ((v = t.normalization) == null ? void 0 : v.direction) !== (_ == null ? void 0 : _.direction) || t.NAValueAs !== w;
66
+ ) || y(w, N) || y(T, U) || (e.dendrogramX || t.dendrogramX) && (((n = t.dendrogramX) == null ? void 0 : n.distance) !== ((o = e.dendrogramX) == null ? void 0 : o.distance) || ((s = t.dendrogramX) == null ? void 0 : s.linkage) !== ((m = e.dendrogramX) == null ? void 0 : m.linkage)) || (e.dendrogramY || t.dendrogramY) && (((c = t.dendrogramY) == null ? void 0 : c.distance) !== ((i = e.dendrogramY) == null ? void 0 : i.distance) || ((d = t.dendrogramY) == null ? void 0 : d.linkage) !== ((g = e.dendrogramY) == null ? void 0 : g.linkage)) || t.chartSettings.valueType !== u.valueType || t.facetSettings.sharedX !== G.sharedX || t.facetSettings.sharedY !== G.sharedY || ((l = t.normalization) == null ? void 0 : l.method) !== (_ == null ? void 0 : _.method) || ((v = t.normalization) == null ? void 0 : v.direction) !== (_ == null ? void 0 : _.direction) || t.NAValueAs !== k;
67
67
  }
68
68
  _needUpdateCalculatedDataByData(t, e) {
69
69
  const a = Object.keys(t.data), r = Object.keys(e.data);
@@ -1,4 +1,4 @@
1
- import { __module as r } from "../../_virtual/index2.js";
1
+ import { __module as r } 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 e;
@@ -1,4 +1,4 @@
1
- import { __module as _ } from "../../_virtual/index3.js";
1
+ import { __module as _ } from "../../_virtual/index2.js";
2
2
  import { __require as e } from "./cjs/react-dom.production.min.js";
3
3
  import { __require as O } from "./cjs/react-dom.development.js";
4
4
  function r() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@milaboratories/graph-maker",
3
- "version": "1.1.161",
3
+ "version": "1.1.162",
4
4
  "type": "module",
5
5
  "main": "dist/lib.js",
6
6
  "types": "dist/lib.d.ts",
@@ -37,7 +37,7 @@
37
37
  "dependencies": {
38
38
  "@ag-grid-community/core": "^32.3.3",
39
39
  "@milaboratories/helpers": "^1.6.15",
40
- "@milaboratories/miplots4": "^1.0.146",
40
+ "@milaboratories/miplots4": "^1.0.147",
41
41
  "@milaboratories/pf-plots": "^1.1.37",
42
42
  "@platforma-sdk/model": "^1.42.36",
43
43
  "@platforma-sdk/ui-vue": "^1.42.36",