/*
* Copyright (C) 2014 Madgalena Herbst
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/
package edu.stanford.rsl.tutorial.noncircularfov;
import ij.ImageJ;
import edu.stanford.rsl.conrad.data.numeric.Grid2D;
import edu.stanford.rsl.tutorial.fan.CosineFilter;
import edu.stanford.rsl.tutorial.fan.FanBeamBackprojector2D;
import edu.stanford.rsl.tutorial.fan.FanBeamProjector2D;
import edu.stanford.rsl.tutorial.filters.RamLakKernel;
import edu.stanford.rsl.tutorial.phantoms.Phantom;
/**
* Short example of how to use the Correspondences class.
*
* @author Magdalena
*
*/
public class TrajectoryExample {
public static void main(String[] args) {
// required parameters
int imgSzXMM = 256, // [mm]
imgSzYMM = imgSzXMM; // [mm]
float pxSzXMM = 1.0f, // [mm]
pxSzYMM = pxSzXMM; // [mm]
int imgSzXGU = (int) Math.floor(imgSzXMM / pxSzXMM), // [GU]
imgSzYGU = (int) Math.floor(imgSzYMM / pxSzYMM); // [GU]
double gammaM =2* 11.768288932020647 * Math.PI / 180, maxT = 501, deltaT = 1.0, focalLength = (maxT / 2.0 - 0.5)
* deltaT / Math.tan(gammaM), maxBeta = 360 * Math.PI / 180, // +gammaM*2,
deltaBeta = maxBeta / 360;
// create Phantom
System.out.println("Creating phantom...");
Phantom phantom = new TwoCirclesGrid(imgSzXMM,imgSzYMM);
phantom.setSpacing(pxSzXMM, pxSzYMM);
// origin is given in (negative) world coordinates
phantom.setOrigin(-(imgSzXGU * phantom.getSpacing()[0]) / 2,
-(imgSzYGU * phantom.getSpacing()[1]) / 2);
new ImageJ();
phantom.show("Phantom");
// make projections
System.out.println("projecting...");
FanBeamProjector2D fanBeamProjector = new FanBeamProjector2D(focalLength, maxBeta, deltaBeta, maxT, deltaT);
Grid2D projectionP = new Grid2D(phantom);
Grid2D sino = fanBeamProjector.projectRayDriven(projectionP);
sino.clone().show("Sinogram");
// computing the minimal set
System.out.println("Computing the minimal set...");
double detSize = 130; // [mm], pixelsize deltaT
int detSizeGU = (int) (detSize/deltaT);
Correspondences c = new Correspondences(focalLength, sino);
int[] minimalSet = c.evaluateNumer(sino, detSizeGU);
System.out.println("Minimal required rotation: " + minimalSet[0]*deltaBeta + "degress, corresp. start angle: " + minimalSet[1]*deltaBeta);
// displaying the minimal set
System.out.println("Display minimal set");
int width = sino.getWidth();
int height = sino.getHeight();
Grid2D mask = new Grid2D(width, height);
Grid2D data = new Grid2D(width, height);
int start = minimalSet[1];
int rot = minimalSet[0];
for (int y = start; y < start + rot; y++) {
for (int x = 0; x < width; x++) {
//if (sino.getAtIndex(x, y%height) > 0) {
if((x>150) && (x < 150+detSize)){
for (int i = 0; i < detSize; i++) {
if (x + i < width) {
mask.setAtIndex(x + i, y%height, 1.f);
data.setAtIndex(x + i, y%height, sino.getAtIndex(x + i, y%height));
}
}
break;
}
}
}
Grid2D res = c.findCorrespondences(mask, sino);
res.setSpacing(deltaT, deltaBeta); // required for reconstruction
Grid2D dou = c.findRedundancies(mask, sino);
Grid2D diff = new Grid2D(width, height);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
// count missing data
if(sino.getAtIndex(x, y) > 0 && res.getAtIndex(x, y) == 0) {
diff.setAtIndex(x, y, 1.f);
}
}
}
data.show("Acquired Data");
res.show("Reconstructed Sinogram");
dou.show("redundant areas");
diff.show("Missing Pixels");
mask.show("Mask");
// resonstruct the completed sinogram
System.out.println("Reconstruct the completed sinogram...");
RamLakKernel ramLak = new RamLakKernel((int) (maxT / deltaT), deltaT);
CosineFilter cKern = new CosineFilter(focalLength, maxT, deltaT);
// Apply filtering
for (int theta = 0; theta < res.getSize()[1]; ++theta) {
cKern.applyToGrid(res.getSubGrid(theta));
}
for (int theta = 0; theta < res.getSize()[1]; ++theta) {
ramLak.applyToGrid(res.getSubGrid(theta));
}
res.show("After Filtering");
// Do the backprojection
FanBeamBackprojector2D fbp = new FanBeamBackprojector2D(focalLength,
deltaT, deltaBeta, imgSzXMM, imgSzYMM);
Grid2D reco = fbp.backprojectPixelDriven(res);
reco.show("Reconstructed result");
//finished
System.out.println("Everything done!");
}
}