Skip to content

Commit f0fc938

Browse files
committed
Add support to calculate per-cell saturation
1 parent d46d297 commit f0fc938

File tree

6 files changed

+151
-4
lines changed

6 files changed

+151
-4
lines changed

singlecell/api-src/org/labkey/api/singlecell/pipeline/AbstractSingleCellPipelineStep.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ protected File createRmd(SingleCellOutput output, SequenceOutputHandler.JobConte
148148
markdown.setup = new SetupChunk(getRLibraries());
149149
markdown.chunks = new ArrayList<>();
150150
markdown.chunks.add(createParamChunk(inputObjects, outputPrefix));
151-
markdown.chunks.addAll(getChunks());
151+
markdown.chunks.addAll(getChunks(ctx));
152152
markdown.chunks.add(createFinalChunk());
153153

154154
markdown.print(out);
@@ -161,7 +161,7 @@ protected File createRmd(SingleCellOutput output, SequenceOutputHandler.JobConte
161161
return outfile;
162162
}
163163

164-
protected List<Chunk> getChunks() throws PipelineJobException
164+
protected List<Chunk> getChunks(SequenceOutputHandler.JobContext ctx) throws PipelineJobException
165165
{
166166
List<Chunk> ret = new ArrayList<>();
167167
ret.add(new Chunk(getProvider().getName(), getProvider().getLabel(), null, loadChunkFromFile()));
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
for (datasetId in names(seuratObjects)) {
2+
seuratObj <- seuratObjects[[datasetId]]
3+
seuratObjects[[datasetId]] <- NULL
4+
molInfoFile <- molInfoFiles[[datasetId]]
5+
if (is.null(molInfoFile)) {
6+
stop(paste0('Unable to find molInfo file for: ', datasetId))
7+
}
8+
9+
seuratObj <- CellMembrane::AppendPerCellSaturation(seuratObj, molInfoFile = molInfoFile)
10+
11+
newSeuratObjects[[datasetId]] <- seuratObj
12+
13+
# Cleanup
14+
rm(seuratObj)
15+
gc()
16+
}

singlecell/src/org/labkey/singlecell/SingleCellModule.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ public static void registerPipelineSteps()
160160
SequencePipelineService.get().registerPipelineStep(new CiteSeqPlots.Provider());
161161
SequencePipelineService.get().registerPipelineStep(new PhenotypePlots.Provider());
162162
SequencePipelineService.get().registerPipelineStep(new AppendMetadata.Provider());
163+
SequencePipelineService.get().registerPipelineStep(new AppendSaturation.Provider());
163164
}
164165

165166
@Override

singlecell/src/org/labkey/singlecell/analysis/ProcessSingleCellHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
public class ProcessSingleCellHandler extends AbstractSingleCellHandler
1414
{
15-
private static FileType LOUPE_TYPE = new FileType("cloupe", false);
15+
public static FileType LOUPE_TYPE = new FileType("cloupe", false);
1616

1717
@Override
1818
public String getName()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected File createRmd(SingleCellOutput output, SequenceOutputHandler.JobConte
4040
markdown.chunks.add(createDataChunk(countData, ctx.getOutputDir()));
4141
markdown.chunks.addAll(addAdditionalChunks(ctx, inputObjects, countData));
4242

43-
markdown.chunks.addAll(getChunks());
43+
markdown.chunks.addAll(getChunks(ctx));
4444
markdown.chunks.add(createFinalChunk());
4545

4646
markdown.print(out);
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package org.labkey.singlecell.pipeline.singlecell;
2+
3+
import au.com.bytecode.opencsv.CSVReader;
4+
import au.com.bytecode.opencsv.CSVWriter;
5+
import org.apache.commons.io.FileUtils;
6+
import org.labkey.api.pipeline.PipelineJobException;
7+
import org.labkey.api.reader.Readers;
8+
import org.labkey.api.sequenceanalysis.SequenceOutputFile;
9+
import org.labkey.api.sequenceanalysis.pipeline.AbstractPipelineStepProvider;
10+
import org.labkey.api.sequenceanalysis.pipeline.PipelineContext;
11+
import org.labkey.api.sequenceanalysis.pipeline.SequenceOutputHandler;
12+
import org.labkey.api.singlecell.pipeline.SingleCellStep;
13+
import org.labkey.api.writer.PrintWriters;
14+
15+
import java.io.File;
16+
import java.io.IOException;
17+
import java.util.ArrayList;
18+
import java.util.Arrays;
19+
import java.util.List;
20+
21+
import static org.labkey.singlecell.analysis.ProcessSingleCellHandler.LOUPE_TYPE;
22+
23+
public class AppendSaturation extends AbstractCellMembraneStep
24+
{
25+
public AppendSaturation(PipelineContext ctx, AppendSaturation.Provider provider)
26+
{
27+
super(provider, ctx);
28+
}
29+
30+
public static class Provider extends AbstractPipelineStepProvider<SingleCellStep>
31+
{
32+
public Provider()
33+
{
34+
super("AppendSaturation", "Append Saturation", "CellMembrane", "This will calculate sequencing saturation per-cell and append as metadata.", Arrays.asList(
35+
36+
), null, null);
37+
}
38+
39+
@Override
40+
public AppendSaturation create(PipelineContext ctx)
41+
{
42+
return new AppendSaturation(ctx, this);
43+
}
44+
}
45+
46+
@Override
47+
public void init(SequenceOutputHandler.JobContext ctx, List<SequenceOutputFile> inputFiles) throws PipelineJobException
48+
{
49+
try (CSVWriter writer = new CSVWriter(PrintWriters.getPrintWriter(getMolInfoTable(ctx))))
50+
{
51+
for (SequenceOutputFile so : inputFiles)
52+
{
53+
if (!LOUPE_TYPE.isType(so.getFile()))
54+
{
55+
throw new PipelineJobException("All input files must be loupe files to use sequence saturation");
56+
}
57+
58+
File molInfo = new File(so.getFile().getParentFile(), "molecule_info.h5");
59+
if (!molInfo.exists())
60+
{
61+
throw new PipelineJobException("Cannot find file: " + molInfo.getPath());
62+
}
63+
64+
writer.writeNext(new String[]{String.valueOf(so.getRowid()), molInfo.getPath()});
65+
}
66+
}
67+
catch (IOException e)
68+
{
69+
throw new PipelineJobException(e);
70+
}
71+
}
72+
73+
private File getMolInfoTable(SequenceOutputHandler.JobContext ctx)
74+
{
75+
return new File(ctx.getSourceDirectory(), "molInfo.txt");
76+
}
77+
78+
@Override
79+
protected List<Chunk> getChunks(SequenceOutputHandler.JobContext ctx) throws PipelineJobException
80+
{
81+
List<String> lines = new ArrayList<>();
82+
83+
lines.add("molInfoFiles <- list(");
84+
File table = getMolInfoTable(ctx);
85+
if (!table.exists())
86+
{
87+
throw new PipelineJobException("Unable to find molInfo table: " + table.getPath());
88+
}
89+
90+
try (CSVReader reader = new CSVReader(Readers.getReader(table)))
91+
{
92+
String[] line;
93+
while ((line = reader.readNext()) != null)
94+
{
95+
File source = new File(line[1]);
96+
File dest = new File(ctx.getWorkingDirectory(), line[0] + ".molInfo.h5");
97+
if (dest.exists())
98+
{
99+
dest.delete();
100+
}
101+
FileUtils.copyFile(source, dest);
102+
103+
lines.add("\t'" + line[0] + "' = '" + dest.getName() + "',");
104+
ctx.getFileManager().addIntermediateFile(dest);
105+
}
106+
}
107+
catch (IOException e)
108+
{
109+
throw new PipelineJobException(e);
110+
}
111+
112+
// Remove trailing comma:
113+
int lastIdx = lines.size() - 1;
114+
lines.set(lastIdx, lines.get(lastIdx).replaceAll(",$", ""));
115+
116+
lines.add(")");
117+
lines.add("");
118+
119+
List<Chunk> ret = super.getChunks(ctx);
120+
ret.add(new Chunk("molInfoFiles", null, null, lines, null));
121+
122+
return ret;
123+
}
124+
125+
@Override
126+
public String getFileSuffix()
127+
{
128+
return "saturation";
129+
}
130+
}

0 commit comments

Comments
 (0)