{-| Module : Gargantext.Core.Viz.Graph.Utils Description : Copyright : (c) CNRS, 2017-Present License : AGPL + CECILL v3 Maintainer : team@gargantext.org Stability : experimental Portability : POSIX These functions are used for Vector.Matrix only. -} {-# LANGUAGE BangPatterns #-} {-# LANGUAGE Strict #-} module Gargantext.Core.Viz.Graph.Utils where import Data.List (unzip) import Data.Map.Strict (Map) import Data.Matrix hiding (identity) import Data.Maybe (catMaybes) import Data.Set (Set) import Data.Vector (Vector) import Gargantext.Core.Text.Metrics.Count (occurrencesWith) import Gargantext.Prelude import qualified Data.List as List import qualified Data.Map.Strict as Map import qualified Data.Set as Set import qualified Data.Vector as Vector ------------------------------------------------------------------------ -- | Some utils to build the matrix from cooccurrence results -- | For tests only, to be removed -- m1 :: Matrix Double -- m1 = fromList 300 300 [1..] ------------------------------------------------------------------------ ------------------------------------------------------------------------ data Axis = Col | Row ------------------------------------------------------------------------ -- | Matrix functions type AxisId = Int -- Data.Vector.Additions dropAt :: Int -> Vector a -> Vector a dropAt n v = debut <> (Vector.tail fin) where debut = Vector.take n v fin = Vector.drop n v total :: Num a => Matrix a -> a total m = Vector.sum $ Vector.map (\c -> Vector.sum (getCol c m)) (Vector.enumFromTo 1 (nOf Col m)) nOf :: Axis -> Matrix a -> Int nOf Row = nrows nOf Col = ncols axis :: Axis -> AxisId -> Matrix a -> Vector a axis Col = getCol axis Row = getRow toListsWithIndex :: Matrix a -> [((Int, Int), a)] toListsWithIndex m = concat' $ zip [1..] $ List.map (\c -> zip [1..] c) $ toLists m where concat' :: [(Int, [(Int, a)])] -> [((Int, Int), a)] concat' xs = List.concat $ List.map (\(x, ys) -> List.map (\(y, a) -> ((x,y), a)) ys ) xs ------------------------------------------------------------------------ -- Utils to manage Graphs edgesFilter :: (Ord a, Ord b) => Map (a,a) b -> Map (a,a) b edgesFilter m = Map.fromList $ catMaybes results where results = [ let ij = Map.lookup (i,j) m ji = Map.lookup (j,i) m in getMax (i,j) ij ji | i <- keys , j <- keys , i < j ] keys = Set.toList $ Set.fromList (x <> y) (x,y) = unzip $ Map.keys m nodesFilter :: (Show a, Show b, Ord a, Ord b, Num b) => (b -> Bool) -> Map (a,a) b -> (Map (a,a) b, Set a) nodesFilter f m = (m', toKeep) where m' = Map.filterWithKey (\(a,b) _ -> Set.member a toKeep && Set.member b toKeep) m toKeep = Set.fromList $ Map.keys $ Map.filter f $ occurrencesWith identity $ tupleConcat $ List.unzip $ Map.keys m tupleConcat :: ([a],[a]) -> [a] tupleConcat (a,b) = a <> b getMax :: Ord b => (a,a) -> Maybe b -> Maybe b -> Maybe ((a,a), b) getMax (i,j) (Just d) Nothing = Just ((i,j), d) getMax (i,j) Nothing (Just d) = Just ((j,i), d) getMax ij (Just di) (Just dj) = if di >= dj then getMax ij (Just di) Nothing else getMax ij Nothing (Just dj) getMax _ _ _ = Nothing