packages feed

too-many-cells-0.1.0.0: src/TooManyCells/MakeTree/Clumpiness.hs

{- TooManyCells.MakeTree.Clumpiness
Gregory W. Schwartz

Collects the functions pertaining to finding the clumpiness from a single cell
dendrogram.
-}

{-# LANGUAGE PackageImports #-}
{-# LANGUAGE OverloadedStrings #-}

module TooManyCells.MakeTree.Clumpiness
    ( dendToClumpList
    , treeToClumpList
    , clumpToCsv
    ) where

-- Remote
import BirchBeer.Types
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import Data.Tree (Tree(..))
import qualified "find-clumpiness" Clumpiness as Clump
import qualified "find-clumpiness" Types as Clump
import qualified Control.Lens as L
import qualified Data.ByteString.Lazy.Char8 as B
import qualified Data.Clustering.Hierarchical as HC
import qualified Data.Csv as CSV
import qualified Data.Map.Strict as Map
import qualified Data.Sequence as Seq
import qualified Data.Text as T
import qualified Data.Vector as V

-- Local
import TooManyCells.MakeTree.Types
import TooManyCells.Matrix.Types

-- | Convert a single cell dendrogram to a workable format for clumpiness.
dendToClumpDend
    :: (TreeItem a)
    => LabelMap
    -> HC.Dendrogram (V.Vector a)
    -> Either String (Tree Clump.NodeLabel)
dendToClumpDend (LabelMap labelMap) dend = do
    inputTree <- sequence
               . fmap ( fmap (Seq.fromList . fmap unLabel . V.toList)
                      . sequence
                      . fmap ( (\ x
                               -> Map.findWithDefault
                                   (Left ("\nCell has no label: " <> show x))
                                   x
                                   (fmap Right labelMap)
                               )
                               . getId
                             )
                      )
               $ dend

    return $ Clump.makeWorkable inputTree

-- | Convert a single cell tree to a workable format for clumpiness.
treeToClumpTree
    :: (TreeItem a)
    => LabelMap
    -> Tree (TreeNode (V.Vector a))
    -> Either String (Tree Clump.NodeLabel)
treeToClumpTree (LabelMap labelMap) tree = do
    inputTree <- sequence
               . fmap ( fmap (Seq.fromList . fmap unLabel . V.toList)
                      . sequence
                      . fmap ( (\ x
                               -> Map.findWithDefault
                                   (Left ("\nCell has no label: " <> show x))
                                   x
                                   (fmap Right labelMap)
                               )
                               . getId
                             )
                      . fromMaybe V.empty
                      . L.view item
                      )
               $ tree

    return $ Clump.makeWorkable inputTree

-- | Format clumpiness output to a CSV.
clumpToCsv :: [(T.Text, T.Text, Double)] -> B.ByteString
clumpToCsv = (<>) "label1,label2,value\n" . CSV.encode

-- | Get the clumpiness of the single cell labels for a dendrogram.
dendToClumpList
    :: Clump.Exclusivity
    -> LabelMap
    -> HC.Dendrogram (V.Vector CellInfo)
    -> Either String [(T.Text, T.Text, Double)]
dendToClumpList exclusivity labelMap =
    fmap (Clump.getClumpiness exclusivity False False) . dendToClumpDend labelMap

-- | Get the clumpiness of the single cell labels for a tree.
treeToClumpList
    :: Clump.Exclusivity
    -> LabelMap
    -> Tree (TreeNode (V.Vector CellInfo))
    -> Either String [(T.Text, T.Text, Double)]
treeToClumpList exclusivity labelMap =
    fmap (Clump.getClumpiness exclusivity False False) . treeToClumpTree labelMap