Skip to content

Commit

Permalink
Merge pull request #48 from RobJY/backsub
Browse files Browse the repository at this point in the history
Add background subtraction
  • Loading branch information
jmuhlich authored Dec 2, 2024
2 parents c7cc952 + 7acc05e commit 5ab677f
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 84 deletions.
10 changes: 5 additions & 5 deletions assets/markers_1_sp.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
channel_number,cycle_number,marker_name,filter,excitation_wavelength,emission_wavelength,background
21,1,DNA_6,DAPI,395,431,21
22,1,ELA NE,FITC,485,525,21
23,1,CD57,Sy tox,555,590,21
24,1,CD45,Cy5,640,690,21
channel_number,cycle_number,marker_name
21,1,DNA_6
22,1,ELA NE
23,1,CD57
24,1,CD45
9 changes: 9 additions & 0 deletions assets/schema_marker.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@
"emission_wavelength": {
"type": "integer",
"errorMessage": ""
},
"exposure": {
"type": "number"
},
"background": {
"type": "string"
},
"remove": {
"type": "boolean"
}
},
"required": ["channel_number", "cycle_number", "marker_name"]
Expand Down
3 changes: 3 additions & 0 deletions nextflow.config
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ params {
// Illumination correction
illumination = null

// Background subtraction
backsub = false

// MultiQC options
multiqc_config = null
multiqc_title = null
Expand Down
4 changes: 4 additions & 0 deletions nextflow_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
"type": "string",
"description": "optional model file for cellpose segmentation"
},
"backsub": {
"type": "boolean",
"description": "boolean to flag whether or not to apply background subtraction"
},
"pixel_size": {
"type": "number",
"description": "Pixel width of input image data, in microns",
Expand Down
25 changes: 24 additions & 1 deletion subworkflows/local/utils_nfcore_mcmicro_pipeline/main.nf
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,35 @@ def validateInputMarkersheet( markersheet_data ) {
error("Duplicate [channel, cycle] pairs: ${dups}")
}

// validate backsub columns if present
def exposure_list = markersheet_data.findResults{ _1, _2, _3, _4, _5, _6, exposure, _8, _9 -> exposure ?: null }
def background_list = markersheet_data.findResults{ _1, _2, _3, _4, _5, _6, _7, background, _9 -> background ?: null }
def remove_list = markersheet_data.findResults{ _1, _2, _3, _4, _5, _6, _7, _8, remove -> remove ?: null }

if (!background_list && (exposure_list || remove_list)) {
error("No values in background column, but values in either exposure or remove columns. Must have background column values to perform background subtraction.")
} else if (background_list) {
inter_list = marker_name_list.intersect(background_list)
if (inter_list.size() != background_list.size()) {
outliers_list = background_list - inter_list
error('background column values must exist in the marker_name column. The following background column values do not exist in the marker_name column: ' + outliers_list)
}

if (!exposure_list) {
error('You must have at least one value in the exposure column to perform background subtraction')
}

if (!remove_list) {
error ('You must have at least one value in the remove column to perform background subtraction')
}
}

return markersheet_data
}

