Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Quantification of cell-nuclei is performed using a 3D-Unet and it is performed o

**Allen Brain Atlas Registration (Optional)**

This workflow registers full brain images to the Allen Brain Reference Atlas. This is an optional workflow and can be chosen by setting the parameter: `ara_registartion`
This workflow registers full brain images to the Allen Brain Reference Atlas. This is an optional workflow and can be chosen by setting the parameter: [`ara_registration`](./parameters/#ara_registration)

## Usage

Expand All @@ -55,9 +55,7 @@ This workflow registers full brain images to the Allen Brain Reference Atlas. Th

To run the pipeline you need to provide a samplesheet with your data in the following structure:

`samplesheet.csv`

```csv
```csv title="samplesheet.csv
sample_id,img_directory,parameter_file
TEST1,path/to/image-files,path/to/parameter/file.csv
```
Expand Down
2 changes: 1 addition & 1 deletion conf/base.config
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ process {
maxRetries = 1
maxErrors = '-1'

cache = 'lenient'


// Process-specific resource requirements
// NOTE - Please try and reuse the labels below as much as possible.
Expand Down
15 changes: 13 additions & 2 deletions docs/usage.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# nf-core/lsmquant: Usage

## :warning: Please read this documentation on the nf-core website: [https://nf-co.re/lsmquant/usage](https://nf-co.re/lsmquant/usage)

> _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._

## Introduction

## Samplesheet input
Expand Down Expand Up @@ -35,6 +39,13 @@ TEST3,/path/to/TEST3/,/path/to/params_TEST3.csv

If different samples should be processed with the same parameter set specified in the `params.csv`, you can use the same `params.csv` for different samples.

```csv title="samplesheet2.csv"
sample_id,img_directory,parameter_file
TEST1,/path/to/TEST1/,/path/to/params_set1.csv
TEST2,/path/to/TEST2/,/path/to/params_set1.csv
TEST3,/path/to/TEST3/,/path/to/params_set1.csv
```

### Parameter file

In the `parameter.csv` file you should specify processing parameters for your data and pipeline run for each sample. The `CSV` contains specific fields that are needed for the processes to run and only the value column should be modified. You can download a template parameter file [here](../assets/params_template_lsmquant.csv).
Expand Down Expand Up @@ -345,7 +356,7 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof
- `wave`
- A generic configuration profile to enable [Wave](https://seqera.io/wave/) containers. Use together with one of the above (requires Nextflow ` 24.03.0-edge` or later).
- `conda`
- This profile is not available for nf-core/lsmquant
- This profile is not available for nf-core/lsmquant. The main tools used in this pipeline are compiled MATLAB applications and cannot be distributed via conda

### `-resume`

Expand Down Expand Up @@ -493,4 +504,4 @@ Stitching process proceeds with iterative alignment in the x–y plane. The star

### Nuclei quantification

Images are subdivided into patches of 112 × 112 × 32 voxels with an overlap of 16 × 16 × 8 voxels to reduce boundary artifacts. Each patch is then passed to a modified pretrained 3D‑UNet (based on Çiçek et al., 2016 and Isensee et al., 2018) to predict binary nuclei masks. Individual nuclei are obtained via connected‑component analysis, and centroid coordinates are extracted from these components. To prevent duplicate detections introduced by overlapping patches, centroids located closer than half the overlap to a patch border (< 8 pixels in x/y or < 4 pixels in z) are removed under the assumption they will be captured by the neighboring patch. Remaining centroids across all patches are merged using a kd‑tree nearest‑neighbor search, eliminating duplicates within 1.5 voxels of each other to ensure each nucleus is counted exactly once.
Images are subdivided into patches of 112 × 112 × 32 voxels with an overlap of 16 × 16 × 8 voxels to reduce boundary artifacts. Each patch is then passed to a modified pretrained 3D‑UNet (based on [Ellis et al., 2022](https://www.frontiersin.org/journals/neuroimaging/articles/10.3389/fnimg.2022.834883/full), [Çiçek et al., 2016](https://arxiv.org/abs/1606.06650) and [Isensee et al., 2018](https://arxiv.org/abs/1802.10508)) to predict binary nuclei masks. Individual nuclei are obtained via connected‑component analysis, and centroid coordinates are extracted from these components. To prevent duplicate detections introduced by overlapping patches, centroids located closer than half the overlap to a patch border (< 8 pixels in x/y or < 4 pixels in z) are removed under the assumption they will be captured by the neighboring patch. Remaining centroids across all patches are merged using a kd‑tree nearest‑neighbor search, eliminating duplicates within 1.5 voxels of each other to ensure each nucleus is counted exactly once.
11 changes: 0 additions & 11 deletions subworkflows/local/numorph_preprocessing/tests/.nftignore

This file was deleted.

4 changes: 2 additions & 2 deletions subworkflows/local/numorph_preprocessing/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ nextflow_workflow {

then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'subworkflows/local/numorph_preprocessing/tests/.nftignore')
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assert workflow.success
assertAll(
{ assert snapshot(
Expand Down Expand Up @@ -93,7 +93,7 @@ nextflow_workflow {
}
then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'subworkflows/local/numorph_preprocessing/tests/.nftignore')
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assert workflow.success
assertAll(
{ assert snapshot(
Expand Down
102 changes: 43 additions & 59 deletions subworkflows/local/numorph_preprocessing/tests/main.nf.test.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,29 @@
"mat2json/preprocessing/TEST1/thresholds.json",
"mat2json/preprocessing/TEST1/z_disp_matrix.json",
"mat2json/preprocessing/TEST1/z_displacement_align.json",
"numorph",
"numorph/results",
"numorph/results/NM_variables.mat",
"numorph/results/samples",
"numorph/results/samples/intensity_adjustment",
"numorph/results/samples/intensity_adjustment/ctip2_1_1_11.tif",
"numorph/results/samples/intensity_adjustment/ctip2_1_2_11.tif",
"numorph/results/samples/intensity_adjustment/ctip2_2_1_11.tif",
"numorph/results/samples/intensity_adjustment/ctip2_2_2_11.tif",
"numorph/results/samples/intensity_adjustment/flatfield_1.png",
"numorph/results/samples/intensity_adjustment/flatfield_2.png",
"numorph/results/samples/intensity_adjustment/tile_adj_1.png",
"numorph/results/samples/intensity_adjustment/tile_adj_2.png",
"numorph/results/samples/intensity_adjustment/topro_1_1_11.tif",
"numorph/results/samples/intensity_adjustment/topro_1_2_11.tif",
"numorph/results/samples/intensity_adjustment/topro_2_1_11.tif",
"numorph/results/samples/intensity_adjustment/topro_2_2_11.tif",
"numorph/results/samples/intensity_adjustment/y_adj_1.png",
"numorph/results/samples/intensity_adjustment/y_adj_2.png",
"numorph/results/variables",
"numorph/results/variables/adj_params.mat",
"numorph/results/variables/path_table.mat",
"numorph/results/variables/thresholds.mat",
"numorph_intensity",
"numorph_intensity/TEST1",
"numorph_intensity/TEST1/NM_variables.mat",
"numorph_intensity/TEST1/samples",
"numorph_intensity/TEST1/samples/intensity_adjustment",
"numorph_intensity/TEST1/samples/intensity_adjustment/ctip2_1_1_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/ctip2_1_2_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/ctip2_2_1_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/ctip2_2_2_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/flatfield_1.png",
"numorph_intensity/TEST1/samples/intensity_adjustment/flatfield_2.png",
"numorph_intensity/TEST1/samples/intensity_adjustment/tile_adj_1.png",
"numorph_intensity/TEST1/samples/intensity_adjustment/tile_adj_2.png",
"numorph_intensity/TEST1/samples/intensity_adjustment/topro_1_1_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/topro_1_2_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/topro_2_1_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/topro_2_2_11.tif",
"numorph_intensity/TEST1/samples/intensity_adjustment/y_adj_1.png",
"numorph_intensity/TEST1/samples/intensity_adjustment/y_adj_2.png",
"numorph_intensity/TEST1/variables",
"numorph_intensity/TEST1/variables/adj_params.mat",
"numorph_intensity/TEST1/variables/path_table.mat",
"numorph_intensity/TEST1/variables/thresholds.mat",
"numorphalign",
"numorphalign/TEST1",
"numorphalign/TEST1/samples",
Expand Down Expand Up @@ -266,27 +266,16 @@
"unzip/TEST1/ctip2_topro/16-35-34_WT7R_ctip2_topro_2-5x_0-085NA_4z_UltraII[03 x 03]_C01_xyz-Table Z0620.ome.tif"
],
[
"stitch_tforms.json:md5,b5cc9b439f94631bee62e3f8315dd9aa",
"z_disp_matrix.json:md5,575020a27eee808b03c615e0a80ca506",
"z_displacement_align.json:md5,0eb5dab0b44ab3c5ceaa8b053ec250e0",
"NM_variables.mat:md5,a4edf2d0e1ae0010fff3aa6a302ca826",
"ctip2_1_1_11.tif:md5,fccec39adaa86a092dd7fca25b480234",
"ctip2_1_2_11.tif:md5,f7eb54ccc7add77d02d5463ff7898356",
"ctip2_2_1_11.tif:md5,684a579cc8df0800a11d2ff892c3938d",
"ctip2_2_2_11.tif:md5,5f4305e1581ccd4651fd750669e3b69a",
"flatfield_1.png:md5,9bcccc81a1d7efd27d1518199150a4b2",
"flatfield_2.png:md5,34a05a01a8522063b5573a53c75c2dc3",
"tile_adj_1.png:md5,9f7c5647a83c2bfcc438da21c4d9d1b7",
"tile_adj_2.png:md5,ac7a8ae352697405e3f3db8afcf4a660",
"topro_1_1_11.tif:md5,733e3e7bc32916dfcbc73c9c77404d69",
"topro_1_2_11.tif:md5,4652de23e14b9b3546c462d18a70e542",
"topro_2_1_11.tif:md5,918562924baffc0b99976837ef4b5121",
"topro_2_2_11.tif:md5,9f6a1c2b631a11cd675e96fd6e29c1b4",
"y_adj_1.png:md5,711d09ff4defb119346d2c2ed9be88c6",
"y_adj_2.png:md5,fb4da0f00238ddd577fffc47738f7f76",
"adj_params.mat:md5,8f77bd1c4f3e882a181a6107594d9012",
"path_table.mat:md5,240e9822c4d685da5a997f9c34f6db22",
"thresholds.mat:md5,6c48f8b4d4a3b9b69af5209a53510c19",
"ctip2_1_1_11.tif:md5,d4220099450790596d1e585f5721eabd",
"ctip2_1_2_11.tif:md5,e817a5ad26397be4c43f98f9697d19b5",
"ctip2_2_1_11.tif:md5,1473780c1a0e04276f09b6624fba583c",
"ctip2_2_2_11.tif:md5,77f71fb498b60ac988e3b59ef5b8c2b2",
"topro_1_1_11.tif:md5,de62497e95d9efefdcbf00d121a56719",
"topro_1_2_11.tif:md5,59d29ed8c9a71e3be77a63badeb7040b",
"topro_2_1_11.tif:md5,b2dd3b0bdfa200461b330fd110263ed9",
"topro_2_2_11.tif:md5,7e4a4bf21d20fc685d8837651905787d",
"TEST1_ctip2_full.tif:md5,fb17be9f66140c674dad1c0eba3b7a2e",
"TEST1_topro_full.tif:md5,5e6784fc7062215bc6538ccccc49a5f4",
"16-35-34_WT7R_ctip2_topro_2-5x_0-085NA_4z_UltraII[02 x 02]_C00_xyz-Table Z0600.ome.tif:md5,5bceac0b61030e08808592c7bf3e8db0",
Expand Down Expand Up @@ -459,7 +448,7 @@
"16-35-34_WT7R_ctip2_topro_2-5x_0-085NA_4z_UltraII[03 x 03]_C01_xyz-Table Z0620.ome.tif:md5,b4f4be8e38b3b84dcd1a34a2b1968abc"
]
],
"timestamp": "2026-03-19T16:13:49.151050141",
"timestamp": "2026-03-20T15:41:54.785343688",
"meta": {
"nf-test": "0.9.4",
"nextflow": "25.10.3"
Expand All @@ -473,16 +462,16 @@
"mat2json/preprocessing",
"mat2json/preprocessing/TEST1",
"mat2json/preprocessing/TEST1/TEST1.json",
"numorph",
"numorph/results",
"numorph/results/NM_variables.mat",
"numorph/results/samples",
"numorph/results/samples/intensity_adjustment",
"numorph/results/samples/intensity_adjustment/TEST1.png",
"numorph/results/variables",
"numorph/results/variables/adj_params.mat",
"numorph/results/variables/path_table.mat",
"numorph/results/variables/thresholds.mat",
"numorph_intensity",
"numorph_intensity/TEST1",
"numorph_intensity/TEST1/NM_variables.mat",
"numorph_intensity/TEST1/samples",
"numorph_intensity/TEST1/samples/intensity_adjustment",
"numorph_intensity/TEST1/samples/intensity_adjustment/TEST1.png",
"numorph_intensity/TEST1/variables",
"numorph_intensity/TEST1/variables/adj_params.mat",
"numorph_intensity/TEST1/variables/path_table.mat",
"numorph_intensity/TEST1/variables/thresholds.mat",
"numorphalign",
"numorphalign/TEST1",
"numorphalign/TEST1/samples",
Expand All @@ -504,15 +493,10 @@
],
[
"TEST1.json:md5,d41d8cd98f00b204e9800998ecf8427e",
"NM_variables.mat:md5,d41d8cd98f00b204e9800998ecf8427e",
"TEST1.png:md5,d41d8cd98f00b204e9800998ecf8427e",
"adj_params.mat:md5,d41d8cd98f00b204e9800998ecf8427e",
"path_table.mat:md5,d41d8cd98f00b204e9800998ecf8427e",
"thresholds.mat:md5,d41d8cd98f00b204e9800998ecf8427e",
"TEST1_full.tif:md5,d41d8cd98f00b204e9800998ecf8427e"
]
],
"timestamp": "2026-03-19T16:14:17.731253075",
"timestamp": "2026-03-20T15:42:24.426800711",
"meta": {
"nf-test": "0.9.4",
"nextflow": "25.10.3"
Expand Down
4 changes: 2 additions & 2 deletions subworkflows/local/numorph_stitch/tests/main.nf.test
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ nextflow_workflow {

then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'subworkflows/local/numorph_preprocessing/tests/.nftignore')
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assert workflow.success
assertAll(
{ assert snapshot(
Expand Down Expand Up @@ -93,7 +93,7 @@ nextflow_workflow {
}
then {
def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}'])
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'subworkflows/local/numorph_preprocessing/tests/.nftignore')
def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore')
assert workflow.success
assertAll(
{ assert snapshot(
Expand Down
Loading
Loading