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 -- | To get all combinations of a list and apply a function to the resulting list of pairs
114 listToDirectedCombiWith :: Eq a => forall b. (a -> b) -> [a] -> [(b,b)]
115 listToDirectedCombiWith f l = [(f x,f y) | x <- l, y <- l, x /= y]
118 -- | To get the sequential combinations of an order list
119 listToSequentialCombi :: Eq a => [a] -> [(a,a)]
120 listToSequentialCombi l = nubBy (\x y -> fst x == fst y) $ listToUnDirectedCombi l
123 -- | To get all combinations of a list with no repetition
124 listToUnDirectedCombi :: [a] -> [(a,a)]
125 listToUnDirectedCombi l = [ (x,y) | (x:rest) <- tails l, y <- rest ]
128 -- | To get all combinations of a list with no repetition and apply a function to the resulting list of pairs
129 listToUnDirectedCombiWith :: forall a b. (a -> b) -> [a] -> [(b,b)]
130 listToUnDirectedCombiWith f l = [ (f x, f y) | (x:rest) <- tails l, y <- rest ]
133 -- | To transform a list of Ngrams Indexes into a Label
134 ngramsToLabel :: Vector Ngrams -> [Int] -> Text
135 ngramsToLabel ngrams l = unwords $ ngramsToText ngrams l
138 -- | To transform a list of Ngrams Indexes into a list of Text
139 ngramsToText :: Vector Ngrams -> [Int] -> [Text]
140 ngramsToText ngrams l = map (\idx -> ngrams Vector.! idx) l
143 -- | To unify the keys (x,y) that Map 1 share with Map 2 such as: (x,y) <=> (y,x)
144 unifySharedKeys :: Eq a => Ord a => Map (a,a) b -> Map (a,a) b -> Map (a,a) b
145 unifySharedKeys m1 m2 = mapKeys (\(x,y) -> if member (y,x) m2
154 -- | An analyzer ingests a Ngrams and generates a modified version of it
155 phyloAnalyzer :: Ngrams -> Ngrams
156 phyloAnalyzer n = toLower n
158 -- | To init the foundation roots of the Phylo as a Vector of Ngrams
159 initFoundationsRoots :: [Ngrams] -> Vector Ngrams
160 initFoundationsRoots l = Vector.fromList $ map phyloAnalyzer l
162 -- | To init the base of a Phylo from a List of Periods and Foundations
163 initPhyloBase :: [(Date, Date)] -> PhyloFoundations -> Map Date Double -> Map Date (Map (Int,Int) Double) -> Map (Date,Date) [PhyloFis] -> PhyloParam -> Phylo
164 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
166 -- | To init the param of a Phylo
167 initPhyloParam :: Maybe Text -> Maybe Software -> Maybe PhyloQueryBuild -> PhyloParam
168 initPhyloParam (def defaultPhyloVersion -> v) (def defaultSoftware -> s) (def defaultQueryBuild -> q) = PhyloParam v s q
170 -- | To get the last computed Level in a Phylo
171 getLastLevel :: Phylo -> Level
172 getLastLevel p = (last . sort)
173 $ map (snd . getPhyloLevelId)
174 $ view ( phylo_periods
176 . phylo_periodLevels ) p
178 -- | To get all the coocurency matrix of a phylo
179 getPhyloCooc :: Phylo -> Map Date (Map (Int,Int) Double)
180 getPhyloCooc p = p ^. phylo_cooc
183 -- | To get the PhyloParam of a Phylo
184 getPhyloParams :: Phylo -> PhyloParam
185 getPhyloParams = _phylo_param
187 -- | To get the title of a Phylo
188 getPhyloTitle :: Phylo -> Text
189 getPhyloTitle p = _q_phyloTitle $ _phyloParam_query $ getPhyloParams p
191 -- | To get the desc of a Phylo
192 getPhyloDescription :: Phylo -> Text
193 getPhyloDescription p = _q_phyloTitle $ _phyloParam_query $ getPhyloParams p
195 getPhyloMatchingFrame :: Phylo -> Int
196 getPhyloMatchingFrame p = _q_interTemporalMatchingFrame $ _phyloParam_query $ getPhyloParams p
198 getPhyloReBranchThr :: Phylo -> Double
199 getPhyloReBranchThr p = _q_reBranchThr $ _phyloParam_query $ getPhyloParams p
201 getPhyloReBranchNth :: Phylo -> Int
202 getPhyloReBranchNth p = _q_reBranchNth $ _phyloParam_query $ getPhyloParams p
204 getPhyloFis :: Phylo -> Map (Date,Date) [PhyloFis]
205 getPhyloFis = _phylo_fis
212 -- | To get the foundations of a Phylo
213 getFoundations :: Phylo -> PhyloFoundations
214 getFoundations = _phylo_foundations
216 -- | To get the foundations roots of a Phylo
217 getFoundationsRoots :: Phylo -> Vector Ngrams
218 getFoundationsRoots p = (getFoundations p) ^. phylo_foundationsRoots
220 -- | To get the Index of a Ngrams in the foundationsRoots of a Phylo
221 getIdxInRoots :: Ngrams -> Phylo -> Int
222 getIdxInRoots n p = case (elemIndex n (getFoundationsRoots p)) of
223 Nothing -> panic "[ERR][Viz.Phylo.Tools.getIdxInRoots] Ngrams not in foundationsRoots"
226 getIdxInVector :: Ngrams -> Vector Ngrams -> Int
227 getIdxInVector n ns = case (elemIndex n ns) of
228 Nothing -> panic "[ERR][Viz.Phylo.Tools.getIdxInRoots] Ngrams not in foundationsRoots"
236 -- | To alter a PhyloGroup matching a given Level
237 alterGroupWithLevel :: (PhyloGroup -> PhyloGroup) -> Level -> Phylo -> Phylo
238 alterGroupWithLevel f lvl p = over ( phylo_periods
244 ) (\g -> if getGroupLevel g == lvl
249 -- | To alter each list of PhyloGroups following a given function
250 alterPhyloGroups :: ([PhyloGroup] -> [PhyloGroup]) -> Phylo -> Phylo
251 alterPhyloGroups f p = over ( phylo_periods
259 -- | To filter the PhyloGroup of a Phylo according to a function and a value
260 filterGroups :: Eq a => (PhyloGroup -> a) -> a -> [PhyloGroup] -> [PhyloGroup]
261 filterGroups f x l = filter (\g -> (f g) == x) l
264 -- | To maybe get the PhyloBranchId of a PhyloGroup
265 getGroupBranchId :: PhyloGroup -> Maybe PhyloBranchId
266 getGroupBranchId = _phylo_groupBranchId
269 -- | To get the PhyloGroups Childs of a PhyloGroup
270 getGroupChilds :: PhyloGroup -> Phylo -> [PhyloGroup]
271 getGroupChilds g p = getGroupsFromIds (getGroupPeriodChildsId g) p
274 -- | To get the id of a PhyloGroup
275 getGroupId :: PhyloGroup -> PhyloGroupId
276 getGroupId = _phylo_groupId
279 getGroupCooc :: PhyloGroup -> Map (Int,Int) Double
280 getGroupCooc = _phylo_groupCooc
283 -- | To get the level out of the id of a PhyloGroup
284 getGroupLevel :: PhyloGroup -> Int
285 getGroupLevel = snd . fst . getGroupId
288 -- | To get the level child pointers of a PhyloGroup
289 getGroupLevelChilds :: PhyloGroup -> [Pointer]
290 getGroupLevelChilds = _phylo_groupLevelChilds
293 -- | To get the PhyloGroups Level Childs Ids of a PhyloGroup
294 getGroupLevelChildsId :: PhyloGroup -> [PhyloGroupId]
295 getGroupLevelChildsId g = map fst $ getGroupLevelChilds g
298 -- | To get the level parent pointers of a PhyloGroup
299 getGroupLevelParents :: PhyloGroup -> [Pointer]
300 getGroupLevelParents = _phylo_groupLevelParents
303 -- | To get the PhyloGroups Level Parents Ids of a PhyloGroup
304 getGroupLevelParentsId :: PhyloGroup -> [PhyloGroupId]
305 getGroupLevelParentsId g = map fst $ getGroupLevelParents g
308 -- | To get the PhyloGroups Level Parents Ids of a PhyloGroup
309 getGroupLevelParentId :: PhyloGroup -> PhyloGroupId
310 getGroupLevelParentId g = (head' "getGroupLevelParentId") $ getGroupLevelParentsId g
312 -- | To get the Meta value of a PhyloGroup
313 getGroupMeta :: Text -> PhyloGroup -> Double
314 getGroupMeta k g = (g ^. phylo_groupMeta) ! k
317 -- | To get the Ngrams of a PhyloGroup
318 getGroupNgrams :: PhyloGroup -> [Int]
319 getGroupNgrams = _phylo_groupNgrams
322 -- | To get the list of pairs (Childs & Parents) of a PhyloGroup
323 getGroupPairs :: PhyloGroup -> Phylo -> [PhyloGroup]
324 getGroupPairs g p = (getGroupChilds g p) ++ (getGroupParents g p)
327 -- | To get the PhyloGroups Parents of a PhyloGroup
328 getGroupParents :: PhyloGroup -> Phylo -> [PhyloGroup]
329 getGroupParents g p = getGroupsFromIds (getGroupPeriodParentsId g) p
332 -- | To get the period out of the id of a PhyloGroup
333 getGroupPeriod :: PhyloGroup -> (Date,Date)
334 getGroupPeriod = fst . fst . getGroupId
337 -- | To get the period child pointers of a PhyloGroup
338 getGroupPeriodChilds :: PhyloGroup -> [Pointer]
339 getGroupPeriodChilds = _phylo_groupPeriodChilds
342 -- | To get the PhyloGroups Period Parents Ids of a PhyloGroup
343 getGroupPeriodChildsId :: PhyloGroup -> [PhyloGroupId]
344 getGroupPeriodChildsId g = map fst $ getGroupPeriodChilds g
347 -- | To get the period parent pointers of a PhyloGroup
348 getGroupPeriodParents :: PhyloGroup -> [Pointer]
349 getGroupPeriodParents = _phylo_groupPeriodParents
352 -- | To get the PhyloGroups Period Parents Ids of a PhyloGroup
353 getGroupPeriodParentsId :: PhyloGroup -> [PhyloGroupId]
354 getGroupPeriodParentsId g = map fst $ getGroupPeriodParents g
357 -- | To get the pointers of a given Phylogroup
358 getGroupPointers :: EdgeType -> Filiation -> PhyloGroup -> [Pointer]
359 getGroupPointers t f g = case t of
360 PeriodEdge -> case f of
361 Ascendant -> getGroupPeriodParents g
362 Descendant -> getGroupPeriodChilds g
363 _ -> panic "[ERR][Viz.Phylo.Tools.getGroupPointers] wrong filiation"
364 LevelEdge -> case f of
365 Ascendant -> getGroupLevelParents g
366 Descendant -> getGroupLevelChilds g
367 _ -> panic "[ERR][Viz.Phylo.Tools.getGroupPointers] wrong filiation"
370 -- | To get the roots labels of a list of group ngrams
371 getGroupText :: PhyloGroup -> Phylo -> [Text]
372 getGroupText g p = ngramsToText (getFoundationsRoots p) (getGroupNgrams g)
375 -- | To get all the PhyloGroup of a Phylo
376 getGroups :: Phylo -> [PhyloGroup]
377 getGroups = view ( phylo_periods
385 -- | To get all PhyloGroups matching a list of PhyloGroupIds in a Phylo
386 getGroupsFromIds :: [PhyloGroupId] -> Phylo -> [PhyloGroup]
387 getGroupsFromIds ids p = filter (\g -> elem (getGroupId g) ids) $ getGroups p
389 -- | To get a PhyloGroup matching a PhyloGroupId in a Phylo
390 getGroupFromId :: PhyloGroupId -> Phylo -> PhyloGroup
391 getGroupFromId id p = (head' "getGroupFromId") $ getGroupsFromIds [id] p
394 -- | To get the corresponding list of PhyloGroups from a list of PhyloNodes
395 getGroupsFromNodes :: [PhyloNode] -> Phylo -> [PhyloGroup]
396 getGroupsFromNodes ns p = getGroupsFromIds (map getNodeId ns) p
399 -- | To get all the PhyloGroup of a Phylo with a given level and period
400 getGroupsWithFilters :: Int -> (Date,Date) -> Phylo -> [PhyloGroup]
401 getGroupsWithFilters lvl prd p = (getGroupsWithLevel lvl p)
403 (getGroupsWithPeriod prd p)
406 -- | To get all the PhyloGroup of a Phylo with a given Level
407 getGroupsWithLevel :: Int -> Phylo -> [PhyloGroup]
408 getGroupsWithLevel lvl p = filterGroups getGroupLevel lvl (getGroups p)
411 -- | To get all the PhyloGroup of a Phylo with a given Period
412 getGroupsWithPeriod :: (Date,Date) -> Phylo -> [PhyloGroup]
413 getGroupsWithPeriod prd p = filterGroups getGroupPeriod prd (getGroups p)
416 -- | To create a PhyloGroup in a Phylo out of a list of Ngrams and a set of parameters
417 initGroup :: [Ngrams] -> Text -> Int -> Int -> Int -> Int -> Phylo -> PhyloGroup
418 initGroup ngrams lbl idx lvl from' to' p = PhyloGroup
419 (((from', to'), lvl), idx)
424 (getMiniCooc (listToFullCombi idxs) (periodsToYears [(from', to')]) (getPhyloCooc p))
427 idxs = sort $ map (\x -> getIdxInRoots x p) ngrams
430 -- | To sum two coocurency Matrix
431 sumCooc :: Map (Int, Int) Double -> Map (Int, Int) Double -> Map (Int, Int) Double
432 sumCooc m m' = unionWith (+) m m'
434 -- | To build the mini cooc matrix of each group
435 getMiniCooc :: [(Int,Int)] -> Set Date -> Map Date (Map (Int,Int) Double) -> Map (Int,Int) Double
436 getMiniCooc pairs years cooc = filterWithKey (\(n,n') _ -> elem (n,n') pairs) cooc'
438 --------------------------------------
439 cooc' :: Map (Int,Int) Double
440 cooc' = foldl (\m m' -> sumCooc m m') empty
442 $ restrictKeys cooc years
443 --------------------------------------
446 ---------------------
447 -- | PhyloPeriod | --
448 ---------------------
451 -- | To alter each PhyloPeriod of a Phylo following a given function
452 alterPhyloPeriods :: (PhyloPeriod -> PhyloPeriod) -> Phylo -> Phylo
453 alterPhyloPeriods f p = over ( phylo_periods
457 -- | To append a list of PhyloPeriod to a Phylo
458 appendToPhyloPeriods :: [PhyloPeriod] -> Phylo -> Phylo
459 appendToPhyloPeriods l p = over (phylo_periods) (++ l) p
462 -- | To get all the PhyloPeriodIds of a Phylo
463 getPhyloPeriods :: Phylo -> [PhyloPeriodId]
464 getPhyloPeriods p = map _phylo_periodId
465 $ view (phylo_periods) p
468 -- | To get the id of a given PhyloPeriod
469 getPhyloPeriodId :: PhyloPeriod -> PhyloPeriodId
470 getPhyloPeriodId prd = _phylo_periodId prd
473 -- | To create a PhyloPeriod
474 initPhyloPeriod :: PhyloPeriodId -> [PhyloLevel] -> PhyloPeriod
475 initPhyloPeriod id l = PhyloPeriod id l
478 -- | To transform a list of periods into a set of Dates
479 periodsToYears :: [(Date,Date)] -> Set Date
480 periodsToYears periods = (Set.fromList . sort . concat)
481 $ map (\(d,d') -> [d..d']) periods
489 -- | To alter a list of PhyloLevels following a given function
490 alterPhyloLevels :: ([PhyloLevel] -> [PhyloLevel]) -> Phylo -> Phylo
491 alterPhyloLevels f p = over ( phylo_periods
493 . phylo_periodLevels) f p
496 -- | To get the PhylolevelId of a given PhyloLevel
497 getPhyloLevelId :: PhyloLevel -> PhyloLevelId
498 getPhyloLevelId = _phylo_levelId
501 -- | To get all the Phylolevels of a given PhyloPeriod
502 getPhyloLevels :: PhyloPeriod -> [PhyloLevel]
503 getPhyloLevels = view (phylo_periodLevels)
506 -- | To create a PhyloLevel
507 initPhyloLevel :: PhyloLevelId -> [PhyloGroup] -> PhyloLevel
508 initPhyloLevel id groups = PhyloLevel id groups
511 -- | To set the LevelId of a PhyloLevel and of all its PhyloGroups
512 setPhyloLevelId :: Int -> PhyloLevel -> PhyloLevel
513 setPhyloLevelId lvl' (PhyloLevel (id, _lvl) groups)
514 = PhyloLevel (id, lvl') groups'
516 groups' = over (traverse . phylo_groupId)
517 (\((period, _lvl), idx) -> ((period, lvl'), idx))
526 -- | To get the clique of a PhyloFis
527 getClique :: PhyloFis -> Clique
528 getClique = _phyloFis_clique
530 -- | To get the support of a PhyloFis
531 getSupport :: PhyloFis -> Support
532 getSupport = _phyloFis_support
534 -- | To get the period of a PhyloFis
535 getFisPeriod :: PhyloFis -> (Date,Date)
536 getFisPeriod = _phyloFis_period
539 ----------------------------
540 -- | PhyloNodes & Edges | --
541 ----------------------------
544 -- | To filter some GroupEdges with a given threshold
545 filterGroupEdges :: Double -> [GroupEdge] -> [GroupEdge]
546 filterGroupEdges thr edges = filter (\((_s,_t),w) -> w > thr) edges
549 -- | To get the neighbours (directed/undirected) of a PhyloGroup from a list of GroupEdges
550 getNeighbours :: Bool -> PhyloGroup -> [GroupEdge] -> [PhyloGroup]
551 getNeighbours directed g e = case directed of
552 True -> map (\((_s,t),_w) -> t)
553 $ filter (\((s,_t),_w) -> s == g) e
554 False -> map (\((s,t),_w) -> (head' "getNeighbours") $ delete g $ nub [s,t,g])
555 $ filter (\((s,t),_w) -> s == g || t == g) e
558 -- | To get the PhyloBranchId of PhyloNode if it exists
559 getNodeBranchId :: PhyloNode -> PhyloBranchId
560 getNodeBranchId n = case n ^. pn_bid of
561 Nothing -> panic "[ERR][Viz.Phylo.Tools.getNodeBranchId] branchId not found"
565 -- | To get the PhyloGroupId of a PhyloNode
566 getNodeId :: PhyloNode -> PhyloGroupId
567 getNodeId n = n ^. pn_id
570 -- | To get the Level of a PhyloNode
571 getNodeLevel :: PhyloNode -> Level
572 getNodeLevel n = (snd . fst) $ getNodeId n
575 -- | To get the Parent Node of a PhyloNode in a PhyloView
576 getNodeParent :: PhyloNode -> PhyloView -> [PhyloNode]
577 getNodeParent n v = filter (\n' -> elem (getNodeId n') (getNodeParentsId n))
581 -- | To get the Parent Node id of a PhyloNode if it exists
582 getNodeParentsId :: PhyloNode -> [PhyloGroupId]
583 getNodeParentsId n = case n ^. pn_parents of
584 Nothing -> panic "[ERR][Viz.Phylo.Tools.getNodeParentsId] node parent not found"
588 -- | To get a list of PhyloNodes grouped by PhyloBranch in a PhyloView
589 getNodesByBranches :: PhyloView -> [(PhyloBranchId,[PhyloNode])]
590 getNodesByBranches v = zip bIds $ map (\id -> filter (\n -> (getNodeBranchId n) == id)
591 $ getNodesInBranches v ) bIds
593 --------------------------------------
594 bIds :: [PhyloBranchId]
595 bIds = getViewBranchIds v
596 --------------------------------------
599 -- | To get a list of PhyloNodes owned by any PhyloBranches in a PhyloView
600 getNodesInBranches :: PhyloView -> [PhyloNode]
601 getNodesInBranches v = filter (\n -> isJust $ n ^. pn_bid)
605 -- | To get the PhyloGroupId of the Source of a PhyloEdge
606 getSourceId :: PhyloEdge -> PhyloGroupId
607 getSourceId e = e ^. pe_source
610 -- | To get the PhyloGroupId of the Target of a PhyloEdge
611 getTargetId :: PhyloEdge -> PhyloGroupId
612 getTargetId e = e ^. pe_target
615 ---------------------
616 -- | PhyloBranch | --
617 ---------------------
620 -- | To get the PhyloBranchId of a PhyloBranch
621 getBranchId :: PhyloBranch -> PhyloBranchId
622 getBranchId b = b ^. pb_id
624 -- | To get a list of PhyloBranchIds
625 getBranchIds :: Phylo -> [PhyloBranchId]
626 getBranchIds p = sortOn snd
628 $ mapMaybe getGroupBranchId
632 -- | To get a list of PhyloBranchIds given a Level in a Phylo
633 getBranchIdsWith :: Level -> Phylo -> [PhyloBranchId]
634 getBranchIdsWith lvl p = sortOn snd
635 $ mapMaybe getGroupBranchId
636 $ getGroupsWithLevel lvl p
639 -- | To get the Meta value of a PhyloBranch
640 getBranchMeta :: Text -> PhyloBranch -> [Double]
641 getBranchMeta k b = (b ^. pb_metrics) ! k
644 -- | To get all the PhyloBranchIds of a PhyloView
645 getViewBranchIds :: PhyloView -> [PhyloBranchId]
646 getViewBranchIds v = map getBranchId $ v ^. pv_branches
649 -- | To get a list of PhyloGroup sharing the same PhyloBranchId
650 getGroupsByBranches :: Phylo -> [(PhyloBranchId,[PhyloGroup])]
651 getGroupsByBranches p = zip (getBranchIds p)
652 $ map (\id -> filter (\g -> (fromJust $ getGroupBranchId g) == id)
653 $ getGroupsInBranches p)
657 -- | To get the sublist of all the PhyloGroups linked to a branch
658 getGroupsInBranches :: Phylo -> [PhyloGroup]
659 getGroupsInBranches p = filter (\g -> isJust $ g ^. phylo_groupBranchId)
663 --------------------------------
664 -- | PhyloQuery & QueryView | --
665 --------------------------------
668 -- | To filter PhyloView's Branches by level
669 filterBranchesByLevel :: Level -> PhyloView -> [PhyloBranch]
670 filterBranchesByLevel lvl pv = filter (\pb -> lvl == (fst $ pb ^. pb_id))
674 -- | To filter PhyloView's Edges by level
675 filterEdgesByLevel :: Level -> [PhyloEdge] -> [PhyloEdge]
676 filterEdgesByLevel lvl pes = filter (\pe -> (lvl == ((snd . fst) $ pe ^. pe_source))
677 && (lvl == ((snd . fst) $ pe ^. pe_target))) pes
680 -- | To filter PhyloView's Edges by type
681 filterEdgesByType :: EdgeType -> [PhyloEdge] -> [PhyloEdge]
682 filterEdgesByType t pes = filter (\pe -> t == (pe ^. pe_type)) pes
685 -- | To filter PhyloView's Nodes by the oldest Period
686 filterNodesByFirstPeriod :: [PhyloNode] -> [PhyloNode]
687 filterNodesByFirstPeriod pns = filter (\pn -> fstPrd == ((fst . fst) $ pn ^. pn_id)) pns
689 --------------------------------------
690 fstPrd :: (Date,Date)
691 fstPrd = (head' "filterNodesByFirstPeriod")
693 $ map (\pn -> (fst . fst) $ pn ^. pn_id) pns
694 --------------------------------------
697 -- | To filter PhyloView's Nodes by Branch
698 filterNodesByBranch :: PhyloBranchId -> [PhyloNode] -> [PhyloNode]
699 filterNodesByBranch bId pns = filter (\pn -> if isJust $ pn ^. pn_bid
700 then if bId == (fromJust $ pn ^. pn_bid)
706 -- | To filter PhyloView's Nodes by level
707 filterNodesByLevel :: Level -> [PhyloNode] -> [PhyloNode]
708 filterNodesByLevel lvl pns = filter (\pn -> lvl == ((snd . fst) $ pn ^. pn_id)) pns
711 -- | To filter PhyloView's Nodes by Period
712 filterNodesByPeriod :: PhyloPeriodId -> [PhyloNode] -> [PhyloNode]
713 filterNodesByPeriod prd pns = filter (\pn -> prd == ((fst . fst) $ pn ^. pn_id)) pns
716 -- | To get the first clustering method to apply to get the contextual units of a Phylo
717 getContextualUnit :: PhyloQueryBuild -> Cluster
718 getContextualUnit q = q ^. q_contextualUnit
721 -- | To get the metrics to apply to contextual units
722 getContextualUnitMetrics :: PhyloQueryBuild -> [Metric]
723 getContextualUnitMetrics q = q ^. q_contextualUnitMetrics
726 -- | To get the filters to apply to contextual units
727 getContextualUnitFilters :: PhyloQueryBuild -> [Filter]
728 getContextualUnitFilters q = q ^. q_contextualUnitFilters
731 -- | To get the cluster methods to apply to the Nths levels of a Phylo
732 getNthCluster :: PhyloQueryBuild -> Cluster
733 getNthCluster q = q ^. q_nthCluster
736 -- | To get the Sup Level of a reconstruction of a Phylo from a PhyloQuery
737 getNthLevel :: PhyloQueryBuild -> Level
738 getNthLevel q = q ^. q_nthLevel
741 -- | To get the Grain of the PhyloPeriods from a PhyloQuery
742 getPeriodGrain :: PhyloQueryBuild -> Int
743 getPeriodGrain q = q ^. q_periodGrain
746 -- | To get the intertemporal matching strategy to apply to a Phylo from a PhyloQuery
747 getInterTemporalMatching :: PhyloQueryBuild -> Proximity
748 getInterTemporalMatching q = q ^. q_interTemporalMatching
751 -- | To get the Steps of the PhyloPeriods from a PhyloQuery
752 getPeriodSteps :: PhyloQueryBuild -> Int
753 getPeriodSteps q = q ^. q_periodSteps
756 --------------------------------------------------
757 -- | PhyloQueryBuild & PhyloQueryView Constructors | --
758 --------------------------------------------------
760 -- | To get the threshold of a Proximity
761 getThreshold :: Proximity -> Double
762 getThreshold prox = case prox of
763 WeightedLogJaccard (WLJParams thr _) -> thr
764 Hamming (HammingParams thr) -> thr
765 Filiation -> panic "[ERR][Viz.Phylo.Tools.getThreshold] Filiation"
768 -- | To get the Proximity associated to a given Clustering method
769 getProximity :: Cluster -> Proximity
770 getProximity cluster = case cluster of
771 Louvain (LouvainParams proxi) -> proxi
772 RelatedComponents (RCParams proxi) -> proxi
773 _ -> panic "[ERR][Viz.Phylo.Tools.getProximity] this cluster has no associated Proximity"
776 -- | To initialize all the Cluster / Proximity with their default parameters
777 initFis :: Maybe Bool -> Maybe Support -> Maybe Int -> FisParams
778 initFis (def True -> kmf) (def 1 -> min') (def 1 -> thr) = FisParams kmf min' thr
780 initHamming :: Maybe Double -> HammingParams
781 initHamming (def 0.01 -> sens) = HammingParams sens
783 initLonelyBranch :: Maybe Int -> Maybe Int -> Maybe Int -> LBParams
784 initLonelyBranch (def 2 -> periodsInf) (def 2 -> periodsSup) (def 1 -> minNodes) = LBParams periodsInf periodsSup minNodes
786 initSizeBranch :: Maybe Int -> SBParams
787 initSizeBranch (def 1 -> minSize) = SBParams minSize
789 initLonelyBranch' :: Maybe Int -> Maybe Int -> Maybe Int -> LBParams
790 initLonelyBranch' (def 0 -> periodsInf) (def 0 -> periodsSup) (def 1 -> minNodes) = LBParams periodsInf periodsSup minNodes
792 initLouvain :: Maybe Proximity -> LouvainParams
793 initLouvain (def defaultWeightedLogJaccard -> proxi) = LouvainParams proxi
795 initRelatedComponents :: Maybe Proximity -> RCParams
796 initRelatedComponents (def Filiation -> proxi) = RCParams proxi
798 initWeightedLogJaccard :: Maybe Double -> Maybe Double -> WLJParams
799 initWeightedLogJaccard (def 0 -> thr) (def 0.01 -> sens) = WLJParams thr sens
802 -- | To initialize a PhyloQueryBuild from given and default parameters
803 initPhyloQueryBuild :: Text -> Text -> Maybe Int -> Maybe Int -> Maybe Cluster -> Maybe [Metric] -> Maybe [Filter] -> Maybe Proximity -> Maybe Int -> Maybe Double -> Maybe Int -> Maybe Level -> Maybe Cluster -> PhyloQueryBuild
804 initPhyloQueryBuild name desc (def 5 -> grain) (def 3 -> steps) (def defaultFis -> cluster) (def [] -> metrics) (def [] -> filters)
805 (def defaultWeightedLogJaccard -> matching') (def 5 -> frame) (def 0.5 -> reBranchThr) (def 4 -> reBranchNth) (def 2 -> nthLevel) (def defaultRelatedComponents -> nthCluster) =
806 PhyloQueryBuild name desc grain steps cluster metrics filters matching' frame reBranchThr reBranchNth nthLevel nthCluster
809 -- | To initialize a PhyloQueryView default parameters
810 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
811 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) =
812 PhyloQueryView lvl f c d ms fs ts s em dm v
815 -- | To define some obvious boolean getters
816 shouldKeepMinorFis :: FisParams -> Bool
817 shouldKeepMinorFis = _fis_keepMinorFis
819 ----------------------------
820 -- | Default ressources | --
821 ----------------------------
825 defaultFis :: Cluster
826 defaultFis = Fis (initFis Nothing Nothing Nothing)
828 defaultLouvain :: Cluster
829 defaultLouvain = Louvain (initLouvain Nothing)
831 defaultRelatedComponents :: Cluster
832 defaultRelatedComponents = RelatedComponents (initRelatedComponents Nothing)
836 defaultLonelyBranch :: Filter
837 defaultLonelyBranch = LonelyBranch (initLonelyBranch Nothing Nothing Nothing)
839 defaultSizeBranch :: Filter
840 defaultSizeBranch = SizeBranch (initSizeBranch Nothing)
844 defaultPhyloParam :: PhyloParam
845 defaultPhyloParam = initPhyloParam Nothing Nothing Nothing
849 defaultHamming :: Proximity
850 defaultHamming = Hamming (initHamming Nothing)
852 defaultWeightedLogJaccard :: Proximity
853 defaultWeightedLogJaccard = WeightedLogJaccard (initWeightedLogJaccard Nothing Nothing)
857 defaultQueryBuild :: PhyloQueryBuild
858 defaultQueryBuild = initPhyloQueryBuild "Cesar et Cleôpatre" "An example of Phylomemy (french without accent)"
859 Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
861 defaultQueryView :: PhyloQueryView
862 defaultQueryView = initPhyloQueryView Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing
866 defaultSoftware :: Software
867 defaultSoftware = Software "Gargantext" "v4"
871 defaultPhyloVersion :: Text
872 defaultPhyloVersion = "v1"