public void iterativeReconstruct() throws Exception { Grid3D r = InitializeProjectionViews(); Grid3D q = InitializeProjectionViews(); Grid3D f = InitializeVolumeImage(); Grid3D d = InitializeVolumeImage(); Grid3D g_new = InitializeVolumeImage(); Grid3D g_old = InitializeVolumeImage(); double gamma; double alpha; NumericPointwiseOperators.copy(projectionViews, r); System.out.print( "Model-based iterative reconstruction using least-squares conjugate gradient solver: \n"); System.out.print("itn \t||r|| \t\t x(0) \t\n"); System.out.print("---------------------------------------- \n"); for (int itr = 1; itr <= maxNumOfIterations; itr++) { if (itr <= 5 || itr % 10 == 0 || itr >= maxNumOfIterations - 5) System.out.print( itr + " \t" + String.format("%8.3g", NumericPointwiseOperators.dotProduct(r)) + " \t" + String.format("%8.4f", f.getAtIndex(maxJ / 2, maxK / 2, maxK / 2)) + " \n"); backproject(r, g_new); if (itr == 1) { gamma = 0.0; NumericPointwiseOperators.copy(g_new, d); } else { gamma = NumericPointwiseOperators.dotProduct(g_new) / NumericPointwiseOperators.dotProduct(g_old); NumericPointwiseOperators.multiplyBy(d, (float) gamma); NumericPointwiseOperators.addBy(d, g_new); } forwardproject(q, d); alpha = NumericPointwiseOperators.dotProduct(g_new, d) / NumericPointwiseOperators.dotProduct(q); NumericGrid tmp = d.clone(); NumericPointwiseOperators.multiplyBy(tmp, (float) alpha); NumericPointwiseOperators.addBy(f, tmp); tmp = q.clone(); NumericPointwiseOperators.multiplyBy(tmp, (float) -alpha); NumericPointwiseOperators.addBy(r, tmp); NumericPointwiseOperators.copy(g_new, g_old); } volumeImage = f; }
private synchronized void projectSingleProjection(int projectionNumber, int dimz) { // load projection matrix initProjectionMatrix(projectionNumber); // load projection Grid2D projection = (Grid2D) projections.get(projectionNumber).clone(); // Correct for constant part of distance weighting + For angular sampling double D = getGeometry().getSourceToDetectorDistance(); NumericPointwiseOperators.multiplyBy( projection, (float) (D * D * 2 * Math.PI / getGeometry().getNumProjectionMatrices())); initProjectionData(projection); if (!largeVolumeMode) { projections.remove(projectionNumber); } // backproject for each slice // CUDA Grids are only two dimensional! int[] zed = new int[1]; int reconDimensionZ = dimz; double voxelSpacingX = getGeometry().getVoxelSpacingX(); double voxelSpacingY = getGeometry().getVoxelSpacingY(); double voxelSpacingZ = getGeometry().getVoxelSpacingZ(); zed[0] = reconDimensionZ; Pointer dOut = Pointer.to(volumePointer); Pointer pWidth = Pointer.to(new int[] {(int) lineOffset}); Pointer pZOffset = Pointer.to(zed); float[] vsx = new float[] {(float) voxelSpacingX}; Pointer pvsx = Pointer.to(vsx); Pointer pvsy = Pointer.to(new float[] {(float) voxelSpacingY}); Pointer pvsz = Pointer.to(new float[] {(float) voxelSpacingZ}); Pointer pox = Pointer.to(new float[] {(float) offsetX}); Pointer poy = Pointer.to(new float[] {(float) offsetY}); Pointer poz = Pointer.to(new float[] {(float) offsetZ}); int offset = 0; // System.out.println(dimz + " " + zed[0] + " " + offsetZ + " " + voxelSpacingZ); offset = CUDAUtil.align(offset, Sizeof.POINTER); JCudaDriver.cuParamSetv(function, offset, dOut, Sizeof.POINTER); offset += Sizeof.POINTER; offset = CUDAUtil.align(offset, Sizeof.INT); JCudaDriver.cuParamSetv(function, offset, pWidth, Sizeof.INT); offset += Sizeof.INT; offset = CUDAUtil.align(offset, Sizeof.INT); JCudaDriver.cuParamSetv(function, offset, pZOffset, Sizeof.INT); offset += Sizeof.INT; offset = CUDAUtil.align(offset, Sizeof.FLOAT); JCudaDriver.cuParamSetv(function, offset, pvsx, Sizeof.FLOAT); offset += Sizeof.FLOAT; offset = CUDAUtil.align(offset, Sizeof.FLOAT); JCudaDriver.cuParamSetv(function, offset, pvsy, Sizeof.FLOAT); offset += Sizeof.FLOAT; offset = CUDAUtil.align(offset, Sizeof.FLOAT); JCudaDriver.cuParamSetv(function, offset, pvsz, Sizeof.FLOAT); offset += Sizeof.FLOAT; offset = CUDAUtil.align(offset, Sizeof.FLOAT); JCudaDriver.cuParamSetv(function, offset, pox, Sizeof.FLOAT); offset += Sizeof.FLOAT; offset = CUDAUtil.align(offset, Sizeof.FLOAT); JCudaDriver.cuParamSetv(function, offset, poy, Sizeof.FLOAT); offset += Sizeof.FLOAT; offset = CUDAUtil.align(offset, Sizeof.FLOAT); JCudaDriver.cuParamSetv(function, offset, poz, Sizeof.FLOAT); offset += Sizeof.FLOAT; JCudaDriver.cuParamSetSize(function, offset); // Call the CUDA kernel, writing the results into the volume which is pointed at JCudaDriver.cuFuncSetBlockShape(function, bpBlockSize[0], bpBlockSize[1], 1); JCudaDriver.cuLaunchGrid(function, gridSize.x, gridSize.y); JCudaDriver.cuCtxSynchronize(); }