CLIJ: overwriting an input with a result/output

So the general way CLIJ works taking input & writing to an output is very intuitive—to me. More so than wrangling open images in normal macros.
But, when playing around and tweaking stuff, such as inserting a step in a process, it can be annoying?
For example, I want to add Exclude on edges into an existing processing macro:

//Label objects
Ext.CLIJ2_connectedComponentsLabelingBox(WS, labels);
Ext.CLIJ2_release(WS);

//Exclude on edges
Ext.CLIJ2_excludeLabelsOnEdges(labels, labelsE);

//Count the number of objects labeled
Ext.CLIJ2_getMaximumOfAllPixels(labelsE, count);
//Ext.CLIJ2_statisticsOfLabelledPixels(labels, labels);

I have to remember to edit the downstream input to match the new output ‘labelsE’. And if I comment out the Exclude step, then I have to fix downstream (back to ‘labels’)
To my surprise, the following works fine instead (as an insertion in the block above):

Ext.CLIJ2_excludeLabelsOnEdges(labels, labels);

No changes downstream required! But is this ‘safe’? Seems OK—and it use is handy!—but I rather not be making fundamental errors…

1 Like

It should be safe in this case. Note that inplace-operations are officially not supported in clij. I guess you found one, which works by chance.

Other operations, especially those where output-pixel intensities depend on regions of input pixels, will not work with input=output. For example mean2DBox:

run("CLIJ2 Macro Extensions", "cl_device=");

// Load image from disc 
run("Blobs");
image_1 = getTitle();
Ext.CLIJ2_push(image_1);

Ext.CLIJ2_mean2DBox(image_1, image_1, 2, 2);

will result in this error:

This error is thrown to prevent image output that is not reproducible due to the highly parallel nature of image computation in graphics processing units.

If you find any operation that has non-reproducible results and better should not allow input=output, please let me know.

Best,
Robert

2 Likes

Thanks! Appreciate the info. Looks like a bad habit, so I’ll not push my luck.
I’m coming from doing R/tidyverse coding where the pipe operator is amazing for chaining data processing.

Looking at my (simple) pipeline (with comments and linebreaks removed): none of the intermediates are stored, they’re all released, as the steps are chained together. I was really tempted before to try overwriting inputs…

Ext.CLIJ2_push(orig);
Ext.CLIJ2_topHatBox(orig, DoG, 6*scale, 6*scale, 0);
Ext.CLIJ2_release(orig);
Ext.CLIJ2_thresholdRenyiEntropy(DoG, mask);
Ext.CLIJ2_release(DoG);
Ext.CLIJ2_erodeBox(mask, eroded);
Ext.CLIJ2_dilateBox(eroded, opened);
Ext.CLIJ2_release(mask);
Ext.CLIJ2_release(eroded);
Ext.CLIJx_imageJWatershed(opened, WS);
Ext.CLIJ2_release(opened);
Ext.CLIJ2_connectedComponentsLabelingBox(WS, labels);
Ext.CLIJ2_release(WS);
Ext.CLIJ2_excludeLabelsOnEdges(labels, labelsE);
Ext.CLIJ2_release(labels);
Ext.CLIJ2_getMaximumOfAllPixels(labelsE, count);

OK, the TopHatBox has other values passed, so we could skip that.
So a bit of a wishlist for me:
Would nice if there was a way to abstract away the intermediate outputs and all the extra release steps.
Tidyverse/magritter pipe pseudo code:

Ext.CLIJ2_push(orig);
orig %>%
Ext.CLIJ2_topHatBox(6*scale, 6*scale, 0) %>%
Ext.CLIJ2_thresholdRenyiEntropy() %>%
Ext.CLIJ2_erodeBox() %>%
Ext.CLIJ2_dilateBox() %>%
Ext.CLIJx_imageJWatershed() %>%
Ext.CLIJ2_connectedComponentsLabelingBox() %>%
Ext.CLIJ2_excludeLabelsOnEdges() %>%
Ext.CLIJ2_getMaximumOfAllPixels() -> count

Notice you can comment out any step in the pipeline and nothing breaks, the step is just skipped. Likewise, you can add a new intermediate step and don’t have to rename the following inputs.

Yeah, that’s a fantastic idea. However, that would involve changing the imagej macro language. I guess that’s out of scope. However, if you feel like developing a R-wrapper for clij, similar to the matlab wrapper clatlab, I would be happy to assist you.

This would be to run CLIJ commands in R?
I know some people use R for image analysis…
My brain has sort of done the thing that I scold students for: pushed stuff into filing drawers.
Got image data? ImageJ!
Got numbers? R!
Of course, I well know that images are numbers, but…

1 Like