Skip to content

Commit 22a469f

Browse files
author
haesleinhuepf
committed
moved compare_workflows, added syntax highlight
1 parent 344a4d7 commit 22a469f

10 files changed

+371
-0
lines changed

compare_workflows.md

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
2+
3+
# Comparing Workflows: ImageJ versus CLIJ
4+
Robert Haase, March 2020
5+
6+
This page shows how to compare ImageJ based workflow with their
7+
translations using CLIJ.
8+
9+
Let's start with ImageJ. We have a workflow loading an image,
10+
processing with background subtracting and thresholding. Note
11+
the two lines using the `getTime()`.
12+
13+
```java
14+
15+
// Get test data
16+
open("https://github.com/clij/clij2-docs/raw/master/src/main/resources/Lund_MAX_001300.tif");
17+
rename("input_imagej");
18+
19+
start_time_imagej = getTime();
20+
21+
// subtract background in the image
22+
run("Duplicate...", "title=background_subtracted_imagej");
23+
run("Subtract Background...", "rolling=25");
24+
25+
// theshold the image
26+
run("Duplicate...", "title=thresholded_imagej");
27+
setAutoThreshold("Default dark");
28+
setOption("BlackBackground", true);
29+
run("Convert to Mask");
30+
31+
end_time_imagej = getTime();
32+
```
33+
<a href="images/compare_workflows/image_1585300495290.png"><img src="images/compare_workflows/image_1585300495290.png" width="250" alt="input_imagej"/></a>
34+
<a href="images/compare_workflows/image_1585300495701.png"><img src="images/compare_workflows/image_1585300495701.png" width="250" alt="background_subtracted_imagej"/></a>
35+
<a href="images/compare_workflows/image_1585300496684.png"><img src="images/compare_workflows/image_1585300496684.png" width="250" alt="thresholded_imagej"/></a>
36+
37+
38+
Now we run the same workflow with CLIJ
39+
40+
```java
41+
42+
// Get test data
43+
open("https://github.com/clij/clij2-docs/raw/master/src/main/resources/Lund_MAX_001300.tif");
44+
rename("input_clij");
45+
46+
start_time_clij = getTime();
47+
48+
// Init GPU
49+
run("CLIJ Macro Extensions", "cl_device=");
50+
Ext.CLIJ2_clear();
51+
52+
// push data to GPU
53+
Ext.CLIJ2_push("input_clij");
54+
55+
// subtract background in the image
56+
radius = 25;
57+
Ext.CLIJ2_topHatBox("input_clij", "background_subtracted_clij", 25, 25, 0);
58+
Ext.CLIJ2_pull("background_subtracted_clij");
59+
60+
// threshold the image
61+
Ext.CLIJ2_automaticThreshold("background_subtracted_clij", "thresholded_clij", "Default");
62+
Ext.CLIJ2_pullBinary("thresholded_clij");
63+
64+
end_time_clij = getTime();
65+
66+
```
67+
<a href="images/compare_workflows/image_1585300498007.png"><img src="images/compare_workflows/image_1585300498007.png" width="250" alt="input_clij"/></a>
68+
<a href="images/compare_workflows/image_1585300498425.png"><img src="images/compare_workflows/image_1585300498425.png" width="250" alt="background_subtracted_clij"/></a>
69+
<a href="images/compare_workflows/image_1585300499005.png"><img src="images/compare_workflows/image_1585300499005.png" width="250" alt="thresholded_clij"/></a>
70+
71+
The results look similar. There are difference because the
72+
implementation of ImageJ background subtraction is close to but
73+
not identical to CLIJs topHatBox filter. Furthermore, CPU and GPUs
74+
do computation a bit differently.
75+
76+
## Quantitative image comparison
77+
78+
You may have noticed already, all intermediate images got new names.
79+
This allows us now to compare them.
80+
81+
Let's start with quantitative measurements on the images and
82+
processing durations.
83+
84+
```java
85+
// configure measurents, clean up before
86+
run("Set Measurements...", "area mean standard min redirect=None decimal=3");
87+
run("Clear Results");
88+
89+
// measure in the image from the imagej workflow
90+
selectWindow("background_subtracted_imagej");
91+
run("Measure");
92+
selectWindow("thresholded_imagej");
93+
run("Measure");
94+
95+
// measure in the image from the imagej workflow
96+
selectWindow("background_subtracted_clij");
97+
run("Measure");
98+
selectWindow("thresholded_clij");
99+
run("Measure");
100+
101+
//Table.rename("Results", "Quantitative measurements");
102+
103+
```
104+
<table>
105+
<tr><th>Area</th><th>Mean</th><th>StdDev</th><th>Min</th><th>Max</th></tr>
106+
<tr><td>524288</td><td>43.772</td><td>89.125</td><td>0</td><td>888</td></tr>
107+
<tr><td>524288</td><td>25.184</td><td>76.077</td><td>0</td><td>255</td></tr>
108+
<tr><td>524288</td><td>53.027</td><td>93.718</td><td>0</td><td>904</td></tr>
109+
<tr><td>524288</td><td>28.614</td><td>80.485</td><td>0</td><td>255</td></tr>
110+
</table>
111+
112+
113+
From these measurements we can conclude that there are small differences
114+
between the background subtracted images, but apparently smaller differences
115+
between the binary result images.
116+
117+
We can verify that by visualising
118+
differences visually. Note that we choose to save the subtraction images
119+
in 32-bit because 8-bit images don't support negative values.
120+
121+
## Visual differences between background_subtracted images
122+
123+
```java
124+
imageCalculator("Subtract create 32-bit", "background_subtracted_imagej","background_subtracted_clij");
125+
126+
```
127+
<a href="images/compare_workflows/image_1585300499308.png"><img src="images/compare_workflows/image_1585300499308.png" width="250" alt="Result of background_subtracted_imagej"/></a>
128+
129+
## Visual differences between thresholded images
130+
131+
```java
132+
imageCalculator("Subtract create 32-bit", "thresholded_imagej","thresholded_clij");
133+
134+
```
135+
<a href="images/compare_workflows/image_1585300499934.png"><img src="images/compare_workflows/image_1585300499934.png" width="250" alt="Result of thresholded_imagej"/></a>
136+
137+
This confirms visually our assumption: The background_subtracted images
138+
are a bit different while the binary result images are not.
139+
140+
## Comparing processing time
141+
142+
Let`s now also compare the different processing times:
143+
144+
```java
145+
146+
print("ImageJ took " + (end_time_imagej - start_time_imagej) + "ms.");
147+
print("CLIJ took " + (end_time_clij - start_time_clij) + "ms.");
148+
149+
```
150+
<pre>
151+
> ImageJ took 439ms.
152+
> CLIJ took 110ms.
153+
</pre>
154+
155+
The numbers shown here depend on used GPU hardware. Let's therefore it's
156+
good practice to document which GPU was used:
157+
158+
```java
159+
160+
run("Clear Results");
161+
Ext.CLIJ2_getGPUProperties();
162+
163+
```
164+
<table>
165+
<tr><th>GPUName</th><th>Global_memory_in_bytes</th><th>OpenCL_version</th></tr>
166+
<tr><td>GeForce RTX 2060 SUPER</td><td>8589934592.000</td><td>1.200</td></tr>
167+
</table>
168+
169+
170+
Note: If you run this script a second time, numbers may be a bit different,
171+
especially CLIJ becomes faster because the so called warmup period is over.
172+
During this period, code is compiled. This compilation takes time and thus,
173+
when doing it a second time, processing can be significantly faster.
174+
Furthermore, there are always fluctations in time measurements. Thus,
175+
it is recommended to run such workflows many times in a loop and doing
176+
statistics on derived measurements.
177+
178+
Last but not least, let's clean up by closing all windows and emptying
179+
GPU memory:
180+
181+
```java
182+
183+
run("Close All");
184+
Ext.CLIJ2_clear();
185+
```
186+
187+
188+
189+
```
190+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
2+
3+
# Comparing Workflows: ImageJ versus CLIJ
4+
Robert Haase, March 2020
5+
6+
This page shows how to compare ImageJ based workflow with their
7+
translations using CLIJ.
8+
9+
Let's start with ImageJ. We have a workflow loading an image,
10+
processing with background subtracting and thresholding. Note
11+
the two lines using the `getTime()`.
12+
13+
```
14+
15+
// Get test data
16+
open("https://github.com/clij/clij2-docs/raw/master/src/main/resources/Lund_MAX_001300.tif");
17+
rename("input_imagej");
18+
19+
start_time_imagej = getTime();
20+
21+
// subtract background in the image
22+
run("Duplicate...", "title=background_subtracted_imagej");
23+
run("Subtract Background...", "rolling=25");
24+
25+
// theshold the image
26+
run("Duplicate...", "title=thresholded_imagej");
27+
setAutoThreshold("Default dark");
28+
setOption("BlackBackground", true);
29+
run("Convert to Mask");
30+
31+
end_time_imagej = getTime();
32+
```
33+
<a href="image_1585236525631.png"><img src="image_1585236525631.png" width="250" alt="input_imagej"/></a>
34+
<a href="image_1585236526062.png"><img src="image_1585236526062.png" width="250" alt="background_subtracted_imagej"/></a>
35+
<a href="image_1585236527056.png"><img src="image_1585236527056.png" width="250" alt="thresholded_imagej"/></a>
36+
37+
38+
Now we run the same workflow with CLIJ
39+
40+
```
41+
42+
// Get test data
43+
open("https://github.com/clij/clij2-docs/raw/master/src/main/resources/Lund_MAX_001300.tif");
44+
rename("input_clij");
45+
46+
start_time_clij = getTime();
47+
48+
// Init GPU
49+
run("CLIJ Macro Extensions", "cl_device=");
50+
Ext.CLIJ2_clear();
51+
52+
// push data to GPU
53+
Ext.CLIJ2_push("input_clij");
54+
55+
// subtract background in the image
56+
radius = 25;
57+
Ext.CLIJ2_topHatBox("input_clij", "background_subtracted_clij", 25, 25, 0);
58+
Ext.CLIJ2_pull("background_subtracted_clij");
59+
60+
// threshold the image
61+
Ext.CLIJ2_automaticThreshold("background_subtracted_clij", "thresholded_clij", "Default");
62+
Ext.CLIJ2_pullBinary("thresholded_clij");
63+
64+
end_time_clij = getTime();
65+
66+
```
67+
<a href="image_1585236529225.png"><img src="image_1585236529225.png" width="250" alt="input_clij"/></a>
68+
<a href="image_1585236529637.png"><img src="image_1585236529637.png" width="250" alt="background_subtracted_clij"/></a>
69+
<a href="image_1585236530228.png"><img src="image_1585236530228.png" width="250" alt="thresholded_clij"/></a>
70+
71+
The results look similar. There are difference because the
72+
implementation of ImageJ background subtraction is close to but
73+
not identical to CLIJs topHatBox filter. Furthermore, CPU and GPUs
74+
do computation a bit differently.
75+
76+
## Quantitative image comparison
77+
78+
You may have noticed already, all intermediate images got new names.
79+
This allows us now to compare them.
80+
81+
Let's start with quantitative measurements on the images and
82+
processing durations.
83+
84+
```
85+
// configure measurents, clean up before
86+
run("Set Measurements...", "area mean standard min redirect=None decimal=3");
87+
run("Clear Results");
88+
89+
// measure in the image from the imagej workflow
90+
selectWindow("background_subtracted_imagej");
91+
run("Measure");
92+
selectWindow("thresholded_imagej");
93+
run("Measure");
94+
95+
// measure in the image from the imagej workflow
96+
selectWindow("background_subtracted_clij");
97+
run("Measure");
98+
selectWindow("thresholded_clij");
99+
run("Measure");
100+
101+
//Table.rename("Results", "Quantitative measurements");
102+
103+
```
104+
105+
From these measurements we can conclude that there are small differences
106+
between the background subtracted images, but apparently smaller differences
107+
between the binary result images.
108+
109+
We can verify that by visualising
110+
differences visually. Note that we choose to save the subtraction images
111+
in 32-bit because 8-bit images don't support negative values.
112+
113+
## Visual differences between background_subtracted images
114+
115+
```
116+
imageCalculator("Subtract create 32-bit", "background_subtracted_imagej","background_subtracted_clij");
117+
118+
```
119+
<a href="image_1585236530523.png"><img src="image_1585236530523.png" width="250" alt="Result of background_subtracted_imagej"/></a>
120+
121+
## Visual differences between thresholded images
122+
123+
```
124+
imageCalculator("Subtract create 32-bit", "thresholded_imagej","thresholded_clij");
125+
126+
```
127+
<a href="image_1585236531143.png"><img src="image_1585236531143.png" width="250" alt="Result of thresholded_imagej"/></a>
128+
129+
This confirms visually our assumption: The background_subtracted images
130+
are a bit different while the binary result images are not.
131+
132+
## Comparing processing time
133+
134+
Let`s now also compare the different processing times:
135+
136+
```
137+
138+
print("ImageJ took " + (end_time_imagej - start_time_imagej) + "ms.");
139+
print("CLIJ took " + (end_time_clij - start_time_clij) + "ms.");
140+
141+
```
142+
<pre>
143+
> ImageJ took 277ms.
144+
> CLIJ took 106ms.
145+
</pre>
146+
147+
The numbers shown here depend on used GPU hardware. Let's therefore it's
148+
good practice to document which GPU was used:
149+
150+
```
151+
152+
run("Clear Results");
153+
Ext.CLIJ2_getGPUProperties();
154+
155+
```
156+
<table>
157+
<tr><th>GPUName</th><th>Global_memory_in_bytes</th><th>OpenCL_version</th></tr>
158+
<tr><td>GeForce RTX 2060 SUPER</td><td>8589934592.000</td><td>1.200</td></tr>
159+
</table>
160+
161+
162+
Note: If you run this script a second time, numbers may be a bit different,
163+
especially CLIJ becomes faster because the so called warmup period is over.
164+
During this period, code is compiled. This compilation takes time and thus,
165+
when doing it a second time, processing can be significantly faster.
166+
Furthermore, there are always fluctations in time measurements. Thus,
167+
it is recommended to run such workflows many times in a loop and doing
168+
statistics on derived measurements.
169+
170+
Last but not least, let's clean up by closing all windows and emptying
171+
GPU memory:
172+
173+
```
174+
175+
run("Close All");
176+
Ext.CLIJ2_clear();
177+
```
178+
179+
180+
181+
Loading
Loading
Loading
Loading
Loading
18.9 KB
Loading
Loading
Loading

0 commit comments

Comments
 (0)