-
Notifications
You must be signed in to change notification settings - Fork 271
SEM image analysis: DiameterJ with Auto thresholding #1970
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
bf74e22
add tool
53ddf7f
update
33233a2
update tool
48a364f
update tool
d8e5dff
fix methods
560b5c2
update container name
99b106f
update tokens
c5027aa
update
84d4021
add auto thresholding methods
39d8d41
fix permission issue
6276f27
update tool
448b7d7
update tool
4c7488c
update
194dab3
add tests
ba5155f
update tests
2b94b2a
Merge branch 'bgruening:master' into fiji_imageJ
anuprulez 55218f1
update documentation
bcd19f7
update tool
d6dd12b
remove all selections
169d7f8
rm readme
ab92c67
add .shed.yml
b1bda21
add .shed.yml
3692fee
fix python linting
3abbe34
update tests
8ef9dfc
Update tools/sem_analysis/sem_analysis.xml
anuprulez 2e0cff7
fix comments
23ef8aa
fix comments
2e9757d
Merge branch 'master' into fiji_imageJ
anuprulez ca53a65
fix failing tests
2636e58
fix test 9
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| name: sem_analysis | ||
| owner: bgruening | ||
| description: Scanning electron micrographs (SEM) fiber analysis using FIJI, DiameterJ and Auto-thresholding. | ||
| long_description: | | ||
| The SEM Analysis tool segments fibers and measures their diameters, and pores with FIJI, DiameterJ and Auto-thresholding | ||
| remote_repository_url: https://github.com/bgruening/galaxytools/tree/master/tools/sem_analysis | ||
| homepage_url: https://github.com/bgruening/galaxytools/tree/master/tools/sem_analysis | ||
| type: | ||
| categories: | ||
| - Imaging | ||
| maintainers: | ||
| anuprulez |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #!/usr/bin/env python3 | ||
| """Convert all DiameterJ radius-plot TIFFs in a result directory to PNG.""" | ||
| import sys | ||
| from pathlib import Path | ||
|
|
||
| from PIL import Image | ||
|
|
||
|
|
||
| def main() -> None: | ||
| result_dir = Path(sys.argv[1]) | ||
| for source in result_dir.glob("*_Radius Plot.tif"): | ||
| destination = source.with_suffix(".png") | ||
| with Image.open(source) as image: | ||
| image.save(destination) | ||
| source.unlink() | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,304 @@ | ||
| <tool id="sem_analysis" name="Scanning electron micrographs (SEM) fiber analysis" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="@PROFILE@"> | ||
| <description>segment fibers and measure their diameters</description> | ||
| <macros> | ||
| <token name="@TOOL_VERSION@">1-018</token> | ||
| <token name="@VERSION_SUFFIX@">0</token> | ||
| <token name="@PROFILE@">25.0</token> | ||
| </macros> | ||
| <creator> | ||
| <person givenName="Anup" familyName="Kumar" email="kumara@informatik.uni-freiburg.de"/> | ||
| <organization name="European Galaxy Team" url="https://galaxyproject.org/eu/"/> | ||
| </creator> | ||
| <requirements> | ||
| <container type="docker">quay.io/galaxy/sem-analysis-fiji-diameterj:@TOOL_VERSION@</container> | ||
| </requirements> | ||
| <required_files> | ||
| <include path="convert_radius_plots.py"/> | ||
| </required_files> | ||
| <command detect_errors="exit_code"><![CDATA[ | ||
| mkdir -p results && | ||
| export ANALYSIS_RESULTS_DIR='results' && | ||
| ln -s '$input_image' input.tif && | ||
| srm_args='' | ||
| #if $segmentation.workflow in ('recursive-srm', 'srm-auto-thresholding'): | ||
| srm_args='--srm-q $segmentation.srm_q' | ||
| #end if | ||
| #if $calibration.source == 'pixel_size': | ||
| calibration_args='--pixel-size-um $calibration.pixel_size_um' | ||
| #else: | ||
| calibration_args='--hfw-um $calibration.hfw_um' | ||
| #end if | ||
| mode_args='' | ||
| #if $analysis_mode == 'qc': | ||
| mode_args='--skip-diameterj' | ||
| #end if | ||
| #if $analysis_mode == 'diameterj': | ||
| /usr/local/bin/sem-analysis --input input.tif --output results --segmentation '$segmentation.workflow' --threshold-methods '#echo ",".join($threshold_methods)#' \$srm_args \$calibration_args \$mode_args --crop-bottom '$advanced.crop_bottom' && | ||
| python3 '$__tool_directory__/convert_radius_plots.py' results | ||
|
bgruening marked this conversation as resolved.
|
||
| #else: | ||
| /usr/local/bin/sem-analysis --input input.tif --output results --segmentation '$segmentation.workflow' --threshold-methods '#echo ",".join($threshold_methods)#' \$srm_args \$calibration_args \$mode_args --crop-bottom '$advanced.crop_bottom' | ||
| #end if | ||
| ]]></command> | ||
| <inputs> | ||
| <param name="input_image" type="data" format="tiff" label="Scanning electron micrographs" help="A 2-D TIFF image. RGB TIFFs are converted to grayscale."/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" type="select" label="Segmentation workflow"> | ||
| <option value="auto-thresholding" selected="true">Auto Thresholding (Traditional)</option> | ||
| <option value="recursive-srm">Recursive SRM with Auto Thresholding (SRM)</option> | ||
| <option value="srm-auto-thresholding">SRM with Auto Thresholding (Mixed)</option> | ||
| </param> | ||
| <when value="auto-thresholding"/> | ||
| <when value="recursive-srm"> | ||
| <param name="srm_q" type="integer" value="100" min="1" label="Starting SRM granularity (q)"/> | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use argument here and elsewhere?
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping |
||
| </when> | ||
| <when value="srm-auto-thresholding"> | ||
| <param name="srm_q" type="integer" value="100" min="1" label="SRM granularity (q)"/> | ||
| </when> | ||
| </conditional> | ||
| <param name="threshold_methods" type="select" multiple="true" optional="false" label="Thresholding methods" help="Select one or more Fiji Auto Threshold methods. Each selected method produces a separate segmentation candidate."> | ||
| <option value="default" selected="true">Default</option> | ||
| <option value="huang">Huang</option> | ||
| <option value="huang2">Huang2</option> | ||
| <option value="intermodes">Intermodes</option> | ||
| <option value="isodata">IsoData</option> | ||
| <option value="li">Li</option> | ||
| <option value="maxentropy">MaxEntropy</option> | ||
| <option value="mean">Mean</option> | ||
| <option value="minerror">MinError(I)</option> | ||
| <option value="minimum">Minimum</option> | ||
| <option value="moments">Moments</option> | ||
| <option value="otsu">Otsu</option> | ||
| <option value="percentile">Percentile</option> | ||
| <option value="renyientropy">RenyiEntropy</option> | ||
| <option value="shanbhag">Shanbhag</option> | ||
| <option value="triangle">Triangle</option> | ||
| <option value="yen">Yen</option> | ||
| </param> | ||
| <param name="analysis_mode" type="select" label="Analysis mode"> | ||
| <option value="diameterj" selected="true">Full DiameterJ analysis</option> | ||
| <option value="qc">Segmentation and QC only</option> | ||
| </param> | ||
| <conditional name="calibration"> | ||
| <param name="source" type="select" label="Pixel calibration"> | ||
| <option value="hfw" selected="true">Derive from horizontal field width</option> | ||
| <option value="pixel_size">Specify pixel size directly</option> | ||
| </param> | ||
| <when value="hfw"> | ||
| <param name="hfw_um" type="float" value="27.04" min="0.01" max="1000" label="Horizontal field width (µm)" help="Physical width of the full image, as recorded by the SEM. The default 27.04 µm corresponds to 0.02640625 µm/pixel for a 1024-pixel-wide image; replace it with the value from your image metadata. Increasing or decreasing HFW scales all derived physical sizes by the same proportion, but does not change pixel-based segmentation."/> | ||
| </when> | ||
| <when value="pixel_size"> | ||
| <param name="pixel_size_um" type="float" value="0.02640625" min="0.000001" max="1000" label="Pixel size (µm/pixel)" help="Physical size represented by one image pixel, as recorded by the SEM or calculated from a known scale. The default 0.02640625 µm/pixel corresponds to a 27.04 µm horizontal field width for a 1024-pixel-wide image; replace it with the value from your image metadata. Increasing or decreasing pixel size scales all derived physical sizes by the same proportion, but does not change pixel-based segmentation."/> | ||
| </when> | ||
| </conditional> | ||
| <section name="advanced" title="Segmentation options" expanded="false"> | ||
| <param name="crop_bottom" type="integer" value="59" min="0" label="Crop from bottom (pixels)" help="Removes the SEM instrument footer before analysis."/> | ||
| </section> | ||
| </inputs> | ||
| <outputs> | ||
| <collection name="results_collection" type="list" label="${tool.name}: results for ${on_string}"> | ||
| <discover_datasets pattern="__name_and_ext__" directory="results"/> | ||
| </collection> | ||
| </outputs> | ||
| <tests> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="auto-thresholding"/> | ||
| </conditional> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <param name="threshold_methods" value="default,otsu"/> | ||
| <output_collection name="results_collection" type="list" count="21"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="auto-thresholding"/> | ||
| </conditional> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="12"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="srm-auto-thresholding"/> | ||
| <param name="srm_q" value="80"/> | ||
| </conditional> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="12"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="recursive-srm"/> | ||
| <param name="srm_q" value="100"/> | ||
| </conditional> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="12"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="auto-thresholding"/> | ||
| </conditional> | ||
| <param name="threshold_methods" value="huang"/> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="12"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="auto-thresholding"/> | ||
| </conditional> | ||
| <param name="threshold_methods" value="huang2,intermodes,isodata"/> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <conditional name="calibration"> | ||
| <param name="source" value="pixel_size"/> | ||
| <param name="pixel_size_um" value="0.03"/> | ||
| </conditional> | ||
| <output_collection name="results_collection" type="list" count="30"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="srm-auto-thresholding"/> | ||
| <param name="srm_q" value="60"/> | ||
| </conditional> | ||
| <param name="threshold_methods" value="li"/> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="12"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="srm-auto-thresholding"/> | ||
| <param name="srm_q" value="120"/> | ||
| </conditional> | ||
| <param name="threshold_methods" value="maxentropy,mean,minerror"/> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="30"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="recursive-srm"/> | ||
| <param name="srm_q" value="64"/> | ||
| </conditional> | ||
| <param name="threshold_methods" value="minerror"/> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <output_collection name="results_collection" type="list" count="12"/> | ||
| </test> | ||
| <test expect_num_outputs="1"> | ||
| <param name="input_image" value="PVA-A_004.tif"/> | ||
| <conditional name="segmentation"> | ||
| <param name="workflow" value="recursive-srm"/> | ||
| <param name="srm_q" value="80"/> | ||
| </conditional> | ||
| <param name="threshold_methods" value="moments,percentile,renyientropy,shanbhag,triangle,yen"/> | ||
| <param name="analysis_mode" value="qc"/> | ||
| <conditional name="calibration"> | ||
| <param name="source" value="hfw"/> | ||
| <param name="hfw_um" value="30"/> | ||
| </conditional> | ||
| <output_collection name="results_collection" type="list" count="57"/> | ||
| </test> | ||
| </tests> | ||
| <help>< | ||
| methods directly to the cropped image. The available methods are Default, | ||
| Huang, Huang2, Intermodes, | ||
| IsoData, Li, MaxEntropy, Mean, MinError(I), Minimum, Moments, Otsu, | ||
| Percentile, RenyiEntropy, Shanbhag, Triangle, and Yen. | ||
| * **SRM with Auto Thresholding** applies one [Statistical Region Merging](https://imagej.net/plugins/statistical-region-merging) pass at | ||
| the selected ``q``, converts the result to 8-bit, and applies the selected | ||
| Auto Threshold methods. | ||
| * **Recursive SRM** runs exactly one recursive workflow. It successively applies | ||
| SRM at ``q``, ``q/2``, ``q/4``, and ``q/8`` (with a minimum of 1), then | ||
| applies the selected threshold methods to the final SRM image. | ||
|
|
||
| Use **Thresholding methods** to choose one or more of these methods. The same | ||
| selection is applied after SRM for either SRM-based workflow. All 17 methods are | ||
| selected by default. | ||
|
|
||
| **Analysis mode** | ||
|
|
||
| * **Full DiameterJ analysis** creates the selected segmentation masks and QC | ||
| results, then runs DiameterJ 1.018 on every mask. Candidates are not rejected | ||
| based on their black-pixel fraction, so review the segmentation and overlay | ||
| montages when a threshold method produces an implausible mask. | ||
| * **Segmentation and QC only** skips DiameterJ analysis. It is faster and | ||
| is useful for comparing candidate masks before a full run. | ||
|
|
||
| **Calibration and interpretation** | ||
|
|
||
| QC measurements are reported in pixels and micrometres. Choose one of the | ||
| following calibration sources: | ||
|
|
||
| * **Horizontal field width** is the physical width represented by the entire | ||
| uncropped image. Pixel size is calculated as ``HFW / image width in pixels``. | ||
| The default is 27.04 µm and should be replaced with the value recorded by the | ||
| microscope for the input image. | ||
| * **Pixel size** directly specifies micrometres per pixel. Use this when the | ||
| calibrated pixel spacing is already known. | ||
|
|
||
| Cropping the bottom does not change image width, so it does not alter an | ||
| HFW-derived pixel size. DiameterJ runs in its validated native-pixel mode because | ||
| physical calibration can change its legacy particle-size filtering. Use the | ||
| ``pixel_size_um`` field in ``qc_summary.csv`` when converting DiameterJ | ||
| measurements to physical units. | ||
|
|
||
| **Segmentation options** | ||
|
|
||
| * **Crop from bottom** removes a fixed number of pixel rows before analysis. The | ||
| default of 59 is intended for an SEM annotation or instrument footer. Set it | ||
| to 0 when the image contains no footer. It must be smaller than image height. | ||
| * **SRM granularity (q)** controls region merging in SRM with Auto Thresholding | ||
| and Recursive SRM modes. It must be positive. Larger values generally | ||
| preserve more, smaller regions; lower values generally merge regions more | ||
| aggressively. The default is 100. | ||
|
|
||
| **Outputs** | ||
|
|
||
| All generated files are returned as one list collection in the Galaxy history. | ||
| Each workflow produces two PNG review sheets: a segmentation montage containing | ||
| the cropped original and every binary mask, and an overlay montage containing | ||
| the original and every boundary overlay. It also produces each candidate as a | ||
| separate, display-ready PNG and as a matching TIFF used for DiameterJ analysis. | ||
| Each workflow produces one segmented PNG and one matching TIFF per selected | ||
| threshold method. | ||
|
|
||
| Dataset names retain the input stem, segmentation family, SRM settings where | ||
| applicable, and threshold method. For each mask, QC-only mode also includes a | ||
| boundary-overlay PNG and diameter-samples CSV; the collection contains one | ||
| QC summary CSV. Full mode adds the DiameterJ total summary, comparison | ||
| image, pore data, radius histogram, characteristic lengths, and radius plot for | ||
| each mask. Every DiameterJ radius-plot TIFF is converted to PNG before Galaxy | ||
| discovers the collection. The resulting collection size depends on the number of | ||
| selected threshold methods and the analysis mode. | ||
|
|
||
| The QC diameter samples are distance-transform measurements on skeleton pixels. | ||
| They are intended as an independent quality check; DiameterJ output is the | ||
| primary result in full-analysis mode. | ||
| ]]></help> | ||
| <citations> | ||
| <citation type="doi">10.1016/j.biomaterials.2015.05.015</citation> | ||
| </citations> | ||
| </tool> | ||
Binary file not shown.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this actually needed? Is TIFF not useful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. But not sure what our collaborators will require. We share them the tool and fix other feedbacks along with this.