@graphty/graph-io 0.3.41 → 0.3.43
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.
- package/README.md +2 -0
- package/dist/chunks/{children-CL3Cy0ez.js → children-CA4coBi0.js} +36 -27
- package/dist/chunks/children-CA4coBi0.js.map +1 -0
- package/dist/chunks/{choose-CwFQamH9.js → choose-DvpbdRuz.js} +2 -2
- package/dist/chunks/{choose-CwFQamH9.js.map → choose-DvpbdRuz.js.map} +1 -1
- package/dist/chunks/{constants-Cf4Nn6tw.js → constants-fT3E8JYY.js} +2 -2
- package/dist/chunks/{constants-Cf4Nn6tw.js.map → constants-fT3E8JYY.js.map} +1 -1
- package/dist/chunks/{escape-DBb8zuNE.js → escape-B62ZGM_a.js} +2 -2
- package/dist/chunks/{escape-DBb8zuNE.js.map → escape-B62ZGM_a.js.map} +1 -1
- package/dist/chunks/{export-DD3Lvw-F.js → export-rKLeGQMo.js} +232 -128
- package/dist/chunks/export-rKLeGQMo.js.map +1 -0
- package/dist/chunks/{exporter-CS35R6Fg.js → exporter-8hLNemFk.js} +4 -4
- package/dist/chunks/{exporter-CS35R6Fg.js.map → exporter-8hLNemFk.js.map} +1 -1
- package/dist/chunks/{exporter-D8r1N2dU.js → exporter-BWwEuOPT.js} +5 -5
- package/dist/chunks/{exporter-D8r1N2dU.js.map → exporter-BWwEuOPT.js.map} +1 -1
- package/dist/chunks/{exporter-BqtmlxNr.js → exporter-RVtXVetw.js} +36 -22
- package/dist/chunks/exporter-RVtXVetw.js.map +1 -0
- package/dist/chunks/{exporter-NMplSnYn.js → exporter-yLxKBvLE.js} +3 -3
- package/dist/chunks/{exporter-NMplSnYn.js.map → exporter-yLxKBvLE.js.map} +1 -1
- package/dist/chunks/{importer-S-abxJHn.js → importer-BbNb7eNg.js} +111 -71
- package/dist/chunks/importer-BbNb7eNg.js.map +1 -0
- package/dist/chunks/{importer-BdWHmlmG.js → importer-C98dpSH4.js} +5 -5
- package/dist/chunks/{importer-BdWHmlmG.js.map → importer-C98dpSH4.js.map} +1 -1
- package/dist/chunks/{importer-r29cWnEf.js → importer-D794XUTe.js} +3 -3
- package/dist/chunks/{importer-r29cWnEf.js.map → importer-D794XUTe.js.map} +1 -1
- package/dist/chunks/{importer-BfbzWk6k.js → importer-Dz7tI8Sa.js} +5 -5
- package/dist/chunks/{importer-BfbzWk6k.js.map → importer-Dz7tI8Sa.js.map} +1 -1
- package/dist/chunks/{importer-DviEsHy4.js → importer-Ht7LNg8L.js} +4 -4
- package/dist/chunks/{importer-DviEsHy4.js.map → importer-Ht7LNg8L.js.map} +1 -1
- package/dist/chunks/{importer-BKC7AmCA.js → importer-WrGRZb0N.js} +6 -6
- package/dist/chunks/{importer-BKC7AmCA.js.map → importer-WrGRZb0N.js.map} +1 -1
- package/dist/chunks/{importer-BmaZcskq.js → importer-xZ-3suY1.js} +5 -5
- package/dist/chunks/{importer-BmaZcskq.js.map → importer-xZ-3suY1.js.map} +1 -1
- package/dist/chunks/{json-elements-DdF-etPT.js → json-elements-DKSqpNW1.js} +3 -3
- package/dist/chunks/{json-elements-DdF-etPT.js.map → json-elements-DKSqpNW1.js.map} +1 -1
- package/dist/chunks/{ontology-export-BC0zyPhj.js → ontology-export-CtRXjg_i.js} +2 -2
- package/dist/chunks/{ontology-export-BC0zyPhj.js.map → ontology-export-CtRXjg_i.js.map} +1 -1
- package/dist/chunks/{records-Uc3LkABx.js → records-Cu4bxYOm.js} +56 -26
- package/dist/chunks/records-Cu4bxYOm.js.map +1 -0
- package/dist/chunks/{text-Bh9SaAob.js → text-DHOJXnED.js} +2 -2
- package/dist/chunks/{text-Bh9SaAob.js.map → text-DHOJXnED.js.map} +1 -1
- package/dist/csv.js +260 -196
- package/dist/csv.js.map +1 -1
- package/dist/cx.js +1 -1
- package/dist/cx2.js +2 -2
- package/dist/cys.js +1 -1
- package/dist/dot.js +1 -1
- package/dist/gexf.js +5 -4
- package/dist/gexf.js.map +1 -1
- package/dist/gml.js +3 -3
- package/dist/graph-io.js +27 -27
- package/dist/graphml.js +2 -2
- package/dist/json.js +1 -1
- package/dist/neo4j.js +3 -3
- package/dist/obo.js +1 -1
- package/dist/pajek.js +1 -1
- package/dist/src/children.d.ts.map +1 -1
- package/dist/src/children.js +50 -27
- package/dist/src/children.js.map +1 -1
- package/dist/src/common/attributes.d.ts.map +1 -1
- package/dist/src/common/attributes.js +52 -33
- package/dist/src/common/attributes.js.map +1 -1
- package/dist/src/common/input.d.ts.map +1 -1
- package/dist/src/common/input.js +178 -82
- package/dist/src/common/input.js.map +1 -1
- package/dist/src/common/lists.js +30 -15
- package/dist/src/common/lists.js.map +1 -1
- package/dist/src/formats/csv/exporter.d.ts.map +1 -1
- package/dist/src/formats/csv/exporter.js +211 -121
- package/dist/src/formats/csv/exporter.js.map +1 -1
- package/dist/src/formats/csv/importer.d.ts.map +1 -1
- package/dist/src/formats/csv/importer.js +113 -74
- package/dist/src/formats/csv/importer.js.map +1 -1
- package/dist/src/formats/csv/records.d.ts.map +1 -1
- package/dist/src/formats/csv/records.js +60 -26
- package/dist/src/formats/csv/records.js.map +1 -1
- package/dist/src/formats/dot/tokenizer.d.ts +39 -0
- package/dist/src/formats/dot/tokenizer.d.ts.map +1 -1
- package/dist/src/formats/dot/tokenizer.js +112 -66
- package/dist/src/formats/dot/tokenizer.js.map +1 -1
- package/dist/src/formats/gexf/exporter.d.ts.map +1 -1
- package/dist/src/formats/gexf/exporter.js +3 -2
- package/dist/src/formats/gexf/exporter.js.map +1 -1
- package/dist/src/formats/json/dialect.d.ts.map +1 -1
- package/dist/src/formats/json/dialect.js +54 -20
- package/dist/src/formats/json/dialect.js.map +1 -1
- package/dist/src/formats/json/importer.d.ts.map +1 -1
- package/dist/src/formats/json/importer.js +2 -1
- package/dist/src/formats/json/importer.js.map +1 -1
- package/dist/xgmml.js +2 -2
- package/package.json +2 -2
- package/src/children.ts +54 -27
- package/src/common/attributes.ts +59 -30
- package/src/common/input.ts +223 -95
- package/src/common/lists.ts +29 -15
- package/src/formats/csv/exporter.ts +274 -136
- package/src/formats/csv/importer.ts +138 -78
- package/src/formats/csv/records.ts +71 -25
- package/src/formats/dot/tokenizer.ts +118 -68
- package/src/formats/gexf/exporter.ts +3 -2
- package/src/formats/json/dialect.ts +61 -22
- package/src/formats/json/importer.ts +2 -1
- package/dist/chunks/children-CL3Cy0ez.js.map +0 -1
- package/dist/chunks/export-DD3Lvw-F.js.map +0 -1
- package/dist/chunks/exporter-BqtmlxNr.js.map +0 -1
- package/dist/chunks/importer-S-abxJHn.js.map +0 -1
- package/dist/chunks/records-Uc3LkABx.js.map +0 -1
|
@@ -170,6 +170,17 @@ export function sniffJsonDialect(root: unknown): JsonImportDialect | null {
|
|
|
170
170
|
if (!isJsonObject(root)) {
|
|
171
171
|
return null;
|
|
172
172
|
}
|
|
173
|
+
const decided = sniffWrapperDialect(root) ?? sniffEdgelessDialect(root);
|
|
174
|
+
return decided === undefined ? sniffEdgeListDialect(root) : decided;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The dialects a top-level wrapper key settles: Cytoscape `elements`, JGF `graph.nodes` /
|
|
179
|
+
* `graph.edges`, and a `graphs[]` array (OBO Graphs when any graph looks like one, else JGF).
|
|
180
|
+
* @param root - the parsed document object
|
|
181
|
+
* @returns the dialect, or undefined when no wrapper key decides it
|
|
182
|
+
*/
|
|
183
|
+
function sniffWrapperDialect(root: Record<string, unknown>): JsonImportDialect | undefined {
|
|
173
184
|
if (hasKey(root, "elements")) {
|
|
174
185
|
return "cytoscape";
|
|
175
186
|
}
|
|
@@ -180,14 +191,31 @@ export function sniffJsonDialect(root: unknown): JsonImportDialect | null {
|
|
|
180
191
|
// any graph decides: an ontology's first graph may be an empty stub before its imports
|
|
181
192
|
return root.graphs.some((g: unknown) => isJsonObject(g) && isOboGraph(g)) ? "obographs" : "jgf";
|
|
182
193
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* The dialect of a document with neither `edges` nor `links`: NetworkX adjacency_data (`nodes`
|
|
199
|
+
* and `adjacency`), tree_data (`children` without `nodes`), or no graph at all.
|
|
200
|
+
* @param root - the parsed document object
|
|
201
|
+
* @returns the dialect; null for no graph; undefined when the edge-list rules decide
|
|
202
|
+
*/
|
|
203
|
+
function sniffEdgelessDialect(root: Record<string, unknown>): JsonImportDialect | null | undefined {
|
|
204
|
+
if (hasKey(root, "edges") || hasKey(root, "links")) {
|
|
205
|
+
return undefined;
|
|
206
|
+
}
|
|
207
|
+
if (hasKey(root, "nodes")) {
|
|
208
|
+
return hasKey(root, "adjacency") ? "adjacency" : undefined;
|
|
190
209
|
}
|
|
210
|
+
return hasKey(root, "children") ? "tree" : null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* The dialect of a node and edge list document: graphology, vis, d3 or NetworkX node-link.
|
|
215
|
+
* @param root - the parsed document object
|
|
216
|
+
* @returns the dialect
|
|
217
|
+
*/
|
|
218
|
+
function sniffEdgeListDialect(root: Record<string, unknown>): JsonImportDialect {
|
|
191
219
|
const firstNode = firstJsonObject(root.nodes);
|
|
192
220
|
const firstEdge = firstJsonObject(hasKey(root, "edges") ? root.edges : root.links);
|
|
193
221
|
if (isJsonObject(root.options) && (hasKey(root.options, "type") || hasKey(root.options, "multi"))) {
|
|
@@ -197,25 +225,36 @@ export function sniffJsonDialect(root: unknown): JsonImportDialect | null {
|
|
|
197
225
|
// like a graphology or vis field (`attributes`, `undirected`, `key`, `from`) must not re-route it
|
|
198
226
|
const networkx =
|
|
199
227
|
hasKey(root, "links") || hasKey(root, "directed") || hasKey(root, "multigraph") || hasKey(root, "graph");
|
|
200
|
-
|
|
228
|
+
const record = networkx ? undefined : sniffRecordDialect(firstNode, firstEdge);
|
|
229
|
+
if (record !== undefined) {
|
|
230
|
+
return record;
|
|
231
|
+
}
|
|
232
|
+
const bare = !hasKey(root, "directed") && !hasKey(root, "multigraph") && !hasKey(root, "graph");
|
|
233
|
+
return bare && hasKey(root, "links") ? "d3" : "node-link";
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* The graphology or vis dialect, read from the first node and edge records of a document without
|
|
238
|
+
* NetworkX's keys: graphology for a `key` node without `id`, or an edge without `from` that has
|
|
239
|
+
* `undirected` or an `attributes` record; vis for an edge with `from` and `to` but no `source`.
|
|
240
|
+
* @param firstNode - the first node record, or null
|
|
241
|
+
* @param firstEdge - the first edge record, or null
|
|
242
|
+
* @returns the dialect, or undefined when the records name neither
|
|
243
|
+
*/
|
|
244
|
+
function sniffRecordDialect(
|
|
245
|
+
firstNode: Record<string, unknown> | null,
|
|
246
|
+
firstEdge: Record<string, unknown> | null,
|
|
247
|
+
): JsonImportDialect | undefined {
|
|
248
|
+
if (firstNode !== null && hasKey(firstNode, "key") && !hasKey(firstNode, "id")) {
|
|
201
249
|
return "graphology";
|
|
202
250
|
}
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
return "graphology";
|
|
206
|
-
}
|
|
251
|
+
if (firstEdge === null) {
|
|
252
|
+
return undefined;
|
|
207
253
|
}
|
|
208
|
-
if (
|
|
209
|
-
|
|
210
|
-
firstEdge !== null &&
|
|
211
|
-
hasKey(firstEdge, "from") &&
|
|
212
|
-
hasKey(firstEdge, "to") &&
|
|
213
|
-
!hasKey(firstEdge, "source")
|
|
214
|
-
) {
|
|
215
|
-
return "vis";
|
|
254
|
+
if (!hasKey(firstEdge, "from")) {
|
|
255
|
+
return hasKey(firstEdge, "undirected") || isJsonObject(firstEdge.attributes) ? "graphology" : undefined;
|
|
216
256
|
}
|
|
217
|
-
|
|
218
|
-
return bare && hasKey(root, "links") ? "d3" : "node-link";
|
|
257
|
+
return hasKey(firstEdge, "to") && !hasKey(firstEdge, "source") ? "vis" : undefined;
|
|
219
258
|
}
|
|
220
259
|
|
|
221
260
|
/** The node types of OBO Graphs (the OWL entity kinds). */
|
|
@@ -1687,7 +1687,8 @@ function arraySection(value: unknown, what: string, report: ImportReportBuilder)
|
|
|
1687
1687
|
if (!Array.isArray(value)) {
|
|
1688
1688
|
return report.fail(JSON_ISSUE.SHAPE, `${what} must be an array, found ${describe(value)}`, { element: what });
|
|
1689
1689
|
}
|
|
1690
|
-
|
|
1690
|
+
const items: readonly unknown[] = value;
|
|
1691
|
+
return items;
|
|
1691
1692
|
}
|
|
1692
1693
|
|
|
1693
1694
|
/**
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"children-CL3Cy0ez.js","sources":["../../src/children.ts"],"sourcesContent":["/**\n * The children CSR over a containment column: containment\n * (GEXF `pid` / `<parents>`, Cytoscape `parent`, DOT clusters, GraphML nested graphs) is a node\n * column with the `parent` role (u32, refersTo node) or the `parents` role (list of u32) and never\n * enters the CSR of the snapshot. Importers and exporters that need to walk containers top-down\n * (nested subgraphs, cluster blocks, parent lists) build this inverse index once: for every node\n * `u`, `children[rowPtr[u] .. rowPtr[u + 1])` are its children in ascending index order, `roots`\n * are the nodes with no parent, and `depthFirst()` is the pre-order the nested writers use.\n *\n * The helper is deliberately outside the core (7.1: it computes a property the arrays do not\n * already imply and only io needs it). A reference is ignored when it is unset, INVALID_INDEX, out\n * of range, or the node itself; a cycle (a parent chain that never reaches a root) is reported\n * through `unreachable` and its members are appended to the depth-first order in index order so\n * every node is written exactly once.\n */\n\nimport { type Column, type GraphSnapshot, INVALID_INDEX } from \"@graphty/graph-format\";\n\n/**\n * The role of the column a children CSR is built over.\n * @category Plugin helpers\n */\nexport type ContainmentRole = \"parent\" | \"parents\";\n\n/**\n * How the CSR is built: from a role column of the snapshot (default `parent`, then `parents`) or an explicit column.\n * @category Plugin helpers\n */\nexport interface ChildrenOptions {\n /**\n * The column to read: a role name (`parent` for the u32 single-parent column, `parents` for\n * the list column) or a column object of either shape; \"auto\" (default) takes the `parent`\n * role column when the snapshot has one, else `parents`, else no containment; null builds\n * the empty CSR (every node a root) whatever the snapshot holds.\n */\n readonly column?: ContainmentRole | Column | \"auto\" | null | undefined;\n}\n\n/**\n * One depth-first traversal of the containment forest.\n * @category Plugin helpers\n */\nexport interface DepthFirstOrder {\n /** Every node index exactly once: roots in index order, each followed by its descendants, cycle members last. */\n readonly order: Uint32Array;\n /** The depth of every node in the traversal (0 for a root or a cycle member forced to the top). */\n readonly depth: Uint32Array;\n /** Whether `order` differs from `0..n-1`. */\n readonly reordered: boolean;\n}\n\n/**\n * The children CSR of a snapshot's containment column: the inverse\n * of the parent relation as a compressed sparse row structure over node indices.\n * @category Plugin helpers\n */\nexport class ChildrenCsr {\n /** The number of nodes (the row count of the CSR). */\n readonly nodeCount: number;\n /** `rowPtr[u] .. rowPtr[u + 1]` is the range of `children` holding the children of `u`; length nodeCount + 1. */\n readonly rowPtr: Uint32Array;\n /** Child node indices, ascending within each parent's range. */\n readonly children: Uint32Array;\n /** The nodes with no (valid) parent, in index order. */\n readonly roots: Uint32Array;\n /** Every (child, parent) reference kept; equal to `children.length`. */\n readonly edgeCount: number;\n /** References dropped because they were INVALID_INDEX, out of range or self-references. */\n readonly dropped: number;\n /** Nodes whose parent chain never reaches a root (members of a cycle), counted once each. */\n readonly unreachable: number;\n /** The column the CSR was built from, or null when the snapshot has no containment. */\n readonly column: Column | null;\n\n private readonly parentCount: Uint32Array;\n\n /**\n * Build the CSR; use childrenCsr() rather than the constructor.\n * @param nodeCount - the node count\n * @param rowPtr - the row pointers\n * @param children - the child list\n * @param parentCount - parents per node (0 for a root)\n * @param dropped - references ignored\n * @param column - the source column, or null\n */\n constructor(\n nodeCount: number,\n rowPtr: Uint32Array,\n children: Uint32Array,\n parentCount: Uint32Array,\n dropped: number,\n column: Column | null,\n ) {\n this.nodeCount = nodeCount;\n this.rowPtr = rowPtr;\n this.children = children;\n this.parentCount = parentCount;\n this.edgeCount = children.length;\n this.dropped = dropped;\n this.column = column;\n let rootCount = 0;\n for (let u = 0; u < nodeCount; u++) {\n if (parentCount[u] === 0) {\n rootCount++;\n }\n }\n const roots = new Uint32Array(rootCount);\n let r = 0;\n for (let u = 0; u < nodeCount; u++) {\n if (parentCount[u] === 0) {\n roots[r++] = u;\n }\n }\n this.roots = roots;\n this.unreachable = nodeCount - this.reachableCount();\n }\n\n /**\n * The children of a node, as a view into `children` (do not modify).\n * @param node - the node index\n * @returns the child indices in ascending order; empty for a leaf\n */\n childrenOf(node: number): Uint32Array {\n return this.children.subarray(this.rowPtr[node], this.rowPtr[node + 1]);\n }\n\n /**\n * How many children a node has.\n * @param node - the node index\n * @returns the count\n */\n childCount(node: number): number {\n return this.rowPtr[node + 1] - this.rowPtr[node];\n }\n\n /**\n * Whether a node is a container (has at least one child).\n * @param node - the node index\n * @returns true when it has children\n */\n hasChildren(node: number): boolean {\n return this.rowPtr[node + 1] > this.rowPtr[node];\n }\n\n /**\n * How many parents a node has: 0 for a root, 1 under a `parent` column, any number under `parents`.\n * @param node - the node index\n * @returns the parent count\n */\n parentCountOf(node: number): number {\n return this.parentCount[node];\n }\n\n /**\n * Whether a node has no parent.\n * @param node - the node index\n * @returns true for a root\n */\n isRoot(node: number): boolean {\n return this.parentCount[node] === 0;\n }\n\n /**\n * Whether the snapshot has any containment at all.\n * @returns true when at least one child reference was kept\n */\n isEmpty(): boolean {\n return this.edgeCount === 0;\n }\n\n /**\n * A pre-order depth-first traversal from the roots in index order (children in ascending\n * order), then every node not yet visited (a cycle member, or a multi-parent node reached\n * only through a cycle) in index order at depth 0. Each node appears exactly once, so nested\n * writers emit every element once even for a `parents` column that shares a child.\n * @returns the order, the depth of every node and whether the order differs from index order\n */\n depthFirst(): DepthFirstOrder {\n const n = this.nodeCount;\n const order = new Uint32Array(n);\n const depth = new Uint32Array(n);\n const visited = new Uint8Array(n);\n const stackNode: number[] = [];\n const stackCursor: number[] = [];\n let position = 0;\n let reordered = false;\n const place = (u: number, d: number): void => {\n visited[u] = 1;\n if (u !== position) {\n reordered = true;\n }\n order[position++] = u;\n depth[u] = d;\n };\n const visit = (root: number): void => {\n place(root, 0);\n stackNode.push(root);\n stackCursor.push(this.rowPtr[root]);\n while (stackNode.length > 0) {\n const top = stackNode.length - 1;\n const u = stackNode[top];\n const cursor = stackCursor[top];\n if (cursor >= this.rowPtr[u + 1]) {\n stackNode.pop();\n stackCursor.pop();\n continue;\n }\n stackCursor[top] = cursor + 1;\n const v = this.children[cursor];\n if (visited[v] === 1) {\n continue;\n }\n place(v, stackNode.length);\n stackNode.push(v);\n stackCursor.push(this.rowPtr[v]);\n }\n };\n for (const root of this.roots) {\n visit(root);\n }\n for (let u = 0; u < n; u++) {\n if (visited[u] === 0) {\n visit(u);\n }\n }\n return { order, depth, reordered };\n }\n\n /**\n * The nodes reachable from the roots by following child references.\n * @returns how many nodes a traversal from the roots reaches\n */\n private reachableCount(): number {\n const visited = new Uint8Array(this.nodeCount);\n // every node is pushed at most once, so a stack of nodeCount entries never overflows\n const stack = new Uint32Array(this.nodeCount);\n let top = 0;\n let count = 0;\n for (const root of this.roots) {\n visited[root] = 1;\n count++;\n stack[top++] = root;\n while (top > 0) {\n const u = stack[--top];\n for (let k = this.rowPtr[u]; k < this.rowPtr[u + 1]; k++) {\n const v = this.children[k];\n if (visited[v] === 0) {\n visited[v] = 1;\n count++;\n stack[top++] = v;\n }\n }\n }\n }\n return count;\n }\n}\n\n/**\n * Build the children CSR of a snapshot.\n * @param snapshot - the snapshot\n * @param options - which column to read; the `parent` role, then `parents`, by default\n * @returns the CSR; empty (every node a root) when the snapshot has no containment column\n * @category Plugin helpers\n */\nexport function childrenCsr(snapshot: GraphSnapshot, options: ChildrenOptions = {}): ChildrenCsr {\n const column = resolveColumn(snapshot, options.column === undefined ? \"auto\" : options.column);\n return childrenFromColumn(snapshot.nodeCount, column);\n}\n\n/**\n * Build the children CSR over one containment column without a snapshot (an importer that holds\n * the column before freezing, a test).\n * @param nodeCount - the node count the references index into\n * @param column - a u32 `parent`-shaped column, a list-of-u32 `parents`-shaped column, or null for none\n * @returns the CSR\n * @category Plugin helpers\n */\nexport function childrenFromColumn(nodeCount: number, column: Column | null): ChildrenCsr {\n const rowPtr = new Uint32Array(nodeCount + 1);\n const parentCount = new Uint32Array(nodeCount);\n let dropped = 0;\n const references: number[] = [];\n if (column !== null) {\n const rows = Math.min(column.length, nodeCount);\n const keep = (child: number, parent: number): void => {\n if (!Number.isInteger(parent) || parent === INVALID_INDEX || parent >= nodeCount || parent === child) {\n dropped++;\n return;\n }\n references.push(child, parent);\n rowPtr[parent + 1]++;\n parentCount[child]++;\n };\n if (column.dtype === \"u32\") {\n const { data } = column;\n for (let i = 0; i < rows; i++) {\n if (column.isSet(i)) {\n keep(i, data[i]);\n }\n }\n } else if (column.dtype === \"list\") {\n for (let i = 0; i < rows; i++) {\n if (!column.isSet(i)) {\n continue;\n }\n for (const item of column.sliceOf(i)) {\n if (typeof item === \"number\") {\n keep(i, item);\n } else {\n dropped++;\n }\n }\n }\n } else {\n throw new TypeError(\n `a containment column must be u32 or a list of u32, found ${column.dtype} column \"${column.meta.name}\"`,\n );\n }\n }\n for (let u = 0; u < nodeCount; u++) {\n rowPtr[u + 1] += rowPtr[u];\n }\n const children = new Uint32Array(rowPtr[nodeCount]);\n const fill = rowPtr.slice(0, nodeCount);\n // references were collected in ascending child order, so each parent's range fills ascending\n for (let k = 0; k < references.length; k += 2) {\n children[fill[references[k + 1]]++] = references[k];\n }\n return new ChildrenCsr(nodeCount, rowPtr, children, parentCount, dropped, column);\n}\n\n/**\n * The column a ChildrenOptions selects.\n * @param snapshot - the snapshot\n * @param choice - the option value\n * @returns the column, or null when the snapshot has none of that shape\n */\nfunction resolveColumn(snapshot: GraphSnapshot, choice: ContainmentRole | Column | \"auto\" | null): Column | null {\n if (typeof choice !== \"string\") {\n return choice;\n }\n if (choice === \"parent\" || choice === \"parents\") {\n return snapshot.nodes.byRole(choice);\n }\n return snapshot.nodes.byRole(\"parent\") ?? snapshot.nodes.byRole(\"parents\");\n}\n"],"names":[],"mappings":"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"}
|