2020import org .labkey .api .sequenceanalysis .pipeline .ToolParameterDescriptor ;
2121import org .labkey .api .sequenceanalysis .run .AbstractAlignmentPipelineStep ;
2222import org .labkey .api .sequenceanalysis .run .AbstractCommandWrapper ;
23+ import org .labkey .api .util .FileUtil ;
2324
2425import java .io .File ;
2526import java .io .IOException ;
@@ -136,7 +137,8 @@ public AlignmentOutput performAlignment(Readset rs, List<File> inputFastqs1, @Nu
136137 params .add ("minid=" + val );
137138 }
138139
139- File bam = getWrapper ().doAlignment (inputFastq1 , inputFastq2 , outputDirectory , basename , params );
140+ boolean retainUnmapped = getProvider ().getParameterByName ("retainUnmapped" ).extractValue (getPipelineCtx ().getJob (), getProvider (), getStepIdx (), Boolean .class , false );
141+ File bam = getWrapper ().doAlignment (inputFastq1 , inputFastq2 , outputDirectory , basename , params , retainUnmapped );
140142 if (!bam .exists ())
141143 {
142144 throw new PipelineJobException ("BAM not created, expected: " + bam .getPath ());
@@ -145,6 +147,17 @@ public AlignmentOutput performAlignment(Readset rs, List<File> inputFastqs1, @Nu
145147 output .setBAM (bam );
146148 output .addCommandsExecuted (getWrapper ().getCommandsExecuted ());
147149
150+ if (retainUnmapped )
151+ {
152+ File unmappedBam = getWrapper ().getUnmappedFilename (bam );
153+ if (!unmappedBam .exists ())
154+ {
155+ throw new PipelineJobException ("Unable to find file: " + unmappedBam .getPath ());
156+ }
157+
158+ output .addSequenceOutput (unmappedBam , rs .getName () + ": BBmap unmapped reads" , "Alignment" , rs .getReadsetId (), null , referenceGenome .getGenomeId (), "BBMap Unmapped Reads" );
159+ }
160+
148161 return output ;
149162 }
150163
@@ -184,14 +197,18 @@ public Provider()
184197 }}, true ),
185198 ToolParameterDescriptor .create ("semiperfectmode" , "Semi-perfectmode" , "Allow only perfect and semiperfect (perfect except for N's in the reference) mappings" , "checkbox" , new JSONObject ()
186199 {{
187- put ("checked" , true );
188- }}, true ),
200+ put ("checked" , false );
201+ }}, false ),
189202 ToolParameterDescriptor .create ("minid" , "Minimum Identity" , "Approximate minimum alignment identity to look for. Higher is faster and less sensitive" , "ldk-numberfield" , new JSONObject ()
190203 {{
191204 put ("minValue" , 0 );
192205 put ("maxValue" , 1 );
193206 put ("decimalPrecision" , 2 );
194- }}, 0.95 )
207+ }}, 0.95 ),
208+ ToolParameterDescriptor .create ("retainUnmapped" , "Retain Unmapped" , "If checked, unmapped reads are written to a separate BAM file" , "checkbox" , new JSONObject ()
209+ {{
210+ put ("checked" , false );
211+ }}, false )
195212 ), null , "https://prost.readthedocs.io/en/latest/bbmap.html" , true , true );
196213 }
197214
@@ -202,12 +219,18 @@ public BBMapAlignmentStep create(PipelineContext context)
202219 }
203220 }
204221
222+ protected File getUnmappedFilename (File mappedSamOrBam )
223+ {
224+ String fn = FileUtil .getBaseName (mappedSamOrBam .getName ()) + ".unmapped." + FileUtil .getExtension (mappedSamOrBam .getName ());
225+ return new File (mappedSamOrBam .getParentFile (), fn );
226+ }
227+
205228 protected File getExe ()
206229 {
207230 return SequencePipelineService .get ().getExeForPackage ("BBMAPPATH" , "bbmap.sh" );
208231 }
209232
210- public File doAlignment (File inputFastq1 , @ Nullable File inputFastq2 , File outputDirectory , String basename , List <String > options ) throws PipelineJobException
233+ public File doAlignment (File inputFastq1 , @ Nullable File inputFastq2 , File outputDirectory , String basename , List <String > options , boolean retainUnmaped ) throws PipelineJobException
211234 {
212235 List <String > args = new ArrayList <>();
213236 args .add (getExe ().getPath ());
@@ -243,6 +266,18 @@ public File doAlignment(File inputFastq1, @Nullable File inputFastq2, File outpu
243266
244267 args .add ("outm=" + outputSam .getPath ());
245268
269+ File outputUnmappedSam = null ;
270+ if (retainUnmaped )
271+ {
272+ outputUnmappedSam = getUnmappedFilename (outputSam );
273+ if (outputUnmappedSam .exists ())
274+ {
275+ outputUnmappedSam .delete ();
276+ }
277+
278+ args .add ("outu=" + outputUnmappedSam .getPath ());
279+ }
280+
246281 Integer maxRam = SequencePipelineService .get ().getMaxRam ();
247282 if (maxRam != null )
248283 {
@@ -284,6 +319,32 @@ public File doAlignment(File inputFastq1, @Nullable File inputFastq2, File outpu
284319
285320 outputSam .delete ();
286321
322+ // repeat for unmapped:
323+ if (outputUnmappedSam != null )
324+ {
325+ File outputUnmappedBam = getUnmappedFilename (outputBam );
326+ if (outputUnmappedBam != null && outputUnmappedBam .exists ())
327+ {
328+ outputUnmappedBam .delete ();
329+ }
330+
331+ samtoolsRunner = new SamtoolsRunner (getLogger ());
332+ stArgs = new ArrayList <>();
333+ stArgs .add (samtoolsRunner .getSamtoolsPath ().getPath ());
334+ stArgs .add ("view" );
335+ stArgs .add ("-o" );
336+ stArgs .add (outputUnmappedBam .getPath ());
337+ stArgs .add (outputUnmappedSam .getPath ());
338+ samtoolsRunner .execute (stArgs );
339+
340+ if (!outputUnmappedBam .exists ())
341+ {
342+ throw new PipelineJobException ("File not found: " + outputBam .getPath ());
343+ }
344+
345+ outputUnmappedSam .delete ();
346+ }
347+
287348 return outputBam ;
288349 }
289350
0 commit comments