too-many-cells 0.1.6.1 → 0.1.7.0
raw patch · 4 files changed
+50/−19 lines, 4 filesdep ~birch-beerdep ~differential
Dependency ranges changed: birch-beer, differential
Files
- app/Main.hs +14/−4
- src/TooManyCells/Differential/Differential.hs +31/−11
- src/TooManyCells/Differential/Types.hs +1/−0
- too-many-cells.cabal +4/−4
app/Main.hs view
@@ -101,7 +101,7 @@ , customCut :: [Int] <?> "([Nothing] | NODE) List of nodes to prune (make these nodes leaves). Invoked by --custom-cut 34 --custom-cut 65 etc." , dendrogramOutput :: Maybe String <?> "([dendrogram.svg] | FILE) The filename for the dendrogram. Supported formats are PNG, PS, PDF, and SVG." , matrixOutput :: Maybe String <?> "([Nothing] | FOLDER | FILE.csv) Output the filtered and normalized (not including TfIdfNorm) matrix in this folder in matrix market format or, if a csv file is specified, a dense csv format."- , 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), DrawItem (DrawThresholdContinuous [(FEATURE, DOUBLE)]), where each item is colored by the binary high / low expression of FEATURE with cutoff DOUBLE (so a value 0 means low <= 0, high > 0) 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!)."+ , 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!)." , drawCollection :: Maybe String <?> "([PieChart] | PieRing | PieNone | CollectionGraph MAXWEIGHT THRESHOLD [NODE]) How to draw item leaves in the dendrogram. PieRing draws a pie chart ring around the items. PieChart only draws a pie chart instead of items. PieNone only draws items, no pie rings or charts. (CollectionGraph MAXWEIGHT THRESHOLD [NODE]) draws the nodes and edges within leaves that are descendents of NODE (empty list [] indicates draw all leaf networks) based on the input matrix, normalizes edges based on the MAXWEIGHT, and removes edges for display less than THRESHOLD (after normalization, so for CollectionGraph 2 0.5 [26], draw the leaf graphs for all leaves under node 26, then a edge of 0.7 would be removed because (0.7 / 2) < 0.5). For CollectionGraph with no colors, use --draw-leaf \"DrawItem DrawLabel\" and all nodes will be black. If you don't specify this option, DrawText from --draw-leaf overrides this argument and only the number of cells will be plotted." , drawMark :: Maybe String <?> "([MarkNone] | MarkModularity) How to draw annotations around each inner node in the tree. MarkNone draws nothing and MarkModularity draws a black circle representing the modularity at that node, darker black means higher modularity for that next split." , drawNodeNumber :: Bool <?> "Draw the node numbers on top of each node in the graph."@@ -145,6 +145,7 @@ , labels :: Maybe String <?> "([Nothing] | ([LABEL], [LABEL])) Use --labels-file to restrict the differential analysis to cells with these labels. Same format as --nodes, so the first list in --nodes and --labels gets the cells within that list of nodes with this list of labels. The same for the second list. For instance, --nodes \"([1], [2])\" --labels \"([\\\"A\\\"], [\\\"B\\\"])\" will compare cells from node 1 of label \"A\" only with cells from node 2 of label \"B\" only. To use all cells for that set of nodes, use an empty list, i.e. --labels \"([], [\\\"A\\\"])\". When comparing all nodes with all other cells, remember that the notation would be ([Other Cells], [Node]), so to compare cells of label X in Node with cells of label Y in Other Cells, use --labels \"([\\\"Y\\\", \\\"X\\\"])\". Requires both --labels and --labels-file, otherwise will include all labels." , topN :: Maybe Int <?> "([100] | INT ) The top INT differentially expressed genes." , genes :: [T.Text] <?> "([Nothing] | GENE) List of genes to plot for all cells within selected nodes. Invoked by --genes CD4 --genes CD8 etc. When this argument is supplied, only the plot is outputted and edgeR differential expression is ignored. Outputs to --output."+ , aggregate :: Bool <?> "([False] | True) Whether to plot the aggregate (mean here) of features for each cell from \"--genes\" instead of plotting different distributions for each feature." , plotOutput :: Maybe String <?> "([out.pdf] | STRING) The file containing the output plot."} | Diversity { priors :: [String] <?> "(PATH) Either input folders containing the output from a run of too-many-cells or a csv files containing the clusters for each cell in the format \"cell,cluster\". Advanced features not available in the latter case. If --labels-file is specified, those labels designate entity type, otherwise the assigned cluster is the entity type." , delimiter :: Maybe Char <?> "([,] | CHAR) The delimiter for the csv file if using a normal csv rather than cellranger output and for --labels-file."@@ -166,6 +167,7 @@ modifiers :: Modifiers modifiers = lispCaseModifiers { shortNameModifier = short } where+ short "aggregate" = Nothing short "customCut" = Nothing short "clumpinessMethod" = Just 'u' short "clusterNormalization" = Just 'C'@@ -361,7 +363,7 @@ drawLeaf' = maybe (maybe DrawText (const (DrawItem DrawLabel)) labelsFile')- (readOrErr "Cannot read draw-leaf.")+ (readOrErr "Cannot read draw-leaf. If using DrawContinuous, remember to put features in a list: DrawItem (DrawContinuous [\\\"FEATURE\\\"])") . unHelpful . drawLeaf $ opts@@ -771,6 +773,7 @@ $ opts topN' = TopN . fromMaybe 100 . unHelpful . topN $ opts genes' = fmap Gene . unHelpful . genes $ opts+ aggregate' = Aggregate . unHelpful . aggregate $ opts labels' = fmap ( DiffLabels . L.over L.both ( (\x -> bool (Just x) Nothing . Set.null $ x) . Set.fromList@@ -822,29 +825,36 @@ H.io . B.putStrLn . getDEString $ res _ -> do+ let outputCsvR = FP.replaceExtension plotOutputR ".csv"+ diffPlot <- getSingleDiff False+ aggregate' labelMap (extractSc processedSc) combined1 combined2 genes' gr- [r| suppressMessages(ggsave(diffPlot_hs, file = plotOutputR_hs)) |]+ [r| suppressMessages(write.csv(diffPlot_hs[[2]], file = outputCsvR_hs, row.names = FALSE, quote = FALSE)) |]+ [r| suppressMessages(ggsave(diffPlot_hs[[1]], file = plotOutputR_hs)) |] let normOutputR = FP.replaceBaseName plotOutputR (FP.takeBaseName plotOutputR <> "_scaled")+ normOutputCsvR = FP.replaceExtension normOutputR ".csv" diffNormPlot <- getSingleDiff True+ aggregate' labelMap (extractSc processedSc) combined1 combined2 genes' gr- [r| suppressMessages(ggsave(diffNormPlot_hs, file = normOutputR_hs)) |]+ [r| suppressMessages(write.csv(diffNormPlot_hs[[2]], file = normOutputCsvR_hs, row.names = FALSE, quote = FALSE)) |]+ [r| suppressMessages(ggsave(diffNormPlot_hs[[1]], file = normOutputR_hs)) |] return ()
src/TooManyCells/Differential/Differential.hs view
@@ -24,7 +24,7 @@ import BirchBeer.Utility (getGraphLeaves, getGraphLeafItems) import Control.Monad (join, mfilter) import Data.Function (on)-import Data.List (sort, sortBy)+import Data.List (sort, sortBy, genericLength) import Data.Maybe (fromMaybe, catMaybes, isJust) import Data.Monoid ((<>)) import Language.R as R@@ -34,6 +34,7 @@ import qualified "differential" Differential as Diff import qualified "differential" Plot as Diff import qualified "differential" Types as Diff+import qualified Control.Foldl as Fold import qualified Control.Lens as L import qualified Data.ByteString.Lazy.Char8 as B import qualified Data.Csv as CSV@@ -42,6 +43,7 @@ import qualified Data.Map as Map import qualified Data.Set as Set import qualified Data.Sparse.Common as S+import qualified Data.Text as T import qualified Data.Vector as V import qualified System.FilePath as FP @@ -77,12 +79,15 @@ $ mappend (collapseStatus (1 :: Int) v1 l1) (collapseStatus (2 :: Int) v2 l2) where collapseStatus s vs ls =- fmap (\ !x -> (unRow . _cellRow $ x, _barcode x, (s, Diff.Status . showt $ vs)))+ fmap (\ !x -> (unRow . _cellRow $ x, _barcode x, (s, Diff.Status $ statusName vs ls))) . mfilter (validCellInfo lm ls) . join . mconcat . fmap (fmap (fromMaybe mempty . snd) . getGraphLeaves gr) $ vs+ statusName vs Nothing = showt vs+ statusName vs (Just ls) =+ (T.intercalate " " . fmap unLabel . Set.toAscList $ ls) <> " " <> showt vs -- | Filter barcodes by labels. validCellInfo :: Maybe LabelMap -> Maybe (Set.Set Label) -> CellInfo -> Bool@@ -200,17 +205,30 @@ $ xs -- | Convert a single cell matrix to a list of Entities with the specified--- features.-scToEntities :: [Gene]+-- features. Also aggregates genes by average value or not.+scToEntities :: Aggregate+ -> [Gene] -> [(Int, Cell, (Int, Diff.Status))] -> SingleCells -> [Diff.Entity]-scToEntities genes cellGroups sc =- concatMap (\x -> fmap (toEntity x) geneIdxs) cellGroups+scToEntities aggregate genes cellGroups sc =+ concatMap (\x -> toEntity aggregate x geneIdxs) cellGroups where mat = getMatrix sc- toEntity (cellIdx, _, (_, status)) (Gene gene, idx) =- Diff.Entity (Diff.Name gene) status $ S.lookupWD_SM mat (cellIdx, idx)+ toEntity (Aggregate False) (cellIdx, (Cell b), (_, status)) =+ fmap (\ (Gene gene, idx) -> Diff.Entity (Diff.Name gene) status (Diff.Id b)+ $ S.lookupWD_SM mat (cellIdx, idx)+ )+ toEntity (Aggregate True) (cellIdx, (Cell b), (_, status)) =+ (:[])+ . Diff.Entity+ (Diff.Name . T.intercalate " " . fmap (unGene . fst) $ geneIdxs)+ status+ (Diff.Id b)+ . (/ n)+ . sum+ . fmap (\(_, idx) -> S.lookupWD_SM mat (cellIdx, idx))+ n = genericLength geneIdxs geneIdxs :: [(Gene, Int)] geneIdxs = fmap (\ !x -> ( x , fromMaybe (err x)@@ -219,8 +237,10 @@ ) genes err x = error $ "Feature " <> show x <> " not found for differential." --- | Get the differential expression plot of features over statuses, filtered by labels.+-- | Get the differential expression plot of features (or aggregate of features+-- by average) over statuses, filtered by labels. getSingleDiff :: Bool+ -> Aggregate -> Maybe LabelMap -> SingleCells -> ([G.Node], Maybe (Set.Set Label))@@ -228,9 +248,9 @@ -> [Gene] -> ClusterGraph CellInfo -> R.R s (R.SomeSEXP s)-getSingleDiff normalize lm sc v1 v2 genes gr = do+getSingleDiff normalize aggregate lm sc v1 v2 genes gr = do let cellGroups = getStatuses lm v1 v2 gr- entities = scToEntities genes cellGroups sc+ entities = scToEntities aggregate genes cellGroups sc Diff.plotSingleDiff normalize entities
src/TooManyCells/Differential/Types.hs view
@@ -20,3 +20,4 @@ newtype DiffNodes = DiffNodes {unDiffNodes :: ([G.Node], [G.Node])} newtype DiffLabels = DiffLabels { unDiffLabels :: (Maybe (Set.Set Label), Maybe (Set.Set Label)) }+newtype Aggregate = Aggregate { unAggregate :: Bool }
too-many-cells.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: too-many-cells-version: 0.1.6.1+version: 0.1.7.0 license: GPL-3 license-file: LICENSE copyright: 2019 Gregory W. Schwartz@@ -46,7 +46,7 @@ build-depends: base >=4.7 && <5, aeson >=1.4.0.0,- birch-beer >=0.1.2.1,+ birch-beer >=0.1.3.0, bytestring >=0.10.8.2, cassava >=0.5.1.0, colour >=2.3.4,@@ -56,7 +56,7 @@ diagrams-lib >=1.4.2.3, diagrams-cairo >=1.4.1, diagrams-graphviz >=1.4.1,- differential >=0.1.1.0,+ differential >=0.1.2.0, directory >=1.3.1.5, diversity >=0.8.1.0, find-clumpiness >=0.2.3.1,@@ -103,7 +103,7 @@ base >=4.11.1.0, too-many-cells -any, aeson >=1.4.0.0,- birch-beer >=0.1.2.1,+ birch-beer >=0.1.3.0, bytestring >=0.10.8.2, cassava >=0.5.1.0, colour >=2.3.4,