Commit abe38cc1 authored by Romain Loth's avatar Romain Loth

Merge commit '34c418592895e1e3da682048e92eb3528b0d0b59' into with_tina_1.2

parents d7ead62c 50f71e4c
......@@ -36,6 +36,7 @@ TW.conf = (function(TW){
TWConf.getRelatedDocs = false
TWConf.relatedDocsMax = 10
TWConf.relatedDocsAPI = "http://127.0.0.1:5000/twitter_search"
TWConf.relatedDocsType = "twitter" // accepted: "twitter" | "LocalDB"
// POSSible: "elastic"
......@@ -145,9 +146,9 @@ TW.conf = (function(TW){
TWConf.maxDiscreteValues = 15
TWConf.legendsBins = 7
// to normalize node sizes: (NB not very useful because tina normalizes them at display)
// to normalize node sizes (larger range does increase visual size difference)
TWConf.desirableNodeSizeMin=1;
TWConf.desirableNodeSizeMax=2;
TWConf.desirableNodeSizeMax=10;
// =============
......@@ -256,8 +257,8 @@ TW.conf = (function(TW){
font: "Droid Sans", // font params
fontStyle: "bold",
defaultLabelColor: '#000', // labels text color
labelSizeRatio: 1, // initial label size (on the slider)
labelThreshold: 5, // min node cam size to start showing label
labelSizeRatio: 1, // label size in ratio of node size
labelThreshold: 4, // min node cam size to start showing label
// (old tina: showLabelsIfZoom)
// hovered nodes
......@@ -301,8 +302,8 @@ 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] = 5.0; // ie for node type 1 (<=> soc)
TWConf.sizeMult[0] = 1.0; // ie for node type 0 (<=> sem)
TWConf.sizeMult[1] = 10.0; // ie for node type 1 (<=> soc)
// ===========
......
......@@ -9,7 +9,7 @@ ini_set('display_startup_errors',1);
include('parameters_details.php');
if ($_GET['dbtype'] == "sql") {
if ($_GET['dbtype'] == "CortextDB") {
$base = new PDO("sqlite:".$mainpath.$graphdb);
include('default_div.php');
}
......
......@@ -756,6 +756,12 @@ var TinaWebJS = function ( sigmacanvas ) {
this.style.cursor = 'wait'
// and waiting icon
this.insertBefore(createWaitIcon('noverlapwait'), this.children[0])
// reconfigure to account for nodesizes (if current sizes up => margin needs up)
let sizeFactor = Math.max.apply(null, TW.gui.sizeRatios)
TW.gui.noverlapConf.nodeMargin = .5 * sizeFactor
TW.gui.noverlapConf.scaleNodes = 1.5 * sizeFactor
TW.partialGraph.configNoverlap(TW.gui.noverlapConf)
var listener = TW.partialGraph.startNoverlap();
var noverButton = this
listener.bind('stop', function(event) {
......@@ -1112,13 +1118,8 @@ var TinaWebJS = function ( sigmacanvas ) {
labelSizeTimeout = setTimeout(function(){
if (TW.gui.sizeRatios[0] != value) {
TW.gui.sizeRatios[0] = value
// -------------------------------------------------------------
// generic efficient method acting on entire graphs label ratio
// (can't use it b/c we need to distinguish by type)
// var adaptedLabelThreshold = 7 - value
// TW.partialGraph.settings('labelSizeRatio', value)
// TW.partialGraph.settings('labelThreshold', adaptedLabelThreshold)
// -------------------------------------------------------------
// also adapt label threshold
TW.partialGraph.settings('labelThreshold', getSizeFactor())
TW.partialGraph.render()
}
}, 200)
......@@ -1138,6 +1139,8 @@ var TinaWebJS = function ( sigmacanvas ) {
labelSizeTimeout = setTimeout(function(){
if (TW.gui.sizeRatios[1] != value) {
TW.gui.sizeRatios[1] = value
// also adapt label threshold
TW.partialGraph.settings('labelThreshold', getSizeFactor())
TW.partialGraph.render()
}
}, 200)
......@@ -1212,5 +1215,4 @@ var TinaWebJS = function ( sigmacanvas ) {
return activereltypes;
}
};
......@@ -27,6 +27,17 @@ TW.gui.lastFilters = {}
TW.gui.sizeRatios = [1,1] // sizeRatios per nodetype
TW.gui.noverlapConf = {
nodeMargin: .4,
scaleNodes: 1.5,
gridSize: 300,
speed: 7,
maxIterations: 8,
easing: 'quadraticOut', // animation transition function
duration: 1500 // animation duration
// NB animation happens *after* processing
}
// POSS: themed variants (ex: for dark bg vs light bg)
// contrasted color list for clusterColoring()
......@@ -475,9 +486,13 @@ function changeType(optionaltypeFlag) {
console.log("selection transitive projection from",sourceNids, "to", newselsArr)
}
// update the color menu
// update the gui (POSS could be handled by TW.pushGUIState)
TW.gui.handpickedcolor = false
changeGraphAppearanceByFacets( getActivetypesNames() )
if (typeFlag != 'all') {
graphResetLabelsAndSizes()
}
TW.partialGraph.settings('labelThreshold', getSizeFactor())
// recreates FA2 nodes array from new nodes
reInitFa2({
......@@ -1114,10 +1129,14 @@ function jsActionOnGexfSelector(graphBasename){
// 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
if (TW.gmenuInfos[graphPath][0] && TW.gmenuInfos[graphPath][0].name) {
TW.conf.catSem = TW.gmenuInfos[graphPath][0].name
console.log("new catSem:", TW.conf.catSem)
}
if (TW.gmenuInfos[graphPath][1] && TW.gmenuInfos[graphPath][1].name) {
TW.conf.catSoc = TW.gmenuInfos[graphPath][1].name
console.log("new catSoc:", TW.conf.catSoc)
}
}
mainStartGraph(newDataRes["format"], newDataRes["data"], TW.instance)
......
......@@ -284,7 +284,7 @@ function syncRemoteGraphData () {
TW.gmenuInfos[path+"/"+aGraph][0] = gSrcEntry.node0
}
if (gSrcEntry.node1) {
TW.gmenuInfos[path+"/"+aGraph][0] = gSrcEntry.node0
TW.gmenuInfos[path+"/"+aGraph][1] = gSrcEntry.node1
}
}
......@@ -531,18 +531,7 @@ function mainStartGraph(inFormat, inData, twInstance) {
// init FA2 for any future forceAtlas2 calls
TW.partialGraph.configForceAtlas2(TW.FA2Params)
// init noverlap for any future calls
TW.partialGraph.configNoverlap({
nodeMargin: .4,
scaleNodes: 1.5,
gridSize: 400,
speed: 5,
maxIterations: 10,
easing: 'quadraticOut', // animation transition function
duration: 1500 // animation duration
// NB animation happens *after* processing
});
// NB: noverlap conf depends on sizeRatios so updated before each run
// REFA new sigma.js
TW.partialGraph.camera.goTo({x:0, y:0, ratio:0.9, angle: 0})
......
......@@ -175,6 +175,11 @@ function getActiverelsKey(someState) {
}
}
// how many types are currently active
function getNActive(someState) {
return TW.SystemState().activetypes.filter(function(bool){return bool}).length
}
// transitional function:
// ----------------------
// Goal: determine if a single nodetype or global activetype is semantic or social
......
......@@ -192,10 +192,11 @@ function scanGexf(gexfContent) {
if (! isUndef(declaredAttrs.nodeAttrs[attr]))
attr = declaredAttrs.nodeAttrs[attr].title
// console.log('attr', attr)
// THIS WILL BECOME catDict (if ncats == 1 => monopart)
if (attr=="category") categoriesDict[val]=val;
if (attr=="category" || attr=="type") {
if (!categoriesDict[val]) categoriesDict[val] = 0
categoriesDict[val]++;
}
}
}
}
......@@ -213,40 +214,58 @@ function scanGexf(gexfContent) {
// ex: ISItermsriskV2_140 & ISItermsriskV2_140
function sortNodeTypes(observedTypesDict) {
var observedTypes = Object.keys(observedTypesDict)
observedTypes.sort(function(a,b) {return observedTypesDict[b] - observedTypesDict[a]})
var newcats = []
var catDict = {}
var nTypes = observedTypes.length
if(nTypes==0) {
observedTypes[0]="Terms";
newcats[0]="Terms";
catDict["Terms"] = 0;
}
if(nTypes==1) {
// if we have only one category, it gets code 0 as Terms
newcats[0] = observedTypes[0]
catDict[observedTypes[0]] = 0;
if (TW.conf.debug.logParsers)
console.log(`cat unique (${observedTypes[0]}) =>0`)
}
if(nTypes>1) {
var newcats = []
// allows multiple node types, with an "all the rest" node1
// try stipulated cats, then fallbacks
if (observedTypesDict[TW.conf.catSem]) {
newcats[0] = TW.conf.catSem;
catDict[TW.conf.catSem] = 0;
}
if (observedTypesDict[TW.conf.catSoc]) {
newcats[1] = TW.conf.catSoc;
catDict[TW.conf.catSoc] = 1;
}
// NB: only 2 cat labels are allowed by this
// NB: type for nodes0 will be the majoritary by default, unless taken
if (!newcats[0]) {
if (observedTypes[0] != newcats[1])
newcats[0] = observedTypes[0] // 0 is the most frequent here
else
newcats[0] = observedTypes[1] // 1 is second most frequent
}
// all the rest
for(var i in observedTypes) {
let c = observedTypes[i]
if(c == TW.conf.catSoc) {// conf says that it's not a term-category
newcats[1] = c;
catDict[c] = 1;
}
// else: term-category is the new default
else {
newcats[0] = c;
catDict[c] = 0;
}
let c = observedTypes[i]
// or c is in "all the rest" group
// (POSS extend to multitypes)
if (c != newcats[0] && c != newcats[1]) {
if (!newcats[1]) newcats[1] = c;
else newcats[1] += '/'+c
catDict[c] = 1;
}
}
observedTypes = newcats;
}
return {'categories': observedTypes, 'lookup_dict': catDict}
return {'categories': newcats, 'lookup_dict': catDict}
}
......@@ -602,12 +621,18 @@ function dictfyGexf( gexf , categories ){
var catCount = {}
for(var i in categories) catDict[categories[i]] = i;
var edges={}, nodes={}
var edges={}, nodes={}, nodesByType={}
var declaredAtts = gexfCheckAttributesMap(gexf)
var nodesAttributes = declaredAtts.nodeAttrs
// var edgesAttributes = declaredAtts.eAttrs
// NB nodesByType lists arrays of ids per nodetype
// (equivalent to TW.partialGraph.graph.getNodesByType but on full nodeset)
for(var i in categories) {
catDict[categories[i]] = i
nodesByType[i] = []
}
var elsNodes = gexf.getElementsByTagName('nodes') // The list of xml nodes 'nodes' (plural)
TW.labels = [];
......@@ -744,6 +769,14 @@ function dictfyGexf( gexf , categories ){
// save record
nodes[node.id] = node
// console.log("catDict", catDict)
// console.log("node.type", node.type)
if (!nodesByType[catDict[node.type]]) {
console.warn("unrecognized type:", node.type)
}
else {
nodesByType[catDict[node.type]].push(node.id)
}
if(parseFloat(node.size) < minNodeSize)
minNodeSize= parseFloat(node.size);
......@@ -886,7 +919,7 @@ function dictfyGexf( gexf , categories ){
resDict.catCount = catCount; // ex: {'ISIterms':1877} ie #nodes
resDict.nodes = nodes; // { nid1: {label:"...", size:"11.1", attributes:"...", color:"#aaa", etc}, nid2: ...}
resDict.edges = edges;
resDict.byType = nodesByType;
return resDict;
}
......@@ -978,8 +1011,11 @@ function scanJSON( data ) {
var nodes = data.nodes;
for(var i in nodes) {
let n = nodes[i];
if(n.type) categoriesDict[n.type]=n.type;
let ntype = nodes[i].type;
if(ntype) {
if (!categoriesDict[ntype]) categoriesDict[ntype] = 0
categoriesDict[ntype]++;
}
}
// sorting observed json node types into Sem (=> 1)/Soc (=> 0)
......@@ -1055,7 +1091,12 @@ function dictfyJSON( data , categories ) {
// record
nodes[node.id] = node;
nodesByType[catDict[node.type]].push(node.id)
if (!nodesByType[catDict[node.type]]) {
console.warn("unrecognized type:", node.type)
}
else {
nodesByType[catDict[node.type]].push(node.id)
}
// creating a faceted index from node.attributes
if (TW.conf.scanClusters) {
......
......@@ -565,6 +565,13 @@ var SigmaUtils = function () {
else {
if ((TW.conf.fa2Enabled || args.manual)
&& TW.partialGraph.graph.nNodes() >= TW.conf.minNodesForAutoFA2) {
setTimeout(function(){
// NB in here scope: 'this' is the window
if (TW.partialGraph.isForceAtlas2Running())
sigma_utils.ourStopFA2()
},
args.duration)
// hide edges during work for smaller cpu load
if (TW.partialGraph.settings('drawEdges')) {
this.toggleEdges(false)
......@@ -578,13 +585,6 @@ var SigmaUtils = function () {
var btn = document.querySelector('#layoutButton')
btn.insertBefore(icon, btn.children[0])
setTimeout(function(){
// NB in here scope: 'this' is the window
if (TW.partialGraph.isForceAtlas2Running())
sigma_utils.ourStopFA2()
},
args.duration)
return;
}
......@@ -1029,6 +1029,23 @@ function clusterColoring(daclass) {
}
// for labelThreshold:
// factor to reduce speed of growth of the amount of labels when size goes up
// /!\ important params to avoid having unreadable mess of labels or none at all
function getSizeFactor(val) {
let nActive = getNActive()
let sliderFactor
let adjustmentFactor = TW.conf.sigmaJsDrawingProperties.labelThreshold
if (nActive == 1) {
let activeId = TW.catDict[getActivetypesNames()[0]]
sliderFactor = TW.gui.sizeRatios[activeId]
}
else {
sliderFactor = Math.min.apply(null, TW.gui.sizeRatios)
}
return adjustmentFactor * (sliderFactor * 1.15)
}
// mobile versions should get lighter settings
function mobileAdaptConf() {
......
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