package edu.stanford.rsl.conrad.opencl;
import java.util.ArrayList;
import com.jogamp.opencl.CLMemory.Mem;
import edu.stanford.rsl.apps.gui.Citeable;
import edu.stanford.rsl.apps.gui.GUIConfigurable;
import edu.stanford.rsl.conrad.geometry.Projection;
import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.utils.FileUtil;
import edu.stanford.rsl.conrad.utils.XmlUtils;
//TODO: Use our own matrices instead of Jama.Matrix
/**
* Forward projection expects input of a volumetric phantom scaled to mass density. Projection result {@latex.inline $p(\\vec{x})$} is then the accumulated mass along the ray {@latex.inline $\\vec{x}$} which consists of the line segments {@latex.inline $x_i$} in {@latex.inline $[\\textnormal{cm}]$} with the mass densities {@latex.inline $\\mu_i$} in {@latex.inline $[\\frac{\\textnormal{g}}{\\textnormal{cm}^3}]$}.
* The actual projection is then computed as:<br>
* {@latex.inline $$p(\\vec{x}) = \\sum_{i} x_i \\cdot \\mu_i$$}<BR>
* The projection values are then returned in {@latex.inline $[\\frac{\\textnormal{g}}{\\textnormal{cm}^2}]$}
* @author akmaier, berger (refactored from CUDA)
*
*/
public class OpenCLForwardProjectorWithMotion extends OpenCLForwardProjector implements GUIConfigurable, Citeable {
/**
* The XML filename where the rigid motion parameters are stored
*/
private String rotationTranslationFilename = null;
@SuppressWarnings("unchecked")
public SimpleMatrix[] readInMotionMatrices() {
SimpleMatrix[] motion = new SimpleMatrix[nrProj];
// load data from XML file
ArrayList<double[][][]> RotTrans = null;
try {
if (rotationTranslationFilename == null)
rotationTranslationFilename = FileUtil.myFileChoose(".xml", false);
RotTrans = (ArrayList<double[][][]>)XmlUtils.importFromXML(rotationTranslationFilename);
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < nrProj; i++) {
motion[i] = new SimpleMatrix(4,4);
SimpleMatrix rotation = new SimpleMatrix(RotTrans.get(0)[i]);
SimpleMatrix translation = new SimpleMatrix(RotTrans.get(1)[i]);
motion[i].setSubMatrixValue(0, 0, rotation.transposed());
motion[i].setSubMatrixValue(0, 3, translation.multipliedBy(-1));
motion[i].setRowValue(3, new SimpleVector(0,0,0,1));
}
return motion;
}
/**
* First incorporate the rigid object motion into the projection matrices, then
* load the inverted projection matrices for all projections and reset the projection data.
* @param projectionNumber
*/
@Override
protected void prepareAllProjections(){
if (gInvARmatrix == null)
gInvARmatrix = context.createFloatBuffer(3*3*nrProj, Mem.READ_ONLY);
if (gSrcPoint == null)
gSrcPoint = context.createFloatBuffer(3*nrProj, Mem.READ_ONLY);
// load the motion transforms
// load data from XML file
SimpleMatrix[] motion = readInMotionMatrices();
gInvARmatrix.getBuffer().rewind();
gSrcPoint.getBuffer().rewind();
for (int i=0; i < nrProj; ++i){
Projection proj = new Projection(projectionMatrices[i]);
proj.setRtValue(SimpleOperators.multiplyMatrixProd(proj.getRt(),motion[i]));
computeCanonicalProjectionMatrix(gInvARmatrix, gSrcPoint, proj);
}
gInvARmatrix.getBuffer().rewind();
gSrcPoint.getBuffer().rewind();
commandQueue
.putWriteBuffer(gSrcPoint, true)
.putWriteBuffer(gInvARmatrix, true)
.finish();
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier, Martin Berger, Marco Bögel
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/