Commit f3cb9626 authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

Merge branch 'dev-lts-16.26-upgrade' into dev-tree-reload

parents ba3cd903 8404a553
Pipeline #1313 failed with stage
from fpco/stack-build:lts-14.27 from fpco/stack-build:lts-16.26
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y git libigraph0-dev && \ apt-get install -y git libigraph0-dev && \
......
name: gargantext name: gargantext
version: '0.0.2.2.1' version: '0.0.2.3'
synopsis: Search, map, share synopsis: Search, map, share
description: Please see README.md description: Please see README.md
category: Data category: Data
...@@ -150,6 +150,7 @@ library: ...@@ -150,6 +150,7 @@ library:
- full-text-search - full-text-search
- fullstop - fullstop
- graphviz - graphviz
- hashable
- haskell-igraph - haskell-igraph
- hlcm - hlcm
- hsparql - hsparql
...@@ -188,6 +189,7 @@ library: ...@@ -188,6 +189,7 @@ library:
- product-profunctors - product-profunctors
- profunctors - profunctors
- protolude - protolude
- pretty-simple
- pureMD5 - pureMD5
- quickcheck-instances - quickcheck-instances
- rake - rake
......
...@@ -19,16 +19,17 @@ module Gargantext.API.Metrics ...@@ -19,16 +19,17 @@ module Gargantext.API.Metrics
where where
import Control.Lens import Control.Lens
import qualified Data.Map as Map
import Data.Text (Text) import Data.Text (Text)
import Data.Time (UTCTime) import Data.Time (UTCTime)
import Servant import Data.Vector (Vector)
import Gargantext.API.HashedResponse import Gargantext.API.HashedResponse
import Gargantext.API.Ngrams.NgramsTree import Gargantext.API.Ngrams.NgramsTree
import Gargantext.API.Ngrams.Types import Gargantext.API.Ngrams.Types
import Gargantext.API.Prelude (GargServer) import Gargantext.API.Prelude (GargServer)
import Gargantext.Core.Text.Metrics (Scored(..), {-normalizeGlobal,-} normalizeLocal)
import Gargantext.Core.Types (CorpusId, Limit, ListId, ListType(..)) import Gargantext.Core.Types (CorpusId, Limit, ListId, ListType(..))
import Gargantext.Core.Viz.Chart
import Gargantext.Core.Viz.Types
import Gargantext.Database.Action.Flow import Gargantext.Database.Action.Flow
import Gargantext.Database.Admin.Types.Hyperdata (HyperdataList(..), hl_chart, hl_pie, hl_scatter, hl_tree) import Gargantext.Database.Admin.Types.Hyperdata (HyperdataList(..), hl_chart, hl_pie, hl_scatter, hl_tree)
import Gargantext.Database.Admin.Types.Metrics (ChartMetrics(..), Metric(..), Metrics(..)) import Gargantext.Database.Admin.Types.Metrics (ChartMetrics(..), Metric(..), Metrics(..))
...@@ -39,9 +40,8 @@ import Gargantext.Database.Query.Table.Node.Error (HasNodeError) ...@@ -39,9 +40,8 @@ import Gargantext.Database.Query.Table.Node.Error (HasNodeError)
import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata) import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata)
import Gargantext.Database.Schema.Node (node_hyperdata) import Gargantext.Database.Schema.Node (node_hyperdata)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Core.Text.Metrics (Scored(..), {-normalizeGlobal,-} normalizeLocal) import Servant
import Gargantext.Core.Viz.Chart import qualified Data.HashMap.Strict as HashMap
import Gargantext.Core.Viz.Types
import qualified Gargantext.Database.Action.Metrics as Metrics import qualified Gargantext.Database.Action.Metrics as Metrics
------------------------------------------------------------- -------------------------------------------------------------
...@@ -78,7 +78,7 @@ getScatter cId maybeListId tabType _maybeLimit = do ...@@ -78,7 +78,7 @@ getScatter cId maybeListId tabType _maybeLimit = do
Nothing -> defaultList cId Nothing -> defaultList cId
node <- getNodeWith listId (Proxy :: Proxy HyperdataList) node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
let HyperdataList { _hl_scatter = scatterMap } = node ^. node_hyperdata let HyperdataList { _hl_scatter = scatterMap } = node ^. node_hyperdata
mChart = Map.lookup tabType scatterMap mChart = HashMap.lookup tabType scatterMap
chart <- case mChart of chart <- case mChart of
Just chart -> pure chart Just chart -> pure chart
...@@ -111,9 +111,9 @@ updateScatter' cId maybeListId tabType maybeLimit = do ...@@ -111,9 +111,9 @@ updateScatter' cId maybeListId tabType maybeLimit = do
(ngs', scores) <- Metrics.getMetrics cId maybeListId tabType maybeLimit (ngs', scores) <- Metrics.getMetrics cId maybeListId tabType maybeLimit
let let
metrics = map (\(Scored t s1 s2) -> Metric t s1 s2 (listType t ngs')) metrics = fmap (\(Scored t s1 s2) -> Metric (unNgramsTerm t) s1 s2 (listType t ngs'))
$ map normalizeLocal scores $ fmap normalizeLocal scores
listType t m = maybe (panic errorMsg) fst $ Map.lookup t m listType t m = maybe (panic errorMsg) fst $ HashMap.lookup t m
errorMsg = "API.Node.metrics: key absent" errorMsg = "API.Node.metrics: key absent"
listId <- case maybeListId of listId <- case maybeListId of
...@@ -122,7 +122,7 @@ updateScatter' cId maybeListId tabType maybeLimit = do ...@@ -122,7 +122,7 @@ updateScatter' cId maybeListId tabType maybeLimit = do
node <- getNodeWith listId (Proxy :: Proxy HyperdataList) node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
let hl = node ^. node_hyperdata let hl = node ^. node_hyperdata
scatterMap = hl ^. hl_scatter scatterMap = hl ^. hl_scatter
_ <- updateHyperdata listId $ hl { _hl_scatter = Map.insert tabType (Metrics metrics) scatterMap } _ <- updateHyperdata listId $ hl { _hl_scatter = HashMap.insert tabType (Metrics metrics) scatterMap }
pure $ Metrics metrics pure $ Metrics metrics
...@@ -172,7 +172,7 @@ getChart cId _start _end maybeListId tabType = do ...@@ -172,7 +172,7 @@ getChart cId _start _end maybeListId tabType = do
Nothing -> defaultList cId Nothing -> defaultList cId
node <- getNodeWith listId (Proxy :: Proxy HyperdataList) node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
let chartMap = node ^. node_hyperdata ^. hl_chart let chartMap = node ^. node_hyperdata ^. hl_chart
mChart = Map.lookup tabType chartMap mChart = HashMap.lookup tabType chartMap
chart <- case mChart of chart <- case mChart of
Just chart -> pure chart Just chart -> pure chart
...@@ -209,7 +209,7 @@ updateChart' cId maybeListId tabType _maybeLimit = do ...@@ -209,7 +209,7 @@ updateChart' cId maybeListId tabType _maybeLimit = do
let hl = node ^. node_hyperdata let hl = node ^. node_hyperdata
chartMap = hl ^. hl_chart chartMap = hl ^. hl_chart
h <- histoData cId h <- histoData cId
_ <- updateHyperdata listId $ hl { _hl_chart = Map.insert tabType (ChartMetrics h) chartMap } _ <- updateHyperdata listId $ hl { _hl_chart = HashMap.insert tabType (ChartMetrics h) chartMap }
pure $ ChartMetrics h pure $ ChartMetrics h
...@@ -258,7 +258,7 @@ getPie cId _start _end maybeListId tabType = do ...@@ -258,7 +258,7 @@ getPie cId _start _end maybeListId tabType = do
Nothing -> defaultList cId Nothing -> defaultList cId
node <- getNodeWith listId (Proxy :: Proxy HyperdataList) node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
let pieMap = node ^. node_hyperdata ^. hl_pie let pieMap = node ^. node_hyperdata ^. hl_pie
mChart = Map.lookup tabType pieMap mChart = HashMap.lookup tabType pieMap
chart <- case mChart of chart <- case mChart of
Just chart -> pure chart Just chart -> pure chart
...@@ -296,7 +296,7 @@ updatePie' cId maybeListId tabType _maybeLimit = do ...@@ -296,7 +296,7 @@ updatePie' cId maybeListId tabType _maybeLimit = do
pieMap = hl ^. hl_pie pieMap = hl ^. hl_pie
p <- chartData cId (ngramsTypeFromTabType tabType) MapTerm p <- chartData cId (ngramsTypeFromTabType tabType) MapTerm
_ <- updateHyperdata listId $ hl { _hl_pie = Map.insert tabType (ChartMetrics p) pieMap } _ <- updateHyperdata listId $ hl { _hl_pie = HashMap.insert tabType (ChartMetrics p) pieMap }
pure $ ChartMetrics p pure $ ChartMetrics p
...@@ -317,7 +317,7 @@ type TreeApi = Summary " Tree API" ...@@ -317,7 +317,7 @@ type TreeApi = Summary " Tree API"
:> QueryParam "list" ListId :> QueryParam "list" ListId
:> QueryParamR "ngramsType" TabType :> QueryParamR "ngramsType" TabType
:> QueryParamR "listType" ListType :> QueryParamR "listType" ListType
:> Get '[JSON] (HashedResponse (ChartMetrics [NgramsTree])) :> Get '[JSON] (HashedResponse (ChartMetrics (Vector NgramsTree)))
:<|> Summary "Tree Chart update" :<|> Summary "Tree Chart update"
:> QueryParam "list" ListId :> QueryParam "list" ListId
:> QueryParamR "ngramsType" TabType :> QueryParamR "ngramsType" TabType
...@@ -341,7 +341,7 @@ getTree :: FlowCmdM env err m ...@@ -341,7 +341,7 @@ getTree :: FlowCmdM env err m
-> Maybe ListId -> Maybe ListId
-> TabType -> TabType
-> ListType -> ListType
-> m (HashedResponse (ChartMetrics [NgramsTree])) -> m (HashedResponse (ChartMetrics (Vector NgramsTree)))
getTree cId _start _end maybeListId tabType listType = do getTree cId _start _end maybeListId tabType listType = do
listId <- case maybeListId of listId <- case maybeListId of
Just lid -> pure lid Just lid -> pure lid
...@@ -349,7 +349,7 @@ getTree cId _start _end maybeListId tabType listType = do ...@@ -349,7 +349,7 @@ getTree cId _start _end maybeListId tabType listType = do
node <- getNodeWith listId (Proxy :: Proxy HyperdataList) node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
let treeMap = node ^. node_hyperdata ^. hl_tree let treeMap = node ^. node_hyperdata ^. hl_tree
mChart = Map.lookup tabType treeMap mChart = HashMap.lookup tabType treeMap
chart <- case mChart of chart <- case mChart of
Just chart -> pure chart Just chart -> pure chart
...@@ -377,17 +377,17 @@ updateTree' :: FlowCmdM env err m => ...@@ -377,17 +377,17 @@ updateTree' :: FlowCmdM env err m =>
-> Maybe ListId -> Maybe ListId
-> TabType -> TabType
-> ListType -> ListType
-> m (ChartMetrics [NgramsTree]) -> m (ChartMetrics (Vector NgramsTree))
updateTree' cId maybeListId tabType listType = do updateTree' cId maybeListId tabType listType = do
listId <- case maybeListId of listId <- case maybeListId of
Just lid -> pure lid Just lid -> pure lid
Nothing -> defaultList cId Nothing -> defaultList cId
node <- getNodeWith listId (Proxy :: Proxy HyperdataList) node <- getNodeWith listId (Proxy :: Proxy HyperdataList)
let hl = node ^. node_hyperdata let hl = node ^. node_hyperdata
treeMap = hl ^. hl_tree treeMap = hl ^. hl_tree
t <- treeData cId (ngramsTypeFromTabType tabType) listType t <- treeData cId (ngramsTypeFromTabType tabType) listType
_ <- updateHyperdata listId $ hl { _hl_tree = Map.insert tabType (ChartMetrics t) treeMap } _ <- updateHyperdata listId $ hl { _hl_tree = HashMap.insert tabType (ChartMetrics t) treeMap }
pure $ ChartMetrics t pure $ ChartMetrics t
......
...@@ -535,7 +535,7 @@ getTableNgrams _nType nId tabType listId limit_ offset ...@@ -535,7 +535,7 @@ getTableNgrams _nType nId tabType listId limit_ offset
setScores :: forall t. Each t t NgramsElement NgramsElement => Bool -> t -> m t setScores :: forall t. Each t t NgramsElement NgramsElement => Bool -> t -> m t
setScores False table = pure table setScores False table = pure table
setScores True table = do setScores True table = do
let ngrams_terms = unNgramsTerm <$> (table ^.. each . ne_ngrams) let ngrams_terms = table ^.. each . ne_ngrams
t1 <- getTime' t1 <- getTime'
occurrences <- getOccByNgramsOnlyFast' nId occurrences <- getOccByNgramsOnlyFast' nId
listId listId
...@@ -552,7 +552,7 @@ getTableNgrams _nType nId tabType listId limit_ offset ...@@ -552,7 +552,7 @@ getTableNgrams _nType nId tabType listId limit_ offset
ngrams_terms ngrams_terms
-} -}
let let
setOcc ne = ne & ne_occurrences .~ sumOf (at (unNgramsTerm (ne ^. ne_ngrams)) . _Just) occurrences setOcc ne = ne & ne_occurrences .~ sumOf (at (ne ^. ne_ngrams) . _Just) occurrences
pure $ table & each %~ setOcc pure $ table & each %~ setOcc
--------------------------------------- ---------------------------------------
...@@ -594,13 +594,13 @@ scoresRecomputeTableNgrams nId tabType listId = do ...@@ -594,13 +594,13 @@ scoresRecomputeTableNgrams nId tabType listId = do
setScores :: forall t. Each t t NgramsElement NgramsElement => t -> m t setScores :: forall t. Each t t NgramsElement NgramsElement => t -> m t
setScores table = do setScores table = do
let ngrams_terms = unNgramsTerm <$> (table ^.. each . ne_ngrams) let ngrams_terms = table ^.. each . ne_ngrams
occurrences <- getOccByNgramsOnlyFast' nId occurrences <- getOccByNgramsOnlyFast' nId
listId listId
ngramsType ngramsType
ngrams_terms ngrams_terms
let let
setOcc ne = ne & ne_occurrences .~ sumOf (at (unNgramsTerm (ne ^. ne_ngrams)) . _Just) occurrences setOcc ne = ne & ne_occurrences .~ sumOf (at (ne ^. ne_ngrams) . _Just) occurrences
pure $ table & each %~ setOcc pure $ table & each %~ setOcc
......
...@@ -15,23 +15,21 @@ module Gargantext.API.Ngrams.NgramsTree ...@@ -15,23 +15,21 @@ module Gargantext.API.Ngrams.NgramsTree
where where
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.Text (Text) import Data.HashMap.Strict (HashMap)
import Data.Tree
import Data.Maybe (catMaybes) import Data.Maybe (catMaybes)
import Data.Map (Map)
import Data.Set (Set) import Data.Set (Set)
import Data.Swagger import Data.Swagger
import qualified Data.Set as Set import Data.Text (Text)
import qualified Data.Map as Map import Data.Tree
import qualified Data.List as List
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Test.QuickCheck
import Gargantext.Prelude
import Gargantext.API.Ngrams.Types import Gargantext.API.Ngrams.Types
import Gargantext.Core.Types (ListType(..), NodeId) import Gargantext.Core.Types (ListType(..), NodeId)
import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger) import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger)
import Gargantext.Prelude
import Test.QuickCheck
import qualified Data.HashMap.Strict as HashMap
import qualified Data.List as List
import qualified Data.Set as Set
type Children = Text type Children = Text
type Root = Text type Root = Text
...@@ -42,8 +40,8 @@ data NgramsTree = NgramsTree { mt_label :: Text ...@@ -42,8 +40,8 @@ data NgramsTree = NgramsTree { mt_label :: Text
} }
deriving (Generic, Show) deriving (Generic, Show)
toNgramsTree :: Tree (Text,Double) -> NgramsTree toNgramsTree :: Tree (NgramsTerm,Double) -> NgramsTree
toNgramsTree (Node (l,v) xs) = NgramsTree l v (map toNgramsTree xs) toNgramsTree (Node (NgramsTerm l,v) xs) = NgramsTree l v (map toNgramsTree xs)
deriveJSON (unPrefix "mt_") ''NgramsTree deriveJSON (unPrefix "mt_") ''NgramsTree
...@@ -53,24 +51,27 @@ instance Arbitrary NgramsTree ...@@ -53,24 +51,27 @@ instance Arbitrary NgramsTree
where where
arbitrary = NgramsTree <$> arbitrary <*> arbitrary <*> arbitrary arbitrary = NgramsTree <$> arbitrary <*> arbitrary <*> arbitrary
toTree :: ListType -> Map Text (Set NodeId) -> Map Text NgramsRepoElement -> [NgramsTree] toTree :: ListType
-> HashMap NgramsTerm (Set NodeId)
-> HashMap NgramsTerm NgramsRepoElement
-> [NgramsTree]
toTree lt vs m = map toNgramsTree $ unfoldForest buildNode roots toTree lt vs m = map toNgramsTree $ unfoldForest buildNode roots
where where
buildNode r = maybe ((r, value r),[]) buildNode r = maybe ((r, value r),[])
(\x -> ((r, value r), unNgramsTerm <$> (mSetToList $ _nre_children x))) (\x -> ((r, value r), mSetToList $ _nre_children x))
(Map.lookup r m) (HashMap.lookup r m)
value l = maybe 0 (fromIntegral . Set.size) $ Map.lookup l vs value l = maybe 0 (fromIntegral . Set.size) $ HashMap.lookup l vs
rootsCandidates :: [NgramsTerm] rootsCandidates :: [NgramsTerm]
rootsCandidates = catMaybes rootsCandidates = catMaybes
$ List.nub $ List.nub
$ map (\(c, c') -> case _nre_root c' of $ map (\(c, c') -> case _nre_root c' of
Nothing -> Just $ NgramsTerm c Nothing -> Just c
_ -> _nre_root c') (Map.toList m) _ -> _nre_root c') (HashMap.toList m)
roots = map fst roots = map fst
$ filter (\(_,l) -> l == lt) $ filter (\(_,l) -> l == lt)
$ catMaybes $ catMaybes
$ map (\c -> (,) <$> Just c <*> (_nre_list <$> Map.lookup c m)) $ map (\c -> (,) <$> Just c <*> (_nre_list <$> HashMap.lookup c m))
$ (unNgramsTerm <$> rootsCandidates) $ rootsCandidates
...@@ -9,29 +9,30 @@ Portability : POSIX ...@@ -9,29 +9,30 @@ Portability : POSIX
-} -}
{-# LANGUAGE TypeFamilies #-}
module Gargantext.API.Ngrams.Tools module Gargantext.API.Ngrams.Tools
where where
import Control.Concurrent import Control.Concurrent
import Control.Lens (_Just, (^.), at, view) import Control.Lens (_Just, (^.), at, view, At, Index, IxValue)
import Control.Monad.Reader import Control.Monad.Reader
import Data.Map.Strict (Map) import Data.HashMap.Strict (HashMap)
import qualified Data.Map.Strict as Map import Data.Hashable (Hashable)
import qualified Data.Set as Set
import Data.Set (Set) import Data.Set (Set)
import Data.Text (Text)
import Data.Validity import Data.Validity
import Gargantext.API.Ngrams.Types import Gargantext.API.Ngrams.Types
import Gargantext.Core.Types (ListType(..), NodeId, ListId) import Gargantext.Core.Types (ListType(..), NodeId, ListId)
import Gargantext.Database.Schema.Ngrams (NgramsType) import Gargantext.Database.Schema.Ngrams (NgramsType)
import Gargantext.Prelude import Gargantext.Prelude
import qualified Data.HashMap.Strict as HM
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
mergeNgramsElement :: NgramsRepoElement -> NgramsRepoElement -> NgramsRepoElement mergeNgramsElement :: NgramsRepoElement -> NgramsRepoElement -> NgramsRepoElement
mergeNgramsElement _neOld neNew = neNew mergeNgramsElement _neOld neNew = neNew
type RootTerm = Text type RootTerm = NgramsTerm
getRepo :: RepoCmdM env err m => m NgramsRepo getRepo :: RepoCmdM env err m => m NgramsRepo
getRepo = do getRepo = do
...@@ -39,87 +40,105 @@ getRepo = do ...@@ -39,87 +40,105 @@ getRepo = do
liftBase $ readMVar v liftBase $ readMVar v
listNgramsFromRepo :: [ListId] -> NgramsType listNgramsFromRepo :: [ListId] -> NgramsType
-> NgramsRepo -> Map Text NgramsRepoElement -> NgramsRepo -> HashMap NgramsTerm NgramsRepoElement
listNgramsFromRepo nodeIds ngramsType repo = Map.mapKeys unNgramsTerm ngrams listNgramsFromRepo nodeIds ngramsType repo = ngrams
where where
ngramsMap = repo ^. r_state . at ngramsType . _Just ngramsMap = repo ^. r_state . at ngramsType . _Just
ngrams = Map.unionsWith mergeNgramsElement -- TODO HashMap linked
ngrams = HM.fromList $ Map.toList $ Map.unionsWith mergeNgramsElement
[ ngramsMap ^. at nodeId . _Just | nodeId <- nodeIds ] [ ngramsMap ^. at nodeId . _Just | nodeId <- nodeIds ]
-- TODO-ACCESS: We want to do the security check before entering here. -- TODO-ACCESS: We want to do the security check before entering here.
-- Add a static capability parameter would be nice. -- Add a static capability parameter would be nice.
-- Ideally this is the access to `repoVar` which needs to -- Ideally this is the access to `repoVar` which needs to
-- be properly guarded. -- be properly guarded.
getListNgrams :: RepoCmdM env err m getListNgrams :: RepoCmdM env err m
=> [ListId] -> NgramsType => [ListId] -> NgramsType
-> m (Map Text NgramsRepoElement) -> m (HashMap NgramsTerm NgramsRepoElement)
getListNgrams nodeIds ngramsType = listNgramsFromRepo nodeIds ngramsType <$> getRepo getListNgrams nodeIds ngramsType = listNgramsFromRepo nodeIds ngramsType <$> getRepo
getTermsWith :: (RepoCmdM env err m, Ord a) getTermsWith :: (RepoCmdM env err m, Eq a, Hashable a)
=> (Text -> a ) -> [ListId] => (NgramsTerm -> a) -> [ListId]
-> NgramsType -> ListType -> NgramsType -> ListType
-> m (Map a [a]) -> m (HashMap a [a])
getTermsWith f ls ngt lt = Map.fromListWith (<>) getTermsWith f ls ngt lt = HM.fromListWith (<>)
<$> map (toTreeWith f) <$> map toTreeWith
<$> Map.toList <$> HM.toList
<$> Map.filter (\f' -> (fst f') == lt) <$> HM.filter (\f' -> fst f' == lt)
<$> mapTermListRoot ls ngt <$> mapTermListRoot ls ngt
<$> getRepo <$> getRepo
where where
toTreeWith f'' (t, (_lt, maybeRoot)) = case maybeRoot of toTreeWith (t, (_lt, maybeRoot)) = case maybeRoot of
Nothing -> (f'' t, []) Nothing -> (f t, [])
Just r -> (f'' r, map f'' [t]) Just r -> (f r, [f t])
mapTermListRoot :: [ListId] mapTermListRoot :: [ListId]
-> NgramsType -> NgramsType
-> NgramsRepo -> NgramsRepo
-> Map Text (ListType, (Maybe Text)) -> HashMap NgramsTerm (ListType, Maybe NgramsTerm)
mapTermListRoot nodeIds ngramsType repo = mapTermListRoot nodeIds ngramsType repo =
Map.fromList [ (t, (_nre_list nre, unNgramsTerm <$> _nre_root nre)) (\nre -> (_nre_list nre, _nre_root nre))
| (t, nre) <- Map.toList ngrams <$> listNgramsFromRepo nodeIds ngramsType repo
]
where ngrams = listNgramsFromRepo nodeIds ngramsType repo filterListWithRootHashMap :: ListType
-> HashMap NgramsTerm (ListType, Maybe NgramsTerm)
-> HashMap NgramsTerm (Maybe RootTerm)
filterListWithRootHashMap lt m = snd <$> HM.filter isMapTerm m
where
isMapTerm (l, maybeRoot) = case maybeRoot of
Nothing -> l == lt
Just r -> case HM.lookup r m of
Nothing -> panic $ "Garg.API.Ngrams.Tools: filterWithRoot, unknown key: " <> unNgramsTerm r
Just (l',_) -> l' == lt
filterListWithRoot :: ListType filterListWithRoot :: ListType
-> Map Text (ListType, Maybe Text) -> HashMap NgramsTerm (ListType, Maybe NgramsTerm)
-> Map Text (Maybe RootTerm) -> HashMap NgramsTerm (Maybe RootTerm)
filterListWithRoot lt m = Map.fromList filterListWithRoot lt m = snd <$> HM.filter isMapTerm m
$ map (\(t,(_,r)) -> (t,r))
$ filter isMapTerm (Map.toList m)
where where
isMapTerm (_t,(l, maybeRoot)) = case maybeRoot of isMapTerm (l, maybeRoot) = case maybeRoot of
Nothing -> l == lt Nothing -> l == lt
Just r -> case Map.lookup r m of Just r -> case HM.lookup r m of
Nothing -> panic $ "Garg.API.Ngrams.Tools: filterWithRoot, unknown key: " <> r Nothing -> panic $ "Garg.API.Ngrams.Tools: filterWithRoot, unknown key: " <> unNgramsTerm r
Just (l',_) -> l' == lt Just (l',_) -> l' == lt
groupNodesByNgrams :: Map Text (Maybe RootTerm) groupNodesByNgrams :: ( At root_map
-> Map Text (Set NodeId) , Index root_map ~ NgramsTerm
-> Map Text (Set NodeId) , IxValue root_map ~ Maybe RootTerm
groupNodesByNgrams syn occs = Map.fromListWith (<>) occs' )
=> root_map
-> HashMap NgramsTerm (Set NodeId)
-> HashMap NgramsTerm (Set NodeId)
groupNodesByNgrams syn occs = HM.fromListWith (<>) occs'
where where
occs' = map toSyn (Map.toList occs) occs' = map toSyn (HM.toList occs)
toSyn (t,ns) = case Map.lookup t syn of toSyn (t,ns) = case syn ^. at t of
Nothing -> panic $ "[Garg.API.Ngrams.Tools.groupNodesByNgrams] unknown key: " <> t Nothing -> panic $ "[Garg.API.Ngrams.Tools.groupNodesByNgrams] unknown key: " <> unNgramsTerm t
Just r -> case r of Just r -> case r of
Nothing -> (t, ns) Nothing -> (t, ns)
Just r' -> (r',ns) Just r' -> (r',ns)
data Diagonal = Diagonal Bool data Diagonal = Diagonal Bool
getCoocByNgrams :: Diagonal -> Map Text (Set NodeId) -> Map (Text, Text) Int getCoocByNgrams :: Diagonal -> HashMap NgramsTerm (Set NodeId) -> HashMap (NgramsTerm, NgramsTerm) Int
getCoocByNgrams = getCoocByNgrams' identity getCoocByNgrams = getCoocByNgrams' identity
getCoocByNgrams' :: (Ord a, Ord c) => (b -> Set c) -> Diagonal -> Map a b -> Map (a, a) Int getCoocByNgrams' :: (Hashable a, Ord a, Ord c) => (b -> Set c) -> Diagonal -> HashMap a b -> HashMap (a, a) Int
getCoocByNgrams' f (Diagonal diag) m = getCoocByNgrams' f (Diagonal diag) m =
Map.fromList [( (t1,t2) HM.fromList [( (t1,t2)
, maybe 0 Set.size $ Set.intersection , maybe 0 Set.size $ Set.intersection
<$> (fmap f $ Map.lookup t1 m) <$> (fmap f $ HM.lookup t1 m)
<*> (fmap f $ Map.lookup t2 m) <*> (fmap f $ HM.lookup t2 m)
) | (t1,t2) <- case diag of )
True -> [ (x,y) | x <- Map.keys m, y <- Map.keys m, x <= y] | (t1,t2) <- if diag then
False -> listToCombi identity (Map.keys m) [ (x,y) | x <- ks, y <- ks, x <= y] -- TODO if we keep a Data.Map here it might be
] -- more efficient to enumerate all the y <= x.
else
listToCombi identity ks
]
where ks = HM.keys m
...@@ -19,6 +19,7 @@ import Data.Aeson hiding ((.=)) ...@@ -19,6 +19,7 @@ import Data.Aeson hiding ((.=))
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Foldable import Data.Foldable
import Data.Hashable (Hashable)
import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap import qualified Data.HashMap.Strict.InsOrd as InsOrdHashMap
import qualified Data.List as List import qualified Data.List as List
import Data.Map.Strict (Map) import Data.Map.Strict (Map)
...@@ -46,6 +47,7 @@ import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary) ...@@ -46,6 +47,7 @@ import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
import Protolude (maybeToEither) import Protolude (maybeToEither)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Prelude.Crypto.Hash (IsHashable(..))
import Gargantext.Core.Text (size) import Gargantext.Core.Text (size)
import Gargantext.Core.Types (ListType(..), ListId, NodeId) import Gargantext.Core.Types (ListType(..), ListId, NodeId)
import Gargantext.Core.Types (TODO) import Gargantext.Core.Types (TODO)
...@@ -60,6 +62,9 @@ data TabType = Docs | Trash | MoreFav | MoreTrash ...@@ -60,6 +62,9 @@ data TabType = Docs | Trash | MoreFav | MoreTrash
| Contacts | Contacts
deriving (Bounded, Enum, Eq, Generic, Ord, Show) deriving (Bounded, Enum, Eq, Generic, Ord, Show)
instance Hashable TabType
instance FromHttpApiData TabType instance FromHttpApiData TabType
where where
parseUrlPiece "Docs" = pure Docs parseUrlPiece "Docs" = pure Docs
...@@ -120,7 +125,13 @@ instance (ToJSONKey a, ToSchema a) => ToSchema (MSet a) where ...@@ -120,7 +125,13 @@ instance (ToJSONKey a, ToSchema a) => ToSchema (MSet a) where
------------------------------------------------------------------------ ------------------------------------------------------------------------
newtype NgramsTerm = NgramsTerm { unNgramsTerm :: Text } newtype NgramsTerm = NgramsTerm { unNgramsTerm :: Text }
deriving (Ord, Eq, Show, Generic, ToJSONKey, ToJSON, FromJSON, Semigroup, Arbitrary, Serialise, ToSchema) deriving (Ord, Eq, Show, Generic, ToJSONKey, ToJSON, FromJSON, Semigroup, Arbitrary, Serialise, ToSchema, Hashable)
instance IsHashable NgramsTerm where
hash (NgramsTerm t) = hash t
instance Monoid NgramsTerm where
mempty = NgramsTerm ""
instance FromJSONKey NgramsTerm where instance FromJSONKey NgramsTerm where
fromJSONKey = FromJSONKeyTextParser $ \t -> pure $ NgramsTerm $ strip t fromJSONKey = FromJSONKeyTextParser $ \t -> pure $ NgramsTerm $ strip t
...@@ -342,11 +353,13 @@ isRem = (== remPatch) ...@@ -342,11 +353,13 @@ isRem = (== remPatch)
type PatchMap = PM.PatchMap type PatchMap = PM.PatchMap
newtype PatchMSet a = PatchMSet (PatchMap a AddRem) newtype PatchMSet a = PatchMSet (PatchMap a AddRem)
deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group, deriving (Eq, Show, Generic, Validity, Semigroup, Monoid, Group,
Transformable, Composable) Transformable, Composable)
unPatchMSet :: PatchMSet a -> PatchMap a AddRem
unPatchMSet (PatchMSet a) = a
type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ()) type ConflictResolutionPatchMSet a = a -> ConflictResolutionReplace (Maybe ())
type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a type instance ConflictResolution (PatchMSet a) = ConflictResolutionPatchMSet a
...@@ -644,7 +657,7 @@ data Repo s p = Repo ...@@ -644,7 +657,7 @@ data Repo s p = Repo
, _r_history :: ![p] , _r_history :: ![p]
-- first patch in the list is the most recent -- first patch in the list is the most recent
} }
deriving (Generic) deriving (Generic, Show)
instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where instance (FromJSON s, FromJSON p) => FromJSON (Repo s p) where
parseJSON = genericParseJSON $ unPrefix "_r_" parseJSON = genericParseJSON $ unPrefix "_r_"
......
...@@ -16,11 +16,9 @@ Main exports of Gargantext: ...@@ -16,11 +16,9 @@ Main exports of Gargantext:
module Gargantext.API.Node.Corpus.Export module Gargantext.API.Node.Corpus.Export
where where
import Data.Map (Map) import Data.Map (Map)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Set (Set) import Data.Set (Set)
import Data.Text (Text)
import Gargantext.API.Node.Corpus.Export.Types import Gargantext.API.Node.Corpus.Export.Types
import Gargantext.API.Ngrams.Types import Gargantext.API.Ngrams.Types
import Gargantext.API.Ngrams.Tools (filterListWithRoot, mapTermListRoot, getRepo) import Gargantext.API.Ngrams.Tools (filterListWithRoot, mapTermListRoot, getRepo)
...@@ -41,6 +39,7 @@ import Gargantext.Prelude ...@@ -41,6 +39,7 @@ import Gargantext.Prelude
import qualified Data.List as List import qualified Data.List as List
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Set as Set import qualified Data.Set as Set
import qualified Data.HashMap.Strict as HashMap
-------------------------------------------------- --------------------------------------------------
-- | Hashes are ordered by Set -- | Hashes are ordered by Set
...@@ -62,13 +61,13 @@ getCorpus cId lId nt' = do ...@@ -62,13 +61,13 @@ getCorpus cId lId nt' = do
ngs <- getNodeNgrams cId lId nt repo ngs <- getNodeNgrams cId lId nt repo
let -- uniqId is hash computed already for each document imported in database let -- uniqId is hash computed already for each document imported in database
r = Map.intersectionWith (\a b -> Document a (Ngrams (Set.toList b) (hash b)) (d_hash a b) r = Map.intersectionWith (\a b -> Document a (Ngrams (Set.toList b) (hash b)) (d_hash a b)
) ns ngs ) ns (Map.map (Set.map unNgramsTerm) ngs)
where where
d_hash a b = hash [ fromMaybe "" (_hd_uniqId $ _node_hyperdata a) d_hash a b = hash [ fromMaybe "" (_hd_uniqId $ _node_hyperdata a)
, hash b , hash b
] ]
pure $ Corpus (Map.elems r) (hash $ List.map _d_hash pure $ Corpus (Map.elems r) (hash $ List.map _d_hash
$ Map.elems r $ Map.elems r
) )
getNodeNgrams :: HasNodeError err getNodeNgrams :: HasNodeError err
...@@ -76,7 +75,7 @@ getNodeNgrams :: HasNodeError err ...@@ -76,7 +75,7 @@ getNodeNgrams :: HasNodeError err
-> Maybe ListId -> Maybe ListId
-> NgramsType -> NgramsType
-> NgramsRepo -> NgramsRepo
-> Cmd err (Map NodeId (Set Text)) -> Cmd err (Map NodeId (Set NgramsTerm))
getNodeNgrams cId lId' nt repo = do getNodeNgrams cId lId' nt repo = do
lId <- case lId' of lId <- case lId' of
Nothing -> defaultList cId Nothing -> defaultList cId
...@@ -84,9 +83,10 @@ getNodeNgrams cId lId' nt repo = do ...@@ -84,9 +83,10 @@ getNodeNgrams cId lId' nt repo = do
lIds <- selectNodesWithUsername NodeList userMaster lIds <- selectNodesWithUsername NodeList userMaster
let ngs = filterListWithRoot MapTerm $ mapTermListRoot [lId] nt repo let ngs = filterListWithRoot MapTerm $ mapTermListRoot [lId] nt repo
r <- getNgramsByNodeOnlyUser cId (lIds <> [lId]) nt (Map.keys ngs) -- TODO HashMap
r <- getNgramsByNodeOnlyUser cId (lIds <> [lId]) nt (HashMap.keys ngs)
pure r pure r
-- TODO -- TODO
-- Exports List -- Exports List
-- Version number of the list -- Version number of the list
\ No newline at end of file
...@@ -20,7 +20,7 @@ import qualified Data.List as DL ...@@ -20,7 +20,7 @@ import qualified Data.List as DL
import qualified Data.Vector as DV import qualified Data.Vector as DV
import qualified Data.Map as M import qualified Data.Map as M
import Gargantext.Core.Text.Metrics.Freq as F import Gargantext.Core.Text.Metrics.Utils as Utils
import Gargantext.Core.Text.Corpus.Parsers.CSV as CSV import Gargantext.Core.Text.Corpus.Parsers.CSV as CSV
data School = School { school_shortName :: Text data School = School { school_shortName :: Text
...@@ -115,7 +115,7 @@ publisBySchool hal_data' = Gargantext.Prelude.map (\(i,n) -> (M.lookup i mapIdSc ...@@ -115,7 +115,7 @@ publisBySchool hal_data' = Gargantext.Prelude.map (\(i,n) -> (M.lookup i mapIdSc
$ DL.reverse $ DL.reverse
$ DL.sortOn snd $ DL.sortOn snd
$ M.toList $ M.toList
$ F.freq $ Utils.freq
$ DL.concat $ DL.concat
$ DV.toList $ DV.toList
$ DV.map (\n -> splitOn ( ", ") (csvHal_instStructId_i n) ) $ DV.map (\n -> splitOn ( ", ") (csvHal_instStructId_i n) )
......
This diff is collapsed.
...@@ -19,61 +19,49 @@ module Gargantext.Core.Text.List.Group ...@@ -19,61 +19,49 @@ module Gargantext.Core.Text.List.Group
where where
import Control.Lens (view) import Control.Lens (view)
import Data.Map (Map) import Data.HashMap.Strict (HashMap)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Monoid (Monoid, mempty) import Data.Monoid (Monoid, mempty)
import Data.Text (Text) import Gargantext.API.Ngrams.Types (NgramsTerm(..))
import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Core.Text.List.Group.Prelude import Gargantext.Core.Text.List.Group.Prelude
import Gargantext.Core.Text.List.Group.WithStem
import Gargantext.Core.Text.List.Group.WithScores import Gargantext.Core.Text.List.Group.WithScores
import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Prelude import Gargantext.Prelude
import qualified Data.Map as Map import qualified Data.HashMap.Strict as HashMap
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | TODO add group with stemming toGroupedTree :: (Ord a, Monoid a)
toGroupedTree :: (Ord a, Monoid a, GroupWithStem a) => FlowCont NgramsTerm FlowListScores
=> GroupParams -> HashMap NgramsTerm a
-> FlowCont Text FlowListScores -> FlowCont NgramsTerm (GroupedTreeScores a)
-> Map Text a toGroupedTree flc scores =
-- -> Map Text (GroupedTreeScores (Set NodeId)) groupWithScores' flc scoring
-> FlowCont Text (GroupedTreeScores a)
toGroupedTree groupParams flc scores = {-view flc_scores-} flow2
where where
flow1 = groupWithScores' flc scoring scoring t = fromMaybe mempty $ HashMap.lookup t scores
scoring t = fromMaybe mempty $ Map.lookup t scores
flow2 = case (view flc_cont flow1) == Map.empty of
True -> flow1
False -> groupWithStem' groupParams flow1
------------------------------------------------------------------------ ------------------------------------------------------------------------
setScoresWithMap :: (Ord a, Ord b, Monoid b) => Map Text b setScoresWithMap :: (Ord a, Ord b, Monoid b) => HashMap NgramsTerm b
-> Map Text (GroupedTreeScores a) -> HashMap NgramsTerm (GroupedTreeScores a)
-> Map Text (GroupedTreeScores b) -> HashMap NgramsTerm (GroupedTreeScores b)
setScoresWithMap m = setScoresWith (score m) setScoresWithMap m = setScoresWith (score m)
where where
score m' t = case Map.lookup t m' of score m' t = case HashMap.lookup t m' of
Nothing -> mempty Nothing -> mempty
Just r -> r Just r -> r
setScoresWith :: (Ord a, Ord b) setScoresWith :: (Ord a, Ord b)
=> (Text -> b) => (NgramsTerm -> b)
-> Map Text (GroupedTreeScores a) -> HashMap NgramsTerm (GroupedTreeScores a)
-> Map Text (GroupedTreeScores b) -> HashMap NgramsTerm (GroupedTreeScores b)
{- {-
-- | This Type level lenses solution does not work -- | This Type level lenses solution does not work
setScoresWith f = Map.mapWithKey (\k v -> over gts'_children (setScoresWith f) setScoresWith f = Map.mapWithKey (\k v -> over gts'_children (setScoresWith f)
$ set gts'_score (f k) v $ set gts'_score (f k) v
) )
-} -}
setScoresWith f = Map.mapWithKey (\k v -> v { _gts'_score = f k setScoresWith f = HashMap.mapWithKey (\k v -> v { _gts'_score = f k
, _gts'_children = setScoresWith f , _gts'_children = setScoresWith f
$ view gts'_children v $ view gts'_children v
} }
) )
------------------------------------------------------------------------ ------------------------------------------------------------------------
...@@ -17,29 +17,28 @@ module Gargantext.Core.Text.List.Group.Prelude ...@@ -17,29 +17,28 @@ module Gargantext.Core.Text.List.Group.Prelude
where where
import Control.Lens (makeLenses, view, set, over) import Control.Lens (makeLenses, view, set, over)
import Data.HashMap.Strict (HashMap)
import Data.Maybe (fromMaybe)
import Data.Monoid import Data.Monoid
import Data.Semigroup import Data.Semigroup
import Data.Set (Set) import Data.Set (Set)
import Data.Text (Text) import Gargantext.API.Ngrams.Types (NgramsElement, mkNgramsElement, NgramsTerm(..), RootParent(..), mSetFromList)
import Data.Maybe (fromMaybe) import Gargantext.Core.Text.Metrics (Scored(..), scored_genInc)
import Data.Map (Map)
import Gargantext.Core.Types (ListType(..)) import Gargantext.Core.Types (ListType(..))
import Gargantext.Database.Admin.Types.Node (NodeId) import Gargantext.Database.Admin.Types.Node (NodeId)
import Gargantext.Core.Text.Metrics (Scored(..), scored_genInc)
import Gargantext.API.Ngrams.Types (NgramsElement, mkNgramsElement, NgramsTerm(..), RootParent(..), mSetFromList)
import Gargantext.Prelude import Gargantext.Prelude
import qualified Data.Set as Set import qualified Data.HashMap.Strict as HashMap
import qualified Data.Map as Map
import qualified Data.List as List import qualified Data.List as List
import qualified Data.Set as Set
type Stem = Text type Stem = NgramsTerm
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Main Types to group With Scores but preserving Tree dependencies -- | Main Types to group With Scores but preserving Tree dependencies
-- Therefore there is a need of Tree of GroupedTextScores -- Therefore there is a need of Tree of GroupedTextScores
-- to target continuation type for the flow (FlowCont Text GroupedTreeScores) -- to target continuation type for the flow (FlowCont Text GroupedTreeScores)
data GroupedTreeScores score = data GroupedTreeScores score =
GroupedTreeScores { _gts'_listType :: !(Maybe ListType) GroupedTreeScores { _gts'_listType :: !(Maybe ListType)
, _gts'_children :: !(Map Text (GroupedTreeScores score)) , _gts'_children :: !(HashMap NgramsTerm (GroupedTreeScores score))
, _gts'_score :: !score , _gts'_score :: !score
} deriving (Show, Ord, Eq) } deriving (Show, Ord, Eq)
...@@ -76,7 +75,7 @@ class ToNgramsElement a where ...@@ -76,7 +75,7 @@ class ToNgramsElement a where
toNgramsElement :: a -> [NgramsElement] toNgramsElement :: a -> [NgramsElement]
class HasTerms a where class HasTerms a where
hasTerms :: a -> Set Text hasTerms :: a -> Set NgramsTerm
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Instances declartion for (GroupedTreeScores a) -- | Instances declartion for (GroupedTreeScores a)
...@@ -87,8 +86,8 @@ instance SetListType (GroupedTreeScores a) where ...@@ -87,8 +86,8 @@ instance SetListType (GroupedTreeScores a) where
setListType lt g = over gts'_children (setListType lt) setListType lt g = over gts'_children (setListType lt)
$ set gts'_listType lt g $ set gts'_listType lt g
instance SetListType (Map Text (GroupedTreeScores a)) where instance SetListType (HashMap NgramsTerm (GroupedTreeScores a)) where
setListType lt = Map.map (set gts'_listType lt) setListType lt = HashMap.map (set gts'_listType lt)
------ ------
...@@ -99,7 +98,7 @@ instance ViewScores (GroupedTreeScores Double) Double where ...@@ -99,7 +98,7 @@ instance ViewScores (GroupedTreeScores Double) Double where
viewScores g = sum $ parent : children viewScores g = sum $ parent : children
where where
parent = view gts'_score g parent = view gts'_score g
children = map viewScores $ Map.elems $ view gts'_children g children = map viewScores $ HashMap.elems $ view gts'_children g
instance ViewScore (GroupedTreeScores (Set NodeId)) Int where instance ViewScore (GroupedTreeScores (Set NodeId)) Int where
...@@ -109,57 +108,55 @@ instance ViewScores (GroupedTreeScores (Set NodeId)) (Set NodeId) where ...@@ -109,57 +108,55 @@ instance ViewScores (GroupedTreeScores (Set NodeId)) (Set NodeId) where
viewScores g = Set.unions $ parent : children viewScores g = Set.unions $ parent : children
where where
parent = view gts'_score g parent = view gts'_score g
children = map viewScores $ Map.elems $ view gts'_children g children = map viewScores $ HashMap.elems $ view gts'_children g
instance ViewScore (GroupedTreeScores (Scored Text)) Double where instance ViewScore (GroupedTreeScores (Scored NgramsTerm)) Double where
viewScore = view (gts'_score . scored_genInc) viewScore = view (gts'_score . scored_genInc)
------ ------
instance HasTerms (Map Text (GroupedTreeScores a)) where instance HasTerms (HashMap NgramsTerm (GroupedTreeScores a)) where
hasTerms = Set.unions . (map hasTerms) . Map.toList hasTerms = Set.unions . (map hasTerms) . HashMap.toList
instance HasTerms (Text, GroupedTreeScores a) where instance HasTerms (NgramsTerm, GroupedTreeScores a) where
hasTerms (t, g) = Set.singleton t <> children hasTerms (t, g) = Set.singleton t <> children
where where
children = Set.unions children = Set.unions
$ map hasTerms $ map hasTerms
$ Map.toList $ HashMap.toList
$ view gts'_children g $ view gts'_children g
------ ------
instance ToNgramsElement (Map Text (GroupedTreeScores a)) where instance ToNgramsElement (HashMap NgramsTerm (GroupedTreeScores a)) where
toNgramsElement = List.concat . (map toNgramsElement) . Map.toList toNgramsElement = List.concat . (map toNgramsElement) . HashMap.toList
instance ToNgramsElement (Text, GroupedTreeScores a) where instance ToNgramsElement (NgramsTerm, GroupedTreeScores a) where
toNgramsElement (t, gts) = parent : children toNgramsElement (t, gts) = parent : children
where where
parent = mkNgramsElement (NgramsTerm t) parent = mkNgramsElement t
(fromMaybe CandidateTerm $ viewListType gts) (fromMaybe CandidateTerm $ viewListType gts)
Nothing Nothing
(mSetFromList $ map NgramsTerm (mSetFromList $ HashMap.keys
$ Map.keys
$ view gts'_children gts $ view gts'_children gts
) )
children = List.concat children = List.concat
$ map (childrenWith (NgramsTerm t) (NgramsTerm t) ) $ map (childrenWith t t)
$ Map.toList $ HashMap.toList
$ view gts'_children gts $ view gts'_children gts
childrenWith root parent' (t', gts') = parent'' : children' childrenWith root parent' (t', gts') = parent'' : children'
where where
parent'' = mkNgramsElement (NgramsTerm t') parent'' = mkNgramsElement t'
(fromMaybe CandidateTerm $ viewListType gts') (fromMaybe CandidateTerm $ viewListType gts')
(Just $ RootParent root parent') (Just $ RootParent root parent')
(mSetFromList $ map NgramsTerm (mSetFromList $ HashMap.keys
$ Map.keys
$ view gts'_children gts' $ view gts'_children gts'
) )
children' = List.concat children' = List.concat
$ map (childrenWith root (NgramsTerm t') ) $ map (childrenWith root t' )
$ Map.toList $ HashMap.toList
$ view gts'_children gts' $ view gts'_children gts'
...@@ -16,49 +16,48 @@ module Gargantext.Core.Text.List.Group.WithScores ...@@ -16,49 +16,48 @@ module Gargantext.Core.Text.List.Group.WithScores
where where
import Control.Lens (view, set, over) import Control.Lens (view, set, over)
import Data.Semigroup import Data.HashMap.Strict (HashMap)
import Data.Map (Map)
import Data.Monoid (Monoid, mempty)
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Text (Text) import Data.Monoid (Monoid, mempty)
import Gargantext.Core.Text.List.Social.Prelude import Data.Semigroup
import Gargantext.API.Ngrams.Types (NgramsTerm(..))
import Gargantext.Core.Text.List.Group.Prelude import Gargantext.Core.Text.List.Group.Prelude
import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Prelude import Gargantext.Prelude
import qualified Data.Map as Map import qualified Data.HashMap.Strict as HashMap
------------------------------------------------------------------------
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Main function -- | Main function
groupWithScores' :: (Eq a, Ord a, Monoid a) groupWithScores' :: (Eq a, Ord a, Monoid a)
=> FlowCont Text FlowListScores => FlowCont NgramsTerm FlowListScores
-> (Text -> a) -- Map Text (a) -> (NgramsTerm -> a)
-> FlowCont Text (GroupedTreeScores (a)) -> FlowCont NgramsTerm (GroupedTreeScores a)
groupWithScores' flc scores = FlowCont groups orphans groupWithScores' flc scores = FlowCont groups orphans
where where
-- parent/child relation is inherited from social lists -- parent/child relation is inherited from social lists
groups = toGroupedTree groups = toGroupedTree
$ toMapMaybeParent scores $ toMapMaybeParent scores
$ view flc_scores flc $ (view flc_scores flc <> view flc_cont flc)
-- orphans should be filtered already then becomes empty
orphans = mempty
-- orphans should be filtered already
orphans = toGroupedTree
$ toMapMaybeParent scores
$ view flc_cont flc
------------------------------------------------------------------------ ------------------------------------------------------------------------
toMapMaybeParent :: (Eq a, Ord a, Monoid a) toMapMaybeParent :: (Eq a, Ord a, Monoid a)
=> (Text -> a) => (NgramsTerm -> a)
-> Map Text FlowListScores -> HashMap NgramsTerm FlowListScores
-> Map (Maybe Parent) (Map Text (GroupedTreeScores (a))) -> HashMap (Maybe Parent) (HashMap NgramsTerm (GroupedTreeScores a))
toMapMaybeParent f = Map.fromListWith (<>) toMapMaybeParent f = HashMap.fromListWith (<>)
. (map (fromScores'' f)) . (map (fromScores'' f))
. Map.toList . HashMap.toList
fromScores'' :: (Eq a, Ord a, Monoid a) fromScores'' :: (Eq a, Ord a, Monoid a)
=> (Text -> a) => (NgramsTerm -> a)
-> (Text, FlowListScores) -> (NgramsTerm, FlowListScores)
-> (Maybe Parent, Map Text (GroupedTreeScores (a))) -> (Maybe Parent, HashMap NgramsTerm (GroupedTreeScores a))
fromScores'' f' (t, fs) = ( maybeParent fromScores'' f' (t, fs) = ( maybeParent
, Map.fromList [( t, set gts'_score (f' t) , HashMap.fromList [( t, set gts'_score (f' t)
$ set gts'_listType maybeList mempty $ set gts'_listType maybeList mempty
)] )]
) )
...@@ -66,32 +65,27 @@ fromScores'' f' (t, fs) = ( maybeParent ...@@ -66,32 +65,27 @@ fromScores'' f' (t, fs) = ( maybeParent
maybeParent = keyWithMaxValue $ view fls_parents fs maybeParent = keyWithMaxValue $ view fls_parents fs
maybeList = keyWithMaxValue $ view fls_listType fs maybeList = keyWithMaxValue $ view fls_listType fs
------------------------------------------------------------------------
toGroupedTree :: Eq a toGroupedTree :: Eq a
=> Map (Maybe Parent) (Map Text (GroupedTreeScores (a))) => HashMap (Maybe Parent) (HashMap NgramsTerm (GroupedTreeScores a))
-> Map Parent (GroupedTreeScores (a)) -> HashMap Parent (GroupedTreeScores a)
toGroupedTree m = case Map.lookup Nothing m of toGroupedTree m = case HashMap.lookup Nothing m of
Nothing -> mempty Nothing -> mempty
Just m' -> toGroupedTree' m m' Just m' -> toGroupedTree' m m'
toGroupedTree' :: Eq a => Map (Maybe Parent) (Map Text (GroupedTreeScores (a))) toGroupedTree' :: Eq a => HashMap (Maybe Parent) (HashMap NgramsTerm (GroupedTreeScores a))
-> (Map Text (GroupedTreeScores (a))) -> (HashMap NgramsTerm (GroupedTreeScores a))
-> Map Parent (GroupedTreeScores (a)) -> HashMap Parent (GroupedTreeScores a)
toGroupedTree' m notEmpty toGroupedTree' m notEmpty
| notEmpty == mempty = mempty | notEmpty == mempty = mempty
| otherwise = Map.mapWithKey (addGroup m) notEmpty | otherwise = HashMap.mapWithKey (addGroup m) notEmpty
where where
addGroup m' k v = over gts'_children ( (toGroupedTree' m') addGroup m' k v = over gts'_children ( (toGroupedTree' m')
. (Map.union ( fromMaybe mempty . (HashMap.union ( fromMaybe mempty
$ Map.lookup (Just k) m' $ HashMap.lookup (Just k) m'
) )
) )
) )
v v
...@@ -17,20 +17,30 @@ Portability : POSIX ...@@ -17,20 +17,30 @@ Portability : POSIX
module Gargantext.Core.Text.List.Group.WithStem module Gargantext.Core.Text.List.Group.WithStem
where where
import Control.Lens (view, over) import Data.HashSet (HashSet)
import Data.Set (Set)
import Data.Map (Map) import Data.Map (Map)
import Data.Monoid (mempty) import Data.Maybe (catMaybes)
import Data.Text (Text) import Gargantext.API.Ngrams.Types
import Gargantext.Core (Lang(..)) import Gargantext.Core (Lang(..))
import Gargantext.Database.Admin.Types.Node (NodeId)
import Gargantext.Core.Text.List.Group.Prelude import Gargantext.Core.Text.List.Group.Prelude
import Gargantext.Core.Text.List.Social.Patch
import Gargantext.Core.Text.List.Social.Prelude import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Core.Text.Terms.Mono.Stem (stem) import Gargantext.Core.Text.Terms.Mono.Stem (stem)
import Gargantext.Prelude import Gargantext.Prelude
import qualified Data.Map as Map import qualified Data.HashSet as Set
import qualified Data.List as List import qualified Data.List as List
import qualified Data.Text as Text import qualified Data.Map as Map
import qualified Data.Map.Strict.Patch as PatchMap
import qualified Data.Patch.Class as Patch (Replace(..))
import qualified Data.Text as Text
------------------------------------------------------------------------
addScoreStem :: GroupParams
-> HashSet NgramsTerm
-> FlowCont NgramsTerm FlowListScores
-> FlowCont NgramsTerm FlowListScores
addScoreStem groupParams ngrams fl = foldl' addScorePatch fl
$ stemPatches groupParams ngrams
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Main Types -- | Main Types
...@@ -49,177 +59,55 @@ data GroupParams = GroupParams { unGroupParams_lang :: !Lang ...@@ -49,177 +59,55 @@ data GroupParams = GroupParams { unGroupParams_lang :: !Lang
| GroupIdentity | GroupIdentity
deriving (Eq) deriving (Eq)
------------------------------------------------------------------------
class GroupWithStem a where
groupWithStem' :: GroupParams
-> FlowCont Text (GroupedTreeScores a)
-> FlowCont Text (GroupedTreeScores a)
-- TODO factorize groupWithStem_*
instance GroupWithStem (Set NodeId) where
groupWithStem' = groupWithStem_SetNodeId
instance GroupWithStem Double where
groupWithStem' = groupWithStem_Double
------------------------------------------------------------------------ ------------------------------------------------------------------------
groupWith :: GroupParams groupWith :: GroupParams
-> Text -> NgramsTerm
-> Text -> NgramsTerm
groupWith GroupIdentity = identity groupWith GroupIdentity = identity
groupWith (GroupParams l _m _n _) = groupWith (GroupParams l _m _n _) =
Text.intercalate " " NgramsTerm
. Text.intercalate " "
. map (stem l) . map (stem l)
-- . take n -- . take n
. List.sort . List.sort
-- . (List.filter (\t -> Text.length t > m)) -- . (List.filter (\t -> Text.length t > m))
. Text.splitOn " " . Text.splitOn " "
. Text.replace "-" " " . Text.replace "-" " "
. unNgramsTerm
------------------------------------------------------------------------ --------------------------------------------------------------------
groupWithStem_SetNodeId :: GroupParams stemPatches :: GroupParams
-> FlowCont Text (GroupedTreeScores (Set NodeId)) -> HashSet NgramsTerm
-> FlowCont Text (GroupedTreeScores (Set NodeId)) -> [(NgramsTerm, NgramsPatch)]
groupWithStem_SetNodeId g flc stemPatches groupParams = patches
| g == GroupIdentity = FlowCont ( (<>) . Map.fromListWith (<>)
(view flc_scores flc) . map (\ng -> ( groupWith groupParams ng
(view flc_cont flc) , Set.singleton ng)
) mempty )
| otherwise = mergeWith (groupWith g) flc . Set.toList
groupWithStem_Double :: GroupParams -- | For now all NgramsTerm which have same stem
-> FlowCont Text (GroupedTreeScores Double) -- are grouped together
-> FlowCont Text (GroupedTreeScores Double) -- Parent is taken arbitrarly for now (TODO use a score like occ)
groupWithStem_Double g flc patches :: Map Stem (HashSet NgramsTerm)
| g == GroupIdentity = FlowCont ( (<>) -> [(NgramsTerm, NgramsPatch)]
(view flc_scores flc) patches = catMaybes . map patch . Map.elems
(view flc_cont flc)
) mempty patch :: HashSet NgramsTerm
| otherwise = mergeWith_Double (groupWith g) flc -> Maybe (NgramsTerm, NgramsPatch)
patch s = case Set.size s > 1 of
False -> Nothing
True -> do
let ngrams = Set.toList s
-- | MergeWith : with stem, we always have an answer parent <- headMay ngrams
-- if Maybe lems then we should add it to continuation let children = List.tail ngrams
mergeWith :: (Text -> Text) pure (parent, toNgramsPatch children)
-> FlowCont Text (GroupedTreeScores (Set NodeId))
-> FlowCont Text (GroupedTreeScores (Set NodeId)) toNgramsPatch :: [NgramsTerm] -> NgramsPatch
mergeWith fun flc = FlowCont scores mempty toNgramsPatch children = NgramsPatch children' Patch.Keep
where where
children' :: PatchMSet NgramsTerm
scores :: Map Text (GroupedTreeScores (Set NodeId)) children' = PatchMSet
scores = foldl' (alter (mapStems scores')) scores' cont' $ fst
where $ PatchMap.fromList
scores' = view flc_scores flc $ List.zip children (List.cycle [addPatch])
cont' = Map.toList $ view flc_cont flc
-- TODO insert at the right place in group hierarchy
-- adding as child of the parent for now
alter :: Map Stem Text
-> Map Text (GroupedTreeScores (Set NodeId))
-> (Text, GroupedTreeScores (Set NodeId))
-> Map Text (GroupedTreeScores (Set NodeId))
alter st target (t,g) = case Map.lookup t st of
Nothing -> Map.alter (alter' (t,g)) t target
Just t' -> Map.alter (alter' (t,g)) t' target
alter' (_t,g) Nothing = Just g
alter' ( t,g) (Just g') = Just $ over gts'_children
( Map.union (Map.singleton t g))
g'
mapStems :: Map Text (GroupedTreeScores (Set NodeId))
-> Map Stem Text
mapStems = (Map.fromListWith (<>)) . List.concat . (map mapStem) . Map.toList
mapStem :: (Text, GroupedTreeScores (Set NodeId))
-> [(Stem, Text)]
mapStem (s,g) = parent : children
where
parent = (fun s, s)
children = List.concat $ map mapStem (Map.toList $ view gts'_children g)
-- | MergeWith : with stem, we always have an answer
-- if Maybe lems then we should add it to continuation
mergeWith_Double :: (Text -> Text)
-> FlowCont Text (GroupedTreeScores Double)
-> FlowCont Text (GroupedTreeScores Double)
mergeWith_Double fun flc = FlowCont scores mempty
where
scores :: Map Text (GroupedTreeScores Double)
scores = foldl' (alter (mapStems scores')) scores' cont'
where
scores' = view flc_scores flc
cont' = Map.toList $ view flc_cont flc
-- TODO insert at the right place in group hierarchy
-- adding as child of the parent for now
alter :: Map Stem Text
-> Map Text (GroupedTreeScores Double)
-> (Text, GroupedTreeScores Double)
-> Map Text (GroupedTreeScores Double)
alter st target (t,g) = case Map.lookup t st of
Nothing -> Map.alter (alter' (t,g)) t target
Just t' -> Map.alter (alter' (t,g)) t' target
alter' (_t,g) Nothing = Just g
alter' ( t,g) (Just g') = Just $ over gts'_children
( Map.union (Map.singleton t g))
g'
mapStems :: Map Text (GroupedTreeScores Double)
-> Map Stem Text
mapStems = (Map.fromListWith (<>)) . List.concat . (map mapStem) . Map.toList
mapStem :: (Text, GroupedTreeScores Double)
-> [(Stem, Text)]
mapStem (s,g) = parent : children
where
parent = (fun s, s)
children = List.concat $ map mapStem (Map.toList $ view gts'_children g)
{-
-- | TODO fixme
mergeWith_a :: (Text -> Text)
-> FlowCont Text (GroupedTreeScores a)
-> FlowCont Text (GroupedTreeScores a)
mergeWith_a fun flc = FlowCont scores mempty
where
scores :: Map Text (GroupedTreeScores a)
scores = foldl' (alter (mapStems scores')) scores' cont'
where
scores' = view flc_scores flc
cont' = Map.toList $ _flc_cont flc
-- TODO insert at the right place in group hierarchy
-- adding as child of the parent for now
alter :: Map Stem Text
-> Map Text (GroupedTreeScores a)
-> (Text, GroupedTreeScores a)
-> Map Text (GroupedTreeScores a)
alter st target (t,g) = case Map.lookup t st of
Nothing -> Map.alter (alter' (t,g)) t target
Just t' -> Map.alter (alter' (t,g)) t' target
alter' (_t,g) Nothing = Just g
alter' ( t,g) (Just g') = Just $ over gts'_children
( Map.union (Map.singleton t g))
g'
mapStems :: Map Text (GroupedTreeScores a)
-> Map Stem Text
mapStems = (Map.fromListWith (<>)) . List.concat . (map mapStem) . Map.toList
mapStem :: (Text, GroupedTreeScores a)
-> [(Stem, Text)]
mapStem (s,g) = parent : children
where
parent = (fun s, s)
children = List.concat $ map mapStem (Map.toList $ view gts'_children g)
-}
{-|
Module : Gargantext.Core.Text.List.Merge
Description :
Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE InstanceSigs #-}
module Gargantext.Core.Text.List.Merge
where
import Control.Lens (view)
import Data.Map (Map)
import Gargantext.API.Ngrams
import Gargantext.API.Ngrams.Types
import Gargantext.Prelude
import Data.Map.Strict.Patch hiding (PatchMap)
type List = Map NgramsTerm NgramsRepoElement
type Patch = PatchMap NgramsTerm (Replace (Maybe NgramsRepoElement))
-- Question: which version of Patching increment is using the FrontEnd ?
diffList :: Versioned List -> Versioned List -> Versioned Patch
diffList l1 l2 = Versioned (1 + view v_version l1)
(diff (view v_data l1) (view v_data l2))
-- | TODO
{-
commit :: ListId -> NgramsType -> Versioned Patch -> List -> List
commit = undefined
-}
...@@ -11,13 +11,15 @@ Portability : POSIX ...@@ -11,13 +11,15 @@ Portability : POSIX
module Gargantext.Core.Text.List.Social module Gargantext.Core.Text.List.Social
where where
import Data.HashMap.Strict (HashMap)
import Data.Map (Map)
import Data.Monoid (mconcat) import Data.Monoid (mconcat)
import Data.Text (Text)
import Gargantext.API.Ngrams.Tools import Gargantext.API.Ngrams.Tools
import Gargantext.API.Ngrams.Types import Gargantext.API.Ngrams.Types
import Gargantext.Core.Text.List.Social.Find import Gargantext.Core.Text.List.Social.Find
import Gargantext.Core.Text.List.Social.History
import Gargantext.Core.Text.List.Social.Patch
import Gargantext.Core.Text.List.Social.Prelude import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Core.Text.List.Social.Scores
import Gargantext.Core.Types.Individu import Gargantext.Core.Types.Individu
import Gargantext.Database.Admin.Types.Node import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude import Gargantext.Database.Prelude
...@@ -39,11 +41,12 @@ flowSocialListPriority :: FlowSocialListPriority -> [NodeMode] ...@@ -39,11 +41,12 @@ flowSocialListPriority :: FlowSocialListPriority -> [NodeMode]
flowSocialListPriority MySelfFirst = [Private{-, Shared, Public -}] flowSocialListPriority MySelfFirst = [Private{-, Shared, Public -}]
flowSocialListPriority OthersFirst = reverse $ flowSocialListPriority MySelfFirst flowSocialListPriority OthersFirst = reverse $ flowSocialListPriority MySelfFirst
{-
-- | We keep the parents for all ngrams but terms -- | We keep the parents for all ngrams but terms
keepAllParents :: NgramsType -> KeepAllParents keepAllParents :: NgramsType -> KeepAllParents
keepAllParents NgramsTerms = KeepAllParents False keepAllParents NgramsTerms = KeepAllParents False
keepAllParents _ = KeepAllParents True keepAllParents _ = KeepAllParents True
-}
------------------------------------------------------------------------ ------------------------------------------------------------------------
flowSocialList :: ( RepoCmdM env err m flowSocialList :: ( RepoCmdM env err m
...@@ -53,8 +56,8 @@ flowSocialList :: ( RepoCmdM env err m ...@@ -53,8 +56,8 @@ flowSocialList :: ( RepoCmdM env err m
) )
=> FlowSocialListPriority => FlowSocialListPriority
-> User -> NgramsType -> User -> NgramsType
-> FlowCont Text FlowListScores -> FlowCont NgramsTerm FlowListScores
-> m (FlowCont Text FlowListScores) -> m (FlowCont NgramsTerm FlowListScores)
flowSocialList flowPriority user nt flc = flowSocialList flowPriority user nt flc =
mconcat <$> mapM (flowSocialListByMode' user nt flc) mconcat <$> mapM (flowSocialListByMode' user nt flc)
(flowSocialListPriority flowPriority) (flowSocialListPriority flowPriority)
...@@ -66,9 +69,9 @@ flowSocialList flowPriority user nt flc = ...@@ -66,9 +69,9 @@ flowSocialList flowPriority user nt flc =
, HasTreeError err , HasTreeError err
) )
=> User -> NgramsType => User -> NgramsType
-> FlowCont Text FlowListScores -> FlowCont NgramsTerm FlowListScores
-> NodeMode -> NodeMode
-> m (FlowCont Text FlowListScores) -> m (FlowCont NgramsTerm FlowListScores)
flowSocialListByMode' user' nt' flc' mode = flowSocialListByMode' user' nt' flc' mode =
findListsId user' mode findListsId user' mode
>>= flowSocialListByModeWith nt' flc' >>= flowSocialListByModeWith nt' flc'
...@@ -80,10 +83,39 @@ flowSocialList flowPriority user nt flc = ...@@ -80,10 +83,39 @@ flowSocialList flowPriority user nt flc =
, HasTreeError err , HasTreeError err
) )
=> NgramsType => NgramsType
-> FlowCont Text FlowListScores -> FlowCont NgramsTerm FlowListScores
-> [NodeId] -> [ListId]
-> m (FlowCont Text FlowListScores) -> m (FlowCont NgramsTerm FlowListScores)
flowSocialListByModeWith nt'' flc'' ns = flowSocialListByModeWith nt'' flc'' listes =
mapM (\l -> getListNgrams [l] nt'') ns getHistoryScores History_User nt'' flc'' listes
{-
mapM (\l -> getListNgrams [l] nt'') listes
>>= pure >>= pure
. toFlowListScores (keepAllParents nt'') flc'' . toFlowListScores (keepAllParents nt'') flc''
-}
-----------------------------------------------------------------
getHistoryScores :: ( RepoCmdM env err m
, CmdM env err m
, HasNodeError err
, HasTreeError err
)
=> History
-> NgramsType
-> FlowCont NgramsTerm FlowListScores
-> [ListId]
-> m (FlowCont NgramsTerm FlowListScores)
getHistoryScores hist nt fl listes =
addScorePatches nt listes fl <$> getHistory hist nt listes
getHistory :: ( RepoCmdM env err m
, CmdM env err m
, HasNodeError err
, HasTreeError err
)
=> History
-> NgramsType
-> [ListId]
-> m (Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch]))
getHistory hist nt listes =
history hist [nt] listes <$> getRepo
{-|
Module : Gargantext.Core.Text.List.Social.History
Description :
Copyright : (c) CNRS, 2018-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
module Gargantext.Core.Text.List.Social.History
where
import Control.Lens hiding (cons)
import Data.HashMap.Strict (HashMap)
import Data.Map (Map)
import Gargantext.API.Ngrams.Types
import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Core.Types (ListId)
import Gargantext.Database.Schema.Ngrams (NgramsType(..))
import Gargantext.Prelude
import qualified Data.List as List
import qualified Data.Map.Strict as Map
-- TODO put this in Prelude
cons :: a -> [a]
cons a = [a]
------------------------------------------------------------------------
-- | History control
data History = History_User
| History_NotUser
| History_All
------------------------------------------------------------------------
-- | Main Function
history :: History
-> [NgramsType]
-> [ListId]
-> Repo s NgramsStatePatch
-> Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch])
history History_User t l = clean . (history' t l)
where
clean = Map.map (Map.map List.init)
history History_NotUser t l = clean . (history' t l)
where
clean = Map.map (Map.map last)
last = (maybe [] cons) . lastMay
history _ t l = history' t l
------------------------------------------------------------------------
history' :: [NgramsType]
-> [ListId]
-> Repo s NgramsStatePatch
-> Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch])
history' types lists = merge
. map (Map.map ( Map.map cons))
. map (Map.map ((Map.filterWithKey (\k _ -> List.elem k lists))))
. map (Map.filterWithKey (\k _ -> List.elem k types))
. map toMap
. view r_history
merge :: [Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch])]
-> Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch])
merge = Map.unionsWith merge'
where
merge' :: Map ListId [HashMap NgramsTerm NgramsPatch]
-> Map ListId [HashMap NgramsTerm NgramsPatch]
-> Map ListId [HashMap NgramsTerm NgramsPatch]
merge' = Map.unionWith (<>)
toMap :: PatchMap NgramsType
(PatchMap ListId
(NgramsTablePatch
)
)
-> Map NgramsType
(Map ListId
(HashMap NgramsTerm NgramsPatch
)
)
toMap = Map.map (Map.map unNgramsTablePatch) . (Map.map unPatchMapToMap) . unPatchMapToMap
{-|
Module : Gargantext.Core.Text.List.Social.Patch
Description :
Copyright : (c) CNRS, 2018-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
module Gargantext.Core.Text.List.Social.Patch
where
import Control.Lens hiding (cons)
import Data.Map (Map)
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import Data.Monoid
import Data.Semigroup
import Gargantext.API.Ngrams.Types
import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Core.Types (ListId)
import Gargantext.Database.Schema.Ngrams (NgramsType(..))
import Gargantext.Prelude
import qualified Data.Map as Map
import qualified Data.List as List
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Patch.Class as Patch (Replace(..))
addScorePatches :: NgramsType -> [ListId]
-> FlowCont NgramsTerm FlowListScores
-> Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch])
-> FlowCont NgramsTerm FlowListScores
addScorePatches nt listes fl repo = foldl' (addScorePatchesList nt repo) fl listes
addScorePatchesList :: NgramsType
-> Map NgramsType (Map ListId [HashMap NgramsTerm NgramsPatch])
-> FlowCont NgramsTerm FlowListScores
-> ListId
-> FlowCont NgramsTerm FlowListScores
addScorePatchesList nt repo fl lid = foldl' addScorePatch fl patches
where
patches = maybe [] (List.concat . (map HashMap.toList)) patches'
patches' = do
lists <- Map.lookup nt repo
mapPatches <- Map.lookup lid lists
pure mapPatches
addScorePatch :: FlowCont NgramsTerm FlowListScores
-> (NgramsTerm , NgramsPatch)
-> FlowCont NgramsTerm FlowListScores
{- | Case of changing listType only. Patches look like:
This patch move "problem" from MapTerm to CandidateTerm
,fromList [(NgramsTerm {unNgramsTerm = "problem"},NgramsPatch {_patch_children = PatchMSet (PatchMap (fromList [])), _patch_list = Replace {_old = MapTerm, _new = CandidateTerm}})]
This patch move "paper" from MapTerm to StopTerm
,fromList [(NgramsTerm {unNgramsTerm = "paper"},NgramsPatch {_patch_children = PatchMSet (PatchMap (fromList [])), _patch_list = Replace {_old = MapTerm, _new = StopTerm}})]])])]
Children are not modified in this specific case.
-}
-- | Old list get -1 score
-- New list get +1 score
-- Hence others lists lay around 0 score
addScorePatch fl (t, (NgramsPatch children' (Patch.Replace old_list new_list))) =
-- | Adding New Children score
addScorePatch fl' (t, NgramsPatch children' Patch.Keep)
where
-- | Adding New ListType score
fl' = fl & flc_scores . at t %~ (score fls_listType old_list (-1))
& flc_scores . at t %~ (score fls_listType new_list ( 1))
& flc_cont %~ (HashMap.delete t)
-- | Patching existing Ngrams with children
addScorePatch fl (p, NgramsPatch children' Patch.Keep) =
foldl' addChild fl $ patchMSet_toList children'
where
-- | Adding a child
addChild fl' (t, Patch.Replace Nothing (Just _)) = doLink ( 1) p t fl'
-- | Removing a child
addChild fl' (t, Patch.Replace (Just _) Nothing) = doLink (-1) p t fl'
-- | This case should not happen: does Nothing
addChild fl' _ = fl'
-- | Inserting a new Ngrams
addScorePatch fl (t, NgramsReplace Nothing (Just nre)) =
childrenScore 1 t (nre ^. nre_children)
$ fl & flc_scores . at t %~ (score fls_listType $ nre ^. nre_list) 1
& flc_cont %~ (HashMap.delete t)
addScorePatch fl (t, NgramsReplace (Just old_nre) maybe_new_nre) =
let fl' = childrenScore (-1) t (old_nre ^. nre_children)
$ fl & flc_scores . at t %~ (score fls_listType $ old_nre ^. nre_list) (-1)
& flc_cont %~ (HashMap.delete t)
in case maybe_new_nre of
Nothing -> fl'
Just new_nre -> addScorePatch fl' (t, NgramsReplace Nothing (Just new_nre))
addScorePatch fl (_, NgramsReplace Nothing Nothing) = fl
-------------------------------------------------------------------------------
-- | Utils
childrenScore :: Int
-> NgramsTerm
-> MSet NgramsTerm
-> FlowCont NgramsTerm FlowListScores
-> FlowCont NgramsTerm FlowListScores
childrenScore n parent children' fl =
foldl' add' fl $ unMSet children'
where
add' fl' t = doLink n parent t fl'
------------------------------------------------------------------------
doLink :: (Ord a, Hashable a)
=> Int
-> NgramsTerm
-> a
-> FlowCont a FlowListScores
-> FlowCont a FlowListScores
doLink n parent child fl' = fl' & flc_scores . at child %~ (score fls_parents parent n)
score :: (Monoid a, At m, Semigroup (IxValue m))
=> ((m -> Identity m) -> a -> Identity b)
-> Index m -> IxValue m -> Maybe a -> Maybe b
score field list n m = (Just mempty <> m)
& _Just
. field
. at list
%~ (<> Just n)
------------------------------------------------------------------------
patchMSet_toList :: (Ord a, Hashable a) => PatchMSet a -> [(a,AddRem)]
patchMSet_toList = HashMap.toList . unPatchMapToHashMap . unPatchMSet
unMSet :: MSet a -> [a]
unMSet (MSet a) = Map.keys a
...@@ -19,29 +19,34 @@ module Gargantext.Core.Text.List.Social.Prelude ...@@ -19,29 +19,34 @@ module Gargantext.Core.Text.List.Social.Prelude
where where
import Control.Lens import Control.Lens
import Data.Semigroup (Semigroup(..))
import Data.Monoid
import Data.Map (Map) import Data.Map (Map)
import Data.Text (Text) import Data.HashMap.Strict (HashMap)
import Data.Hashable (Hashable)
import Data.Monoid
import Data.Semigroup (Semigroup(..))
import GHC.Generics (Generic)
import Gargantext.API.Ngrams.Types
import Gargantext.Core.Types.Main import Gargantext.Core.Types.Main
import Gargantext.Prelude import Gargantext.Prelude
import GHC.Generics (Generic) import qualified Gargantext.Data.HashMap.Strict.Utils as HashMap
import qualified Data.Map as Map import qualified Data.Map.Strict as Map
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Map.Strict.Patch as PatchMap
------------------------------------------------------------------------ ------------------------------------------------------------------------
type Parent = Text type Parent = NgramsTerm
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | DataType inspired by continuation Monad (but simpler) -- | DataType inspired by continuation Monad (but simpler)
data FlowCont a b = data FlowCont a b =
FlowCont { _flc_scores :: Map a b FlowCont { _flc_scores :: HashMap a b
, _flc_cont :: Map a b , _flc_cont :: HashMap a b
} }
deriving (Show) deriving (Show)
instance (Ord a, Eq b) => Monoid (FlowCont a b) where instance (Ord a, Eq b, Hashable a) => Monoid (FlowCont a b) where
mempty = FlowCont mempty mempty mempty = FlowCont mempty mempty
instance (Eq a, Ord a, Eq b) => Semigroup (FlowCont a b) where instance (Eq a, Ord a, Eq b, Hashable a) => Semigroup (FlowCont a b) where
(<>) (FlowCont m1 s1) (<>) (FlowCont m1 s1)
(FlowCont m2 s2) (FlowCont m2 s2)
= FlowCont (m1 <> m2) = FlowCont (m1 <> m2)
...@@ -51,10 +56,10 @@ makeLenses ''FlowCont ...@@ -51,10 +56,10 @@ makeLenses ''FlowCont
-- | Datatype definition -- | Datatype definition
data FlowListScores = data FlowListScores =
FlowListScores { _fls_listType :: Map ListType Int FlowListScores { _fls_listType :: HashMap ListType Int
, _fls_parents :: Map Parent Int , _fls_parents :: HashMap Parent Int
-- You can add any score by incrementing this type -- You can add any score by incrementing this type
-- , _flc_score :: Map Score Int -- , _flc_score :: HashMap Score Int
} }
deriving (Show, Generic, Eq) deriving (Show, Generic, Eq)
...@@ -72,16 +77,16 @@ instance Semigroup FlowListScores where ...@@ -72,16 +77,16 @@ instance Semigroup FlowListScores where
(l1 <> l2) (l1 <> l2)
instance Monoid FlowListScores where instance Monoid FlowListScores where
mempty = FlowListScores Map.empty Map.empty mempty = FlowListScores HashMap.empty HashMap.empty
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Tools to inherit groupings -- | Tools to inherit groupings
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Tools -- | Tools
parentUnionsMerge :: (Ord a, Ord b, Num c) parentUnionsMerge :: (Ord a, Ord b, Num c, Hashable a, Hashable b)
=> [Map a (Map b c)] => [HashMap a (HashMap b c)]
-> Map a (Map b c) -> HashMap a (HashMap b c)
parentUnionsMerge = Map.unionsWith (Map.unionWith (+)) parentUnionsMerge = HashMap.unionsWith (HashMap.unionWith (+))
-- This Parent union is specific -- This Parent union is specific
-- [Private, Shared, Public] -- [Private, Shared, Public]
...@@ -89,22 +94,38 @@ parentUnionsMerge = Map.unionsWith (Map.unionWith (+)) ...@@ -89,22 +94,38 @@ parentUnionsMerge = Map.unionsWith (Map.unionWith (+))
-- Private > Shared > Public -- Private > Shared > Public
-- if data have not been tagged privately, then use others tags -- if data have not been tagged privately, then use others tags
-- This unions behavior takes first key only and ignore others -- This unions behavior takes first key only and ignore others
parentUnionsExcl :: Ord a parentUnionsExcl :: (Ord a, Hashable a)
=> [Map a b] => [HashMap a b]
-> Map a b -> HashMap a b
parentUnionsExcl = Map.unions parentUnionsExcl = HashMap.unions
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | Takes key with max value if and only if value > 0
-- If value <= 0 alors key is not taken at all
-- It can happens since some score are non positive (i.e. removing a child)
-- >>> keyWithMaxValue $ DM.fromList $ zip (['a'..'z'] :: [Char]) ([1,2..]::[Int])
-- Just 'z'
-- >>> keyWithMaxValue $ DM.fromList $ zip (['a'..'z'] :: [Char]) ([-1,-2..]::[Int])
-- Nothing
-- TODO duplicate with getMaxFromMap and improve it (lookup value should not be needed)
-- TODO put in custom Prelude
keyWithMaxValue :: (Ord a, Ord b, Num b, Hashable a)
=> HashMap a b -> Maybe a
keyWithMaxValue m = do
maxKey <- headMay $ HashMap.getKeysOrderedByValueMaxFirst m
maxValue <- HashMap.lookup maxKey m
if maxValue > 0
then pure maxKey
else Nothing
hasParent :: Text
-> Map Text (Map Parent Int)
-> Maybe Parent
hasParent t m = case Map.lookup t m of
Nothing -> Nothing
Just m' -> keyWithMaxValue m'
------------------------------------------------------------------------ ------------------------------------------------------------------------
keyWithMaxValue :: Map a b -> Maybe a unPatchMapToHashMap :: (Ord a, Hashable a) => PatchMap a b -> HashMap a b
keyWithMaxValue m = (fst . fst) <$> Map.maxViewWithKey m unPatchMapToHashMap = HashMap.fromList . PatchMap.toList
unPatchMapToMap :: Ord a => PatchMap a b -> Map a b
unPatchMapToMap = Map.fromList . PatchMap.toList
unNgramsTablePatch :: NgramsTablePatch -> HashMap NgramsTerm NgramsPatch
unNgramsTablePatch (NgramsTablePatch p) = unPatchMapToHashMap p
{-|
Module : Gargantext.Core.Text.List.Social.Scores
Description :
Copyright : (c) CNRS, 2018-Present
License : AGPL + CECILL v3
Maintainer : team@gargantext.org
Stability : experimental
Portability : POSIX
-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
module Gargantext.Core.Text.List.Social.Scores
where
import Control.Lens
import Data.Map (Map)
import Data.Monoid (mempty)
import Data.Set (Set)
import Data.Text (Text)
import Gargantext.API.Ngrams.Types
import Gargantext.Core.Types.Main
import Gargantext.Core.Text.List.Social.Prelude
import Gargantext.Prelude
import qualified Data.Map as Map
import qualified Data.Set as Set
------------------------------------------------------------------------
-- | Generates Score from list of Map Text NgramsRepoElement
toFlowListScores :: KeepAllParents
-> FlowCont Text FlowListScores
-> [Map Text NgramsRepoElement]
-> FlowCont Text FlowListScores
toFlowListScores k flc_origin = foldl' (toFlowListScores_Level1 k flc_origin) mempty
where
toFlowListScores_Level1 :: KeepAllParents
-> FlowCont Text FlowListScores
-> FlowCont Text FlowListScores
-> Map Text NgramsRepoElement
-> FlowCont Text FlowListScores
toFlowListScores_Level1 k' flc_origin' flc_dest ngramsRepo =
Set.foldl' (toFlowListScores_Level2 k' ngramsRepo flc_origin')
flc_dest
(Set.fromList $ Map.keys $ view flc_cont flc_origin')
toFlowListScores_Level2 :: KeepAllParents
-> Map Text NgramsRepoElement
-> FlowCont Text FlowListScores
-> FlowCont Text FlowListScores
-> Text
-> FlowCont Text FlowListScores
toFlowListScores_Level2 k'' ngramsRepo flc_origin'' flc_dest' t =
case Map.lookup t ngramsRepo of
Nothing -> over flc_cont (Map.union $ Map.singleton t mempty) flc_dest'
Just nre -> updateScoresParent k'' ngramsRepo nre flc_origin''
$ updateScores k'' t nre setText flc_dest'
where
setText = Set.fromList
$ Map.keys
$ view flc_cont flc_origin''
updateScoresParent :: KeepAllParents -> Map Text NgramsRepoElement -> NgramsRepoElement
-> FlowCont Text FlowListScores
-> FlowCont Text FlowListScores
-> FlowCont Text FlowListScores
updateScoresParent keep@(KeepAllParents k''') ngramsRepo nre flc_origin'' flc_dest'' = case k''' of
False -> flc_dest''
True -> case view nre_parent nre of
Nothing -> flc_dest''
Just (NgramsTerm parent) -> toFlowListScores_Level2 keep ngramsRepo flc_origin'' flc_dest'' parent
------------------------------------------------------------------------
updateScores :: KeepAllParents
-> Text -> NgramsRepoElement -> Set Text
-> FlowCont Text FlowListScores
-> FlowCont Text FlowListScores
updateScores k t nre setText mtf =
over flc_cont ( Map.delete t)
$ over flc_scores ((Map.alter (addParent k nre setText ) t)
.(Map.alter (addList $ view nre_list nre) t)
) mtf
------------------------------------------------------------------------
-- | Main addFunctions to groupResolution the FlowListScores
-- Use patch-map library here
-- diff, transformWith patches simplifies functions below
addList :: ListType
-> Maybe FlowListScores
-> Maybe FlowListScores
addList l Nothing =
Just $ set fls_listType (addListScore l mempty) mempty
addList l (Just fls) =
Just $ over fls_listType (addListScore l) fls
-- * Unseful but nice comment:
-- "the addList function looks like an ASCII bird"
-- | Concrete function to pass to PatchMap
addListScore :: ListType -> Map ListType Int -> Map ListType Int
addListScore l m = Map.alter (plus l) l m
where
plus CandidateTerm Nothing = Just 1
plus CandidateTerm (Just x) = Just $ x + 1
plus MapTerm Nothing = Just 2
plus MapTerm (Just x) = Just $ x + 2
plus StopTerm Nothing = Just 3
plus StopTerm (Just x) = Just $ x + 3
------------------------------------------------------------------------
data KeepAllParents = KeepAllParents Bool
addParent :: KeepAllParents -> NgramsRepoElement -> Set Text
-> Maybe FlowListScores
-> Maybe FlowListScores
addParent k nre ss Nothing =
Just $ FlowListScores mempty mapParent
where
mapParent = addParentScore k (view nre_parent nre) ss mempty
addParent k nre ss (Just fls{-(FlowListScores mapList mapParent)-}) =
Just $ over fls_parents (addParentScore k (view nre_parent nre) ss) fls
addParentScore :: Num a
=> KeepAllParents
-> Maybe NgramsTerm
-> Set Text
-> Map Text a
-> Map Text a
addParentScore _ Nothing _ss mapParent = mapParent
addParentScore (KeepAllParents keep) (Just (NgramsTerm p')) ss mapParent =
case keep of
True -> Map.alter addCount p' mapParent
False -> case Set.member p' ss of
False -> mapParent
True -> Map.alter addCount p' mapParent
where
addCount Nothing = Just 1
addCount (Just n) = Just $ n + 1
------------------------------------------------------------------------
------------------------------------------------------------------------
...@@ -20,29 +20,32 @@ module Gargantext.Core.Text.Metrics ...@@ -20,29 +20,32 @@ module Gargantext.Core.Text.Metrics
--import Math.KMeans (kmeans, euclidSq, elements) --import Math.KMeans (kmeans, euclidSq, elements)
import Control.Lens (makeLenses) import Control.Lens (makeLenses)
import Data.Map (Map) import Data.Map (Map)
import Data.Semigroup (Semigroup)
import Data.Monoid (Monoid, mempty) import Data.Monoid (Monoid, mempty)
import Gargantext.Prelude import Data.HashMap.Strict (HashMap)
import Data.Semigroup (Semigroup)
import Gargantext.Core.Methods.Distances.Accelerate.SpeGen import Gargantext.Core.Methods.Distances.Accelerate.SpeGen
import Gargantext.Core.Viz.Graph.Index
import Gargantext.Core.Statistics (pcaReduceTo, Dimension(..)) import Gargantext.Core.Statistics (pcaReduceTo, Dimension(..))
import Gargantext.Core.Viz.Graph.Index
import Gargantext.Prelude
import qualified Data.Array.Accelerate as DAA import qualified Data.Array.Accelerate as DAA
import qualified Data.Array.Accelerate.Interpreter as DAA import qualified Data.Array.Accelerate.Interpreter as DAA
import qualified Data.Map as Map import qualified Data.Map as Map
import qualified Data.Vector as V
import qualified Data.Vector.Storable as Vec import qualified Data.Vector.Storable as Vec
import qualified Data.HashMap.Strict as HashMap
type MapListSize = Int type MapListSize = Int
type InclusionSize = Int type InclusionSize = Int
scored :: Ord t => Map (t,t) Int -> [Scored t] scored :: Ord t => HashMap (t,t) Int -> V.Vector (Scored t)
scored = map2scored . (pcaReduceTo (Dimension 2)) . scored2map scored = map2scored . (pcaReduceTo (Dimension 2)) . scored2map . Map.fromList . HashMap.toList
where where
scored2map :: Ord t => Map (t,t) Int -> Map t (Vec.Vector Double) scored2map :: Ord t => Map (t,t) Int -> Map t (Vec.Vector Double)
scored2map m = Map.fromList $ map (\(Scored t i s) -> (t, Vec.fromList [i,s])) $ scored' m scored2map m = Map.fromList $ map (\(Scored t i s) -> (t, Vec.fromList [i,s])) $ scored' m
map2scored :: Ord t => Map t (Vec.Vector Double) -> [Scored t] map2scored :: Ord t => Map t (Vec.Vector Double) -> V.Vector (Scored t)
map2scored = map (\(t, ds) -> Scored t (Vec.head ds) (Vec.last ds)) . Map.toList map2scored = V.map (\(t, ds) -> Scored t (Vec.head ds) (Vec.last ds)) . V.fromList . Map.toList
-- TODO change type with (x,y) -- TODO change type with (x,y)
data Scored ts = Scored data Scored ts = Scored
......
...@@ -25,20 +25,17 @@ module Gargantext.Core.Text.Metrics.FrequentItemSet ...@@ -25,20 +25,17 @@ module Gargantext.Core.Text.Metrics.FrequentItemSet
) )
where where
import Data.List (concat, null)
import Data.Map.Strict (Map)
import Data.Maybe (catMaybes)
import Data.Set (Set)
import Gargantext.Prelude
import HLCM
import Prelude (Functor(..)) -- TODO import Prelude (Functor(..)) -- TODO
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.Map.Strict (Map)
import qualified Data.Set as Set import qualified Data.Set as Set
import Data.Set (Set)
import qualified Data.Vector as V import qualified Data.Vector as V
import Data.List (concat, null)
import Data.Maybe (catMaybes)
import HLCM
import Gargantext.Prelude
data Size = Point Int | Segment Int Int data Size = Point Int | Segment Int Int
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
{-| {-|
Module : Gargantext.Core.Text.Metrics.Freq Module : Gargantext.Core.Text.Metrics.Utils
Description : Some functions to count. Description : Some functions to count.
Copyright : (c) CNRS, 2017-Present Copyright : (c) CNRS, 2017-Present
License : AGPL + CECILL v3 License : AGPL + CECILL v3
...@@ -10,7 +10,7 @@ Portability : POSIX ...@@ -10,7 +10,7 @@ Portability : POSIX
-} -}
module Gargantext.Core.Text.Metrics.Freq where module Gargantext.Core.Text.Metrics.Utils where
import Gargantext.Prelude import Gargantext.Prelude
import Data.Map (empty, Map, insertWith, toList) import Data.Map (empty, Map, insertWith, toList)
......
...@@ -107,8 +107,6 @@ $(deriveJSON (unPrefix "_") ''PosSentences) ...@@ -107,8 +107,6 @@ $(deriveJSON (unPrefix "_") ''PosSentences)
-- }, -- },
-- --
corenlp' :: ( FromJSON a corenlp' :: ( FromJSON a
, ConvertibleStrings p ByteString , ConvertibleStrings p ByteString
) )
......
...@@ -20,6 +20,7 @@ module Gargantext.Core.Types.Main where ...@@ -20,6 +20,7 @@ module Gargantext.Core.Types.Main where
import Data.Aeson (FromJSON, ToJSON) import Data.Aeson (FromJSON, ToJSON)
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Hashable (Hashable)
import Data.Map (fromList, lookup) import Data.Map (fromList, lookup)
import Data.Semigroup (Semigroup(..)) import Data.Semigroup (Semigroup(..))
import Data.Swagger import Data.Swagger
...@@ -59,6 +60,7 @@ instance ToSchema ListType ...@@ -59,6 +60,7 @@ instance ToSchema ListType
instance ToParamSchema ListType instance ToParamSchema ListType
instance Arbitrary ListType where instance Arbitrary ListType where
arbitrary = elements [minBound..maxBound] arbitrary = elements [minBound..maxBound]
instance Hashable ListType
instance Semigroup ListType instance Semigroup ListType
where where
......
...@@ -14,11 +14,11 @@ Portability : POSIX ...@@ -14,11 +14,11 @@ Portability : POSIX
module Gargantext.Core.Viz.Chart module Gargantext.Core.Viz.Chart
where where
import Data.List (unzip, sortOn) import Data.List (sortOn)
import Data.Map (toList) import Data.Map (toList)
import qualified Data.List as List import qualified Data.List as List
import qualified Data.Map as Map
import Data.Maybe (catMaybes) import Data.Maybe (catMaybes)
import qualified Data.Vector as V
import Gargantext.Core.Types.Main import Gargantext.Core.Types.Main
import Gargantext.Database.Admin.Config import Gargantext.Database.Admin.Config
...@@ -33,17 +33,21 @@ import Gargantext.Core.Text.Metrics.Count (occurrencesWith) ...@@ -33,17 +33,21 @@ import Gargantext.Core.Text.Metrics.Count (occurrencesWith)
-- Pie Chart -- Pie Chart
import Gargantext.API.Ngrams.NgramsTree import Gargantext.API.Ngrams.NgramsTree
import Gargantext.API.Ngrams.Tools import Gargantext.API.Ngrams.Tools
import Gargantext.API.Ngrams.Types
import Gargantext.Core.Types import Gargantext.Core.Types
import Gargantext.Database.Action.Flow import Gargantext.Database.Action.Flow
import Gargantext.Database.Action.Metrics.NgramsByNode import Gargantext.Database.Action.Metrics.NgramsByNode
import Gargantext.Database.Schema.Ngrams import Gargantext.Database.Schema.Ngrams
import Gargantext.Core.Viz.Types import Gargantext.Core.Viz.Types
import qualified Data.HashMap.Strict as HashMap
histoData :: CorpusId -> Cmd err Histo histoData :: CorpusId -> Cmd err Histo
histoData cId = do histoData cId = do
dates <- selectDocsDates cId dates <- selectDocsDates cId
let (ls, css) = unzip let (ls, css) = V.unzip
$ sortOn fst $ V.fromList
$ sortOn fst -- TODO Vector.sortOn
$ toList $ toList
$ occurrencesWith identity dates $ occurrencesWith identity dates
pure (Histo ls css) pure (Histo ls css)
...@@ -58,20 +62,20 @@ chartData cId nt lt = do ...@@ -58,20 +62,20 @@ chartData cId nt lt = do
ts <- mapTermListRoot ls nt <$> getRepo ts <- mapTermListRoot ls nt <$> getRepo
let let
dico = filterListWithRoot lt ts dico = filterListWithRoot lt ts
terms = catMaybes $ List.concat $ map (\(a,b) -> [Just a, b]) $ Map.toList dico terms = catMaybes $ List.concat $ map (\(a,b) -> [Just a, b]) $ HashMap.toList dico
group dico' x = case Map.lookup x dico' of group dico' x = case HashMap.lookup x dico' of
Nothing -> x Nothing -> x
Just x' -> maybe x identity x' Just x' -> maybe x identity x'
(_total,mapTerms) <- countNodesByNgramsWith (group dico) (_total,mapTerms) <- countNodesByNgramsWith (group dico)
<$> getNodesByNgramsOnlyUser cId (ls' <> ls) nt terms <$> getNodesByNgramsOnlyUser cId (ls' <> ls) nt terms
let (dates, count) = unzip $ map (\(t,(d,_)) -> (t, d)) $ Map.toList mapTerms let (dates, count) = V.unzip $ fmap (\(NgramsTerm t,(d,_)) -> (t, d)) $ V.fromList $ HashMap.toList mapTerms
pure (Histo dates (map round count)) pure (Histo dates (round <$> count))
treeData :: FlowCmdM env err m treeData :: FlowCmdM env err m
=> CorpusId -> NgramsType -> ListType => CorpusId -> NgramsType -> ListType
-> m [NgramsTree] -> m (V.Vector NgramsTree)
treeData cId nt lt = do treeData cId nt lt = do
ls' <- selectNodesWithUsername NodeList userMaster ls' <- selectNodesWithUsername NodeList userMaster
ls <- map (_node_id) <$> getListsWithParentId cId ls <- map (_node_id) <$> getListsWithParentId cId
...@@ -79,10 +83,10 @@ treeData cId nt lt = do ...@@ -79,10 +83,10 @@ treeData cId nt lt = do
let let
dico = filterListWithRoot lt ts dico = filterListWithRoot lt ts
terms = catMaybes $ List.concat $ map (\(a,b) -> [Just a, b]) $ Map.toList dico terms = catMaybes $ List.concat $ map (\(a,b) -> [Just a, b]) $ HashMap.toList dico
cs' <- getNodesByNgramsOnlyUser cId (ls' <> ls) nt terms cs' <- getNodesByNgramsOnlyUser cId (ls' <> ls) nt terms
m <- getListNgrams ls nt m <- getListNgrams ls nt
pure $ toTree lt cs' m pure $ V.fromList $ toTree lt cs' m
...@@ -18,38 +18,36 @@ module Gargantext.Core.Viz.Graph.API ...@@ -18,38 +18,36 @@ module Gargantext.Core.Viz.Graph.API
import Control.Lens (set, (^.), _Just, (^?)) import Control.Lens (set, (^.), _Just, (^?))
import Data.Aeson import Data.Aeson
import qualified Data.Map as Map
import Data.Swagger import Data.Swagger
import Data.Text import Data.Text
import Debug.Trace (trace) import Debug.Trace (trace)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Servant
import Servant.Job.Async
import Servant.XML
import Gargantext.API.Admin.Orchestrator.Types import Gargantext.API.Admin.Orchestrator.Types
import Gargantext.API.Ngrams.Types (NgramsRepo, r_version)
import Gargantext.API.Ngrams.Tools import Gargantext.API.Ngrams.Tools
import Gargantext.API.Ngrams.Types (NgramsRepo, r_version)
import Gargantext.API.Prelude import Gargantext.API.Prelude
import Gargantext.Core.Methods.Distances (Distance(..), GraphMetric(..))
import Gargantext.Core.Types.Main import Gargantext.Core.Types.Main
import Gargantext.Core.Viz.Graph
import Gargantext.Core.Viz.Graph.GEXF ()
import Gargantext.Core.Viz.Graph.Tools -- (cooc2graph)
import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsOnlyUser) import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsOnlyUser)
import Gargantext.Database.Action.Node (mkNodeWithParent) import Gargantext.Database.Action.Node (mkNodeWithParent)
import Gargantext.Database.Admin.Config import Gargantext.Database.Admin.Config
import Gargantext.Database.Admin.Types.Node import Gargantext.Database.Admin.Types.Node
import Gargantext.Database.Prelude (Cmd) import Gargantext.Database.Prelude (Cmd)
import Gargantext.Database.Query.Table.Node import Gargantext.Database.Query.Table.Node
import Gargantext.Database.Query.Table.Node.User (getNodeUser)
import Gargantext.Database.Query.Table.Node.Error (HasNodeError) import Gargantext.Database.Query.Table.Node.Error (HasNodeError)
import Gargantext.Database.Query.Table.Node.Select import Gargantext.Database.Query.Table.Node.Select
import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata) import Gargantext.Database.Query.Table.Node.UpdateOpaleye (updateHyperdata)
import Gargantext.Database.Query.Table.Node.User (getNodeUser)
import Gargantext.Database.Schema.Ngrams import Gargantext.Database.Schema.Ngrams
import Gargantext.Database.Schema.Node (node_parentId, node_hyperdata, node_name, node_userId) import Gargantext.Database.Schema.Node (node_parentId, node_hyperdata, node_name, node_userId)
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Core.Viz.Graph import Servant
import Gargantext.Core.Viz.Graph.GEXF () import Servant.Job.Async
import Gargantext.Core.Viz.Graph.Tools -- (cooc2graph) import Servant.XML
import Gargantext.Core.Methods.Distances (Distance(..), GraphMetric(..)) import qualified Data.HashMap.Strict as HashMap
------------------------------------------------------------------------ ------------------------------------------------------------------------
-- | There is no Delete specific API for Graph since it can be deleted -- | There is no Delete specific API for Graph since it can be deleted
-- as simple Node. -- as simple Node.
...@@ -150,10 +148,10 @@ computeGraph cId d nt repo = do ...@@ -150,10 +148,10 @@ computeGraph cId d nt repo = do
let ngs = filterListWithRoot MapTerm $ mapTermListRoot [lId] nt repo let ngs = filterListWithRoot MapTerm $ mapTermListRoot [lId] nt repo
-- TODO split diagonal -- TODO split diagonal
myCooc <- Map.filter (>1) myCooc <- HashMap.filter (>1)
<$> getCoocByNgrams (Diagonal True) <$> getCoocByNgrams (Diagonal True)
<$> groupNodesByNgrams ngs <$> groupNodesByNgrams ngs
<$> getNodesByNgramsOnlyUser cId (lIds <> [lId]) nt (Map.keys ngs) <$> getNodesByNgramsOnlyUser cId (lIds <> [lId]) nt (HashMap.keys ngs)
graph <- liftBase $ cooc2graph d 0 myCooc graph <- liftBase $ cooc2graph d 0 myCooc
......
...@@ -13,28 +13,31 @@ Portability : POSIX ...@@ -13,28 +13,31 @@ Portability : POSIX
module Gargantext.Core.Viz.Graph.Tools module Gargantext.Core.Viz.Graph.Tools
where where
import Debug.Trace (trace)
import Data.Graph.Clustering.Louvain.Utils (LouvainNode(..))
-- import Data.Graph.Clustering.Louvain (hLouvain, {-iLouvainMap-}) -- import Data.Graph.Clustering.Louvain (hLouvain, {-iLouvainMap-})
import Data.Graph.Clustering.Louvain.CplusPlus (cLouvain) import Data.Graph.Clustering.Louvain.CplusPlus (cLouvain)
import Data.Graph.Clustering.Louvain.Utils (LouvainNode(..))
import Data.Map (Map) import Data.Map (Map)
import qualified Data.Set as Set import Data.HashMap.Strict (HashMap)
import Data.Text (Text) import Data.Text (Text)
import Gargantext.Prelude import Debug.Trace (trace)
import GHC.Float (sin, cos)
import Gargantext.API.Ngrams.Types (NgramsTerm(..))
import Gargantext.Core.Methods.Distances (Distance(..), measure)
import Gargantext.Core.Methods.Graph.BAC.Proxemy (confluence)
import Gargantext.Core.Statistics import Gargantext.Core.Statistics
import Gargantext.Core.Viz.Graph import Gargantext.Core.Viz.Graph
import Gargantext.Core.Viz.Graph.Bridgeness (bridgeness) import Gargantext.Core.Viz.Graph.Bridgeness (bridgeness)
import Gargantext.Core.Methods.Distances (Distance(..), measure)
import Gargantext.Core.Viz.Graph.Index (createIndices, toIndex, map2mat, mat2map, Index)
import Gargantext.Core.Viz.Graph.IGraph (mkGraphUfromEdges) import Gargantext.Core.Viz.Graph.IGraph (mkGraphUfromEdges)
import Gargantext.Core.Methods.Graph.BAC.Proxemy (confluence) import Gargantext.Core.Viz.Graph.Index (createIndices, toIndex, map2mat, mat2map, Index)
import GHC.Float (sin, cos) import Gargantext.Prelude
import qualified IGraph as Igraph
import IGraph.Random -- (Gen(..)) import IGraph.Random -- (Gen(..))
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Set as Set
import qualified Data.Vector.Storable as Vec
import qualified IGraph as Igraph
import qualified IGraph.Algorithms.Layout as Layout import qualified IGraph.Algorithms.Layout as Layout
import qualified Data.Vector.Storable as Vec import qualified Data.HashMap.Strict as HashMap
import qualified Data.Map as Map
import qualified Data.List as List
type Threshold = Double type Threshold = Double
...@@ -54,13 +57,15 @@ cooc2graph' distance threshold myCooc = distanceMap ...@@ -54,13 +57,15 @@ cooc2graph' distance threshold myCooc = distanceMap
cooc2graph :: Distance cooc2graph :: Distance
-> Threshold -> Threshold
-> (Map (Text, Text) Int) -> HashMap (NgramsTerm, NgramsTerm) Int
-> IO Graph -> IO Graph
cooc2graph distance threshold myCooc = do cooc2graph distance threshold myCooc = do
printDebug "cooc2graph" distance printDebug "cooc2graph" distance
let let
(ti, _) = createIndices myCooc -- TODO remove below
myCooc' = toIndex ti myCooc theMatrix = Map.fromList $ HashMap.toList myCooc
(ti, _) = createIndices theMatrix
myCooc' = toIndex ti theMatrix
matCooc = map2mat 0 (Map.size ti) matCooc = map2mat 0 (Map.size ti)
$ Map.filterWithKey (\(a,b) _ -> a /= b) $ Map.filterWithKey (\(a,b) _ -> a /= b)
$ Map.filter (> 1) myCooc' $ Map.filter (> 1) myCooc'
...@@ -87,7 +92,7 @@ cooc2graph distance threshold myCooc = do ...@@ -87,7 +92,7 @@ cooc2graph distance threshold myCooc = do
$ bridgeness rivers partitions distanceMap $ bridgeness rivers partitions distanceMap
confluence' = confluence (Map.keys bridgeness') 3 True False confluence' = confluence (Map.keys bridgeness') 3 True False
pure $ data2graph (Map.toList ti) myCooc' bridgeness' confluence' partitions pure $ data2graph (Map.toList $ Map.mapKeys unNgramsTerm ti) myCooc' bridgeness' confluence' partitions
......
...@@ -14,34 +14,32 @@ Portability : POSIX ...@@ -14,34 +14,32 @@ Portability : POSIX
module Gargantext.Core.Viz.Phylo.Main module Gargantext.Core.Viz.Phylo.Main
where where
import Data.GraphViz import Data.GraphViz
import qualified Data.ByteString as DB
import qualified Data.List as List
import qualified Data.Map as Map
import Data.Maybe import Data.Maybe
import qualified Data.Text as Text
import Data.Text (Text) import Data.Text (Text)
import Debug.Trace (trace) import Debug.Trace (trace)
import GHC.IO (FilePath) import GHC.IO (FilePath)
import Gargantext.API.Ngrams.Tools (getTermsWith) import Gargantext.API.Ngrams.Tools (getTermsWith)
import Gargantext.Core.Types import Gargantext.API.Ngrams.Types
import Gargantext.Database.Action.Flow
import Gargantext.Database.Admin.Types.Hyperdata
import Gargantext.Database.Query.Table.Node(defaultList)
import Gargantext.Database.Query.Table.NodeNode (selectDocs)
import Gargantext.Database.Schema.Ngrams (NgramsType(..))
import Gargantext.Prelude
import Gargantext.Core.Text.Context (TermList) import Gargantext.Core.Text.Context (TermList)
import Gargantext.Core.Text.Terms.WithList import Gargantext.Core.Text.Terms.WithList
import Gargantext.Core.Types
import Gargantext.Core.Viz.Phylo hiding (Svg, Dot) import Gargantext.Core.Viz.Phylo hiding (Svg, Dot)
import Gargantext.Core.Viz.Phylo.LevelMaker (toPhylo) import Gargantext.Core.Viz.Phylo.LevelMaker (toPhylo)
import Gargantext.Core.Viz.Phylo.Tools import Gargantext.Core.Viz.Phylo.Tools
import Gargantext.Core.Viz.Phylo.View.Export import Gargantext.Core.Viz.Phylo.View.Export
import Gargantext.Core.Viz.Phylo.View.ViewMaker -- TODO Just Maker is fine import Gargantext.Core.Viz.Phylo.View.ViewMaker -- TODO Just Maker is fine
import Gargantext.Database.Action.Flow
import Gargantext.Database.Admin.Types.Hyperdata
import Gargantext.Database.Query.Table.Node(defaultList)
import Gargantext.Database.Query.Table.NodeNode (selectDocs)
import Gargantext.Database.Schema.Ngrams (NgramsType(..))
import Gargantext.Prelude
import qualified Data.ByteString as DB
import qualified Data.List as List
import qualified Data.Map as Map
import qualified Data.Text as Text
import qualified Data.HashMap.Strict as HashMap
type MinSizeBranch = Int type MinSizeBranch = Int
...@@ -51,7 +49,7 @@ flowPhylo :: FlowCmdM env err m ...@@ -51,7 +49,7 @@ flowPhylo :: FlowCmdM env err m
flowPhylo cId = do flowPhylo cId = do
list <- defaultList cId list <- defaultList cId
termList <- Map.toList <$> getTermsWith Text.words [list] NgramsTerms MapTerm termList <- HashMap.toList <$> getTermsWith (Text.words . unNgramsTerm) [list] NgramsTerms MapTerm
docs' <- catMaybes docs' <- catMaybes
<$> map (\h -> (,) <$> _hd_publication_year h <$> map (\h -> (,) <$> _hd_publication_year h
......
...@@ -9,6 +9,8 @@ module Gargantext.Core.Viz.Types where ...@@ -9,6 +9,8 @@ module Gargantext.Core.Viz.Types where
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.Swagger import Data.Swagger
import Data.Vector (Vector)
import qualified Data.Vector as V
import Protolude import Protolude
import Test.QuickCheck (elements) import Test.QuickCheck (elements)
import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary) import Test.QuickCheck.Arbitrary (Arbitrary, arbitrary)
...@@ -23,8 +25,8 @@ data Chart = ChartHisto | ChartScatter | ChartPie ...@@ -23,8 +25,8 @@ data Chart = ChartHisto | ChartScatter | ChartPie
deriving (Generic) deriving (Generic)
-- TODO use UTCTime -- TODO use UTCTime
data Histo = Histo { histo_dates :: ![Text] data Histo = Histo { histo_dates :: !(Vector Text)
, histo_count :: ![Int] , histo_count :: !(Vector Int)
} }
deriving (Show, Generic) deriving (Show, Generic)
...@@ -32,7 +34,7 @@ instance ToSchema Histo where ...@@ -32,7 +34,7 @@ instance ToSchema Histo where
declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "histo_") declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "histo_")
instance Arbitrary Histo instance Arbitrary Histo
where where
arbitrary = elements [ Histo ["2012"] [1] arbitrary = elements [ Histo (V.singleton "2012") (V.singleton 1)
, Histo ["2013"] [1] , Histo (V.singleton "2013") (V.singleton 1)
] ]
deriveJSON (unPrefix "histo_") ''Histo deriveJSON (unPrefix "histo_") ''Histo
module Gargantext.Data.HashMap.Strict.Utils where
import Data.HashMap.Strict (HashMap)
import Data.Hashable (Hashable)
import Gargantext.Prelude
import qualified Data.HashMap.Strict as HashMap
------------------------------------------------------------------------
unionsWith :: (Foldable f, Eq k, Hashable k) => (a->a->a) -> f (HashMap k a) -> HashMap k a
unionsWith f = foldl' (HashMap.unionWith f) HashMap.empty
------------------------------------------------------------------------
-- | Partition the map according to some predicate. The first map contains all
-- elements that satisfy the predicate, the second all elements that fail the
-- predicate.
partition :: (Ord k, Hashable k) => (a -> Bool) -> HashMap k a -> (HashMap k a, HashMap k a)
partition p m = (HashMap.filter p m, HashMap.filter (not . p) m)
-- | Partition the map according to some predicate. The first map contains all
-- elements that satisfy the predicate, the second all elements that fail the
-- predicate.
partitionWithKey :: (Ord a, Hashable k) => (k -> a -> Bool) -> HashMap k a -> (HashMap k a, HashMap k a)
partitionWithKey p m = (HashMap.filterWithKey p m, HashMap.filterWithKey (\k -> not . p k) m)
------------------------------------------------------------------------
-- getKeyWithMaxValue :: Hashable k => HashMap k a -> Maybe k
getKeysOrderedByValueMaxFirst :: (Ord k, Hashable k, Ord a) => HashMap k a -> [k]
getKeysOrderedByValueMaxFirst m = go [] Nothing (HashMap.toList m)
where
go ks _ [] = ks
go ks Nothing ((k,v):rest) = go (k:ks) (Just v) rest
go ks (Just u) ((k,v):rest)
| v < u = go ks (Just u) rest
| v > u = go [k] (Just v) rest
| otherwise = go (k:ks) (Just v) rest
...@@ -17,13 +17,14 @@ module Gargantext.Database.Action.Flow.Pairing ...@@ -17,13 +17,14 @@ module Gargantext.Database.Action.Flow.Pairing
where where
import Control.Lens (_Just, (^.)) import Control.Lens (_Just, (^.))
import Data.Map (Map, fromList, fromListWith) import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import Data.Maybe (catMaybes, fromMaybe) import Data.Maybe (catMaybes, fromMaybe)
import Data.Set (Set) import Data.Set (Set)
import Data.Text (Text)
import Gargantext.API.Ngrams.Tools import Gargantext.API.Ngrams.Tools
import Gargantext.API.Ngrams.Types (NgramsTerm(..))
import Gargantext.API.Prelude (GargNoServer) import Gargantext.API.Prelude (GargNoServer)
import Gargantext.Core.Types (TableResult(..), Term) import Gargantext.Core.Types (TableResult(..))
import Gargantext.Core.Types.Main import Gargantext.Core.Types.Main
import Gargantext.Database import Gargantext.Database
import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsOnlyUser) import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsOnlyUser)
...@@ -39,11 +40,10 @@ import Gargantext.Database.Schema.Ngrams -- (NgramsType(..)) ...@@ -39,11 +40,10 @@ import Gargantext.Database.Schema.Ngrams -- (NgramsType(..))
import Gargantext.Database.Schema.Node import Gargantext.Database.Schema.Node
import Gargantext.Prelude hiding (sum) import Gargantext.Prelude hiding (sum)
import Opaleye import Opaleye
import qualified Data.List as List import qualified Data.HashMap.Strict as HashMap
import qualified Data.Map as Map import qualified Data.List as List
import qualified Data.Set as Set import qualified Data.Set as Set
import qualified Data.Text as DT import qualified Data.Text as DT
-- | isPairedWith -- | isPairedWith
-- All NodeAnnuaire paired with a Corpus of NodeId nId: -- All NodeAnnuaire paired with a Corpus of NodeId nId:
...@@ -79,7 +79,7 @@ dataPairing :: AnnuaireId ...@@ -79,7 +79,7 @@ dataPairing :: AnnuaireId
-> (CorpusId, ListId, NgramsType) -> (CorpusId, ListId, NgramsType)
-> (ContactName -> Projected) -> (ContactName -> Projected)
-> (DocAuthor -> Projected) -> (DocAuthor -> Projected)
-> GargNoServer (Map ContactId (Set DocId)) -> GargNoServer (HashMap ContactId (Set DocId))
dataPairing aId (cId, lId, ngt) fc fa = do dataPairing aId (cId, lId, ngt) fc fa = do
mc <- getNgramsContactId aId mc <- getNgramsContactId aId
md <- getNgramsDocId cId lId ngt md <- getNgramsDocId cId lId ngt
...@@ -87,14 +87,14 @@ dataPairing aId (cId, lId, ngt) fc fa = do ...@@ -87,14 +87,14 @@ dataPairing aId (cId, lId, ngt) fc fa = do
printDebug "ngramsContactId" mc printDebug "ngramsContactId" mc
printDebug "ngramsDocId" md printDebug "ngramsDocId" md
let let
from = projectionFrom (Set.fromList $ Map.keys mc) fc from = projectionFrom (Set.fromList $ HM.keys mc) fc
to = projectionTo (Set.fromList $ Map.keys md) fa to = projectionTo (Set.fromList $ HM.keys md) fa
pure $ fusion mc $ align from to md pure $ fusion mc $ align from to md
prepareInsert :: Map ContactId (Set DocId) -> [NodeNode] prepareInsert :: HashMap ContactId (Set DocId) -> [NodeNode]
prepareInsert m = map (\(n1,n2) -> NodeNode n1 n2 Nothing Nothing) prepareInsert m = map (\(n1,n2) -> NodeNode n1 n2 Nothing Nothing)
$ List.concat $ List.concat
$ map (\(contactId, setDocIds) $ map (\(contactId, setDocIds)
...@@ -102,21 +102,21 @@ prepareInsert m = map (\(n1,n2) -> NodeNode n1 n2 Nothing Nothing) ...@@ -102,21 +102,21 @@ prepareInsert m = map (\(n1,n2) -> NodeNode n1 n2 Nothing Nothing)
-> (contactId, setDocId) -> (contactId, setDocId)
) $ Set.toList setDocIds ) $ Set.toList setDocIds
) )
$ Map.toList m $ HM.toList m
------------------------------------------------------------------------ ------------------------------------------------------------------------
type ContactName = Text type ContactName = NgramsTerm
type DocAuthor = Text type DocAuthor = NgramsTerm
type Projected = Text type Projected = NgramsTerm
projectionFrom :: Set ContactName -> (ContactName -> Projected) -> Map ContactName Projected projectionFrom :: Set ContactName -> (ContactName -> Projected) -> HashMap ContactName Projected
projectionFrom ss f = fromList $ map (\s -> (s, f s)) (Set.toList ss) projectionFrom ss f = HM.fromList $ map (\s -> (s, f s)) (Set.toList ss) -- use HS.toMap
projectionTo :: Set DocAuthor -> (DocAuthor -> Projected) -> Map Projected (Set DocAuthor) projectionTo :: Set DocAuthor -> (DocAuthor -> Projected) -> HashMap Projected (Set DocAuthor)
projectionTo ss f = fromListWith (<>) $ map (\s -> (f s, Set.singleton s)) (Set.toList ss) projectionTo ss f = HM.fromListWith (<>) $ map (\s -> (f s, Set.singleton s)) (Set.toList ss) -- use HS.toMap
------------------------------------------------------------------------ ------------------------------------------------------------------------
takeName :: Term -> Term takeName :: NgramsTerm -> NgramsTerm
takeName texte = DT.toLower texte' takeName (NgramsTerm texte) = NgramsTerm $ DT.toLower texte'
where where
texte' = maybe texte (\x -> if DT.length x > 3 then x else texte) texte' = maybe texte (\x -> if DT.length x > 3 then x else texte)
(lastName' texte) (lastName' texte)
...@@ -124,51 +124,51 @@ takeName texte = DT.toLower texte' ...@@ -124,51 +124,51 @@ takeName texte = DT.toLower texte'
------------------------------------------------------------------------ ------------------------------------------------------------------------
align :: Map ContactName Projected align :: HashMap ContactName Projected
-> Map Projected (Set DocAuthor) -> HashMap Projected (Set DocAuthor)
-> Map DocAuthor (Set DocId) -> HashMap DocAuthor (Set DocId)
-> Map ContactName (Set DocId) -> HashMap ContactName (Set DocId)
align mc ma md = fromListWith (<>) align mc ma md = HM.fromListWith (<>)
$ map (\c -> (c, getProjection md $ testProjection c mc ma)) $ map (\c -> (c, getProjection md $ testProjection c mc ma))
$ Map.keys mc $ HM.keys mc
where where
getProjection :: Map DocAuthor (Set DocId) -> Set DocAuthor -> Set DocId getProjection :: HashMap DocAuthor (Set DocId) -> Set DocAuthor -> Set DocId
getProjection ma' sa' = getProjection ma' sa' =
if Set.null sa' if Set.null sa'
then Set.empty then Set.empty
else Set.unions $ sets ma' sa' else Set.unions $ sets ma' sa'
where where
sets ma'' sa'' = Set.map (\s -> lookup s ma'') sa'' sets ma'' sa'' = Set.map (\s -> lookup s ma'') sa''
lookup s' ma''= fromMaybe Set.empty (Map.lookup s' ma'') lookup s' ma''= fromMaybe Set.empty (HM.lookup s' ma'')
testProjection :: ContactName testProjection :: ContactName
-> Map ContactName Projected -> HashMap ContactName Projected
-> Map Projected (Set DocAuthor) -> HashMap Projected (Set DocAuthor)
-> Set DocAuthor -> Set DocAuthor
testProjection cn' mc' ma' = case Map.lookup cn' mc' of testProjection cn' mc' ma' = case HM.lookup cn' mc' of
Nothing -> Set.empty Nothing -> Set.empty
Just c -> case Map.lookup c ma' of Just c -> case HM.lookup c ma' of
Nothing -> Set.empty Nothing -> Set.empty
Just a -> a Just a -> a
fusion :: Map ContactName (Set ContactId) fusion :: HashMap ContactName (Set ContactId)
-> Map ContactName (Set DocId) -> HashMap ContactName (Set DocId)
-> Map ContactId (Set DocId) -> HashMap ContactId (Set DocId)
fusion mc md = Map.fromListWith (<>) fusion mc md = HM.fromListWith (<>)
$ catMaybes $ catMaybes
$ [ (,) <$> Just cId <*> Map.lookup cn md $ [ (,) <$> Just cId <*> HM.lookup cn md
| (cn, setContactId) <- Map.toList mc | (cn, setContactId) <- HM.toList mc
, cId <- Set.toList setContactId , cId <- Set.toList setContactId
] ]
------------------------------------------------------------------------ ------------------------------------------------------------------------
getNgramsContactId :: AnnuaireId getNgramsContactId :: AnnuaireId
-> Cmd err (Map ContactName (Set NodeId)) -> Cmd err (HashMap ContactName (Set NodeId))
getNgramsContactId aId = do getNgramsContactId aId = do
contacts <- getAllContacts aId contacts <- getAllContacts aId
pure $ fromListWith (<>) pure $ HM.fromListWith (<>)
$ catMaybes $ catMaybes
$ map (\contact -> (,) <$> contact^.(node_hyperdata . hc_who . _Just . cw_lastName) $ map (\contact -> (,) <$> (NgramsTerm <$> contact^.(node_hyperdata . hc_who . _Just . cw_lastName))
<*> Just ( Set.singleton (contact^.node_id)) <*> Just ( Set.singleton (contact^.node_id))
) (tr_docs contacts) ) (tr_docs contacts)
...@@ -176,11 +176,11 @@ getNgramsContactId aId = do ...@@ -176,11 +176,11 @@ getNgramsContactId aId = do
getNgramsDocId :: CorpusId getNgramsDocId :: CorpusId
-> ListId -> ListId
-> NgramsType -> NgramsType
-> GargNoServer (Map DocAuthor (Set NodeId)) -> GargNoServer (HashMap DocAuthor (Set NodeId))
getNgramsDocId cId lId nt = do getNgramsDocId cId lId nt = do
repo <- getRepo repo <- getRepo
lIds <- selectNodesWithUsername NodeList userMaster lIds <- selectNodesWithUsername NodeList userMaster
let ngs = filterListWithRoot MapTerm $ mapTermListRoot [lId] nt repo let ngs = filterListWithRoot MapTerm $ mapTermListRoot [lId] nt repo
groupNodesByNgrams ngs groupNodesByNgrams ngs
<$> getNodesByNgramsOnlyUser cId (lIds <> [lId]) nt (Map.keys ngs) <$> getNodesByNgramsOnlyUser cId (lIds <> [lId]) nt (HashMap.keys ngs)
...@@ -10,17 +10,14 @@ Portability : POSIX ...@@ -10,17 +10,14 @@ Portability : POSIX
Node API Node API
-} -}
module Gargantext.Database.Action.Metrics module Gargantext.Database.Action.Metrics
where where
import Data.Map (Map) import Data.HashMap.Strict (HashMap)
import qualified Data.Map as Map import Data.Vector (Vector)
import Data.Text (Text)
import Gargantext.API.Ngrams.Types (TabType(..), ngramsTypeFromTabType)
import Gargantext.API.Ngrams.Tools (filterListWithRoot, groupNodesByNgrams, Diagonal(..), getCoocByNgrams, mapTermListRoot, RootTerm, getRepo) import Gargantext.API.Ngrams.Tools (filterListWithRoot, groupNodesByNgrams, Diagonal(..), getCoocByNgrams, mapTermListRoot, RootTerm, getRepo)
import Gargantext.API.Ngrams.Types (TabType(..), ngramsTypeFromTabType, NgramsTerm)
import Gargantext.Core.Text.Metrics (scored, Scored(..), {-localMetrics, toScored-})
import Gargantext.Core.Types (ListType(..), Limit, NodeType(..)) import Gargantext.Core.Types (ListType(..), Limit, NodeType(..))
import Gargantext.Database.Action.Flow.Types (FlowCmdM) import Gargantext.Database.Action.Flow.Types (FlowCmdM)
import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsOnlyUser{-, getTficfWith-}) import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsOnlyUser{-, getTficfWith-})
...@@ -29,21 +26,22 @@ import Gargantext.Database.Admin.Types.Node (ListId, CorpusId) ...@@ -29,21 +26,22 @@ import Gargantext.Database.Admin.Types.Node (ListId, CorpusId)
import Gargantext.Database.Query.Table.Node (defaultList) import Gargantext.Database.Query.Table.Node (defaultList)
import Gargantext.Database.Query.Table.Node.Select import Gargantext.Database.Query.Table.Node.Select
import Gargantext.Prelude import Gargantext.Prelude
import Gargantext.Core.Text.Metrics (scored, Scored(..), {-localMetrics, toScored-}) import qualified Data.HashMap.Strict as HM
getMetrics :: FlowCmdM env err m getMetrics :: FlowCmdM env err m
=> CorpusId -> Maybe ListId -> TabType -> Maybe Limit => CorpusId -> Maybe ListId -> TabType -> Maybe Limit
-> m (Map Text (ListType, Maybe Text), [Scored Text]) -> m (HashMap NgramsTerm (ListType, Maybe NgramsTerm), Vector (Scored NgramsTerm))
getMetrics cId maybeListId tabType maybeLimit = do getMetrics cId maybeListId tabType maybeLimit = do
(ngs, _, myCooc) <- getNgramsCooc cId maybeListId tabType maybeLimit (ngs, _, myCooc) <- getNgramsCooc cId maybeListId tabType maybeLimit
-- TODO HashMap
pure (ngs, scored myCooc) pure (ngs, scored myCooc)
getNgramsCooc :: (FlowCmdM env err m) getNgramsCooc :: (FlowCmdM env err m)
=> CorpusId -> Maybe ListId -> TabType -> Maybe Limit => CorpusId -> Maybe ListId -> TabType -> Maybe Limit
-> m ( Map Text (ListType, Maybe Text) -> m ( HashMap NgramsTerm (ListType, Maybe NgramsTerm)
, Map Text (Maybe RootTerm) , HashMap NgramsTerm (Maybe RootTerm)
, Map (Text, Text) Int , HashMap (NgramsTerm, NgramsTerm) Int
) )
getNgramsCooc cId maybeListId tabType maybeLimit = do getNgramsCooc cId maybeListId tabType maybeLimit = do
(ngs', ngs) <- getNgrams cId maybeListId tabType (ngs', ngs) <- getNgrams cId maybeListId tabType
...@@ -55,17 +53,19 @@ getNgramsCooc cId maybeListId tabType maybeLimit = do ...@@ -55,17 +53,19 @@ getNgramsCooc cId maybeListId tabType maybeLimit = do
lId <- defaultList cId lId <- defaultList cId
lIds <- selectNodesWithUsername NodeList userMaster lIds <- selectNodesWithUsername NodeList userMaster
myCooc <- Map.filter (>1) <$> getCoocByNgrams (Diagonal True) myCooc <- HM.filter (>1) <$> getCoocByNgrams (Diagonal True)
<$> groupNodesByNgrams ngs <$> groupNodesByNgrams ngs
<$> getNodesByNgramsOnlyUser cId (lIds <> [lId]) (ngramsTypeFromTabType tabType) <$> getNodesByNgramsOnlyUser cId (lIds <> [lId]) (ngramsTypeFromTabType tabType)
(take' maybeLimit $ Map.keys ngs) (take' maybeLimit $ HM.keys ngs)
pure $ (ngs', ngs, myCooc) pure $ (ngs', ngs, myCooc)
getNgrams :: (FlowCmdM env err m) getNgrams :: (FlowCmdM env err m)
=> CorpusId -> Maybe ListId -> TabType => CorpusId -> Maybe ListId -> TabType
-> m (Map Text (ListType, Maybe Text), Map Text (Maybe RootTerm)) -> m ( HashMap NgramsTerm (ListType, Maybe NgramsTerm)
, HashMap NgramsTerm (Maybe RootTerm)
)
getNgrams cId maybeListId tabType = do getNgrams cId maybeListId tabType = do
lId <- case maybeListId of lId <- case maybeListId of
...@@ -73,7 +73,7 @@ getNgrams cId maybeListId tabType = do ...@@ -73,7 +73,7 @@ getNgrams cId maybeListId tabType = do
Just lId' -> pure lId' Just lId' -> pure lId'
lists <- mapTermListRoot [lId] (ngramsTypeFromTabType tabType) <$> getRepo lists <- mapTermListRoot [lId] (ngramsTypeFromTabType tabType) <$> getRepo
let maybeSyn = Map.unions $ map (\t -> filterListWithRoot t lists) let maybeSyn = HM.unions $ map (\t -> filterListWithRoot t lists)
[MapTerm, StopTerm, CandidateTerm] [MapTerm, StopTerm, CandidateTerm]
pure (lists, maybeSyn) pure (lists, maybeSyn)
...@@ -19,17 +19,16 @@ Portability : POSIX ...@@ -19,17 +19,16 @@ Portability : POSIX
module Gargantext.Database.Action.Metrics.Lists module Gargantext.Database.Action.Metrics.Lists
where where
import Prelude hiding (null, id, map, sum)
import qualified Data.Map as Map
import qualified Data.Vector as Vec
import qualified Gargantext.Database.Action.Metrics as Metrics
import Gargantext.API.Ngrams.Types (TabType(..)) import Gargantext.API.Ngrams.Types (TabType(..))
import Gargantext.Core.Text.Metrics (Scored(..))
import Gargantext.Core.Types -- (NodePoly(..), NodeCorpus, ListId) import Gargantext.Core.Types -- (NodePoly(..), NodeCorpus, ListId)
import Gargantext.Database.Action.Flow.Types (FlowCmdM) import Gargantext.Database.Action.Flow.Types (FlowCmdM)
import Gargantext.Prelude hiding (sum, head) import Gargantext.Prelude hiding (sum, head)
import Gargantext.Core.Text.Metrics (Scored(..)) import Prelude hiding (null, id, map, sum)
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Map as Map
import qualified Data.Vector as Vec
import qualified Gargantext.Database.Action.Metrics as Metrics
{- {-
trainModel :: FlowCmdM env ServantErr m trainModel :: FlowCmdM env ServantErr m
=> Username -> m Score => Username -> m Score
...@@ -50,11 +49,11 @@ getMetrics' cId maybeListId tabType maybeLimit = do ...@@ -50,11 +49,11 @@ getMetrics' cId maybeListId tabType maybeLimit = do
let let
metrics = map (\(Scored t s1 s2) -> (listType t ngs', [Vec.fromList [s1,s2]])) scores metrics = map (\(Scored t s1 s2) -> (listType t ngs', [Vec.fromList [s1,s2]])) scores
listType t m = maybe (panic errorMsg) fst $ Map.lookup t m listType t m = maybe (panic errorMsg) fst $ HashMap.lookup t m
errorMsg = "API.Node.metrics: key absent" errorMsg = "API.Node.metrics: key absent"
{- {-
_ <- Learn.grid 100 110 metrics' metrics' _ <- Learn.grid 100 110 metrics' metrics'
--} --}
pure $ Map.fromListWith (<>) metrics pure $ Map.fromListWith (<>) $ Vec.toList metrics
...@@ -16,40 +16,37 @@ module Gargantext.Database.Action.Metrics.TFICF ...@@ -16,40 +16,37 @@ module Gargantext.Database.Action.Metrics.TFICF
-- import Debug.Trace (trace) -- import Debug.Trace (trace)
-- import Gargantext.Core (Lang(..)) -- import Gargantext.Core (Lang(..))
import Data.Map.Strict (Map, toList, fromList) import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Gargantext.Core.Text.Metrics.TFICF import Gargantext.Core.Text.Metrics.TFICF
import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsUser, getOccByNgramsOnlyFast) import Gargantext.Database.Action.Metrics.NgramsByNode (getNodesByNgramsUser, getOccByNgramsOnlyFast)
import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId) import Gargantext.Database.Admin.Types.Node -- (ListId, CorpusId, NodeId)
import Gargantext.Database.Prelude (Cmd) import Gargantext.Database.Prelude (Cmd)
import Gargantext.Database.Query.Table.NodeNode (selectCountDocs) import Gargantext.Database.Query.Table.NodeNode (selectCountDocs)
import Gargantext.Database.Schema.Ngrams (NgramsType(..)) import Gargantext.Database.Schema.Ngrams (NgramsType(..))
import Gargantext.API.Ngrams.Types
import Gargantext.Prelude import Gargantext.Prelude
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set import qualified Data.Set as Set
getTficf :: UserCorpusId getTficf :: UserCorpusId
-> MasterCorpusId -> MasterCorpusId
-> NgramsType -> NgramsType
-> Cmd err (Map Text Double) -> Cmd err (HashMap NgramsTerm Double)
getTficf cId mId nt = do getTficf cId mId nt = do
mapTextDoubleLocal <- Map.filter (> 1) mapTextDoubleLocal <- HM.filter (> 1)
<$> Map.map (fromIntegral . Set.size) <$> HM.map (fromIntegral . Set.size)
<$> getNodesByNgramsUser cId nt <$> getNodesByNgramsUser cId nt
mapTextDoubleGlobal <- Map.map fromIntegral mapTextDoubleGlobal <- HM.map fromIntegral
<$> getOccByNgramsOnlyFast mId nt (Map.keys mapTextDoubleLocal) <$> getOccByNgramsOnlyFast mId nt (HM.keys mapTextDoubleLocal)
countLocal <- selectCountDocs cId countLocal <- selectCountDocs cId
countGlobal <- selectCountDocs mId countGlobal <- selectCountDocs mId
pure $ fromList [ ( t pure $ HM.mapWithKey (\t n ->
, tficf (TficfInfra (Count n ) tficf (TficfInfra (Count n )
(Total $ fromIntegral countLocal )) (Total $ fromIntegral countLocal))
(TficfSupra (Count $ fromMaybe 0 $ Map.lookup t mapTextDoubleGlobal) (TficfSupra (Count $ fromMaybe 0 $ HM.lookup t mapTextDoubleGlobal)
(Total $ fromIntegral countGlobal)) (Total $ fromIntegral countGlobal))
) ) mapTextDoubleLocal
| (t, n) <- toList mapTextDoubleLocal
]
...@@ -21,8 +21,10 @@ Portability : POSIX ...@@ -21,8 +21,10 @@ Portability : POSIX
module Gargantext.Database.Admin.Types.Hyperdata.List module Gargantext.Database.Admin.Types.Hyperdata.List
where where
import Data.Map (Map) import Data.Vector (Vector)
import qualified Data.Map as Map --import qualified Data.Vector as V
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as HM
import Control.Applicative import Control.Applicative
import Gargantext.Prelude import Gargantext.Prelude
...@@ -34,11 +36,11 @@ import Gargantext.Database.Admin.Types.Metrics (ChartMetrics(..), Metrics) ...@@ -34,11 +36,11 @@ import Gargantext.Database.Admin.Types.Metrics (ChartMetrics(..), Metrics)
------------------------------------------------------------------------ ------------------------------------------------------------------------
data HyperdataList = data HyperdataList =
HyperdataList { _hl_chart :: !(Map TabType (ChartMetrics Histo)) HyperdataList { _hl_chart :: !(HashMap TabType (ChartMetrics Histo))
, _hl_list :: !(Maybe Text) , _hl_list :: !(Maybe Text)
, _hl_pie :: !(Map TabType (ChartMetrics Histo)) , _hl_pie :: !(HashMap TabType (ChartMetrics Histo))
, _hl_scatter :: !(Map TabType Metrics) , _hl_scatter :: !(HashMap TabType Metrics)
, _hl_tree :: !(Map TabType (ChartMetrics [NgramsTree])) , _hl_tree :: !(HashMap TabType (ChartMetrics (Vector NgramsTree)))
} deriving (Show, Generic) } deriving (Show, Generic)
-- HyperdataList { _hl_chart :: !(Maybe (ChartMetrics Histo)) -- HyperdataList { _hl_chart :: !(Maybe (ChartMetrics Histo))
-- , _hl_list :: !(Maybe Text) -- , _hl_list :: !(Maybe Text)
...@@ -49,11 +51,11 @@ data HyperdataList = ...@@ -49,11 +51,11 @@ data HyperdataList =
defaultHyperdataList :: HyperdataList defaultHyperdataList :: HyperdataList
defaultHyperdataList = defaultHyperdataList =
HyperdataList { _hl_chart = Map.empty HyperdataList { _hl_chart = HM.empty
, _hl_list = Nothing , _hl_list = Nothing
, _hl_pie = Map.empty , _hl_pie = HM.empty
, _hl_scatter = Map.empty , _hl_scatter = HM.empty
, _hl_tree = Map.empty , _hl_tree = HM.empty
} }
------------------------------------------------------------------------ ------------------------------------------------------------------------
......
...@@ -5,6 +5,8 @@ module Gargantext.Database.Admin.Types.Metrics where ...@@ -5,6 +5,8 @@ module Gargantext.Database.Admin.Types.Metrics where
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.Swagger import Data.Swagger
import Data.Vector (Vector)
import qualified Data.Vector as V
import Protolude import Protolude
import Test.QuickCheck.Arbitrary import Test.QuickCheck.Arbitrary
...@@ -13,15 +15,15 @@ import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger, wellNamedSchema) ...@@ -13,15 +15,15 @@ import Gargantext.Core.Utils.Prefix (unPrefix, unPrefixSwagger, wellNamedSchema)
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
data Metrics = Metrics newtype Metrics = Metrics
{ metrics_data :: [Metric]} { metrics_data :: Vector Metric}
deriving (Generic, Show) deriving (Generic, Show)
instance ToSchema Metrics where instance ToSchema Metrics where
declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "metrics_") declareNamedSchema = genericDeclareNamedSchema (unPrefixSwagger "metrics_")
instance Arbitrary Metrics instance Arbitrary Metrics
where where
arbitrary = Metrics <$> arbitrary arbitrary = (Metrics . V.fromList) <$> arbitrary
data Metric = Metric data Metric = Metric
{ m_label :: !Text { m_label :: !Text
...@@ -43,7 +45,7 @@ deriveJSON (unPrefix "metrics_") ''Metrics ...@@ -43,7 +45,7 @@ deriveJSON (unPrefix "metrics_") ''Metrics
deriveJSON (unPrefix "m_") ''Metric deriveJSON (unPrefix "m_") ''Metric
data ChartMetrics a = ChartMetrics { chartMetrics_data :: a } newtype ChartMetrics a = ChartMetrics { chartMetrics_data :: a }
deriving (Generic, Show) deriving (Generic, Show)
instance (Typeable a, ToSchema a) => ToSchema (ChartMetrics a) where instance (Typeable a, ToSchema a) => ToSchema (ChartMetrics a) where
......
...@@ -24,6 +24,7 @@ import Control.Monad (mzero) ...@@ -24,6 +24,7 @@ import Control.Monad (mzero)
import Data.Aeson import Data.Aeson
import Data.Aeson.TH (deriveJSON) import Data.Aeson.TH (deriveJSON)
import Data.Either import Data.Either
import Data.Hashable (Hashable)
import Data.Swagger import Data.Swagger
import Data.Text (Text, unpack) import Data.Text (Text, unpack)
import Data.Time (UTCTime) import Data.Time (UTCTime)
...@@ -130,7 +131,7 @@ pgNodeId = O.pgInt4 . id2int ...@@ -130,7 +131,7 @@ pgNodeId = O.pgInt4 . id2int
------------------------------------------------------------------------ ------------------------------------------------------------------------
newtype NodeId = NodeId Int newtype NodeId = NodeId Int
deriving (Show, Read, Generic, Num, Eq, Ord, Enum, ToJSONKey, FromJSONKey, ToJSON, FromJSON) deriving (Show, Read, Generic, Num, Eq, Ord, Enum, ToJSONKey, FromJSONKey, ToJSON, FromJSON, Hashable)
unNodeId :: NodeId -> Int unNodeId :: NodeId -> Int
unNodeId (NodeId n) = n unNodeId (NodeId n) = n
......
...@@ -19,6 +19,7 @@ Ngrams connection to the Database. ...@@ -19,6 +19,7 @@ Ngrams connection to the Database.
module Gargantext.Database.Schema.Ngrams module Gargantext.Database.Schema.Ngrams
where where
import Data.Hashable (Hashable)
import Codec.Serialise (Serialise()) import Codec.Serialise (Serialise())
import Control.Lens (over) import Control.Lens (over)
import Control.Monad (mzero) import Control.Monad (mzero)
...@@ -81,6 +82,7 @@ data NgramsType = Authors | Institutes | Sources | NgramsTerms ...@@ -81,6 +82,7 @@ data NgramsType = Authors | Institutes | Sources | NgramsTerms
deriving (Eq, Show, Read, Ord, Enum, Bounded, Generic) deriving (Eq, Show, Read, Ord, Enum, Bounded, Generic)
instance Serialise NgramsType instance Serialise NgramsType
instance Hashable NgramsType
ngramsTypes :: [NgramsType] ngramsTypes :: [NgramsType]
ngramsTypes = [minBound..] ngramsTypes = [minBound..]
...@@ -153,6 +155,7 @@ text2ngrams txt = UnsafeNgrams txt' $ length $ splitOn " " txt' ...@@ -153,6 +155,7 @@ text2ngrams txt = UnsafeNgrams txt' $ length $ splitOn " " txt'
where where
txt' = strip txt txt' = strip txt
------------------------------------------------------------------------- -------------------------------------------------------------------------
-- | TODO put it in Gargantext.Core.Text.Ngrams -- | TODO put it in Gargantext.Core.Text.Ngrams
-- Named entity are typed ngrams of Terms Ngrams -- Named entity are typed ngrams of Terms Ngrams
......
...@@ -45,6 +45,7 @@ instance {-# OVERLAPPING #-} IsHashable String where ...@@ -45,6 +45,7 @@ instance {-# OVERLAPPING #-} IsHashable String where
instance IsHashable Text where instance IsHashable Text where
hash = hash . Text.unpack hash = hash . Text.unpack
instance IsHashable (Set Hash) where instance IsHashable (Set Hash) where
hash = hash . foldl (<>) "" . Set.toList hash = hash . foldl (<>) "" . Set.toList
......
resolver: lts-16.14 resolver: lts-16.26
flags: {} flags: {}
extra-package-dbs: [] extra-package-dbs: []
packages: packages:
...@@ -10,7 +10,7 @@ packages: ...@@ -10,7 +10,7 @@ packages:
docker: docker:
enable: false enable: false
repo: 'fpco/stack-build:lts-14.27-garg' repo: 'fpco/stack-build:lts-16.26-garg'
run-args: run-args:
- '--publish=8008:8008' - '--publish=8008:8008'
...@@ -21,47 +21,57 @@ nix: ...@@ -21,47 +21,57 @@ nix:
allow-newer: true allow-newer: true
extra-deps: extra-deps:
# Data Mining Libs
- git: https://github.com/delanoe/data-time-segment.git - git: https://github.com/delanoe/data-time-segment.git
commit: 10a416b9f6c443866b36479c3441ebb3bcdeb7ef commit: 10a416b9f6c443866b36479c3441ebb3bcdeb7ef
- git: https://gitlab.iscpif.fr/gargantext/hlcm.git - git: https://gitlab.iscpif.fr/gargantext/hlcm.git
commit: 6f0595d2421005837d59151a8b26eee83ebb67b5 commit: 6f0595d2421005837d59151a8b26eee83ebb67b5
- git: https://github.com/delanoe/servant-static-th.git
commit: 8cb8aaf2962ad44d319fcea48442e4397b3c49e8
- git: https://github.com/delanoe/hstatistics.git - git: https://github.com/delanoe/hstatistics.git
commit: 90eef7604bb230644c2246eccd094d7bfefcb135 commit: 90eef7604bb230644c2246eccd094d7bfefcb135
- git: https://github.com/paulrzcz/HSvm.git - git: https://github.com/paulrzcz/HSvm.git
commit: 3fe28b683aba5ddf05e3b5f8eced0bd05c5a29f9 commit: 3fe28b683aba5ddf05e3b5f8eced0bd05c5a29f9
# API libs
- git: https://github.com/delanoe/servant-static-th.git
commit: 8cb8aaf2962ad44d319fcea48442e4397b3c49e8
# Databases libs
- git: https://github.com/delanoe/haskell-opaleye.git #- opaleye-0.6.7002.0
commit: 63ee65d974e9d20eaaf17a2e83652175988cbb79
- git: https://github.com/delanoe/hsparql.git
commit: 308c74b71a1abb0a91546fa57d353131248e3a7f
- git: https://github.com/robstewart57/rdf4h.git - git: https://github.com/robstewart57/rdf4h.git
commit: 4fd2edf30c141600ffad6d730cc4c1c08a6dbce4 commit: 4fd2edf30c141600ffad6d730cc4c1c08a6dbce4
#
# External API connectin to get data # External Data API connectors
- git: https://gitlab.iscpif.fr/gargantext/crawlers/pubmed.git - git: https://gitlab.iscpif.fr/gargantext/crawlers/pubmed.git
commit: a9d8e08a7ef82f90e29dfaced4071704a3163394 commit: a9d8e08a7ef82f90e29dfaced4071704a3163394
- git: https://gitlab.iscpif.fr/gargantext/crawlers/istex.git - git: https://gitlab.iscpif.fr/gargantext/crawlers/istex.git
commit: daeae80365250c4bd539f0a65e271f9aa37f731f commit: daeae80365250c4bd539f0a65e271f9aa37f731f
- git: https://gitlab.iscpif.fr/gargantext/crawlers/hal.git - git: https://gitlab.iscpif.fr/gargantext/crawlers/hal.git
commit: 95e8f01a5d3b404a14a7fc664996569a6fb41ec4 commit: 020f5f9b308f5c23c925aedf5fb11f8b4728fb19
- git: https://gitlab.iscpif.fr/gargantext/crawlers/isidore.git - git: https://gitlab.iscpif.fr/gargantext/crawlers/isidore.git
commit: 3db385e767d2100d8abe900833c6e7de3ac55e1b commit: 3db385e767d2100d8abe900833c6e7de3ac55e1b
#
- git: https://gitlab.com/npouillard/patches-class.git
commit: 4712bfb055888fae63cd2e88431972375f979b94
# NP libs
#- git: https://github.com/np/servant-job.git # waiting for PR #- git: https://github.com/np/servant-job.git # waiting for PR
- git: https://github.com/delanoe/servant-job.git - git: https://github.com/delanoe/servant-job.git
commit: a9d8ec247b60906ae0ad76ea017cacd6ff36a7a1 commit: a9d8ec247b60906ae0ad76ea017cacd6ff36a7a1
- git: https://github.com/np/patches-map #- git: https://github.com/np/patches-map
commit: d42c37de5046ba22abcb5e21c121d1072126f3cc - git: https://github.com/delanoe/patches-map
- git: https://github.com/delanoe/haskell-opaleye.git #- opaleye-0.6.7002.0 commit: 76cae88f367976ff091e661ee69a5c3126b94694
commit: 63ee65d974e9d20eaaf17a2e83652175988cbb79 #- git: https://gitlab.com/npouillard/patches-class.git
- git: https://github.com/delanoe/hsparql.git - git: https://gitlab.iscpif.fr/gargantext/patches-class.git
commit: 308c74b71a1abb0a91546fa57d353131248e3a7f commit: d3e971d4e78d1dfcc853f2fb86bde1995faf22ae
- git: https://gitlab.iscpif.fr/gargantext/clustering-louvain.git
commit: 7d74f96dfea8e51fbab1793cc0429b2fe741f73d
# Graph libs
- git: https://github.com/kaizhang/haskell-igraph.git - git: https://github.com/kaizhang/haskell-igraph.git
commit: 34553acc4ebdcae7065311dcefb426e0fd58c5a0 commit: 34553acc4ebdcae7065311dcefb426e0fd58c5a0
- git: https://gitlab.iscpif.fr/gargantext/clustering-louvain.git
commit: 7d74f96dfea8e51fbab1793cc0429b2fe741f73d
# Others dependencies (with stack resolver)
- KMP-0.2.0.0@sha256:6dfbac03ef00ebd9347234732cb86a40f62ab5a80c0cc6bedb8eb51766f7df28,2562 - KMP-0.2.0.0@sha256:6dfbac03ef00ebd9347234732cb86a40f62ab5a80c0cc6bedb8eb51766f7df28,2562
- Unique-0.4.7.7@sha256:2269d3528271e25d34542e7c24a4e541e27ec33460e1ea00845da95b82eec6fa,2777 - Unique-0.4.7.7@sha256:2269d3528271e25d34542e7c24a4e541e27ec33460e1ea00845da95b82eec6fa,2777
- accelerate-1.2.0.1@sha256:bb1928efe602545df4043692916ed427c959110cbd678d03c3f9c3be25d1ae88,20112 - accelerate-1.2.0.1@sha256:bb1928efe602545df4043692916ed427c959110cbd678d03c3f9c3be25d1ae88,20112
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment