Commit 81a271bf authored by Romain Loth's avatar Romain Loth

Merge ProjectExplorer (3 relation types shown) commit '98f68d' into with_tina_1.2

parents 5be215b5 086db2d8
{
"data/gargistex": {
"first" : "shale_and_ice.gexf",
"gexfs": {
"graphs":{
"shale_and_ice.gexf": {
"dbtype": "csv",
"semantic":["title","keywords","abstract"],
"social":["authors"],
"dbfile": "shale_and_ice.csv"
"node0": {
"name": "terms",
"reldbtype": "csv",
"reldbfile": "shale_and_ice.csv",
"reldbqcols": ["title"],
"reltemplate": "_todo"
}
},
"model_calibration.gexf": {
"node0": {
"name": "terms",
"reldbtype": "csv",
"reldbfile": "model_calibration.csv",
"reldbqcols": ["title"],
"reltemplate": "_todo"
}
}
}
},
"data/test": {
"first" : "mini_for_csv.gexf",
"gexfs": {
"graphs": {
"mini_for_csv.gexf": {
"_comment": "NB: underspecified for csv and for db.json !! so this is a prototype structure",
"_comment": "POSS: weighted columns for matching importance",
"dbtype": "csv",
"semantic":["title","keywords","text"],
"social":["author"],
"dbfile": "mini_for_csv.csv"
"node0": {
"name": "term",
"reldbtype": "csv",
"reldbfile": "mini_for_csv.csv",
"reldbqcols": ["title","keywords","text"],
"reltemplate": "_todo"
},
"node1": {
"name": "person",
"reldbtype": "csv",
"reldbfile": "mini_for_csv.csv",
"reldbqcols": ["author"],
"reltemplate": "_todo"
}
},
"test_with_various_atts.gexf": {}
}
},
"data/politoscope": {
"dbname":null,
"title":"Politoscope",
"date":"2017",
"abstract":"",
"first" : "ProgrammeDesCandidats.enrichi.gexf",
"gexfs": {
"ProgrammeDesCandidats.enrichi.gexf": {
"social": {},
"semantic": {}
},
"ProgrammeDesCandidats.gexf": {
"social": {},
"semantic": {}
}
}
},
"dbname":null,
"title":"Politoscope",
"date":"2017",
"abstract":"",
"first" : "ProgrammeDesCandidats.enrichi.gexf",
"graphs": {
"ProgrammeDesCandidats.enrichi.gexf": {
"node0": { "name": "terms" }
},
"ProgrammeDesCandidats.gexf": {
"node0": { "name": "terms" }
}
}
},
"data/ClimateChange": {
"dbname":"wos_climate-change_title_2014-2015.db",
"title":"ISITITLE",
"date":"ISIpubdate",
"abstract":"ISIABSTRACT",
"gexfs": {
"Maps_S_800.gexf": {
"social": { "table":"ISIAUTHOR" , "textCol":"data","forkeyCol":"id"},
"semantic": { "table":"ISItermsWhitelistV2Oct_5" , "textCol":"data","forkeyCol":"id"}
}
}
"abstract":"ISIABSTRACT",
"graphs": {
"Maps_S_800.gexf": {
"node0": {
"name": "ISItermsWhitelistV2Oct_5 & ISItermsWhitelistV2Oct_5",
"reldbtable": "ISItermsWhitelistV2Oct_5",
"reldbname" : "wos_climate-change_title_2014-2015.db",
"reldbtype": "CortextDB"
}
}
}
},
"data/comexjsons": {
"first" : "graph_example.json",
"gexfs": {
"graph_example.json": {}
}
}
"data/comexjsons": {
"first" : "graph_example.json",
"graphs": {
"graph_example.json": {
"node0": { "name": "NGram" },
"node1": { "name": "Document" }
}
}
}
}
......@@ -467,7 +467,7 @@
class="custom-select form-control"
onchange="TW.conf.relatedDocsType=this.value; getTopPapers()">
<option value="twitter">Twitter API</option>
<option value="wosLocalDB">Local DB query</option>
<option value="LocalDB">Local DB query</option>
</select>
</div>
</div>
......
......@@ -38,12 +38,12 @@ TW.conf = (function(TW){
TWConf.relatedDocsMax = 10
TWConf.relatedDocsAPI = "http://127.0.0.1:5000/twitter_search"
TWConf.relatedDocsType = "twitter" // accepted: "twitter" | "wosLocalDB"
TWConf.relatedDocsType = "LocalDB" // accepted: "twitter" | "LocalDB"
// POSSible: "elastic"
TWConf.relatedDocsAPIS = {
// routes by corresponding type
"wosLocalDB": "twbackends/phpAPI",
"LocalDB": "twbackends/phpAPI",
"twitter": "http://127.0.0.1:5000/twitter_search"
}
......@@ -158,8 +158,9 @@ TW.conf = (function(TW){
// Node typology: categories (resp. 0 and 1) will get these default labels
TWConf.catSem = "NGram";
TWConf.catSoc = "Document";
// NB: these labels may be superseded by the input data's node types values
// cf. sortNodeTypes()
// NB: these labels may be superseded by:
// - the input data's node types values cf. sortNodeTypes()
// - in servermenu mode, by the node0 & node1 properties
// Modules path
// ------------
......@@ -183,7 +184,7 @@ TW.conf = (function(TW){
// Other GUI options
// ------------------
TWConf.sidePanelSize = "300px" // width of the side panel (def: 400px)
TWConf.sidePanelSize = "400px" // width of the side panel (def: 400px)
TWConf.filterSliders = true // show sliders for nodes/edges subsets
......@@ -248,7 +249,7 @@ TW.conf = (function(TW){
twNodeRendBorderColor: "#222",
// edges
minEdgeSize: 1, // in fact used in tina as edge size
minEdgeSize: 2, // in fact used in tina as edge size
defaultEdgeType: 'curve', // 'curve' or 'line' (curve only iff ourRendering)
twEdgeDefaultOpacity: 0.4, // initial opacity added to src/tgt colors
......@@ -272,8 +273,8 @@ TW.conf = (function(TW){
twSelectedColor: "default", // "node" for a label bg like the node color,
// "default" for note-like yellow
// not selected <=> grey
twNodesGreyOpacity: .35, // smaller value: more grey
// not selected <=> (1-greyness)
twNodesGreyOpacity: .7, // smaller value: more grey
twBorderGreyColor: "rgba(100, 100, 100, 0.5)",
twEdgeGreyColor: "rgba(150, 150, 150, 0.5)",
};
......@@ -302,7 +303,7 @@ TW.conf = (function(TW){
// relative sizes (iff ChangeType == both nodetypes)
TWConf.sizeMult = [];
TWConf.sizeMult[0] = 1.0; // ie for node type 0 (<=> sem)
TWConf.sizeMult[1] = 2.0; // ie for node type 1 (<=> soc)
TWConf.sizeMult[1] = 2.5; // ie for node type 1 (<=> soc)
// ===========
......@@ -317,7 +318,7 @@ TW.conf = (function(TW){
logFacets: false, // ...about parsing node attribute:value facets
logSettings: false, // ...about settings at Tina and Sigma init time
logStates: false, // ...about TW.states array
logSelections: true
logSelections: false
}
......
......@@ -52,7 +52,7 @@ To use the API for the "topPapers" embedded search in ProjectExplorer, the corre
- via the interface (side panel menu)
- or directly in settings_explorerjs.js:
```
TWConf.relatedDocsType = "wosLocalDB"
TWConf.relatedDocsType = "LocalDB" (CSV or CortextDB)
```
Finally, to match the correct DB with the correct graph file:
......@@ -64,7 +64,7 @@ Finally, to match the correct DB with the correct graph file:
"title":"yourDocumentTitlesTable",
"date":"yourDocumentPubDatesTable",
"abstract":"yourDocumentContentsTable",
"gexfs": {
"graphs": {
"your.graph.gexf": {
"semantic": { "table":"yourTableWithTerms"},
"social": { "table":"yourTableWithSocialNodes"}
......
This diff is collapsed.
......@@ -275,7 +275,9 @@ function changeType() {
// new state is the complement of the received state ~[X\Y]
var t1Activetypes = []
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)
var bipartiteKey = "1|1"
......@@ -288,7 +290,6 @@ function changeType() {
// so => we set here a fallback to "1|0"
if (t1ActivetypesKey == "0|0") {
t1Activetypes = [true, false]
t1ActivetypesKey = "1|0"
// 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
......@@ -299,6 +300,12 @@ function changeType() {
// special case: "macro level opens bipartite possibilities"
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
// (but only needed if local and no selections)
......@@ -324,12 +331,14 @@ function changeType() {
}
}
for(var eid in TW.Edges) {
if(TW.Edges[eid].categ==t1ActivetypesKey)
for (var k in t1Activereltypes) {
let reltype = t1Activereltypes[k]
if(TW.Edges[eid].categ==reltype)
add1Elem(eid)
}
// NB ie we don't add sameside edges "1|0" or "0|1" when target
// activetypes is "1|1" (aka "both")
// NB ie we **do** add sameside edges "1|0" or "0|1" when target
// activetypes is "1|1" (aka "both"), cf. inferActivereltypes
}
sourceNodes = sels
......@@ -361,8 +370,8 @@ function changeType() {
// [ ChangeType: incremental selection ;]
// Dictionaries of: opposite-neighs of current source nodes
var newnodeset = {}
var newsels = {}
var edgesToAdd = {}
for(var i in sourceNodes) {
let srcnid = sourceNodes[i];
let srctyp = TW.Nodes[srcnid].type
......@@ -370,7 +379,17 @@ function changeType() {
if (!mixedStart) {
// case where we have an single kind of Relations to consider
// 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 {
// case with a mixed starting point
......@@ -394,10 +413,9 @@ function changeType() {
if (t1Activetypes[TW.catDict[tgttyp]]) {
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) {
edgesToAdd[`${srcnid};${tgtnid}`] = true
edgesToAdd[`${tgtnid};${srcnid}`] = true
newnodeset[tgtnid] = true
}
}
}
......@@ -419,8 +437,23 @@ function changeType() {
for(var nid in newsels) {
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() {
TW.pushState({
activetypes: t1Activetypes,
activereltypes: t1Activereltypes,
sels: newselsArr,
// 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
......@@ -491,6 +525,7 @@ function changeLevel() {
var activetypes = present.activetypes;
var activetypesKey = activetypes.map(Number).join("|")
var activereltypes = present.activereltypes
TW.partialGraph.graph.clear();
......@@ -502,22 +537,26 @@ function changeLevel() {
for(var i in sels) {
s = sels[i];
nodesToAdd[s]=true;
if (TW.Relations[activetypesKey]) {
neigh = TW.Relations[activetypesKey][s]
if(neigh) {
for(var j in neigh) {
t = neigh[j]
nodesToAdd[t]=true;
edgesToAdd[s+";"+t]=true;
edgesToAdd[t+";"+s]=true;
if( !selsChecker[t] )
voisinage[ t ] = true;
}
for (var k in activereltypes) {
let activereltype = activereltypes[k]
console.log("level: considering reltype ", activereltype)
if (TW.Relations[activereltype]) {
neigh = TW.Relations[activereltype][s]
if(neigh) {
for(var j in neigh) {
t = neigh[j]
nodesToAdd[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() {
if( voisinage[i]!=voisinage[j] ) {
// console.log( "\t" + voisinage[i] + " vs " + voisinage[j] )
add1Elem( voisinage[i]+";"+voisinage[j] )
add1Elem( voisinage[j]+";"+voisinage[i] )
}
}
}
......@@ -1040,8 +1080,8 @@ function createWaitIcon(idname, width) {
}
function jsActionOnGexfSelector(gexfBasename){
let gexfPath = TW.gexfPaths[gexfBasename] || gexfBasename+".gexf"
function jsActionOnGexfSelector(graphBasename){
let graphPath = TW.gmenuPaths[graphBasename] || graphBasename+".gexf"
let serverPrefix = ''
var pathcomponents = window.location.pathname.split('/')
for (var i in pathcomponents) {
......@@ -1049,13 +1089,21 @@ function jsActionOnGexfSelector(gexfBasename){
serverPrefix += '/'+pathcomponents[i]
}
var newDataRes = AjaxSync({ "url": window.location.origin+serverPrefix+'/'+gexfPath });
var newDataRes = AjaxSync({ "url": window.location.origin+serverPrefix+'/'+graphPath });
// remove any previous instance and flags
TW.resetGraph()
// override default categories with the ones from db.json
if (TW.gmenuInfos[graphPath]) {
if (TW.gmenuInfos[graphPath].node0 && TW.gmenuInfos[graphPath].node0.name)
TW.conf.catSem = TW.gmenuInfos[graphPath].node0.name
if (TW.gmenuInfos[graphPath].node1 && TW.gmenuInfos[graphPath].node1.name)
TW.conf.catSem = TW.gmenuInfos[graphPath].node1.name
}
mainStartGraph(newDataRes["format"], newDataRes["data"], TW.instance)
writeLabel(gexfBasename)
TW.File = gexfPath
writeLabel(graphBasename)
TW.File = graphPath
}
//============================= </OTHER ACTIONS > =============================//
......@@ -22,7 +22,7 @@ function changeGraphAppearanceByFacets(actypes) {
let currentNbNodes = TW.partialGraph.graph.nNodes()
// create colormenu and 1st default entry
var color_menu_info = '<li><a href="#" onclick="TW.gui.handpickedcolor = false ; graphResetLabelsAndSizes()">By Default</a></li>';
var color_menu_info = '<li><a href="#" onclick="TW.gui.handpickedcolor = false ; graphResetLabelsAndSizes() ; TW.partialGraph.refresh()">By Default</a></li>';
if( $( "#colorgraph-menu" ).length>0 ) {
for (var tid in actypes) {
......@@ -404,6 +404,9 @@ function topPapersFetcher(swType, qWords, priorHtml, cbNext){
if (isUndef(priorHtml)) priorHtml = ''
if (isUndef(cbNext)) cbNext = displayTopPapers
// introducing the modern node type thanks to updated db.json specs
let nodetype = (swType == 'semantic') ? 0 : 1
let stockErrMsg = `<p class="micromessage">
Your settings for relatedDocsType are set on ${TW.conf.relatedDocsType}
API but it couldn't be connected to.</p>`
......@@ -448,19 +451,18 @@ function topPapersFetcher(swType, qWords, priorHtml, cbNext){
}
});
}
else if (TW.conf.relatedDocsType == "wosLocalDB") {
let gexfinfos = TW.relDocsInfos[TW.File]
if (!gexfinfos || !gexfinfos[swType]) {
else if (TW.conf.relatedDocsType == "LocalDB") {
let thisRelDocsConf = TW.gmenuInfos[TW.File][nodetype]
if (!thisRelDocsConf) {
resHTML =
`<p>Your settings for relatedDocsType are set on a local wos database,
`<p>Your settings for relatedDocsType are set on a local database,
but your servermenu file does not provide any information about
the DB table to query for related documents
(on nodetype ${swType})</p>`
the CSV or DB table to query for related documents
(on nodetype ${nodetype}: ${swType})</p>`
cbNext(priorHtml + resHTML)
return
}
else {
// /!\ documentation and specification needed for the php use cases /!\
let joinedQ = JSON.stringify(qWords).split('&').join('__and__');
// cf. the php code for these url args:
......@@ -469,23 +471,31 @@ function topPapersFetcher(swType, qWords, priorHtml, cbNext){
// or 'csv' (like gargantext exports)
// POSS object + join.map(join)
let urlParams = "type="+swType+"&query="+joinedQ+"&gexf="+TW.File+"&n="+TW.conf.relatedDocsMax+"&dbtype="+gexfinfos.dbtype
let urlParams = "type="+swType+"&query="+joinedQ+"&gexf="+TW.File+"&n="+TW.conf.relatedDocsMax+"&dbtype="+thisRelDocsConf.reldbtype
if (gexfinfos.dbtype == "sql") {
var qIndex = gexfinfos[swType] // a table
if (thisRelDocsConf.reldbtype == "CortextDB") {
var qIndex = thisRelDocsConf.reldbtable // a table
urlParams += `&index=${qIndex}`
}
else {
// a list of csv columns to search in
// ex: for semantic nodes matching we look in 'title', 'keywords' cols
// for social nodes matching we look in 'authors' col... etc.
let joinedSearchCols = JSON.stringify(gexfinfos[swType])
let joinedSearchCols = JSON.stringify(thisRelDocsConf.reldbqcols)
urlParams += `&searchin=${joinedSearchCols}`
let joinedAllCols = JSON.stringify(gexfinfos)
// HIGHER LEVEL SCOPE (whole indexation directive) WILL BE MOVED TO PHP
let allCols = {}
if (TW.gmenuInfos[TW.File][0])
allCols.semantic = TW.gmenuInfos[TW.File][0].reldbqcols
if (TW.gmenuInfos[TW.File][1])
allCols.social = TW.gmenuInfos[TW.File][1].reldbqcols
let joinedAllCols = JSON.stringify(allCols)
urlParams += `&toindex=${joinedAllCols}`
// POSS use a direct access from php to db.json to avoid toindex
// POSS make it a REST array like: index[]=title&index[]=keywords
}
$.ajax({
......@@ -502,12 +512,6 @@ function topPapersFetcher(swType, qWords, priorHtml, cbNext){
cbNext(priorHtml + stockErrMsg)
}
});
}
}
}
......
......@@ -12,18 +12,19 @@ TW.File = "" // remember the currently opened file
TW.partialGraph = null // will contain the sigma visible graph instance
TW.labels=[]; // fulltext search list
TW.gexfPaths={}; // for file selectors iff servermenu
TW.relDocsInfos={}; // map [graphsource => relatedDocs db fields or tables names]
// TODO requires specifications !!
// (iff servermenu && relatedDocsType == 'wosLocalDB')
TW.categories = []; // possible node types and their inverted map
TW.catDict = {};
// used iff servermenu
TW.gmenuPaths={}; // map [graphname => graphsource] for file selectors
TW.gmenuInfos={}; // map [graphsource => { node0/1 categories
// + relatedDocs db fields names}]
// a system state is the summary of tina situation
TW.initialSystemState = {
activetypes: [], // <== filled from TW.categories
activereltypes: [], // <== same for edges
level: true,
selectionNids: [], // <== current selection !!
selectionRels: [], // <== current highlighted neighbors
......@@ -259,58 +260,40 @@ function syncRemoteGraphData () {
var files_selector = '<select onchange="jsActionOnGexfSelector(this.value);">'
for( var path in preRES.data ) {
var theGexfs = preRES.data[path]["gexfs"]
var theGraphs = preRES.data[path]["graphs"]
for(var aGexf in theGexfs) {
var gexfBasename = aGexf.replace(/\.gexf$/, "") // more human-readable in the menu
TW.gexfPaths[gexfBasename] = path+"/"+aGexf
for(var aGraph in theGraphs) {
var graphBasename = aGraph.replace(/\.gexf$/, "") // more human-readable in the menu
TW.gmenuPaths[graphBasename] = path+"/"+aGraph
// ex : "RiskV2PageRank1000.gexf":data/AXA/RiskV2PageRank1000.gexf
// (we assume there's no duplicate basenames)
if (TW.conf.debug.logFetchers)
console.log("\t\t\t"+gexfBasename)
// for associated wosLocalDBs sql queries
if (theGexfs[aGexf]) {
let gSrcEntry = theGexfs[aGexf]
console.log("\t\t\t"+graphBasename)
TW.relDocsInfos[path+"/"+aGexf] = {"semantic":null, "social":null, "dbtype": null}
// for associated LocalDB php queries: CSV (or CortextDBs sql)
if (theGraphs[aGraph]) {
// POSS have this type attribute in db.json *for all the entries*
let gSrcEntry = theGraphs[aGraph]
// ----------------------------------------------------------------------------------
// choice: we'll keep a flat structure by source unless some use cases need otherwise
// ----------------------------------------------------------------------------------
// csv LocalDB ~ gargantext
if(gSrcEntry["dbtype"] && gSrcEntry["dbtype"] == "csv") {
TW.relDocsInfos[path+"/"+aGexf]['dbtype'] = "csv"
TW.gmenuInfos[path+"/"+aGraph] = new Array(2)
// it's CSV columns here
TW.relDocsInfos[path+"/"+aGexf]['semantic'] = gSrcEntry["semantic"]
TW.relDocsInfos[path+"/"+aGexf]['social'] = gSrcEntry["social"]
if (gSrcEntry.node0) {
TW.gmenuInfos[path+"/"+aGraph][0] = gSrcEntry.node0
}
// sqlite LocalDB ~ wos
else {
TW.relDocsInfos[path+"/"+aGexf]['dbtype'] = "sql"
if (theGexfs[aGexf]["semantic"] && theGexfs[aGexf]["semantic"]["table"]) {
TW.relDocsInfos[path+"/"+aGexf]['semantic'] = theGexfs[aGexf]["semantic"]["table"]
}
if (theGexfs[aGexf]["social"] && theGexfs[aGexf]["social"]["table"]) {
TW.relDocsInfos[path+"/"+aGexf]['social'] = theGexfs[aGexf]["social"]["table"]
}
if (gSrcEntry.node1) {
TW.gmenuInfos[path+"/"+aGraph][0] = gSrcEntry.node0
}
}
else {
TW.relDocsInfos[path+"/"+aGexf] = null
TW.gmenuInfos[path+"/"+aGraph] = null
}
// ^^^^^^ FIXME see if we got the expected behavior right
// (? specifications ?)
// ^^^^^^ FIXME finish implementing new specifications
let cssFileSelected = (TW.File==(path+"/"+aGexf))?"selected":""
files_selector += '<option '+cssFileSelected+'>'+gexfBasename+'</option>'
let cssFileSelected = (TW.File==(path+"/"+aGraph))?"selected":""
files_selector += '<option '+cssFileSelected+'>'+graphBasename+'</option>'
}
// console.log( files_selector )
}
......@@ -384,6 +367,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
// activetypes: the node categorie(s) that is (are) currently displayed
// ex: [true,false] = [nodes of type 0 shown ; nodes of type 1 not drawn]
var initialActivetypes = TW.instance.initialActivetypes( TW.categories )
var initialActivereltypes = TW.instance.inferActivereltypes( initialActivetypes )
// XML parsing from ParseCustom
var dicts = start.makeDicts(TW.categories); // > parse json or gexf, dictfy
......@@ -424,7 +408,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
// preparing the data (TW.Nodes and TW.Edges filtered by initial type)
// POSS: avoid this step and use the filters at rendering time!
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 ---------
......@@ -514,7 +498,10 @@ function mainStartGraph(inFormat, inData, twInstance) {
// ==================================================================
// 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
// by changeLevel, changeType or subset sliders => no need to keep it
......@@ -528,7 +515,11 @@ function mainStartGraph(inFormat, inData, twInstance) {
// 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
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 ]
......
......@@ -19,9 +19,10 @@ TW.pushState = function( args ) {
newState.id ++
// 2) we update it with provided args
if (!isUndef(args.activetypes)) newState.activetypes = args.activetypes
if (!isUndef(args.level)) newState.level = args.level;
if (!isUndef(args.sels)) newState.selectionNids = args.sels;
if (!isUndef(args.activetypes)) newState.activetypes = args.activetypes
if (!isUndef(args.activereltypes)) newState.activereltypes = args.activereltypes
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
if(!isUndef(args.rels)) newState.selectionRels = args.rels;
......@@ -72,9 +73,10 @@ TW.pushState = function( args ) {
NodeWeightFilter( "#slidercat0nodesweight" , TW.categories[0]);
NodeWeightFilter( "#slidercat1nodesweight" , TW.categories[1]);
// only truly bipartite edges => only one GUI slider
showDisabledSlider("#slidercat0edgesweight")
EdgeWeightFilter("#slidercat1edgesweight", "1|1", "weight");
// one slider for each intra-type reltype
EdgeWeightFilter("#slidercat0edgesweight", "1|0", "weight");
EdgeWeightFilter("#slidercat1edgesweight", "0|1", "weight");
// NB: no slider for truly bipartite edges => 2 GUI sliders but 3 edge types
}
}
......
......@@ -3,19 +3,25 @@
var SigmaUtils = function () {
// 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("FillGraph catDict",catDict)
// console.log("FillGraph nodes",nodes)
// console.log("FillGraph edges",edges)
// retrocompatibility -------------------------------- 8< -------------
if (!initialActivereltypes.length) {
initialActivereltypes = [initialActivetypes.map(Number).join("|")]
}
// ---------------------------------------------------- 8< -------------
let i = 0
for(var nid in nodes) {
var n = nodes[nid];
// console.debug('tr >>> fgr node', n)
if(initialActivetypes[catDict[n.type]] || TW.conf.debug.initialShowAll) {
if(initialActivetypes[catDict[n.type]]) {
// var node = {
// id : n.id,
// label : n.label,
......@@ -43,20 +49,20 @@ var SigmaUtils = function () {
}
}
// the typestring of the activetypes is the key to stored Relations (<=> edges)
var activetypesKey = initialActivetypes.map(Number).join("|")
for(let srcnid in TW.Relations[activetypesKey]) {
for(var j in TW.Relations[activetypesKey][srcnid]) {
let tgtnid = TW.Relations[activetypesKey][srcnid][j]
let e = TW.Edges[srcnid+";"+tgtnid]
if(e) {
if(e.source != e.target) {
graph.edges.push( e);
}
}
}
// the typestrings in activereltypes are the key to stored Relations (<=> edges)
for (var k in initialActivereltypes) {
let reltype = initialActivereltypes[k]
for(let srcnid in TW.Relations[reltype]) {
for(var j in TW.Relations[reltype][srcnid]) {
let tgtnid = TW.Relations[reltype][srcnid][j]
let e = TW.Edges[srcnid+";"+tgtnid]
if(e) {
if(e.source != e.target) {
graph.edges.push( e);
}
}
}
}
}
return graph;
}// output = sigma graph
......@@ -665,7 +671,6 @@ function edgeInfos(anEdge) {
function gradientColoring(daclass) {
cancelSelection(false); // loops only on selected
graphResetLabelsAndSizes() // full loop
TW.gui.handpickedcolor = true
......@@ -853,7 +858,6 @@ function heatmapColoring(daclass) {
binColors = getHeatmapColors(nColors)
// let's go
cancelSelection(false); // loops only on selected
graphResetLabelsAndSizes() // full loop
// global flag
......@@ -909,9 +913,6 @@ function heatmapColoring(daclass) {
function clusterColoring(daclass) {
console.log("clusterColoring ( "+daclass+" )")
cancelSelection(false); // now loops only on selected
graphResetLabelsAndSizes() // full loop
// louvain needs preparation
......
......@@ -37,12 +37,12 @@ TW.conf = (function(TW){
TWConf.getRelatedDocs = false
TWConf.relatedDocsMax = 10
TWConf.relatedDocsType = "twitter" // accepted: "twitter" | "wosLocalDB"
TWConf.relatedDocsType = "twitter" // accepted: "twitter" | "LocalDB"
// POSSible: "elastic"
TWConf.relatedDocsAPIS = {
// routes by corresponding type
"wosLocalDB": "twbackends/phpAPI",
"LocalDB": "twbackends/phpAPI",
"twitter": "http://127.0.0.1:5000/twitter_search"
}
......
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