Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
clinicaltrials
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
david Chavalarias
clinicaltrials
Commits
e5d1e4ec
Commit
e5d1e4ec
authored
7 years ago
by
Romain Loth
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP bi colors in bipa cases
parent
ce9b46c4
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
355 additions
and
278 deletions
+355
-278
explorerjs.html
explorerjs.html
+5
-5
settings_explorerjs.js
settings_explorerjs.js
+3
-3
selection-panels-mobile.css
twlibs/css/selection-panels-mobile.css
+9
-6
selection-panels.css
twlibs/css/selection-panels.css
+29
-18
enviroment.js
twmain/enviroment.js
+3
-3
extras_explorerjs.js
twmain/extras_explorerjs.js
+116
-100
globalUtils.js
twmain/globalUtils.js
+4
-2
methods.js
twmain/methods.js
+2
-2
sigma.parseCustom.js
twmain/sigma.parseCustom.js
+2
-2
sigmaUtils.js
twmain/sigmaUtils.js
+179
-134
settings_explorerjs.comex.js
twpresets/settings_explorerjs.comex.js
+2
-2
settings_explorerjs.devdefault.js
twpresets/settings_explorerjs.devdefault.js
+1
-1
No files found.
explorerjs.html
View file @
e5d1e4ec
...
...
@@ -159,8 +159,8 @@
<li>
<a>
<select id="aselector" onchange="console.log('salut monde')" class="selectpicker" data-style="btn btn-success btn-sm" data-width="auto">
<option value="
Document
" selected>Scholars</option>
<option value="
NGram
">Keywords</option>
<option value="
Scholars
" selected>Scholars</option>
<option value="
Keywords
">Keywords</option>
</select>
</a>
</li>
...
...
@@ -430,9 +430,9 @@
</div>
<!-- /row -->
</div>
<!-- class="my-legend" (absolute position bottom left
) -->
<div
id=
"legend-for-
cluster
s"
class=
"over-panels"
></div>
<!-- attributes' legends (absolute position bottom left)
(contains one div of class "my-legend" per colored nodetype
) -->
<div
id=
"legend-for-
facet
s"
class=
"over-panels"
></div>
<!-- to reopen the panel -->
<div
id=
"sideunfold"
>
...
...
This diff is collapsed.
Click to expand it.
settings_explorerjs.js
View file @
e5d1e4ec
...
...
@@ -21,7 +21,7 @@ TW.conf = (function(TW){
// ...or remote bridge to default source api ajax queries
TWConf
.
sourceAPI
=
{}
TWConf
.
sourceAPI
[
"nodetypes"
]
=
{
"node0"
:
"
NGram"
,
"node1"
:
"Document
"
}
TWConf
.
sourceAPI
[
"nodetypes"
]
=
{
"node0"
:
"
Keywords"
,
"node1"
:
"Scholars
"
}
TWConf
.
sourceAPI
[
"forNormalQuery"
]
=
"services/api/graph"
TWConf
.
sourceAPI
[
"forFilteredQuery"
]
=
"services/api/graph"
...
...
@@ -114,8 +114,8 @@ TW.conf = (function(TW){
// =============
// Node typology: categories (resp. 0 and 1) will get these default labels
TWConf
.
catSem
=
"
NGram
"
;
TWConf
.
catSoc
=
"
Document
"
;
TWConf
.
catSem
=
"
Keywords
"
;
TWConf
.
catSoc
=
"
Scholars
"
;
// NB: these labels may be superseded by:
// - the input data's node types values cf. sortNodeTypes()
// - in servermenu mode, by the node0 & node1 properties
...
...
This diff is collapsed.
Click to expand it.
twlibs/css/selection-panels-mobile.css
View file @
e5d1e4ec
...
...
@@ -49,8 +49,8 @@
}
/* legend re-positioned */
.my-legend
{
bottom
:
calc
(
40%
-
10
5
px
);
#legend-for-facets
{
bottom
:
calc
(
40%
-
10
0
px
);
/* bot just above #sidebar which has top at calc(105px + 60%); */
}
...
...
@@ -97,17 +97,20 @@
}
/* legend reduction */
#legend-for-facets
{
max-width
:
25%
;
}
.my-legend
{
max-width
:
27%
;
max-height
:
25%
;
padding
:
0
2px
;
font-size
:
85%
;
margin
:
0
0
5px
0
;
margin
:
0
;
padding
:
0
1px
3px
1px
;
}
.my-legend
.legend-title
{
margin-bottom
:
0
;
font-size
:
90
%
;
font-size
:
85
%
;
}
.my-legend
.legend-scale
ul
{
margin-bottom
:
0
;
...
...
This diff is collapsed.
Click to expand it.
twlibs/css/selection-panels.css
View file @
e5d1e4ec
...
...
@@ -33,44 +33,55 @@
}
/* LEGEND PANEL */
#legend-for-facets
{
bottom
:
10px
;
left
:
0
;
position
:
fixed
;
/* width: we set it a bit more than #lefttopbox width */
max-width
:
20%
;
max-height
:
40%
;
font-size
:
120%
;
cursor
:
default
;
overflow-y
:
auto
;
overflow-x
:
hidden
;
}
.my-legend
{
position
:
fixed
;
/* width: we set it equal or smaller than #lefttopbox width */
max-width
:
20%
;
max-height
:
30%
;
padding
:
0
5px
;
overflow-y
:
scroll
;
bottom
:
18px
;
left
:
0
;
border
:
solid
1px
black
;
background-color
:
white
;
opacity
:
0.8
;
position
:
relative
;
height
:
100%
;
width
:
100%
;
margin
:
0
;
padding
:
0
5px
5px
5px
;
opacity
:
1
;
background-color
:
white
;
color
:
#250587
;
margin
:
7px
;
font-size
:
120%
;
cursor
:
default
;
overflow
:
hidden
;
z-index
:
5
;
}
.my-legend
.legend-title
{
text-align
:
left
;
margin-bottom
:
5px
;
font-weight
:
bold
;
font-size
:
90%
;
}
font-size
:
75%
;
}
.my-legend
.legend-scale
ul
{
margin
:
0
;
margin-bottom
:
5px
;
padding
:
0
;
float
:
left
;
list-style
:
none
;
}
}
.my-legend
.legend-scale
ul
li
{
font-size
:
80%
;
list-style
:
none
;
margin-left
:
0
;
line-height
:
16px
;
margin-bottom
:
2px
;
}
}
.my-legend
ul
.legend-labels
li
span
.lgdcol
{
display
:
block
;
float
:
left
;
...
...
This diff is collapsed.
Click to expand it.
twmain/enviroment.js
View file @
e5d1e4ec
...
...
@@ -23,8 +23,8 @@ TW.gui.checkBox=false;
TW
.
gui
.
shiftKey
=
false
;
TW
.
gui
.
foldedSide
=
false
;
TW
.
gui
.
manuallyChecked
=
false
;
TW
.
gui
.
handpickedcolor
=
false
;
// <= changes edge rendering strategy
TW
.
gui
.
lastFilters
=
{}
TW
.
gui
.
handpickedcolor
=
{};
// <= changes rendering, by nodetype
TW
.
gui
.
lastFilters
=
{}
// <= last values, by slider id
TW
.
gui
.
reldocTabs
=
[{},
{}]
// <= by nodetype and then dbtype
TW
.
gui
.
sizeRatios
=
[
1
,
1
]
// sizeRatios per nodetype
...
...
@@ -519,7 +519,7 @@ function changeType(optionaltypeFlag) {
// update the gui (POSS could be handled by TW.pushGUIState)
TW
.
gui
.
handpickedcolor
=
fals
e
TW
.
gui
.
handpickedcolor
=
{}
// <=> non
e
updateDynamicFacets
()
changeGraphAppearanceByFacets
(
getActivetypesNames
()
)
...
...
This diff is collapsed.
Click to expand it.
twmain/extras_explorerjs.js
View file @
e5d1e4ec
...
...
@@ -71,7 +71,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() ; TW.partialGraph.refresh()">By Default</a></li>'
;
var
color_menu_info
=
'<li><a href="#" onclick="TW.gui.handpickedcolor =
{}
; graphResetLabelsAndSizes() ; TW.partialGraph.refresh()">By Default</a></li>'
;
let
gotPreviousLouvain
=
false
if
(
$
(
"#colorgraph-menu"
).
length
>
0
)
{
...
...
@@ -130,7 +130,7 @@ function changeGraphAppearanceByFacets(actypes) {
}
else
attLabel
=
attTitle
color_menu_info
+=
`<li><a href="#" onclick='
${
colMethod
}
("
${
attTitle
}
")'>By
${
attLabel
}
(
${
attNbClasses
}
|
${
attNbNodes
}
)</a></li>`
color_menu_info
+=
`<li><a href="#" onclick='
${
colMethod
}
("
${
attTitle
}
"
,"
${
ty
}
"
)'>By
${
attLabel
}
(
${
attNbClasses
}
|
${
attNbNodes
}
)</a></li>`
}
// POSS add cumulated degree via TW.partialGraph.graph.degree(nid)
...
...
@@ -151,8 +151,8 @@ function changeGraphAppearanceByFacets(actypes) {
}
function
RunLouvain
()
{
// @cb: optional callback
function
RunLouvain
(
cb
)
{
var
node_realdata
=
[]
var
nodesV
=
getVisibleNodes
()
...
...
@@ -216,6 +216,11 @@ function RunLouvain() {
TW
.
facetOptions
[
'clust_louvain'
]
=
{
'col'
:
'cluster'
}
}
// NB the LouvainFait flag is updated by caller fun
// callback
if
(
cb
&&
typeof
cb
==
'function'
)
{
cb
()
}
}
...
...
@@ -269,139 +274,150 @@ function graphResetLabelsAndSizes(){
n
.
size
=
TW
.
Nodes
[
n
.
id
].
size
}
}
set_ClustersLegend
()
}
// @daclass: the name of a numeric/categorical attribute from node.attributes
// @forTypes: optional array of which typenames are concerned
// @groupingTicks: an optional threshold's array expressing ranges with their low/up bounds label and ref to matchin nodeIds
function
set_ClustersLegend
(
daclass
,
groupedByTicks
)
{
$
(
"#legend-for-clusters"
).
removeClass
(
"my-legend"
)
$
(
"#legend-for-clusters"
).
html
(
""
)
if
(
daclass
==
null
)
return
;
var
actypes
=
getActivetypesNames
()
// TODO test more for multiple types
// we have no specifications yet for colors (and legends) on multiple types
if
(
actypes
.
length
>
1
)
{
console
.
warn
(
"colors by bins will only color nodes of type 0"
)
function
set_ClustersLegend
(
daclass
,
forTypes
,
groupedByTicks
)
{
// shortcut to erase legends for all types
if
(
daclass
==
null
)
{
$
(
"#legend-for-facets"
).
html
(
""
)
};
// current display among TW.categories (ex: ['terms'])
if
(
typeof
forTypes
!=
'array'
||
!
forTypes
.
length
)
{
forTypes
=
getActivetypesNames
().
filter
(
function
(
ty
){
return
daclass
in
TW
.
Facets
[
ty
]
})
}
// current display among TW.categories (ex: 'terms')
var
curType
=
actypes
[
0
]
// all infos in a bin array
var
legendInfo
=
[]
for
(
var
k
in
forTypes
)
{
let
curType
=
forTypes
[
k
]
var
LegendDiv
=
"<div id=legend-for-"
+
curType
+
" class=
\"
over-panels my-legend
\"
>"
// sample node color
var
ClustNB_CurrentColor
=
{}
// all infos in a bin array
var
legendInfo
=
[]
// passed as arg or prepared in parseCustom
if
(
!
groupedByTicks
&&
(
!
TW
.
Facets
[
curType
]
||
!
TW
.
Facets
[
curType
][
daclass
]))
{
console
.
warn
(
`no class bins for
${
daclass
}
, displaying no legend`
)
// sample node color
var
ClustNB_CurrentColor
=
{}
$
(
"#legend-for-clusters"
).
hide
()
}
else
{
let
daclassLabel
=
daclass
if
(
TW
.
facetOptions
&&
TW
.
facetOptions
[
daclass
]
&&
TW
.
facetOptions
[
daclass
].
legend
)
{
daclassLabel
=
TW
.
facetOptions
[
daclass
].
legend
// passed as arg or prepared in parseCustom
if
(
!
groupedByTicks
&&
(
!
TW
.
Facets
[
curType
]
||
!
TW
.
Facets
[
curType
][
daclass
]))
{
console
.
warn
(
`no class bins for
${
curType
}
${
daclass
}
`
)
}
var
LegendDiv
=
""
LegendDiv
+=
` <div class="legend-title">
${
daclassLabel
}
</div>`
LegendDiv
+=
' <div class="legend-scale">'
LegendDiv
+=
' <ul class="legend-labels">'
else
{
let
daclassLabel
=
daclass
if
(
TW
.
facetOptions
&&
TW
.
facetOptions
[
daclass
]
&&
TW
.
facetOptions
[
daclass
].
legend
)
{
daclassLabel
=
TW
.
facetOptions
[
daclass
].
legend
}
var
legendInfo
=
groupedByTicks
||
TW
.
Facets
[
curType
][
daclass
].
invIdx
LegendDiv
+=
` <div class="legend-title">
${
curType
}
:
${
daclassLabel
}
</div>`
LegendDiv
+=
' <div class="legend-scale">'
LegendDiv
+=
' <ul class="legend-labels">'
// valueclasses (values or intervals or classes) are already sorted in TW.Facets
for
(
var
l
in
legendInfo
)
{
var
nMatchedNodes
=
legendInfo
[
l
][
'nids'
].
length
var
legendInfo
=
groupedByTicks
||
TW
.
Facets
[
curType
][
daclass
].
invIdx
// get a sample node color for each bin/class
let
theColor
=
legendInfo
[
l
].
col
||
"#777"
// grey if empty
// valueclasses (values or intervals or classes) are already sorted in TW.Facets
for
(
var
l
in
legendInfo
)
{
var
nMatchedNodes
=
legendInfo
[
l
][
'nids'
].
length
// create the legend item
var
preparedLabel
=
legendInfo
[
l
][
'labl'
]
// get a sample node color for each bin/class
let
theColor
=
legendInfo
[
l
].
col
||
"#777"
// grey if empty
if
(
/^_non_numeric_/
.
test
(
preparedLabel
))
{
if
(
!
nMatchedNodes
)
{
continue
// we skip "trash" category if empty
}
else
{
preparedLabel
=
"not numeric"
// create the legend item
var
preparedLabel
=
legendInfo
[
l
][
'labl'
]
if
(
/^_non_numeric_/
.
test
(
preparedLabel
))
{
if
(
!
nMatchedNodes
)
{
continue
// we skip "trash" category if empty
}
else
{
preparedLabel
=
"not numeric"
}
}
}
// we add a title to cluster classes by ranking their nodes and taking k best labels, except if type is "social"
if
(
TW
.
facetOptions
[
daclass
]
&&
TW
.
facetOptions
[
daclass
].
col
==
'cluster'
&&
curType
!=
TW
.
categories
[
1
])
{
// we add a title to cluster classes by ranking their nodes and taking k best labels, except if type is "social"
if
(
TW
.
facetOptions
[
daclass
]
&&
TW
.
facetOptions
[
daclass
].
col
==
'cluster'
&&
curType
!=
TW
.
categories
[
1
])
{
// let t0 = performance.now()
// let t0 = performance.now()
let
titles
=
[]
let
theRankingAttr
=
TW
.
facetOptions
[
daclass
].
titlingMetric
let
maxLen
=
TW
.
facetOptions
[
daclass
].
titlingNTerms
||
2
let
titles
=
[]
let
theRankingAttr
=
TW
.
facetOptions
[
daclass
].
titlingMetric
let
maxLen
=
TW
.
facetOptions
[
daclass
].
titlingNTerms
||
2
// custom accessor (sigma auto attr or user settings or by default)
let
getVal
if
(
theRankingAttr
)
{
// one of the 3 sigma dynamic attributes 'degree', etc
if
(
theRankingAttr
in
TW
.
sigmaAttributes
)
{
getVal
=
TW
.
sigmaAttributes
[
theRankingAttr
](
TW
.
partialGraph
)
// custom accessor (sigma auto attr or user settings or by default)
let
getVal
if
(
theRankingAttr
)
{
// one of the 3 sigma dynamic attributes 'degree', etc
if
(
theRankingAttr
in
TW
.
sigmaAttributes
)
{
getVal
=
TW
.
sigmaAttributes
[
theRankingAttr
](
TW
.
partialGraph
)
}
// a user setting for a source data attribute
else
{
getVal
=
function
(
node
)
{
return
node
.
attributes
[
theRankingAttr
]}
}
}
//
a user setting for a source data attribut
e
//
default ranking: by siz
e
else
{
getVal
=
function
(
node
)
{
return
node
.
attributes
[
theRankingAttr
]
}
getVal
=
function
(
node
)
{
return
node
.
size
}
}
}
// default ranking: by size
else
{
getVal
=
function
(
node
)
{
return
node
.
size
}
}
for
(
let
j
in
legendInfo
[
l
][
'nids'
])
{
let
n
=
TW
.
partialGraph
.
graph
.
nodes
(
legendInfo
[
l
][
'nids'
][
j
])
for
(
let
j
in
legendInfo
[
l
][
'nids'
])
{
let
n
=
TW
.
partialGraph
.
graph
.
nodes
(
legendInfo
[
l
][
'nids'
][
j
])
let
theRankingVal
=
getVal
(
n
)
let
theRankingVal
=
getVal
(
n
)
if
(
titles
.
length
<
maxLen
)
{
titles
.
push
({
'key'
:
n
.
label
,
'val'
:
theRankingVal
})
}
else
{
// we keep titles sorted for this
let
lastMax
=
titles
.
slice
(
-
1
)[
0
].
val
if
(
theRankingVal
>
lastMax
)
{
if
(
titles
.
length
<
maxLen
)
{
titles
.
push
({
'key'
:
n
.
label
,
'val'
:
theRankingVal
})
}
else
{
// we keep titles sorted for this
let
lastMax
=
titles
.
slice
(
-
1
)[
0
].
val
if
(
theRankingVal
>
lastMax
)
{
titles
.
push
({
'key'
:
n
.
label
,
'val'
:
theRankingVal
})
}
}
titles
.
sort
(
function
(
a
,
b
)
{
return
b
.
val
-
a
.
val
})
titles
=
titles
.
slice
(
0
,
maxLen
)
}
titles
.
sort
(
function
(
a
,
b
)
{
return
b
.
val
-
a
.
val
})
titles
=
titles
.
slice
(
0
,
maxLen
)
}
// replacing the cluster numbers by those k best titles in the legend
preparedLabel
=
"["
+
titles
.
map
(
function
(
x
){
return
x
.
key
}).
join
(
' / '
)
+
"...]"
+
` (
${
nMatchedNodes
}
)`
// replacing the cluster numbers by those k best titles in the legend
preparedLabel
=
"["
+
titles
.
map
(
function
(
x
){
return
x
.
key
}).
join
(
' / '
)
+
"...]"
+
` (
${
nMatchedNodes
}
)`
// console.log("finding title perf", performance.now() - t0, titles)
}
//
console.log("finding title perf", performance.now() - t0, titles)
}
//
all-in-one argument for SomeEffect
var
valueclassId
=
`
${
curType
}
::
${
daclass
}
::
${
l
}
`
// all-in-one argument for SomeEffect
var
valueclassId
=
`
${
curType
}
::
${
daclass
}
::
${
l
}
`
var
colorBg
=
`<span class="lgdcol" style="background:
${
theColor
}
;"></span>`
var
colorBg
=
`<span class="lgdcol" style="background:
${
theColor
}
;"></span>`
LegendDiv
+=
`<li onclick='SomeEffect("
${
valueclassId
}
")'>`
LegendDiv
+=
colorBg
+
preparedLabel
LegendDiv
+=
"</li>
\n
"
}
LegendDiv
+=
' </ul>'
LegendDiv
+=
' </div>'
LegendDiv
+=
' </div>'
LegendDiv
+=
`<li onclick='SomeEffect("
${
valueclassId
}
")'>`
LegendDiv
+=
colorBg
+
preparedLabel
LegendDiv
+=
"</li>
\n
"
let
perhapsPreviousLegend
=
document
.
getElementById
(
"legend-for-"
+
curType
)
if
(
perhapsPreviousLegend
)
{
perhapsPreviousLegend
.
outerHTML
=
LegendDiv
}
else
{
let
newLegend
=
document
.
createElement
(
'div'
)
document
.
getElementById
(
"legend-for-facets"
).
appendChild
(
newLegend
)
newLegend
.
outerHTML
=
LegendDiv
}
}
LegendDiv
+=
' </ul>'
LegendDiv
+=
' </div>'
$
(
"#legend-for-clusters"
).
addClass
(
"my-legend"
);
$
(
"#legend-for-clusters"
).
html
(
LegendDiv
)
$
(
"#legend-for-clusters"
).
show
()
}
$
(
"#legend-for-facets"
).
show
()
}
// = = = = = = = = = = = [ / Clusters Plugin ] = = = = = = = = = = = //
...
...
This diff is collapsed.
Click to expand it.
twmain/globalUtils.js
View file @
e5d1e4ec
...
...
@@ -96,8 +96,10 @@ function isUndef(variable){
function
stringToSomeInt
(
anyString
)
{
let
charCodeSum
=
0
for
(
let
i
=
0
;
i
<
anyString
.
length
;
i
++
)
{
charCodeSum
+=
anyString
.
charCodeAt
(
i
)
if
(
anyString
&&
anyString
.
length
)
{
for
(
let
i
=
0
;
i
<
anyString
.
length
;
i
++
)
{
charCodeSum
+=
anyString
.
charCodeAt
(
i
)
}
}
return
charCodeSum
}
...
...
This diff is collapsed.
Click to expand it.
twmain/methods.js
View file @
e5d1e4ec
...
...
@@ -97,7 +97,7 @@ TW.resetGraph = function() {
// reset rendering gui flags
TW
.
gui
.
selectionActive
=
false
TW
.
gui
.
handpickedcolor
=
false
TW
.
gui
.
handpickedcolor
=
{}
// reset circle size and cursor
TW
.
gui
.
circleSize
=
0
...
...
@@ -734,7 +734,7 @@ function prepareNodesRenderingProperties(nodesDict) {
// default unselected color
defgrey_color
:
"rgba("
+
rgbStr
+
","
+
TW
.
conf
.
sigmaJsDrawingProperties
.
twNodesGreyOpacity
+
")"
,
// will be used for repainting (read when TW.gui.handpickedcolor flag)
// will be used for repainting (read when TW.gui.handpickedcolor flag
s
)
alt_color
:
null
,
altgrey_color
:
null
,
}
...
...
This diff is collapsed.
Click to expand it.
twmain/sigma.parseCustom.js
View file @
e5d1e4ec
...
...
@@ -211,8 +211,8 @@ function scanGexf(gexfContent) {
// ex: terms
// ex: ISItermsriskV2_140 & ISItermsriskV2_140
// optional arg optionalNodeConf should contain keys of the form:
// "node0": "
NGram
",
// "node1": "
Document
"
// "node0": "
Keywords
",
// "node1": "
Scholars
"
// etc.
// (it's read from project_conf.json)
function
sortNodeTypes
(
observedTypesDict
,
optionalNodeConf
)
{
...
...
This diff is collapsed.
Click to expand it.
twmain/sigmaUtils.js
View file @
e5d1e4ec
...
...
@@ -118,7 +118,7 @@ var SigmaUtils = function () {
context
.
beginPath
();
if
(
settings
(
'twSelectedColor'
)
==
"node"
)
context
.
fillStyle
=
TW
.
gui
.
handpickedcolor
?
node
.
customAttrs
.
alt_color
:
node
.
color
;
// node's
context
.
fillStyle
=
TW
.
gui
.
handpickedcolor
[
node
.
type
]
?
node
.
customAttrs
.
alt_color
:
node
.
color
;
// node's
else
context
.
fillStyle
=
"#fff"
;
// default
...
...
@@ -180,7 +180,6 @@ var SigmaUtils = function () {
var
color
,
size
,
prefix
=
settings
(
'prefix'
)
||
''
//debug
// console.warn("rendering edge", edge)
...
...
@@ -188,7 +187,7 @@ var SigmaUtils = function () {
// precomputed color with no opacity
// cf. sigmaTools.edgeRGB
var
baseRGB
=
TW
.
gui
.
handpickedc
olor
?
edge
.
customAttrs
.
alt_rgb
:
edge
.
customAttrs
.
rgb
var
baseRGB
=
edge
.
customAttrs
.
useAltC
olor
?
edge
.
customAttrs
.
alt_rgb
:
edge
.
customAttrs
.
rgb
if
(
edge
.
customAttrs
.
activeEdge
)
{
size
=
(
defSize
*
2
)
+
1
...
...
@@ -291,7 +290,7 @@ var SigmaUtils = function () {
// mode variants 1: if a coloringFunction is active
if
(
!
TW
.
gui
.
handpickedcolor
)
{
if
(
!
TW
.
gui
.
handpickedcolor
[
node
.
type
]
)
{
nodeColor
=
node
.
color
}
else
{
...
...
@@ -301,7 +300,6 @@ var SigmaUtils = function () {
// mode variants 2: if node is selected, highlighted or unselected
if
(
TW
.
gui
.
selectionActive
)
{
// the selected node(s)
if
(
node
.
customAttrs
.
active
)
{
// called by label+background overlay cf. "subcall"
...
...
@@ -317,7 +315,7 @@ var SigmaUtils = function () {
// passive nodes should blend in the grey of twEdgeGreyColor
// cf settings_explorerjs, defgrey_color and deselectNodes()
else
{
if
(
!
TW
.
gui
.
handpickedcolor
)
{
if
(
!
TW
.
gui
.
handpickedcolor
[
node
.
type
]
)
{
nodeColor
=
node
.
customAttrs
.
defgrey_color
}
else
{
...
...
@@ -656,11 +654,15 @@ function edgeInfos(anEdge) {
}
// FIXME this function could be optimized
function
gradientColoring
(
daclass
)
{
graphResetLabelsAndSizes
()
// full loop
TW
.
gui
.
handpickedcolor
=
true
// strategy on multiple types: color all types that have the attr
let
forTypes
=
getActivetypesNames
().
filter
(
function
(
ty
){
return
daclass
in
TW
.
Facets
[
ty
]
})
// value getter
let
getVal
...
...
@@ -672,18 +674,22 @@ function gradientColoring(daclass) {
}
var
min_pow
=
0
;
for
(
var
nid
in
TW
.
Nodes
)
{
var
the_node
=
TW
.
Nodes
[
nid
]
var
attval
=
getVal
(
the_node
);
for
(
var
k
in
forTypes
)
{
let
nids
=
TW
.
partialGraph
.
graph
.
getNodesByType
(
TW
.
catDict
[
forTypes
[
k
]]
)
for
(
var
j
in
nids
)
{
let
attval
=
getVal
(
TW
.
Nodes
[
nids
[
j
]
]);
if
(
!
isNaN
(
parseFloat
(
attval
))
)
{
//is float
while
(
true
)
{
var
themult
=
Math
.
pow
(
10
,
min_pow
);
if
(
parseFloat
(
attval
)
==
0.0
)
break
;
if
(
(
parseFloat
(
attval
)
*
themult
)
<
1.0
)
{
min_pow
++
;
}
else
break
;
}
while
(
true
)
{
var
themult
=
Math
.
pow
(
10
,
min_pow
);
if
(
parseFloat
(
attval
)
==
0.0
)
break
;
if
(
(
parseFloat
(
attval
)
*
themult
)
<
1.0
)
{
min_pow
++
;
}
else
break
;
}
}
}
}
var
NodeID_Val
=
{}
...
...
@@ -692,9 +698,13 @@ function gradientColoring(daclass) {
var
themult
=
Math
.
pow
(
10
,
min_pow
);
// console.log('themult', themult)
for
(
var
nid
in
TW
.
Nodes
)
{
var
the_node
=
TW
.
Nodes
[
nid
]
var
attval
=
getVal
(
the_node
)
for
(
var
k
in
forTypes
)
{
let
nids
=
TW
.
partialGraph
.
graph
.
getNodesByType
(
TW
.
catDict
[
forTypes
[
k
]]
// unordered type names to type id
)
for
(
var
j
in
nids
)
{
let
nid
=
nids
[
j
]
var
attval
=
getVal
(
TW
.
Nodes
[
nid
])
var
attnumber
=
Number
(
attval
);
if
(
isNaN
(
attnumber
))
{
...
...
@@ -707,6 +717,7 @@ function gradientColoring(daclass) {
if
(
round_number
<
real_min
)
real_min
=
round_number
;
if
(
round_number
>
real_max
)
real_max
=
round_number
;
}
}
// console.log("NodeID_Val", NodeID_Val)
...
...
@@ -718,14 +729,21 @@ function gradientColoring(daclass) {
// console.log("the mult: "+themult)
// console.log(" - - - - - - - - -- - - ")
// [ Scaling node colours(0-255) and sizes(2-7) ]
var
Min_color
=
0
;
var
Max_color
=
255
;
var
Min_size
=
1
;
var
Max_size
=
8
;
var
setSize
=
(
TW
.
facetOptions
[
daclass
]
&&
TW
.
facetOptions
[
daclass
].
setsize
)
for
(
var
nid
in
NodeID_Val
)
{
var
newval_color
=
Math
.
round
(
(
Min_color
+
(
NodeID_Val
[
nid
][
"round"
]
-
real_min
)
*
((
Max_color
-
Min_color
)
/
(
real_max
-
real_min
))
)
);
var
newval_color
// special case: all nodes have the same size
if
(
real_min
==
real_max
)
{
newval_color
=
0
}
else
{
newval_color
=
Math
.
round
(
(
Min_color
+
(
NodeID_Val
[
nid
][
"round"
]
-
real_min
)
*
((
Max_color
-
Min_color
)
/
(
real_max
-
real_min
))
)
);
}
var
hex_color
=
rgbToHex
(
255
,
(
255
-
newval_color
)
,
0
)
let
n
=
TW
.
partialGraph
.
graph
.
nodes
(
nid
)
...
...
@@ -736,7 +754,7 @@ function gradientColoring(daclass) {
n
.
customAttrs
.
altgrey_color
=
"rgba("
+
(
hex2rgba
(
hex_color
).
slice
(
0
,
3
).
join
(
','
))
+
",0.4)"
// optionally changing size
if
(
TW
.
facetOptions
[
daclass
]
&&
TW
.
facetOptions
[
daclass
].
sets
ize
)
{
if
(
setS
ize
)
{
var
newval_size
=
Math
.
round
(
(
Min_size
+
(
NodeID_Val
[
nid
][
"round"
]
-
real_min
)
*
((
Max_size
-
Min_size
)
/
(
real_max
-
real_min
))
)
);
n
.
size
=
newval_size
;
}
...
...
@@ -752,36 +770,40 @@ function gradientColoring(daclass) {
// Edge precompute alt_rgb by new source-target nodes-colours combination
repaintEdges
()
// remember in clusters
let
bins
=
TW
.
Facets
[
getActivetypesNames
()[
0
]][
daclass
]
if
(
bins
&&
bins
.
invIdx
)
{
for
(
var
i
in
bins
.
invIdx
)
{
if
(
bins
.
invIdx
[
i
].
labl
!=
'_non_numeric_'
)
{
let
nidList
=
bins
.
invIdx
[
i
][
'nids'
]
if
(
nidList
.
length
)
{
// we take first non null exemplar from last in the range
// (possible skip due to changeLevel or filters)
for
(
var
k
=
nidList
.
length
-
1
;
k
>=
0
;
k
--
)
{
let
nd
=
TW
.
partialGraph
.
graph
.
nodes
(
nidList
[
k
])
if
(
nd
)
{
bins
.
invIdx
[
i
].
col
=
nd
.
customAttrs
.
alt_color
break
// remember in clusters of each requested type
for
(
var
k
in
forTypes
)
{
let
ty
=
forTypes
[
k
]
TW
.
gui
.
handpickedcolor
[
ty
]
=
true
let
bins
=
TW
.
Facets
[
ty
][
daclass
]
if
(
bins
&&
bins
.
invIdx
)
{
for
(
var
i
in
bins
.
invIdx
)
{
if
(
bins
.
invIdx
[
i
].
labl
!=
'_non_numeric_'
)
{
let
nidList
=
bins
.
invIdx
[
i
][
'nids'
]
if
(
nidList
.
length
)
{
// we take first non null exemplar from last in the range
// (possible skip due to changeLevel or filters)
for
(
var
k
=
nidList
.
length
-
1
;
k
>=
0
;
k
--
)
{
let
nd
=
TW
.
partialGraph
.
graph
.
nodes
(
nidList
[
k
])
if
(
nd
)
{
bins
.
invIdx
[
i
].
col
=
nd
.
customAttrs
.
alt_color
break
}
}
}
else
{
bins
.
invIdx
[
i
].
col
=
"#777"
// empty bin
}
}
else
{
bins
.
invIdx
[
i
].
col
=
"#
777"
// empty
bin
bins
.
invIdx
[
i
].
col
=
"#
bbb"
// non numeric values
bin
}
}
else
{
bins
.
invIdx
[
i
].
col
=
"#bbb"
// non numeric values bin
}
}
}
// NB legend will group different possible values using
// precomputed ticks from TW.Facets
.terms
[daclass]
set_ClustersLegend
(
daclas
s
)
// precomputed ticks from TW.Facets
[type]
[daclass]
set_ClustersLegend
(
daclass
,
forType
s
)
TW
.
partialGraph
.
render
();
}
...
...
@@ -808,15 +830,27 @@ function repaintEdges() {
if
(
src
&&
tgt
)
{
let
src_color
let
tgt_color
if
(
TW
.
gui
.
handpickedcolor
)
{
// handpickedcolor on multiple types may or may not affect
// a given edge so we need the useAltColor individual flag
let
useAlt
=
false
if
(
TW
.
gui
.
handpickedcolor
[
src
.
type
])
{
src_color
=
src
.
customAttrs
.
alt_color
||
'#555'
tgt_color
=
tgt
.
customAttrs
.
alt_color
||
'#555'
useAlt
=
true
}
else
{
else
src_color
=
src
.
color
||
'#555'
tgt_color
=
tgt
.
color
||
'#555'
if
(
TW
.
gui
.
handpickedcolor
[
tgt
.
type
])
{
tgt_color
=
tgt
.
customAttrs
.
alt_color
||
'#555'
useAlt
=
true
}
else
tgt_color
=
tgt
.
color
||
'#555'
e
.
customAttrs
.
alt_rgb
=
sigmaTools
.
edgeRGB
(
src_color
,
tgt_color
)
e
.
customAttrs
.
useAltColor
=
useAlt
// we don't set e.color because opacity may vary if selected or not
}
}
...
...
@@ -833,7 +867,9 @@ function repaintEdges() {
function
heatmapColoring
(
daclass
)
{
var
binColors
var
doModifyLabel
=
false
var
actypes
=
getActivetypesNames
()
// let's go
graphResetLabelsAndSizes
()
// full loop
// default value
let
nColors
=
TW
.
conf
.
legendsBins
||
5
...
...
@@ -848,73 +884,72 @@ function heatmapColoring(daclass) {
}
}
// we have no specifications yet for colors and legends on multiple types
if
(
actypes
.
length
>
1
)
{
console
.
warn
(
"colors by bins will only color nodes of type 0"
)
}
var
ty
=
actypes
[
0
]
// strategy on multiple types: color all types that have the attr
let
forTypes
=
getActivetypesNames
().
filter
(
function
(
ty
){
return
daclass
in
TW
.
Facets
[
ty
]
})
// our binning
var
tickThresholds
=
TW
.
Facets
[
ty
][
daclass
].
invIdx
for
(
var
k
in
forTypes
)
{
var
ty
=
forTypes
[
k
]
// verifications
if
(
tickThresholds
.
length
-
1
!=
nColors
)
{
console
.
warn
(
`heatmapColoring setup mismatch: TW.Facets ticks
${
tickThresholds
.
length
}
- 1 non_numeric from scanAttributes should == nColors
${
nColors
}
`
)
nColors
=
tickThresholds
.
length
-
1
}
// global flag
TW
.
gui
.
handpickedcolor
[
ty
]
=
true
binColors
=
getHeatmapColors
(
nColors
)
// our binning
var
tickThresholds
=
TW
.
Facets
[
ty
][
daclass
].
invIdx
// let's go
graphResetLabelsAndSizes
()
// full loop
// verifications
if
(
tickThresholds
.
length
-
1
!=
nColors
)
{
console
.
warn
(
`heatmapColoring setup mismatch: TW.Facets ticks
${
tickThresholds
.
length
}
- 1 non_numeric from scanAttributes should == nColors
${
nColors
}
`
)
nColors
=
tickThresholds
.
length
-
1
}
// global flag
TW
.
gui
.
handpickedcolor
=
true
binColors
=
getHeatmapColors
(
nColors
)
// use our valueclass => ids mapping
for
(
var
k
in
tickThresholds
)
{
// use our valueclass => ids mapping
for
(
var
k
in
tickThresholds
)
{
// console.debug('tick infos', tickThresholds[k])
// ex: {labl: "terms||growth_rate||[0 ; 0.583]", nids: Array(99), range: [0 ; 0.583210]}
// console.debug('tick infos', tickThresholds[k])
// ex: {labl: "terms||growth_rate||[0 ; 0.583]", nids: Array(99), range: [0 ; 0.583210]}
let
theColor
let
theColor
// skip grouped NaN values case => grey
if
(
tickThresholds
[
k
].
labl
==
'_non_numeric_'
)
{
theColor
=
'#bbb'
}
else
{
theColor
=
binColors
[
k
]
}
// skip grouped NaN values case => grey
if
(
tickThresholds
[
k
].
labl
==
'_non_numeric_'
)
{
theColor
=
'#bbb'
}
else
{
theColor
=
binColors
[
k
]
}
if
(
tickThresholds
[
k
].
nids
.
length
)
{
let
rgbColStr
=
hex2rgba
(
binColors
[
k
]).
slice
(
0
,
3
).
join
(
','
)
if
(
tickThresholds
[
k
].
nids
.
length
)
{
let
rgbColStr
=
hex2rgba
(
binColors
[
k
]).
slice
(
0
,
3
).
join
(
','
)
// color the referred nodes
for
(
var
j
in
tickThresholds
[
k
].
nids
)
{
let
n
=
TW
.
partialGraph
.
graph
.
nodes
(
tickThresholds
[
k
].
nids
[
j
])
if
(
n
)
{
n
.
customAttrs
.
alt_color
=
binColors
[
k
]
n
.
customAttrs
.
altgrey_color
=
"rgba("
+
rgbColStr
+
",0.4)"
// color the referred nodes
for
(
var
j
in
tickThresholds
[
k
].
nids
)
{
let
n
=
TW
.
partialGraph
.
graph
.
nodes
(
tickThresholds
[
k
].
nids
[
j
])
if
(
n
)
{
n
.
customAttrs
.
alt_color
=
binColors
[
k
]
n
.
customAttrs
.
altgrey_color
=
"rgba("
+
rgbColStr
+
",0.4)"
var
originalLabel
=
TW
.
Nodes
[
n
.
id
].
label
if
(
doModifyLabel
)
{
var
valSt
=
n
.
attributes
[
daclass
]
n
.
label
=
`(
${
valSt
}
)
${
originalLabel
}
`
var
originalLabel
=
TW
.
Nodes
[
n
.
id
].
label
if
(
doModifyLabel
)
{
var
valSt
=
n
.
attributes
[
daclass
]
n
.
label
=
`(
${
valSt
}
)
${
originalLabel
}
`
}
}
}
}
}
// remember
tickThresholds
[
k
].
col
=
theColor
// remember
tickThresholds
[
k
].
col
=
theColor
}
}
// Edge precompute alt_rgb by new source-target nodes-colours combination
repaintEdges
()
set_ClustersLegend
(
daclass
)
set_ClustersLegend
(
daclass
,
forTypes
)
TW
.
partialGraph
.
render
();
}
...
...
@@ -924,18 +959,25 @@ function clusterColoring(daclass) {
graphResetLabelsAndSizes
()
// full loop
let
forTypes
=
getActivetypesNames
().
filter
(
function
(
ty
){
return
daclass
in
TW
.
Facets
[
ty
]
})
// louvain needs preparation
if
(
daclass
==
"clust_louvain"
)
{
if
(
!
TW
.
SystemState
().
LouvainFait
)
{
try
{
RunLouvain
()
TW
.
SystemState
().
LouvainFait
=
true
RunLouvain
(
function
()
{
TW
.
SystemState
().
LouvainFait
=
true
clusterColoring
(
"clust_louvain"
)
})
}
catch
(
e
)
{
TW
.
SystemState
().
LouvainFait
=
false
console
.
warn
(
"skipped error on louvain, falling back to default colors"
)
daclass
==
'clust_default'
}
return
}
}
...
...
@@ -949,10 +991,9 @@ function clusterColoring(daclass) {
}
// reset the global state
TW
.
gui
.
handpickedcolor
=
false
TW
.
gui
.
handpickedcolor
=
{}
}
else
{
let
colList
=
[]
if
(
TW
.
conf
.
randomizeClusterColors
)
{
// shuffle on entire array is better than random sorting function on each element
...
...
@@ -964,47 +1005,51 @@ function clusterColoring(daclass) {
let
nColors
=
TW
.
gui
.
colorList
.
length
for
(
var
k
in
forTypes
)
{
let
typeName
=
forTypes
[
k
]
let
facets
=
TW
.
Facets
[
typeName
][
daclass
]
let
facets
=
TW
.
Facets
[
getActivetypesNames
()[
0
]][
daclass
]
if
(
facets
&&
facets
.
invIdx
)
{
for
(
var
i
in
facets
.
invIdx
)
{
let
valGroup
=
facets
.
invIdx
[
i
]
let
theColor
if
(
valGroup
.
labl
==
"_non_numeric_"
)
{
theColor
==
'#bbb'
}
else
{
let
val
=
valGroup
.
val
||
valGroup
.
range
// use the int as an index between 0 and nColors
if
(
parseInt
(
val
)
==
val
)
{
theColor
=
colList
[
val
%
nColors
]
if
(
facets
&&
facets
.
invIdx
)
{
for
(
var
i
in
facets
.
invIdx
)
{
let
valGroup
=
facets
.
invIdx
[
i
]
let
theColor
if
(
valGroup
.
labl
==
"_non_numeric_"
)
{
theColor
==
'#bbb'
}
// or create a representative int on the same range
else
{
let
someRepresentativeInt
=
stringToSomeInt
(
val
)
%
nColors
theColor
=
colList
[
someRepresentativeInt
]
let
val
=
valGroup
.
val
||
valGroup
.
range
// use the int as an index between 0 and nColors
if
(
parseInt
(
val
)
==
val
)
{
theColor
=
colList
[
val
%
nColors
]
}
// or create a representative int on the same range
else
{
let
someRepresentativeInt
=
stringToSomeInt
(
val
)
%
nColors
theColor
=
colList
[
someRepresentativeInt
]
}
}
}
if
(
valGroup
.
nids
.
length
)
{
let
rgbColStr
=
hex2rgba
(
theColor
).
slice
(
0
,
3
).
join
(
','
)
for
(
let
j
in
valGroup
.
nids
)
{
let
theNode
=
TW
.
partialGraph
.
graph
.
nodes
(
valGroup
.
nids
[
j
])
if
(
theNode
)
{
theNode
.
customAttrs
.
alt_color
=
theColor
theNode
.
customAttrs
.
altgrey_color
=
"rgba("
+
rgbColStr
+
",0.4)"
if
(
valGroup
.
nids
.
length
)
{
let
rgbColStr
=
hex2rgba
(
theColor
).
slice
(
0
,
3
).
join
(
','
)
for
(
let
j
in
valGroup
.
nids
)
{
let
theNode
=
TW
.
partialGraph
.
graph
.
nodes
(
valGroup
.
nids
[
j
])
if
(
theNode
)
{
theNode
.
customAttrs
.
alt_color
=
theColor
theNode
.
customAttrs
.
altgrey_color
=
"rgba("
+
rgbColStr
+
",0.4)"
}
}
}
}
// remember in TW.Facets
valGroup
.
col
=
theColor
// remember in TW.Facets
valGroup
.
col
=
theColor
}
}
}
// fallback on old, slower strategy if scanAttributes inactive
else
{
for
(
var
nid
in
TW
.
Nodes
)
{
var
the_node
=
TW
.
partialGraph
.
graph
.
nodes
(
nid
)
// fallback on old, slower strategy if scanAttributes inactive
else
{
let
nids
=
TW
.
partialGraph
.
graph
.
getNodesByType
(
TW
.
catDict
[
typeName
])
for
(
var
j
in
nids
)
{
let
nid
=
nids
[
j
]
let
the_node
=
TW
.
partialGraph
.
graph
.
nodes
(
nid
)
if
(
the_node
)
{
...
...
@@ -1031,17 +1076,17 @@ function clusterColoring(daclass) {
the_node
.
customAttrs
.
altgrey_color
=
"rgba("
+
(
hex2rgba
(
theColor
).
slice
(
0
,
3
).
join
(
','
))
+
",0.4)"
}
}
}
}
// set the global state
TW
.
gui
.
handpickedcolor
[
typeName
]
=
true
}
// set the global state
TW
.
gui
.
handpickedcolor
=
true
}
// Edge precompute alt_rgb by new source-target nodes-colours combination
repaintEdges
()
set_ClustersLegend
(
daclass
)
set_ClustersLegend
(
daclass
,
forTypes
)
TW
.
partialGraph
.
render
();
}
...
...
This diff is collapsed.
Click to expand it.
twpresets/settings_explorerjs.comex.js
View file @
e5d1e4ec
...
...
@@ -21,7 +21,7 @@ TW.conf = (function(TW){
// ...or remote bridge to default source api ajax queries
TWConf
.
sourceAPI
=
{}
TWConf
.
sourceAPI
[
"nodetypes"
]
=
{
"node0"
:
"
NGram"
,
"node1"
:
"Document
"
}
TWConf
.
sourceAPI
[
"nodetypes"
]
=
{
"node0"
:
"
Keywords"
,
"node1"
:
"Scholars
"
}
TWConf
.
sourceAPI
[
"forNormalQuery"
]
=
"services/api/graph"
TWConf
.
sourceAPI
[
"forFilteredQuery"
]
=
"services/api/graph"
...
...
@@ -59,7 +59,7 @@ TW.conf = (function(TW){
TWConf
.
scanAttributes
=
true
// use a facet for default color
TWConf
.
defaultColoring
=
"clust_louvain"
TWConf
.
defaultColoring
=
null
// facetOptions: choose here the default visual result of your node attributes
// ---------------------------------------------------------------------------
...
...
This diff is collapsed.
Click to expand it.
twpresets/settings_explorerjs.devdefault.js
View file @
e5d1e4ec
...
...
@@ -21,7 +21,7 @@ TW.conf = (function(TW){
// ...or remote bridge to default source api ajax queries
TWConf
.
sourceAPI
=
{}
TWConf
.
sourceAPI
[
"nodetypes"
]
=
{
"node0"
:
"
NGram"
,
"node1"
:
"Document
"
}
TWConf
.
sourceAPI
[
"nodetypes"
]
=
{
"node0"
:
"
Keywords"
,
"node1"
:
"Scholars
"
}
TWConf
.
sourceAPI
[
"forNormalQuery"
]
=
"services/api/graph"
TWConf
.
sourceAPI
[
"forFilteredQuery"
]
=
"services/api/graph"
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment