Command for extracting average out of an array

Hello community! I am pretty new in the world of ImageJ and I also just started developing my own macros. I am currently at a dead end and I need your help.
So, I have an array containing around 15 values and I want to build the sum of them. I tried using some loops, but that didn´t work out.
Also, I only need the value separately, not as an array, so I can then work further with it alone.

1 Like

Hey @ThanosT,

the sum of numbers in an macro array can be computed by the mean in the array multiplied by the number of elements:

numbers = newArray(3, 7, 4, 7, 1);
Array.getStatistics(numbers, minimum, maximum, mean);
number_of_elements = lengthOf(numbers);

sum = mean * number_of_elements;

https://imagej.nih.gov/ij/developer/macro/functions.html#array.getstatistics

Let us know if it works!

Cheers,
Robert

1 Like

It worked out perfectly fine Robert! Danke dir!

I now have a new question… While performing the macro, I now have 3 values which interest me. They all have their string names of course and I want to somehow extract them in excel. The whole process will be looped for multiple images and what I want to end up with, is an excel table with the 3 values I measured from every image.
I am familiar with looping, so this won´t be a problem and I also saw a way of extracting (actually saving) the results in an excel format.
The problems are:

  1. I don´t know how to display all 3 values in the result window at the end of each loop (with their respective name).
  2. With this way of extracting the values, I will end up with multiple excel files containing my values for each image and then I have to somehow compress them in one. Is there a faster way of doing this? Maybe displaying the results after looping all the images and then extracting them all together?

I thank you in advance and I totally respect the fact, that this may take a lot of your time to explain it to me.

Greetings from Düsseldorf
Thanos

1 Like

Hey @ThanosT,

I’m not sure if I understand correctly. You could write numbers in tables, line by line, during a for loop and then save the table to disc in excel format after the for loop. I can’t see where the multiple Excel files should come from. If you are writing about a specific ImageJ macro which is in front of you, please share it here as it might ease the life of us trying to help you :wink:

Furthermore, you can learn what to do with tables in ImageJ macro in this video:

Let us know if you need further assistance.

Cheers,
Robert

1 Like

Hey Robert, sorry for the late response.

Your video is very helpful and I used a lot of your tips in my macro. Let me explain what is the case here in detail. The macro is too long, that´s why I don´t share it here, it will be such a pain to go through it, especially because it has so many variables, which only I know what they stand for.

The loop goes through the images in my folder and gets three measurements, so if I have five images, I end up with three arrays containing five values each.
One of those three arrays contains the average area of a set of ROIs. I end up to this average by creating an array with all the areas and then extracting the mean of the array. For my analysis I would also like to have the areas of each single ROI, not only the average.

So here is the problem, each loop adds one value to each of my arrays, but resets the array containing all the areas. At the end I use the “array.show” command to create a table containing the three main arrays, but if I try to also include the array with the individual areas, I end up with only the areas of the last image (makes sense).

To make the question clear, is there a way to make an array out of arrays (in my case, an array of all images containing the arrays of the areas of my ROIs)?

Greetings
Thanos

I figured a way “around” the problem. I display the array I want to extract at the end of each loop and save it as an excel file before the next loop starts. I end up with several files containing the arrays of each loop and using an excel array, I combine them in a single table.

You can concatenate arrays. And if you need to remember where the individual ones are, keep an extra array in which you keep pointers to each of the concatenated arrays within the big array.
So if arrays are {1,2,3},{5,6,7} and {9,10}, your concatenated array will be {1,2,3,5,6,7,9,10} and the pointer array will contain {0,3,6}, pointing to the first, fourth and seventh(!) element of the array.
In a similar array, you can keep the averages, while in the large array you keep the individual values.

1 Like

I am not sure if I get what you mean. So when the first “small” loop is over I end up with an array containing all individual areas and the array with the average areas gets its first value. The first “big” loop is now over and the second one starts with the new image. The second “small” loop takes place, measures the individual areas again (the areas of the first loop get replaced) and after that, the array with the averages gets its second value. This goes on for all my images.

You are saying, that after each small loop is over and before the next big loop starts (new image), I should create another array which gets all the values from the array containing the individual areas. When the next image is processed, the new individual areas will get added to this array, so at the end of my macro I end up with an array containing all the individual areas for all my images. At the same time, I create another array which saves the position where the new individual areas got added, so I can split them later in individual arrays and display them separately?

If this is the case, can you show me an example of how this would approximately look like? I only know how to add single values to arrays using the command array[i] = value, but this will reset after the first big loop… Also I don´t know how this pointer array can be created.

If this is too complicated, don´t bother spending your time for this. Thank you for your help.

Hi @ThanosT,

Yes, you’ve got it. This is a small macro that calculates the average of two arrays, keeps track of the average and [a pointer to the first entry of each small array in a large array] and the large array consisting of the smaller arrays. Of course, you can build this into loops, as long as you can use (ImageJ1’s) expandable arrays option OR know in advance the total number of elements in the large array.

Sample macro
setOption("ExpandableArrays", true);
smallArray1 = newArray(1,1,1,1);
smallArray2 = newArray(1,2,3,4);
largeArray = newArray();
averageArray = newArray();
pointerArray = newArray();
sum = 0;
for(i = 0; i < smallArray1.length; i++){
	sum = sum + smallArray1[i];
}
pointerArray[0] = largeArray.length;
averageArray[0] = sum/smallArray1.length;
largeArray = Array.copy(smallArray1);

sum = 0;
for(i = 0; i < smallArray2.length; i++){
	sum = sum + smallArray2[i];
}
averageArray[1] = sum/smallArray2.length;
pointerArray[1] = largeArray.length;
largeArray = Array.concat(largeArray,smallArray2);

Array.show(averageArray);
Array.show(pointerArray);
Array.show(largeArray);
1 Like

Hello @eljonco!

Thank you very much for your ideas! They gave me food for thought and I came up with a different solutions. Your suggestion maybe is better than what I have done, but it works…

So, at the end of each small loop I add an if-command which works regarding the number of the image. So for the first image, it defines an array named singleAreas1, with the length of my initial array containing the individual areas and gets all the values from it. When the second loop takes place (second image) the if command guides the macro to create a new array named singleAreas2 and puts the new values from the initial array in this one. I know that my files don´t have more than 10 images, so I made the if-commands go up to number 10…

At the end I ask the user to type the number of images and according to the input, I use the array.show command with the respective number of arrays I want it to show (if I add more, I get an error). Finally, I print the values in a single table and export them directly to excel.

Thank you very much for your time guys!!

1 Like

@ThanosT,
Well done!
The learning experience is the most important result here, next best is that you solved your problems on your own.

How to handle an unknown-in-advance number of images without spelling out array names, but instead using array concatenation and indexing is of secondary importance; maybe for later, when you have gained more experience in programming.

1 Like

@eljonco
Exactly, thank you very much!

Since you have the experience, can I asked you another small thing? I already created a topic about this, but no one has replied to me yet…

I have an image, duplicate it and apply threshold to it. I then use the AND operation of the image calculator between the two images and I click the “32-bit (float) result” box. The values of my original (without threshold) image are kept as they were before, but the decimal values are gone. So, a value of 3.00 and 8.00 for example stay the same, but values like 2.45, 6.02 and 8.99 get rounded to 2.00, 6.00 and 8.00…

Do you know something about this?

Hi @ThanosT,

I guess it is a consequence of applying a logical operation on a floating point image.
Do you want to replace the thresholded pixels with zero and leave the rest intact?
Then threshold on a duplicate; threshold the duplicate should create a binary (only 0 or 255 as pixel values), on that do math divide by 255, so the thresholded duplicate contains 1 where you want to keep the original and 0 where you want to threshold out pixels, then (maybe convert this image to 32 bit and) do an image math multiplication of the one-or-zero image and the original. I guess the decimals now should be retained.

1 Like

Hi everyone,

I think @eljonco is right: The AND operation is not thought for grey-value images. Alternatively to the suggestion above, you could use the “Clear Outside” command to set all pixels outside a thresholded region to zero. That actually also spares some steps like duplication and multiplication. This macro demonstrates it:

run("Blobs (25K)");

// use thresholding to create an ROI
setAutoThreshold("Default"); // just set the threshold; don't apply it
run("Create Selection");
resetThreshold();

// set all pixels outside the ROI to zero
setBackgroundColor(0, 0, 0);
run("Clear Outside");

Cheers,
Robert

Hello guys! Thank you both so much for your suggestions! Both ways work fine!
@haesleinhuepf just to understand what these commands do:
setBackgroundColor(0, 0, 0); basically sets all the pixels not included in the selection to 0?
And what does run(“Clear Outside”); do then?

1 Like

With setBackground you define what color background should have and wit Clear Outside you set all pixels outside the ROI to this value.

@haesleinhuepf Oh, now I see! Okay Robert, thank you very much!

1 Like