Skip to content

Commit fa22d6c

Browse files
committed
Add step to re-process Seurat prototypes
1 parent 53980d7 commit fa22d6c

File tree

3 files changed

+188
-0
lines changed

3 files changed

+188
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
if (!file.exists('/homeDir/.netrc')) {
2+
print(list.files('/homeDir'))
3+
stop('Unable to find file: /homeDir/.netrc')
4+
}
5+
6+
invisible(Rlabkey::labkey.setCurlOptions(NETRC_FILE = '/homeDir/.netrc'))
7+
Rdiscvr::SetLabKeyDefaults(baseUrl = serverBaseUrl, defaultFolder = defaultLabKeyFolder)
8+
9+
for (datasetId in names(seuratObjects)) {
10+
printName(datasetId)
11+
seuratObj <- readSeuratRDS(seuratObjects[[datasetId]])
12+
13+
if (reapplyMetadata) {
14+
seuratObj <- Rdiscvr::QueryAndApplyCdnaMetadata(seuratObj)
15+
}
16+
17+
if (runRira) {
18+
seuratObj <- RIRA::Classify_ImmuneCells(seuratObj, maxBatchSize = maxBatchSize, retainProbabilityMatrix = retainProbabilityMatrix)
19+
seuratObj <- RIRA::Classify_TNK(seuratObj, maxBatchSize = maxBatchSize, retainProbabilityMatrix = retainProbabilityMatrix)
20+
seuratObj <- RIRA::Classify_Myeloid(seuratObj, maxBatchSize = maxBatchSize, retainProbabilityMatrix = retainProbabilityMatrix)
21+
}
22+
23+
if (applyTCR) {
24+
seuratObj <- Rdiscvr::DownloadAndAppendTcrClonotypes(seuratObj, allowMissing = allowMissingTcr)
25+
}
26+
27+
if (runTNKClassification) {
28+
# ClassifyTNKByExpression will fail without this, so ignore allowMissingTcr
29+
if (!'HasCDR3Data' %in% names(seuratObj@meta.data)) {
30+
seuratObj <- Rdiscvr::DownloadAndAppendTcrClonotypes(seuratObj)
31+
}
32+
33+
seuratObj <- Rdiscvr::ClassifyTNKByExpression(seuratObj)
34+
}
35+
36+
saveData(seuratObj, datasetId)
37+
38+
# Cleanup
39+
rm(seuratObj)
40+
gc()
41+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ public static void registerPipelineSteps()
226226
SequencePipelineService.get().registerPipelineStep(new RunCsCore.Provider());
227227
SequencePipelineService.get().registerPipelineStep(new CustomGSEA.Provider());
228228
SequencePipelineService.get().registerPipelineStep(new StudyMetadata.Provider());
229+
SequencePipelineService.get().registerPipelineStep(new UpdateSeuratPrototype.Provider());
229230

230231
SequenceAnalysisService.get().registerReadsetListener(new SingleCellReadsetListener());
231232
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package org.labkey.singlecell.pipeline.singlecell;
2+
3+
import org.apache.commons.io.FileUtils;
4+
import org.json.JSONObject;
5+
import org.labkey.api.pipeline.PipelineJobException;
6+
import org.labkey.api.sequenceanalysis.SequenceOutputFile;
7+
import org.labkey.api.sequenceanalysis.model.Readset;
8+
import org.labkey.api.sequenceanalysis.pipeline.AbstractPipelineStepProvider;
9+
import org.labkey.api.sequenceanalysis.pipeline.PipelineContext;
10+
import org.labkey.api.sequenceanalysis.pipeline.SequenceOutputHandler;
11+
import org.labkey.api.singlecell.pipeline.SeuratToolParameter;
12+
import org.labkey.api.singlecell.pipeline.SingleCellStep;
13+
import org.labkey.api.util.FileUtil;
14+
import org.labkey.api.writer.PrintWriters;
15+
import org.labkey.singlecell.analysis.AbstractSingleCellHandler;
16+
17+
import java.io.File;
18+
import java.io.IOException;
19+
import java.io.PrintWriter;
20+
import java.nio.file.Files;
21+
import java.util.Arrays;
22+
import java.util.List;
23+
24+
import static org.labkey.singlecell.analysis.AbstractSingleCellHandler.SEURAT_PROTOTYPE;
25+
26+
public class UpdateSeuratPrototype extends AbstractRDiscvrStep
27+
{
28+
public UpdateSeuratPrototype(PipelineContext ctx, UpdateSeuratPrototype.Provider provider)
29+
{
30+
super(provider, ctx);
31+
}
32+
33+
public static class Provider extends AbstractPipelineStepProvider<SingleCellStep>
34+
{
35+
public Provider()
36+
{
37+
super("UpdateSeuratPrototype", "Update Seurat Prototype", "CellMembrane/Rdiscvr", "This will re-process an existing seurat prototype object and overwrite the original", Arrays.asList(
38+
SeuratToolParameter.create("reapplyMetadata", "Reapply Metadata", "If checked, metadata will be re-applied", "checkbox", null, true),
39+
SeuratToolParameter.create("runRira", "Run RIRA", "If checked, RIRA classification will be re-run", "checkbox", null, true),
40+
SeuratToolParameter.create("runTNKClassification", "Run T/NK Classification", "If checked, T/NK expression-based classification will be re-run", "checkbox", null, true),
41+
SeuratToolParameter.create("applyTCR", "Append TCR Data", "If checked, TCR data will be applied. This will fail if", "checkbox", null, true),
42+
SeuratToolParameter.create("allowMissingTcr", "Allow Missing TCR Data", "Unless checked, an error will be thrown if any sample lacks TCR data", "checkbox", new JSONObject()
43+
{{
44+
put("checked", false);
45+
}}, false),
46+
SeuratToolParameter.create("keepOriginal", "Keep Copy of Original File", "If checked, the original file will be copied with the file extension '.bk'", "checkbox", new JSONObject()
47+
{{
48+
put("checked", false);
49+
}}, false)
50+
), null, null);
51+
}
52+
53+
@Override
54+
public UpdateSeuratPrototype create(PipelineContext ctx)
55+
{
56+
return new UpdateSeuratPrototype(ctx, this);
57+
}
58+
}
59+
60+
@Override
61+
public void init(SequenceOutputHandler.JobContext ctx, List<SequenceOutputFile> inputFiles) throws PipelineJobException
62+
{
63+
if (inputFiles.size() > 1)
64+
{
65+
throw new PipelineJobException("Seurat prototype step expects this job to have a single input. Consider selecting the option to run jobs individually instead of merged");
66+
}
67+
68+
if (inputFiles.get(0).getReadset() == null)
69+
{
70+
throw new PipelineJobException("Seurat prototype step expects all inputs to have a readset ID.");
71+
}
72+
73+
if (!SEURAT_PROTOTYPE.equals(inputFiles.get(0).getCategory()))
74+
{
75+
throw new PipelineJobException("Expected the input to be a seurat prototype, found: " + inputFiles.get(0).getCategory());
76+
}
77+
78+
if (ctx.getSequenceSupport().getCachedGenomes().size() > 1)
79+
{
80+
throw new PipelineJobException("Expected seurat prototype step to use a single genome");
81+
}
82+
83+
Readset rs = ctx.getSequenceSupport().getCachedReadset(inputFiles.get(0).getReadset());
84+
if (!ctx.getJob().getContainer().getId().equalsIgnoreCase(rs.getContainer()))
85+
{
86+
throw new PipelineJobException("Seurat prototype jobs must be submitted to the same folder as the source readset");
87+
}
88+
}
89+
90+
@Override
91+
public Output execute(SequenceOutputHandler.JobContext ctx, List<SeuratObjectWrapper> inputObjects, String outputPrefix) throws PipelineJobException
92+
{
93+
Output output = super.execute(ctx, inputObjects, outputPrefix);
94+
95+
if (ctx.getSequenceSupport().getCachedGenomes().size() > 1)
96+
{
97+
throw new PipelineJobException("Expected seurat prototype step to use a single genome");
98+
}
99+
100+
if (output.getSeuratObjects().size() != 1)
101+
{
102+
throw new PipelineJobException("Expected a single output object, found: " + output.getSeuratObjects().size());
103+
}
104+
105+
SeuratObjectWrapper inputRDS = inputObjects.get(0);
106+
SeuratObjectWrapper wrapper = output.getSeuratObjects().get(0);
107+
if (wrapper.getReadsetId() == null)
108+
{
109+
throw new PipelineJobException("Missing readset Id: " + wrapper.getDatasetId());
110+
}
111+
112+
File toReplace = inputRDS.getSequenceOutputFile().getFile();
113+
if (!toReplace.exists())
114+
{
115+
throw new PipelineJobException("Missing file: " + toReplace);
116+
}
117+
try
118+
{
119+
ctx.getLogger().info("Replacing existing prototype: " + toReplace.getPath());
120+
121+
if (ctx.getParams().optBoolean("keepOriginal", false))
122+
{
123+
File backup = new File(toReplace.getPath() + ".orig");
124+
if (backup.exists())
125+
{
126+
backup.delete();
127+
}
128+
129+
FileUtils.moveFile(toReplace, backup);
130+
}
131+
132+
if (toReplace.exists())
133+
{
134+
toReplace.delete();
135+
}
136+
137+
FileUtils.moveFile(wrapper.getFile(), toReplace);
138+
}
139+
catch (IOException e)
140+
{
141+
throw new PipelineJobException(e);
142+
}
143+
144+
return output;
145+
}
146+
}

0 commit comments

Comments
 (0)