-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
111 changed files
with
3,380 additions
and
1,243 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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 |
---|---|---|
|
@@ -10,6 +10,7 @@ _site* | |
.idea | ||
Thumbs.db | ||
~$* | ||
*.ipynb | ||
.ipynb_checkpoints | ||
**/__pycache__/ | ||
Untitl* |
This file contains 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
This file contains 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,93 @@ | ||
# %% | ||
# Batch analysis of 2D nuclei shape measurements | ||
|
||
|
||
# %% | ||
# Import python modules | ||
from OpenIJTIFF import open_ij_tiff, save_ij_tiff | ||
from skimage.measure import label, regionprops_table | ||
from skimage.filters import threshold_otsu | ||
import pandas as pd | ||
import pathlib | ||
from pathlib import Path | ||
|
||
|
||
# %% | ||
# Create a function that analyses one image | ||
# Below, this function will be called several times, for all images | ||
def analyse(image_filepath, output_folder): | ||
|
||
# This prints which image is currently analysed | ||
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_filepath) | ||
|
||
# Binarize the image using auto-thresholding | ||
threshold = threshold_otsu(image) | ||
print("Threshold:", threshold) | ||
binary_image = image > threshold | ||
|
||
# Perform connected components analysis (i.e create labels) | ||
# Note that label returns 32 bit data which save_ij_tif below can't handle. | ||
# 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', 'centroid'}, | ||
spacing=scales)) | ||
|
||
# Round all measurements to 2 decimal places. | ||
# This increases the readability a lot, | ||
# but depending on your scientific question, | ||
# you may not want to round that much! | ||
df = df.round(2) | ||
|
||
# Add the image and label filepaths to the data-frame | ||
df['image'] = image_filepath | ||
df['labels'] = label_image_filepath | ||
|
||
# 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 = [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: | ||
|
||
# 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) | ||
|
||
|
||
# %% | ||
# 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) | ||
|
File renamed without changes.
This file contains 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,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 pseudo-code below will run fine, but does not produce any results: | ||
|
||
``` | ||
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 | ||
- Inspect the analysis results in a suitable software |
File renamed without changes.
File renamed without changes.
File renamed without changes.
49 changes: 23 additions & 26 deletions
49
_includes/binarization/binarization_act1_skimage_napari.py
This file contains 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 |
---|---|---|
@@ -1,48 +1,45 @@ | ||
# %% [markdown] | ||
# ## Thresholding bright and dim cell | ||
# %% | ||
# Thresholding bright and dim cells | ||
|
||
# %% | ||
# Instantiate the napari viewer | ||
# Instantiate napari | ||
import napari | ||
from OpenIJTIFF import open_ij_tiff | ||
viewer = napari.Viewer() | ||
|
||
# %% | ||
# Read the intensity image | ||
image, axes, scales, units = open_ij_tiff('https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__two_cells.tif') | ||
# Load the image | ||
from OpenIJTIFF import open_ij_tiff | ||
image, *_ = open_ij_tiff('https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__two_cells.tif') | ||
|
||
# %% | ||
# View the intensity image | ||
viewer.add_image(image) | ||
|
||
# Check the intensity image's datatype | ||
# Check the datatype and view the image | ||
print(image.dtype) | ||
|
||
# %% [markdown] | ||
# **Napari GUI** Inspect the intensity image values in order to identify a threshold that segments both cells \ | ||
# **Napari GUI** hover with mouse \ | ||
# **Napari GUI** make a line profile using the Napari plugin `napari-plot-profile` (`pip install napari-plot-profile`) | ||
viewer.add_image(image) | ||
|
||
# %% | ||
# Threshold the image | ||
binary_image_two_cells = image > 49 | ||
# Napari: Inspect the pixel values to identify a threshold that segments both cells | ||
|
||
# %% | ||
# Overlay the binary image | ||
viewer.add_image(binary_image_two_cells, opacity=0.8) | ||
|
||
# Inspect data type | ||
print(binary_image_two_cells.dtype) | ||
# Inspect the image histogram to confirm the above threshold | ||
import matplotlib.pyplot as plt | ||
import numpy as np | ||
plt.hist(image.flatten(), bins=np.arange(image.min(), image.max() + 1)); | ||
plt.yscale('log') # the background peak is so dominat that without the log scale it is hard to see the threshold | ||
|
||
# %% | ||
# Inspect value content | ||
# Threshold the image and inspect the resulting values and data type | ||
binary_image_two_cells = image > 49 | ||
import numpy as np | ||
print(np.unique(binary_image_two_cells)) | ||
print(binary_image_two_cells.dtype) | ||
|
||
# %% | ||
# Overlay the binary image | ||
viewer.add_labels(binary_image_two_cells, opacity=0.8) | ||
|
||
# %% | ||
# Apply a higher threshold | ||
# to only select the brighter cell | ||
# and also add this to the viewer | ||
binary_image_one_cell = image > 100 | ||
viewer.add_image(binary_image_one_cell, opacity=0.8) | ||
|
||
# %% | ||
viewer.add_labels(binary_image_one_cell, opacity=0.8) |
This file contains 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 |
---|---|---|
@@ -1,6 +1,7 @@ | ||
<h4 id="spots"><a href="#spots">Spots and threshold interval</a></h4> | ||
<h4 id="spots"><a href="#spots">Apply various thresholds to one image</a></h4> | ||
|
||
- Open image [xy_8bit__PCNA.tif](https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__PCNA.tif) | ||
- Find a threshold value so that there are 2 foreground nuclei | ||
- Find a threshold value so that only the bright dots remain | ||
- Find a threshold interval so that only the boundaries of the nuclei remain | ||
- Open [xy_8bit__PCNA.tif](https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__PCNA.tif) | ||
- Apply a threshold value such that there are two foreground nuclei | ||
- Apply a higher threshold such that is only one foreground nucleus | ||
- Apply an even higher threshold such that only the intra-nuclear speckles are foreground | ||
- Optionally, also find a threshold interval so that only the boundaries of the nuclei remain |
60 changes: 31 additions & 29 deletions
60
_includes/binarization/binarization_act2_skimage_napari.py
This file contains 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 |
---|---|---|
@@ -1,54 +1,56 @@ | ||
# %% [markdown] | ||
# ## Spots and threshold interval | ||
# %% | ||
# Nuclei, spots and nuclei boundary segmentation | ||
|
||
# %% | ||
# Instantiate the napari viewer | ||
# Import libraries and instantiate the viewer | ||
import napari | ||
import numpy as np | ||
import matplotlib.pyplot as plt | ||
viewer = napari.Viewer() | ||
|
||
# %% | ||
# Read the intensity image | ||
from OpenIJTIFF import open_ij_tiff | ||
image, axes, scales, units = open_ij_tiff('https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__PCNA.tif') | ||
|
||
# View the intensity image | ||
viewer.add_image(image) | ||
image, *_ = open_ij_tiff('https://github.com/NEUBIAS/training-resources/raw/master/image_data/xy_8bit__PCNA.tif') | ||
|
||
# %% | ||
# Check the intensity image's datatype | ||
# Check the image's data type and | ||
# view the image | ||
print(image.dtype) | ||
viewer.add_image(image) | ||
|
||
# %% [markdown] | ||
# **Napari GUI** Inspect the intensity image values in order to identify a threshold \ | ||
# **Napari GUI** hover with mouse \ | ||
# **Napari GUI** make a line profile using the Napari plugin `napari-plot-profile` (`pip install napari-plot-profile`) | ||
# %% | ||
# Napari: Inspect the pixel values in order to identify a threshold | ||
|
||
# %% | ||
# Threshold the image | ||
binary_image_two_nuclei = image > 5 | ||
|
||
# Overlay the binary image | ||
viewer.add_image(binary_image_two_nuclei, opacity=0.8) | ||
# Also check the image histogram for a threshold | ||
# Observe that interestingly there are several local minima in the histogram | ||
plt.hist(image.flatten(), bins=np.arange(image.min(), image.max() + 1)); | ||
plt.yscale('log') | ||
|
||
# %% | ||
# Inspect data type | ||
# Threshold both nuclei | ||
# check the resulting datatype and content | ||
# and view the binary image | ||
binary_image_two_nuclei = image > 5 | ||
print(binary_image_two_nuclei.dtype) | ||
|
||
# %% | ||
# Inspect value content | ||
import numpy as np | ||
print(np.unique(binary_image_two_nuclei)) | ||
viewer.add_image(binary_image_two_nuclei, opacity=0.8) | ||
|
||
# %% | ||
# Apply a higher threshold | ||
# to only select the brighter dots | ||
binary_image_bright_dots = image > 44 | ||
viewer.add_image(binary_image_bright_dots, opacity=0.8) | ||
# to only segment the brighter nucleus | ||
binary_image_one_nucleus = image > 15 | ||
viewer.add_image(binary_image_one_nucleus, opacity=0.8) | ||
|
||
# %% | ||
# Apply two thresholds | ||
# to only select the boundary of cells | ||
binary_image_boundary = (image < 5) * (image >= 4) | ||
viewer.add_image(binary_image_boundary, opacity=0.8) | ||
# Apply an even higher threshold | ||
# to only select the intranuclear speckles | ||
binary_image_speckles = image > 44 | ||
viewer.add_image(binary_image_speckles, opacity=0.8) | ||
|
||
# %% | ||
# Apply two thresholds (aka "gating") | ||
# to only select the boundary of cells | ||
binary_image_boundary = (image < 5) & (image >= 4) | ||
viewer.add_image(binary_image_boundary, opacity=0.8) |
This file contains 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
Oops, something went wrong.