def validateInputSamplesheetMarkersheet ( samples, markers ) {
def sample_cycles = samples.collect{ meta, image_tiles, dfp, ffp -> meta.cycle_number }
def marker_cycles = markers.collect{ channel_number, cycle_number, marker_name, filter, excitation_wavelength, emission_wavelength -> cycle_number }
def marker_cycles = markers.collect{ channel_number, cycle_number, marker_name, _1, _2, _3, _4, _5, _6 -> cycle_number }

if (marker_cycles.unique(false) != sample_cycles.unique(false) ) {
error("cycle_number values must match between sample and marker sheets")
Expand Down
185 changes: 120 additions & 65 deletions tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -68,10 +68,10 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -113,10 +113,10 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -167,18 +167,18 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[5,1,'DNA_7',[],[],[]],
[6,1,'ELANE7',[],[],[]],
[7,1,'CD577',[],[],[]],
[8,1,'CD457',[],[],[]],
[9,1,'DNA_8',[],[],[]],
[10,1,'ELANE8',[],[],[]],
[11,1,'CD578',[],[],[]],
[12,1,'CD458',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
[5,1,'DNA_7',[],[],[],[],[],[]],
[6,1,'ELANE7',[],[],[],[],[],[]],
[7,1,'CD577',[],[],[],[],[],[]],
[8,1,'CD457',[],[],[],[],[],[]],
[9,1,'DNA_8',[],[],[],[],[],[]],
[10,1,'ELANE8',[],[],[],[],[],[]],
[11,1,'CD578',[],[],[],[],[],[]],
[12,1,'CD458',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -235,14 +235,14 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[5,1,'DNA_7',[],[],[]],
[6,1,'ELANE7',[],[],[]],
[7,1,'CD577',[],[],[]],
[8,1,'CD457',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
[5,1,'DNA_7',[],[],[],[],[],[]],
[6,1,'ELANE7',[],[],[],[],[],[]],
[7,1,'CD577',[],[],[],[],[],[]],
[8,1,'CD457',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -302,14 +302,14 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[5,1,'DNA_7',[],[],[]],
[6,1,'ELANE7',[],[],[]],
[7,1,'CD577',[],[],[]],
[8,1,'CD457',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
[5,1,'DNA_7',[],[],[],[],[],[]],
[6,1,'ELANE7',[],[],[],[],[],[]],
[7,1,'CD577',[],[],[],[],[],[]],
[8,1,'CD457',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -368,18 +368,18 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[5,1,'DNA_7',[],[],[]],
[6,1,'ELANE7',[],[],[]],
[7,1,'CD577',[],[],[]],
[8,1,'CD457',[],[],[]],
[9,1,'DNA_8',[],[],[]],
[10,1,'ELANE8',[],[],[]],
[11,1,'CD578',[],[],[]],
[12,1,'CD458',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
[5,1,'DNA_7',[],[],[],[],[],[]],
[6,1,'ELANE7',[],[],[],[],[],[]],
[7,1,'CD577',[],[],[],[],[],[]],
[8,1,'CD457',[],[],[],[],[],[]],
[9,1,'DNA_8',[],[],[],[],[],[]],
[10,1,'ELANE8',[],[],[],[],[],[]],
[11,1,'CD578',[],[],[],[],[],[]],
[12,1,'CD458',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -443,14 +443,14 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[5,1,'DNA_7',[],[],[]],
[6,1,'ELANE7',[],[],[]],
[7,1,'CD577',[],[],[]],
[8,1,'CD457',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
[5,1,'DNA_7',[],[],[],[],[],[]],
[6,1,'ELANE7',[],[],[],[],[],[]],
[7,1,'CD577',[],[],[],[],[],[]],
[8,1,'CD457',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -498,10 +498,10 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[2,1,'ELANE',[],[],[]],
[3,1,'CD57',[],[],[]],
[4,1,'CD45',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
[2,1,'ELANE',[],[],[],[],[],[]],
[3,1,'CD57',[],[],[],[],[],[]],
[4,1,'CD45',[],[],[],[],[],[]],
],
)
"""
Expand Down Expand Up @@ -543,7 +543,7 @@ nextflow_workflow {
)
input[1] = Channel.of(
[
[1,1,'DNA_6',[],[],[]],
[1,1,'DNA_6',[],[],[],[],[],[]],
],
)
"""
Expand All @@ -564,5 +564,60 @@ nextflow_workflow {
}
},

test("cycle: no illumination correction, backsub") {

when {
params {
segmentation = "mesmer"
backsub = true
}
workflow {
"""
input[0] = Channel.of(
[
[id:"TEST1", cycle_number:1, channel_count:4],
"https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/imaging/ome-tiff/cycif-tonsil-cycle1.ome.tif",
[],
[],
],
[
[id:"TEST1", cycle_number:2, channel_count:4],
"https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/imaging/ome-tiff/cycif-tonsil-cycle2.ome.tif",
[],
[],
],
)
input[1] = Channel.of(
[
[1,1,'DNA 1',[],[],[],100,[],[]],
[2,1,'Na/K ATPase',[],[],[],100,[],[]],
[3,1,'CD3',[],[],[],100,[],[]],
[4,1,'CD45RO',[],[],[],100,[],[]],
[5,1,'DNA 2',[],[],[],100,[],[]],
[6,1,'Antigen Ki67',[],[],[],100,[],[]],
[7,1,'Pan-cytokeratin',[],[],[],100,[],[]],
[8,1,'Aortic smooth muscle actin',[],[],[],100,[],[]]
],
)
"""
}
}

then {
assertAll (
{
assert snapshot (
path("$outputDir/registration/ashlar/TEST1.ome.tif"),
path("$outputDir/segmentation/deepcell_mesmer/mask_TEST1.tif"),
CsvUtils.summarizeCsv("$outputDir/quantification/mcquant/mesmer/TEST1_mask_TEST1.csv"),
path("$outputDir/backsub/TEST1.backsub.ome.tif"),
).match()
},
{ assert workflow.success }
)
}

},

]
}
35 changes: 35 additions & 0 deletions tests/main.nf.test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,41 @@
},
"timestamp": "2024-08-14T13:21:48.678353201"
},
"cycle: no illumination correction, backsub": {
"content": [
"TEST1.ome.tif:md5,fd414b610e189f3e805c8e99f4e78c09",
"mask_TEST1.tif:md5,3103759bd55b9deeb8c8a0dade798d9a",
{
"headers": [
"CellID",
"DNA 1",
"Na/K ATPase",
"CD3",
"CD45RO",
"DNA 2",
"Antigen Ki67",
"Pan-cytokeratin",
"Aortic smooth muscle actin",
"X_centroid",
"Y_centroid",
"Area",
"MajorAxisLength",
"MinorAxisLength",
"Eccentricity",
"Solidity",
"Extent",
"Orientation"
],
"rowCount": 2111
},
"TEST1.backsub.ome.tif:md5,82b15c88057ab8fd8248402a687997ea"
],
"meta": {
"nf-test": "0.9.0",
"nextflow": "24.04.4"
},
"timestamp": "2024-10-08T12:33:35.316668616"
},
"cycle: multiple file ashlar input with multiple samples no correction, multiple segmentation": {
"content": [
"cycif-tonsil.ome.tif:md5,fd414b610e189f3e805c8e99f4e78c09",
Expand Down
Loading

0 comments on commit 5ab677f

Please sign in to comment.