Skip to content

Commit

Permalink
Merge pull request #29 from mc2-center/allow-custom-config
Browse files Browse the repository at this point in the history
Allow use of a custom config file
  • Loading branch information
adamjtaylor authored Feb 11, 2024
2 parents 0a099eb + b9d4ce8 commit dd3b395
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 27 deletions.
64 changes: 44 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ Other columns may be provided but are not used by the pipeline.
- `input`: Path to a CSV sample sheet. This parameter is required.
- `outDir`: Specifies the directory where the output data should be saved. Default is `outputs`.

#### HistoQC options
#### Other options

- `config`: Configuration file used by HistoQC. Must be one of `default`, `ihc`, `clinical`, `first`, `light`, or `v2.1`.Custom config files are not currently supported.
- `config` (string): Name of a built-in configuration used by HistoQC. Must be one of `default`, `ihc`, `clinical`, `first`, `light`, or `v2.1`. Defaults to `default`.
- `custom_config` (path): Path to a HistoQC compatible configuration file. Must have a `.ini` extension. Overrides `config`.
- `convert` (bool): If provided, `vips` is used to [create an OpenSlide compatiable TIFF file](http://www.andrewjanowczyk.com/converting-an-existing-image-into-an-openslide-compatible-format/). Uses [mc2-center/histoqc-openslide-converter](https://github.com/mc2-center/histoqc-openslide-converter).

### Profiles

Expand All @@ -86,23 +88,45 @@ The container is automatically pulled by NextFlow, but if local use is required
> A Nextflow pipeline is implicitly modelled by a direct acyclic graph (DAG). The vertices in the graph represent the pipeline’s processes and operators, while the edges represent the data connections (i.e. channels) between them.
```mermaid
flowchart TD
p0((Channel.fromPath))
p1([splitCsv])
p2([map])
p3[NF_HISTOQC:RUN_HISTOQC:HISTOQC]
p4(( ))
p5(( ))
p6([collect])
p7[NF_HISTOQC:COLLECT_RESULTS:COLLECT]
p8(( ))
p0 --> p1
p1 --> p2
p2 -->|images| p3
p3 -->|results| p6
p3 --> p5
p3 -->|output| p4
p6 --> p7
p7 --> p8
flowchart TB
subgraph " "
v0["Channel.fromPath"]
v3["Channel.fromPath"]
v6["config_string"]
end
subgraph NF_HISTOQC
subgraph RUN
v5([CONVERT])
v7([HISTOQC])
v1(( ))
v4(( ))
v9(( ))
v13(( ))
end
subgraph COLLECT
v10([RESULTS])
v11([TIDY])
v14([LOGS])
end
end
subgraph " "
v8["output"]
v12[" "]
v15[" "]
end
v0 --> v1
v3 --> v4
v1 --> v5
v5 --> v7
v6 --> v7
v4 --> v7
v7 --> v8
v7 --> v9
v7 --> v13
v9 --> v10
v10 --> v11
v11 --> v12
v13 --> v14
v14 --> v15
```
Empty file added assets/empty.txt
Empty file.
17 changes: 14 additions & 3 deletions main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,35 @@

nextflow.enable.dsl=2

// Set parameters and defaults

// Check if the input samplesheet is provided
if (params.input) { params.input = file(params.input) } else { exit 1, 'Input samplesheet not specified!' }

// Check requirements for the convert param to be used
params.convert = false

if (params.convert) {
if (!params.mag || !params.mpp) {
error "Both nominal magnification ('mag') and microns per pixel ('mpp' parameters must be provided when 'params.convert' is set to true."
}
}

// Check requirements for the custom_config param to be used
params.custom_config = null
if ( params.custom_config ) {
if (! file(params.custom_config).exists() ) { error "Custom config file does not exist" }
if (! file(params.custom_config).getName().endsWith(".ini") ) { error "Custom config file is not a .ini file" }
}

// Set parameters and defaults
// Set default outdir and config
params.outDir = './outputs'
params.config = 'default'

// Import workflow
include { NF_HISTOQC } from './workflows/nf_histoqc.nf'
// include { COMBINE_RESULTS } from './modules/combine_results.nf'


// Run workflow
workflow {
NF_HISTOQC ()
}
15 changes: 14 additions & 1 deletion modules/histoqc.nf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ process HISTOQC {

input:
tuple val(meta), path(images)
val config_string
path custom_config

output:
path "out/results.tsv", emit: results
Expand All @@ -16,7 +18,18 @@ process HISTOQC {

script:
"""
python -m histoqc -c ${params.config} $images -o out
# Add the logic for the if config_string or custom_config here
# Check if custom_config points to "empty.txt"
if [[ "$custom_config" == *empty.txt ]]; then
# If yes, use the config_string
ini="$config_string"
else
# If no, use the path to custom_config
ini=$custom_config
fi
echo "Using config: \$ini"
python -m histoqc $images -o out -c \$ini
mv out/$images/*.png .
"""
}
11 changes: 9 additions & 2 deletions nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,20 @@
"title": "HistoQC options",
"type": "object",
"fa_icon": "fas fa-solid fa-microscope",
"description": "Define parameters for histoqc",
"description": "Define parameters for HistoQC",
"required": ["config"],
"properties": {
"config": {
"type": "string",
"default": "default",
"enum": ["default", "ihc", "clinical", "first", "light", "v2.1"]
"enum": ["default", "ihc", "clinical", "first", "light", "v2.1"],
"description": "Name of built-in HistoQC config. Overridden by `custom_config`."
},
"custom_config": {
"type": "string",
"format": "file-path",
"mimetype": "text/plain",
"description": "Path to a HistoQC config `.ini` file. Overrides `config`"
}
}
},
Expand Down
13 changes: 12 additions & 1 deletion subworkflows/run_histoqc.nf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@ workflow RUN {

main:

params.convert ? CONVERT(images) | HISTOQC : HISTOQC(images)
// If a custom config is passed use it, otherwise pass a dummy file
def custom_config = params.custom_config ? Channel.fromPath(params.custom_config).first() : Channel.fromPath("assets/empty.txt").first() // need to pass a dummy file in the projectDir or similar

// Scenario 1: Conversion
if (params.convert ) {
CONVERT(images)
HISTOQC(CONVERT.out, params.config, custom_config)
}
// Scenario 2: No conversion
else {
HISTOQC(images, params.config, custom_config)
}

emit:
output = HISTOQC.out.masks
Expand Down

0 comments on commit dd3b395

Please sign in to comment.