2 Module : Gargantext.Viz.Phylo.Tools
3 Description : Phylomemy Tools to build/manage it
4 Copyright : (c) CNRS, 2017-Present
5 License : AGPL + CECILL v3
6 Maintainer : team@gargantext.org
7 Stability : experimental
13 {-# LANGUAGE NoImplicitPrelude #-}
14 {-# LANGUAGE FlexibleContexts #-}
15 {-# LANGUAGE OverloadedStrings #-}
17 module Gargantext.Viz.Phylo.Tools
20 import Control.Lens hiding (both, Level)
21 import Data.List (filter, intersect, (++), sort, null, head, tail, last)
24 import Data.Text (Text)
25 import Data.Tuple.Extra
26 import Data.Vector (Vector,elemIndex)
27 import Gargantext.Prelude hiding (head)
28 import Gargantext.Viz.Phylo
30 import qualified Data.List as List
31 import qualified Data.Map as Map
32 import qualified Data.Set as Set
35 ------------------------------------------------------------------------
39 -- | To add a PhyloLevel at the end of a list of PhyloLevels
40 addPhyloLevel :: PhyloLevel -> [PhyloLevel] -> [PhyloLevel]
41 addPhyloLevel lvl l = l ++ [lvl]
44 -- | To alter each list of PhyloGroups following a given function
45 alterPhyloGroups :: ([PhyloGroup] -> [PhyloGroup]) -> Phylo -> Phylo
46 alterPhyloGroups f p = over ( phylo_periods
54 -- | To alter each PhyloPeriod of a Phylo following a given function
55 alterPhyloPeriods :: (PhyloPeriod -> PhyloPeriod) -> Phylo -> Phylo
56 alterPhyloPeriods f p = over ( phylo_periods
60 -- | To alter a list of PhyloLevels following a given function
61 alterPhyloLevels :: ([PhyloLevel] -> [PhyloLevel]) -> Phylo -> Phylo
62 alterPhyloLevels f p = over ( phylo_periods
64 . phylo_periodLevels) f p
67 -- | To append a list of PhyloPeriod to a Phylo
68 appendPhyloPeriods :: [PhyloPeriod] -> Phylo -> Phylo
69 appendPhyloPeriods l p = over (phylo_periods) (++ l) p
72 -- | Does a List of Sets contains at least one Set of an other List
73 doesAnySetContains :: Eq a => Set a -> [Set a] -> [Set a] -> Bool
74 doesAnySetContains h l l' = any (\c -> doesContains (Set.toList c) (Set.toList h)) (l' ++ l)
77 -- | Does a list of A contains an other list of A
78 doesContains :: Eq a => [a] -> [a] -> Bool
81 | length l' > length l = False
82 | elem (head l') l = doesContains l (tail l')
86 -- | Does a list of ordered A contains an other list of ordered A
87 doesContainsOrd :: Eq a => Ord a => [a] -> [a] -> Bool
90 | last l < head l' = False
91 | head l' `elem` l = True
92 | otherwise = doesContainsOrd l (tail l')
95 -- | To filter the PhyloGroup of a Phylo according to a function and a value
96 filterGroups :: Eq a => (PhyloGroup -> a) -> a -> Phylo -> [PhyloGroup]
97 filterGroups f x p = filter (\g -> (f g) == x) (getGroups p)
100 -- | To filter nested Sets of a
101 filterNestedSets :: Eq a => Set a -> [Set a] -> [Set a] -> [Set a]
102 filterNestedSets h l l'
103 | null l = if doesAnySetContains h l l'
106 | doesAnySetContains h l l' = filterNestedSets (head l) (tail l) l'
107 | otherwise = filterNestedSets (head l) (tail l) (h : l')
110 -- | To get the id of a PhyloGroup
111 getGroupId :: PhyloGroup -> PhyloGroupId
112 getGroupId = _phylo_groupId
115 -- | To get the level out of the id of a PhyloGroup
116 getGroupLevel :: PhyloGroup -> Int
117 getGroupLevel = snd . fst . getGroupId
120 -- | To get the Ngrams of a PhyloGroup
121 getGroupNgrams :: PhyloGroup -> [Int]
122 getGroupNgrams = _phylo_groupNgrams
125 -- | To get the period out of the id of a PhyloGroup
126 getGroupPeriod :: PhyloGroup -> (Date,Date)
127 getGroupPeriod = fst . fst . getGroupId
130 -- | To get all the PhyloGroup of a Phylo
131 getGroups :: Phylo -> [PhyloGroup]
132 getGroups = view ( phylo_periods
140 -- | To get all the PhyloGroup of a Phylo with a given level and period
141 getGroupsWithFilters :: Int -> (Date,Date) -> Phylo -> [PhyloGroup]
142 getGroupsWithFilters lvl prd p = (filterGroups getGroupLevel lvl p)
144 (filterGroups getGroupPeriod prd p)
147 -- | To get the index of an element of a Vector
148 getIdx :: Eq a => a -> Vector a -> Int
149 getIdx x v = case (elemIndex x v) of
150 Nothing -> panic "[ERR][Viz.Phylo.Tools.getIndex] Nothing"
154 -- | To get the label of a Level
155 getLevelLabel :: Level -> LevelLabel
156 getLevelLabel lvl = _levelLabel lvl
159 -- | To get the value of a Level
160 getLevelValue :: Level -> Int
161 getLevelValue lvl = _levelValue lvl
164 -- | To get the label of a LevelLink based on a Direction
165 getLevelLinkLabel :: Direction -> LevelLink -> LevelLabel
166 getLevelLinkLabel dir link = case dir of
167 From -> view (levelFrom . levelLabel) link
168 To -> view (levelTo . levelLabel) link
169 _ -> panic "[ERR][Viz.Phylo.Tools.getLevelLinkLabel] Wrong direction"
172 -- | To get the value of a LevelLink based on a Direction
173 getLevelLinkValue :: Direction -> LevelLink -> Int
174 getLevelLinkValue dir link = case dir of
175 From -> view (levelFrom . levelValue) link
176 To -> view (levelTo . levelValue) link
177 _ -> panic "[ERR][Viz.Phylo.Tools.getLevelLinkValue] Wrong direction"
180 -- | To get all the Phylolevels of a given PhyloPeriod
181 getPhyloLevels :: PhyloPeriod -> [PhyloLevel]
182 getPhyloLevels = view (phylo_periodLevels)
185 -- | To get the Ngrams of a Phylo
186 getPhyloNgrams :: Phylo -> PhyloNgrams
187 getPhyloNgrams = _phylo_ngrams
190 -- | To create a PhyloGroup in a Phylo out of a list of Ngrams and a set of parameters
191 initGroup :: [Ngrams] -> Text -> Int -> Int -> Int -> Int -> Phylo -> PhyloGroup
192 initGroup ngrams lbl idx lvl from to p = PhyloGroup
193 (((from, to), lvl), idx)
195 (sort $ map (\x -> ngramsToIdx x p) ngrams)
200 -- | To create a Level
201 initLevel :: Int -> LevelLabel -> Level
202 initLevel lvl lbl = Level lbl lvl
205 -- | To create a LevelLink
206 initLevelLink :: Level -> Level -> LevelLink
207 initLevelLink lvl lvl' = LevelLink lvl lvl'
210 -- | To create a PhyloLevel
211 initPhyloLevel :: PhyloLevelId -> [PhyloGroup] -> PhyloLevel
212 initPhyloLevel id groups = PhyloLevel id groups
215 -- | To create a PhyloPeriod
216 initPhyloPeriod :: PhyloPeriodId -> [PhyloLevel] -> PhyloPeriod
217 initPhyloPeriod id l = PhyloPeriod id l
220 -- | To transform an Ngrams into its corresponding index in a Phylo
221 ngramsToIdx :: Ngrams -> Phylo -> Int
222 ngramsToIdx x p = getIdx x (_phylo_ngrams p)
225 -- | To set the LevelId of a PhyloLevel and of all its PhyloGroups
226 setPhyloLevelId :: Int -> PhyloLevel -> PhyloLevel
227 setPhyloLevelId lvl' (PhyloLevel (id, lvl) groups)
228 = PhyloLevel (id, lvl') groups'
230 groups' = over (traverse . phylo_groupId) (\((period, lvl), idx) -> ((period, lvl'), idx)) groups
233 -- | To choose a LevelLink strategy based an a given Level
234 shouldLink :: LevelLink -> [Int] -> [Int] -> Bool
236 | from <= 1 = doesContainsOrd l l'
237 | from > 1 = undefined
238 | otherwise = panic ("[ERR][Viz.Phylo.Tools.shouldLink] LevelLink not defined")
240 --------------------------------------
242 from = getLevelLinkValue From lvl
243 --------------------------------------