Skip to content
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

Batch processing #713

Merged
merged 5 commits into from
Jul 30, 2024
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
66 changes: 38 additions & 28 deletions _includes/batch_processing/batch_measure_nuclei_shape.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# %%
# Batch analysis of 2D nuclei shape measurements


# %%
# Import python modules
from OpenIJTIFF import open_ij_tiff, save_ij_tiff
Expand All @@ -9,17 +10,21 @@
import pandas as pd
import pathlib
from pathlib import Path
from napari import Viewer


# %%
# Create a function that analyses one image
# Below, this function will be called several times, for all images
def analyse(image_path, output_folder):
def analyse(image_filepath, output_folder):

# This prints which image is currently analysed
print("Analyzing:", image_path)
print("Analyzing:", image_filepath)

# Convert the image_filepath String to a Path,
# which is more convenient to create the output files
image_filepath = pathlib.Path(image_filepath)

image, axes, scales, units = open_ij_tiff(image_path)
image, axes, scales, units = open_ij_tiff(image_filepath)

# Binarize the image using auto-thresholding
threshold = threshold_otsu(image)
Expand All @@ -31,10 +36,14 @@ def analyse(image_path, output_folder):
# We can safely convert to 16 bit as we know that we don't have too many objects
label_image = label(binary_image).astype('uint16')

# Save the labels
label_image_filepath = output_folder / f"{image_filepath.stem}_labels.tif"
save_ij_tiff(label_image_filepath, label_image, axes, scales, units)

# Measure calibrated (scaled) nuclei shapes
df = pd.DataFrame(regionprops_table(
label_image,
properties={'label', 'area'},
properties={'label', 'area', 'centroid'},
spacing=scales))

# Round all measurements to 2 decimal places.
Expand All @@ -43,41 +52,42 @@ def analyse(image_path, output_folder):
# you may not want to round that much!
df = df.round(2)

# Save the results to disk

# Convert the image_path String to a Path,
# which is more convenient to create the output files
image_path = pathlib.Path(image_path)
# Add the image and label filepaths to the data-frame
df['image'] = image_filepath
df['labels'] = label_image_filepath

# Save the labels
label_image_path = output_folder / f"{image_path.stem}_labels.tif"
save_ij_tiff(label_image_path, label_image, axes, scales, units)

# Save the measurements table
# to a tab delimited text file (sep='\t')
# without row numbers (index=False)
table_path = output_folder / f"{image_path.stem}_measurements.csv"
df.to_csv(table_path, sep='\t', index=False)
# Return the data-frame
return df


# %%
# Assign an output folder
# Note: This uses your current working directory; you may want to change this to another folder on your computer
output_dir = Path.cwd()


# %%
# Create a list of the paths to all data
image_paths = ["https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__mitocheck_incenp_t1.tif",
"https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__mitocheck_incenp_t70.tif"]
image_paths = [output_dir / "xy_8bit__mitocheck_incenp_t1.tif",
output_dir / "xy_8bit__mitocheck_incenp_t70.tif"]
# Create an empty list for the measurement results
result_dfs = []


# %%
# The loop which performs the analysis
for image_path in image_paths:
analyse(image_path, output_dir)

# Computes the analysis and returns a data-frame with the resulting measurements
result_df = analyse(image_path, output_dir)

# Append the label image path to the list initialized before the loop
result_dfs.append(result_df)


# %%
# Plot the first output image to check if the pipeline worked
image1, *_ = open_ij_tiff(image_paths[0])
labels1, *_ = open_ij_tiff('xy_8bit__mitocheck_incenp_t1_labels.tif')
# Concatenate the result data-frames to a single one which contains all results
final_df = pd.concat(result_dfs, ignore_index=True)
# Save the final results to disk
final_df.to_csv(output_dir / 'batch_processing_results.csv', sep='\t', index=False)

viewer = Viewer()
viewer.add_image(image1)
viewer.add_labels(labels1)
18 changes: 11 additions & 7 deletions _includes/batch_processing/batch_measure_nuclei_shapes.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<h4 id="batchshape"><a href="#batchshape">Batch analysis of nuclear shapes</a></h4>

- Download the input.zip containing the input images from [here](https://github.com/NEUBIAS/training-resources/tree/master/image_data/batch_process) and unpack to your course directory
- In a previous module [there is a workflow to measure the shapes of nuclei in one image](https://neubias.github.io/training-resources/workflow_segment_2d_nuclei_measure_shape/index.html#2dnuclei)
- Adapt this workflow for automated batch analysis of many images
- Start by building the skeleton of the workflow without filling in the functionality;

Note that the code below runs fine, but does not produce any results:
Note that the pseudo-code below will run fine, but does not produce any results:

```
def analyse(image_path, output_folder):
print("Analyzing:", image_path)

for image_path in image_paths:
analyse(image_path, output_dir)
FUNCTION analyse(image_path, output_folder)
PRINT "Analyzing:", image_path
END FUNCTION

FOR each image_path in image_paths
CALL analyse(image_path, output_dir)
END FOR
```

- Make sure the loop with the (almost) empty analyse function runs without error before filling in the image analysis steps
- Make sure the loop with the (almost) empty analyse function runs without error before filling in the image analysis steps
- Inspect the analysis results in a suitable software
2 changes: 2 additions & 0 deletions _modules/batch_processing.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ learn_next:

external_links:
- "[Batch processing in ImageJ](https://imagej.net/scripting/batch)"
- [MoBIE](https://github.com/mobie/mobie-viewer-fiji)
- [ImageDataExplorer](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0273698)
---
Loading