From b14fb531ad9ae3d565f2cf28f5506408ab10dbed Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 18 Nov 2015 11:26:15 +0100 Subject: Add CompositeGeometryManager This handles FP and BP operations on multiple data objects at once, splitting them to fit in GPU memory where necessary. --- include/astra/CompositeGeometryManager.h | 150 ++++++++++++++++++++++++ include/astra/ConeProjectionGeometry3D.h | 10 +- include/astra/ConeVecProjectionGeometry3D.h | 11 +- include/astra/GeometryUtil3D.h | 17 +++ include/astra/ParallelProjectionGeometry3D.h | 11 +- include/astra/ParallelVecProjectionGeometry3D.h | 10 +- include/astra/ProjectionGeometry3D.h | 19 ++- 7 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 include/astra/CompositeGeometryManager.h (limited to 'include/astra') diff --git a/include/astra/CompositeGeometryManager.h b/include/astra/CompositeGeometryManager.h new file mode 100644 index 0000000..a6e57f1 --- /dev/null +++ b/include/astra/CompositeGeometryManager.h @@ -0,0 +1,150 @@ +/* +----------------------------------------------------------------------- +Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp + 2014-2015, CWI, Amsterdam + +Contact: astra@uantwerpen.be +Website: http://sf.net/projects/astra-toolbox + +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 . + +----------------------------------------------------------------------- +*/ + +#ifndef _INC_ASTRA_COMPOSITEGEOMETRYMANAGER +#define _INC_ASTRA_COMPOSITEGEOMETRYMANAGER + +#include "Globals.h" + +#ifdef ASTRA_CUDA + +#include +#include +#include +#include + + +namespace astra { + +class CCompositeVolume; +class CCompositeProjections; +class CFloat32Data3DMemory; +class CFloat32ProjectionData3DMemory; +class CFloat32VolumeData3DMemory; +class CVolumeGeometry3D; +class CProjectionGeometry3D; +class CProjector3D; + + + +class _AstraExport CCompositeGeometryManager { +public: + class CPart; + typedef std::list > TPartList; + class CPart { + public: + CPart() { } + CPart(const CPart& other); + virtual ~CPart() { } + + enum { + PART_VOL, PART_PROJ + } eType; + + CFloat32Data3DMemory* pData; + unsigned int subX; + unsigned int subY; + unsigned int subZ; + + bool uploadToGPU(); + bool downloadFromGPU(/*mode?*/); + virtual TPartList split(size_t maxSize, int div) = 0; + virtual CPart* reduce(const CPart *other) = 0; + virtual void getDims(size_t &x, size_t &y, size_t &z) = 0; + size_t getSize(); + }; + + class CVolumePart : public CPart { + public: + CVolumePart() { eType = PART_VOL; } + CVolumePart(const CVolumePart& other); + virtual ~CVolumePart(); + + CVolumeGeometry3D* pGeom; + + virtual TPartList split(size_t maxSize, int div); + virtual CPart* reduce(const CPart *other); + virtual void getDims(size_t &x, size_t &y, size_t &z); + + CVolumePart* clone() const; + }; + class CProjectionPart : public CPart { + public: + CProjectionPart() { eType = PART_PROJ; } + CProjectionPart(const CProjectionPart& other); + virtual ~CProjectionPart(); + + CProjectionGeometry3D* pGeom; + + virtual TPartList split(size_t maxSize, int div); + virtual CPart* reduce(const CPart *other); + virtual void getDims(size_t &x, size_t &y, size_t &z); + + CProjectionPart* clone() const; + }; + + struct SJob { + public: + boost::shared_ptr pInput; + boost::shared_ptr pOutput; + CProjector3D *pProjector; // For a `global' geometry. It will not match + // the geometries of the input and output. + + + enum { + JOB_FP, JOB_BP, JOB_NOP + } eType; + enum { + MODE_ADD, MODE_SET + } eMode; + + }; + + typedef std::list TJobList; + // output part -> list of jobs for that output + typedef std::map TJobSet; + + bool doJobs(TJobList &jobs); + + // Convenience functions for creating and running a single FP or BP job + bool doFP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, + CFloat32ProjectionData3DMemory *pProjData); + bool doBP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, + CFloat32ProjectionData3DMemory *pProjData); + + +protected: + + bool splitJobs(TJobSet &jobs, size_t maxSize, int div, TJobSet &split); + +}; + +} + +#endif + +#endif diff --git a/include/astra/ConeProjectionGeometry3D.h b/include/astra/ConeProjectionGeometry3D.h index 00e72ce..dede6e1 100644 --- a/include/astra/ConeProjectionGeometry3D.h +++ b/include/astra/ConeProjectionGeometry3D.h @@ -186,9 +186,15 @@ public: */ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; - virtual void projectPoint(float32 fX, float32 fY, float32 fZ, + virtual void projectPoint(double fX, double fY, double fZ, int iAngleIndex, - float32 &fU, float32 &fV) const; + double &fU, double &fV) const; + virtual void backprojectPointX(int iAngleIndex, double fU, double fV, + double fX, double &fY, double &fZ) const; + virtual void backprojectPointY(int iAngleIndex, double fU, double fV, + double fY, double &fX, double &fZ) const; + virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, + double fZ, double &fX, double &fY) const; }; diff --git a/include/astra/ConeVecProjectionGeometry3D.h b/include/astra/ConeVecProjectionGeometry3D.h index 71e8010..f76f9dd 100644 --- a/include/astra/ConeVecProjectionGeometry3D.h +++ b/include/astra/ConeVecProjectionGeometry3D.h @@ -148,9 +148,16 @@ public: const SConeProjection* getProjectionVectors() const { return m_pProjectionAngles; } - virtual void projectPoint(float32 fX, float32 fY, float32 fZ, + virtual void projectPoint(double fX, double fY, double fZ, int iAngleIndex, - float32 &fU, float32 &fV) const; + double &fU, double &fV) const; + virtual void backprojectPointX(int iAngleIndex, double fU, double fV, + double fX, double &fY, double &fZ) const; + virtual void backprojectPointY(int iAngleIndex, double fU, double fV, + double fY, double &fX, double &fZ) const; + virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, + double fZ, double &fX, double &fY) const; + }; } // namespace astra diff --git a/include/astra/GeometryUtil3D.h b/include/astra/GeometryUtil3D.h index 6ceac63..e4d73e4 100644 --- a/include/astra/GeometryUtil3D.h +++ b/include/astra/GeometryUtil3D.h @@ -119,6 +119,23 @@ void computeBP_UV_Coeffs(const SConeProjection& proj, double &fDX, double &fDY, double &fDZ, double &fDC); +SConeProjection* genConeProjections(unsigned int iProjAngles, + unsigned int iProjU, + unsigned int iProjV, + double fOriginSourceDistance, + double fOriginDetectorDistance, + double fDetUSize, + double fDetVSize, + const float *pfAngles); + +SPar3DProjection* genPar3DProjections(unsigned int iProjAngles, + unsigned int iProjU, + unsigned int iProjV, + double fDetUSize, + double fDetVSize, + const float *pfAngles); + + } diff --git a/include/astra/ParallelProjectionGeometry3D.h b/include/astra/ParallelProjectionGeometry3D.h index 72401e5..d95c050 100644 --- a/include/astra/ParallelProjectionGeometry3D.h +++ b/include/astra/ParallelProjectionGeometry3D.h @@ -147,9 +147,16 @@ public: */ virtual CVector3D getProjectionDirection(int _iProjectionIndex, int _iDetectorIndex) const; - virtual void projectPoint(float32 fX, float32 fY, float32 fZ, + virtual void projectPoint(double fX, double fY, double fZ, int iAngleIndex, - float32 &fU, float32 &fV) const; + double &fU, double &fV) const; + virtual void backprojectPointX(int iAngleIndex, double fU, double fV, + double fX, double &fY, double &fZ) const; + virtual void backprojectPointY(int iAngleIndex, double fU, double fV, + double fY, double &fX, double &fZ) const; + virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, + double fZ, double &fX, double &fY) const; + /** * Creates (= allocates) a 2D projection geometry used when projecting one slice using a 2D projector diff --git a/include/astra/ParallelVecProjectionGeometry3D.h b/include/astra/ParallelVecProjectionGeometry3D.h index 59238c8..ec91086 100644 --- a/include/astra/ParallelVecProjectionGeometry3D.h +++ b/include/astra/ParallelVecProjectionGeometry3D.h @@ -149,9 +149,15 @@ public: const SPar3DProjection* getProjectionVectors() const { return m_pProjectionAngles; } - virtual void projectPoint(float32 fX, float32 fY, float32 fZ, + virtual void projectPoint(double fX, double fY, double fZ, int iAngleIndex, - float32 &fU, float32 &fV) const; + double &fU, double &fV) const; + virtual void backprojectPointX(int iAngleIndex, double fU, double fV, + double fX, double &fY, double &fZ) const; + virtual void backprojectPointY(int iAngleIndex, double fU, double fV, + double fY, double &fX, double &fZ) const; + virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, + double fZ, double &fX, double &fY) const; }; } // namespace astra diff --git a/include/astra/ProjectionGeometry3D.h b/include/astra/ProjectionGeometry3D.h index 19ac3ab..0b60287 100644 --- a/include/astra/ProjectionGeometry3D.h +++ b/include/astra/ProjectionGeometry3D.h @@ -317,9 +317,24 @@ public: * @param iAngleIndex the index of the angle to use * @param fU,fV the projected point. */ - virtual void projectPoint(float32 fX, float32 fY, float32 fZ, + virtual void projectPoint(double fX, double fY, double fZ, int iAngleIndex, - float32 &fU, float32 &fV) const = 0; + double &fU, double &fV) const = 0; + + /* Backproject a point onto a plane parallel to a coordinate plane. + * The 2D point coordinates are the (unrounded) indices of the detector + * column and row. The output is in 3D coordinates in units. + * are in units. The output fU,fV are the (unrounded) indices of the + * detector column and row. + * This may fall outside of the actual detector. + */ + virtual void backprojectPointX(int iAngleIndex, double fU, double fV, + double fX, double &fY, double &fZ) const = 0; + virtual void backprojectPointY(int iAngleIndex, double fU, double fV, + double fY, double &fX, double &fZ) const = 0; + virtual void backprojectPointZ(int iAngleIndex, double fU, double fV, + double fZ, double &fX, double &fY) const = 0; + /** Returns true if the type of geometry defined in this class is the one specified in _sType. * -- cgit v1.2.3 From 81e7385c110a6210d0f9bc402df522301ec162f6 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Fri, 4 Dec 2015 15:14:19 +0100 Subject: Add utility functions for creating FP/BP JobLists --- include/astra/CompositeGeometryManager.h | 2 + src/CompositeGeometryManager.cpp | 113 ++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 2 deletions(-) (limited to 'include/astra') diff --git a/include/astra/CompositeGeometryManager.h b/include/astra/CompositeGeometryManager.h index a6e57f1..6610151 100644 --- a/include/astra/CompositeGeometryManager.h +++ b/include/astra/CompositeGeometryManager.h @@ -136,6 +136,8 @@ public: bool doBP(CProjector3D *pProjector, CFloat32VolumeData3DMemory *pVolData, CFloat32ProjectionData3DMemory *pProjData); + bool doFP(CProjector3D *pProjector, const std::vector& volData, const std::vector& projData); + bool doBP(CProjector3D *pProjector, const std::vector& volData, const std::vector& projData); protected: diff --git a/src/CompositeGeometryManager.cpp b/src/CompositeGeometryManager.cpp index fc8bc2e..9be4797 100644 --- a/src/CompositeGeometryManager.cpp +++ b/src/CompositeGeometryManager.cpp @@ -102,7 +102,6 @@ bool CCompositeGeometryManager::splitJobs(TJobSet &jobs, size_t maxSize, int div i_out != splitOutput.end(); ++i_out) { boost::shared_ptr outputPart = *i_out; - split[outputPart.get()] = TJobList(); SJob newjob; newjob.pOutput = outputPart; @@ -319,7 +318,7 @@ static size_t computeVerticalSplit(size_t maxBlock, int div, size_t sliceCount) // (This can't make the blocks larger) blockSize = ceildiv(sliceCount, blockCount); - ASTRA_DEBUG("%ld %ld -> %ld * %ld\n", sliceCount, maxBlock, blockCount, blockSize); + ASTRA_DEBUG("%ld %ld -> %ld * %ld", sliceCount, maxBlock, blockCount, blockSize); assert(blockSize <= maxBlock); assert((divCount * divCount > sliceCount) || (blockCount % div) == 0); @@ -725,6 +724,116 @@ bool CCompositeGeometryManager::doBP(CProjector3D *pProjector, CFloat32VolumeDat return doJobs(L); } +bool CCompositeGeometryManager::doFP(CProjector3D *pProjector, const std::vector& volData, const std::vector& projData) +{ + ASTRA_DEBUG("CCompositeGeometryManager::doFP, multi-volume"); + + std::vector::const_iterator i; + std::vector > inputs; + + for (i = volData.begin(); i != volData.end(); ++i) { + CVolumePart *input = new CVolumePart(); + input->pData = *i; + input->subX = 0; + input->subY = 0; + input->subZ = 0; + input->pGeom = (*i)->getGeometry()->clone(); + + inputs.push_back(boost::shared_ptr(input)); + } + + std::vector::const_iterator j; + std::vector > outputs; + + for (j = projData.begin(); j != projData.end(); ++j) { + CProjectionPart *output = new CProjectionPart(); + output->pData = *j; + output->subX = 0; + output->subY = 0; + output->subZ = 0; + output->pGeom = (*j)->getGeometry()->clone(); + + outputs.push_back(boost::shared_ptr(output)); + } + + std::vector >::iterator i2; + std::vector >::iterator j2; + TJobList L; + + for (i2 = outputs.begin(); i2 != outputs.end(); ++i2) { + SJob FP; + FP.eMode = SJob::MODE_SET; + for (j2 = inputs.begin(); j2 != inputs.end(); ++j2) { + FP.pInput = *j2; + FP.pOutput = *i2; + FP.pProjector = pProjector; + FP.eType = SJob::JOB_FP; + L.push_back(FP); + + // Set first, add rest + FP.eMode = SJob::MODE_ADD; + } + } + + return doJobs(L); +} + +bool CCompositeGeometryManager::doBP(CProjector3D *pProjector, const std::vector& volData, const std::vector& projData) +{ + ASTRA_DEBUG("CCompositeGeometryManager::doBP, multi-volume"); + + + std::vector::const_iterator i; + std::vector > outputs; + + for (i = volData.begin(); i != volData.end(); ++i) { + CVolumePart *output = new CVolumePart(); + output->pData = *i; + output->subX = 0; + output->subY = 0; + output->subZ = 0; + output->pGeom = (*i)->getGeometry()->clone(); + + outputs.push_back(boost::shared_ptr(output)); + } + + std::vector::const_iterator j; + std::vector > inputs; + + for (j = projData.begin(); j != projData.end(); ++j) { + CProjectionPart *input = new CProjectionPart(); + input->pData = *j; + input->subX = 0; + input->subY = 0; + input->subZ = 0; + input->pGeom = (*j)->getGeometry()->clone(); + + inputs.push_back(boost::shared_ptr(input)); + } + + std::vector >::iterator i2; + std::vector >::iterator j2; + TJobList L; + + for (i2 = outputs.begin(); i2 != outputs.end(); ++i2) { + SJob BP; + BP.eMode = SJob::MODE_SET; + for (j2 = inputs.begin(); j2 != inputs.end(); ++j2) { + BP.pInput = *j2; + BP.pOutput = *i2; + BP.pProjector = pProjector; + BP.eType = SJob::JOB_BP; + L.push_back(BP); + + // Set first, add rest + BP.eMode = SJob::MODE_ADD; + } + } + + return doJobs(L); +} + + bool CCompositeGeometryManager::doJobs(TJobList &jobs) -- cgit v1.2.3