package edu.stanford.rsl.conrad.reconstruction; import edu.stanford.rsl.conrad.data.numeric.Grid3D; import edu.stanford.rsl.conrad.geometry.motion.MotionField; import edu.stanford.rsl.conrad.geometry.motion.MotionUtil; import edu.stanford.rsl.conrad.utils.CONRAD; /** * This FBP-based mathod splits the reconstruction volume into sub volumes which can be processed in parallel to speed up the reconstruction further. * Internally motion-compensated voi reconstructors are used. * @author akmaier * */ public class MotionCompensatedSubVolumeBackprojector extends SubVolumeBackprojector { /** * */ private static final long serialVersionUID = 6027629320244326462L; MotionField motionField; public void setMotionField(MotionField motionField) { this.motionField = motionField; } public MotionField getMotionField() { return motionField; } public MotionCompensatedSubVolumeBackprojector() { numThreads = CONRAD.getNumberOfThreads(); projectors = new VOIBasedReconstructionFilter[numThreads]; subVolumes = new Grid3D[numThreads]; for (int i = 0; i < numThreads; i++){ projectors[i] = new MotionCompensatedVOIBasedReconstructionFilter(); } } @Override public String getName(){ return "Parallel Motion Compensated CPU-based Sub-volume Backprojector"; } public void initializeProjectionVolume(){ super.initializeProjectionVolume(); motionField = MotionUtil.get4DSpline(); int reconDimensionX = getGeometry().getReconDimensionX(); int reconDimensionY = getGeometry().getReconDimensionY(); int reconDimensionZ = getGeometry().getReconDimensionZ(); double voxelSpacingX = getGeometry().getVoxelSpacingX(); double voxelSpacingY = getGeometry().getVoxelSpacingY(); double voxelSpacingZ = getGeometry().getVoxelSpacingZ(); int subVolumeReconDimensionX = (int) Math.ceil((reconDimensionX + 0.0) / numThreads); int lastSubVolumeReconDimensionX = reconDimensionX - ((numThreads - 1) * subVolumeReconDimensionX); for (int i = 0; i < numThreads; i++){ if (debug) { projectors[i].setMaxI(subVolumeReconDimensionX); projectors[i].initializeProjectionVolume(); } else { if (i < numThreads - 1) subVolumes[i] = new Grid3D(subVolumeReconDimensionX,reconDimensionY,reconDimensionZ); else subVolumes[i] = new Grid3D(lastSubVolumeReconDimensionX,reconDimensionY,reconDimensionZ); projectors[i].setProjectionVolume(subVolumes[i]); projectors[i].offsetX = (-getGeometry().getOriginX()) - (i * subVolumeReconDimensionX * voxelSpacingX) ; projectors[i].offsetY = ((reconDimensionY-1) * voxelSpacingY) / 2; projectors[i].offsetZ = ((reconDimensionZ-1) * voxelSpacingZ) / 2; if (i < numThreads - 1) { projectors[i].setMaxI(subVolumeReconDimensionX); } else { projectors[i].setMaxI(lastSubVolumeReconDimensionX); } projectors[i].maxK = this.maxK; projectors[i].maxJ = this.maxJ; projectors[i].lineOffset = lineOffset; if(projectors[i].useVOImap && projectors[i].interestedInVolume!=null){ projectors[i].setFastVOIMode(false); projectors[i].initializeVOIMap(); } ((MotionCompensatedVOIBasedReconstructionFilter)projectors[i]).setMotionField(motionField); projectors[i].init = true; } } volumeRewritten = false; } @Override public void prepareForSerialization(){ super.prepareForSerialization(); motionField = null; } @Override public String getBibtexCitation() { return CONRAD.CONRADBibtex; } @Override public String getMedlineCitation() { return CONRAD.CONRADMedline; } @Override public String getToolName(){ return "Motion-compensated Subvolume CPU-based Backprojector"; } } /* * Copyright (C) 2010-2014 Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */