package edu.stanford.rsl.conrad.reconstruction;
import java.lang.Math;
import edu.stanford.rsl.conrad.data.numeric.Grid3D;
import edu.stanford.rsl.conrad.data.numeric.NumericPointwiseOperators;
import edu.stanford.rsl.conrad.geometry.Projection;
import edu.stanford.rsl.conrad.geometry.SeparableFootprints;
import edu.stanford.rsl.conrad.geometry.trajectories.Trajectory;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
public class SeparableFootprintsBasedReconstruction extends ModelBasedIterativeReconstruction {
private static final long serialVersionUID = 1L;
public boolean Debug = true;
public boolean Debug1 = false;
public boolean Debug2 = false;
protected static final int MAX_WEIGHT_LENGTH = 6;
protected enum SFOperation{ SF_PROJECT, SF_BACKPROJECT};
public enum FootprintsType{ RectRect, TrapRect, TrapTrap };
public SeparableFootprintsBasedReconstruction( Trajectory dataTrajectory ) {
super(dataTrajectory);
// TODO Auto-generated constructor stub
}
@Override
public void iterativeReconstruct() throws Exception {
forwardproject( projectionViews, volumeImage );
}
@Override
protected void forwardproject(Grid3D projImage, Grid3D volImage) throws Exception {
//zero out whole volume image
NumericPointwiseOperators.fill(projImage, 0.0f);
NumericPointwiseOperators.fill(volImage, 1.0f);
//if (Debug) volImage.printOneSlice(3);
Projection proj;
for ( int p = 0; p < nImages ; p++ ){
proj = getGeometry().getProjectionMatrix(p);
separableFootprintsRectRect( projImage, volImage, proj, p , SFOperation.SF_PROJECT);
}
//if (Debug) projImage.printOneSlice(8);
}
@Override
protected void backproject(Grid3D projImage, Grid3D volImage) throws Exception {
//zero out whole volume image
NumericPointwiseOperators.fill(volImage, 0.0f);
//if (Debug) volImage.printOneSlice(3);
Projection proj;
for ( int p = 0; p < nImages; p++ ){
proj = getGeometry().getProjectionMatrix(p);
separableFootprintsRectRect( projImage, volImage, proj, p , SFOperation.SF_BACKPROJECT);
}
}
protected void separableFootprintsRectRect( Grid3D projImage, Grid3D volImage, Projection proj, final int ip, final SFOperation operation ) throws Exception{
SimpleMatrix mat = proj.computeP();
SimpleVector cameraCenter = proj.computeCameraCenter();
// buffer have move of voxel
SimpleVector halfVoxelMoveX = mat.getCol(0);
halfVoxelMoveX.multiplyBy(dx/2);
SimpleVector halfVoxelMoveY = mat.getCol(1);
halfVoxelMoveY.multiplyBy(dy/2);
SimpleVector fullVoxelMoveZ = mat.getCol(2);
fullVoxelMoveZ.multiplyBy(dz);
SimpleVector point3d = new SimpleVector(4);
point3d.setElementValue(3, 1);
SimpleVector point2d, point2dMinus, point2dPlus;
double cx = cameraCenter.getElement(0);
double cy = cameraCenter.getElement(1);
double cz = cameraCenter.getElement(2);
double dsx0, dsy0, dsxy0_sqr;
double coordLeft, coordRight, coordBottom, coordTop, coordStep;
double ds0, amplitude;
SeparableFootprints footprints = new SeparableFootprints();;
boolean projOnDetector;
for (int i=1; i < maxI; i++){
point3d.setElementValue(0, i*dx - offsetX );
for (int j = 0; j < maxJ; j++){
point3d.setElementValue(1, j*dy - offsetY );
point3d.setElementValue(2, -dz/2 - offsetZ);
point2d = SimpleOperators.multiply(mat, point3d);
dsx0 = Math.abs(point3d.getElement(0) - cx);
dsy0 = Math.abs(point3d.getElement(1) - cy);
dsxy0_sqr = dsx0*dsx0 + dsy0*dsy0;
if ( dsy0 > dsx0){
ds0 = dsy0;
point2dMinus = SimpleOperators.subtract(point2d, halfVoxelMoveX);
point2dPlus = SimpleOperators.add(point2d, halfVoxelMoveX);
}else{
ds0 = dsx0;
point2dMinus = SimpleOperators.subtract(point2d, halfVoxelMoveY);
point2dPlus = SimpleOperators.add(point2d, halfVoxelMoveY);
}
coordLeft = point2dMinus.getElement(0) / point2dMinus.getElement(2) + 0.5;
coordRight = point2dPlus.getElement(0) / point2dPlus.getElement(2) + 0.5;
projOnDetector = footprints.rectFootprintWeightU(coordLeft, coordRight, maxU);
if ( !projOnDetector )
continue;
coordBottom = point2d.getElement(1) / point2d.getElement(2) + 0.5;
point2d.add(fullVoxelMoveZ);
coordTop = point2d.getElement(1) / point2d.getElement(2) + 0.5;
coordStep = coordTop - coordBottom;
for ( int k = 0; k < maxK; k++ ){
double dsz0 = Math.abs(k*dz-offsetZ-cz);
projOnDetector = footprints.rectFootprintWeightV(coordBottom, coordTop, maxV);
if ( !projOnDetector )
continue;
amplitude = Math.sqrt(dsz0*dsz0 + dsxy0_sqr) / ds0;
if ( operation == SFOperation.SF_PROJECT ){
footprints.footprintsProject( projImage, volImage, amplitude, i, j, k, ip);
}else if ( operation == SFOperation.SF_BACKPROJECT ) {
footprints.footprintsBackproject( projImage, volImage, amplitude, i, j, k, ip);
}else{
throw new Exception("Wrong SF Operation");
}
coordBottom = coordTop;
coordTop = coordTop + coordStep;
} //k
}//j
}//i
}
@Override
public String getBibtexCitation() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getMedlineCitation() {
// TODO Auto-generated method stub
return null;
}
}
/*
* Copyright (C) 2010-2014 Meng Wu
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/