Commit da1b7457 authored by rhaase's avatar rhaase

added exercise solution

parent eccf5da8
/*
# Drosophila embryo morphometry
Authors: Robert Haase, Daniela Vorkel, April 2020
[Source](https://github.com/clij/clij2-docs/tree/master/src/main/macro/tribolium_morphometry.ijm)
This script is an example of heavy GPU-accelerated processing. It is recommended to use a dedicated
graphics card with at least 8 GB of GDDR6 memory. Otherwise, it may be quite slow.
Let's initialize that graphics card and mesure the start time.
*/
run("CLIJ2 Macro Extensions", "cl_device=[GeForce RTX 2060 SUPER]");
Ext.CLIJ2_clear();
run("Close All");
time = getTime();
Ext.CLIJ2_startTimeTracing();
/*
## Load a data set
All processing steps are performed in 3D space. For visualization purpose, we are using the maximum intensity projection in Z:
*/
path = "C:/structure/teaching/lecture_applied_bioimage_analysis_2020/12_Volumetric_image_data/data/";
open(path + "000200.raw.tif");
input = getTitle();
print("Loading took " + (getTime() - time) + " msec");
Ext.CLIJ2_push(input);
run("Close All");
// visualize the dataset
show(input, "input");
/*
## Spot detection
After some noise removal/smoothing, we perform a local maximum detection:
*/
// difference of Gaussian
sigma1 = 2;
sigma2 = 10;
Ext.CLIJ2_differenceOfGaussian3D(input, blurred, sigma1, sigma1, sigma1, sigma2, sigma2, sigma2);
// detect maxima
radius = 2.0;
Ext.CLIJ2_detectMaximaBox(blurred, detected_maxima, radius);
show_spots(detected_maxima, "detected maxima");
/*
## Spot curation
Now, we remove spots with values below a certain intensity and label the remaining spots.
*/
// threshold
threshold = 10.0;
Ext.CLIJ2_threshold(blurred, thresholded, threshold);
// mask
Ext.CLIJ2_mask(detected_maxima, thresholded, masked_spots);
// label spots
Ext.CLIJ2_labelSpots(masked_spots, labelled_spots);
show_spots(labelled_spots, "selected, labelled spots");
run("glasbey_on_dark");
/*
Let's see how many spots are left:
*/
Ext.CLIJ2_getMaximumOfAllPixels(labelled_spots, number_of_spots);
print("Number of detected spots: " + number_of_spots);
/*
## Expanding labelled spots
Next, we spatially extend the labelled spots by applying a maximum filter.
*/
// label map closing
number_of_dilations = 10;
number_of_erosions = 4;
Ext.CLIJ2_copy(labelled_spots, flip);
for (i = 0; i < number_of_dilations; i++) {
Ext.CLIJ2_onlyzeroOverwriteMaximumBox(flip, flop);
Ext.CLIJ2_onlyzeroOverwriteMaximumDiamond(flop, flip);
if (i % 2 == 0) {
show(flip, "Extended spots after " + (i * 2) + " dilations");
run("glasbey_on_dark");
}
}
/*
Afterwards, we erode all labels in the map and get a final result of cell segementation.
*/
Ext.CLIJ2_threshold(flip, flap, 1);
for (i = 0; i < number_of_erosions; i++) {
Ext.CLIJ2_erodeBox(flap, flop);
Ext.CLIJ2_erodeBox(flop, flap);
}
Ext.CLIJ2_mask(flip, flap, labels);
show(labels, "cell segmentation");
run("glasbey_on_dark");
/*
We also save all labels to disc to use them as starting point in other notebooks, later.
*/
Ext.CLIJ2_pull(labels);
saveAs("TIF", path + "lund1051_labelled.tif");
close();
/*
## Draw connectivity of the cells as a mesh
We then read out all current positions of detected nuclei as a pointlist to generate
a distance matrix of all nuclei towards each other:
*/
Ext.CLIJ2_labelledSpotsToPointList(labelled_spots, pointlist);
Ext.CLIJ2_generateDistanceMatrix(pointlist, pointlist, distance_matrix);
show(distance_matrix, "distance matrix");
/*
Starting from the label map of segmented cells, we generate a touch matrix:
*/
Ext.CLIJ2_generateTouchMatrix(labels, touch_matrix);
// touch matrix:
// set the first column to zero to ignore all spots touching the background (background label 0, first column)
Ext.CLIJ2_setColumn(touch_matrix, 0, 0);
show_spots(touch_matrix, "touch matrix");
/*
Using element by element multiplication of a distance matrix and a touch matrix, we calculate the length of
each edge. We use this result to draw a mesh with a color gradient of distance (between 0 and 50 micron):
*/
Ext.CLIJ2_multiplyImages(touch_matrix, distance_matrix, touch_matrix_with_distances);
Ext.CLIJ2_getDimensions(input, width, height, depth);
Ext.CLIJ2_create3D(mesh, width, height, depth, 32);
Ext.CLIJ2_touchMatrixToMesh(pointlist, touch_matrix_with_distances, mesh);
show(mesh, "distance mesh");
run("Green Fire Blue");
setMinAndMax(0, 50);
/*
## Quantitative analysis of distance between neighbors
Next, we determine the averge distance between a node and of all its neighbors. The resulting
vector has as many entries as nodes in the graph. We use this vector to color-code the
label map of segmented cells. This means, label 1 gets replaced by the average distance to
node 1, label 2 by the average distance to node 2, et cetera.
*/
Ext.CLIJ2_averageDistanceOfTouchingNeighbors(distance_matrix, touch_matrix, distances_vector);
Ext.CLIJ2_replaceIntensities(labels, distances_vector, distance_map);
show(distance_map, "distance map");
run("Fire");
setMinAndMax(0, 50);
/*
Now, we measure the mean between neighbors and visualize it as above.
*/
Ext.CLIJ2_meanOfTouchingNeighbors(distances_vector, touch_matrix, local_mean_distances_vector);
Ext.CLIJ2_replaceIntensities(labels, local_mean_distances_vector, local_mean_pixel_count_map);
show(local_mean_pixel_count_map, "neighbor mean distance map");
run("Fire");
setMinAndMax(0, 50);
/*
We can also use the minimum, median and maximum to measure distances:
*/
Ext.CLIJ2_minimumOfTouchingNeighbors(distances_vector, touch_matrix, local_minimum_distances_vector);
Ext.CLIJ2_replaceIntensities(labels, local_minimum_distances_vector, local_minimum_pixel_count_map);
show(local_minimum_pixel_count_map, "neighbor minimum distance map");
run("Fire");
setMinAndMax(0, 50);
Ext.CLIJ2_medianOfTouchingNeighbors(distances_vector, touch_matrix, local_median_distances_vector);
Ext.CLIJ2_replaceIntensities(labels, local_median_distances_vector, local_median_pixel_count_map);
show(local_median_pixel_count_map, "neighbor median distance map");
run("Fire");
setMinAndMax(0, 50);
Ext.CLIJ2_maximumOfTouchingNeighbors(distances_vector, touch_matrix, local_maximum_distances_vector);
Ext.CLIJ2_replaceIntensities(labels, local_maximum_distances_vector, local_maximum_pixel_count_map);
show(local_maximum_pixel_count_map, "neighbor maximum distance map");
run("Fire");
setMinAndMax(0, 50);
Ext.CLIJ2_standardDeviationOfTouchingNeighbors(distances_vector, touch_matrix, local_stddev_distances_vector);
Ext.CLIJ2_replaceIntensities(labels, local_stddev_distances_vector, local_stddev_pixel_count_map);
show(local_stddev_pixel_count_map, "neighbor standard deviation distance map");
run("Fire");
setMinAndMax(0, 50);
/*
## Performance evaluation
Finally, a time measurement. Note that performing this workflow in ImageJ macro markdown is slower,
because intermediate results are saved to disc.
*/
print("The whole workflow took " + (getTime() - time) + " msec");
/*
### Detailed time tracing for all operations
*/
Ext.CLIJ2_stopTimeTracing();
Ext.CLIJ2_getTimeTracing(time_traces);
print(time_traces);
/*
Also, let's see how much of GPU memory got used by this workflow. At the end, cleaning up remains important.
*/
Ext.CLIJ2_reportMemory();
// finally, clean up
Ext.CLIJ2_clear();
/*
Following methods are convenient for a proper visualization in a notebook:
*/
function show(input, text) {
Ext.CLIJ2_maximumZProjection(input, max_projection);
Ext.CLIJ2_pull(max_projection);
setColor(100000);
drawString(text, 20, 20);
Ext.CLIJ2_release(max_projection);
}
function show_spots(input, text) {
Ext.CLIJ2_maximum3DBox(input, extended, 1, 1, 0);
Ext.CLIJ2_maximumZProjection(extended, max_projection);
Ext.CLIJ2_pull(max_projection);
setColor(100000);
drawString(text, 20, 20);
Ext.CLIJ2_release(extended);
Ext.CLIJ2_release(max_projection);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment