in src/visual.ts [336:503]
public static converter(
dataView: DataView,
colorPalette: IColorPalette,
colorHelper: ColorHelper,
host: IVisualHost,
): ForceGraphData {
const settings: ForceGraphSettings = ForceGraph.parseSettings(dataView, colorHelper);
const metadata: ForceGraphColumns<DataViewMetadataColumn> = ForceGraphColumns.getMetadataColumns(dataView);
const nodes: ForceGraphNodes = {};
let minFiles: number = Number.MAX_VALUE;
let maxFiles: number = 0;
const linkedByName: LinkedByName = {};
const links: ForceGraphLink[] = [];
const linkDataPoints = {};
let linkTypeCount: number = 0;
if (!metadata || !metadata.Source || !metadata.Target) {
return null;
}
let categorical: ForceGraphColumns<DataViewCategoryColumn & DataViewValueColumn[]>
= ForceGraphColumns.getCategoricalColumns(dataView);
if (!categorical
|| !categorical.Source
|| !categorical.Target
|| _.isEmpty(categorical.Source.source)
|| _.isEmpty(categorical.Source.values)
|| _.isEmpty(categorical.Target.source)
|| _.isEmpty(categorical.Target.values)
) {
return null;
}
let sourceCategories: any[] = categorical.Source.values,
targetCategories: any[] = categorical.Target.values,
sourceTypeCategories: any[] = (categorical.SourceType || { values: [] }).values,
targetTypeCategories: any[] = (categorical.TargetType || { values: [] }).values,
linkTypeCategories: any[] = (categorical.LinkType || { values: [] }).values,
weightValues: any[] = (categorical.Weight && categorical.Weight[0] || { values: [] }).values;
let weightFormatter: IValueFormatter = null;
if (metadata.Weight) {
let weightValue: number = settings.links.displayUnits;
if (!weightValue && categorical.Weight && categorical.Weight.length) {
weightValue = categorical.Weight[0].maxLocal as number;
}
weightFormatter = valueFormatter.create({
format: valueFormatter.getFormatStringByColumn(metadata.Weight, true),
precision: settings.links.decimalPlaces,
value: weightValue
});
}
let sourceFormatter: IValueFormatter = valueFormatter.create({
format: valueFormatter.getFormatStringByColumn(metadata.Source, true),
});
let targetFormatter: IValueFormatter = valueFormatter.create({
format: valueFormatter.getFormatStringByColumn(metadata.Target, true),
});
for (let i = 0; i < targetCategories.length; i++) {
const source = sourceCategories[i];
const target = targetCategories[i];
const targetType = targetTypeCategories[i];
const sourceType = sourceTypeCategories[i];
const linkType = linkTypeCategories[i];
const weight = weightValues[i];
linkedByName[`${source},${target}`] = ForceGraph.DefaultValueOfExistingLink;
if (!nodes[source]) {
nodes[source] = {
name: sourceFormatter.format(source),
hideLabel: false,
image: sourceType || ForceGraph.DefaultSourceType,
adj: {},
identity: host.createSelectionIdBuilder()
.withCategory(categorical.Source, i)
.withMeasure(<string>categorical.Source.values[i])
.createSelectionId()
};
}
if (!nodes[target]) {
nodes[target] = {
name: targetFormatter.format(target),
hideLabel: false,
image: targetType || ForceGraph.DefaultTargetType,
adj: {},
identity: host.createSelectionIdBuilder()
.withCategory(categorical.Target, i)
.withMeasure(<string>categorical.Target.values[i])
.createSelectionId()
};
}
let sourceNode: ForceGraphNode = nodes[source],
targetNode: ForceGraphNode = nodes[target];
sourceNode.adj[targetNode.name] = ForceGraph.DefaultValueOfExistingLink;
targetNode.adj[sourceNode.name] = ForceGraph.DefaultValueOfExistingLink;
const tooltipInfo: VisualTooltipDataItem[] = ForceGraphTooltipsFactory.build(
{
Source: source,
Target: target,
Weight: weight,
LinkType: linkType,
SourceType: sourceType,
TargetType: targetType
},
dataView.metadata.columns
);
let link: ForceGraphLink = {
source: sourceNode,
target: targetNode,
weight: Math.max(metadata.Weight
? (weight || ForceGraph.MinWeight)
: ForceGraph.MaxWeight,
ForceGraph.MinWeight),
formattedWeight: weight && weightFormatter.format(weight),
linkType: linkType || ForceGraph.DefaultLinkType,
tooltipInfo: tooltipInfo
};
if (metadata.LinkType && !linkDataPoints[linkType]) {
const color: string = colorHelper.getHighContrastColor(
"foreground",
colorPalette.getColor((linkTypeCount++).toString()).value
);
linkDataPoints[linkType] = {
color,
label: linkType,
};
}
if (link.weight < minFiles) {
minFiles = link.weight;
}
if (link.weight > maxFiles) {
maxFiles = link.weight;
}
links.push(link);
}
return {
nodes,
links,
minFiles,
maxFiles,
linkedByName,
settings,
linkTypes: linkDataPoints,
formatter: targetFormatter
};
}