# Zprojector sum algorithm

#1

Hi everybody,
Here is a piece of code I use:

``````ZProjector zp = new ZProjector(pile);
zp.setMethod(ZProjector.SUM_METHOD);
zp.setStartSlice(1);
zp.setStopSlice(pile.getNSlices());
zp.doProjection();
ImagePlus imps = zp.getProjection();
``````

Looking to imps with thresholds it appears that the sum results are spread across the range (8 bits). Has somebody an axplanation for this?

Alan

#2

Hi @Alan,

I’m not sure what you mean by this. Could you explain what the input looks like, what the output is and in what way this differs from you expectation.

John

#3

Hi John,
Imagine a stack with 8 slices each one with 0 and 1 values.
Adding the 8 slices together will produce a result between 0 and 8.
Doing this with the ZProjector produces the following values:

255, 223,…255 -i*32

Alan

#4

I am unable to reproduce this problem. Here is my test script:

``````  stack = IJ.createImage("Stack", "8-bit noise", 256, 256, 8);
IJ.run(stack, "Divide...", "value=256 stack");
stats = stack.getStatistics();
print("max1="+stats.max);
zp = new ZProjector(stack);
zp.setMethod(ZProjector.SUM_METHOD);
zp.setStartSlice(1);
zp.setStopSlice(stack.getNSlices());
zp.doProjection();
sum = zp.getProjection();
stats = sum.getStatistics();
print("max2="+stats.max);
sum.show();
``````

And here is the output:

``````  max1=1
max2=8
``````

Here is a macro version of the script:

``````  newImage("Untitled", "8-bit noise", 256, 256, 8);
run("Divide...", "value=256 stack");
Stack.getStatistics(voxelCount, mean, min, max)
print("stack max="+max);
run("Z Project...", "projection=[Sum Slices]");
getStatistics(voxelCount, mean, min, max)
print("sum max="+max);``````

#5

Hello Wayne,
Here is the plugin in which I get the problem:

``````import ij.*;
import ij.io.*;
import ij.process.*;
import ij.gui.*;
import ij.plugin.*;

import java.awt.*;

public class ZProjTest1 implements PlugIn {
double offset[][] = new double[9][2];
public void run(String arg) {

// Prépare les offsets

offset[0][0]=0.0;
offset[0][1]=0.0;

offset[1][0]=1.0;
offset[1][1]=0.0;

offset[2][0]=1.0;
offset[2][1]=1.0;

offset[3][0]=0.0;
offset[3][1]=1.0;

offset[4][0]=-1.0;
offset[4][1]=1.0;

offset[5][0]=-1.0;
offset[5][1]=0.0;

offset[6][0]=-1.0;
offset[6][1]=-1.0;

offset[7][0]=0.0;
offset[7][1]=-1.0;

offset[8][0]=1.0;
offset[8][1]=-1.0;

// Open image dialogue ouverture fichier

OpenDialog od = new OpenDialog("Open image file", arg);
String file = od.getFileName();
if (file == null) return;
String directory = od.getDirectory();
Opener opener = new Opener();

ImagePlus imp0 = opener.openImage(directory, file);
imp0.show();
IJ.showMessage("Original  ");

// Seuile l'image

double tmin=40.0;  //Arbitraire
double tmax=170.0; //Arbitraire
ImageProcessor ip0 = imp0.getProcessor();
ip0.setThreshold(tmin,tmax,0); //BLACK_AND_WHITE_LUT=1, 0=RED_LUT
imp1.show();
IJ.showMessage("Seuils  ");

// crée la pile, remplir avec imp1 (binaire)

ImageProcessor ip1 = imp1.getProcessor();
ImagePlus pile = makeStack(ip1,9); // nb slices mais premier index =0 !!!
pile.show();
int nSlices = pile.getStackSize();
IJ.showMessage("nb Slices:  "+String.valueOf(nSlices));

// Aligne les voisins dans la pile

for (int i=0;i<9; i++){
doTranslation(pile,offset[i][0],offset[i][1],i);
}
IJ.showMessage("Translations show  ");

// repasser à  0-1 au lieu de 0-255

for (int i=1;i<=9; i++){
pile.setSlice(i);
ImagePlus  impi=pile;
ImageProcessor ipi =impi.getProcessor();
// passer de 255 -> 1, on garde le dernier bit
ipi.and(0x01);
}

// Addition des tranches de pile avec ZProjector

/*	ZProjector zp = new ZProjector(pile);
zp.setMethod(ZProjector.SUM_METHOD);
zp.setStartSlice(1);
zp.setStopSlice(pile.getNSlices());
zp.doProjection();
ImagePlus imps = zp.getProjection();
*/
ZProjector projector = new ZProjector(pile);
ImagePlus imps = projector.run(pile, "Sum Slices", 1, 9);

imps.show();
imps.setTitle("Somme");

IJ.run(imps, "8-bit", "");
imps.setTitle("Somme");
imps.show();
}

//procedures de translation
void doTranslation(ImagePlus pile,double u0, double v0, int x) {
pile.setSlice(x+1);
pile.setProcessor(Shift(pile.getProcessor(),(double)u0,(double)v0));
}

//procedures de shift
ImageProcessor Shift(ImageProcessor ip, double x0, double y0) {
ip.setInterpolationMethod(0);
ip.translate(x0, y0);
return ip;
}

// selfexplained
public void showImageMaximized(ImagePlus imp) {
imp.show();
ImageWindow win = imp.getWindow();
win.setExtendedState(ImageWindow.MAXIMIZED_BOTH);
}

// génère l'image binaire avec les seuils
ImagePlus createMaskFromThreshold(ImagePlus imp, String imgnom) {
ImageProcessor ip = imp.getProcessor();
if (ip.getMinThreshold()==ImageProcessor.NO_THRESHOLD)
{IJ.error("Create Mask", "Area selection or thresholded image required");
return null;
}
double t1 = ip.getMinThreshold();
double t2 = ip.getMaxThreshold();
IJ.run("Duplicate...", "title="+imgnom);
ImagePlus imp2 = WindowManager.getCurrentImage();
ImageProcessor ip2 = imp2.getProcessor();
ip2.setThreshold(t1, t2, ip2.getLutUpdateMode());
return imp2;
}

// crée un stack
ImagePlus makeStack(ImageProcessor ip, int nbi) {
int width = ip.getWidth();
int height = ip.getHeight();
ImagePlus stack = IJ.createImage("Itérés", "GRAY8", width, height, nbi);
for (int k =1; k<=nbi;  k++){
insertStack(ip,stack,k);
}
return stack;
}

void insertStack(ImageProcessor ip, ImagePlus stack, int i) {
int width = ip.getWidth();
int height = ip.getHeight();
ip.setRoi(1, 1, width, height);
stack.setSlice(i);
ImageProcessor 	ip2 = stack.getProcessor();
ip2.insert(ip, 1, 1);
}

}
``````

#6

Dear @Alan,

Please provide a minimal reproducible example.

Something like this JavaScript example:

``````  stack = IJ.createImage("Stack", "8-bit noise", 256, 256, 8);
IJ.run(stack, "Divide...", "value=256 stack");
stats = stack.getStatistics();
print("max1="+stats.max);
zp = new ZProjector(stack);
zp.setMethod(ZProjector.SUM_METHOD);
zp.doProjection();
sum = zp.getProjection();
stats = sum.getStatistics();
print("max2="+stats.max);
sum.show();
``````

which outputs

``````  max1=1
max2=8``````

#7

Hi Waine,
OK understood, I’ll do that.
How can I send attached files with the MWE.