Commit 72a3fee0 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[graph] noverlap first draft

parent 27895371
Pipeline #3535 canceled with stage
......@@ -29,6 +29,7 @@ import Gargantext.Config (defaultFrontends)
import Gargantext.Data.Louvain as Louvain
import Gargantext.Hooks.Session (useSession)
import Gargantext.Hooks.Sigmax.ForceAtlas2 as ForceAtlas
import Gargantext.Hooks.Sigmax.Noverlap as Noverlap
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Types as GT
......@@ -46,6 +47,7 @@ here = R2.here "Gargantext.Components.GraphExplorer.Layout"
type Props =
( fa2Ref :: R.Ref (Maybe ForceAtlas.FA2Layout)
, noverlapRef :: R.Ref (Maybe Noverlap.NoverlapLayout)
, sigmaRef :: R.Ref Sigmax.Sigma
)
......@@ -54,6 +56,7 @@ layout = R2.leaf layoutCpt
layoutCpt :: R.Component Props
layoutCpt = here.component "layout" cpt where
cpt { fa2Ref
, noverlapRef
, sigmaRef
} _ = do
-- | States
......@@ -191,6 +194,7 @@ layoutCpt = here.component "layout" cpt where
[
Controls.controls
{ fa2Ref
, noverlapRef
, reloadForest: reloadForest
, sigmaRef
}
......@@ -205,6 +209,7 @@ layoutCpt = here.component "layout" cpt where
graphView
{ elRef: graphRef
, fa2Ref
, noverlapRef
, sigmaRef
}
]
......@@ -215,6 +220,7 @@ layoutCpt = here.component "layout" cpt where
type GraphProps =
( elRef :: R.Ref (Nullable Element)
, fa2Ref :: R.Ref (Maybe ForceAtlas.FA2Layout)
, noverlapRef :: R.Ref (Maybe Noverlap.NoverlapLayout)
, sigmaRef :: R.Ref Sigmax.Sigma
)
......@@ -224,6 +230,7 @@ graphViewCpt :: R.Memo GraphProps
graphViewCpt = R.memo' $ here.component "graphView" cpt where
cpt { elRef
, fa2Ref
, noverlapRef
, sigmaRef
} _ = do
-- | States
......@@ -278,6 +285,7 @@ graphViewCpt = R.memo' $ here.component "graphView" cpt where
Graph.drawGraph
{ elRef
, fa2Ref
, noverlapRef
, forceAtlas2Settings: Graph.forceAtlas2Settings
, sigmaRef
, sigmaSettings: Graph.sigmaSettings
......
......@@ -27,6 +27,7 @@ import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Camera as Camera
import Gargantext.Hooks.Sigmax.Graphology as Graphology
import Gargantext.Hooks.Sigmax.ForceAtlas2 as ForceAtlas2
import Gargantext.Hooks.Sigmax.Noverlap as Noverlap
import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as SigmaxTypes
import Gargantext.Utils (getter)
......@@ -41,6 +42,7 @@ here = R2.here "Gargantext.Components.GraphExplorer.Resources"
type Props sigma forceatlas2 =
( elRef :: R.Ref (Nullable Element)
, fa2Ref :: R.Ref (Maybe ForceAtlas2.FA2Layout)
, noverlapRef :: R.Ref (Maybe Noverlap.NoverlapLayout)
, forceAtlas2Settings :: forceatlas2
, sigmaRef :: R.Ref Sigmax.Sigma
, sigmaSettings :: sigma
......@@ -57,6 +59,7 @@ drawGraphCpt = here.component "drawGraph" cpt where
-- |
cpt { elRef
, fa2Ref
, noverlapRef
, sigmaRef
, forceAtlas2Settings: fa2Settings
, transformedGraph
......@@ -157,7 +160,7 @@ drawGraphCpt = here.component "drawGraph" cpt where
fa2 <- ForceAtlas2.init (Sigma.graph sig) fa2Settings
ForceAtlas2.start fa2
R.setRef fa2Ref (Just fa2)
Just fa2 -> do
Just _fa2 -> do
-- TODO Kill and restart? Maybe check fa2.graph first? Should be equal to sigma.graph
pure unit
else
......@@ -165,6 +168,13 @@ drawGraphCpt = here.component "drawGraph" cpt where
Nothing -> pure unit
Just fa2 -> ForceAtlas2.stop fa2
case R.readRef noverlapRef of
Nothing -> do
noverlap <- Noverlap.init (Sigma.graph sig) {}
R.setRef noverlapRef (Just noverlap)
Just _noverlap -> do
pure unit
case mCamera of
Just cam -> do
Camera.updateCamera (Camera.camera sig) cam
......
......@@ -45,6 +45,7 @@ type Store =
, edgeConfluenceRange :: T.Box Range.NumberRange
, edgeWeight :: T.Box Range.NumberRange
, forceAtlasState :: T.Box SigmaxT.ForceAtlasState
, noverlapState :: T.Box SigmaxT.NoverlapState
, graphStage :: T.Box GET.Stage
, nodeSize :: T.Box Range.NumberRange
, nodeSizeRange :: T.Box Range.NumberRange
......@@ -78,6 +79,7 @@ type State =
, edgeConfluenceRange :: Range.NumberRange
, edgeWeight :: Range.NumberRange
, forceAtlasState :: SigmaxT.ForceAtlasState
, noverlapState :: SigmaxT.NoverlapState
, graphStage :: GET.Stage
, nodeSize :: Range.NumberRange
, nodeSizeRange :: Range.NumberRange
......
......@@ -4,6 +4,7 @@ module Gargantext.Components.GraphExplorer.Toolbar.Buttons
, edgesToggleButton
, louvainToggleButton
, pauseForceAtlasButton
, pauseNoverlapButton
, resetForceAtlasButton
, multiSelectEnabledButton
) where
......@@ -228,6 +229,45 @@ pauseForceAtlasButtonCpt = here.component "pauseForceAtlasButtonButton" cpt
{ name: icn state'}
]
type NoverlapButtonProps =
( state :: T.Box SigmaxTypes.NoverlapState
)
pauseNoverlapButton :: R2.Leaf NoverlapButtonProps
pauseNoverlapButton = R2.leaf pauseNoverlapButtonCpt
pauseNoverlapButtonCpt :: R.Component NoverlapButtonProps
pauseNoverlapButtonCpt = here.component "pauseNoverlapButton" cpt
where
cpt { state } _ = do
-- States
state' <- R2.useLive' state
-- Computed
let
vrt SigmaxTypes.NoverlapRunning = ButtonVariant Secondary
vrt _ = OutlinedButtonVariant Secondary
icn SigmaxTypes.NoverlapRunning = "object-ungroup"
icn SigmaxTypes.NoverlapPaused = "object-ungroup"
-- Render
pure $
B.button
{ variant: vrt state'
, className: intercalate " "
[ "toolbar-atlas-button"
]
, callback: \_ -> T.modify_ SigmaxTypes.toggleNoverlapState state
}
[
B.icon
{ name: icn state'}
]
--------------------------------------------------------
type ResetForceAtlasProps =
......
......@@ -11,11 +11,12 @@ import Effect.Timer (setTimeout)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.GraphExplorer.Resources as Graph
import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Toolbar.Buttons (centerButton, edgesToggleButton, louvainToggleButton, pauseForceAtlasButton, multiSelectEnabledButton)
import Gargantext.Components.GraphExplorer.Toolbar.Buttons (centerButton, edgesToggleButton, louvainToggleButton, pauseForceAtlasButton, pauseNoverlapButton, multiSelectEnabledButton)
import Gargantext.Components.GraphExplorer.Toolbar.RangeControl (edgeConfluenceControl, nodeSizeControl)
import Gargantext.Components.GraphExplorer.Toolbar.SlideButton (labelSizeButton, labelRenderedSizeThresholdButton, mouseSelectorSizeSlider)
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax.ForceAtlas2 as ForceAtlas
import Gargantext.Hooks.Sigmax.Noverlap as Noverlap
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Hooks.Sigmax.Types as SigmaxT
......@@ -31,6 +32,7 @@ here = R2.here "Gargantext.Components.GraphExplorer.Toolbar.Controls"
type Controls =
( fa2Ref :: R.Ref (Maybe ForceAtlas.FA2Layout)
, noverlapRef :: R.Ref (Maybe Noverlap.NoverlapLayout)
, reloadForest :: T2.ReloadS
, sigmaRef :: R.Ref Sigmax.Sigma
)
......@@ -40,6 +42,7 @@ controls = R2.leaf controlsCpt
controlsCpt :: R.Memo Controls
controlsCpt = R.memo' $ here.component "controls" cpt where
cpt { fa2Ref
, noverlapRef
-- , reloadForest
, sigmaRef
} _ = do
......@@ -49,6 +52,7 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
, edgeConfluenceRange
-- , edgeWeight
, forceAtlasState
, noverlapState
, graph
, graphStage
, labelRenderedSizeThreshold
......@@ -65,6 +69,7 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
} <- GraphStore.use
forceAtlasState' <- R2.useLive' forceAtlasState
noverlapState' <- R2.useLive' noverlapState
graphStage' <- R2.useLive' graphStage
selectedNodeIds' <- R2.useLive' selectedNodeIds
showSidebar' <- R2.useLive' showSidebar
......@@ -91,6 +96,17 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
-- Handle case when FA is paused from outside events, eg. the automatic timer.
R.useEffect' $ Sigmax.handleForceAtlas2Pause fa2Ref forceAtlasState mFAPauseRef Graph.forceAtlas2Settings
R.useEffect' do
here.log2 "[controls] noverlapState'" noverlapState'
case R.readRef noverlapRef of
Nothing -> pure unit
Just noverlap -> do
case noverlapState' of
SigmaxT.NoverlapRunning -> do
Noverlap.start noverlap
SigmaxT.NoverlapPaused -> do
Noverlap.stop noverlap
-- Handle automatic edge hiding when FA is running (to prevent flickering).
-- TODO Commented temporarily: this breaks forceatlas rendering after reset
-- NOTE This is a hack anyways. It's force atlas that should be fixed.
......@@ -151,6 +167,7 @@ controlsCpt = R.memo' $ here.component "controls" cpt where
[
-- resetForceAtlasButton { forceAtlasState, sigmaRef }
pauseForceAtlasButton { state: forceAtlasState }
, pauseNoverlapButton { state: noverlapState }
,
gap
{- ,
......
......@@ -22,6 +22,7 @@ import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Hooks.Loader (useLoaderEffect)
import Gargantext.Hooks.Session (useSession)
import Gargantext.Hooks.Sigmax.ForceAtlas2 as ForceAtlas
import Gargantext.Hooks.Sigmax.Noverlap as Noverlap
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Utils (getter)
......@@ -161,6 +162,7 @@ hydrateStoreCpt = here.component "hydrateStore" cpt where
sigmaRef <- Sigmax.initSigma >>= R.useRef
fa2Ref <- R.useRef (Nothing :: Maybe ForceAtlas.FA2Layout)
noverlapRef <- R.useRef (Nothing :: Maybe Noverlap.NoverlapLayout)
-- | Precompute some values
-- |
......@@ -195,6 +197,7 @@ hydrateStoreCpt = here.component "hydrateStore" cpt where
-- Controls
, startForceAtlas
, forceAtlasState
, noverlapState: SigmaxT.NoverlapPaused
, edgeWeight: Range.Closed
{ min: 0.0
, max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph
......@@ -217,5 +220,6 @@ hydrateStoreCpt = here.component "hydrateStore" cpt where
[
layout
{ fa2Ref
, noverlapRef
, sigmaRef }
]
'use strict';
// https://graphology.github.io/standard-library/layout-noverlap.htlm
import NoverlapLayout from 'graphology-layout-noverlap/worker';
export function _init(graph, options) {
return new NoverlapLayout(graph, {
maxIterations: 50000,
settings: {
gridSize: 5,
margin: 500,
expansion: 2.0,
ratio: 1.5
}
});
}
export function _start(layout) {
console.log('[noverlap] _start', layout);
return layout.start();
}
export function _stop(layout) {
console.log('[noverlap] _stop', layout);
return layout.stop();
}
export function _kill(layout) {
return layout.kill();
}
export function _isRunning(layout) {
return layout.isRunning();
}
module Gargantext.Hooks.Sigmax.Noverlap where
-- FFI for noverlap: https://graphology.github.io/standard-library/layout-noverlap.html
import Prelude
import Data.Array as A
import Data.Sequence as Seq
import Data.Set as Set
import Data.Traversable (traverse)
import Effect (Effect)
import Effect.Timer (setTimeout)
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, EffectFn4, runEffectFn1, runEffectFn2, runEffectFn3, runEffectFn4)
import FFI.Simple ((..), (...), (.=))
import Gargantext.Hooks.Sigmax.Graphology as Graphology
import Gargantext.Hooks.Sigmax.Types as Types
import Record as Record
-- | Type representing the web worker.
foreign import data NoverlapLayout :: Type
graph :: NoverlapLayout -> Graphology.Graph
graph s = s .. "graph" :: Graphology.Graph
foreign import _init :: forall settings. EffectFn2 Graphology.Graph settings NoverlapLayout
foreign import _start :: EffectFn1 NoverlapLayout Unit
foreign import _stop :: EffectFn1 NoverlapLayout Unit
foreign import _kill :: EffectFn1 NoverlapLayout Unit
foreign import _isRunning :: EffectFn1 NoverlapLayout Boolean
init :: forall settings. Graphology.Graph -> settings -> Effect NoverlapLayout
init = runEffectFn2 _init
start :: NoverlapLayout -> Effect Unit
start = runEffectFn1 _start
stop :: NoverlapLayout -> Effect Unit
stop = runEffectFn1 _stop
kill :: NoverlapLayout -> Effect Unit
kill = runEffectFn1 _kill
isRunning :: NoverlapLayout -> Effect Boolean
isRunning = runEffectFn1 _isRunning
......@@ -165,7 +165,6 @@ eqGraph (Graph {nodes: n1, edges: e1}) (Graph {nodes: n2, edges: e2}) = (n1 == n
-- seconds and then stops (unless the user alters this by clicking the toggle
-- button).
data ForceAtlasState = {- InitialLoading | -} InitialRunning | InitialStopped | Running | Paused | Killed
derive instance Generic ForceAtlasState _
instance Eq ForceAtlasState where
eq = genericEq
......@@ -187,6 +186,15 @@ forceAtlasComponentStatus Running = Disabled
forceAtlasComponentStatus Paused = Enabled
forceAtlasComponentStatus Killed = Enabled
data NoverlapState = NoverlapPaused | NoverlapRunning
derive instance Generic NoverlapState _
instance Eq NoverlapState where
eq = genericEq
toggleNoverlapState :: NoverlapState -> NoverlapState
toggleNoverlapState NoverlapRunning = NoverlapPaused
toggleNoverlapState NoverlapPaused = NoverlapRunning
-- | Custom state for show edges. Normally it is EShow or EHide (show/hide
-- | edges). However, edges are temporarily turned off when forceAtlas is
......
......@@ -5395,6 +5395,13 @@ graphology-layout-forceatlas2@^0.9.2:
dependencies:
graphology-utils "^2.1.0"
graphology-layout-noverlap@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/graphology-layout-noverlap/-/graphology-layout-noverlap-0.4.2.tgz#2ffa054ceeebaa31fcffe695d271fc55707cd29c"
integrity sha512-13WwZSx96zim6l1dfZONcqLh3oqyRcjIBsqz2c2iJ3ohgs3605IDWjldH41Gnhh462xGB1j6VGmuGhZ2FKISXA==
dependencies:
graphology-utils "^2.3.0"
graphology-operators@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/graphology-operators/-/graphology-operators-1.6.0.tgz#daad1600219ad47a3005504f252f80d9b402ad09"
......@@ -5402,15 +5409,15 @@ graphology-operators@^1.6.0:
dependencies:
graphology-utils "^2.0.0"
graphology-utils@^2.0.0, graphology-utils@^2.1.0, graphology-utils@^2.5.0:
graphology-utils@^2.0.0, graphology-utils@^2.1.0, graphology-utils@^2.3.0, graphology-utils@^2.5.0:
version "2.5.2"
resolved "https://registry.yarnpkg.com/graphology-utils/-/graphology-utils-2.5.2.tgz#4d30d6e567d27c01f105e1494af816742e8d2440"
integrity sha512-ckHg8MXrXJkOARk56ZaSCM1g1Wihe2d6iTmz1enGOz4W/l831MBCKSayeFQfowgF8wd+PQ4rlch/56Vs/VZLDQ==
graphology@^0.24.1:
version "0.24.1"
resolved "https://registry.yarnpkg.com/graphology/-/graphology-0.24.1.tgz#035e452e294b01168cf5c85d5dd0a4b7e4837d87"
integrity sha512-6lNz1PNTAe9Q6ioHKrXu0Lp047sgvOoHa4qmP/8mnJWCGv2iIZPQkuHPUb2/OWDWCqHpw2hKgJLJ55X/66xmHg==
graphology@^0.25.1:
version "0.25.1"
resolved "https://registry.yarnpkg.com/graphology/-/graphology-0.25.1.tgz#f92b86294782522d3898ce4480e4a577c0c2568a"
integrity sha512-yYA7BJCcXN2DrKNQQ9Qf22zBHm/yTbyBR71T1MYBbGtywNHsv0QZtk8zaR6zxNcp2hCCZayUkHp9DyMSZCpoxQ==
dependencies:
events "^3.3.0"
obliterator "^2.0.2"
......
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