From 81c77cb9f2013b9cd5957eadbd26086c4ddeae56 Mon Sep 17 00:00:00 2001 From: Przemek Kaminski <pk@intrepidus.pl> Date: Wed, 12 Oct 2022 20:14:42 +0200 Subject: [PATCH] [utils] generic renormalization using lens --- .../Components/GraphExplorer/Utils.purs | 54 +++++++++++-------- src/Gargantext/Utils/Lens.purs | 26 +++++++++ 2 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 src/Gargantext/Utils/Lens.purs diff --git a/src/Gargantext/Components/GraphExplorer/Utils.purs b/src/Gargantext/Components/GraphExplorer/Utils.purs index 5ee91e07..94e3009f 100644 --- a/src/Gargantext/Components/GraphExplorer/Utils.purs +++ b/src/Gargantext/Components/GraphExplorer/Utils.purs @@ -8,6 +8,7 @@ import Gargantext.Prelude import Data.Array as A import Data.Foldable (maximum, minimum) +import Data.Lens (lens) import Data.Maybe (Maybe(..)) import Data.Newtype (wrap) import Data.Sequence as Seq @@ -15,6 +16,7 @@ import Gargantext.Components.GraphExplorer.GraphTypes as GEGT import Gargantext.Components.GraphExplorer.Types as GET import Gargantext.Hooks.Sigmax.Types as ST import Gargantext.Utils (getter) +import Gargantext.Utils.Lens as GUL import Gargantext.Utils.Seq as GUS stEdgeToGET :: Record ST.Edge -> GEGT.Edge @@ -34,31 +36,37 @@ stNodeToGET { id, label, x, y, _original: GEGT.Node { attributes, size, type_ } ----------------------------------------------------------------------- +-- | Normalize nodes, i.e. set their {x, y} values so that they are in +-- | range [0, 1]. normalizeNodes :: Seq.Seq GEGT.Node -> Seq.Seq GEGT.Node -normalizeNodes ns = Seq.map normalizeNode ns +normalizeNodes ns = GUL.normalizeLens xLens $ GUL.normalizeLens yLens ns where - xs = map (\(GEGT.Node { x }) -> x) ns - ys = map (\(GEGT.Node { y }) -> y) ns - mMinx = minimum xs - mMaxx = maximum xs - mMiny = minimum ys - mMaxy = maximum ys - mXrange = do - minx <- mMinx - maxx <- mMaxx - pure $ maxx - minx - mYrange = do - miny <- mMiny - maxy <- mMaxy - pure $ maxy - miny - xdivisor = case mXrange of - Nothing -> 1.0 - Just xdiv -> 1.0 / xdiv - ydivisor = case mYrange of - Nothing -> 1.0 - Just ydiv -> 1.0 / ydiv - normalizeNode (GEGT.Node n@{ x, y }) = GEGT.Node $ n { x = x * xdivisor - , y = y * ydivisor } + xLens = lens (\(GEGT.Node { x }) -> x) $ (\(GEGT.Node n) val -> GEGT.Node (n { x = val })) + yLens = lens (\(GEGT.Node { y }) -> y) $ (\(GEGT.Node n) val -> GEGT.Node (n { y = val })) +-- normalizeNodes ns = Seq.map normalizeNode ns +-- where +-- xs = map (\(GEGT.Node { x }) -> x) ns +-- ys = map (\(GEGT.Node { y }) -> y) ns +-- mMinx = minimum xs +-- mMaxx = maximum xs +-- mMiny = minimum ys +-- mMaxy = maximum ys +-- mXrange = do +-- minx <- mMinx +-- maxx <- mMaxx +-- pure $ maxx - minx +-- mYrange = do +-- miny <- mMiny +-- maxy <- mMaxy +-- pure $ maxy - miny +-- xdivisor = case mXrange of +-- Nothing -> 1.0 +-- Just xdiv -> 1.0 / xdiv +-- ydivisor = case mYrange of +-- Nothing -> 1.0 +-- Just ydiv -> 1.0 / ydiv +-- normalizeNode (GEGT.Node n@{ x, y }) = GEGT.Node $ n { x = x * xdivisor +-- , y = y * ydivisor } ------------------------------------------------------------------------ diff --git a/src/Gargantext/Utils/Lens.purs b/src/Gargantext/Utils/Lens.purs new file mode 100644 index 00000000..c8b85c02 --- /dev/null +++ b/src/Gargantext/Utils/Lens.purs @@ -0,0 +1,26 @@ +module Gargantext.Utils.Lens where + +import Gargantext.Prelude + +import Data.Foldable (maximum, minimum) +import Data.Maybe (Maybe(..)) +import Data.Lens +import Data.Traversable + +-- | Given a Traversable of entities and a lens for them, normalize +-- | over lens getter so that the value of lens setter is in range [0, +-- | 1]. +normalizeLens :: forall a t. Traversable t => Lens' a Number -> t a -> t a +normalizeLens l ns = over traversed normalize' ns + where + values = over traversed (_ ^. l) ns + vMin = minimum values + vMax = maximum values + vRange = do + minv <- vMin + maxv <- vMax + pure $ maxv - minv + divisor = case vRange of + Nothing -> 1.0 + Just d -> 1.0 / d + normalize' n = over l (_ * divisor) n -- 2.21.0