@formant/ava
Version:
A framework for automated visual analytics.
189 lines (188 loc) • 8.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var analysis_1 = require("../../analysis");
var graph_1 = require("../../analysis/graph");
var field_1 = require("../../analysis/field");
var utils_1 = require("../../utils");
var dataFrame_1 = tslib_1.__importDefault(require("../field/dataFrame"));
var utils_2 = require("./utils");
/* eslint-disable no-param-reassign */
function parseTreeNode(data, extra) {
var nodes = [];
var links = [];
var childrenKey = (extra === null || extra === void 0 ? void 0 : extra.childrenKey) || 'children';
var parseTree = function (treeNode) {
var children = treeNode[childrenKey] || [];
delete treeNode[childrenKey];
nodes === null || nodes === void 0 ? void 0 : nodes.push(treeNode);
for (var i = 0; i < children.length; i += 1) {
var item = children[i];
links === null || links === void 0 ? void 0 : links.push({
source: treeNode.id,
target: item.id,
});
parseTree(item);
}
};
parseTree(data);
return { nodes: nodes, links: links };
}
/**
* @param data link array
*/
function parseArray(data, extra) {
var _a = tslib_1.__read(data, 1), data0 = _a[0];
(0, utils_1.assert)((0, utils_1.isObject)(data0), 'Data is unable transform to graph');
var sourceKey = (extra === null || extra === void 0 ? void 0 : extra.sourceKey) || ('source' in data0 && 'source') || ('from' in data0 && 'from');
var targetKey = (extra === null || extra === void 0 ? void 0 : extra.targetKey) || ('target' in data0 && 'target') || ('to' in data0 && 'to');
var childrenKey = (extra === null || extra === void 0 ? void 0 : extra.childrenKey) || ('children' in data0 && 'children') || ('to' in data0 && 'to');
(0, utils_1.assert)(sourceKey || targetKey || childrenKey, 'Data is unable transform to graph');
var nodes = [];
var links = [];
var _b = data0, _c = sourceKey, source = _b[_c], _d = targetKey, target = _b[_d], _e = childrenKey, children = _b[_e];
if ((0, utils_1.isBasicType)(source) && (0, utils_1.isBasicType)(target)) {
var _loop_1 = function (i) {
var link = data[i];
var _g = link, _h = sourceKey, source_1 = _g[_h], _j = targetKey, target_1 = _g[_j];
if (nodes.findIndex(function (n) { return n.id === source_1; }) === -1) {
nodes.push({ id: source_1 });
}
if (nodes.findIndex(function (n) { return n.id === target_1; }) === -1) {
nodes.push({ id: target_1 });
}
var formatLink = tslib_1.__assign(tslib_1.__assign({}, link), { source: source_1, target: target_1 });
links.push(formatLink);
};
for (var i = 0; i < data.length; i += 1) {
_loop_1(i);
}
}
else if ((0, utils_1.isArray)(children)) {
// try to parse the array as multiple trees
for (var i = 0; i < data.length; i += 1) {
var tree = data[i];
var _f = parseTreeNode(tree, extra), subNodes = _f.nodes, subLinks = _f.links;
var _loop_2 = function (i_1) {
var node = subNodes[i_1];
var repeatNode = nodes.find(function (n) { return n.id === node.id; });
if (repeatNode) {
repeatNode = tslib_1.__assign(tslib_1.__assign({}, node), repeatNode);
}
else {
nodes.push(node);
}
};
for (var i_1 = 0; i_1 < subNodes.length; i_1 += 1) {
_loop_2(i_1);
}
links.push.apply(links, tslib_1.__spreadArray([], tslib_1.__read(subLinks), false));
}
}
return { nodes: nodes, links: links };
}
function isNodeArray(arr) {
if (!(0, utils_1.isArray)(arr) || arr.length <= 1)
return false;
var nodeIdInfo = (0, analysis_1.analyzeField)(arr.map(function (node) { return node.id; }));
return (0, field_1.isUnique)(nodeIdInfo);
}
function isValidNodeLinks(nodes, links) {
if (!(0, utils_1.isArray)(links) || !isNodeArray(nodes) || links.length <= 1)
return false;
var _loop_3 = function (i) {
var link = links[i];
var source = link.source, target = link.target;
var hasSourceNode = nodes.findIndex(function (item) { return item.id === source; });
var hasTargetNode = nodes.findIndex(function (item) { return item.id === target; });
if (!(hasSourceNode > -1 && hasTargetNode > -1)) {
return { value: false };
}
};
for (var i = 0; i < links.length; i += 1) {
var state_1 = _loop_3(i);
if (typeof state_1 === "object")
return state_1.value;
}
return true;
}
// TODO: The automatic parsing function has not been completed yet, for now, the GraphData constructor only accepts input data in several specified formats (see type GraphInput)
var GraphData = /** @class */ (function () {
function GraphData(data, extra) {
this.data = {
nodes: [],
links: [],
};
this.extra = extra;
var _a = this.autoParse(data, extra), nodes = _a.nodes, links = _a.links;
(0, utils_1.assert)(isValidNodeLinks(nodes, links), 'Data is unable transform to graph');
this.data = {
nodes: nodes.map(function (node) { return (0, utils_2.flatObject)(node); }),
links: links.map(function (link) { return (0, utils_2.flatObject)(link); }),
};
}
GraphData.prototype.autoParse = function (data, extra) {
var nodes;
var links;
(0, utils_1.assert)((0, utils_1.isArray)(data) || (0, utils_1.isObject)(data), 'Data is unable transform to graph');
// try parse data as link array or multiple trees
if ((0, utils_1.isArray)(data)) {
var parsedData = parseArray(data, extra);
nodes = parsedData.nodes;
links = parsedData.links;
}
// if passed data tyoe is object
if ((0, utils_1.isObject)(data)) {
if ((extra === null || extra === void 0 ? void 0 : extra.nodeKey) && (extra === null || extra === void 0 ? void 0 : extra.linkKey)) {
nodes = data[extra.nodeKey];
links = data[extra.linkKey];
}
else if ((extra === null || extra === void 0 ? void 0 : extra.childrenKey) || 'children' in data) {
var parsedTree = parseTreeNode(data, extra);
nodes = parsedTree.nodes;
links = parsedTree.links;
}
else {
var nodeKey = 'nodes' in data && 'nodes';
var linkKey = ('links' in data && 'links') || ('edges' in data && 'edges');
nodes = data[nodeKey];
links = data[linkKey];
}
}
return { nodes: nodes, links: links };
};
GraphData.prototype.getNodeFrame = function () {
var _a, _b;
var extra = {
indexes: (_a = this.extra) === null || _a === void 0 ? void 0 : _a.nodeIndexes,
columns: (_b = this.extra) === null || _b === void 0 ? void 0 : _b.nodeColumns,
};
return new dataFrame_1.default(this.data.nodes, extra);
};
GraphData.prototype.getLinkFrame = function () {
var _a, _b;
var extra = {
indexes: (_a = this.extra) === null || _a === void 0 ? void 0 : _a.linkIndexes,
columns: (_b = this.extra) === null || _b === void 0 ? void 0 : _b.linkColumns,
};
return new dataFrame_1.default(this.data.links, extra);
};
/**
* Get statistics.
*/
GraphData.prototype.info = function () {
var _a = this.data, nodes = _a.nodes, links = _a.links;
// calc fields statistics and structural statistics
var graphStructFeats = (0, graph_1.getAllStructFeats)(nodes, links);
var _b = (0, graph_1.getNodeFields)(nodes), nodeFields = _b.nodeFields, nodeFieldNames = _b.nodeFieldNames;
var _c = (0, graph_1.getLinkFields)(links), linkFields = _c.linkFields, linkFieldNames = _c.linkFieldNames;
var nodeFieldsInfo = (0, graph_1.getAllFieldsInfo)(nodeFields, nodeFieldNames);
var linkFieldsInfo = (0, graph_1.getAllFieldsInfo)(linkFields, linkFieldNames);
var getClusterField = (0, graph_1.clusterNodes)(nodes, nodeFieldsInfo, links);
nodeFieldsInfo.push(getClusterField);
var graphProps = tslib_1.__assign({ nodeFieldsInfo: nodeFieldsInfo, linkFieldsInfo: linkFieldsInfo }, graphStructFeats);
return graphProps;
};
return GraphData;
}());
exports.default = GraphData;