birch-beer 0.1.3.1 → 0.1.4.0
raw patch · 6 files changed
+57/−7 lines, 6 files
Files
- app/Main.hs +6/−2
- birch-beer.cabal +1/−1
- src/BirchBeer/Interactive.hs +1/−0
- src/BirchBeer/MainDiagram.hs +6/−0
- src/BirchBeer/Stopping.hs +39/−4
- src/BirchBeer/Types.hs +4/−0
app/Main.hs view
@@ -54,7 +54,8 @@ , maxStep :: Maybe Int <?> "([Nothing] | INT) Only keep clusters that are INT steps from the root. Defaults to all steps." , maxProportion :: Maybe Double <?> "([Nothing] | DOUBLE) Stopping criteria to stop at the node immediate after a node with DOUBLE proportion split. So a node N with L and R children will stop with this criteria at 0.5 if |L| / |R| < 0.5 or > 2 (absolute log2 transformed), that is, if one child has over twice as many items as the other child. Includes L and R in the final result." , minDistance :: Maybe Double <?> "([Nothing] | DOUBLE) Stopping criteria to stop at the node immediate after a node with DOUBLE distance. So a node N with L and R children will stop with this criteria the distance at N to L and R is < DOUBLE. Includes L and R in the final result."- , smartCutoff :: Maybe Double <?> "([Nothing] | DOUBLE) Whether to set the cutoffs for --min-size, --max-proportion, and --min-distance based off of the distributions (median + (DOUBLE * MAD)) of all nodes. To use smart cutoffs, use this argument and then set one of the three arguments to an arbitrary number, whichever cutoff type you want to use. --min-size distribution is log2 transformed."+ , minDistanceSearch :: Maybe Double <?> "([Nothing] | DOUBLE) Similar to --min-distance, but searches from the leaves to the root -- if a path from a subtree contains a distance of at least DOUBLE, keep that path, otherwise prune it. This argument assists in finding distant nodes."+ , smartCutoff :: Maybe Double <?> "([Nothing] | DOUBLE) Whether to set the cutoffs for --min-size, --max-proportion, --min-distance, and --min-distance-search based off of the distributions (median + (DOUBLE * MAD)) of all nodes. To use smart cutoffs, use this argument and then set one of the three arguments to an arbitrary number, whichever cutoff type you want to use. --min-size distribution is log2 transformed." , customCut :: [Int] <?> "([Nothing] | NODE) List of nodes to prune (make these nodes leaves). Invoked by --custom-cut 34 --custom-cut 65 etc." , order :: Maybe Double <?> "([1] | DOUBLE) The order of diversity for DrawItem DrawDiversity." , drawLeaf :: Maybe String <?> "([DrawText] | DrawItem DrawItemType) How to draw leaves in the dendrogram. DrawText is the number of items in that leaf. DrawItem is the collection of items represented by circles, consisting of: DrawItem DrawLabel, where each item is colored by its label, DrawItem (DrawContinuous [FEATURE]), where each item is colored by the expression of FEATURE (corresponding to a feature name in the input matrix, [FEATURE] is a list, so if more than one FEATURE is listed, uses the average of the feature values), DrawItem (DrawThresholdContinuous [(FEATURE, DOUBLE)]), where each item is colored by the binary high / low expression of FEATURE based on DOUBLE and multiple FEATUREs can be used to combinatorically label items (FEATURE1 high / FEATURE2 low, etc.), DrawItem DrawSumContinuous, where each item is colored by the sum of the post-normalized columns (use --normalization NoneNorm for UMI counts, default), and DrawItem DrawDiversity, where each node is colored by the diversity based on the labels of each item and the color is normalized separately for the leaves and the inner nodes. The default is DrawText, unless --labels-file is provided, in which DrawItem DrawLabel is the default. If the label or feature cannot be found, the default color will be black (check your spelling!)."@@ -81,7 +82,8 @@ short "minSize" = Just 'M' short "maxStep" = Just 'S' short "maxProportion" = Just 'P'- short "maxDistance" = Just 'T'+ short "minDistance" = Just 'T'+ short "minDistanceSearch" = Nothing short "drawLeaf" = Just 'L' short "drawCollection" = Just 'D' short "drawDiscretize" = Nothing@@ -117,6 +119,7 @@ maxStep' = fmap MaxStep . unHelpful . maxStep $ opts maxProportion' = fmap MaxProportion . unHelpful . maxProportion $ opts minDistance' = fmap MinDistance . unHelpful . minDistance $ opts+ minDistanceSearch' = fmap MinDistanceSearch . unHelpful . minDistanceSearch $ opts smartCutoff' = fmap SmartCutoff . unHelpful . smartCutoff $ opts customCut' = CustomCut . Set.fromList . unHelpful . customCut $ opts order' = fmap Order . unHelpful . order $ opts@@ -232,6 +235,7 @@ , _birchMaxStep = maxStep' , _birchMaxProportion = maxProportion' , _birchMinDistance = minDistance'+ , _birchMinDistanceSearch = minDistanceSearch' , _birchSmartCutoff = smartCutoff' , _birchCustomCut = customCut' , _birchOrder = order'
birch-beer.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: birch-beer-version: 0.1.3.1+version: 0.1.4.0 license: GPL-3 license-file: LICENSE copyright: 2019 Gregory W. Schwartz
src/BirchBeer/Interactive.hs view
@@ -102,6 +102,7 @@ , _birchMaxStep = Just maxStep' , _birchMaxProportion = Nothing , _birchMinDistance = Nothing+ , _birchMinDistanceSearch = Nothing , _birchSmartCutoff = Nothing , _birchCustomCut = CustomCut Set.empty , _birchOrder = Nothing
src/BirchBeer/MainDiagram.hs view
@@ -67,6 +67,11 @@ (Just x, Just _) -> Just . MinDistance $ smartCut x getDistance tree otherwise -> _birchMinDistance config+ minDistanceSearch' =+ case (fmap unSmartCutoff smartCutoff', _birchMinDistanceSearch config) of+ (Just x, Just _) ->+ Just . MinDistanceSearch $ smartCut x getDistance tree+ otherwise -> _birchMinDistanceSearch config drawLeaf' = _birchDrawLeaf config drawCollection' = _birchDrawCollection config drawMark' = _birchDrawMark config@@ -94,6 +99,7 @@ ) , (\x -> maybe x (flip proportionCut x . unMaxProportion) maxProportion') , (\x -> maybe x (flip distanceCut x . unMinDistance) minDistance')+ , (\x -> maybe x (flip distanceSearchCut x . unMinDistanceSearch) minDistanceSearch') , (\x -> maybe x (flip sizeCut x . unMinClusterSize) minSize') , (\x -> maybe x (flip stepCut x . unMaxStep) maxStep') ]
src/BirchBeer/Stopping.hs view
@@ -17,6 +17,7 @@ , proportionCutDendrogram , distanceCut , distanceCutDendrogram+ , distanceSearchCut , getSize , getSizeDend , getDistance@@ -26,18 +27,21 @@ , smartCut , smartCutDend , customCut+ , searchCut ) where -- Remote import Control.Monad.State (MonadState (..), State (..), evalState, execState, modify) import Data.Function (on) import Data.Int (Int32)-import Data.List (genericLength, maximumBy)-import Data.Maybe (fromMaybe, catMaybes)+import Data.List (genericLength, maximumBy, tails)+import Data.Maybe (catMaybes, fromMaybe) import Data.Monoid ((<>)) import Data.Tree (Tree (..), flatten)+import Safe (headMay) import qualified Control.Lens as L import qualified Data.Clustering.Hierarchical as HC+import qualified Data.Foldable as F import qualified Data.Graph.Inductive as G import qualified Data.Map.Strict as Map import qualified Data.Sequence as Seq@@ -125,7 +129,7 @@ proportionCut n b@(Node { subForest = xs }) = if (absLog2 $ (maximum . fmap getSize $ xs) / (minimum . fmap getSize $ xs)) > absLog2 n- then b { subForest = fmap branchToLeaf xs }+ then branchToLeaf b else b { subForest = fmap (proportionCut n) xs } -- | Cut a dendrogram based off of the distance, keeping up to and including the@@ -158,9 +162,27 @@ distanceCut _ b@(all isLeaf . subForest -> True) = b distanceCut d b = if (L.view distance . rootLabel $ b) < Just d- then b { subForest = fmap branchToLeaf . subForest $ b }+ then branchToLeaf b else b { subForest = fmap (distanceCut d) . subForest $ b } +-- | Get tree ignoring paths to nodes with designated distance or higher (and+-- children) and cutting the rest. This returns the tree.+distanceSearchCut :: (Semigroup a)+ => Double+ -> Tree (TreeNode a)+ -> Tree (TreeNode a)+distanceSearchCut d = searchCut (maybe False (>= d) . L.view distance) False++-- | Get tree ignoring paths to nodes with designated distance or higher (and+-- children) and cutting the rest. This returns the appropriate set of nodes to+-- cut. Ignored in favor of searchCut.+distanceSearchCutNodes :: Double -> ClusterGraph a -> Set.Set G.Node+distanceSearchCutNodes d = Set.fromList+ . concatMap (\(!x, !y, _) -> [x, y])+ . filter ((>= d) . L.view L._3)+ . G.labEdges+ . unClusterGraph+ -- | Cut a graph tree at designated nodes. Using a graph due to node labels. -- Must not include cycles! customCut :: Set.Set G.Node -> ClusterGraph a -> ClusterGraph a@@ -170,6 +192,19 @@ | Set.member n ns = (parents, n, (n, Just $ getGraphLeafItems gr n), []) | otherwise = all++-- | Keep all paths containing valid nodes (and possibly children) from root to+-- that node.+searchCut :: (Semigroup a)+ => (TreeNode a -> Bool)+ -> Bool+ -> Tree (TreeNode a)+ -> Tree (TreeNode a)+searchCut f keepChildren b+ | any f . flatten $ b =+ b { subForest = fmap (searchCut f keepChildren) . subForest $ b }+ | keepChildren = b { subForest = fmap branchToLeaf . subForest $ b }+ | otherwise = branchToLeaf b -- | Get a property about each node in a dendrogram. getNodeInfoDend :: (HC.Dendrogram a -> b) -> HC.Dendrogram a -> [b]
src/BirchBeer/Types.hs view
@@ -100,6 +100,9 @@ newtype MinDistance = MinDistance { unMinDistance :: Double } deriving (Read,Show)+newtype MinDistanceSearch = MinDistanceSearch+ { unMinDistanceSearch :: Double+ } deriving (Read,Show) newtype CustomCut = CustomCut { unCustomCut :: Set.Set Int } deriving (Read,Show)@@ -214,6 +217,7 @@ , _birchMaxStep :: Maybe MaxStep , _birchMaxProportion :: Maybe MaxProportion , _birchMinDistance :: Maybe MinDistance+ , _birchMinDistanceSearch :: Maybe MinDistanceSearch , _birchOrder :: Maybe Order , _birchDrawLeaf :: DrawLeaf , _birchDrawCollection :: DrawCollection