Commit e9f27795 authored by Romain Loth's avatar Romain Loth

politoscope data and fix gexf cats parsing

various experiments around gexf parsing: take into account declared atts, trace comments for parseCustom, declarable @cluster_index equivalent, and separate function in sigma_tools for using stock gexf parser (unconnected now)
parent a0aa844c
<?php
# £TODO WTF ??? => move params to settings_explorerjs ???
$gexf_db = array();
# $gexf_db["data/terrorism/terrorism_bi.gexf"] = "data/terrorism/data.db";
......@@ -11,6 +13,10 @@ $gexf_db["data/AXA/RiskV2PageRank1000.gexf"] = "data/AXA/data.db";
$gexf_db["data/AXA/RiskV2PageRank2500.gexf"] = "data/AXA/data.db";
$gexf_db["data/AXA/RiskV2PageRank5000.gexf"] = "data/AXA/data.db";
// TESTS
$gexf_db["data/ProgrammeDesCandidats.gexf"] = "foobar";
$gexf= str_replace('"','',$_GET["gexf"]);
$mainpath=dirname(getcwd())."/";
......
{
"data/politoscope": {
"dbname":null,
"title":"Politoscope",
"date":"2017",
"abstract":"hello woerld",
"first" : "ProgrammeDesCandidats.gexf",
"gexfs": {
"ProgrammeDesCandidats.gexf": {
"social": {},
"semantic": {}
}
}
},
"data/AXA": {
"dbname":"data.db",
"title":"ISITITLE",
"date":"ISIpubdate",
"abstract":"ISIABSTRACT",
"first" : "RiskV2PageRank1000.gexf",
"first" : "RiskV2PageRank1000.gexf",
"gexfs": {
"RiskV2PageRank1000.gexf": {
"social": { "table":"ISIAUTHOR" , "textCol":"data","forkeyCol":"id"},
......
......@@ -587,10 +587,15 @@
<!-- new sigma 1.2 imports -->
<script src="tinawebJS/sigma_v1.2/sigma.min.js" type="text/javascript" language="javascript"></script>
<!-- <script src="tinawebJS/sigma_v1.2/sigma.js" type="text/javascript" language="javascript"></script> -->
<script src="tinawebJS/sigma_v1.2/plugins/sigma.layout.forceAtlas2/supervisor.js"></script>
<script src="tinawebJS/sigma_v1.2/plugins/sigma.layout.forceAtlas2/worker.js"></script>
<script src="tinawebJS/sigma_v1.2/plugins/sigma.renderers.snapshot/sigma.renderers.snapshot.js"></script>
<!-- Tested as replacement for parseCustom -->
<!-- <script src="tinawebJS/sigma_v1.2/plugins/sigma.parsers.gexf/gexf-parser.js"></script> -->
<!-- <script src="tinawebJS/sigma_v1.2/plugins/sigma.parsers.gexf/sigma.parsers.gexf.js"></script> -->
<!-- testing sigma 1.5 imports from linkurious src -->
<!-- <script src="tinawebJS/sigma_v1.5/sigma.js" type="text/javascript" language="javascript"></script>
<script src="tinawebJS/sigma_v1.5/plugins.js" type="text/javascript" language="javascript"></script> -->
......
......@@ -21,14 +21,12 @@ function ChangeGraphAppearanceByAtt( manualflag ) {
// Seeing all the possible attributes!
var AttsDict = {}
var Atts_2_Exclude = {}
var v_nodes = getVisibleNodes();
for (var i in v_nodes) {
if(!v_nodes[i].hidden) {
var id = v_nodes[i].id;
for(var a in TW.Nodes[id].attributes) {
var someatt = TW.Nodes[id].attributes[a]
for (var j in TW.nodeIds) {
let nid = TW.nodeIds[j]
let n = TW.partialGraph.graph.nodes(nid)
if(!n.hidden) {
for(var a in TW.Nodes[nid].attributes) {
var someatt = TW.Nodes[nid].attributes[a]
// Identifying the attribute datatype: exclude strings and objects
if ( ( typeof(someatt)=="string" && isNaN(Number(someatt)) ) || typeof(someatt)=="object" ) {
......@@ -38,10 +36,10 @@ function ChangeGraphAppearanceByAtt( manualflag ) {
}
var possible_atts = [];
if (!isUndef(TW.Nodes[id].attributes))
possible_atts = Object.keys(TW.Nodes[id].attributes)
if (!isUndef(TW.Nodes[nid].attributes))
possible_atts = Object.keys(TW.Nodes[nid].attributes)
if(!isUndef(v_nodes[i].degree))
if(!isUndef(n.degree))
possible_atts.push("degree")
possible_atts.push("clust_louvain")
......@@ -240,10 +238,15 @@ function set_ClustersLegend ( daclass ) {
var Type = raw[0]
var ClustType = raw[1]
var ClustID = raw[2]
var legTxt = "N/A"
if (TW.Clusters && TW.Clusters[Type] && TW.Clusters[Type][ClustType] && TW.Clusters[Type][ClustType][ClustID]) {
legTxt = TW.Clusters[Type][ClustType][ClustID]
}
var Color = ClustNB_CurrentColor[IDx]
pr ( Color+" : "+ TW.Clusters[Type][ClustType][ClustID] )
// console.log ( Color+" : ", Type, ClustType, ClustID )
pr ( Color+" : "+ legTxt )
var ColorDiv = '<span style="background:'+Color+';"></span>'
LegendDiv += '<li onclick=\'SomeEffect("'+IDx+'")\'>'+ColorDiv+ TW.Clusters[Type][ClustType][ClustID]+"</li>"+"\n"
LegendDiv += '<li onclick=\'SomeEffect("'+IDx+'")\'>'+ColorDiv+ legTxt+"</li>"+"\n"
}
} else {
for(var i in OrderedClustDicts) {
......
......@@ -101,7 +101,8 @@ var semanticConverged=false;
// ============ < / DEVELOPER OPTIONS > ============
var showLabelsIfZoom=1.0;
TW.nodeClusAtt = "modularity_class"
TW.edgeDefaultOpacity = 0.5 // opacity when true_color
TW.edgeGreyColor = "rgba(150, 150, 150, 0.2)";
TW.nodesGreyBorderColor = "rgba(100, 100, 100, 0.5)";
......@@ -111,6 +112,7 @@ TW.selectedColor = "node" // "node" for a background like the node's color,
TW.overSampling = true // costly hi-def rendering (true => pixelRatio x 2)
TW.deselectOnclickStage = false // will a click on the background remove selection ? (except when dragging)
var showLabelsIfZoom=1.0;
// ============ < / DEVELOPER OPTIONS > ============
......@@ -164,7 +166,7 @@ var twjs="tinawebJS/";
TW.categories = {};
TW.categoriesIndex = [];
var gexf;
var gexfFile;
//var zoom=0;
var checkBox=false;
......
......@@ -3,6 +3,18 @@
// always useful
var theHtml = document.getElementsByTagName('html')[0]
// overriding pixelRatio is possible if we need very high definition
// var realRatio = sigma.utils.getPixelRatio
// if (TW.overSampling) {
// sigma.utils.getPixelRatio = function() {
// return 2 * realRatio()
// }
// }
TW.anynodegoes = true
// TW.anynodegoes = true
//============================ < NEW BUTTONS > =============================//
......@@ -449,6 +461,11 @@ function changeLevel() {
// NB new sigma js: dropEdge is quite slow so we add a waiting cursor
function EdgeWeightFilter(sliderDivID , type_attrb , type , criteria) {
console.log("EdgeWeightFilter")
console.log("sliderDivID", sliderDivID)
console.log("type_attrb", type_attrb)
console.log("type", type)
console.log("criteria", criteria)
// if ($(sliderDivID).html()!="") {
// console.log("\t\t\t\t\t\t[[ algorithm not applied "+sliderDivID+" ]]")
// return;
......@@ -480,10 +497,16 @@ function EdgeWeightFilter(sliderDivID , type_attrb , type , criteria) {
var filterparams = AlgorithmForSliders ( TW.Edges , type_attrb , type , criteria) //OK
// TODO make an index
// console.log("EdgeWeightFilter: "+type)
// console.log(filterparams)
console.log("EdgeWeightFilter: "+type)
console.log(filterparams)
var steps = filterparams["steps"]
// TODO polito filterparams comes back like this {steps:0, finalarray:[]}
console.warn("overriding steps")
steps = 2
var finalarray = filterparams["finalarray"]
// if(steps<3) {
// $(sliderDivID).freshslider({
......
......@@ -34,7 +34,7 @@ var AjaxSync = (function(TYPE, URL, DATA, CT , DT) {
var Result = []
TYPE = (!TYPE)?"GET":"POST"
if(DT && (DT=="jsonp" || DT=="json")) CT="application/json";
// console.log(TYPE, URL, DATA, CT , DT)
console.log("---AjaxSync---\n", TYPE, URL, DATA, CT , DT, "\n--------------")
$.ajax({
type: TYPE,
url: URL,
......@@ -56,6 +56,7 @@ var AjaxSync = (function(TYPE, URL, DATA, CT , DT) {
Result = { "OK":true , "format":format , "data":data };
},
error: function(exception) {
console.log('now error')
Result = { "OK":false , "format":false , "data":exception.status };
}
});
......@@ -93,20 +94,27 @@ if(!isUndef(getUrlParam.mode)) { // if {db|api}.json
// RES == { OK: true, format: "json", data: Object }
var RES = AjaxSync({ URL: file });
console.log('RES', RES)
if(RES["OK"]) {
var fileparam;// = { db|api.json , somefile.json|gexf }
var the_data = RES["data"];
// console.log('initial AjaxSync result RES', RES)
console.log('initial AjaxSync result RES', RES)
// ===================
var the_file = "";
// ===================
if ( !isUndef(getUrlParam.mode) && getUrlParam.mode=="db.json") {
var first_file = "" , first_path = ""
for( var path in the_data ) {
console.log("db.json path", path)
first_file = the_data[path]["first"]
first_path = path
console.log("db.json first_file", first_path, first_file)
break;
}
......@@ -116,24 +124,23 @@ if(RES["OK"]) {
the_file = first_path+"/"+getUrlParam.file
}
fileparam = the_file;
var files_selector = '<select onchange="jsActionOnGexfSelector(this.value , true);">'
for( var path in the_data ) {
var the_gexfs = the_data[path]["gexfs"]
console.log("\t\tThese are the available Gexfs:")
for(var gexf in the_gexfs) {
var gexfBasename = gexf.replace(/\.gexf$/, "") // more human-readable in the menu
console.log("\t\t\t"+gexf+ " -> table:" +the_gexfs[gexf]["semantic"]["table"] )
console.log(the_gexfs)
for(var aGexf in the_gexfs) {
var gexfBasename = aGexf.replace(/\.gexf$/, "") // more human-readable in the menu
console.log("\t\t\t"+gexfBasename+ " -> table:" +the_gexfs[aGexf]["semantic"]["table"] )
TW.field[path+"/"+gexf] = the_gexfs[gexf]["semantic"]["table"]
TW.field[path+"/"+aGexf] = the_gexfs[aGexf]["semantic"]["table"]
// ex : data/AXA/RiskV2PageRank5000.gexf:"ISItermsAxa_2015"
TW.gexfDict[path+"/"+gexf] = gexf
TW.gexfDict[path+"/"+aGexf] = aGexf
// ex : data/AXA/RiskV2PageRank1000.gexf:"RiskV2PageRank1000.gexf"
var selected = (the_file==(path+"/"+gexf))?"selected":""
var selected = (the_file==(path+"/"+aGexf))?"selected":""
files_selector += '<option '+selected+'>'+gexfBasename+'</option>'
}
// console.log( files_selector )
......@@ -147,12 +154,15 @@ if(RES["OK"]) {
// console.log("\n============================\n")
// console.log(TW.field)
// console.log(TW.gexfDict)
var sub_RES = AjaxSync({ URL: fileparam });
var sub_RES = AjaxSync({ URL: the_file });
the_data = sub_RES["data"]
fileparam = sub_RES["format"]
// console.log(the_data.length)
// console.log(fileparam)
console.warn('@the_file', sub_RES["OK"], the_file)
// why now ???
getUrlParam.file=the_file;
console.log(" . .. . -. - .- . - -.")
console.log(getUrlParam.file)
......@@ -171,8 +181,8 @@ if(RES["OK"]) {
console.log("parsing the data")
var start = new ParseCustom( fileparam , the_data );
var categories = start.scanFile(); //user should choose the order of categories
// console.log("Categories: ")
// console.log(categories)
console.error("Categories: ")
console.log(categories)
if (! categories) {
console.warn ('ParseCustom scanFile found no categories!!')
......@@ -181,7 +191,11 @@ if(RES["OK"]) {
var possibleStates = makeSystemStates( categories )
var initialState = buildInitialState( categories ) //[true,false]//
var dicts = start.makeDicts(categories);
// XML parsing from ParseCustom
var dicts = start.makeDicts(categories); // > parseGexf, dictfyGexf
console.warn("parsing result:", dicts)
TW.Nodes = dicts.nodes;
TW.Edges = dicts.edges;
TW.nodeIds = Object.keys(dicts.nodes) // useful for loops
......@@ -195,10 +209,12 @@ if(RES["OK"]) {
if (the_data.clusters) TW.Clusters = the_data.clusters
// relations already copied in TW.Relations at this point
// TW.nodes1 = dicts.n1;//not used
var catDict = dicts.catDict
// console.log("CategoriesDict: ")
// console.log(catDict)
console.log("CategoriesDict: ")
console.log(catDict)
TW.categoriesIndex = categories;//to_remove
TW.catSoc = categories[0];//to_remove
......@@ -231,7 +247,40 @@ if(RES["OK"]) {
// preparing the data and settings
TW.graphData = {nodes: [], edges: []}
TW.graphData = sigma_utils.FillGraph( initialState , catDict , dicts.nodes , dicts.edges , TW.graphData );
TW.graphData = sigma_utils.FillGraph( initialState , catDict , TW.Nodes , TW.Edges , TW.graphData );
// // ----------- TEST stock parse gexf and use nodes to replace TW's ---------
// var gexfData = gexf.fetch('data/politoscope/ProgrammeDesCandidats.gexf')
//
// TW.graphData = sigmaTools.myGexfParserReplacement(
// gexfData.nodes,
// gexfData.edges
// )
// console.log ('ex in TW.graphData.nodes[0]', TW.graphData.nodes[0])
//
// // our holey id-indexed arrays
// TW.Nodes = {}
// TW.Edges = {}
// TW.nodeIds = []
// TW.edgeIds = []
// for (var j in TW.graphData.nodes) {
// var nid = TW.graphData.nodes[j].id
// TW.Nodes[nid] = TW.graphData.nodes[j]
// TW.nodeIds.push(nid)
// }
// for (var i in TW.graphData.edges) {
// var eid = TW.graphData.edges[i].id
// TW.Edges[eid] = TW.graphData.edges[i]
// TW.edgeIds.push(eid)
// }
//
//
// // -------------------------------------------------------------------------
if (TW.graphData.nodes.length == 0) console.error("empty graph")
if (TW.graphData.edges.length == 0) console.error("no edges in graph")
// cf github.com/jacomyal/sigma.js/wiki/Settings
var customSettings = Object.assign(
......@@ -324,10 +373,17 @@ if(RES["OK"]) {
TW.partialGraph.states[1] = TW.SystemStates;
TW.partialGraph.states[1].categories = categories
TW.partialGraph.states[1].categoriesDict = catDict;
console.log("!? initialState => states[1].type")
TW.partialGraph.states[1].type = initialState;
TW.partialGraph.states[1].LouvainFait = false;
// [ / Poblating the Sigma-Graph ]
// ex called for new selections with args like:
// (undefined, undefined, [268], undefined)
// ^^^^
// why type not used (monopart? deprecated?)
TW.partialGraph.states[1].setState = (function( type , level , sels , oppos ) {
var bistate=false, typestring=false;
console.log("IN THE SET STATE METHOD:")
......@@ -342,7 +398,7 @@ if(RES["OK"]) {
this.LouvainFait = false;
console.log("")
console.log(" % % % % % % % % % % ")
// console.log("type: "+thetype.map(Number));
console.log("setState type: ", type);
console.log("bistate: "+bistate)
console.log("level: "+level);
console.log("selections: ");
......@@ -476,7 +532,12 @@ if(RES["OK"]) {
// }
}
ChangeGraphAppearanceByAtt(true)
try {
ChangeGraphAppearanceByAtt(true)
}
catch (e) {
console.error(e)
}
set_ClustersLegend ( "clust_default" )
......
This diff is collapsed.
......@@ -7,11 +7,14 @@ SigmaUtils = function () {
this.FillGraph = function( initialState , catDict , nodes, edges , graph ) {
console.log("Filling the graaaaph:")
// console.log(catDict)
console.log("FillGraph catDict",catDict)
console.log("FillGraph nodes",nodes)
console.log("FillGraph edges",edges)
for(var i in nodes) {
var n = nodes[i];
// console.debug('tr >>> fgr node', n)
if(initialState[catDict[n.type]]) {
if(initialState[catDict[n.type]] || TW.anynodegoes) {
// var node = {
// id : n.id,
// label : n.label,
......@@ -30,7 +33,7 @@ SigmaUtils = function () {
// no attributes to remove: I use n directly
graph.nodes.push(n);
if(Number(n.id)==287) console.log("node 287:", n)
if(i==2) console.log("node 2 ("+n.id+")", n)
// fill the "labels" global variable
updateSearchLabels( n.id , n.label , n.type);
......
......@@ -5,6 +5,71 @@ var sigmaTools = {};
sigmaTools = (function(stools) {
// a simpler alternative to avoid parseCustom and prepareNodesRenderingProperties
// temporarily after using the new gexf stock parser
// (mostly to transform viz: attrs in real attrs)
stools.myGexfParserReplacement = function(rawGexfNodes, rawGexfEdges) {
// output, indexed by IDs
var newNodes = [],
newEdges = []
for (var j in rawGexfNodes) {
var rawNode = rawGexfNodes[j]
// pre-parse node rgb color
var rgbStr = rawNode.viz.color.match(/rgb\(([^\(]+)\)/)[1]
var newNode = {
id: rawNode.id,
label: rawNode.label,
x: rawNode.viz.position.x,
y: rawNode.viz.position.y,
color: rawNode.viz.color,
size: Math.round(rawNode.viz.size*1000)/1000,
active: false,
hidden: false,
customAttrs: {
grey: false,
highlight: false,
true_color: rawNode.viz.color,
defgrey_color : "rgba("+rgbStr+",.4)"
},
// for metrics like centrality
attributes: {
'clust_default': rawNode.attributes.modularity_class
}
}
newNodes[j] = newNode
}
for (var i in rawGexfEdges) {
var rawEdge = rawGexfEdges[i]
var rgbStr = sigmaTools.edgeRGB(rawEdge.source, rawEdge.target, newNodes)
var leColor = "rgba("+rgbStr+","+TW.edgeDefaultOpacity+")"
var newEid = rawEdge.source+";"+rawEdge.target;
var newEdge = {
id: newEid,
source: rawEdge.source,
target: rawEdge.target,
color: leColor,
weight: Math.round(rawEdge.weight*1000)/1000,
customAttrs: {
grey: false,
activeEdge: false,
true_color: leColor,
rgb: rgbStr
}
}
newEdges[i] = newEdge
}
return {nodes: newNodes, edges: newEdges}
};
stools.rgbToHex = function(R, G, B) {
return stools.toHex(R) + stools.toHex(G) + stools.toHex(B);
};
......@@ -21,26 +86,49 @@ sigmaTools = (function(stools) {
};
// TODO check duplicate functionalities with repaintEdges
stools.edgeRGB = function(src_id, tgt_id) {
//edge color will be the combination of the 2 node colors
var a = TW.Nodes[src_id]['color'];
var b = TW.Nodes[tgt_id]['color'];
stools.edgeRGB = function(src_id, tgt_id, nodeIndex) {
if (!nodeIndex) {
nodeIndex = TW.Nodes
}
if (!Object.keys(nodeIndex).length) {
console.warn('empty nodeIndex')
}
// console.log('edgeRGB, src_id', src_id)
// console.log('edgeRGB, tgt_id', tgt_id)
//
if (!nodeIndex[src_id] || !nodeIndex[tgt_id]) {
return '0,0,0'
}
//edge color will be the combination of the 2 node colors
var a = nodeIndex[src_id]['color'];
var b = nodeIndex[tgt_id]['color'];
var tmp
// console.log("color a", a)
// console.log("color b", b)
if(a.charAt(0)!="#") {
tmp = a.replace("rgba(","").replace(")","").split(",")
a = stools.rgbToHex( parseFloat( tmp[0] ) , parseFloat( tmp[1] ) , parseFloat( tmp[2] ) );
tmp = a.replace(/rgba?\(/,"").replace(")","").split(",")
// rgb array
a = [parseFloat( tmp[0] ) , parseFloat( tmp[1] ) , parseFloat( tmp[2] )];
}
else {
a = hex2rga(a);
}
if(b.charAt(0)!="#") {
tmp = b.replace("rgba(","").replace(")","").split(",")
b = stools.rgbToHex( parseFloat( tmp[0] ) , parseFloat( tmp[1] ) , parseFloat( tmp[2] ) );
tmp = b.replace(/rgba?\(/,"").replace(")","").split(",")
b = [parseFloat( tmp[0] ) , parseFloat( tmp[1] ) , parseFloat( tmp[2] )];
}
else {
b = hex2rga(b);
}
// console.log(source+" : "+a+"\t|\t"+target+" : "+b)
a = hex2rga(a);
b = hex2rga(b);
var r = (a[0] + b[0]) >> 1;
var g = (a[1] + b[1]) >> 1;
var b = (a[2] + b[2]) >> 1;
......
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