Skip to content

Commit 9cabc80

Browse files
committed
Allow cellbender to save filtered matrix to cellranger dir
1 parent 242bd65 commit 9cabc80

File tree

4 files changed

+63
-13
lines changed

4 files changed

+63
-13
lines changed

singlecell/resources/chunks/CiteSeqPlots.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ for (datasetId in names(seuratObjects)) {
55
print('ADT assay not present, skipping')
66
} else {
77
for (adt in rownames(seuratObj[['ADT']])) {
8-
CellMembrane::FeaturePlotAcrossReductions(seuratObj, features = c(adt))
8+
CellMembrane::FeaturePlotAcrossReductions(seuratObj, features = paste0('adt_', adt))
99
}
1010
}
1111

singlecell/src/org/labkey/singlecell/pipeline/singlecell/PrepareRawCounts.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,21 @@ public static class Provider extends AbstractPipelineStepProvider<SingleCellRawD
3030
public Provider()
3131
{
3232
super("PrepareRawCounts", LABEL, "CellMembrane/Seurat", "This step reads the raw count matrix/matrices, and runs EmptyDrops to provide an unfiltered count matrix.", Arrays.asList(
33-
SeuratToolParameter.create("emptyDropsLower", "Lower", "Passed to DropletUtils::emptyDrops lower argument", "ldk-integerfield", null, 200),
34-
SeuratToolParameter.create("emptyDropsFdrThreshold", "FDR Threshold", "The FDR limit used to filter the results of DropletUtils::emptyDrops", "ldk-numberfield", null, 0.001),
35-
SeuratToolParameter.create("maxAllowableCells", "Max Cells Allowed", "If more than this many cells are predicted by EmptyDrops, the job will fail", "ldk-integerfield", null, 20000),
33+
SeuratToolParameter.create("emptyDropsLower", "Lower", "Passed to DropletUtils::emptyDrops lower argument", "ldk-integerfield", new JSONObject(){{
34+
put("minValue", 0);
35+
}}, 200),
36+
SeuratToolParameter.create("emptyDropsFdrThreshold", "FDR Threshold", "The FDR limit used to filter the results of DropletUtils::emptyDrops", "ldk-numberfield", new JSONObject(){{
37+
put("minValue", 0);
38+
put("decimalPrecision", 4);
39+
}}, 0.001),
40+
SeuratToolParameter.create("maxAllowableCells", "Max Cells Allowed", "If more than this many cells are predicted by EmptyDrops, the job will fail", "ldk-integerfield", new JSONObject(){{
41+
put("minValue", 0);
42+
}}, 20000),
3643
SeuratToolParameter.create("useEmptyDropsCellRanger", "Use emptyDropsCellRanger", "If checked, this will run emptyDropsCellRanger instead of emptyDrops", "checkbox", null, false),
37-
SeuratToolParameter.create("nExpectedCells", "# Expected Cells", "Only applied if emptyDropsCellRanger is selected. Passed to n.expected.cells argument", "ldk-integerfield", null, false),
38-
SeuratToolParameter.create("useCellBender", "Run CellBender", "If checked, cellbender will be run on the raw count matrix (instead of emptyDrops) to remove background/ambient RNA signal", "checkbox", new JSONObject(){{
44+
SeuratToolParameter.create("nExpectedCells", "# Expected Cells", "Only applied if emptyDropsCellRanger is selected. Passed to n.expected.cells argument", "ldk-integerfield", new JSONObject(){{
45+
put("minValue", 0);
46+
}}, false),
47+
SeuratToolParameter.create("useCellBender", "Run CellBender", "If checked, instead of the loupe counts, the system will attempt to find a previously created cellbender corrected count matrix and use this as input", "checkbox", new JSONObject(){{
3948

4049
}}, false),
4150
SeuratToolParameter.create("useSoupX", "Run SoupX", "If checked, SoupX will be run on the raw count matrix (instead of emptyDrops) to remove background/ambient RNA signal", "checkbox", new JSONObject(){{

singlecell/src/org/labkey/singlecell/run/CellBenderCiteSeqHandler.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ public class CellBenderCiteSeqHandler extends AbstractParameterizedOutputHandler
2727
{
2828
public CellBenderCiteSeqHandler()
2929
{
30-
super(ModuleLoader.getInstance().getModule(SingleCellModule.class), "Run CellBender (CITE-seq)", "This will run cellbender on the input cellranger folder and create a subset matrix with background/ambient noise removed.", null, getParams(0.05, false));
30+
super(ModuleLoader.getInstance().getModule(SingleCellModule.class), "Run CellBender (CITE-seq)", "This will run cellbender on the input cellranger folder and create a subset matrix with background/ambient noise removed.", null, getParams(0.05, false, false));
3131
}
3232

33-
protected static List<ToolParameterDescriptor> getParams(double fpr, boolean useGPU)
33+
protected static List<ToolParameterDescriptor> getParams(double fpr, boolean useGPU, boolean copyH5)
3434
{
35-
return Arrays.asList(
35+
List<ToolParameterDescriptor> ret = new ArrayList<>(Arrays.asList(
3636
ToolParameterDescriptor.createCommandLineParam(CommandLineParam.create("--expected-cells"), "expectedCells", "Expected Cells", "Passed to CellBender --expected-cells", "ldk-integerfield", null, 5000),
3737
ToolParameterDescriptor.createCommandLineParam(CommandLineParam.create("--total-droplets-included"), "totalDropletsIncluded", "Total Droplets Included", "Passed to CellBender --total-droplets-included", "ldk-integerfield", null, 20000),
3838
ToolParameterDescriptor.createCommandLineParam(CommandLineParam.create("--fpr"), "fpr", "FPR", "Passed to CellBender --fpr", "ldk-numberfield", new JSONObject(){{
@@ -42,7 +42,16 @@ protected static List<ToolParameterDescriptor> getParams(double fpr, boolean use
4242
ToolParameterDescriptor.createCommandLineParam(CommandLineParam.createSwitch("--cuda"), "useGpus", "Use GPUs", "If checked, the --cuda argument will be set on cellbender", "checkbox", new JSONObject(){{
4343
put("checked", useGPU);
4444
}}, useGPU)
45-
);
45+
));
46+
47+
if (copyH5)
48+
{
49+
ret.add(ToolParameterDescriptor.create("copyH5", "Use Matrix Source Dir", "If checked, the filtered matrix and output will be deposited in the same folder as the input cellranger project. This is required to use the filtered matrix in the seurat pipeline", "checkbox", new JSONObject(){{
50+
put("checked", true);
51+
}}, true));
52+
}
53+
54+
return ret;
4655
}
4756

4857
@Override

singlecell/src/org/labkey/singlecell/run/CellBenderLoupeHandler.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.labkey.singlecell.run;
22

3+
import org.apache.commons.io.FileUtils;
34
import org.json.JSONObject;
45
import org.labkey.api.module.ModuleLoader;
56
import org.labkey.api.pipeline.PipelineJob;
@@ -15,6 +16,7 @@
1516
import org.labkey.singlecell.SingleCellModule;
1617

1718
import java.io.File;
19+
import java.io.IOException;
1820
import java.util.ArrayList;
1921
import java.util.Arrays;
2022
import java.util.List;
@@ -23,7 +25,7 @@ public class CellBenderLoupeHandler extends AbstractParameterizedOutputHandler<S
2325
{
2426
public CellBenderLoupeHandler()
2527
{
26-
super(ModuleLoader.getInstance().getModule(SingleCellModule.class), "Run CellBender (RNA-seq)", "This will run cellbender on the input cellranger folder and create a subset matrix with background/ambient noise removed.", null, CellBenderCiteSeqHandler.getParams(0.01, true));
28+
super(ModuleLoader.getInstance().getModule(SingleCellModule.class), "Run CellBender (RNA-seq)", "This will run cellbender on the input cellranger folder and create a subset matrix with background/ambient noise removed.", null, CellBenderCiteSeqHandler.getParams(0.01, true, true));
2729
}
2830

2931
@Override
@@ -88,18 +90,48 @@ public void processFilesOnWebserver(PipelineJob job, SequenceAnalysisJobSupport
8890
public void processFilesRemote(List<SequenceOutputFile> inputFiles, JobContext ctx) throws UnsupportedOperationException, PipelineJobException
8991
{
9092
File filteredH5 = runCellBender(inputFiles.get(0).getFile(), ctx);
93+
if (ctx.getParams().optBoolean("copyH5", false))
94+
{
95+
ctx.getLogger().info("Copying h5 file to cellranger dir");
96+
List<File> toMove = Arrays.asList(
97+
filteredH5,
98+
new File(filteredH5.getParentFile(), filteredH5.getName().replaceAll("_filtered.h5", ".pdf")),
99+
new File(filteredH5.getParentFile(), filteredH5.getName().replaceAll("_filtered.h5", "_cell_barcodes.csv")),
100+
new File(filteredH5.getParentFile(), filteredH5.getName().replaceAll("_filtered.h5", ".log"))
101+
);
102+
103+
try
104+
{
105+
File destDir = getH5(inputFiles.get(0).getFile()).getParentFile();
106+
for (File f : toMove)
107+
{
108+
File dest = new File(destDir, f.getName());
109+
if (dest.exists())
110+
{
111+
dest.delete();
112+
}
113+
114+
ctx.getLogger().debug("Copying file to: " + dest.getPath());
115+
FileUtils.copyFile(f, dest);
116+
}
117+
}
118+
catch (IOException e)
119+
{
120+
throw new PipelineJobException(e);
121+
}
122+
}
91123

92124
SequenceOutputFile so = new SequenceOutputFile();
93125
so.setReadset(inputFiles.get(0).getReadset());
94126
so.setLibrary_id(inputFiles.get(0).getLibrary_id());
95127
so.setFile(filteredH5);
96128
if (so.getReadset() != null)
97129
{
98-
so.setName(ctx.getSequenceSupport().getCachedReadset(so.getReadset()).getName() + ": CellBender Filtered");
130+
so.setName(ctx.getSequenceSupport().getCachedReadset(so.getReadset()).getName() + ": CellBender Filtered RNA");
99131
}
100132
else
101133
{
102-
so.setName(inputFiles.get(0).getName() + ": CellBender Filtered");
134+
so.setName(inputFiles.get(0).getName() + ": CellBender Filtered RNA");
103135
}
104136
so.setCategory("CellBender Filtered RNA-Seq Counts");
105137
ctx.addSequenceOutput(so);

0 commit comments

Comments
 (0)