mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 22:49:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
|
||||
*-----------------------------------------------------------------------*
|
||||
| |
|
||||
| Except where otherwise noted, this work is licensed under a |
|
||||
| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
| International (CC BY-NC-SA 4.0) license. |
|
||||
| |
|
||||
| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
| |
|
||||
| Author: CXS group, PSI |
|
||||
*-----------------------------------------------------------------------*
|
||||
You may use this code with the following provisions:
|
||||
|
||||
If the code is fully or partially redistributed, or rewritten in another
|
||||
computing language this notice should be included in the redistribution.
|
||||
|
||||
If this code, or subfunctions or parts of it, is used for research in a
|
||||
publication or if it is fully or partially rewritten for another
|
||||
computing language the authors and institution should be acknowledged
|
||||
in written form in the publication: “Data processing was carried out
|
||||
using the “cSAXS matlab package” developed by the CXS group,
|
||||
Paul Scherrer Institut, Switzerland.”
|
||||
Variations on the latter text can be incorporated upon discussion with
|
||||
the CXS group if needed to more specifically reflect the use of the package
|
||||
for the published work.
|
||||
|
||||
A publication that focuses on describing features, or parameters, that
|
||||
are already existing in the code should be first discussed with the
|
||||
authors.
|
||||
|
||||
This code and subroutines are part of a continuous development, they
|
||||
are provided “as they are” without guarantees or liability on part
|
||||
of PSI or the authors. It is the user responsibility to ensure its
|
||||
proper use and the correctness of the results.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// Defines the exported functions for the DLL application.
|
||||
//
|
||||
// recompile commands
|
||||
// (Linux, GCC 4.8.5) mexcuda -outdir private ASTRA_GPU_wrapper/ASTRA_GPU_wrapper.cu ASTRA_GPU_wrapper/util3d.cu ASTRA_GPU_wrapper/par3d_fp.cu ASTRA_GPU_wrapper/par3d_bp.cu
|
||||
// (Windows) mexcuda -outdir private ASTRA_GPU_wrapper\ASTRA_GPU_wrapper.cu ASTRA_GPU_wrapper\util3d.cu ASTRA_GPU_wrapper\par3d_fp.cu ASTRA_GPU_wrapper\par3d_bp.cu
|
||||
|
||||
/************* INPUTS *****************************/
|
||||
/*
|
||||
string 'fp' or 'bp' - forward / backward projection
|
||||
single gpuArray volume or data object
|
||||
struct cfg - contain configuration for astra, created by ASTRA_initialize.m
|
||||
double array vec - contain projection geometry for astra, created by ASTRA_initialize.m
|
||||
(optional)
|
||||
single gpuArray - volume or data object to write the results to
|
||||
*/
|
||||
|
||||
|
||||
#include "cuda_runtime.h"
|
||||
#include "device_launch_parameters.h"
|
||||
#include <cuda.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
|
||||
#include "mex.h"
|
||||
#include "gpu/mxGPUArray.h"
|
||||
|
||||
#include "util3d.h"
|
||||
#include "dims3d.h"
|
||||
#include "par3d_bp.h"
|
||||
#include "par3d_fp.h"
|
||||
|
||||
|
||||
|
||||
void mexFunction(int nlhs, mxArray *plhs[],
|
||||
int nrhs, mxArray const *prhs[])
|
||||
{
|
||||
|
||||
//mexPrintf("Warning: loading development version of ASTRA\n");
|
||||
//mexPrintf("Ninputs:%i\n", nrhs);
|
||||
|
||||
if (!((nrhs == 4) || (nrhs == 5) || (nrhs == 8 ) || (nrhs == 11 ) ))
|
||||
mexErrMsgTxt("4,5, 8, or 11 input arguments required");
|
||||
|
||||
|
||||
using namespace astraCUDA3d;
|
||||
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
|
||||
char const * const errMsg = "Invalid input to MEX file.";
|
||||
|
||||
|
||||
/* Throw an error if the input is not a GPU array. */
|
||||
if (!mxIsGPUArray(prhs[1])) {
|
||||
mexErrMsgIdAndTxt(errId, "The second input must be GPU array");
|
||||
}
|
||||
|
||||
|
||||
/* Load configuration */
|
||||
SDimensions3D dims;
|
||||
mxArray * tmp;
|
||||
double * val;
|
||||
#define SETVAR(name) do {tmp = mxGetField(prhs[2], 0, ""#name""); if (tmp!=NULL) { val = mxGetPr(tmp); dims.name = (unsigned int)val[0]; }} while (0);
|
||||
SETVAR(iVolX);
|
||||
SETVAR(iVolY);
|
||||
SETVAR(iVolZ);
|
||||
SETVAR(iProjAngles);
|
||||
SETVAR(iProjU);
|
||||
SETVAR(iProjV);
|
||||
SETVAR(iRaysPerDetDim);
|
||||
SETVAR(iRaysPerVoxelDim);
|
||||
#undef SETVAR
|
||||
|
||||
|
||||
/* Initialize the MathWorks GPU API. */
|
||||
mxInitGPU();
|
||||
|
||||
|
||||
/* load confuguration of angles */
|
||||
double * my_angles = mxGetPr(prhs[3]);
|
||||
int Nangles = (int)mxGetM(prhs[3]);
|
||||
SPar3DProjection* angle = new SPar3DProjection[Nangles];
|
||||
|
||||
#define SETVAR(name,i,j) do { angle[i].name = my_angles[i+j*Nangles]; } while (0);
|
||||
for (int i = 0; i < Nangles; i++)
|
||||
{
|
||||
SETVAR(fRayX, i, 0);
|
||||
SETVAR(fRayY, i, 1);
|
||||
SETVAR(fRayZ, i, 2);
|
||||
SETVAR(fDetSX, i, 3);
|
||||
SETVAR(fDetSY, i, 4);
|
||||
SETVAR(fDetSZ, i, 5);
|
||||
SETVAR(fDetUX, i, 6);
|
||||
SETVAR(fDetUY, i, 7);
|
||||
SETVAR(fDetUZ, i, 8);
|
||||
SETVAR(fDetVX, i, 9);
|
||||
SETVAR(fDetVY, i, 10);
|
||||
SETVAR(fDetVZ, i, 11);
|
||||
// mexPrintf("---------------------- \n");
|
||||
}
|
||||
#undef SETVAR
|
||||
|
||||
|
||||
char * task = mxArrayToString(prhs[0]);
|
||||
|
||||
//mexPrintf("--------- Task %s \n ", task);
|
||||
|
||||
|
||||
/* Load input data */
|
||||
mxGPUArray const * m_data = mxGPUCreateFromMxArray(prhs[1]);
|
||||
if ((mxGPUGetClassID(m_data) != mxSINGLE_CLASS)) {
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
float * p_data = (float *)mxGPUGetDataReadOnly(m_data);
|
||||
|
||||
DeformField DF;
|
||||
if (nrhs == 8 || nrhs == 11 ) {
|
||||
/* load deformation field */
|
||||
DF.use_deform = true;
|
||||
DF.use_linear_model = false; // assume contant deformation
|
||||
DF.X0 = mxGPUCreateFromMxArray(prhs[5]);
|
||||
DF.Y0 = mxGPUCreateFromMxArray(prhs[6]);
|
||||
DF.Z0 = mxGPUCreateFromMxArray(prhs[7]);
|
||||
if ((mxGPUGetClassID(DF.X0) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(DF.Y0) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(DF.Z0) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("wrong input type: deformation fields has to be single\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
if (nrhs == 11 ) {
|
||||
DF.use_linear_model = true; // assume linear deformation
|
||||
DF.X1 = mxGPUCreateFromMxArray(prhs[8]);
|
||||
DF.Y1 = mxGPUCreateFromMxArray(prhs[9]);
|
||||
DF.Z1 = mxGPUCreateFromMxArray(prhs[10]);
|
||||
if ((mxGPUGetClassID(DF.X1) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(DF.Y1) != mxSINGLE_CLASS) |
|
||||
(mxGPUGetClassID(DF.Z1) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("wrong input type: deformation fields has to be single\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
DF.use_deform = false;
|
||||
|
||||
|
||||
|
||||
if (strcmp(task, "fp")==0)
|
||||
{
|
||||
//mexPrintf(" forward projection \n ");
|
||||
|
||||
/* make volume array (no copying) */
|
||||
cudaPitchedPtr volData;
|
||||
volData.ptr = p_data;
|
||||
volData.pitch = dims.iVolX * sizeof(float);
|
||||
volData.xsize = dims.iVolX;
|
||||
volData.ysize = dims.iVolY;
|
||||
|
||||
|
||||
mxGPUArray * m_projData;
|
||||
if(nrhs >= 5 && !mxIsEmpty(prhs[4]) )
|
||||
{
|
||||
/**** copy of the array is the slow operation and also GPU memory is limited *****/
|
||||
// m_projData = mxGPUCopyFromMxArray(prhs[4]);
|
||||
|
||||
/* Use ugly trick to write directly to the provided GPU array ...
|
||||
=> Now it is writting directly into the input field !!! DANGEROUS */
|
||||
|
||||
m_projData = const_cast<mxGPUArray*>(mxGPUCreateFromMxArray(prhs[4]));
|
||||
if ((mxGPUGetClassID(m_projData) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("m_projData\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
const mwSize * projSize = mxGPUGetDimensions(m_projData);
|
||||
|
||||
if (dims.iProjU != projSize[0] ||
|
||||
dims.iProjV != projSize[1] ||
|
||||
dims.iProjAngles != projSize[2])
|
||||
mexErrMsgIdAndTxt(errId, "Wrong size of the inputs array");
|
||||
|
||||
//mexPrintf("Writting directly to the input array\n\n");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* allocate projection field */
|
||||
int const Ndim = 3;
|
||||
mwSize projSize[3];
|
||||
projSize[0] = (mwSize)dims.iProjU;
|
||||
projSize[1] = (mwSize)dims.iProjV;
|
||||
projSize[2] = (mwSize)dims.iProjAngles;
|
||||
m_projData = mxGPUCreateGPUArray(Ndim,
|
||||
projSize,
|
||||
mxSINGLE_CLASS,
|
||||
mxREAL,
|
||||
MX_GPU_INITIALIZE_VALUES);
|
||||
}
|
||||
|
||||
/* make cudaPitchedPtr for projection field */
|
||||
cudaPitchedPtr projData;
|
||||
projData.ptr = (float *)mxGPUGetData(m_projData);
|
||||
projData.pitch = dims.iProjU * sizeof(float);
|
||||
projData.xsize = dims.iProjU;
|
||||
projData.ysize = dims.iProjV;
|
||||
|
||||
//mexPrintf("astraCUDA3d::Par3DFP \n ") ;
|
||||
astraCUDA3d::Par3DFP(volData, projData, dims, angle, 1.0f, DF);
|
||||
checkLastError("After Projector");
|
||||
|
||||
|
||||
/* Wrap the result up as a MATLAB gpuArray for return. */
|
||||
if (nlhs > 0)
|
||||
plhs[0] = mxGPUCreateMxArrayOnGPU(m_projData);
|
||||
mxGPUDestroyGPUArray(m_projData);
|
||||
mxGPUDestroyGPUArray(m_data);
|
||||
|
||||
|
||||
}
|
||||
else if (strcmp(task, "bp")==0)
|
||||
{
|
||||
//mexPrintf(" backward projection \n ");
|
||||
|
||||
|
||||
/* make projection field (no copying) */
|
||||
cudaPitchedPtr projData;
|
||||
projData.ptr = p_data;
|
||||
projData.pitch = dims.iProjU * sizeof(float);
|
||||
projData.xsize = dims.iProjU;
|
||||
projData.ysize = dims.iProjAngles;
|
||||
mxGPUArray* m_volData;
|
||||
if(nrhs >= 5 && !mxIsEmpty(prhs[4]) )
|
||||
{
|
||||
/**** copy of the array is the slow operation and also GPU memory is limited *****/
|
||||
// m_volData = mxGPUCopyFromMxArray(prhs[4]);
|
||||
|
||||
/* Use ugly trick to write directly to the provided GPU array ...
|
||||
=> Now it is writting directly into the input field !!! DANGEROUS */
|
||||
|
||||
m_volData = const_cast<mxGPUArray*>(mxGPUCreateFromMxArray(prhs[4]));
|
||||
if ((mxGPUGetClassID(m_volData) != mxSINGLE_CLASS)) {
|
||||
mexPrintf("m_volData\n");
|
||||
mexErrMsgIdAndTxt(errId, errMsg);
|
||||
}
|
||||
mwSize volSize[3];
|
||||
const mwSize * volSize0 = mxGPUGetDimensions(m_volData);
|
||||
if (mxGPUGetNumberOfDimensions(m_volData)==3) {
|
||||
volSize[0]=volSize0[0];
|
||||
volSize[1]=volSize0[1];
|
||||
volSize[2]=volSize0[2];
|
||||
} else {
|
||||
volSize[0]=volSize0[0];
|
||||
volSize[1]=volSize0[1];
|
||||
volSize[2]=1;
|
||||
}
|
||||
|
||||
|
||||
if (dims.iVolX != volSize[0] ||
|
||||
dims.iVolY != volSize[1] ||
|
||||
dims.iVolZ != volSize[2])
|
||||
mexErrMsgIdAndTxt(errId, "Wrong size of the inputs array");
|
||||
|
||||
} else {
|
||||
/* allocate volume data */
|
||||
int const Ndim = 3;
|
||||
mwSize volSize[3];
|
||||
volSize[0] = (mwSize)dims.iVolX;
|
||||
volSize[1] = (mwSize)dims.iVolY;
|
||||
volSize[2] = (mwSize)dims.iVolZ;
|
||||
m_volData = mxGPUCreateGPUArray(Ndim,
|
||||
volSize,
|
||||
mxSINGLE_CLASS,
|
||||
mxREAL,
|
||||
MX_GPU_INITIALIZE_VALUES);
|
||||
}
|
||||
|
||||
/* make volume array pointer*/
|
||||
cudaPitchedPtr volData;
|
||||
volData.ptr = (float *)mxGPUGetData(m_volData);
|
||||
volData.pitch = dims.iVolX * sizeof(float);
|
||||
volData.xsize = dims.iVolX;
|
||||
volData.ysize = dims.iVolY;
|
||||
|
||||
astraCUDA3d::Par3DBP(volData, projData, dims, angle, 1.0f, DF);
|
||||
checkLastError("After Projector");
|
||||
|
||||
|
||||
/* Wrap the result up as a MATLAB gpuArray for return. */
|
||||
if (nlhs > 0)
|
||||
plhs[0] = mxGPUCreateMxArrayOnGPU(m_volData);
|
||||
mxGPUDestroyGPUArray(m_volData);
|
||||
mxGPUDestroyGPUArray(m_data);
|
||||
|
||||
}
|
||||
else
|
||||
mexPrintf("No such option");
|
||||
|
||||
if (DF.use_deform) {
|
||||
//mexPrintf("Deleted DF");
|
||||
mxGPUDestroyGPUArray(DF.X0);
|
||||
mxGPUDestroyGPUArray(DF.Y0);
|
||||
mxGPUDestroyGPUArray(DF.Z0);
|
||||
if (DF.use_linear_model) {
|
||||
mxGPUDestroyGPUArray(DF.X1);
|
||||
mxGPUDestroyGPUArray(DF.Y1);
|
||||
mxGPUDestroyGPUArray(DF.Z1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user