Skip to content
This repository was archived by the owner on Jan 14, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 48 additions & 55 deletions frontend/src/conformance.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,71 +24,65 @@ function visualizeAlignment(alignedTraces){
const stats = getAlignmentDecorations(alignedTraces)

//set the violation color
/**
* A high level API will be provided: see https://github.com/process-analytics/bpmn-visualization-R/issues/13
*/
let mxGraph = globals.bpmnVisualization.graph
let activityCurrentStyle = null
let activityCell = null

//first reset fill and font color
const graph = globals.bpmnVisualization.graph

// first reset fill and font color
// and remove overlays if existing
let activities = globals.bpmnVisualization.bpmnElementsRegistry.getElementsByKinds(ShapeBpmnElementKind.TASK)
let activityCells = activities.map(elt => mxGraph.getModel().getCell(elt.bpmnSemantic.id))
mxGraph.getModel().beginUpdate()
const activities = globals.bpmnVisualization.bpmnElementsRegistry.getElementsByKinds(ShapeBpmnElementKind.TASK)
const activityCells = activities.map(elt => graph.getModel().getCell(elt.bpmnSemantic.id))

graph.getModel().beginUpdate()
try {
mxgraph.mxUtils.setCellStyles(mxGraph.getModel(), activityCells, "fillColor", "none")
mxgraph.mxUtils.setCellStyles(mxGraph.getModel(), activityCells, "fontColor", "none")
mxgraph.mxUtils.setCellStyles(graph.getModel(), activityCells, mxgraph.mxConstants.STYLE_FILLCOLOR, "none")
mxgraph.mxUtils.setCellStyles(graph.getModel(), activityCells, mxgraph.mxConstants.STYLE_FONTCOLOR, "none")
} finally {
mxGraph.getModel().endUpdate();
graph.getModel().endUpdate();
}

//remove overlays
activities.forEach(act => globals.bpmnVisualization.bpmnElementsRegistry.removeAllOverlays(act.bpmnSemantic.id))


//set violation color
for (const [activityName, violationRatio] of Object.entries(stats.normalizedStats)) {
const activityElement = getBpmnActivityElementbyName(activityName)
if(activityElement){
activityCell = mxGraph.getModel().getCell(activityElement.bpmnSemantic.id)
activityCurrentStyle = mxGraph.getModel().getStyle(activityCell)
mxGraph.getModel().beginUpdate()
try {
let style = mxgraph.mxUtils.setStyle(activityCurrentStyle, "fillColor", myViolationScale(violationRatio*100))
mxGraph.getModel().setStyle(activityCell, style);
activityCurrentStyle = mxGraph.getModel().getStyle(activityCell)
//different way of setting the style
//mxGraph.setCellStyles("fillColor", "red", [activityCell]);

//set violation color
graph.getModel().beginUpdate()
try {
for (const [activityName, violationRatio] of Object.entries(stats.normalizedStats)) {
const activityElement = getBpmnActivityElementbyName(activityName)
if (activityElement) {
const activityCell = graph.getModel().getCell(activityElement.bpmnSemantic.id)
let style = graph.getModel().getStyle(activityCell)
style = mxgraph.mxUtils.setStyle(style, mxgraph.mxConstants.STYLE_FILLCOLOR, myViolationScale(violationRatio * 100))
//set label to white when the activity fillColor is above the scale average
if(violationRatio > 0.5){
style = mxgraph.mxUtils.setStyle(activityCurrentStyle, 'fontColor', 'white')
mxGraph.getModel().setStyle(activityCell, style);
if (violationRatio > 0.5) {
style = mxgraph.mxUtils.setStyle(style, mxgraph.mxConstants.STYLE_FONTCOLOR, 'white')
}
} finally {
mxGraph.getModel().endUpdate();
graph.getModel().setStyle(activityCell, style);

//add overlay
globals.bpmnVisualization.bpmnElementsRegistry.addOverlays(
activityElement.bpmnSemantic.id,
[
getDeviationOverlay(stats.aggStats[activityName].modelMove,
violationRatio,
myViolationScale(violationRatio * 100)),
getSynchronousOverlay(stats.aggStats[activityName].syncMove)
])
}
//add overlay
globals.bpmnVisualization.bpmnElementsRegistry.addOverlays(
activityElement.bpmnSemantic.id,
[
getDeviationOverlay(stats.aggStats[activityName].modelMove,
violationRatio,
myViolationScale(violationRatio*100)),
getSynchronousOverlay(stats.aggStats[activityName].syncMove)
])
}

// Allow to save the style in a new state, in particular keep the rounded activity
graph.refresh();
} finally {
graph.getModel().endUpdate();
}

//add legend
colorLegend({
colorScale: myViolationScale,
title: "% deviations (model moves)"
})

overlayLegend({
leftOverlayLegend: "# conformoties\n(synchronous moves)",
leftOverlayLegend: "# conformoties\n(synchronous moves)",
rightOverlayLegend : "# deviations\n(model moves)"})
}

Expand All @@ -97,17 +91,16 @@ function visualizeAlignment(alignedTraces){
*/
function getAlignmentDecorations(alignments){
//initialize the aggregated statistics for each activity
let aggStats = globals.bpmnActivityElements.map(function(elt){
let result = new Object()
const aggStats = globals.bpmnActivityElements.map(elt => {
let result = {}
result[elt.bpmnSemantic.name] = {syncMove: 0, modelMove: 0}
return result
})

//convert the list aggStats to one object whose keys are the activity names
aggStats = aggStats.reduce(function(obj,item){
const key = Object.keys(item)[0]
obj[key] = item[key];
return obj;
//convert the list aggStats to one object whose keys are the activity names
.reduce((obj, item) => {
const key = Object.keys(item)[0]
obj[key] = item[key];
return obj;
}, {});

//extract the alignments
Expand All @@ -118,7 +111,7 @@ function getAlignmentDecorations(alignments){
//pair[0] is a trace_move, pair[1] is a model_move
if(pair[1] && pair[1] != '>>'){ //pair[1] is not null (tau transitions from petri net) and it is not a log move
pair[1] === pair[0]? aggStats[pair[1]].syncMove++ : aggStats[pair[1]].modelMove++
}
}
}
}

Expand All @@ -129,4 +122,4 @@ function getAlignmentDecorations(alignments){
);

return {"aggStats": aggStats, "normalizedStats": normalizedStats}
}
}
67 changes: 25 additions & 42 deletions frontend/src/discovery.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,55 +47,38 @@ function visualizeFrequency(data) {
const myFrequencyScale = frequencyScale(0, max)

//change activity style through mxGraph
/**
* A high level API will be provided: see https://github.com/process-analytics/bpmn-visualization-R/issues/13
*/
let mxGraph = globals.bpmnVisualization.graph
let activityCurrentStyle = null
let activityCell = null
let graph = globals.bpmnVisualization.graph

//iterate over the activites and set their color by calling the frequency color scale function
for (const [activityName, freqValue] of Object.entries(data)) {
const activityElement = getBpmnActivityElementbyName(activityName)
if(activityElement){
activityCell = mxGraph.getModel().getCell(activityElement.bpmnSemantic.id)
//activityCurrentStyle = mxGraph.getCurrentCellStyle(activityCell)
activityCurrentStyle = mxGraph.getModel().getStyle(activityCell)

mxGraph.getModel().beginUpdate()
try {
let style = mxgraph.mxUtils.setStyle(activityCurrentStyle, 'fillColor', myFrequencyScale(freqValue))
mxGraph.getModel().setStyle(activityCell, style);
activityCurrentStyle = mxGraph.getModel().getStyle(activityCell)
//different ways of setting the style
//mxGraph.setCellStyles("fillColor", myFrequencyScale(freqValue), [activityCell]);
//or
//mxGraph.setCellStyles(mxgraph.mxConstants.STYLE_FILLCOLOR, 'red', [activityCell]);

//set label to white when the activity fillColor is above the scale average
if (freqValue > avg){
style = mxgraph.mxUtils.setStyle(activityCurrentStyle, 'fontColor', 'white')
mxGraph.getModel().setStyle(activityCell, style);
//different way of setting the style
//mxGraph.setCellStyles("fontColor", "white", [activityCell]);
try {
//iterate over the activities and set their color by calling the frequency color scale function
for (const [activityName, freqValue] of Object.entries(data)) {
const activityElement = getBpmnActivityElementbyName(activityName)
if (activityElement) {
const activityCell = graph.getModel().getCell(activityElement.bpmnSemantic.id)
let style = graph.getModel().getStyle(activityCell);
style = mxgraph.mxUtils.setStyle(style, mxgraph.mxConstants.STYLE_FILLCOLOR, myFrequencyScale(freqValue))
if (freqValue > avg) {
style = mxgraph.mxUtils.setStyle(style, mxgraph.mxConstants.STYLE_FONTCOLOR, 'white')
}
} finally {
mxGraph.getModel().endUpdate();
}
graph.getModel().setStyle(activityCell, style);

//add frequency overlay
globals.bpmnVisualization.bpmnElementsRegistry.addOverlays(
activityElement.bpmnSemantic.id,
getFrequencyOverlay(freqValue, max,
myFrequencyScale(freqValue)))
}
//add frequency overlay
globals.bpmnVisualization.bpmnElementsRegistry.addOverlays(
activityElement.bpmnSemantic.id,
getFrequencyOverlay(freqValue, max, myFrequencyScale(freqValue)))
}
}
// Allow to save the style in a new state, in particular keep the rounded activity
graph.refresh();
} finally {
graph.getModel().endUpdate();
}

//add legend
colorLegend({
colorScale: myFrequencyScale,
title: "Frequency of execution"
})
})

overlayLegend({rightOverlayLegend : "# executions"})
}
}