Commit 4c1a7550 authored by Romain Loth's avatar Romain Loth

1st working version of bipartite colors

parent 5789f53a
...@@ -165,6 +165,13 @@ html.waiting { ...@@ -165,6 +165,13 @@ html.waiting {
display: none; /* initial display off but turned on if bipartite */ display: none; /* initial display off but turned on if bipartite */
} }
.pseudo-optgroup {
color: #555;
text-align: center;
font-size: 90%;
padding: 1.5em 0 .5em 0;
}
.tagcloud-item{ .tagcloud-item{
display:inline-block; display:inline-block;
border:solid 1px; border:solid 1px;
......
...@@ -68,56 +68,120 @@ function changeGraphAppearanceByFacets(actypes) { ...@@ -68,56 +68,120 @@ function changeGraphAppearanceByFacets(actypes) {
if (!actypes) actypes = getActivetypesNames() if (!actypes) actypes = getActivetypesNames()
let colorsMeta = {}
let allNbNodes = TW.partialGraph.graph.nNodes() let allNbNodes = TW.partialGraph.graph.nNodes()
// create colormenu and 1st default entry
var color_menu_info = '<li><a href="#" onclick="graphResetAllColors() ; TW.partialGraph.refresh()">By Default</a></li>';
let gotPreviousLouvain = false let gotPreviousLouvain = false
if( $( "#colorgraph-menu" ).length>0 ) {
for (var k in actypes) {
let ty = actypes[k]
let currentNbNodes = TW.ByType[TW.catDict[ty]].length
// each facet family or clustering type was already prepared let currentNbNodes = {}
for (var attTitle in TW.Facets[ty]) { for (var k in actypes) {
currentNbNodes[actypes[k]] = TW.partialGraph.graph.getNodesByType(TW.catDict[actypes[k]]).length
}
// console.warn('changeGraphAppearanceByFacets:', ty, attTitle) // 1st loop: census on [colors <=> types] and involved nb Nodes
for (var k in actypes) {
let ty = actypes[k]
let attNbNodes = currentNbNodes[ty]
// note any previous louvains // each facet family or clustering type was already prepared
if (attTitle == 'clust_louvain') gotPreviousLouvain = true for (var attTitle in TW.Facets[ty]) {
if (! colorsMeta[attTitle]) {
colorsMeta[attTitle] = []
}
// attribute counts: nb of classes // attribute counts: nb of classes
// POSS here distinguish [ty][attTitle].classes.length and ranges.length // POSS here distinguish [ty][attTitle].classes.length and ranges.length
let attNbClasses = TW.Facets[ty][attTitle].invIdx.length let attNbClasses = TW.Facets[ty][attTitle].invIdx.length
let attNbNodes = currentNbNodes
if (attNbClasses) { if (attNbClasses) {
let lastClass = TW.Facets[ty][attTitle].invIdx[attNbClasses-1] let lastClass = TW.Facets[ty][attTitle].invIdx[attNbClasses-1]
if (lastClass.labl && /^_non_numeric_/.test(lastClass.labl) && lastClass.nids) { if (lastClass.labl && /^_non_numeric_/.test(lastClass.labl) && lastClass.nids) {
if (lastClass.nids.length) { if (lastClass.nids.length) {
attNbNodes -= lastClass.nids.length attNbNodes -= lastClass.nids.length
} }
else { else {
attNbClasses -= 1 attNbClasses -= 1
}
} }
} }
}
// coloring function // note any previous louvains
let colMethod = getColorFunction(attTitle) if (attTitle == 'clust_louvain') gotPreviousLouvain = true
// family label :) // save relevant info
var attLabel ; colorsMeta[attTitle].push({
if (TW.facetOptions[attTitle] && TW.facetOptions[attTitle]['legend']) { 'type': ty,
attLabel = TW.facetOptions[attTitle]['legend'] 'nbDomain': attNbNodes,
'nbOutput': attNbClasses
})
}
}
console.log(colorsMeta)
// sorted by type and how many types (one type x by alpha, one type y by alpha, two types xy by alpha)
let colorsList = Object.keys(colorsMeta)
colorsList.sort(function (a, b) {
let cmp = colorsMeta[a].length - colorsMeta[b].length
if (cmp == 0) {
cmp = (a in TW.sigmaAttributes) - (b in TW.sigmaAttributes)
if (cmp == 0) {
if (colorsMeta[a][0].type < colorsMeta[b][0].type) cmp = -1
else if (colorsMeta[a][0].type > colorsMeta[b][0].type) cmp = 1
else {
if (a < b) cmp = -1
else if (a > b) cmp = 1
} }
else attLabel = attTitle }
}
return cmp
})
// 2nd loop: create colormenu and 1st default entry
var color_menu_info = '<li><a href="#" onclick="graphResetAllColors() ; TW.partialGraph.refresh()">By Default</a></li>';
let lastGroup = null
if( $( "#colorgraph-menu" ).length>0 ) {
for (var l in colorsList) {
var attTitle = colorsList[l]
color_menu_info += `<li><a href="#" onclick='${colMethod}("${attTitle}","${ty}")'>By ${attLabel} (${attNbClasses} | ${attNbNodes})</a></li>` // which concerned types and how many concerned nodes and output classes
let attNbNodes = 0
let forTypes = []
for (var i in colorsMeta[attTitle]) {
forTypes.push(colorsMeta[attTitle][i].type)
attNbNodes += colorsMeta[attTitle][i].nbDomain
} }
let attNbClasses = colorsMeta[attTitle][0].nbOutput
// POSS add cumulated degree via TW.partialGraph.graph.degree(nid) // coloring function
let colMethod = getColorFunction(attTitle)
// family label :)
var attLabel ;
if (TW.facetOptions[attTitle] && TW.facetOptions[attTitle]['legend']) {
attLabel = TW.facetOptions[attTitle]['legend']
}
else attLabel = attTitle
if (actypes.length == 1) {
color_menu_info += `
<li><a href="#" onclick='${colMethod}("${attTitle}")'>
By ${attLabel} (${attNbClasses} | ${attNbNodes})
</a></li>
`
}
else {
groupName = `${forTypes}`
if (groupName != lastGroup) {
color_menu_info += `<li class="pseudo-optgroup">${groupName}</li>`
}
color_menu_info += `
<li><a href="#" onclick='${colMethod}("${attTitle}",${JSON.stringify(forTypes)})'>
By ${attLabel} (${attNbClasses} | ${attNbNodes})
</a></li>
`
lastGroup = groupName
}
} }
// we also add clust_louvain if not already there // we also add clust_louvain if not already there
...@@ -132,7 +196,6 @@ function changeGraphAppearanceByFacets(actypes) { ...@@ -132,7 +196,6 @@ function changeGraphAppearanceByFacets(actypes) {
} }
// Legend slots were prepared in TW.Facets // Legend slots were prepared in TW.Facets
} }
function getColorFunction(attTitle) { function getColorFunction(attTitle) {
...@@ -291,7 +354,7 @@ function graphResetAllColors() { ...@@ -291,7 +354,7 @@ function graphResetAllColors() {
// removes selectively for an array of nodetypes // removes selectively for an array of nodetypes
function clearColorLegend (forTypes) { function clearColorLegend (forTypes) {
console.log('clearColorLegend', forTypes) // console.log('clearColorLegend', forTypes)
for (var ty of forTypes) { for (var ty of forTypes) {
let legTy = document.getElementById("legend-for-"+ty) let legTy = document.getElementById("legend-for-"+ty)
if (legTy) if (legTy)
......
...@@ -655,14 +655,16 @@ function edgeInfos(anEdge) { ...@@ -655,14 +655,16 @@ function edgeInfos(anEdge) {
// FIXME this function could be optimized // FIXME this function could be optimized
function gradientColoring(daclass) { function gradientColoring(daclass, forTypes) {
graphResetLabelsAndSizes() // full loop graphResetLabelsAndSizes() // full loop
// strategy on multiple types: color all types that have the attr if (typeof forTypes != 'array' || ! forTypes.length) {
let forTypes = getActivetypesNames().filter(function (ty){ // default strategy on multiple types: color all types that have the attr
return daclass in TW.Facets[ty] forTypes = getActivetypesNames().filter(function(ty){
}) return daclass in TW.Facets[ty]
})
}
// value getter // value getter
let getVal let getVal
...@@ -865,7 +867,7 @@ function repaintEdges() { ...@@ -865,7 +867,7 @@ function repaintEdges() {
// (good for values centered around a neutral zone) // (good for values centered around a neutral zone)
// NB - binning is done at parseCustom (cf. TW.Facets) // NB - binning is done at parseCustom (cf. TW.Facets)
// - number of bins can be specified by attribute name in TW.facetOptions[daclass]["n"] // - number of bins can be specified by attribute name in TW.facetOptions[daclass]["n"]
function heatmapColoring(daclass) { function heatmapColoring(daclass, forTypes) {
var binColors var binColors
var doModifyLabel = false var doModifyLabel = false
...@@ -885,12 +887,15 @@ function heatmapColoring(daclass) { ...@@ -885,12 +887,15 @@ function heatmapColoring(daclass) {
} }
} }
// strategy on multiple types: color all types that have the attr if (typeof forTypes != 'array' || ! forTypes.length) {
let forTypes = getActivetypesNames().filter(function (ty){ // default strategy on multiple types: color all types that have the attr
return daclass in TW.Facets[ty] forTypes = getActivetypesNames().filter(function(ty){
}) return daclass in TW.Facets[ty]
})
}
for (var k in forTypes) { for (var k in forTypes) {
var ty = forTypes[k] var ty = forTypes[k]
// global flag // global flag
...@@ -904,7 +909,7 @@ function heatmapColoring(daclass) { ...@@ -904,7 +909,7 @@ function heatmapColoring(daclass) {
// verifications // verifications
if (tickThresholds.length - 1 != nColors) { if (tickThresholds.length - 1 != nColors) {
console.warn (`heatmapColoring setup mismatch: TW.Facets ticks ${tickThresholds.length} - 1 non_numeric from scanAttributes should == nColors ${nColors}`) console.log (`heatmapColoring setup mismatch: TW.Facets ticks ${tickThresholds.length} - 1 non_numeric from scanAttributes should == nColors ${nColors}`)
nColors = tickThresholds.length - 1 nColors = tickThresholds.length - 1
} }
...@@ -959,13 +964,16 @@ function heatmapColoring(daclass) { ...@@ -959,13 +964,16 @@ function heatmapColoring(daclass) {
} }
function clusterColoring(daclass) { function clusterColoring(daclass, forTypes) {
graphResetLabelsAndSizes() // full loop graphResetLabelsAndSizes() // full loop (could be avoided most times if flag in sstate)
let forTypes = getActivetypesNames().filter(function (ty){ if (typeof forTypes != 'array' || ! forTypes.length) {
return daclass in TW.Facets[ty] // default strategy on multiple types: color all types that have the attr
}) forTypes = getActivetypesNames().filter(function(ty){
return daclass in TW.Facets[ty]
})
}
// louvain needs preparation // louvain needs preparation
if(daclass=="clust_louvain") { if(daclass=="clust_louvain") {
......
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