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.LevelMaker
20 import Control.Lens hiding (both, Level)
21 import Data.List ((++), sort, concat, nub, words, zip)
22 import Data.Map (Map, (!), empty, restrictKeys, filterWithKey, singleton, union)
24 import Data.Text (Text, words)
25 import Data.Tuple.Extra
27 import Gargantext.Prelude hiding (head)
28 import Gargantext.Viz.Phylo.Aggregates.Cluster
29 import Gargantext.Viz.Phylo.Aggregates.Cooc
30 import Gargantext.Viz.Phylo
31 import Gargantext.Viz.Phylo.Tools
32 import Gargantext.Viz.Phylo.LinkMaker
33 import Gargantext.Viz.Phylo.BranchMaker
35 import qualified Data.List as List
36 import qualified Data.Map as Map
37 import qualified Data.Set as Set
38 import qualified Data.Text as Text
41 -- | A typeClass for polymorphic PhyloLevel functions
42 class PhyloLevelMaker aggregate
44 -- | To add a new Level of PhyloGroups to a Phylo based on a list of Aggregates
45 addPhyloLevel :: Level -> Map (Date,Date) [aggregate] -> Phylo -> Phylo
46 -- | To create a list of PhyloGroups based on a list of aggregates a
47 toPhyloGroups :: Level -> (Date,Date) -> [aggregate] -> Map (Date,Date) [aggregate] -> Phylo -> [PhyloGroup]
50 instance PhyloLevelMaker Cluster
52 --------------------------------------
53 -- | Level -> Map (Date,Date) [Cluster] -> Phylo -> Phylo
55 | lvl > 1 = toPhyloLevel lvl m p
56 | otherwise = panic ("[ERR][Viz.Phylo.Example.addPhyloLevel] No process declared for adding Clusters at level < 2")
57 --------------------------------------
58 -- | Level -> (Date,Date) -> [Cluster] -> Map (Date,Date) [Cluster] -> Phylo -> [PhyloGroup]
59 toPhyloGroups lvl (d,d') l m p = map (\(idx,cluster) -> clusterToGroup (d,d') lvl idx "" cluster m p) $ zip [1..] l
60 --------------------------------------
63 instance PhyloLevelMaker Fis
65 --------------------------------------
66 -- | Level -> Map (Date,Date) [Fis] -> Phylo -> Phylo
68 | lvl == 1 = toPhyloLevel lvl m p
69 | otherwise = panic ("[ERR][Viz.Phylo.Example.addPhyloLevel] No process declared for adding Fis at level <> 1")
70 --------------------------------------
71 -- | Level -> (Date,Date) -> [Fis] -> Map (Date,Date) [Fis] -> Phylo -> [PhyloGroup]
72 toPhyloGroups lvl (d,d') l m p = map (\(idx,fis) -> cliqueToGroup (d,d') lvl idx "" fis m p) $ zip [1..] l
73 --------------------------------------
76 instance PhyloLevelMaker Document
78 --------------------------------------
79 -- | Level -> Map (Date,Date) [Document] -> Phylo -> Phylo
81 | lvl < 0 = toPhyloLevel lvl m p
82 | otherwise = panic ("[ERR][Viz.Phylo.Example.addPhyloLevel] No process declared for adding Documents at level <> -1")
83 --------------------------------------
84 -- | Level -> (Date,Date) -> [Document] -> Map (Date,Date) [Fis] -> Phylo -> [PhyloGroup]
85 toPhyloGroups lvl (d,d') l m p = map (\(idx,ngram) -> ngramsToGroup (d,d') lvl idx ngram [ngram] p)
88 $ map (Text.words . text) l
89 --------------------------------------
92 -- | To transform a Cluster into a Phylogroup
93 clusterToGroup :: PhyloPeriodId -> Level -> Int -> Text -> Cluster -> Map (Date,Date) [Cluster] -> Phylo -> PhyloGroup
94 clusterToGroup prd lvl idx lbl groups m p =
95 PhyloGroup ((prd, lvl), idx) lbl ngrams empty cooc [] [] [] (map (\g -> (getGroupId g, 1)) groups)
97 --------------------------------------
99 ngrams = (sort . nub . concat) $ map getGroupNgrams groups
100 --------------------------------------
101 cooc :: Map (Int, Int) Double
102 cooc = filterWithKey (\k _ -> elem (fst k) ngrams && elem (snd k) ngrams)
105 $ getGroupsWithFilters 1 prd p
106 --------------------------------------
109 -- | To transform a Clique into a PhyloGroup
110 cliqueToGroup :: PhyloPeriodId -> Level -> Int -> Text -> (Clique,Support) -> Map (Date, Date) [Fis] -> Phylo -> PhyloGroup
111 cliqueToGroup prd lvl idx lbl fis m p =
112 PhyloGroup ((prd, lvl), idx) lbl ngrams (singleton "support" (fromIntegral $ snd fis)) cooc [] [] [] []
114 --------------------------------------
116 ngrams = sort $ map (\x -> ngramsToIdx x p)
119 --------------------------------------
120 cooc :: Map (Int, Int) Double
121 cooc = filterWithKey (\k _ -> elem (fst k) ngrams && elem (snd k) ngrams)
122 $ fisToCooc (restrictKeys m $ Set.fromList [prd]) p
123 --------------------------------------
126 -- | To transform a list of Ngrams into a PhyloGroup
127 ngramsToGroup :: PhyloPeriodId -> Level -> Int -> Text -> [Ngrams] -> Phylo -> PhyloGroup
128 ngramsToGroup prd lvl idx lbl ngrams p =
129 PhyloGroup ((prd, lvl), idx) lbl (sort $ map (\x -> ngramsToIdx x p) ngrams) empty empty [] [] [] []
132 -- | To traverse a Phylo and add a new PhyloLevel linked to a new list of PhyloGroups
133 toPhyloLevel :: PhyloLevelMaker a => Level -> Map (Date, Date) [a] -> Phylo -> Phylo
134 toPhyloLevel lvl m p = alterPhyloPeriods
135 (\period -> let pId = _phylo_periodId period
136 in over (phylo_periodLevels)
138 let groups = toPhyloGroups lvl pId (m ! pId) m p
139 in phyloLevels ++ [PhyloLevel (pId, lvl) groups]
143 -- | To incrementally add new Levels to a Phylo by making all the linking and aggregation tasks
144 toNthLevel :: Level -> (Proximity,[Double]) -> (Clustering,[Double]) -> (Proximity,[Double]) -> Phylo -> Phylo
145 toNthLevel lvlMax (prox,param1) (clus,param2) (prox',param3) p
147 | otherwise = toNthLevel lvlMax (prox,param1) (clus,param2) (prox',param3)
148 $ pairGroupsToGroups Childs (lvl + 1) (prox',param3)
149 $ pairGroupsToGroups Parents (lvl + 1) (prox',param3)
150 $ setPhyloBranches (lvl + 1)
151 $ setLevelLinks (lvl, lvl + 1)
152 $ addPhyloLevel (lvl + 1)
153 (phyloToClusters lvl (prox,param1) (clus,param2) p) p
155 --------------------------------------
158 --------------------------------------