Skip to content
Snippets Groups Projects

feat: new paohvis version and with interactions

Merged Marcos Pieras requested to merge paohvisUpdates into main
5 files
+ 36
256
Compare changes
  • Side-by-side
  • Inline
Files
5
@@ -6,239 +6,10 @@
import { getGroupName } from './ResultNodeLinkParserUseCase';
import { GraphQueryResult, Node } from '@graphpolaris/shared/lib/data-access';
import { MultiGraph } from 'graphology';
import {
PaohvisAxisInfo,
PaohvisData,
PaohvisFilters,
PaohvisNodeInfo,
PaohvisNodeOrder,
Relation,
AugmentedNodeAttributesGraph,
HyperEdgeRange2,
HyperEdgeI2,
} from '../types';
import { PaohvisAxisInfo, PaohvisData, PaohvisFilters, PaohvisNodeInfo, HyperEdgeRange2, HyperEdgeI2 } from '../types';
import AttributeFilterUsecase, { getIds } from './AttributesFilterUseCase';
//import SortUseCase from './SortUseCase';
import {
sortObjectsByDegree,
countRepetition,
getTransformIndices,
sortObjectsByName2Show,
sortByIndicesLength2,
sortByRangeText2,
} from './utils';
import { countRepetition } from './utils';
//type Index = number;
//type Index = number;
/**
* This parser is used to parse the incoming query result to the format that's needed to make the Paohvis table.
*/
export class ToPaohvisDataParserUseCase {
private queryResult: GraphQueryResult;
private xAxisNodeGroup: string;
private yAxisNodeGroup: string;
private paohvisFilters: PaohvisFilters;
public constructor(queryResult: GraphQueryResult) {
this.queryResult = queryResult;
this.xAxisNodeGroup = '';
this.yAxisNodeGroup = '';
this.paohvisFilters = { nodeFilters: [], edgeFilters: [] };
}
/**
* Parses query results to the format that's needed to make a Paohvis table.
* @param axisInfo is the information that's needed to parse everything to the correct axis.
* @param nodeOrder is the order in which the nodes should be parsed.
* @returns the information that's needed to make a Paohvis table.
*/
public parseQueryResult(axisInfo: PaohvisAxisInfo, entityHorizontal: string, entityVertical: string): PaohvisData {
console.log('this.paohvisFilters ', this.paohvisFilters);
this.setAxesNodeGroups(axisInfo, entityHorizontal, entityVertical);
const augmentedNodes: AugmentedNodeAttributesGraph[] = this.queryResult.nodes.map((node: Node) => ({
id: node._id,
attributes: node.attributes,
label: node._id,
}));
//const nodeA: AugmentedNodeAttributesGraph[] = data.nodes.filter((obj) => obj.id.includes(configuration.rowNode));
console.log('augmentedNodes ', this.queryResult.nodes);
const nodesRow: AugmentedNodeAttributesGraph[] = augmentedNodes.filter((node) => {
return node.label == this.yAxisNodeGroup;
});
const nodesColumn: AugmentedNodeAttributesGraph[] = augmentedNodes.filter((node) => {
return node.label == this.xAxisNodeGroup;
});
const nodeIdIndex: { [id: string]: number } = nodesRow.reduce((acc, node, index) => ({ ...acc, [node._id]: index }), {});
const filteredData = AttributeFilterUsecase.applyFilters(this.queryResult, this.paohvisFilters);
//parse nodes
const rowInfo: PaohvisNodeInfo = ToPaohvisDataParserUseCase.parseNodes(nodesRow, this.yAxisNodeGroup, this.xAxisNodeGroup);
let nodeListAttr: any[] = [];
nodeListAttr = nodesRow.map((node) => node._id);
nodeListAttr = nodesRow.map((node) => node._id);
const [resultHyperEdgeRanges, rowsDegree] = ToPaohvisDataParserUseCase.parseHyperEdgeRanges(
nodesColumn,
nodesRow,
filteredData,
axisInfo,
rowInfo,
nodeIdIndex,
this.xAxisNodeGroup,
);
return {
rowLabels: nodeListAttr,
hyperEdgeRanges: resultHyperEdgeRanges,
rowDegrees: rowsDegree,
};
}
/**
* Sets the x-axis and y-axis node groups from the given PaohvisAxisInfo in the parser.
* @param axisInfo is the new PaohvisAxisInfo that will be used.
*/
private setAxesNodeGroups(axisInfo: PaohvisAxisInfo, entityHorizontal: string, entityVertical: string): void {
this.xAxisNodeGroup = entityHorizontal;
this.yAxisNodeGroup = entityVertical;
}
/**
* This parses the nodes to get the information that's needed to parse the hyperedges.
* @param nodes are the nodes from the query result.
* @param hyperEdgeDegree is the dictionary where you can find how many edges connected from the node.
* @param nodeOrder is the order in which the nodes should be sorted.
* @param yAxisNodeType is the type of nodes that should be on the y-axis.
* @param xAxisNodeType is the type of nodes that should be on the x-axis.
* @returns the information that's needed to parse the hyperedges.
*/
private static parseNodes(nodes: Node[], yAxisNodeType: string, xAxisNodeType: string): PaohvisNodeInfo {
//const rowNodes = filterRowNodes(nodes, hyperEdgeDegree, yAxisNodeType);
const rowNodes = nodes; // to list all nodes available, even if they do not have connections
const rowLabels = getIds(rowNodes);
//make dictionary for finding the index of a row
const yNodesIndexDict: Record<string, number> = {};
let yNodeIndexCounter = 0;
for (let i = 0; i < rowNodes.length; i++) {
yNodesIndexDict[rowNodes[i]._id] = yNodeIndexCounter;
yNodeIndexCounter++;
}
const xNodesAttributesDict: Record<string, any> = getXNodesAttributesDict(yAxisNodeType, xAxisNodeType, nodes);
return {
rowLabels: rowLabels,
xNodesAttributesDict: xNodesAttributesDict,
yNodesIndexDict: yNodesIndexDict,
};
}
/**
* Parses the edges to make hyperedge ranges for the Paohvis table.
* @param nodes the unused nodes should already be filtered out.
* @param edges the unused edges should already be filtered out.
* @param axisInfo is the information that's needed to parse the edges to their respective hyperedge range.
* @param rowInfo is the information about the nodes that's needed to parse the edges to their respective hyperedge range.
* @returns the hyperedge ranges that will be used by the Paohvis table.
*/
private static parseHyperEdgeRanges(
nodesColumn: AugmentedNodeAttributesGraph[],
nodesRow: AugmentedNodeAttributesGraph[],
filteredData: GraphQueryResult,
axisInfo: PaohvisAxisInfo,
rowInfo: PaohvisNodeInfo,
nodeIdIndex: { [id: string]: number },
xAxisNodeGroup: string,
): [HyperEdgeRange2[], { [key: string]: number }] {
if (nodesColumn.length == 0 || nodesRow.length == 0) return [[], {}];
let resultHyperEdgeRanges: HyperEdgeRange2[] = nodesColumn.map((element) => {
const rangeText: any = element.attributes[axisInfo.selectedAttribute.name];
const id = element._id;
const degree = 0;
const hyperEdges: HyperEdgeI2 = {
indices: [],
};
return {
rangeText,
hyperEdges,
id,
degree,
};
});
const toOrFrom = axisInfo.relation.to == xAxisNodeGroup ? 'to' : 'from';
const toOrFromOpposite = toOrFrom == 'to' ? 'from' : 'to';
// loop through all edges - and creates hyperedge structure (coluumn order/x)
for (let i = 0; i < filteredData.edges.length; i++) {
const edge = filteredData.edges[i];
const hyperEdgeRange = resultHyperEdgeRanges.find((range) => range._id === edge[toOrFrom])?.hyperEdges;
//console.log(i, edge.from, edge.to, nodeIdIndex[edge[toOrFromOpposite]]);
hyperEdgeRange?.indices.push(nodeIdIndex[edge[toOrFromOpposite]]);
}
// Sequential order in indices and count degree ( remove undefined = nodes without connection )
resultHyperEdgeRanges.forEach((element) => {
element.degree = element.hyperEdges.indices.filter((num) => {
//console.log(num, typeof num);
if (typeof num !== 'number') {
//console.log('Filtered out:', num);
}
return typeof num === 'number';
}).length;
});
resultHyperEdgeRanges.forEach((element) => {
element.hyperEdges.indices.sort((a, b) => a - b);
});
// Count nodes degree from structure
const repetitionCounts: { [key: number]: number } = {};
for (let indexX = 0; indexX < resultHyperEdgeRanges.length; indexX++) {
countRepetition(resultHyperEdgeRanges[indexX].hyperEdges.indices, repetitionCounts);
}
const repetitionCountLabel: { [key: string]: number } = {};
// get nodes ids
rowInfo.rowLabels.forEach((arrayElement, index) => {
repetitionCountLabel[arrayElement] = repetitionCounts[index] === undefined ? 0 : repetitionCounts[index];
});
return [resultHyperEdgeRanges, repetitionCountLabel];
}
/** Sets new PaohvisFilters. */
public setPaohvisFilters(filters: PaohvisFilters): void {
this.paohvisFilters = filters;
}
}
/** Gets a dictionary where you can find the attributes that belong to the nodes on teh x-axis. */
function getXNodesAttributesDict(yAxisNodeType: string, xAxisNodeType: string, nodes: Node[]) {
const resultXNodesAttributesDict: Record<string, any> = {};
// it goes to case1:
if (yAxisNodeType == xAxisNodeType) nodes.forEach((node) => (resultXNodesAttributesDict[node!._id] = node.attributes));
//console.log('cas2 ', yAxisNodeType == xAxisNodeType);
else
nodes.forEach((node) => {
if (getGroupName(node) == xAxisNodeType) resultXNodesAttributesDict[node._id] = node.attributes;
});
return resultXNodesAttributesDict;
}
Loading