Skip to content

Commit

Permalink
Merge pull request #713 from NEUBIAS/batch_processing
Browse files Browse the repository at this point in the history
Batch processing
  • Loading branch information
tischi authored Jul 30, 2024
2 parents 2ccbd8a + fc14243 commit a751677
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 35 deletions.
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)
---

0 comments on commit a751677

Please sign in to comment.