/*
-----------------------------------------------------------------------
Copyright: 2010-2018, imec Vision Lab, University of Antwerp
2014-2018, CWI, Amsterdam
Contact: astra@astra-toolbox.com
Website: http://www.astra-toolbox.com/
This file is part of the ASTRA Toolbox.
The ASTRA Toolbox is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The ASTRA Toolbox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the ASTRA Toolbox. If not, see .
-----------------------------------------------------------------------
*/
#include "astra/cuda/2d/algo.h"
#include "astra/cuda/2d/par_fp.h"
#include "astra/cuda/2d/fan_fp.h"
#include "astra/cuda/2d/par_bp.h"
#include "astra/cuda/2d/fan_bp.h"
#include "astra/cuda/2d/util.h"
#include "astra/cuda/2d/arith.h"
#include "astra/cuda/2d/astra.h"
#include
namespace astraCUDA {
ReconAlgo::ReconAlgo()
{
parProjs = 0;
fanProjs = 0;
useVolumeMask = false;
useSinogramMask = false;
D_maskData = 0;
D_smaskData = 0;
D_sinoData = 0;
D_volumeData = 0;
useMinConstraint = false;
useMaxConstraint = false;
freeGPUMemory = false;
}
ReconAlgo::~ReconAlgo()
{
reset();
}
void ReconAlgo::reset()
{
delete[] parProjs;
delete[] fanProjs;
if (freeGPUMemory) {
cudaFree(D_maskData);
cudaFree(D_smaskData);
cudaFree(D_sinoData);
cudaFree(D_volumeData);
}
parProjs = 0;
fanProjs = 0;
useVolumeMask = false;
useSinogramMask = false;
D_maskData = 0;
D_smaskData = 0;
D_sinoData = 0;
D_volumeData = 0;
useMinConstraint = false;
useMaxConstraint = false;
freeGPUMemory = false;
}
bool ReconAlgo::setGPUIndex(int iGPUIndex)
{
if (iGPUIndex != -1) {
cudaSetDevice(iGPUIndex);
cudaError_t err = cudaGetLastError();
// Ignore errors caused by calling cudaSetDevice multiple times
if (err != cudaSuccess && err != cudaErrorSetOnActiveProcess)
return false;
}
return true;
}
bool ReconAlgo::enableVolumeMask()
{
useVolumeMask = true;
return true;
}
bool ReconAlgo::enableSinogramMask()
{
useSinogramMask = true;
return true;
}
bool ReconAlgo::setGeometry(const astra::CVolumeGeometry2D* pVolGeom,
const astra::CProjectionGeometry2D* pProjGeom)
{
bool ok;
ok = convertAstraGeometry_dims(pVolGeom, pProjGeom, dims);
if (!ok)
return false;
delete[] parProjs;
parProjs = 0;
delete[] fanProjs;
fanProjs = 0;
fOutputScale = 1.0f;
ok = convertAstraGeometry(pVolGeom, pProjGeom, parProjs, fanProjs, fOutputScale);
if (!ok)
return false;
return true;
}
bool ReconAlgo::setSuperSampling(int raysPerDet, int raysPerPixelDim)
{
if (raysPerDet <= 0 || raysPerPixelDim <= 0)
return false;
dims.iRaysPerDet = raysPerDet;
dims.iRaysPerPixelDim = raysPerPixelDim;
return true;
}
bool ReconAlgo::setVolumeMask(float* _D_maskData, unsigned int _maskPitch)
{
assert(useVolumeMask);
D_maskData = _D_maskData;
maskPitch = _maskPitch;
return true;
}
bool ReconAlgo::setSinogramMask(float* _D_smaskData, unsigned int _smaskPitch)
{
assert(useSinogramMask);
D_smaskData = _D_smaskData;
smaskPitch = _smaskPitch;
return true;
}
bool ReconAlgo::setBuffers(float* _D_volumeData, unsigned int _volumePitch,
float* _D_projData, unsigned int _projPitch)
{
D_volumeData = _D_volumeData;
volumePitch = _volumePitch;
D_sinoData = _D_projData;
sinoPitch = _projPitch;
return true;
}
bool ReconAlgo::setMinConstraint(float fMin)
{
fMinConstraint = fMin;
useMinConstraint = true;
return true;
}
bool ReconAlgo::setMaxConstraint(float fMax)
{
fMaxConstraint = fMax;
useMaxConstraint = true;
return true;
}
bool ReconAlgo::allocateBuffers()
{
bool ok;
ok = allocateVolumeData(D_volumeData, volumePitch, dims);
if (!ok)
return false;
ok = allocateProjectionData(D_sinoData, sinoPitch, dims);
if (!ok) {
cudaFree(D_volumeData);
D_volumeData = 0;
return false;
}
if (useVolumeMask) {
ok = allocateVolumeData(D_maskData, maskPitch, dims);
if (!ok) {
cudaFree(D_volumeData);
cudaFree(D_sinoData);
D_volumeData = 0;
D_sinoData = 0;
return false;
}
}
if (useSinogramMask) {
ok = allocateProjectionData(D_smaskData, smaskPitch, dims);
if (!ok) {
cudaFree(D_volumeData);
cudaFree(D_sinoData);
cudaFree(D_maskData);
D_volumeData = 0;
D_sinoData = 0;
D_maskData = 0;
return false;
}
}
freeGPUMemory = true;
return true;
}
bool ReconAlgo::copyDataToGPU(const float* pfSinogram, unsigned int iSinogramPitch, float fSinogramScale,
const float* pfReconstruction, unsigned int iReconstructionPitch,
const float* pfVolMask, unsigned int iVolMaskPitch,
const float* pfSinoMask, unsigned int iSinoMaskPitch)
{
if (!pfSinogram)
return false;
if (!pfReconstruction)
return false;
bool ok = copySinogramToDevice(pfSinogram, iSinogramPitch,
dims,
D_sinoData, sinoPitch);
if (!ok)
return false;
// rescale sinogram
if (fSinogramScale != 1.0f)
processSino(D_sinoData, fSinogramScale,
sinoPitch, dims);
ok = copyVolumeToDevice(pfReconstruction, iReconstructionPitch,
dims,
D_volumeData, volumePitch);
if (!ok)
return false;
if (useVolumeMask) {
if (!pfVolMask)
return false;
ok = copyVolumeToDevice(pfVolMask, iVolMaskPitch,
dims,
D_maskData, maskPitch);
if (!ok)
return false;
}
if (useSinogramMask) {
if (!pfSinoMask)
return false;
ok = copySinogramToDevice(pfSinoMask, iSinoMaskPitch,
dims,
D_smaskData, smaskPitch);
if (!ok)
return false;
}
return true;
}
bool ReconAlgo::getReconstruction(float* pfReconstruction,
unsigned int iReconstructionPitch) const
{
bool ok = copyVolumeFromDevice(pfReconstruction, iReconstructionPitch,
dims,
D_volumeData, volumePitch);
if (!ok)
return false;
return true;
}
bool ReconAlgo::callFP(float* D_volumeData, unsigned int volumePitch,
float* D_projData, unsigned int projPitch,
float outputScale)
{
if (parProjs) {
assert(!fanProjs);
return FP(D_volumeData, volumePitch, D_projData, projPitch,
dims, parProjs, fOutputScale * outputScale);
} else {
assert(fanProjs);
return FanFP(D_volumeData, volumePitch, D_projData, projPitch,
dims, fanProjs, fOutputScale * outputScale);
}
}
bool ReconAlgo::callBP(float* D_volumeData, unsigned int volumePitch,
float* D_projData, unsigned int projPitch,
float outputScale)
{
if (parProjs) {
assert(!fanProjs);
return BP(D_volumeData, volumePitch, D_projData, projPitch,
dims, parProjs, fOutputScale * outputScale);
} else {
assert(fanProjs);
return FanBP(D_volumeData, volumePitch, D_projData, projPitch,
dims, fanProjs, fOutputScale * outputScale);
}
}
}