Convert projections to sinogram

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Convert projections to sinogram

Thomas Carlier
Hi all,

For those who are involved in nuclear medicine application : I would  
like to know if somebody has already developed a plugin that converts  
a stack (projections) into a sinogram.

Thanks a lot for your answer


Thomas Carlier
University Hospital
Nantes, France
Reply | Threaded
Open this post in threaded view
|

Re: Convert projections to sinogram

Russell Kincaid
Dear Thomas,

I have a plugin that should work for you. It was a second generation
design that was made to work with 32-bit real images, but I tested it
now with a 16-bit unsigned set, and it seems to work.

If you have the projections open as a stack, just make them the "active
image", and compile and run the plugin.

I have attached the plugin.

Please let me know if you have any problems or questions.

Sincerely,

Russell Kincaid
Physics Dept.
Syracuse University
and
Radiology Department
SUNY Upstate Medical University

Syracuse, NY


Thomas Carlier wrote:

> Hi all,
>
> For those who are involved in nuclear medicine application : I would
> like to know if somebody has already developed a plugin that converts
> a stack (projections) into a sinogram.
>
> Thanks a lot for your answer
>
>
> Thomas Carlier
> University Hospital
> Nantes, France

import ij.*;          /*  Russell Kincaid      */
import ij.process.*;  /*  [hidden email]     */
import ij.gui.*;      /* start August 30, 2002 */
import java.awt.*;    /*    hacked from        */
import ij.plugin.*;   /*  various plugins      */

/*  "row only" so now only makes one new stack...

bug fixed 7/11/05, now using correct range for SLICE,
ROW, and COL which sometimes start at 1 and sometimes start at 0.
This is tricky because one loop runs from 1 to A_stackSize,
and the others need to run from 0 to (B_numDetRows -1) and
(0 to C_numDetCols - 1).
 Also changed to deal with Real data, using "doubles",
and "Get" and "Put" - "PixelValue"...


 This plugin was conceived by my Professor Andrzej Krol
for use in Nuclear Medicine to determine if the patient
has moved during the scan by looking at parallel projection
set data in a very special form hence the name SineO_Gram.
A particular point of activity will be seen on each row of
one slice of the new stack and will move as a sine wave
downward (vertically). If the patient moves, the curve will
be disrupted and that point will "stick out like a sore thumb"...

   This Plugin "maps" one stack into TWO new stacks
 where the original stack (projection set) is
 of form [A-slices(views), B-rows, C-columns]
   (where A, B, C, are integers)
 and the first new stack becomes
 of form [B-slices, A-rows, C-columns]
    (note the swap of A and B)
So, think of A as Angle (for number of views), and
C as number of detector columns (which does not change)
but B (which is the number of detector rows),
now is the number of slices so each detector row is
seen on its own slice with the rows of the slice
refering to the Angle it was seen from...
The SECOND new stack swaps Cols and Slices
so together they show movement from each direction */

public class Sine_O_GramRowOnlyReal implements PlugIn {

        public void run(String arg) {
                ImagePlus imp = WindowManager.getCurrentImage();
                String fileName = imp.getTitle();
       
                if (imp==null)
                        {IJ.noImage(); return;}
                ImageStack mystack = imp.getStack();
                if (mystack.getSize()==1)
                        {IJ.error("Stack Required"); return;}
                if (!showDialog(mystack))
                        return;  
                new ImagePlus(fileName+" sogRows", makeSineOGramRows(mystack)).show();
    //  "row only" new ImagePlus(fileName+" sogCols", makeSineOGramCols(mystack)).show();
            //        IJ.register(Sine_O_GramRowOnly.class);
        }

        public boolean showDialog(ImageStack stack) {
                GenericDialog gd = new GenericDialog("Sine-O-Gram");
                gd.showDialog();
                if (gd.wasCanceled())
                        return false;
                return true;
        }
       
        public ImageStack makeSineOGramRows(ImageStack stack) {   /* returns an ImageStack */
                int A_stackSize = stack.getSize(); /* new row number */
                int B_numDetRows = stack.getHeight(); /* new slice number */
                int C_numDetCols = stack.getWidth();
                double PIXVAL = 0.0;
                ImageStack newStack = new ImageStack(C_numDetCols, A_stackSize, stack.getColorModel());
                for (int SLICE=0; SLICE<=(B_numDetRows - 1); SLICE++) { /* SLICE is the old row number */
                        ImageProcessor ip = stack.getProcessor(1);   /* just to name the ip first ??? */
                    ImageProcessor ip1, ip2;
                    ip2 = ip.createProcessor(C_numDetCols, A_stackSize); /* so, now I can do this...??? */
                   
                        for (int ROW=1; ROW<=(A_stackSize);ROW++) { /* ROW is the old slice number */
                                ip1 = stack.getProcessor(ROW);
                            for (int COL=0; COL<=(C_numDetCols - 1); COL++) {
                                PIXVAL = ip1.getPixelValue(COL,SLICE);
                                ip2.putPixelValue(COL,ROW,PIXVAL);
                            }    /* does just 1 row */
                        }     /* has created a new slice */
                    newStack.addSlice(null,ip2);
                }
                return newStack;
        }
        public ImageStack makeSineOGramCols(ImageStack stack) {   /* returns an ImageStack */
                int A_stackSize = stack.getSize(); /* new row number */
                int B_numDetRows = stack.getHeight();
                int C_numDetCols = stack.getWidth(); /* new slice number */
                double PIXVAL = 0.0;
                ImageStack newStack = new ImageStack(A_stackSize, B_numDetRows, stack.getColorModel());
                for (int SLICE=0; SLICE<=(C_numDetCols - 1); SLICE++) { /* SLICE is the old col number */
                        ImageProcessor ip = stack.getProcessor(1);   /* just to name the ip first ??? */
                    ImageProcessor ip3, ip4;
                    ip4 = ip.createProcessor(A_stackSize, B_numDetRows); /* so, now I can do this...??? */
                   
                        for (int COL=1; COL<=(A_stackSize);COL++) { /* COL is the old slice number */
                                ip3 = stack.getProcessor(COL);
                            for (int ROW=0; ROW<=(B_numDetRows - 1); ROW++) {
                                PIXVAL = ip3.getPixelValue(SLICE, ROW);
                                ip4.putPixelValue(COL,ROW,PIXVAL);
                            }    /* does just 1 col */
                        }     /* has created a new slice */
                    newStack.addSlice(null,ip4);
                }              

               
                return newStack;
        }

}