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 |
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; } } |
Free forum by Nabble | Edit this page |