package edu.stanford.rsl.conrad.reconstruction;
import edu.stanford.rsl.conrad.data.numeric.Grid2D;
import edu.stanford.rsl.conrad.reconstruction.ReconstructionFilter;
import edu.stanford.rsl.conrad.utils.Configuration;
import edu.stanford.rsl.conrad.utils.ImageGridBuffer;
import ij.IJ;
@Deprecated
public abstract class SuperShortScanBackprojection extends ReconstructionFilter {
/**
*
*/
private static final long serialVersionUID = 8744415315605892588L;
protected double [] primaryAngles;
protected double SID;
protected double width =-1;
protected double height = -1;
protected double detectorElementSizeX;
protected double detectorElementSizeY;
private boolean closed = false;
protected ReconstructionFilter projector;
protected ImageGridBuffer imageBuffer;
protected Grid2D[] projections;
@Override
public void configure() throws Exception{
projectionVolume = null;
Configuration config = Configuration.getGlobalConfiguration();
SID = config.getGeometry().getSourceToDetectorDistance();
detectorElementSizeX = config.getGeometry().getPixelDimensionX();
detectorElementSizeY = config.getGeometry().getPixelDimensionY();
//maxProjections = config.getGeometry().getProjectionStackSize();
//projections = new ImageProcessor[maxProjections];
//ReconstructionFilter [] projectors = BufferedProjectionSink.getBackprojectors();
//projector = (ReconstructionFilter) UserUtil.chooseObject("Select Backprojector", "Backprojector Selection", projectors, projector);
projector.configure();
configured = true;
}
@Override
public String getName(){
return "Super Short Scan Backprojector";
}
@Override
public synchronized void process(Grid2D img, int index) throws Exception{
if (imageBuffer == null){
imageBuffer = new ImageGridBuffer();
}
imageBuffer.add(img, index);
}
public void close(){
//if (true) throw new RuntimeException("closing" + closed);
if (!closed) {
projections = imageBuffer.toArray();
int maxProjections = imageBuffer.size();
imageBuffer = null;
// Backproject using selected algorithm
for(int i=0; i < maxProjections; i++){
IJ.showStatus("Backprojecting");
IJ.showProgress(((float)i)/maxProjections);
try {
projector.process(projections[i], i);
} catch (Exception e){
e.printStackTrace();
}
}
IJ.showProgress(1.0);
projector.close();
//projectionVolume = projector.getResult();
//for (int n = 1; n <=projectionVolume.getNSlices(); n++){
// projectionVolume.getStack().getProcessor(n).multiply(-1.0);
//}
//projectionVolume.show();
closed = true;
}
}
/*
public void close_old() throws Exception{
if (!closed) {
projections = imageBuffer.toArray();
int maxProjections = imageBuffer.size();
imageBuffer = null;
// precompute weights
double [] uWeights = new double[projections[0].getWidth()];
for (int i=0; i<uWeights.length;i++){
double pos = (i-(uWeights.length/2)) * detectorElementSizeX;
uWeights[i]= ((Math.pow(pos,2) + Math.pow(SID, 2)) / SID);
}
double [][] vWeights = new double[projections[0].getWidth()][projections[0].getHeight()];
for (int j=0; j<vWeights[0].length;j++){
for (int i=0; i<vWeights.length;i++){
double posU = (i-(vWeights.length/2)) * detectorElementSizeX;
double posV = (j-(vWeights[0].length/2)) * detectorElementSizeY;
vWeights[i][j]= (posU * posV) / SID;
}
}
// perform triplet-wise derivative;
ImageProcessor lastProjection = projections[0].duplicate();
for (int i = 1; i< maxProjections-1; i++){
IJ.showStatus("Computing lambda derivative");
IJ.showProgress(((float)i)/maxProjections);
ImageProcessor projectionBasedDerivative = computeUVDerivative(i, uWeights, vWeights);
ImageProcessor lambdaDerivative = lastProjection;
//if (i == 15) VisualizationUtil.showImageProcessor(lambdaDerivative.duplicate());
//lambdaDerivative.multiply(-1.0);
//if (i == 15) VisualizationUtil.showImageProcessor(lambdaDerivative.duplicate());
ImageUtil.subtractProcessors(lambdaDerivative, projections[i]);
//if (i == 15) VisualizationUtil.showImageProcessor(lambdaDerivative.duplicate());
//lambdaDerivative.multiply(-1.0);
//if (i == 15) VisualizationUtil.showImageProcessor(lambdaDerivative.duplicate());
ImageUtil.addProcessors(lambdaDerivative, projectionBasedDerivative);
lastProjection = projections[i];
projections[i] = lambdaDerivative;
}
// we assume derivative 0 in first and last projection in lambda direction.
projections[0]=computeUVDerivative(0, uWeights, vWeights);
projections[maxProjections-1]=computeUVDerivative(maxProjections-1, uWeights, vWeights);
// Backproject using selected algorithm
for(int i=0; i < maxProjections; i++){
IJ.showStatus("Backprojecting");
IJ.showProgress(((float)i)/maxProjections);
projector.process(projections[i], i);
}
IJ.showProgress(1.0);
closed = true;
}
}
private ImageProcessor computeUVDerivative(int index, double [] uWeights, double [][] vWeights){
float [] kernel = {-1, 0, 1};
ImageProcessor revan = new FloatProcessor(projections[index].getWidth(), projections[index].getHeight());
// derivative in row direction
ImageProcessor uDev = projections[index].duplicate();
uDev.convolve(kernel, 3, 1);
// derivative in column direction
ImageProcessor vDev = projections[index].duplicate();
vDev.convolve(kernel, 1, 3);
// weight and add to result.
for(int i =0; i<uDev.getWidth(); i++){
for (int j=0; j< uDev.getHeight(); j++){
double u = uDev.getPixelValue(i,j);
u *= uWeights[i];
double v = vDev.getPixelValue(i, j);
v *= vWeights[i][j];
revan.putPixelValue(i, j, v+u);
}
}
return revan;
}
*/
@Override
public void prepareForSerialization(){
super.prepareForSerialization();
primaryAngles = null;
projections = null;
projector = null;
configured = false;
closed = false;
imageBuffer = null;
}
@Override
public String getBibtexCitation(){
return "see medline";
}
@Override
public String getMedlineCitation(){
return "Yu H, Wang G. Feldkamp-type VOI reconstruction from super-short-scan cone-beam data. Med Phys 31(6):1357-62. 2004.";
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/