2 Module : Gargantext.Viz.Phylo.PhyloTools
3 Description : Module dedicated to all the tools needed for making a Phylo
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
11 {-# LANGUAGE FlexibleContexts #-}
12 {-# LANGUAGE NoImplicitPrelude #-}
13 {-# LANGUAGE OverloadedStrings #-}
14 {-# LANGUAGE RankNTypes #-}
15 {-# LANGUAGE ViewPatterns #-}
17 module Gargantext.Viz.Phylo.PhyloTools where
19 import Data.Vector (Vector, elemIndex)
20 import Data.List (sort, concat, null, union, (++), tails, sortOn, nub)
21 import Data.Set (Set, size)
22 import Data.Map (Map, elems, fromList, unionWith, keys, member, (!), filterWithKey)
23 import Data.String (String)
25 import Gargantext.Prelude
26 import Gargantext.Viz.AdaptativePhylo
28 import Debug.Trace (trace)
29 import Control.Lens hiding (Level)
31 import qualified Data.Vector as Vector
32 import qualified Data.List as List
33 import qualified Data.Set as Set
40 countSup :: Double -> [Double] -> Int
41 countSup s l = length $ filter (>s) l
44 elemIndex' :: Eq a => a -> [a] -> Int
45 elemIndex' e l = case (List.elemIndex e l) of
46 Nothing -> panic ("[ERR][Viz.Phylo.PhyloTools] element not in list")
55 -- | Is this Ngrams a Foundations Root ?
56 isRoots :: Ngrams -> Vector Ngrams -> Bool
57 isRoots n ns = Vector.elem n ns
59 -- | To transform a list of nrams into a list of foundation's index
60 ngramsToIdx :: [Ngrams] -> Vector Ngrams -> [Int]
61 ngramsToIdx ns fdt = map (\n -> fromJust $ elemIndex n fdt) ns
68 -- | To transform a list of periods into a set of Dates
69 periodsToYears :: [(Date,Date)] -> Set Date
70 periodsToYears periods = (Set.fromList . sort . concat)
71 $ map (\(d,d') -> [d..d']) periods
74 findBounds :: [Date] -> (Date,Date)
76 let dates' = sort dates
77 in (head' "findBounds" dates', last' "findBounds" dates')
80 toPeriods :: [Date] -> Int -> Int -> [(Date,Date)]
82 let (start,end) = findBounds dates
83 in map (\dates' -> (head' "toPeriods" dates', last' "toPeriods" dates'))
84 $ chunkAlong p s [start .. end]
87 -- | Get a regular & ascendante timeScale from a given list of dates
88 toTimeScale :: [Date] -> Int -> [Date]
89 toTimeScale dates step =
90 let (start,end) = findBounds dates
91 in [start, (start + step) .. end]
94 getTimeStep :: TimeUnit -> Int
95 getTimeStep time = case time of
98 getTimePeriod :: TimeUnit -> Int
99 getTimePeriod time = case time of
102 getTimeFrame :: TimeUnit -> Int
103 getTimeFrame time = case time of
111 -- | To find if l' is nested in l
112 isNested :: Eq a => [a] -> [a] -> Bool
115 | length l' > length l = False
116 | (union l l') == l = True
120 -- | To filter Fis with small Support but by keeping non empty Periods
121 keepFilled :: (Int -> [a] -> [a]) -> Int -> [a] -> [a]
122 keepFilled f thr l = if (null $ f thr l) && (not $ null l)
123 then keepFilled f (thr - 1) l
127 traceClique :: Map (Date, Date) [PhyloFis] -> String
128 traceClique mFis = foldl (\msg cpt -> msg <> show (countSup cpt cliques) <> " (>" <> show (cpt) <> ") " ) "" [1..6]
130 --------------------------------------
132 cliques = sort $ map (fromIntegral . size . _phyloFis_clique) $ concat $ elems mFis
133 --------------------------------------
136 traceSupport :: Map (Date, Date) [PhyloFis] -> String
137 traceSupport mFis = foldl (\msg cpt -> msg <> show (countSup cpt supports) <> " (>" <> show (cpt) <> ") " ) "" [1..6]
139 --------------------------------------
141 supports = sort $ map (fromIntegral . _phyloFis_support) $ concat $ elems mFis
142 --------------------------------------
145 traceFis :: [Char] -> Map (Date, Date) [PhyloFis] -> Map (Date, Date) [PhyloFis]
146 traceFis msg mFis = trace ( "\n" <> "-- | " <> msg <> " : " <> show (sum $ map length $ elems mFis) <> "\n"
147 <> "Support : " <> (traceSupport mFis) <> "\n"
148 <> "Clique : " <> (traceClique mFis) <> "\n" ) mFis
151 -------------------------
152 -- | Contextual unit | --
153 -------------------------
156 getFisSupport :: ContextualUnit -> Int
157 getFisSupport unit = case unit of
159 -- _ -> panic ("[ERR][Viz.Phylo.PhyloTools.getFisSupport] Only Fis has a support")
161 getFisSize :: ContextualUnit -> Int
162 getFisSize unit = case unit of
164 -- _ -> panic ("[ERR][Viz.Phylo.PhyloTools.getFisSupport] Only Fis has a clique size")
172 listToCombi' :: [a] -> [(a,a)]
173 listToCombi' l = [(x,y) | (x:rest) <- tails l, y <- rest]
175 listToEqual' :: Eq a => [a] -> [(a,a)]
176 listToEqual' l = [(x,y) | x <- l, y <- l, x == y]
178 listToKeys :: Eq a => [a] -> [(a,a)]
179 listToKeys lst = (listToCombi' lst) ++ (listToEqual' lst)
181 listToMatrix :: [Int] -> Map (Int,Int) Double
182 listToMatrix lst = fromList $ map (\k -> (k,1)) $ listToKeys $ sort lst
184 sumCooc :: Cooc -> Cooc -> Cooc
185 sumCooc cooc cooc' = unionWith (+) cooc cooc'
187 getTrace :: Cooc -> Double
188 getTrace cooc = sum $ elems $ filterWithKey (\(k,k') _ -> k == k') cooc
194 getGroupId :: PhyloGroup -> PhyloGroupId
195 getGroupId group = ((group ^. phylo_groupPeriod, group ^. phylo_groupLevel), group ^. phylo_groupIndex)
201 addPointers :: PhyloGroup -> Filiation -> PointerType -> [Pointer] -> PhyloGroup
202 addPointers group fil pty pointers =
204 TemporalPointer -> case fil of
205 ToChilds -> group & phylo_groupPeriodChilds %~ (++ pointers)
206 ToParents -> group & phylo_groupPeriodParents %~ (++ pointers)
207 LevelPointer -> case fil of
208 ToChilds -> group & phylo_groupLevelChilds %~ (++ pointers)
209 ToParents -> group & phylo_groupLevelParents %~ (++ pointers)
212 getPeriodIds :: Phylo -> [(Date,Date)]
213 getPeriodIds phylo = sortOn fst
215 $ phylo ^. phylo_periods
218 getConfig :: Phylo -> Config
219 getConfig phylo = (phylo ^. phylo_param) ^. phyloParam_config
222 getRoots :: Phylo -> Vector Ngrams
223 getRoots phylo = (phylo ^. phylo_foundations) ^. foundations_roots
226 getGroupsFromLevel :: Level -> Phylo -> [PhyloGroup]
227 getGroupsFromLevel lvl phylo =
228 elems $ view ( phylo_periods
232 . filtered (\phyloLvl -> phyloLvl ^. phylo_levelLevel == lvl)
233 . phylo_levelGroups ) phylo
236 updatePhyloGroups :: Level -> Map PhyloGroupId PhyloGroup -> Phylo -> Phylo
237 updatePhyloGroups lvl m phylo =
242 . filtered (\phyloLvl -> phyloLvl ^. phylo_levelLevel == lvl)
246 let id = getGroupId group
258 pointersToLinks :: PhyloGroupId -> [Pointer] -> [Link]
259 pointersToLinks id pointers = map (\p -> ((id,fst p),snd p)) pointers
266 getSensibility :: Proximity -> Double
267 getSensibility proxi = case proxi of
268 WeightedLogJaccard s _ _ -> s
271 getThresholdInit :: Proximity -> Double
272 getThresholdInit proxi = case proxi of
273 WeightedLogJaccard _ t _ -> t
276 getThresholdStep :: Proximity -> Double
277 getThresholdStep proxi = case proxi of
278 WeightedLogJaccard _ _ s -> s
286 ngramsInBranches :: [[PhyloGroup]] -> [Int]
287 ngramsInBranches branches = nub $ foldl (\acc g -> acc ++ (g ^. phylo_groupNgrams)) [] $ concat branches