metamap-fastqingress

This commit is contained in:
Matt Parker 2022-07-21 12:28:45 +01:00
parent 63d1d894ee
commit 0f38613c6a
3 changed files with 84 additions and 31 deletions

View File

@ -6,7 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [unreleased] ## [unreleased]
### Changed ### Changed
- Skip unnecessary conversion to fasta from fastq. - Skip unnecessary conversion to fasta from fastq
- Fastqingress metadata map
## [v0.1.4] ## [v0.1.4]
### Changed ### Changed

View File

@ -29,6 +29,25 @@ process checkSampleSheet {
""" """
} }
/**
* Compare number of samples in samplesheet
* with the number of barcoded dirs found and
* print warnings
*
*
* @param number of samples in sample sheet
* @param number of barcoded directories
* @return null
*/
def compareSampleSheetFastq(int sample_sheet_count, int valid_dir_count)
{
if (sample_sheet_count != valid_dir_count) {
log.warn """The number of samplesheet entries ({}) does not match the number of barcoded directories ({})""", sample_sheet_count, valid_dir_count
}
}
/** /**
* Take an input file and sample name to return a channel with * Take an input file and sample name to return a channel with
@ -37,13 +56,14 @@ process checkSampleSheet {
* *
* @param input_file Single fastq file * @param input_file Single fastq file
* @param sample_name Name to give the sample * @param sample_name Name to give the sample
* @return Channel of tuples (path, sample_id, type) * @return Channel of tuples (path, map(sample_id, type, barcode))
*/ */
def handle_single_file(input_file, sample_name) def handle_single_file(input_file, sample_name)
{ {
singleFile = Channel.fromPath(input_file) singleFile = Channel.fromPath(input_file)
sample = handleSingleFile(singleFile) sample = handleSingleFile(singleFile)
return sample.map { it -> tuple(it, sample_name === null ? it.simpleName : sample_name, 'test_sample') } return sample.map { it -> tuple(it, create_metamap([sample_id:sample_name ?: it.simpleName])) }
} }
@ -207,13 +227,14 @@ def get_valid_directories(input_dirs)
* *
* @param input_directory Directory of fastq files * @param input_directory Directory of fastq files
* @param sample_name Name to give the sample * @param sample_name Name to give the sample
* @return Channel of tuples (path, sample_id, type) * @return Channel of tuples (path, map(sample_id, type, barcode))
*/ */
def handle_flat_dir(input_directory, sample_name) def handle_flat_dir(input_directory, sample_name)
{ {
valid_dirs= get_valid_directories([ file(input_directory) ]) valid_dirs= get_valid_directories([ file(input_directory) ])
return Channel.fromPath(valid_dirs) return Channel.fromPath(valid_dirs)
.map { it -> tuple(it, sample_name === null ? it.baseName : sample_name, 'test_sample') } .map { it -> tuple(it, create_metamap([sample_id:sample_name ?: it.baseName])) }
} }
@ -227,7 +248,7 @@ def handle_flat_dir(input_directory, sample_name)
* or a simple string for non-multiplexed data. * or a simple string for non-multiplexed data.
* @param min_barcode Minimum barcode to accept. * @param min_barcode Minimum barcode to accept.
* @param max_barcode Maximum (inclusive) barcode to accept. * @param max_barcode Maximum (inclusive) barcode to accept.
* @return Channel of tuples (path, sample_id, type) * @return Channel of tuples (path, map(sample_id, type, barcode))
*/ */
def handle_barcoded_dirs(barcoded_dirs, sample_sheet, min_barcode, max_barcode) def handle_barcoded_dirs(barcoded_dirs, sample_sheet, min_barcode, max_barcode)
{ {
@ -239,14 +260,33 @@ def handle_barcoded_dirs(barcoded_dirs, sample_sheet, min_barcode, max_barcode)
.filter(~/.*barcode[0-9]{1,3}$/) // up to 192 .filter(~/.*barcode[0-9]{1,3}$/) // up to 192
.filter { barcode_in_range(it, min_barcode, max_barcode) } .filter { barcode_in_range(it, min_barcode, max_barcode) }
.map { path -> tuple(path.baseName, path.baseName, 'test_sample')} .map { path -> tuple(path.baseName, path.baseName, 'test_sample')}
} else {
// return warning if there is a discrepancy between the samplesheet and barcode dirs
// unclassfied will never be in the sample_sheet so remove
non_unclassified = valid_dirs
non_unclassified -= 'unclassified'
barcode_dirs_found = non_unclassified.size()
int count = 0
// We do this instead of .count() because valid_dirs is a list and
// sample_sheet is a channel - the channel is only populated after
// checkSampleSheet is complete and so if you compare without
// waiting for that then the comparisson fails
sample_sheet_entries = sample_sheet.subscribe onNext: { count++ }, onComplete: { compareSampleSheetFastq(count,barcode_dirs_found) }
} }
return Channel return Channel
.fromPath(valid_dirs) .fromPath(valid_dirs)
.filter(~/.*barcode[0-9]{1,3}$/) // up to 192 .filter(~/.*barcode[0-9]{1,3}$/) // up to 192
.filter { barcode_in_range(it, min_barcode, max_barcode) } .filter { barcode_in_range(it, min_barcode, max_barcode) }
.map { path -> tuple(path.baseName, path) } .map { path -> tuple(path.baseName, path) }
.join(sample_sheet) .join(sample_sheet)
.map { barcode, path, sample, type -> tuple(path, sample, type) } .map { barcode, path, sample, type -> tuple(path, create_metamap([sample_id:sample, type:type, barcode:barcode])) }
} }
@ -273,15 +313,26 @@ def barcode_in_range(path, min_barcode, max_barcode)
* *
* *
* @param non_barcoded_dirs List of directories (mydir,...) * @param non_barcoded_dirs List of directories (mydir,...)
* @return Channel of tuples (path, sample_id, type) * @return Channel of tuples (path, map(sample_id, type, barcode))
*/ */
def handle_non_barcoded_dirs(non_barcoded_dirs) def handle_non_barcoded_dirs(non_barcoded_dirs)
{ {
valid_dirs = get_valid_directories(non_barcoded_dirs) valid_dirs = get_valid_directories(non_barcoded_dirs)
return Channel.fromPath(valid_dirs) return Channel.fromPath(valid_dirs)
.map { path -> tuple(path, path.baseName, 'test_sample') } .map { path -> tuple(path, create_metamap([sample_id:path.baseName])) }
} }
def create_metamap(Map arguments) {
def parser = new ArgumentParser(
args:["sample_id"],
kwargs:[
"type": "test_sample",
"barcode": null,
],
name:"create_metamap",
)
return parser.parse_args(arguments)
}
/** /**
* Take an input (file or directory) and return a channel of * Take an input (file or directory) and return a channel of
@ -295,7 +346,7 @@ def handle_non_barcoded_dirs(non_barcoded_dirs)
* @param min_barcode Minimum barcode to accept. * @param min_barcode Minimum barcode to accept.
* @param max_barcode Maximum (inclusive) barcode to accept. * @param max_barcode Maximum (inclusive) barcode to accept.
* *
* @return Channel of tuples (path, sample_id, type) * @return Channel of tuples (path, map(sample_id, type, barcode))
*/ */
def fastq_ingress(Map arguments) def fastq_ingress(Map arguments)
{ {
@ -311,6 +362,7 @@ def fastq_ingress(Map arguments)
throw new Exception("Argument 'output' required if 'sanitize' is true.") throw new Exception("Argument 'output' required if 'sanitize' is true.")
} }
println("Checking fastq input.") println("Checking fastq input.")
input = file(margs.input) input = file(margs.input)

View File

@ -22,13 +22,13 @@ process summariseConcatReads {
label "isoforms" label "isoforms"
cpus 1 cpus 1
input: input:
tuple path(directory), val(sample_id), val(type) tuple path(directory), val(meta)
output: output:
tuple val(sample_id), path("${sample_id}.fastq"), emit: input_reads tuple val(meta.sample_id), path("${meta.sample_id}.fastq"), emit: input_reads
tuple val(sample_id), path('*.stats'), emit: summary tuple val(meta.sample_id), path('*.stats'), emit: summary
script: script:
""" """
fastcat -s ${sample_id} -r ${sample_id}.stats -x ${directory} > ${sample_id}.fastq fastcat -s ${meta.sample_id} -r ${meta.sample_id}.stats -x ${directory} > ${meta.sample_id}.fastq
""" """
} }