package edu.stanford.rsl.conrad.reconstruction.iterative;
import edu.stanford.rsl.conrad.data.numeric.Grid3D;
import edu.stanford.rsl.conrad.data.numeric.NumericPointwiseOperators;
import edu.stanford.rsl.conrad.geometry.trajectories.Trajectory;
public class PenalizedLeastSquareART extends DistanceDrivenBasedReconstruction {
/**
* Model-based iterative reconstruction using penalized least-squares solver.
* by Meng Wu
*/
private static final long serialVersionUID = 1L;
int maxNumOfIterations = 30;
float beta = 0.1f;
float delta = 0.01f;
public PenalizedLeastSquareART(Trajectory dataTrajectory) {
super(dataTrajectory);
// TODO Auto-generated constructor stub
}
public PenalizedLeastSquareART(Trajectory dataTrajectory, int maxIterations) {
super(dataTrajectory);
this.maxNumOfIterations = maxIterations;
}
public PenalizedLeastSquareART(Trajectory dataTrajectory, int maxIterations, float beta, float delta) {
super(dataTrajectory);
this.maxNumOfIterations = maxIterations;
this.beta = beta;
this.delta = delta;
}
huberPenalty pfun = new huberPenalty( beta, delta );
public void initialize( Grid3D proj){
maxI = getGeometry().getReconDimensionX();
maxJ = getGeometry().getReconDimensionY();
maxK = getGeometry().getReconDimensionZ();
maxU = getGeometry().getDetectorWidth(); //or it should be projection.getWidth();
maxV = getGeometry().getDetectorHeight();
dx = getGeometry().getVoxelSpacingX();
dy = getGeometry().getVoxelSpacingY();
dz = getGeometry().getVoxelSpacingZ();
time = System.currentTimeMillis();
projectionViews = proj;
}
public void iterativeReconstruct() throws Exception{
Grid3D a = InitializeVolumeImage();
Grid3D d = InitializeProjectionViews();
Grid3D e = InitializeVolumeImage();
Grid3D s = InitializeVolumeImage();
Grid3D t = InitializeVolumeImage();
Grid3D f = InitializeVolumeImage();
//pre-compute denumerator constant
NumericPointwiseOperators.fill(a, 1.0f);
forwardproject(d, a);
backproject(d, a);
forwardproject(d, f); // d = A(f)
d = (Grid3D)NumericPointwiseOperators.subtractedBy(d, projectionViews); // d = A(f) - l
System.out.print("Model-based iterative reconstruction: ");
System.out.print( "\t beta = " + beta + " delta = " + delta + "\n");
System.out.print("itn \t||r|| \t\t x(0) \tR(x) \t\n" );
System.out.print("------------------------------------------------ \n");
for ( int itr = 1; itr <= maxNumOfIterations; itr++ ){
backproject( d, e ); //e = At(d)
pfun.huberDerivative(f, s);
//PointwiseOperators.fill(s, 0.0f);
NumericPointwiseOperators.addBy(s, e); // s = e + s
pfun.huberCurvature(f, t);
//PointwiseOperators.fill(t, 0.0f);
NumericPointwiseOperators.addBy(t, a); // t = t + a
NumericPointwiseOperators.divideBy(e, t); // e = s ./ t
//update here
NumericPointwiseOperators.subtractBy(f, e); // f = f - e
NumericPointwiseOperators.removeNegative(f);
forwardproject(d, f); // d = A(f)
NumericPointwiseOperators.subtractBy(d, projectionViews); // d = A(f) - l
if ( itr <= 5 || itr%10 == 0 || itr >= maxNumOfIterations - 5 )
System.out.print( itr + " \t" + String.format( "%8.3g", NumericPointwiseOperators.dotProduct( d )) + " \t"
+ String.format( "%8.4f", f.getAtIndex(maxJ/2, maxK/2, maxK/2)) + " \t"
+ String.format( "%8.4f", pfun.huber(f)) + " \n" );
}
volumeImage = f;
}
}
/*
* Copyright (C) 2010-2014 Meng Wu
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/