Commit 086db2d8 authored by Romain Loth's avatar Romain Loth

WIP edgetypes: first quick working version (unoptimized)

parent 039ff7ad
This diff is collapsed.
...@@ -275,7 +275,9 @@ function changeType() { ...@@ -275,7 +275,9 @@ function changeType() {
// new state is the complement of the received state ~[X\Y] // new state is the complement of the received state ~[X\Y]
var t1Activetypes = [] var t1Activetypes = []
for(var i in t0Activetypes) t1Activetypes[i] = !t0Activetypes[i] for(var i in t0Activetypes) t1Activetypes[i] = !t0Activetypes[i]
var t1ActivetypesKey = t1Activetypes.map(Number).join("|")
// apriori key
let t1ActivetypesKey = t1Activetypes.map(Number).join("|")
// "union realm" (where we'll search the real bipartite Relations) // "union realm" (where we'll search the real bipartite Relations)
var bipartiteKey = "1|1" var bipartiteKey = "1|1"
...@@ -288,7 +290,6 @@ function changeType() { ...@@ -288,7 +290,6 @@ function changeType() {
// so => we set here a fallback to "1|0" // so => we set here a fallback to "1|0"
if (t1ActivetypesKey == "0|0") { if (t1ActivetypesKey == "0|0") {
t1Activetypes = [true, false] t1Activetypes = [true, false]
t1ActivetypesKey = "1|0"
// this case "0|0" => "1|0" won't have a unique edge realm to look at // this case "0|0" => "1|0" won't have a unique edge realm to look at
// nodes of "1|0" will need their "1|0" neighbors // nodes of "1|0" will need their "1|0" neighbors
...@@ -299,6 +300,12 @@ function changeType() { ...@@ -299,6 +300,12 @@ function changeType() {
// special case: "macro level opens bipartite possibilities" // special case: "macro level opens bipartite possibilities"
if(!level) t1Activetypes = [true, true]; if(!level) t1Activetypes = [true, true];
// now that we have the future types, infer associated state representations
// let t1ActivetypesKey = t1Activetypes.map(Number).join("|")
let t1Activereltypes = TW.instance.inferActivereltypes(t1Activetypes)
console.log("activetypes:", t1ActivetypesKey)
console.log("activereltypes:", t1Activereltypes)
// list of present nodes: needed *before* clearing // list of present nodes: needed *before* clearing
// (but only needed if local and no selections) // (but only needed if local and no selections)
...@@ -324,12 +331,14 @@ function changeType() { ...@@ -324,12 +331,14 @@ function changeType() {
} }
} }
for(var eid in TW.Edges) { for(var eid in TW.Edges) {
for (var k in t1Activereltypes) {
if(TW.Edges[eid].categ==t1ActivetypesKey) let reltype = t1Activereltypes[k]
if(TW.Edges[eid].categ==reltype)
add1Elem(eid) add1Elem(eid)
}
// NB ie we don't add sameside edges "1|0" or "0|1" when target // NB ie we **do** add sameside edges "1|0" or "0|1" when target
// activetypes is "1|1" (aka "both") // activetypes is "1|1" (aka "both"), cf. inferActivereltypes
} }
sourceNodes = sels sourceNodes = sels
...@@ -361,8 +370,8 @@ function changeType() { ...@@ -361,8 +370,8 @@ function changeType() {
// [ ChangeType: incremental selection ;] // [ ChangeType: incremental selection ;]
// Dictionaries of: opposite-neighs of current source nodes // Dictionaries of: opposite-neighs of current source nodes
var newnodeset = {}
var newsels = {} var newsels = {}
var edgesToAdd = {}
for(var i in sourceNodes) { for(var i in sourceNodes) {
let srcnid = sourceNodes[i]; let srcnid = sourceNodes[i];
let srctyp = TW.Nodes[srcnid].type let srctyp = TW.Nodes[srcnid].type
...@@ -370,7 +379,17 @@ function changeType() { ...@@ -370,7 +379,17 @@ function changeType() {
if (!mixedStart) { if (!mixedStart) {
// case where we have an single kind of Relations to consider // case where we have an single kind of Relations to consider
// ie the realm of the bipartite relations called "1|1" // ie the realm of the bipartite relations called "1|1"
neighs = TW.Relations[bipartiteKey][srcnid]
for (var k in t1Activereltypes) {
let reltype = t1Activereltypes[k]
if (TW.Relations[reltype] && TW.Relations[reltype][srcnid])
neighs = neighs.concat(TW.Relations[reltype][srcnid])
}
console.log("=> neighs", neighs)
// neighs = TW.Relations[bipartiteKey][srcnid]
} }
else { else {
// case with a mixed starting point // case with a mixed starting point
...@@ -394,10 +413,9 @@ function changeType() { ...@@ -394,10 +413,9 @@ function changeType() {
if (t1Activetypes[TW.catDict[tgttyp]]) { if (t1Activetypes[TW.catDict[tgttyp]]) {
newsels[tgtnid]=true; newsels[tgtnid]=true;
// since we're here we keep the edges if needed // since we're here we keep in the new scope (nodeset) if local
if (!present.level) { if (!present.level) {
edgesToAdd[`${srcnid};${tgtnid}`] = true newnodeset[tgtnid] = true
edgesToAdd[`${tgtnid};${srcnid}`] = true
} }
} }
} }
...@@ -419,8 +437,23 @@ function changeType() { ...@@ -419,8 +437,23 @@ function changeType() {
for(var nid in newsels) { for(var nid in newsels) {
add1Elem(nid) add1Elem(nid)
} }
for(var eid in edgesToAdd) {
add1Elem(eid) // new loop on current scope to add sels edges and intra-neighbors edges
for(var srcnid in newnodeset) {
for(var tgtnid in newnodeset) {
let possEids = [`${srcnid};${tgtnid}`,`${tgtnid};${srcnid}`]
for (var l in possEids) {
let eid = possEids[l]
if (TW.Edges[eid]) {
let e = TW.Edges[eid]
for (var k in t1Activereltypes) {
let reltype = t1Activereltypes[k]
if (e.categ == reltype)
add1Elem(eid)
}
}
}
}
} }
} }
...@@ -430,6 +463,7 @@ function changeType() { ...@@ -430,6 +463,7 @@ function changeType() {
TW.pushState({ TW.pushState({
activetypes: t1Activetypes, activetypes: t1Activetypes,
activereltypes: t1Activereltypes,
sels: newselsArr, sels: newselsArr,
// rels: added by MS2 (highlighted opposite- and same-side neighbours) // rels: added by MS2 (highlighted opposite- and same-side neighbours)
// possible: add it in an early way here and request that MS2 doesn't change state // possible: add it in an early way here and request that MS2 doesn't change state
...@@ -491,6 +525,7 @@ function changeLevel() { ...@@ -491,6 +525,7 @@ function changeLevel() {
var activetypes = present.activetypes; var activetypes = present.activetypes;
var activetypesKey = activetypes.map(Number).join("|") var activetypesKey = activetypes.map(Number).join("|")
var activereltypes = present.activereltypes
TW.partialGraph.graph.clear(); TW.partialGraph.graph.clear();
...@@ -502,22 +537,26 @@ function changeLevel() { ...@@ -502,22 +537,26 @@ function changeLevel() {
for(var i in sels) { for(var i in sels) {
s = sels[i]; s = sels[i];
nodesToAdd[s]=true; nodesToAdd[s]=true;
if (TW.Relations[activetypesKey]) { for (var k in activereltypes) {
neigh = TW.Relations[activetypesKey][s] let activereltype = activereltypes[k]
if(neigh) { console.log("level: considering reltype ", activereltype)
for(var j in neigh) { if (TW.Relations[activereltype]) {
t = neigh[j] neigh = TW.Relations[activereltype][s]
nodesToAdd[t]=true; if(neigh) {
edgesToAdd[s+";"+t]=true; for(var j in neigh) {
edgesToAdd[t+";"+s]=true; t = neigh[j]
if( !selsChecker[t] ) nodesToAdd[t]=true;
voisinage[ t ] = true; edgesToAdd[s+";"+t]=true;
} edgesToAdd[t+";"+s]=true;
if( !selsChecker[t] )
voisinage[ t ] = true;
}
}
}
else {
// case where no edges at all (ex: scholars have no common keywords)
console.log("no edges between these nodes")
} }
}
else {
// case where no edges at all (ex: scholars have no common keywords)
console.log("no edges between these nodes")
} }
} }
...@@ -536,6 +575,7 @@ function changeLevel() { ...@@ -536,6 +575,7 @@ function changeLevel() {
if( voisinage[i]!=voisinage[j] ) { if( voisinage[i]!=voisinage[j] ) {
// console.log( "\t" + voisinage[i] + " vs " + voisinage[j] ) // console.log( "\t" + voisinage[i] + " vs " + voisinage[j] )
add1Elem( voisinage[i]+";"+voisinage[j] ) add1Elem( voisinage[i]+";"+voisinage[j] )
add1Elem( voisinage[j]+";"+voisinage[i] )
} }
} }
} }
......
...@@ -24,6 +24,7 @@ TW.gmenuInfos={}; // map [graphsource => { node0/1 categories ...@@ -24,6 +24,7 @@ TW.gmenuInfos={}; // map [graphsource => { node0/1 categories
// a system state is the summary of tina situation // a system state is the summary of tina situation
TW.initialSystemState = { TW.initialSystemState = {
activetypes: [], // <== filled from TW.categories activetypes: [], // <== filled from TW.categories
activereltypes: [], // <== same for edges
level: true, level: true,
selectionNids: [], // <== current selection !! selectionNids: [], // <== current selection !!
selectionRels: [], // <== current highlighted neighbors selectionRels: [], // <== current highlighted neighbors
...@@ -366,6 +367,7 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -366,6 +367,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
// activetypes: the node categorie(s) that is (are) currently displayed // activetypes: the node categorie(s) that is (are) currently displayed
// ex: [true,false] = [nodes of type 0 shown ; nodes of type 1 not drawn] // ex: [true,false] = [nodes of type 0 shown ; nodes of type 1 not drawn]
var initialActivetypes = TW.instance.initialActivetypes( TW.categories ) var initialActivetypes = TW.instance.initialActivetypes( TW.categories )
var initialActivereltypes = TW.instance.inferActivereltypes( initialActivetypes )
// XML parsing from ParseCustom // XML parsing from ParseCustom
var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy
...@@ -406,7 +408,7 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -406,7 +408,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
// preparing the data (TW.Nodes and TW.Edges filtered by initial type) // preparing the data (TW.Nodes and TW.Edges filtered by initial type)
// POSS: avoid this step and use the filters at rendering time! // POSS: avoid this step and use the filters at rendering time!
TW.graphData = {nodes: [], edges: []} TW.graphData = {nodes: [], edges: []}
TW.graphData = sigma_utils.FillGraph( initialActivetypes , TW.catDict , TW.Nodes , TW.Edges , TW.graphData ); TW.graphData = sigma_utils.FillGraph( initialActivetypes , initialActivereltypes, TW.catDict , TW.Nodes , TW.Edges , TW.graphData );
// // ----------- TEST stock parse gexf and use nodes to replace TW's --------- // // ----------- TEST stock parse gexf and use nodes to replace TW's ---------
...@@ -496,7 +498,10 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -496,7 +498,10 @@ function mainStartGraph(inFormat, inData, twInstance) {
// ================================================================== // ==================================================================
// a new state // a new state
TW.pushState({'activetypes': initialActivetypes}) TW.pushState({
'activetypes': initialActivetypes,
'activereltypes': initialActivereltypes
})
// NB the list of nodes and edges from TW.graphData will be changed // NB the list of nodes and edges from TW.graphData will be changed
// by changeLevel, changeType or subset sliders => no need to keep it // by changeLevel, changeType or subset sliders => no need to keep it
...@@ -510,7 +515,11 @@ function mainStartGraph(inFormat, inData, twInstance) { ...@@ -510,7 +515,11 @@ function mainStartGraph(inFormat, inData, twInstance) {
// renderer position depend on viewpoint/zoom (like ~ html absolute positions of the node in the div) // renderer position depend on viewpoint/zoom (like ~ html absolute positions of the node in the div)
// now that we have a sigma instance, let's bind our click handlers to it // now that we have a sigma instance, let's bind our click handlers to it
TW.instance.initSigmaListeners(TW.partialGraph, initialActivetypes) TW.instance.initSigmaListeners(
TW.partialGraph,
initialActivetypes, // to init node sliders and .class gui elements
initialActivereltypes // to init edge sliders
)
// [ / Poblating the Sigma-Graph ] // [ / Poblating the Sigma-Graph ]
......
...@@ -19,9 +19,10 @@ TW.pushState = function( args ) { ...@@ -19,9 +19,10 @@ TW.pushState = function( args ) {
newState.id ++ newState.id ++
// 2) we update it with provided args // 2) we update it with provided args
if (!isUndef(args.activetypes)) newState.activetypes = args.activetypes if (!isUndef(args.activetypes)) newState.activetypes = args.activetypes
if (!isUndef(args.level)) newState.level = args.level; if (!isUndef(args.activereltypes)) newState.activereltypes = args.activereltypes
if (!isUndef(args.sels)) newState.selectionNids = args.sels; if (!isUndef(args.level)) newState.level = args.level;
if (!isUndef(args.sels)) newState.selectionNids = args.sels;
// neighbors (of any type) and their edges in an .selectionRels[type] slot // neighbors (of any type) and their edges in an .selectionRels[type] slot
if(!isUndef(args.rels)) newState.selectionRels = args.rels; if(!isUndef(args.rels)) newState.selectionRels = args.rels;
...@@ -72,9 +73,10 @@ TW.pushState = function( args ) { ...@@ -72,9 +73,10 @@ TW.pushState = function( args ) {
NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0]); NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0]);
NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1]); NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1]);
// only truly bipartite edges => only one GUI slider // one slider for each intra-type reltype
showDisabledSlider("#slidercat0edgesweight") EdgeWeightFilter("#slidercat0edgesweight", "1|0", "weight");
EdgeWeightFilter("#slidercat1edgesweight", "1|1", "weight"); EdgeWeightFilter("#slidercat1edgesweight", "0|1", "weight");
// NB: no slider for truly bipartite edges => 2 GUI sliders but 3 edge types
} }
} }
......
...@@ -3,19 +3,25 @@ ...@@ -3,19 +3,25 @@
var SigmaUtils = function () { var SigmaUtils = function () {
// input = GEXFstring // input = GEXFstring
this.FillGraph = function( initialActivetypes , catDict , nodes, edges , graph ) { this.FillGraph = function( initialActivetypes , initialActivereltypes, catDict , nodes, edges , graph ) {
console.log("Filling the graaaaph:") console.log("Filling the graaaaph:")
console.log("FillGraph catDict",catDict) console.log("FillGraph catDict",catDict)
// console.log("FillGraph nodes",nodes) // console.log("FillGraph nodes",nodes)
// console.log("FillGraph edges",edges) // console.log("FillGraph edges",edges)
// retrocompatibility -------------------------------- 8< -------------
if (!initialActivereltypes.length) {
initialActivereltypes = [initialActivetypes.map(Number).join("|")]
}
// ---------------------------------------------------- 8< -------------
let i = 0 let i = 0
for(var nid in nodes) { for(var nid in nodes) {
var n = nodes[nid]; var n = nodes[nid];
// console.debug('tr >>> fgr node', n) // console.debug('tr >>> fgr node', n)
if(initialActivetypes[catDict[n.type]] || TW.conf.debug.initialShowAll) { if(initialActivetypes[catDict[n.type]]) {
// var node = { // var node = {
// id : n.id, // id : n.id,
// label : n.label, // label : n.label,
...@@ -43,20 +49,20 @@ var SigmaUtils = function () { ...@@ -43,20 +49,20 @@ var SigmaUtils = function () {
} }
} }
// the typestrings in activereltypes are the key to stored Relations (<=> edges)
// the typestring of the activetypes is the key to stored Relations (<=> edges) for (var k in initialActivereltypes) {
var activetypesKey = initialActivetypes.map(Number).join("|") let reltype = initialActivereltypes[k]
for(let srcnid in TW.Relations[reltype]) {
for(let srcnid in TW.Relations[activetypesKey]) { for(var j in TW.Relations[reltype][srcnid]) {
for(var j in TW.Relations[activetypesKey][srcnid]) { let tgtnid = TW.Relations[reltype][srcnid][j]
let tgtnid = TW.Relations[activetypesKey][srcnid][j] let e = TW.Edges[srcnid+";"+tgtnid]
let e = TW.Edges[srcnid+";"+tgtnid] if(e) {
if(e) { if(e.source != e.target) {
if(e.source != e.target) { graph.edges.push( e);
graph.edges.push( e); }
} }
} }
} }
} }
return graph; return graph;
}// output = sigma graph }// output = sigma graph
......
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