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": {}
}
......@@ -30,33 +50,35 @@
"date":"2017",
"abstract":"",
"first" : "ProgrammeDesCandidats.enrichi.gexf",
"gexfs": {
"graphs": {
"ProgrammeDesCandidats.enrichi.gexf": {
"social": {},
"semantic": {}
"node0": { "name": "terms" }
},
"ProgrammeDesCandidats.gexf": {
"social": {},
"semantic": {}
"node0": { "name": "terms" }
}
}
},
"data/ClimateChange": {
"dbname":"wos_climate-change_title_2014-2015.db",
"title":"ISITITLE",
"date":"ISIpubdate",
"abstract":"ISIABSTRACT",
"gexfs": {
"graphs": {
"Maps_S_800.gexf": {
"social": { "table":"ISIAUTHOR" , "textCol":"data","forkeyCol":"id"},
"semantic": { "table":"ISItermsWhitelistV2Oct_5" , "textCol":"data","forkeyCol":"id"}
"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": {}
"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"}
......
......@@ -175,6 +175,7 @@ function SelectionEngine() {
var activetypesKey = getActivetypesKey()
var activereltypes = TW.SystemState().activereltypes
// Dictionaries of: selection+neighbors for the new state and updateRelatedNodesPanel
......@@ -182,7 +183,11 @@ function SelectionEngine() {
// detailed relations sorted by types and srcid (for state cache, deselects etc)
let activeRelations = {}
activeRelations[activetypesKey] = {}
for (var k in activereltypes) {
let activereltype = activereltypes[k]
activeRelations[activereltype] = {}
}
// cumulated neighbor weights no matter what srcid (for tagCloud etc)
let sameSideNeighbors = {}
......@@ -197,10 +202,14 @@ function SelectionEngine() {
for(var i in ndsids) {
var srcnid = ndsids[i];
if(TW.Relations[activetypesKey] && TW.Relations[activetypesKey][srcnid] ) {
var neighs = TW.Relations[activetypesKey][srcnid]
activeRelations[activetypesKey][srcnid] = {}
for (var k in activereltypes) {
let activereltype = activereltypes[k]
if(TW.Relations[activereltype] && TW.Relations[activereltype][srcnid] ) {
var neighs = TW.Relations[activereltype][srcnid]
activeRelations[activereltype][srcnid] = {}
if(neighs) {
for(var j in neighs) {
......@@ -227,20 +236,20 @@ function SelectionEngine() {
}
// and the detailed info
if (typeof activeRelations[activetypesKey][srcnid][tgtnid] == 'undefined') {
activeRelations[activetypesKey][srcnid][tgtnid]=0
if (typeof activeRelations[activereltype][srcnid][tgtnid] == 'undefined') {
activeRelations[activereltype][srcnid][tgtnid]=0
}
// **make the edge active**
if (e1 && !e1.hidden) {
e1.customAttrs.activeEdge = 1;
sameSideNeighbors[tgtnid] += e1.weight || 1
activeRelations[activetypesKey][srcnid][tgtnid] += e1.weight || 1
activeRelations[activereltype][srcnid][tgtnid] += e1.weight || 1
}
if (e2 && !e2.hidden) {
e2.customAttrs.activeEdge = 1;
sameSideNeighbors[tgtnid] += e2.weight || 1
activeRelations[activetypesKey][srcnid][tgtnid] += e2.weight || 1
activeRelations[activereltype][srcnid][tgtnid] += e2.weight || 1
}
// we add as neighbor to color it (except if already in targeted)
......@@ -250,6 +259,9 @@ function SelectionEngine() {
}
}
}
}
// we make the selected (source) node active too
let src = TW.partialGraph.graph.nodes(srcnid)
src.customAttrs.active = true;
......@@ -643,31 +655,22 @@ var TinaWebJS = function ( sigmacanvas ) {
});
$("#changetype").click(function(){
console.log("")
console.log(" ############ changeTYPE click");
console.log("changeTYPE click");
if (TW.partialGraph.isForceAtlas2Running())
sigma_utils.ourStopFA2();
console.log("DBG before changeType SystemState:", TW.SystemState())
changeType();
setTimeout(function(){
$('.etabs a[href="#tabs1"]').trigger('click');
},500)
console.log(" ############ / changeTYPE click");
console.log("")
});
$("#changelevel").click(function(){
console.log("")
console.log(" ############ changeLEVEL click");
console.log("changeLEVEL click");
if (TW.partialGraph.isForceAtlas2Running())
sigma_utils.ourStopFA2();
changeLevel();
console.log(" ############ / changeLEVEL click");
console.log("")
});
// sidepanel folding
......@@ -876,9 +879,9 @@ var TinaWebJS = function ( sigmacanvas ) {
// to init local, instance-related listeners (need to run at new sigma instance)
// args: @partialGraph = a sigma instance
this.initSigmaListeners = function(partialGraph, initialActivetypes) {
this.initSigmaListeners = function(partialGraph, initialActivetypes, initialActivereltypes) {
console.log("initSigmaListeners TW.categories", TW.categories)
console.log("initSigmaListeners TW.categories / types array / reltypeskeys array: ", TW.categories, initialActivetypes, initialActivereltypes)
var selInst = this.selNgn
......@@ -1075,20 +1078,30 @@ var TinaWebJS = function ( sigmacanvas ) {
// the indice of the first cat to be active (ex: '1')
let activeId = initialActivetypes.indexOf(true)
for (let activeId in initialActivetypes) {
if (initialActivetypes[activeId]) {
// args: for display: target div ,
// for context: family/type prop value,
// for values: the property to filter
NodeWeightFilter ( `#slidercat${activeId}nodesweight` ,
TW.categories[activeId]
);
}
}
for (var k in initialActivereltypes) {
let reltypeKey = initialActivereltypes[k]
// ex: #slidercat1edgesweight
EdgeWeightFilter(`#slidercat${activeId}edgesweight`,
getActivetypesKey(),
reltypeKey,
"weight"
);
}
}
// node's label size
var labelSizeTimeout = null
$("#sliderlabelsize0").freshslider({
......@@ -1170,14 +1183,39 @@ var TinaWebJS = function ( sigmacanvas ) {
// our current choice: show only the last cat
// POSS make it a configuration settings
// except when setting TW.conf.debug.initialShowAll
this.initialActivetypes = function( categories ) {
var firstActivetypes = []
let firstActivetypes = []
for(var i=0; i<categories.length ; i++) {
if(i==categories.length-1) firstActivetypes.push(true)
if (TW.conf.debug.initialShowAll || i==categories.length-1) {
firstActivetypes.push(true)
}
else firstActivetypes.push(false)
}
return firstActivetypes;
}
// new business logic associating some activetypes to some activerels
// (it now allows multiple "relation-families" to be added as visible edges)
this.inferActivereltypes = function( nodeActivetypes ) {
let firstActivereltypes = []
// multiple nodetypes all true => all reltypes
if (TW.conf.debug.initialShowAll || nodeActivetypes.indexOf(false) == -1) {
let combinations = {}
if (TW.categories.length == 1) {
firstActivereltypes = ['1']
}
else if (TW.categories.length == 2) {
firstActivereltypes = ['0|1', '1|0', '1|1']
}
// POSSible: generalize if length > 1: recurse to generate all true/false combinations except the all-false one
}
// normal case: one activereltype, equal to the initialActivetype key
else {
firstActivereltypes = [nodeActivetypes.map(Number).join("|")]
}
return firstActivereltypes;
}
};
......@@ -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,10 +437,25 @@ function changeType() {
for(var nid in newsels) {
add1Elem(nid)
}
for(var eid in edgesToAdd) {
// 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)
}
}
}
}
}
}
let newselsArr = Object.keys(newsels)
......@@ -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,8 +537,11 @@ function changeLevel() {
for(var i in sels) {
s = sels[i];
nodesToAdd[s]=true;
if (TW.Relations[activetypesKey]) {
neigh = TW.Relations[activetypesKey][s]
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]
......@@ -520,6 +558,7 @@ function changeLevel() {
console.log("no edges between these nodes")
}
}
}
var futurelevel = null
......@@ -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]
TW.relDocsInfos[path+"/"+aGexf] = {"semantic":null, "social":null, "dbtype": null}
console.log("\t\t\t"+graphBasename)
// POSS have this type attribute in db.json *for all the entries*
// for associated LocalDB php queries: CSV (or CortextDBs sql)
if (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"
let gSrcEntry = theGraphs[aGraph]
// it's CSV columns here
TW.relDocsInfos[path+"/"+aGexf]['semantic'] = gSrcEntry["semantic"]
TW.relDocsInfos[path+"/"+aGexf]['social'] = gSrcEntry["social"]
}
TW.gmenuInfos[path+"/"+aGraph] = new Array(2)
// 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.node0) {
TW.gmenuInfos[path+"/"+aGraph][0] = gSrcEntry.node0
}
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 ]
......
......@@ -20,6 +20,7 @@ TW.pushState = function( args ) {
// 2) we update it with provided args
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;
......@@ -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,13 +49,12 @@ 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]
// 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) {
......@@ -58,6 +63,7 @@ var SigmaUtils = function () {
}
}
}
}
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