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 FlexibleContexts #-}
14 {-# LANGUAGE NoImplicitPrelude #-}
15 {-# LANGUAGE OverloadedStrings #-}
16 {-# LANGUAGE RankNTypes #-}
17 {-# LANGUAGE ViewPatterns #-}
19 module Gargantext.Viz.Phylo.Tools
22 import Control.Lens hiding (both, Level, Empty)
23 import Data.List (filter, intersect, (++), sort, null, tail, last, tails, delete, nub, sortOn, nubBy, concat)
24 import Data.Maybe (mapMaybe,fromMaybe)
25 import Data.Map (Map, mapKeys, member, (!), restrictKeys, elems, empty, filterWithKey, unionWith)
27 import Data.Text (Text,toLower,unwords)
28 import Data.Tuple.Extra
29 import Data.Vector (Vector,elemIndex)
30 import Gargantext.Prelude
31 import Gargantext.Viz.Phylo
32 import qualified Data.Map as Map
33 import qualified Data.Set as Set
34 import qualified Data.Vector as Vector
42 -- | Define a default value
43 def :: a -> Maybe a -> a
47 -- | Does a List of Sets contains at least one Set of an other List
48 doesAnySetContains :: Eq a => Set a -> [Set a] -> [Set a] -> Bool
49 doesAnySetContains h l l' = any (\c -> doesContains (Set.toList c) (Set.toList h)) (l' ++ l)
52 -- | Does a list of A contains an other list of A
53 doesContains :: Eq a => [a] -> [a] -> Bool
56 | length l' > length l = False
57 | elem (head' "doesContains" l') l = doesContains l (tail l')
61 -- | Does a list of ordered A contains an other list of ordered A
62 doesContainsOrd :: Eq a => Ord a => [a] -> [a] -> Bool
65 | last l < (head' "doesContainsOrd" l') = False
66 | (head' "doesContainsOrd" l') `elem` l = True
67 | otherwise = doesContainsOrd l (tail l')
70 -- | To filter nested Sets of a
71 filterNestedSets :: Eq a => Set a -> [Set a] -> [Set a] -> [Set a]
72 filterNestedSets h l l'
73 | null l = if doesAnySetContains h l l'
76 | doesAnySetContains h l l' = filterNestedSets (head' "filterNestedSets1" l) (tail l) l'
77 | otherwise = filterNestedSets (head' "filterNestedSets2" l) (tail l) (h : l')
81 -- | To get the good pair of keys (x,y) or (y,x) in a given Map (a,b) c
82 getKeyPair :: (Int,Int) -> Map (Int,Int) a -> (Int,Int)
83 getKeyPair (x,y) m = case findPair (x,y) m of
84 Nothing -> panic "[ERR][Viz.Phylo.Example.getKeyPair] Nothing"
87 --------------------------------------
88 findPair :: (Int,Int) -> Map (Int,Int) a -> Maybe (Int,Int)
90 | member (x',y') m' = Just (x',y')
91 | member (y',x') m' = Just (y',x')
93 --------------------------------------
96 -- | To filter Fis with small Support but by keeping non empty Periods
97 keepFilled :: (Int -> [a] -> [a]) -> Int -> [a] -> [a]
98 keepFilled f thr l = if (null $ f thr l) && (not $ null l)
99 then keepFilled f (thr - 1) l
103 -- | To get all combinations of a list
104 listToFullCombi :: Eq a => [a] -> [(a,a)]
105 listToFullCombi l = [(x,y) | x <- l, y <- l]
108 -- | To get all combinations of a list
109 listToDirectedCombi :: Eq a => [a] -> [(a,a)]
110 listToDirectedCombi l = [(x,y) | x <- l, y <- l, x /= y]
113 listToEqualCombi :: Eq a => [a] -> [(a,a)]
114 listToEqualCombi l = [(x,y) | x <- l, y <- l, x == y]
116 listToPairs :: Eq a => [a] -> [(a,a)]
117 listToPairs l = (listToEqualCombi l) ++ (listToUnDirectedCombi l)
119 -- | To get all combinations of a list and apply a function to the resulting list of pairs
120 listToDirectedCombiWith :: Eq a => forall b. (a -> b) -> [a] -> [(b,b)]
121 listToDirectedCombiWith f l = [(f x,f y) | x <- l, y <- l, x /= y]
124 -- | To get the sequential combinations of an order list
125 listToSequentialCombi :: Eq a => [a] -> [(a,a)]
126 listToSequentialCombi l = nubBy (\x y -> fst x == fst y) $ listToUnDirectedCombi l
129 -- | To get all combinations of a list with no repetition
130 listToUnDirectedCombi :: [a] -> [(a,a)]
131 listToUnDirectedCombi l = [ (x,y) | (x:rest) <- tails l, y <- rest ]
134 -- | To get all combinations of a list with no repetition and apply a function to the resulting list of pairs
135 listToUnDirectedCombiWith :: forall a b. (a -> b) -> [a] -> [(b,b)]
136 listToUnDirectedCombiWith f l = [ (f x, f y) | (x:rest) <- tails l, y <- rest ]
139 -- | To transform a list of Ngrams Indexes into a Label
140 ngramsToLabel :: Vector Ngrams -> [Int] -> Text
141 ngramsToLabel ngrams l = unwords $ tail' "ngramsToLabel" $ concat $ map (\n -> ["|",n]) $ ngramsToText ngrams l
144 -- | To transform a list of Ngrams Indexes into a list of Text
145 ngramsToText :: Vector Ngrams -> [Int] -> [Text]
146 ngramsToText ngrams l = map (\idx -> ngrams Vector.! idx) l
149 -- | To transform a list of ngrams into a list of indexes
150 ngramsToIdx :: [Ngrams] -> Vector Ngrams -> [Int]
151 ngramsToIdx ns v = sort $ map (\n -> getIdxInVector n v) ns
154 -- | To unify the keys (x,y) that Map 1 share with Map 2 such as: (x,y) <=> (y,x)
155 unifySharedKeys :: Eq a => Ord a => Map (a,a) b -> Map (a,a) b -> Map (a,a) b
156 unifySharedKeys m1 m2 = mapKeys (\(x,y) -> if member (y,x) m2
165 -- | An analyzer ingests a Ngrams and generates a modified version of it
166 phyloAnalyzer :: Ngrams -> Ngrams
167 phyloAnalyzer n = toLower n
169 -- | To init the foundation roots of the Phylo as a Vector of Ngrams
170 initFoundationsRoots :: [Ngrams] -> Vector Ngrams
171 initFoundationsRoots l = Vector.fromList $ map phyloAnalyzer l
173 -- | To init the base of a Phylo from a List of Periods and Foundations
174 initPhyloBase :: [(Date, Date)] -> PhyloFoundations -> Map Date Double -> Map Date (Map (Int,Int) Double) -> Map (Date,Date) [PhyloFis] -> PhyloParam -> Phylo
175 initPhyloBase pds fds nbDocs cooc fis prm = Phylo ((fst . (head' "initPhyloBase")) pds, (snd . last) pds) fds (map (\pd -> initPhyloPeriod pd []) pds) nbDocs cooc fis prm
177 -- | To init the param of a Phylo
178 initPhyloParam :: Maybe Text -> Maybe Software -> Maybe PhyloQueryBuild -> PhyloParam
179 initPhyloParam (def defaultPhyloVersion -> v) (def defaultSoftware -> s) (def defaultQueryBuild -> q) = PhyloParam v s q
181 -- | To get the last computed Level in a Phylo
182 getLastLevel :: Phylo -> Level
183 getLastLevel p = (last . sort)
184 $ map (snd . getPhyloLevelId)
185 $ view ( phylo_periods
187 . phylo_periodLevels ) p
189 -- | To get all the coocurency matrix of a phylo
190 getPhyloCooc :: Phylo -> Map Date (Map (Int,Int) Double)
191 getPhyloCooc p = p ^. phylo_cooc
194 -- | To get the PhyloParam of a Phylo
195 getPhyloParams :: Phylo -> PhyloParam
196 getPhyloParams = _phylo_param
198 -- | To get the title of a Phylo
199 getPhyloTitle :: Phylo -> Text
200 getPhyloTitle p = _q_phyloTitle $ _phyloParam_query $ getPhyloParams p
202 -- | To get the desc of a Phylo
203 getPhyloDescription :: Phylo -> Text
204 getPhyloDescription p = _q_phyloTitle $ _phyloParam_query $ getPhyloParams p
206 getPhyloMatchingFrame :: Phylo -> Int
207 getPhyloMatchingFrame p = _q_interTemporalMatchingFrame $ _phyloParam_query $ getPhyloParams p
209 getPhyloMatchingFrameTh :: Phylo -> Double
210 getPhyloMatchingFrameTh p = _q_interTemporalMatchingFrameTh $ _phyloParam_query $ getPhyloParams p
212 getPhyloProximity :: Phylo -> Proximity
213 getPhyloProximity p = _q_interTemporalMatching $ _phyloParam_query $ getPhyloParams p
215 getPhyloReBranchThr :: Phylo -> Double
216 getPhyloReBranchThr p = _q_reBranchThr $ _phyloParam_query $ getPhyloParams p
218 getPhyloReBranchNth :: Phylo -> Int
219 getPhyloReBranchNth p = _q_reBranchNth $ _phyloParam_query $ getPhyloParams p
221 getPhyloFis :: Phylo -> Map (Date,Date) [PhyloFis]
222 getPhyloFis = _phylo_fis
229 -- | To get the foundations of a Phylo
230 getFoundations :: Phylo -> PhyloFoundations
231 getFoundations = _phylo_foundations
233 -- | To get the foundations roots of a Phylo
234 getFoundationsRoots :: Phylo -> Vector Ngrams
235 getFoundationsRoots p = (getFoundations p) ^. phylo_foundationsRoots
237 -- | To get the Index of a Ngrams in the foundationsRoots of a Phylo
238 getIdxInRoots :: Ngrams -> Phylo -> Int
239 getIdxInRoots n p = case (elemIndex n (getFoundationsRoots p)) of
240 Nothing -> panic $ "[ERR][Viz.Phylo.Tools.getIdxInRoots] Ngrams not in foundationsRoots: " <> cs n
243 getIdxInRoots' :: Ngrams -> Vector Ngrams -> Int
244 getIdxInRoots' n root = case (elemIndex n root) of
245 Nothing -> panic $ "[ERR][Viz.Phylo.Tools.getIdxInRoots] Ngrams not in foundationsRoots: " <> cs n
248 getIdxInVector :: Ngrams -> Vector Ngrams -> Int
249 getIdxInVector n ns = case (elemIndex n ns) of
250 Nothing -> panic $ "[ERR][Viz.Phylo.Tools.getIdxInVector] Ngrams not in foundationsRoots: " <> cs n
257 -- | To alter a PhyloGroup matching a given Level
258 alterGroupWithLevel :: (PhyloGroup -> PhyloGroup) -> Level -> Phylo -> Phylo
259 alterGroupWithLevel f lvl p = over ( phylo_periods
265 ) (\g -> if getGroupLevel g == lvl
270 -- | To alter each list of PhyloGroups following a given function
271 alterPhyloGroups :: ([PhyloGroup] -> [PhyloGroup]) -> Phylo -> Phylo
272 alterPhyloGroups f p = over ( phylo_periods
280 -- | To filter the PhyloGroup of a Phylo according to a function and a value
281 filterGroups :: Eq a => (PhyloGroup -> a) -> a -> [PhyloGroup] -> [PhyloGroup]
282 filterGroups f x l = filter (\g -> (f g) == x) l
285 -- | To maybe get the PhyloBranchId of a PhyloGroup
286 getGroupBranchId :: PhyloGroup -> Maybe PhyloBranchId
287 getGroupBranchId = _phylo_groupBranchId
290 -- | To get the PhyloGroups Childs of a PhyloGroup
291 getGroupChilds :: PhyloGroup -> Phylo -> [PhyloGroup]
292 getGroupChilds g p = getGroupsFromIds (getGroupPeriodChildsId g) p
295 -- | To get the id of a PhyloGroup
296 getGroupId :: PhyloGroup -> PhyloGroupId
297 getGroupId = _phylo_groupId
300 getGroupCooc :: PhyloGroup -> Map (Int,Int) Double
301 getGroupCooc = _phylo_groupCooc
304 -- | To get the level out of the id of a PhyloGroup
305 getGroupLevel :: PhyloGroup -> Int
306 getGroupLevel = snd . fst . getGroupId
309 -- | To get the level child pointers of a PhyloGroup
310 getGroupLevelChilds :: PhyloGroup -> [Pointer]
311 getGroupLevelChilds = _phylo_groupLevelChilds
314 -- | To get the PhyloGroups Level Childs Ids of a PhyloGroup
315 getGroupLevelChildsId :: PhyloGroup -> [PhyloGroupId]
316 getGroupLevelChildsId g = map fst $ getGroupLevelChilds g
319 -- | To get the level parent pointers of a PhyloGroup
320 getGroupLevelParents :: PhyloGroup -> [Pointer]
321 getGroupLevelParents = _phylo_groupLevelParents
324 -- | To get the PhyloGroups Level Parents Ids of a PhyloGroup
325 getGroupLevelParentsId :: PhyloGroup -> [PhyloGroupId]
326 getGroupLevelParentsId g = map fst $ getGroupLevelParents g
329 -- | To get the PhyloGroups Level Parents Ids of a PhyloGroup
330 getGroupLevelParentId :: PhyloGroup -> PhyloGroupId
331 getGroupLevelParentId g = (head' "getGroupLevelParentId") $ getGroupLevelParentsId g
333 -- | To get the Meta value of a PhyloGroup
334 getGroupMeta :: Text -> PhyloGroup -> Double
335 getGroupMeta k g = (g ^. phylo_groupMeta) ! k
338 -- | To get the Ngrams of a PhyloGroup
339 getGroupNgrams :: PhyloGroup -> [Int]
340 getGroupNgrams = _phylo_groupNgrams
343 -- | To get the list of pairs (Childs & Parents) of a PhyloGroup
344 getGroupPairs :: PhyloGroup -> Phylo -> [PhyloGroup]
345 getGroupPairs g p = (getGroupChilds g p) ++ (getGroupParents g p)
348 -- | To get the PhyloGroups Parents of a PhyloGroup
349 getGroupParents :: PhyloGroup -> Phylo -> [PhyloGroup]
350 getGroupParents g p = getGroupsFromIds (getGroupPeriodParentsId g) p
353 -- | To get the period out of the id of a PhyloGroup
354 getGroupPeriod :: PhyloGroup -> (Date,Date)
355 getGroupPeriod = fst . fst . getGroupId
358 -- | To get the period child pointers of a PhyloGroup
359 getGroupPeriodChilds :: PhyloGroup -> [Pointer]
360 getGroupPeriodChilds = _phylo_groupPeriodChilds
363 -- | To get the PhyloGroups Period Parents Ids of a PhyloGroup
364 getGroupPeriodChildsId :: PhyloGroup -> [PhyloGroupId]
365 getGroupPeriodChildsId g = map fst $ getGroupPeriodChilds g
368 -- | To get the period parent pointers of a PhyloGroup
369 getGroupPeriodParents :: PhyloGroup -> [Pointer]
370 getGroupPeriodParents = _phylo_groupPeriodParents
373 -- | To get the PhyloGroups Period Parents Ids of a PhyloGroup
374 getGroupPeriodParentsId :: PhyloGroup -> [PhyloGroupId]
375 getGroupPeriodParentsId g = map fst $ getGroupPeriodParents g
378 -- | To get the pointers of a given Phylogroup
379 getGroupPointers :: EdgeType -> Filiation -> PhyloGroup -> [Pointer]
380 getGroupPointers t f g = case t of
381 PeriodEdge -> case f of
382 Ascendant -> getGroupPeriodParents g
383 Descendant -> getGroupPeriodChilds g
384 _ -> panic "[ERR][Viz.Phylo.Tools.getGroupPointers] wrong filiation"
385 LevelEdge -> case f of
386 Ascendant -> getGroupLevelParents g
387 Descendant -> getGroupLevelChilds g
388 _ -> panic "[ERR][Viz.Phylo.Tools.getGroupPointers] wrong filiation"
391 -- | To get the roots labels of a list of group ngrams
392 getGroupText :: PhyloGroup -> Phylo -> [Text]
393 getGroupText g p = ngramsToText (getFoundationsRoots p) (getGroupNgrams g)
396 -- | To get all the PhyloGroup of a Phylo
397 getGroups :: Phylo -> [PhyloGroup]
398 getGroups = view ( phylo_periods
406 -- | To get all PhyloGroups matching a list of PhyloGoupIds in a Phylo
407 -- getGroupsFromIds :: [PhyloGroupId] -> Phylo -> [PhyloGroup]
408 -- getGroupsFromIds ids p = filter (\g -> elem (getGroupId g) ids) $ getGroups p
410 getGroupFromId :: PhyloGroupId -> Phylo -> PhyloGroup
411 getGroupFromId id p =
412 let groups = Map.fromList $ map (\g -> (getGroupId g, g)) $ getGroups p
415 getGroupsFromIds :: [PhyloGroupId] -> Phylo -> [PhyloGroup]
416 getGroupsFromIds ids p =
417 let groups = Map.fromList $ map (\g -> (getGroupId g, g)) $ getGroups p
418 in elems $ restrictKeys groups (Set.fromList ids)
421 -- | To get the corresponding list of PhyloGroups from a list of PhyloNodes
422 getGroupsFromNodes :: [PhyloNode] -> Phylo -> [PhyloGroup]
423 getGroupsFromNodes ns p = getGroupsFromIds (map getNodeId ns) p
426 -- | To get all the PhyloGroup of a Phylo with a given level and period
427 getGroupsWithFilters :: Int -> (Date,Date) -> Phylo -> [PhyloGroup]
428 getGroupsWithFilters lvl prd p = (getGroupsWithLevel lvl p)
430 (getGroupsWithPeriod prd p)
433 -- | To get all the PhyloGroup of a Phylo with a given Level
434 getGroupsWithLevel :: Int -> Phylo -> [PhyloGroup]
435 getGroupsWithLevel lvl p = filterGroups getGroupLevel lvl (getGroups p)
438 -- | To get all the PhyloGroup of a Phylo with a given Period
439 getGroupsWithPeriod :: (Date,Date) -> Phylo -> [PhyloGroup]
440 getGroupsWithPeriod prd p = filterGroups getGroupPeriod prd (getGroups p)
443 -- | To create a PhyloGroup in a Phylo out of a list of Ngrams and a set of parameters
444 initGroup :: [Ngrams] -> Text -> Int -> Int -> Int -> Int -> Phylo -> PhyloGroup
445 initGroup ngrams lbl idx lvl from' to' p = PhyloGroup
446 (((from', to'), lvl), idx)
452 (getMiniCooc (listToFullCombi idxs) (periodsToYears [(from', to')]) (getPhyloCooc p))
455 idxs = sort $ map (\x -> getIdxInRoots x p) ngrams
458 -- | To sum two coocurency Matrix
459 sumCooc :: Map (Int, Int) Double -> Map (Int, Int) Double -> Map (Int, Int) Double
460 sumCooc m m' = unionWith (+) m m'
462 -- | To build the mini cooc matrix of each group
463 getMiniCooc :: [(Int,Int)] -> Set Date -> Map Date (Map (Int,Int) Double) -> Map (Int,Int) Double
464 getMiniCooc pairs years cooc = filterWithKey (\(n,n') _ -> elem (n,n') pairs) cooc'
466 --------------------------------------
467 cooc' :: Map (Int,Int) Double
468 cooc' = foldl (\m m' -> sumCooc m m') empty
470 $ restrictKeys cooc years
471 --------------------------------------
474 ---------------------
475 -- | PhyloPeriod | --
476 ---------------------
479 -- | To alter each PhyloPeriod of a Phylo following a given function
480 alterPhyloPeriods :: (PhyloPeriod -> PhyloPeriod) -> Phylo -> Phylo
481 alterPhyloPeriods f p = over ( phylo_periods
485 -- | To append a list of PhyloPeriod to a Phylo
486 appendToPhyloPeriods :: [PhyloPeriod] -> Phylo -> Phylo
487 appendToPhyloPeriods l p = over (phylo_periods) (++ l) p
490 -- | To get all the PhyloPeriodIds of a Phylo
491 getPhyloPeriods :: Phylo -> [PhyloPeriodId]
492 getPhyloPeriods p = map _phylo_periodId
493 $ view (phylo_periods) p
496 -- | To get the id of a given PhyloPeriod
497 getPhyloPeriodId :: PhyloPeriod -> PhyloPeriodId
498 getPhyloPeriodId prd = _phylo_periodId prd
501 -- | To create a PhyloPeriod
502 initPhyloPeriod :: PhyloPeriodId -> [PhyloLevel] -> PhyloPeriod
503 initPhyloPeriod id l = PhyloPeriod id l
506 -- | To transform a list of periods into a set of Dates
507 periodsToYears :: [(Date,Date)] -> Set Date
508 periodsToYears periods = (Set.fromList . sort . concat)
509 $ map (\(d,d') -> [d..d']) periods
517 -- | To alter a list of PhyloLevels following a given function
518 alterPhyloLevels :: ([PhyloLevel] -> [PhyloLevel]) -> Phylo -> Phylo
519 alterPhyloLevels f p = over ( phylo_periods
521 . phylo_periodLevels) f p
524 -- | To get the PhylolevelId of a given PhyloLevel
525 getPhyloLevelId :: PhyloLevel -> PhyloLevelId
526 getPhyloLevelId = _phylo_levelId
529 -- | To get all the Phylolevels of a given PhyloPeriod
530 getPhyloLevels :: PhyloPeriod -> [PhyloLevel]
531 getPhyloLevels = view (phylo_periodLevels)
534 -- | To create a PhyloLevel
535 initPhyloLevel :: PhyloLevelId -> [PhyloGroup] -> PhyloLevel
536 initPhyloLevel id groups = PhyloLevel id groups
539 -- | To set the LevelId of a PhyloLevel and of all its PhyloGroups
540 setPhyloLevelId :: Int -> PhyloLevel -> PhyloLevel
541 setPhyloLevelId lvl' (PhyloLevel (id, _lvl) groups)
542 = PhyloLevel (id, lvl') groups'
544 groups' = over (traverse . phylo_groupId)
545 (\((period, _lvl), idx) -> ((period, lvl'), idx))
554 -- | To get the clique of a PhyloFis
555 getClique :: PhyloFis -> Clique
556 getClique = _phyloFis_clique
558 -- | To get the support of a PhyloFis
559 getSupport :: PhyloFis -> Support
560 getSupport = _phyloFis_support
562 -- | To get the period of a PhyloFis
563 getFisPeriod :: PhyloFis -> (Date,Date)
564 getFisPeriod = _phyloFis_period
567 ----------------------------
568 -- | PhyloNodes & Edges | --
569 ----------------------------
572 -- | To alter a PhyloNode
573 alterPhyloNode :: (PhyloNode -> PhyloNode) -> PhyloView -> PhyloView
574 alterPhyloNode f v = over ( pv_nodes
579 -- | To filter some GroupEdges with a given threshold
580 filterGroupEdges :: Double -> [GroupEdge] -> [GroupEdge]
581 filterGroupEdges thr edges = filter (\((_s,_t),w) -> w > thr) edges
584 -- | To get the neighbours (directed/undirected) of a PhyloGroup from a list of GroupEdges
585 getNeighbours :: Bool -> PhyloGroup -> [GroupEdge] -> [PhyloGroup]
586 getNeighbours directed g e = case directed of
587 True -> map (\((_s,t),_w) -> t)
588 $ filter (\((s,_t),_w) -> s == g) e
589 False -> map (\((s,t),_w) -> (head' "getNeighbours") $ delete g $ nub [s,t,g])
590 $ filter (\((s,t),_w) -> s == g || t == g) e
593 -- | To get the PhyloBranchId of PhyloNode if it exists
594 getNodeBranchId :: PhyloNode -> PhyloBranchId
595 getNodeBranchId n = case n ^. pn_bid of
596 Nothing -> panic "[ERR][Viz.Phylo.Tools.getNodeBranchId] branchId not found"
600 -- | To get the PhyloGroupId of a PhyloNode
601 getNodeId :: PhyloNode -> PhyloGroupId
602 getNodeId n = n ^. pn_id
605 getNodePeriod :: PhyloNode -> (Date,Date)
606 getNodePeriod n = fst $ fst $ getNodeId n
609 -- | To get the Level of a PhyloNode
610 getNodeLevel :: PhyloNode -> Level
611 getNodeLevel n = (snd . fst) $ getNodeId n
614 -- | To get the Parent Node of a PhyloNode in a PhyloView
615 getNodeParent :: PhyloNode -> PhyloView -> [PhyloNode]
616 getNodeParent n v = filter (\n' -> elem (getNodeId n') (getNodeParentsId n))
620 -- | To get the Parent Node id of a PhyloNode if it exists
621 getNodeParentsId :: PhyloNode -> [PhyloGroupId]
622 getNodeParentsId n = case n ^. pn_parents of
623 Nothing -> panic "[ERR][Viz.Phylo.Tools.getNodeParentsId] node parent not found"
627 -- | To get a list of PhyloNodes grouped by PhyloBranch in a PhyloView
628 getNodesByBranches :: PhyloView -> [(PhyloBranchId,[PhyloNode])]
629 getNodesByBranches v = zip bIds $ map (\id -> filter (\n -> (getNodeBranchId n) == id)
630 $ getNodesInBranches v ) bIds
632 --------------------------------------
633 bIds :: [PhyloBranchId]
634 bIds = getViewBranchIds v
635 --------------------------------------
638 -- | To get a list of PhyloNodes owned by any PhyloBranches in a PhyloView
639 getNodesInBranches :: PhyloView -> [PhyloNode]
640 getNodesInBranches v = filter (\n -> isJust $ n ^. pn_bid)
644 -- | To get the PhyloGroupId of the Source of a PhyloEdge
645 getSourceId :: PhyloEdge -> PhyloGroupId
646 getSourceId e = e ^. pe_source
649 -- | To get the PhyloGroupId of the Target of a PhyloEdge
650 getTargetId :: PhyloEdge -> PhyloGroupId
651 getTargetId e = e ^. pe_target
654 ---------------------
655 -- | PhyloBranch | --
656 ---------------------
659 -- | To get the PhyloBranchId of a PhyloBranch
660 getBranchId :: PhyloBranch -> PhyloBranchId
661 getBranchId b = b ^. pb_id
663 -- | To get a list of PhyloBranchIds
664 getBranchIds :: Phylo -> [PhyloBranchId]
665 getBranchIds p = sortOn snd
667 $ mapMaybe getGroupBranchId
671 -- | To get a list of PhyloBranchIds given a Level in a Phylo
672 getBranchIdsWith :: Level -> Phylo -> [PhyloBranchId]
673 getBranchIdsWith lvl p = sortOn snd
674 $ mapMaybe getGroupBranchId
675 $ getGroupsWithLevel lvl p
678 -- | To get the Meta value of a PhyloBranch
679 getBranchMeta :: Text -> PhyloBranch -> [Double]
680 getBranchMeta k b = (b ^. pb_metrics) ! k
683 -- | To get all the PhyloBranchIds of a PhyloView
684 getViewBranchIds :: PhyloView -> [PhyloBranchId]
685 getViewBranchIds v = map getBranchId $ v ^. pv_branches
688 -- | To get a list of PhyloGroup sharing the same PhyloBranchId
689 getGroupsByBranches :: Phylo -> [(PhyloBranchId,[PhyloGroup])]
690 getGroupsByBranches p = zip (getBranchIds p)
691 $ map (\id -> filter (\g -> (fromJust $ getGroupBranchId g) == id)
692 $ getGroupsInBranches p)
696 -- | To get the sublist of all the PhyloGroups linked to a branch
697 getGroupsInBranches :: Phylo -> [PhyloGroup]
698 getGroupsInBranches p = filter (\g -> isJust $ g ^. phylo_groupBranchId)
702 --------------------------------
703 -- | PhyloQuery & QueryView | --
704 --------------------------------
707 -- | To filter PhyloView's Branches by level
708 filterBranchesByLevel :: Level -> PhyloView -> [PhyloBranch]
709 filterBranchesByLevel lvl pv = filter (\pb -> lvl == (fst $ pb ^. pb_id))
713 -- | To filter PhyloView's Edges by level
714 filterEdgesByLevel :: Level -> [PhyloEdge] -> [PhyloEdge]
715 filterEdgesByLevel lvl pes = filter (\pe -> (lvl == ((snd . fst) $ pe ^. pe_source))
716 && (lvl == ((snd . fst) $ pe ^. pe_target))) pes
719 -- | To filter PhyloView's Edges by type
720 filterEdgesByType :: EdgeType -> [PhyloEdge] -> [PhyloEdge]
721 filterEdgesByType t pes = filter (\pe -> t == (pe ^. pe_type)) pes
724 -- | To filter PhyloView's Nodes by the oldest Period
725 filterNodesByFirstPeriod :: [PhyloNode] -> [PhyloNode]
726 filterNodesByFirstPeriod pns = filter (\pn -> fstPrd == ((fst . fst) $ pn ^. pn_id)) pns
728 --------------------------------------
729 fstPrd :: (Date,Date)
730 fstPrd = (head' "filterNodesByFirstPeriod")
732 $ map (\pn -> (fst . fst) $ pn ^. pn_id) pns
733 --------------------------------------
736 -- | To filter PhyloView's Nodes by Branch
737 filterNodesByBranch :: PhyloBranchId -> [PhyloNode] -> [PhyloNode]
738 filterNodesByBranch bId pns = filter (\pn -> if isJust $ pn ^. pn_bid
739 then if bId == (fromJust $ pn ^. pn_bid)
745 -- | To filter PhyloView's Nodes by level
746 filterNodesByLevel :: Level -> [PhyloNode] -> [PhyloNode]
747 filterNodesByLevel lvl pns = filter (\pn -> lvl == ((snd . fst) $ pn ^. pn_id)) pns
750 -- | To filter PhyloView's Nodes by Period
751 filterNodesByPeriod :: PhyloPeriodId -> [PhyloNode] -> [PhyloNode]
752 filterNodesByPeriod prd pns = filter (\pn -> prd == ((fst . fst) $ pn ^. pn_id)) pns
755 -- | To get the first clustering method to apply to get the contextual units of a Phylo
756 getContextualUnit :: PhyloQueryBuild -> Cluster
757 getContextualUnit q = q ^. q_contextualUnit
760 -- | To get the metrics to apply to contextual units
761 getContextualUnitMetrics :: PhyloQueryBuild -> [Metric]
762 getContextualUnitMetrics q = q ^. q_contextualUnitMetrics
765 -- | To get the filters to apply to contextual units
766 getContextualUnitFilters :: PhyloQueryBuild -> [Filter]
767 getContextualUnitFilters q = q ^. q_contextualUnitFilters
770 -- | To get the cluster methods to apply to the Nths levels of a Phylo
771 getNthCluster :: PhyloQueryBuild -> Cluster
772 getNthCluster q = q ^. q_nthCluster
775 -- | To get the Sup Level of a reconstruction of a Phylo from a PhyloQuery
776 getNthLevel :: PhyloQueryBuild -> Level
777 getNthLevel q = q ^. q_nthLevel
780 -- | To get the Grain of the PhyloPeriods from a PhyloQuery
781 getPeriodGrain :: PhyloQueryBuild -> Int
782 getPeriodGrain q = q ^. q_periodGrain
785 -- | To get the intertemporal matching strategy to apply to a Phylo from a PhyloQuery
786 getInterTemporalMatching :: PhyloQueryBuild -> Proximity
787 getInterTemporalMatching q = q ^. q_interTemporalMatching
790 -- | To get the Steps of the PhyloPeriods from a PhyloQuery
791 getPeriodSteps :: PhyloQueryBuild -> Int
792 getPeriodSteps q = q ^. q_periodSteps
795 --------------------------------------------------
796 -- | PhyloQueryBuild & PhyloQueryView Constructors | --
797 --------------------------------------------------
799 -- | To get the threshold of a Proximity
800 getThreshold :: Proximity -> Double
801 getThreshold prox = case prox of
802 WeightedLogJaccard (WLJParams thr _) -> thr
803 Hamming (HammingParams thr) -> thr
804 Filiation -> panic "[ERR][Viz.Phylo.Tools.getThreshold] Filiation"
807 -- | To get the Proximity associated to a given Clustering method
808 getProximity :: Cluster -> Proximity
809 getProximity cluster = case cluster of
810 Louvain (LouvainParams proxi) -> proxi
811 RelatedComponents (RCParams proxi) -> proxi
812 _ -> panic "[ERR][Viz.Phylo.Tools.getProximity] this cluster has no associated Proximity"
815 -- | To initialize all the Cluster / Proximity with their default parameters
816 initFis :: Maybe Bool -> Maybe Support -> Maybe Int -> FisParams
817 initFis (def True -> kmf) (def 0 -> min') (def 0 -> thr) = FisParams kmf min' thr
819 initHamming :: Maybe Double -> HammingParams
820 initHamming (def 0.01 -> sens) = HammingParams sens
822 initLonelyBranch :: Maybe Int -> Maybe Int -> Maybe Int -> LBParams
823 initLonelyBranch (def 2 -> periodsInf) (def 2 -> periodsSup) (def 1 -> minNodes) = LBParams periodsInf periodsSup minNodes
825 initSizeBranch :: Maybe Int -> SBParams
826 initSizeBranch (def 1 -> minSize) = SBParams minSize
828 initLonelyBranch' :: Maybe Int -> Maybe Int -> Maybe Int -> LBParams
829 initLonelyBranch' (def 0 -> periodsInf) (def 0 -> periodsSup) (def 1 -> minNodes) = LBParams periodsInf periodsSup minNodes
831 initLouvain :: Maybe Proximity -> LouvainParams
832 initLouvain (def defaultWeightedLogJaccard -> proxi) = LouvainParams proxi
834 initRelatedComponents :: Maybe Proximity -> RCParams
835 initRelatedComponents (def defaultWeightedLogJaccard -> proxi) = RCParams proxi
837 -- | TODO user param in main function
838 initWeightedLogJaccard :: Maybe Double -> Maybe Double -> WLJParams
839 initWeightedLogJaccard (def 0.3 -> thr) (def 20.0 -> sens) = WLJParams thr sens
842 -- | To initialize a PhyloQueryBuild from given and default parameters
843 initPhyloQueryBuild :: Text -> Text -> Maybe Int
844 -> Maybe Int -> Maybe Cluster -> Maybe [Metric]
845 -> Maybe [Filter]-> Maybe Proximity -> Maybe Int
846 -> Maybe Double -> Maybe Double -> Maybe Int
847 -> Maybe Level -> Maybe Cluster -> PhyloQueryBuild
848 initPhyloQueryBuild name desc (def 5 -> grain)
849 (def 1 -> steps) (def defaultFis -> cluster) (def [] -> metrics)
850 (def [] -> filters) (def defaultWeightedLogJaccard -> matching') (def 5 -> frame)
851 (def 0.8 -> frameThr) (def 0.5 -> reBranchThr) (def 4 -> reBranchNth)
852 (def 2 -> nthLevel) (def defaultRelatedComponents -> nthCluster) =
853 PhyloQueryBuild name desc grain
854 steps cluster metrics filters matching' frame frameThr reBranchThr reBranchNth nthLevel nthCluster
857 -- | To initialize a PhyloQueryView default parameters
858 initPhyloQueryView :: Maybe Level -> Maybe Filiation -> Maybe Bool -> Maybe Level -> Maybe [Metric] -> Maybe [Filter] -> Maybe [Tagger] -> Maybe (Sort, Order) -> Maybe ExportMode -> Maybe DisplayMode -> Maybe Bool -> PhyloQueryView
859 initPhyloQueryView (def 2 -> lvl) (def Descendant -> f) (def False -> c) (def 1 -> d) (def [] -> ms) (def [] -> fs) (def [] -> ts) s (def Json -> em) (def Flat -> dm) (def True -> v) =
860 PhyloQueryView lvl f c d ms fs ts s em dm v
863 -- | To define some obvious boolean getters
864 shouldKeepMinorFis :: FisParams -> Bool
865 shouldKeepMinorFis = _fis_keepMinorFis
867 ----------------------------
868 -- | Default ressources | --
869 ----------------------------
873 defaultFis :: Cluster
874 defaultFis = Fis (initFis Nothing Nothing Nothing)
876 defaultLouvain :: Cluster
877 defaultLouvain = Louvain (initLouvain Nothing)
879 defaultRelatedComponents :: Cluster
880 defaultRelatedComponents = RelatedComponents (initRelatedComponents Nothing)
884 defaultLonelyBranch :: Filter
885 defaultLonelyBranch = LonelyBranch (initLonelyBranch Nothing Nothing Nothing)
887 defaultSizeBranch :: Filter
888 defaultSizeBranch = SizeBranch (initSizeBranch Nothing)
892 defaultPhyloParam :: PhyloParam
893 defaultPhyloParam = initPhyloParam Nothing Nothing Nothing
897 defaultHamming :: Proximity
898 defaultHamming = Hamming (initHamming Nothing)
900 defaultWeightedLogJaccard :: Proximity
901 defaultWeightedLogJaccard = WeightedLogJaccard (initWeightedLogJaccard Nothing Nothing)
907 defaultQueryBuild :: PhyloQueryBuild
908 defaultQueryBuild = defaultQueryBuild'
910 "An example of Phylomemy (french without accent)"
912 defaultQueryBuild' :: Title -> Desc -> PhyloQueryBuild
913 defaultQueryBuild' t d = initPhyloQueryBuild t d
914 Nothing Nothing Nothing
915 Nothing Nothing Nothing
916 Nothing Nothing Nothing
917 Nothing Nothing Nothing
919 defaultQueryView :: PhyloQueryView
920 defaultQueryView = initPhyloQueryView
921 Nothing Nothing Nothing
922 Nothing Nothing Nothing
923 Nothing Nothing Nothing
928 defaultSoftware :: Software
929 defaultSoftware = Software "Gargantext" "v4"
933 defaultPhyloVersion :: Text
934 defaultPhyloVersion = "v1"