-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* WIP-#1290: Update pipeline.webgmex to incorporate color of line2d(patch) * WIP- #1290: Update the library seed to incorporate subgraphs, add nodes according to newer metamodel in ExecuteJob.metadata.js * #1290- Modify exisiting widget to support updated metamodel (Should close #1290) * WIP #1308, #1290: Create a new Branch For plotly.js visualizer, plotly as a library import * WIP- #1308, #1290: Add single plot support via plotly visualizer(Updates to metamodel might be necessary) * WIP- #1290, #1308: Add Plotly JSON Helper with changeset to the widget * WIP- #1308: Complete ExecutionIndex Graph Creation Logic * WIP- #1308: Add Multiple Execution visualization support to subplots support * WIP: #1308: Remove changeset, matplotlib maps from requirements, changes to clone graph desc * #1308: Checkout LineGraph visualizer from master * #1308:- Refactor ExecutionIndexWidget to consolidate multiple graphs data, Refactor GraphDescExtractor to send plotlyJSON Directly to widget (Widget Display problem for Failed execcutions) * #1308: Fix graph display issue for running executions * Remove invalid codeclimate config * #1308- Codeclimate fix * 1. Use Map insted of ForEach in PlotlyDescExtractor.js 2. Major Update to the pipeline seed, which is now 0.14.0 3. Remove All the var keywords with let/const 4. Check isEmpty without spread operator in plotlyGraphWidget.js, change plotlyJSON to directly be stored as an object 5. Remove Displayed Executions spread operator in ExecutionIndexControl.js 6. Remove widget calls from consolidateGraphData in ExecutionIndexControl.js 7. Remove extrabookkeeping in ExecutionIndexControl 8. Add function called setDisplayName to add default title with execution Abbr in ExecutionIndexControl 9. Refactor _updateGraphData to _updateGraphWidget, _widget methods are called from there in ExecutionIndexControl.js Now. 10. setDisplayedExections in ExecutionIndexWidget now updates the displayedExecutions added or removed. 11. Couple of other minor changes * Remove unused id from plotlyGraphWidget.removeNode * Refactor setDisplayedExecutions to take after clicked states only, change displayedExecutions to an array in ExecutionIndex, change variable name in PlotlyGraphWidget from plotsData to plotlyJSON * Modify subgraph title display, refactor ExecuteJob.Metadata.js to remove createIdToMetadataId * WIP Fixed indentation issues (eslint) * WIP Add plotly.min.js to ignore codeclimate files * WIP minor style fixes
- Loading branch information
1 parent
9575cc3
commit e4585d5
Showing
15 changed files
with
869 additions
and
182 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
/*globals define*/ | ||
define([], function () { | ||
const PlotlyDescExtractor = function (client) { | ||
this._client = client; | ||
}; | ||
|
||
PlotlyDescExtractor.prototype.constructor = PlotlyDescExtractor; | ||
|
||
PlotlyDescExtractor.prototype.getGraphDesc = function (node) { | ||
const id = node.getId(), | ||
jobId = node.getParentId(), | ||
execId = this._client.getNode(jobId).getParentId(); | ||
let desc = { | ||
id: id, | ||
execId: execId, | ||
type: 'graph', | ||
name: node.getAttribute('name'), | ||
graphId: node.getAttribute('id'), | ||
title: node.getAttribute('title'), | ||
}; | ||
let subGraphNodeIds = node.getChildrenIds(); | ||
desc.subGraphs = subGraphNodeIds.map((subGraphNodeId) => { | ||
let subGraphNode = this._client.getNode(subGraphNodeId); | ||
return this.getSubGraphDesc(subGraphNode); | ||
}); | ||
desc.subGraphs.sort(this.compareSubgraphIDs); | ||
return desc; | ||
}; | ||
|
||
PlotlyDescExtractor.prototype.getSubGraphDesc = function (node) { | ||
let id = node.getId(), | ||
graphId = node.getParentId(), | ||
jobId = this._client.getNode(graphId).getParentId(), | ||
execId = this._client.getNode(jobId).getParentId(), | ||
desc; | ||
|
||
desc = { | ||
id: id, | ||
execId: execId, | ||
type: 'subgraph', | ||
graphId: this._client.getNode(graphId).getAttribute('id'), | ||
subgraphId: node.getAttribute('id'), | ||
subgraphName: node.getAttribute('name'), | ||
title: node.getAttribute('title'), | ||
xlim: node.getAttribute('xlim'), | ||
ylim: node.getAttribute('ylim'), | ||
xlabel: node.getAttribute('xlabel'), | ||
ylabel: node.getAttribute('ylabel'), | ||
}; | ||
|
||
const lineIds = node.getChildrenIds(); | ||
desc.lines = lineIds.map((lineId) => { | ||
let lineNode = this._client.getNode(lineId); | ||
return this.getLineDesc(lineNode); | ||
}); | ||
return desc; | ||
}; | ||
|
||
PlotlyDescExtractor.prototype.getLineDesc = function (node) { | ||
let id = node.getId(), | ||
subGraphId = node.getParentId(), | ||
graphId = this._client.getNode(subGraphId).getParentId(), | ||
jobId = this._client.getNode(graphId).getParentId(), | ||
execId = this._client.getNode(jobId).getParentId(), | ||
points, | ||
desc; | ||
|
||
points = node.getAttribute('points').split(';') | ||
.filter(data => !!data) // remove any '' | ||
.map(pair => { | ||
const [x, y] = pair.split(',').map(num => parseFloat(num)); | ||
return {x, y}; | ||
}); | ||
desc = { | ||
id: id, | ||
execId: execId, | ||
subgraphId: this._client.getNode(node.getParentId()).getAttribute('id'), | ||
lineName: node.getAttribute('name'), | ||
label: node.getAttribute('label'), | ||
name: node.getAttribute('name'), | ||
type: 'line', | ||
points: points, | ||
color: node.getAttribute('color') | ||
}; | ||
|
||
return desc; | ||
}; | ||
|
||
|
||
PlotlyDescExtractor.prototype.compareSubgraphIDs = function (desc1, desc2) { | ||
if (desc1.subgraphId >= desc2.subgraphId) return 1; | ||
else return -1; | ||
}; | ||
|
||
PlotlyDescExtractor.prototype.descToPlotlyJSON = function (desc) { | ||
let plotlyJSON = {}; | ||
if (desc) { | ||
plotlyJSON.layout = createLayout(desc); | ||
let dataArr = desc.subGraphs.map((subGraph, index) => { | ||
return createScatterTraces(subGraph, index); | ||
}); | ||
plotlyJSON.data = flatten(dataArr); | ||
const axesData = addAxesLabels(desc.subGraphs); | ||
Object.keys(axesData).forEach((axis) => { | ||
plotlyJSON.layout[axis] = axesData[axis]; | ||
}); | ||
plotlyJSON.id = desc.id; | ||
} | ||
return plotlyJSON; | ||
}; | ||
|
||
/*** Helper Methods For Creating The plotly JSON Reference ***/ | ||
const TraceTypes = { | ||
SCATTER: 'scatter', | ||
IMAGE: 'image' | ||
}; | ||
|
||
const descHasMultipleSubPlots = function (desc) { | ||
return desc.subGraphs.length > 1; | ||
}; | ||
|
||
const createLayout = function (desc) { | ||
let layout = { | ||
title: desc.title, | ||
height: 500 | ||
}; | ||
// Every plot should be drawn as n * 2 Grid?? | ||
if (descHasMultipleSubPlots(desc)) { | ||
const numRows = Math.ceil(desc.subGraphs.length / 2); | ||
layout.height = 250 * numRows; | ||
let subPlots = []; | ||
let currentSubplotAxes; | ||
for (let i = 0; i < numRows * 2; i += 2) { | ||
if (i === 0) | ||
currentSubplotAxes = ['xy', 'x2y2']; | ||
else | ||
currentSubplotAxes = [`x${i + 1}y${i + 1}`, `x${i + 2}y${i + 2}`]; | ||
subPlots.push(currentSubplotAxes); | ||
} | ||
layout.grid = { | ||
subplots: subPlots | ||
}; | ||
layout.annotations = addAnnotations(desc.subGraphs); | ||
} else { | ||
if (!layout.title) | ||
layout.title = desc.subGraphs[0].title; | ||
else | ||
layout.title = { | ||
text: `${layout.title}<br>${desc.subGraphs[0].title}` | ||
}; | ||
} | ||
return layout; | ||
}; | ||
|
||
// https://github.com/plotly/plotly.js/issues/2746#issuecomment-528342877 | ||
// At present the only hacky way to add subplots title | ||
const addAnnotations = function (subGraphs) { | ||
const evenLength = subGraphs.length % 2 === 0 ? subGraphs.length : subGraphs.length + 1; | ||
return subGraphs.map((subGraph, index) => { | ||
const yPosMarker = (index % 2 === 0) ? index : index - 1; | ||
return { | ||
text: `<b>${subGraph.title}</b>`, | ||
font: { | ||
family: 'Arial', | ||
color: 'black', | ||
size: 14 | ||
}, | ||
showarrow: false, | ||
xref: 'paper', | ||
yref: 'paper', | ||
align: 'center', | ||
x: (index % 2 === 0) ? 0.15 : 0.85, | ||
y: (1 - yPosMarker / evenLength) * 1.1 - 0.06 | ||
}; | ||
}); | ||
}; | ||
|
||
const createScatterTraces = function (subGraph, index) { | ||
let traceArr = subGraph.lines.map(line => { | ||
let points = pointsToCartesianArray(line.points); | ||
let traceData = { | ||
x: points[0], | ||
y: points[1], | ||
name: line.label, | ||
type: TraceTypes.SCATTER, | ||
mode: line.marker ? 'line+marker' : 'line', | ||
line: { | ||
width: line.lineWidth ? line.lineWidth : 3, | ||
color: line.color | ||
}, | ||
}; | ||
if (index !== 0) { | ||
traceData.xaxis = `x${index + 1}`; | ||
traceData.yaxis = `y${index + 1}`; | ||
} | ||
return traceData; | ||
}); | ||
return traceArr; | ||
}; | ||
|
||
const addAxesLabels = function (subGraphs) { | ||
let axesData = {}; | ||
subGraphs.forEach((subGraph, index) => { | ||
let xAxisName = `xaxis${index + 1}`; | ||
let yAxisName = `yaxis${index + 1}`; | ||
if (index === 0) { | ||
xAxisName = 'xaxis'; | ||
yAxisName = 'yaxis'; | ||
} | ||
axesData[xAxisName] = { | ||
title: { | ||
text: subGraph.xlabel, | ||
color: '#7f7f7f', | ||
standoff: 0 | ||
} | ||
}; | ||
axesData[yAxisName] = { | ||
title: { | ||
text: subGraph.ylabel, | ||
color: '#7f7f7f', | ||
standoff: 0 | ||
} | ||
}; | ||
}); | ||
return axesData; | ||
}; | ||
|
||
const pointsToCartesianArray = function (points) { | ||
let x = [], | ||
y = []; | ||
points.forEach((point) => { | ||
x.push(point.x); | ||
y.push(point.y); | ||
}); | ||
return [x, y]; | ||
}; | ||
|
||
const flatten = function (arr) { | ||
return arr.reduce(function (flat, toFlatten) { | ||
return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten); | ||
}, []); | ||
}; | ||
|
||
|
||
return PlotlyDescExtractor; | ||
}); |
Oops, something went wrong.