content: package edu.stanford.rsl.conrad.opencl;
  
  import com.jogamp.opencl.CLMemory.Mem;
  
  import edu.stanford.rsl.conrad.geometry.transforms.AffineTransform;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleOperators;
  import edu.stanford.rsl.conrad.utils.Configuration;
  import edu.stanford.rsl.conrad.utils.XmlUtils;
  
  public class OpenCLDetectorMotionBackProjector extends OpenCLBackProjector{
  	
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = -7764566238080291654L;
  	
  	AffineTransform[] affDetMotion;
  
  	public OpenCLDetectorMotionBackProjector () {
  		super();
  		affDetMotion = null;
  	}
  
  	@Override
  	public void configure() throws Exception{
  		super.configure();
  		affDetMotion = (AffineTransform[])XmlUtils.importFromXML();
  		if (affDetMotion==null || affDetMotion.length != Configuration.getGlobalConfiguration().getGeometry().getProjectionStackSize())
  			throw new Exception("Motion fields exceed the number of projections");
  	}
  	
  	public void configure(AffineTransform[] transf) throws Exception{
  		super.configure();
  		if (transf==null || transf.length != Configuration.getGlobalConfiguration().getGeometry().getProjectionStackSize()){
  			configured = false;
  			throw new Exception("Motion fields exceed the number of projections");
  		}
  		this.affDetMotion = transf;
  	}
  
  	@Override
  	protected synchronized void initProjectionMatrix(int projectionNumber){
  		// load projection Matrix for current Projection.
  		// if detector motion field exists, apply to projection matrix to do correction
  		SimpleMatrix pMat;
  		if (affDetMotion== null || affDetMotion.length <= projectionNumber)
  			pMat = getGeometry().getProjectionMatrix(projectionNumber).computeP();
  		else{
  			SimpleMatrix affMotionH = new SimpleMatrix(3,3);
  			affMotionH.setSubMatrixValue(0, 0, affDetMotion[projectionNumber].getRotation(2));
  			affMotionH.setSubColValue(0, 2, affDetMotion[projectionNumber].getTranslation(2));
  			affMotionH.setElementValue(2,2,1);
  			pMat = SimpleOperators.multiplyMatrixProd(affMotionH, getGeometry().getProjectionMatrix(projectionNumber).computeP());
  		}
  		
  		float [] pMatFloat = new float[pMat.getCols() * pMat.getRows()];
  		for (int j = 0; j< pMat.getRows(); j++) {
  			for (int i = 0; i< pMat.getCols(); i++) {
  
  				pMatFloat[(j * pMat.getCols()) + i] = (float) pMat.getElement(j, i);
  			}
  		}
  
  		// Obtain the global pointer to the view matrix from
  		// the module
  		if (projectionMatrix == null)
  			projectionMatrix = context.createFloatBuffer(pMatFloat.length, Mem.READ_ONLY);
  
  		projectionMatrix.getBuffer().put(pMatFloat);
  		projectionMatrix.getBuffer().rewind();
  		commandQueue.putWriteBuffer(projectionMatrix, true).finish();
  	}
  
  
  	@Override
  	public String getName() {
  		return "OpenCL Backprojector With Detector Motion";
  	}
  
  	@Override
  	public String getToolName(){
  		return "OpenCL Backprojector With Detector Motion";
  	}
  
  }
  /*
   * Copyright (C) 2010-2014 Martin Berger
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */