Commit 22f0cd2d authored by Fintan Mc Gee's avatar Fintan Mc Gee

finished first working versin of Layer / Aspect Combination Functionality

parent 57703ef6
......@@ -141,7 +141,7 @@
<script src="js/controllers/sideMenuController.js"></script>
<script src="js/controllers/temporalLayeringController.js"></script>
<script src="js/controllers/attributeBarChartListController.js"></script>
<!--<script src="js/controllers/aspectCombinationViewController.js"></script>-->
<script src="js/controllers/aspectCombinationViewController.js"></script>
<!-- Font-->
<!--Directives-->
......
<ng-include src="'./html/templates/topAspectDataToolBar.html'"></ng-include>
<H2 class="centered"><span>Aspect Combination</span></H2>
<div ng-controller="aspectCombinationViewCtrl" ng-init="init()">
<div class="centeredDiv" style="position:relative;display:inline-block;width: 95%;">
<div class="row">
<div class="col-sm-1"><label>Aspect</label> </div>
<div class="col-sm-2">
<select class="form-control" id="primaryAspect" ng-model="model.selectedPrimaryAspectName" ng-change="changePrimaryAspect()" >
<option ng-selected="{{pAspect === model.selectedPrimaryAspectName}}" ng-repeat="pAspect in model.availablePrimaryAspects" value="{{pAspect}}">{{pAspect}}</option>
</select>
</div>
<div class="col-sm-1"><label>layer</label> </div>
<div class="col-sm-2">
<select class="form-control" id="primarylayer" ng-model="model.selectedPrimaryLayerLocal" ng-change="changePrimaryLayer()" >
<option ng-selected="{{pLayer === model.selectedPrimaryLayerLocal}}" ng-repeat="pLayer in model.primaryLayerList" value="{{pLayer}}">{{pLayer}}</option>
</select>
</div>
<div class="col-sm-2">
<div class="btn btn-default" ng-click="combineAspects()">Combine</div>
</div>
<div class="col-sm-2"><label>Secondary Aspect</label> </div>
<div class="col-sm-2">
<select class="form-control" id="secondaryAspect" ng-model="model.selectedSecondaryAspectName" ng-change="changeSecondaryAspect()" >
<option ng-selected="{{sAspect === model.selectedSecondaryAspectName}}" ng-repeat="sAspect in model.availableSecondaryAspects" value="{{sAspect}}">{{sAspect}}</option>
</select>
</div>
</div>
<div class="row">
<div class="centeredDiv" id = "graphPanel" style = "height: 100%; white-space: nowrap; overflow-x: scroll; overflow-y: hidden;">
<div ng-repeat = "cGraph in model.displayGraphs" style = "display: inline-block; width: 50%; height: 60%;">
<div class="centeredDiv">{{cGraph.graphDisplayName}}</div>
<!--<svg-directive class= "bordered-graph-custom_size" givenId="{{cGraph.tagName}}" graphname="{{cGraph.graph}}" combinationName = "{{model.combinationName}}" width=0.45 height = 0.8 selectacrossalllayers = "true"></svg-directive>-->
<svg-labels-directive class= "bordered-graph-custom_size" givenId="{{cGraph.tagName}}" graphname="{{cGraph.graph}}" combinationName = "{{model.combinationName}}" width=0.45 height = 0.8 selectacrossalllayers = "true"></svg-labels-directive >
</div>
</div>
</div>
</div>
</div>
<!--<H2 class = "centered"><span>SVG Rendering</span></H2>-->
<svg-directive class="bordered-graph"></svg-directive>
<div class ="centeredDiv" id="graphDiv"></div>
<ng-include src="'./html/templates/simpleGraphOptions.html'"></ng-include>
......
......@@ -68,6 +68,9 @@ angular.module(
$routeProvider.when('/bioList', {
templateUrl: 'html/partials/bioListView.html'
});
$routeProvider.when('/aspectCombination', {
templateUrl: 'html/partials/aspectCombinationView.html'
});
$routeProvider.when('/nodeLinkList', {
templateUrl: 'html/partials/nodeLinkListView.html'
});
......
......@@ -544,6 +544,8 @@ angular.module('blizaarModule.controllers', [])
if(params !== undefined && params.graphname !== undefined) {
graphData = multiLayerGraphService.getLayerByName(params.graphname);
}
return graphData;
}
......
/**************************************
* 'aspectCombinationViewCtrl'
* based on original 'GraphFileAndRenderCtrl' Angular controller
* Functionality: Combine aspect to foem graphs across layer definitions
*
* Created By : Fintan McGee(LIST)
* Date: 11/005/2019
*
*******************************/
angular.module('blizaarModule.controllers')
.controller('aspectCombinationViewCtrl', ['$scope', 'dataService', 'multiLayerGraphService', 'graphLayeringService','$rootScope',
function ($scope, dataService,multiLayerGraphService, graphLayeringService, $rootScope) {
// Declare the model, (this overwrites the parent Controllers model, so we cannot inherit from it)
$scope.model = {};
// Will store the selected source
$scope.model.selectedPrimaryAspectName = undefined;
$scope.model.availablePrimaryAspects = undefined;
$scope.model.primaryLayerList = [];
$scope.model.selectedPrimaryLayerLocal = undefined;
$scope.model.currentCombinationName = "";
$scope.model.selectedSecondaryAspectName = "";
$scope.model.availableSecondaryAspects = [];
$scope.model.displayGraphs = []; //grphs to be displaxed in a row
// usually of the form {graphDisplayName; graph: [ref]}
/**************************************
* initializeAspects()
* Functionality: Initialize the combo containing the list of accessible sources
*
* Created By : Fintan McGee (LIST)
* Date: 11/02/20119
*******************************/
$scope.initializeAspects = function() {
$scope.model.availablePrimaryAspects =[]
$scope.model.availableSecondaryAspects = [];
if(multiLayerGraphService.getGraph().aspects) {
$scope.model.selectedPrimaryAspectName = $scope.getGlobalSelectedAspect();
for (var aspectName in multiLayerGraphService.getGraph().aspects) {
$scope.model.availablePrimaryAspects.push(aspectName);
if(aspectName !== $scope.model.selectedPrimaryAspectName ) {
$scope.model.availableSecondaryAspects.push(aspectName);
}
}
}
};
// $scope.changeAspect = function(){
// $scope.setGlobalSelectedAspect($scope.model.selectedAspectName );
// angular.element(document).ready(function () {
// $rootScope.$broadcast('refreshGraph');
// });
// }
//
$scope.$on('aspectsUpdated', function(){
$scope.initializeAspects();
// createChart();
});
$scope.populateprimaryLayerList = function () {
if(multiLayerGraphService.getGraph()) {
//$scope.model.selectedLayer = $scope.getCurrentlySelectedLayer();
if($scope.model.selectedPrimaryAspectName) {
$scope.model.primaryLayerList = [];
multiLayerGraphService.getGraph().getAspectLayers($scope.model.selectedPrimaryAspectName).forEach(function (layer) {
if (layer.name !== $scope.model.selectedPrimaryLayerLocal) {
$scope.model.primaryLayerList.push(layer.name);
}
});
var currentLayer = $scope.getCurrentlySelectedLayer();
if ($scope.model.primaryLayerList.indexOf(currentLayer) > -1) {
$scope.model.selectedPrimaryLayerLocal = $scope.getCurrentlySelectedLayer()
} else {
$scope.model.selectedPrimaryLayerLocal = $scope.model.primaryLayerList[0];
}
}
}
};
$scope.init = function () {
$scope.initializeAspects();
$scope.populateprimaryLayerList();
}
$scope.changePrimaryAspect = function() {
$scope.populateprimaryLayerList();
$scope.model.selectedPrimaryLayerLocal = "";
$scope.model.availableSecondaryAspects = [];
if(multiLayerGraphService.getGraph().aspects) {
for (var aspectName in multiLayerGraphService.getGraph().aspects) {
if(aspectName !== $scope.model.selectedPrimaryAspectName ) {
$scope.model.availableSecondaryAspects.push(aspectName);
}
}
}
}
$scope.changePrimaryLayer = function() {
}
$scope.changeSecondaryAspect = function() {
}
$scope.getLayerID = function (graphName){
var graphIndex = 9999;
$scope.model.primaryLayerList.forEach(function(layer,index) {
if(layer === graphName) {
graphIndex = index + 1;
}
});
return graphIndex;
}
$scope.combineAspects= function(){
$scope.model.displayGraphs = [];
if(!$scope.model.selectedSecondaryAspectName || $scope.model.selectedSecondaryAspectName.length < 1) {
// just load the primary layers for the currently select aspect ...., i.e. the layer list
$scope.model.primaryLayerList.forEach(function(layerName) {
$scope.model.displayGraphs.push({graphDisplayName: layerName, graph: layerName, tagName:"graph_" + ($scope.model.displayGraphs.length + 1) })
});
} else {
var masterGraph = multiLayerGraphService.getGraph();
$scope.model.combinationName = masterGraph.createCombination($scope.model.selectedPrimaryLayerLocal, $scope.model.selectedSecondaryAspectName);
masterGraph.aspectCombinations.forEach(function(combinationLayer) {
$scope.model.displayGraphs.push({graphDisplayName: combinationLayer.name, graph: combinationLayer.name, tagName:"graph_" + ($scope.model.displayGraphs.length + 1) })
});
}
}
$scope.$watch('model.selectedLayerLocal', function(newData, oldData){
// layer has changged need to refresh the graph
if(newData !== oldData) {
$scope.setCurrentlySelectedLayer([newData]);
$scope.refreshGraph();
}
});
$scope.$watch('model.selectedAspectName', function(newData, oldData){
// layer has changged need to refresh the graph
if(newData !== oldData) {
$scope.populateprimaryLayerList();
}
});
$scope.$on('loadedUserGraph', function() {
$scope.initializeAspects();
});
}]);
\ No newline at end of file
......@@ -27,7 +27,8 @@ angular.module('blizaarModule.controllers')
list:{name: "list",fullName: "List",enabled: true, index:10},
DHList:{name: "DHList",fullName: "DH List",enabled: true, index:11},
bioList:{name: "bioList",fullName: "Bio List",enabled: true, index:1},
nodeLinkList:{name: "nodeLinkList",fullName: "Node Link List",enabled: true, index:1},
nodeLinkList:{name: "nodeLinkList",fullName: "Node Link List",enabled: true, index:2},
aspectCombination:{name: "aspectCombination", fullName: "Aspect Combination", enabled:true, index:3},
smallMultiples:{name: "smallMultiples",fullName: "Small Multiples",enabled: true, index:12},
layerComparison:{name: "layerComparison",fullName: "Layer Comparison",enabled: true, index:13},
nodeLinkAttribute:{name: "nodeLinkAttribute", fullName: "Node Link Attribute",enabled:true, index: 14},
......
......@@ -27,7 +27,7 @@ angular.module('blizaarModule.directives')
* @param params.width used to scale the view width
* @param params.height ed to scale the view height
*/
template: '<div class ="centeredDiv"></div>',
template: '<div></div>',
link: function (scope, element, params) {
console.log("svgDirective installed");
scope.setRenderType('SVG');
......
......@@ -49,6 +49,8 @@ var MultiLayerGraph = function (nodes, links, layerName) {
g.linkTypeList = [];
g.interLayerEdgeMap = null;
g.aspectCombinations = []; //aspect combinatinas are a sungle layer difded by other layers.
// utility functions
// var compareIds = function (a, b) {
......@@ -1398,6 +1400,13 @@ var MultiLayerGraph = function (nodes, links, layerName) {
}
if(!foundLayer) {
// console.log("getLayerByName could not find the specified layer" + layerName );
// maybe if is a combinatin layer
g.aspectCombinations.forEach(function (layer) {
if (layer.name === layerName) {
foundLayer = layer;
console.log("getLayerByName found the specified layer in a combination: " + layerName );
}
});
}
return foundLayer;
};
......@@ -2622,11 +2631,11 @@ var MultiLayerGraph = function (nodes, links, layerName) {
sourceLayer = g.getLayerByName(sourceLayerName),
targetLayer = g.getLayerByName(targetLayerName);
if(g.name != "MasterLayer") {
console.log("Error:copyNodeLayout was called on layer other than master");
console.log("Error:getCommonNodeUids was called on layer other than master");
return;
}
if(!sourceLayer || !targetLayer) {
console.log("Error:copyNodeLayout: either source or target layer name not found");
console.log("Error:getCommonNodeUids: either source or target layer name not found");
return;
}
......@@ -2638,6 +2647,40 @@ var MultiLayerGraph = function (nodes, links, layerName) {
});
return commmonNodeList;
}
/** getCommonEdgeUids
*
* Functionality: Get the intersection of node Ids between 2 layers
*
* @param sourceLayerName :name of the source layer
* @param targetLayerName : name of the target layer
* * @return an array of the common ID
*
* Created By : Fintan McGee (LIST)
* Date: 26/09/2018
*/
g.getCommonEdgeUids= function(sourceLayerName,targetLayerName) {
var commmonEdgeList = [],
sourceLayer = g.getLayerByName(sourceLayerName),
targetLayer = g.getLayerByName(targetLayerName);
if(g.name != "MasterLayer") {
console.log("Error:getCommonEdgeUids was called on layer other than master");
return;
}
if(!sourceLayer || !targetLayer) {
console.log("Error:getCommonEdgeUids: either source or target layer name not found");
return;
}
sourceLayer.links.forEach(function(edge) {
var targetLink = targetLayer.link[edge.uid];
if(targetLink) {
commmonEdgeList.push(edge.uid);
}
});
return commmonEdgeList;
}
/** getDistinctNodeUids
*
* Functionality: Get the diffence of node Ids between 2 layers
......@@ -3273,6 +3316,12 @@ var MultiLayerGraph = function (nodes, links, layerName) {
};
g.setNodeProperty =function(uid,propName, propValue) {
if(!g.node) {
g.buildNodeLookUp();
}
if(!uid || !g.node[uid]) {
console.log( "unrecgognised node for set property : layer" + g.name + " uid:" + uid + " propName:"+ propName + " propValue:" + propValue+ "")
}
if(g.isLocalLayerProperty(propName)) {
g.node[uid][propName] = propValue;
} else {
......@@ -3280,6 +3329,7 @@ var MultiLayerGraph = function (nodes, links, layerName) {
}
};
g.getLinkProperty =function(uid,propName) {
if(g.isLocalLayerProperty(propName)) {
return g.link[uid][propName];
......@@ -3401,7 +3451,75 @@ var MultiLayerGraph = function (nodes, links, layerName) {
return layerArray;
}
/**************************************
* createCombination()
* Functionality: Divdes the target layer into sublayers based on teh layers defined in the other aspec
* new layes are stored as a special combination at the master layer. ONly one combinatin is stored at a time
*
* @param a JSON object containing the asapects names of keys, and and array of layer names for each aspect
* Created By : Fintan McGee (LIST)
* Date: 21/02/2019
********************************/
g.createCombination = function (targetLayerName, otherAspectname) {
if (g.name != "MasterLayer") {
console.log("Error:createCombination was called on layer other than master");
return;
}
var combinationName = targetLayerName + "_by_" + otherAspectname;
var targetLayer = g.getLayerByName(targetLayerName);
var aspectLayers = g.getAspectLayers(otherAspectname);
g.aspectCombinations = [] ; // wilkl be a lsit of mutilyer grrahs
g.aspectCombinationName = combinationName;
aspectLayers.forEach(function(aspectLayer) {
var newLayerName = "[" + targetLayerName +"]-BY-[" + aspectLayer.name + "]";
var commonNodeUids = g.getCommonNodeUids(targetLayer.name,aspectLayer.name);
var commonEdgeUids = g.getCommonEdgeUids(targetLayer.name,aspectLayer.name);
var newIntersectionLayer = MultiLayerGraph([], [],newLayerName);
newIntersectionLayer.master = g;
commonNodeUids.forEach(function(n_id) {
if (g.node[n_id]) {
newIntersectionLayer.copyNodeToLayer(g.node[n_id]);
}
});
commonEdgeUids.forEach(function(l_id) {
if(g.link[l_id]) {
newIntersectionLayer.copyEdgeToLayer(g.link[l_id]);
}
});
newIntersectionLayer.buildNodeLookUp();
newIntersectionLayer.buildLinkLookUp();
newIntersectionLayer.buildAdjacencyList();
newIntersectionLayer.buildEdgeList();
newIntersectionLayer.prepareGraph();
g.aspectCombinations.push(newIntersectionLayer);
});
console.log("Created Combination: "+ combinationName);
return combinationName;
};
g.getCombinationLayerByName = function(combinationLayerName) {
var resultLayer = null;
g.aspectCombinations.forEach(function(layer) {
if(layer.name === combinationLayerName) {
resultLayer = layer;
}
});
return resultLayer;
}
/**************************************
* toJSON()
* Functionality: When sending as JSON need to remove all cyclical References
......@@ -3415,8 +3533,8 @@ var MultiLayerGraph = function (nodes, links, layerName) {
var jsonVersion = {};
jsonVersion.nodes = g.nodes;
jsonVersion.links = g.links;
jsonVersion.name = g.name
jsonVersion.master = "MasterLayer"
jsonVersion.name = g.name;
jsonVersion.master = "MasterLayer";
jsonVersion.layers = g.layers
var aspectsByName = {};
......@@ -3466,6 +3584,8 @@ var MultiLayerGraph = function (nodes, links, layerName) {
}
sVersion.aspects = aspectsByName;
sVersion.aspects["Master"] = [];
g.layers.forEach(function(layer) {
......
......@@ -18,9 +18,9 @@ module.exports = {
Rserve_host: "127.0.0.1",
Rserve_port: "6311",
views: {
admin: ["loadData", "svgView","nodeLink", "canvas2dView", "sigmaView","webglView","hiveplotList","Multiple_Edges", "hiveplot", "setGraphQBE", "list","nodeLinkList","nodeLinkAttribute","DHList", "bioList","smallMultiples","layerComparison","admin"],
cvce: ["DHList","nodeLink","setGraphQBE", "svgView", "hiveplot","hiveplotList","nodeLinkList","smallMultiples","layerComparison"],
biology:[ "setGraphQBE","bioList","nodeLink","svgView", "hiveplot","hiveplotList", "nodeLinkList","nodeLinkAttribute","smallMultiples","layerComparison"],
admin: ["loadData", "svgView","nodeLink", "canvas2dView", "sigmaView","webglView","aspectCombination","hiveplotList","Multiple_Edges", "hiveplot", "setGraphQBE", "list","nodeLinkList","nodeLinkAttribute","DHList", "bioList","smallMultiples","layerComparison","admin"],
cvce: ["DHList","nodeLink","setGraphQBE", "svgView","aspectCombination", "hiveplot","hiveplotList","nodeLinkList","smallMultiples","layerComparison"],
biology:[ "setGraphQBE","bioList","nodeLink","aspectCombination","svgView", "hiveplot","hiveplotList", "nodeLinkList","nodeLinkAttribute","smallMultiples","layerComparison"],
//default: ["loadData", "svgView", "Multiple_Edges", "hiveplot", "setGraphQBE", "list","DHList","bioList","nodeLinkList","smallMultiples"]
default: []
}
......
......@@ -1420,6 +1420,13 @@ var MultiLayerGraph = function (nodes, links, layerName) {
}
if(!foundLayer) {
// console.log("getLayerByName could not find the specified layer" + layerName );
// maybe if is a combinatin layer
g.aspectCombinations.forEach(function (layer) {
if (layer.name === layerName) {
foundLayer = layer;
console.log("getLayerByName found the specified layer in a combination: " + layerName );
}
});
}
return foundLayer;
};
......@@ -2644,11 +2651,11 @@ var MultiLayerGraph = function (nodes, links, layerName) {
sourceLayer = g.getLayerByName(sourceLayerName),
targetLayer = g.getLayerByName(targetLayerName);
if(g.name != "MasterLayer") {
console.log("Error:copyNodeLayout was called on layer other than master");
console.log("Error:getCommonNodeUids was called on layer other than master");
return;
}
if(!sourceLayer || !targetLayer) {
console.log("Error:copyNodeLayout: either source or target layer name not found");
console.log("Error:getCommonNodeUids: either source or target layer name not found");
return;
}
......@@ -2660,6 +2667,40 @@ var MultiLayerGraph = function (nodes, links, layerName) {
});
return commmonNodeList;
}
/** getCommonEdgeUids
*
* Functionality: Get the intersection of node Ids between 2 layers
*
* @param sourceLayerName :name of the source layer
* @param targetLayerName : name of the target layer
* * @return an array of the common ID
*
* Created By : Fintan McGee (LIST)
* Date: 26/09/2018
*/
g.getCommonEdgeUids= function(sourceLayerName,targetLayerName) {
var commmonEdgeList = [],
sourceLayer = g.getLayerByName(sourceLayerName),
targetLayer = g.getLayerByName(targetLayerName);
if(g.name != "MasterLayer") {
console.log("Error:getCommonEdgeUids was called on layer other than master");
return;
}
if(!sourceLayer || !targetLayer) {
console.log("Error:getCommonEdgeUids: either source or target layer name not found");
return;
}
sourceLayer.links.forEach(function(edge) {
var targetLink = targetLayer.link[edge.uid];
if(targetLink) {
commmonEdgeList.push(edge.uid);
}
});
return commmonEdgeList;
}
/** getDistinctNodeUids
*
* Functionality: Get the diffence of node Ids between 2 layers
......@@ -3369,7 +3410,6 @@ var MultiLayerGraph = function (nodes, links, layerName) {
layer.buildNodeLookUp();
layer.buildLinkLookUp();
});
}
g.setUID();
g.buildNodeLookUp();
......@@ -3431,7 +3471,75 @@ var MultiLayerGraph = function (nodes, links, layerName) {
return layerArray;
}
/**************************************
* createCombination()
* Functionality: Divdes the target layer into sublayers based on teh layers defined in the other aspec
* new layes are stored as a special combination at the master layer. ONly one combinatin is stored at a time
*
* @param a JSON object containing the asapects names of keys, and and array of layer names for each aspect
* Created By : Fintan McGee (LIST)
* Date: 21/02/2019
********************************/
g.createCombination = function (targetLayerName, otherAspectname) {
if (g.name != "MasterLayer") {
console.log("Error:createCombination was called on layer other than master");
return;
}
var combinationName = targetLayerName + "_by_" + otherAspectname;
var targetLayer = g.getLayerByName(targetLayerName);
var aspectLayers = g.getAspectLayers(otherAspectname);
g.aspectCombinations = [] ; // wilkl be a lsit of mutilyer grrahs
g.aspectCombinationName = combinationName;
aspectLayers.forEach(function(aspectLayer) {
var newLayerName = "[" + targetLayerName +"]-BY-[" + aspectLayer.name + "]";
var commonNodeUids = g.getCommonNodeUids(targetLayer.name,aspectLayer.name);
var commonEdgeUids = g.getCommonEdgeUids(targetLayer.name,aspectLayer.name);
var newIntersectionLayer = MultiLayerGraph([], [],newLayerName);
newIntersectionLayer.master = g;
commonNodeUids.forEach(function(n_id) {
if (g.node[n_id]) {
newIntersectionLayer.copyNodeToLayer(g.node[n_id]);
}
});
commonEdgeUids.forEach(function(l_id) {
if(g.link[l_id]) {
newIntersectionLayer.copyEdgeToLayer(g.link[l_id]);
}
});
newIntersectionLayer.buildNodeLookUp();
newIntersectionLayer.buildLinkLookUp();
newIntersectionLayer.buildAdjacencyList();
newIntersectionLayer.buildEdgeList();
// newIntersectionLayer.prepareGraph();
g.aspectCombinations.push(newIntersectionLayer);
});
console.log("Created Combination: "+ combinationName);
return combinationName;
};
g.getCombinationLayerByName = function(combinationLayerName) {
var resultLayer = null;
g.aspectCombinations.forEach(function(layer) {
if(layer.name === combinationLayerName) {
resultLayer = layer;
}
});
return resultLayer;
}
/**************************************
* toJSON()
* Functionality: When sending as JSON need to remove all cyclical References
......@@ -3445,8 +3553,8 @@ var MultiLayerGraph = function (nodes, links, layerName) {
var jsonVersion = {};
jsonVersion.nodes = g.nodes;
jsonVersion.links = g.links;
jsonVersion.name = g.name
jsonVersion.master = "MasterLayer"
jsonVersion.name = g.name;
jsonVersion.master = "MasterLayer";
jsonVersion.layers = g.layers
var aspectsByName = {};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment