initial commit

This commit is contained in:
2026-08-07 15:56:42 +09:00
commit 91ad25aca9
1012 changed files with 159314 additions and 0 deletions
@@ -0,0 +1,168 @@
/*
*
*
Academic License Agreement
Source Code
Introduction
• This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
Terms and Conditions of the LICENSE
1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
hereinafter set out and until termination of this license as set forth below.
2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
LICENSEEs responsibility to ensure its proper use and the correctness of the results.”
3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
"IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
in the commercial use, application or exploitation of works similar to the PROGRAM.
5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
another computing language:
"Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
Scherrer Institut, Switzerland."
Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
(doi: 10.1126/science.1158573),
for mixed coherent modes:
P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
for LSQ-ML method
M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
for OPRP method
M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
and/or for multislice:
E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
© All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
the courts of Zürich, Switzerland.
*
Compilation from Matlab:
maybe a tiny bit faster code is generated by
mex -O COPTIMFLAGS='-O2' LDOPTIMFLAGS='-O2' CFLAGS="\$CFLAGS -fopenmp" LDFLAGS="\$LDFLAGS -fopenmp" get_views_cpu_mex.cpp
Usage from Matlab:
get_views_cpu_mex(object,obj_proj,positions, ind_ok);
This code in matlab:
asize = size(probe);
for i=ind_ok
Indy = positions(i,1) + (1:asize(1));
Indx = positions(i,2) + (1:asize(2));
ob(Indy,Indx) = ob(Indy,Indx) + probe;
end
*/
#include "mex.h"
#include <math.h>
#include <stdio.h>
#include <omp.h>
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int i;
/* Check for proper number of arguments. */
if (nrhs != 4)
mexErrMsgTxt("Four input arguments required: get_views_cpu_mex(object,obj_proj,positions,ind_ok)");
else if (nlhs != 0)
mexErrMsgTxt("No output argument has to be specified.");
/* Input must be of type single. */
for (i=0; i < 2; i++) {
if (mxIsSingle(prhs[i]) != 1){
printf(" Input %d is not single\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
/* Input must be of type int32. */
for (i=2; i<nrhs; i++){
if (mxIsInt32(prhs[i]) != 1){
printf("Input %d is not integer\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
/* It cannot be one-dimensional */
if(mxGetNumberOfDimensions(prhs[0]) < 2) {
printf("The 1st input argument must have at least two dimensions.");
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
}
/* It cannot be more than 3-dimensional */
if(mxGetNumberOfDimensions(prhs[0]) > 3) {
printf("The 1st input argument must have at most three dimensions.");
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
}
/* Check that arrays are complex */
if(mxIsComplex(prhs[0]) != 1) {
printf("object input argument must be complex-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
}
if(mxIsComplex(prhs[1]) != 1) {
printf("probe input argument must be complex-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
}
float *object_r, *object_i, *projection_r,*projection_i;
const int *positions;
positions = (int*)mxGetData(prhs[2]);
object_r = (float*)mxGetData(prhs[0]);
projection_r = (float*)mxGetData(prhs[1]);
/* get pointers to input data */
object_i = (float*)mxGetImagData(prhs[0]);
projection_i = (float*)mxGetImagData(prhs[1]);
/* Get dimension of probe and object */
const mwSize Ndims = mxGetNumberOfDimensions(prhs[1]);
const mwSize * dims = mxGetDimensions(prhs[1]);
const mwSize No_y = mxGetM(prhs[0]);
const mwSize No_x = mxGetN(prhs[0]);
const mwSize Np_y = dims[0];
const mwSize Np_x = dims[1];
const mwSize Npos = mxGetM(prhs[2]);
if((Npos > dims[2])) {
printf("wrong size of update / positions %i", Ndims);
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
}
mwSize id_small, id_large, pos, col, row;
#pragma omp parallel for private(pos,col, row, id_small, id_large)
for (pos=0;pos<Npos;pos++){
for (col=0;col<Np_x;col++) {
for (row=0;row<Np_y;row++) {
id_small = row + col*Np_y + Np_y*Np_x*pos;
id_large = row + positions[pos] + (col+positions[pos+Npos])*No_y;
projection_r[id_small] = object_r[id_large];
projection_i[id_small] = object_i[id_large];
}
}
}
return;
}
@@ -0,0 +1,260 @@
/*
Get complex views from complex object
mexcuda -output +engines/+GPU/+shared/private/get_views_gpu_mex +engines/+GPU/+shared/private/get_views_gpu_mex.cu
*/
#include "mex.h"
#include "gpu/mxGPUArray.h"
#include <math.h>
#include <stdio.h>
typedef const unsigned int cuint;
typedef const uint16_T cuint16;
// unfortunatelly ~10800 is the maximum of const memory
const unsigned int MAX_IND_READ = 10800;
__constant__ uint16_T gC_ind_read[MAX_IND_READ];
__constant__ uint16_T gC_pos_X[MAX_IND_READ];
__constant__ uint16_T gC_pos_Y[MAX_IND_READ];
#define MAX(x,y) (x>y?x:y);
#define MIN(x,y) (x<y?x:y);
#define ABS(x) (x>0?x:-x);
int checkLastError(char * msg)
{
cudaError_t cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
char err[512];
sprintf(err, "getprojection failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
mexPrintf(err);
return 1;
}
return 0;
}
/*
* Device code
*/
/*********** fast const memory based version ***************/
__global__ void readFromArray_c_fast(float2 * sarray, const float2 * larray,
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
cuint Npos) {
// Location in a 3D matrix
int idx= blockIdx.x * blockDim.x + threadIdx.x;
int idy= blockIdx.y * blockDim.y + threadIdx.y;
int id = blockIdx.z * blockDim.z + threadIdx.z;
if ( idx < Np_px & idy < Np_py & id < Npos)
{
int idz = gC_ind_read[id]-1; // go only through some of the indices
int id_large = gC_pos_X[idz]+idx + Np_ox*(gC_pos_Y[idz]+idy);
int id_small = idx + Np_px*idy + Np_px*Np_py*idz ;
sarray[ id_small ].x = larray[ id_large ].x ;
sarray[ id_small ].y = larray[ id_large ].y ;
}
}
/*********** global memory based version ***************/
__global__ void readFromArray_c(float2 * sarray, const float2 * larray, cuint16* ind_read, cuint16* pos_X, cuint16* posY,
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
cuint Npos) {
// Location in a 3D matrix
int idx= blockIdx.x * blockDim.x + threadIdx.x;
int idy= blockIdx.y * blockDim.y + threadIdx.y;
int id = blockIdx.z * blockDim.z + threadIdx.z;
if ( idx < Np_px & idy < Np_py & id < Npos)
{
int idz = ind_read[id]-1; // go only through some of the indices
int id_large = pos_X[idz]+idx + Np_ox*(posY[idz]+idy);
int id_small = idx + Np_px*idy + Np_px*Np_py*idz ;
sarray[ id_small ].x = larray[ id_large ].x ;
sarray[ id_small ].y = larray[ id_large ].y ;
}
}
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int i ;
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
char const * const errMsg = "Invalid input to MEX file.";
/* Initialize the MathWorks GPU API. */
//mxInitGPU();
/* Check for proper number of arguments. */
if (nrhs != 5)
mexErrMsgTxt("Five input arguments required");
for (i=0; i < 2; i++) {
if ( !mxIsGPUArray(prhs[i]) && !mxIsCell(prhs[i]) ){
printf("Input %d is not GPU array / cell \n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
// load positions
const mxGPUArray * m_positions_x = mxGPUCreateFromMxArray(prhs[2]);
if ((mxGPUGetClassID(m_positions_x) != mxUINT16_CLASS)) {
mexPrintf("m_positions_x\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const cuint16 * p_positions_x = (cuint16 *)mxGPUGetDataReadOnly(m_positions_x);
const mxGPUArray * m_positions_y = mxGPUCreateFromMxArray(prhs[3]);
if ((mxGPUGetClassID(m_positions_y) != mxUINT16_CLASS)) {
mexPrintf("m_positions_y\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const cuint16 * p_positions_y = (cuint16 *)mxGPUGetDataReadOnly(m_positions_y);
/**** copy of the array is the slowest operation *****/
// Now it is writting directly into the input field !!!
//mxGPUArray * m_obj_proj = mxGPUCopyFromMxArray(prhs[0]);
mxGPUArray * m_obj_proj = const_cast<mxGPUArray*>(mxGPUCreateFromMxArray(prhs[0])); //
if ((mxGPUGetClassID(m_obj_proj) != mxSINGLE_CLASS)) {
mexPrintf("m_obj_proj\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
if (mxGPUGetComplexity(m_obj_proj) != mxCOMPLEX) {
mexPrintf("m_obj_proj is not complex \n");
mexErrMsgIdAndTxt(errId, errMsg);
}
float2 * p_obj_proj = (float2 *)mxGPUGetData(m_obj_proj);
if (!mxIsCell(prhs[1]) || !mxIsCell(prhs[4]))
mexErrMsgIdAndTxt("MexError:ptycho","Object and indices has to be in cell/cells !! ");
if (mxGetNumberOfElements(prhs[1]) != mxGetNumberOfElements(prhs[4]))
mexErrMsgIdAndTxt("MexError:ptycho","Number of objects != number of indices ");
/* Get dimension of probe and object */
const unsigned int Ndims = (unsigned int)mxGPUGetNumberOfDimensions(m_obj_proj);
cuint Ncells = mxGetNumberOfElements(prhs[1]);
const unsigned int Np_pp = mxGPUGetNumberOfElements(m_positions_x);
if (Np_pp < MAX_IND_READ) {
cudaMemcpyToSymbol(gC_pos_X, p_positions_x, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
cudaMemcpyToSymbol(gC_pos_Y, p_positions_y, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
checkLastError("after cudaMemcpyToSymbol pos");
}
for (int l=0; l<Ncells; l++)
{
// read the cell content
mxArray * mx_object = mxGetCell(prhs[1],l);
mxArray * mx_ind = mxGetCell(prhs[4],l);
int N_ok = mxGetNumberOfElements(mx_ind);
if(N_ok == 0)
continue;
const mxGPUArray * m_object = mxGPUCreateFromMxArray(mx_object);
if ((mxGPUGetClassID(m_object) != mxSINGLE_CLASS)) {
mexPrintf("m_object\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
if (mxGPUGetComplexity(m_object) != mxCOMPLEX) {
mexPrintf("m_object is not complex \n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const float2 * p_object = (float2 *)mxGPUGetDataReadOnly(m_object);
const mxGPUArray * m_ind_ok = mxGPUCreateFromMxArray(mx_ind);
if ((mxGPUGetClassID(m_ind_ok) != mxUINT16_CLASS)) {
mexPrintf("m_ind_ok\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const cuint16 * p_ind_ok = (cuint16 *)mxGPUGetDataReadOnly(m_ind_ok);
const mwSize * Np_o = mxGPUGetDimensions(m_object);
const mwSize * Np_p = mxGPUGetDimensions(m_obj_proj);
const unsigned int Npos = mxGPUGetNumberOfElements(m_ind_ok);
// mexPrintf("Ndims %i Np_o %i %i Np_p %i %i %i Npos %i \n " ,Ndims,Np_o[0],Np_o[1],Np_p[0],Np_p[1],Np_p[2],Npos);
if (Ndims == 3 && Npos > Np_p[2]) {
printf("wrong size of update / positions %i", Ndims);
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
}
// Choose a reasonably sized number of threads in each dimension for the block.
int const threadsPerBlockEachDim = 32;
// Compute the thread block and grid sizes based on the board dimensions.
int const blocksPerGrid_M = (Np_p[0] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
int const blocksPerGrid_N = (Np_p[1] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
int const blocksPerGrid_O = Npos;
// mexPrintf("Threads %i %i %i \n ", blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
dim3 const dimBlock(blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
dim3 const dimThread(threadsPerBlockEachDim, threadsPerBlockEachDim, 1);
checkLastError("after dimThread");
//mexPrintf("Blocks %i %i %i \n ", dimThread.x, dimThread.y, dimThread.z);
if (Np_pp > MAX_IND_READ) {
//mexPrintf( "More than %i positions may be slow \n", MAX_IND_READ);
} else {
cudaMemcpyToSymbol(gC_ind_read, p_ind_ok, Npos*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
checkLastError("after cudaMemcpyToSymbol pos");
}
checkLastError("after cudaMemcpyToSymbol");
//============= run the kernel ======================
if (Npos < MAX_IND_READ)
readFromArray_c_fast<<<dimBlock, dimThread>>>(p_obj_proj,p_object, Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos);
else
readFromArray_c<<<dimBlock, dimThread>>>(p_obj_proj,p_object,p_ind_ok, p_positions_x,p_positions_y,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos);
checkLastError("after kernel");
mxGPUDestroyGPUArray(m_object);
mxGPUDestroyGPUArray(m_ind_ok);
}
cudaThreadSynchronize();
// plhs[0] = mxGPUCreateMxArrayOnGPU(m_obj_proj);
mxGPUDestroyGPUArray(m_obj_proj);
mxGPUDestroyGPUArray(m_positions_x);
mxGPUDestroyGPUArray(m_positions_y);
return;
}
@@ -0,0 +1,193 @@
/*
*
*Academic License Agreement
Source Code
Introduction
• This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
Terms and Conditions of the LICENSE
1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
hereinafter set out and until termination of this license as set forth below.
2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
LICENSEEs responsibility to ensure its proper use and the correctness of the results.”
3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
"IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
in the commercial use, application or exploitation of works similar to the PROGRAM.
5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
another computing language:
"Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
Scherrer Institut, Switzerland."
Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
(doi: 10.1126/science.1158573),
for mixed coherent modes:
P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
for LSQ-ML method
M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
for OPRP method
M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
and/or for multislice:
E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
© All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
the courts of Zürich, Switzerland.
*
*
Compilation from Matlab:
maybe a tiny bit faster code is generated by
mex -O COPTIMFLAGS='-O2' LDOPTIMFLAGS='-O2' set_views_cpu_mex.c
Usage from Matlab:
set_views_cpu_mex(probe,object,positions, Npos);
This code in matlab:
asize = size(probe);
for i=1:Npos
Indy = positions(i,1) + (1:asize(1));
Indx = positions(i,2) + (1:asize(2));
ob(Indy,Indx) = ob(Indy,Indx) + probe;
end
*/
#include "mex.h"
#include <math.h>
#include <stdio.h>
#include <omp.h>
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int i;
/* Check for proper number of arguments. */
if (nrhs != 4)
mexErrMsgTxt("Four input arguments required: set_views_cpu_mex(probe,object,positions,Npos)");
else if (nlhs != 0)
mexErrMsgTxt("No output argument has to be specified.");
/* Input must be of type single. */
for (i=0; i < 2; i++) {
if (mxIsSingle(prhs[i]) != 1){
printf("Input %d is not single\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
/* Input must be of type int32. */
for (i=2; i<nrhs; i++){
if (mxIsInt32(prhs[i]) != 1){
printf("Input %d is not integer\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
/* It cannot be one-dimensional */
if(mxGetNumberOfDimensions(prhs[0]) < 2) {
printf("The 1st input argument must have at least two dimensions.");
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
}
/* It cannot be more than 3-dimensional */
if(mxGetNumberOfDimensions(prhs[0]) > 3) {
printf("The 1st input argument must have at most three dimensions.");
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
}
// /* Check that arrays are complex */
// if(mxIsComplex(prhs[0]) != 1) {
// printf("object input argument must be complex-valued.");
// mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
// }
// if(mxIsComplex(prhs[1]) != 1) {
// printf("probe input argument must be complex-valued.");
// mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
// }
float *object_r, *object_i, *probe_r,*probe_i;
const int *positions, *ind_ok;
bool cprobe, cobject;
cobject = mxIsComplex(prhs[0]);
cprobe = mxIsComplex(prhs[1]);
if( cobject != cobject)
{
printf("probe/object input argument must be complex/real-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected both complex / real arrays");
}
ind_ok = (int*)mxGetData(prhs[3]);
positions = (int*)mxGetData(prhs[2]);
object_r = (float*)mxGetData(prhs[0]);
probe_r = (float*)mxGetData(prhs[1]);
if(cprobe)
{
/* get pointers to input data */
object_i = (float*)mxGetImagData(prhs[0]);
probe_i = (float*)mxGetImagData(prhs[1]);
}
/* Get dimension of probe and object */
const mwSize Ndims = mxGetNumberOfDimensions(prhs[1]);
const mwSize * dims = mxGetDimensions(prhs[1]);
const mwSize No_y = mxGetM(prhs[0]);
const mwSize No_x = mxGetN(prhs[0]);
const mwSize Np_y = dims[0];
const mwSize Np_x = dims[1];
const mwSize Npos = mxGetM(prhs[2]);
if((mxGetM(prhs[2]) != dims[2]) && (Ndims == 3)) {
printf("wrong size of update / positions %i", Ndims);
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
}
mwSize id_small, id_large, pos, col, row, o, p;
bool flat_probe = Ndims == 2;
#pragma omp parallel for private(p,pos, col, row, id_small, id_large)
for (p=0;p<Npos;p++){
pos = ind_ok[p]-1;
for (col=0;col<Np_x;col++) {
for (row=0;row<Np_y;row++) {
if(flat_probe)
id_small = row + col*Np_y;
else
id_small = row + col*Np_y + Np_y*Np_x*pos;
id_large = row + positions[pos] + (col+positions[pos+Npos])*No_y;
#pragma omp atomic
object_r[id_large] += probe_r[id_small];
if(cprobe)
#pragma omp atomic
object_i[id_large] += probe_i[id_small];
}
}
}
return;
}
@@ -0,0 +1,182 @@
/*
*
*Academic License Agreement
Source Code
Introduction
• This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
Terms and Conditions of the LICENSE
1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
hereinafter set out and until termination of this license as set forth below.
2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
LICENSEEs responsibility to ensure its proper use and the correctness of the results.”
3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
"IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
in the commercial use, application or exploitation of works similar to the PROGRAM.
5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
another computing language:
"Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
Scherrer Institut, Switzerland."
Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
(doi: 10.1126/science.1158573),
for mixed coherent modes:
P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
for LSQ-ML method
M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
for OPRP method
M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
and/or for multislice:
E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
© All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
the courts of Zürich, Switzerland.
*
*
Compilation from Matlab:
maybe a tiny bit faster code is generated by
mex -O COPTIMFLAGS='-O2' LDOPTIMFLAGS='-O2' set_views_cpu_mex_rc.cpp
Usage from Matlab:
set_views_cpu_mex(probe,object,positions, Npos);
This code in matlab:
asize = size(probe);
for i=1:Npos
Indy = positions(i,1) + (1:asize(1));
Indx = positions(i,2) + (1:asize(2));
ob(Indy,Indx) = ob(Indy,Indx) + probe;
end
*/
#include "mex.h"
#include <math.h>
#include <stdio.h>
#include <omp.h>
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int i;
/* Check for proper number of arguments. */
if (nrhs != 6)
mexErrMsgTxt("Six input arguments required: set_views_cpu_mex_rc(object,obj_upd, illum, illum_upd, positions,ind_ok)");
else if (nlhs != 0)
mexErrMsgTxt("No output argument has to be specified.");
/* Input must be of type single. */
for (i=0; i < 4; i++) {
if (mxIsSingle(prhs[i]) != 1){
printf("Input %d is not single\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
/* Input must be of type int32. */
for (i=4; i<nrhs; i++){
if (mxIsInt32(prhs[i]) != 1){
printf("Input %d is not integer\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
/* Check that arrays are complex */
if(mxIsComplex(prhs[0]) != 1) {
printf("first input argument must be complex-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
}
if(mxIsComplex(prhs[1]) == 1) {
printf("second input argument must be real-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected real arrays");
}
if(mxIsComplex(prhs[2]) != 1) {
printf("third input argument must be complex-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected complex arrays");
}
if(mxIsComplex(prhs[3]) == 1) {
printf("fourth input argument must be real-valued.");
mexErrMsgIdAndTxt("MexError:ptycho","Expected real arrays");
}
float *object_r, *object_i, *probe_r,*probe_i, *illum_r, *illum_upd;
const int *positions, *ind_ok;
bool cprobe, cobject;
positions = (int*)mxGetData(prhs[4]);
ind_ok = (int*)mxGetData(prhs[5]);
object_r = (float*)mxGetData(prhs[0]);
object_i = (float*)mxGetImagData(prhs[0]);
illum_r = (float*)mxGetData(prhs[1]);
probe_r = (float*)mxGetData(prhs[2]);
probe_i = (float*)mxGetImagData(prhs[2]);
illum_upd = (float*)mxGetData(prhs[3]);
/* Get dimension of probe and object */
const mwSize Ndims = mxGetNumberOfDimensions(prhs[2]);
const mwSize * dims = mxGetDimensions(prhs[2]);
const mwSize No_y = mxGetM(prhs[0]);
const mwSize No_x = mxGetN(prhs[0]);
const mwSize Np_y = dims[0];
const mwSize Np_x = dims[1];
const mwSize Npos = mxGetNumberOfElements(prhs[5]);
if(mxGetM(prhs[4]) != dims[2]) {
printf("wrong size of update / positions %i", Ndims);
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
}
// mexPrintf("O %i %i P %i %i N %i \n ", No_y, No_x, Np_y, Np_x, Npos);
mwSize id_small, id_small_3D, id_large, pos, col, row, p;
#pragma omp parallel for private(p,pos, col, row, id_small,id_small_3D, id_large)
for (p=0;p<Npos;p++){
pos = ind_ok[p]-1;
for (col=0;col<Np_x;col++) {
for (row=0;row<Np_y;row++) {
id_small = row + col*Np_y;
id_small_3D = id_small + Np_y*Np_x*pos;
id_large = row + positions[pos] + (col+positions[pos+Npos])*No_y;
#pragma omp atomic
object_r[id_large] += probe_r[id_small_3D];
#pragma omp atomic
object_i[id_large] += probe_i[id_small_3D];
#pragma omp atomic
illum_r[id_large] += illum_upd[id_small];
}
}
}
return;
}
@@ -0,0 +1,303 @@
/*
Set complex views to complex object
mexcuda -output +engines/+GPU/+shared/private/set_views_gpu_mex +engines/+GPU/+shared/private/set_views_gpu_mex.cu
*/
#include "mex.h"
#include "gpu/mxGPUArray.h"
#include <math.h>
#include <stdio.h>
typedef const unsigned int cuint;
typedef const uint16_T cuint16;
// unfortunatelly ~10800 is the maximum of const memory
const unsigned int MAX_IND_READ = 10800;
static const unsigned MAX_IND_READ_DEV = MAX_IND_READ;
__constant__ uint16_T gC_ind_read[MAX_IND_READ_DEV];
__constant__ uint16_T gC_pos_X[MAX_IND_READ_DEV];
__constant__ uint16_T gC_pos_Y[MAX_IND_READ_DEV];
int checkLastError(char * msg)
{
cudaError_t cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
char err[512];
sprintf(err, "setprojection failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
mexPrintf(err);
return 1;
}
return 0;
}
/*
* Device code
*/
/*********** reduction of object projection array to single object ***************/
template <bool useGlobal>
__global__ void addToArray_r( float const * sarray, float * larray, cuint16* ind_read, cuint16* pos_X, cuint16* posY,
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
cuint Npos, const bool isFlat) {
// Location in a 3D matrix
int idx= blockIdx.x * blockDim.x + threadIdx.x;
int idy= blockIdx.y * blockDim.y + threadIdx.y;
if ( idx < Np_px & idy < Np_py ) {
int idz, id_large;
float sarray_val;
for(int id = 0; id < Npos; id++)
{
if (useGlobal) {
// fast const memory based version
idz = gC_ind_read[id]-1; // go only through some of the indices
id_large = gC_pos_X[idz]+idx + Np_ox*(gC_pos_Y[idz]+idy);
} else {
// slower global memory based version
idz = ind_read[id]-1; // go only through some of the indices
id_large = pos_X[idz]+idx + Np_ox*(posY[idz]+idy);
}
int id_small = idx + Np_px*idy ;
if (!isFlat)
id_small = id_small + Np_px*Np_py*idz ;
// prevent extra memory load
sarray_val = (isFlat && (idz > 0)) ? sarray_val: sarray[ id_small ];
//larray[id_large] += sarray_val;
//__syncthreads();
// slowest step, without atomicAdd it misses some values
atomicAdd(&larray[id_large] ,sarray_val);
}
}
}
template <bool useGlobal>
__global__ void addToArray_c( float2 const * sarray, float2 * larray, cuint16* ind_read, cuint16* pos_X, cuint16* posY,
cuint Np_px,cuint Np_py, cuint Np_pz,cuint Np_ox, cuint Np_oy,
cuint Npos, const bool isFlat) {
// Location in a 3D matrix
int idx= blockIdx.x * blockDim.x + threadIdx.x;
int idy= blockIdx.y * blockDim.y + threadIdx.y;
if ( idx < Np_px & idy < Np_py ) {
int idz, id_large;
float2 sarray_val;
for(int id = 0; id < Npos; id++)
{
if (useGlobal) {
// fast const memory based version
idz = gC_ind_read[id]-1; // go only through some of the indices
id_large = gC_pos_X[idz]+idx + Np_ox*(gC_pos_Y[idz]+idy);
} else {
// slower global memory based version
idz = ind_read[id]-1; // go only through some of the indices
id_large = pos_X[idz]+idx + Np_ox*(posY[idz]+idy);
}
int id_small = idx + Np_px*idy ;
if (!isFlat)
id_small = id_small + Np_px*Np_py*idz ;
// prevent extra memory load
sarray_val = (isFlat && (idz > 0)) ? sarray_val: sarray[ id_small ];
//larray[id_large].x += sarray_val.x;
//larray[id_large].y += sarray_val.y;
//__syncthreads();
// slowest step, without atomicAdd it misses some values
atomicAdd(&larray[id_large].x ,sarray_val.x);
atomicAdd(&larray[id_large].y ,sarray_val.y);
}
}
}
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
int i ;
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
char const * const errMsg = "Invalid input to MEX file.";
// Check for proper number of arguments.
if (nrhs != 5)
mexErrMsgTxt("Five input arguments required");
// Input must be of type single.
for (i=0; i < 2; i++) {
if ( !mxIsGPUArray(prhs[i]) && !mxIsCell(prhs[i]) ){
printf("Input %d is not cell array\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type.");
}
}
// Input must be of type int16.
for (i=2; i<4; i++){
if (mxIsUint16(prhs[i]) != 1){
printf("Input %d is not integer\n",i+1);
mexErrMsgIdAndTxt("MexError:ptycho","Inputs must be of correct type uint16.");
}
}
// It cannot be one-dimensional
if(mxGetNumberOfDimensions(prhs[0]) < 2) {
printf("The 1st input argument must have at least two dimensions.");
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
}
// It cannot be more than 3-dimensional
if(mxGetNumberOfDimensions(prhs[0]) > 3) {
printf("The 1st input argument must have at most three dimensions.");
mexErrMsgIdAndTxt("MexError:ptycho","wrong number of dimensions");
}
// Check that arrays are complex
const mxGPUArray * m_obj_proj = mxGPUCreateFromMxArray(prhs[0]);
if ((mxGPUGetClassID(m_obj_proj) != mxSINGLE_CLASS)) {
mexPrintf("m_obj_proj\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const mxGPUArray * m_positions_x = mxGPUCreateFromMxArray(prhs[2]);
if ((mxGPUGetClassID(m_positions_x) != mxUINT16_CLASS)) {
mexPrintf("m_positions_x\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const uint16_T * p_positions_x = (uint16_T *)mxGPUGetDataReadOnly(m_positions_x);
const mxGPUArray * m_positions_y = mxGPUCreateFromMxArray(prhs[3]);
if ((mxGPUGetClassID(m_positions_y) != mxUINT16_CLASS)) {
mexPrintf("m_positions_y\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const uint16_T * p_positions_y = (uint16_T *)mxGPUGetDataReadOnly(m_positions_y);
if (!mxIsCell(prhs[1]) || !mxIsCell(prhs[4]))
mexErrMsgIdAndTxt("MexError:ptycho","Object and indices has to be in cell/cells !! ");
if (mxGetNumberOfElements(prhs[1]) != mxGetNumberOfElements(prhs[4]))
mexErrMsgIdAndTxt("MexError:ptycho","Number of objects != number of indices ");
cuint Ncells = mxGetNumberOfElements(prhs[1]);
const unsigned int Np_pp = mxGPUGetNumberOfElements(m_positions_y);
if (Np_pp < MAX_IND_READ) {
cudaMemcpyToSymbol(gC_pos_X, p_positions_x, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
cudaMemcpyToSymbol(gC_pos_Y, p_positions_y, Np_pp*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
checkLastError("after cudaMemcpyToSymbol pos");
}
for (int l=0; l<Ncells; l++)
{
// read the cell content
mxArray * mx_object = mxGetCell(prhs[1],l);
mxArray * mx_ind = mxGetCell(prhs[4],l);
int N_ok = mxGetNumberOfElements(mx_ind);
if(N_ok == 0)
continue;
mxGPUArray * m_object = const_cast<mxGPUArray*>(mxGPUCreateFromMxArray(mx_object)); // mxGPUCopyFromMxArray(prhs[1]);
if ((mxGPUGetClassID(m_object) != mxSINGLE_CLASS)) {
mexPrintf("m_object\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
if (mxGPUGetComplexity(m_object) != mxGPUGetComplexity(m_obj_proj)) {
mexPrintf("m_object and m_obj_proj complexity has to be the same \n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const mxGPUArray * m_ind_ok = mxGPUCreateFromMxArray(mx_ind);
if ((mxGPUGetClassID(m_ind_ok) != mxUINT16_CLASS)) {
mexPrintf("m_ind_ok\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const uint16_T * p_ind_ok = (uint16_T *)mxGPUGetDataReadOnly(m_ind_ok);
// Get dimension of probe and object
const unsigned int Ndims = (unsigned int)mxGPUGetNumberOfDimensions(m_obj_proj);
const mwSize * Np_o = mxGPUGetDimensions(m_object);
const mwSize * Np_p = mxGPUGetDimensions(m_obj_proj);
const unsigned int Npos = mxGPUGetNumberOfElements(m_ind_ok);
//mexPrintf("Ndims %i Np_o %i %i Np_p %i %i %i Npos %i \n " ,Ndims,Np_o[0],Np_o[1],Np_p[0],Np_p[1],Np_p[3],Npos);
if (Ndims == 3 && Npos > Np_p[2]) {
printf("wrong size of update / positions %i", Ndims);
mexErrMsgIdAndTxt("MexError:ptycho","wrong size of update / positions");
}
if (Npos > MAX_IND_READ) {
//mexPrintf( "More than %i positions may be slow \n", MAX_IND_READ);
} else {
cudaMemcpyToSymbol(gC_ind_read, p_ind_ok, Npos*sizeof(uint16_T), 0, cudaMemcpyHostToDevice);
checkLastError("after cudaMemcpyToSymbol pos");
}
// Choose a reasonably sized number of threads in each dimension for the block.
int const threadsPerBlockEachDim = 32;
// Compute the thread block and grid sizes based on the board dimensions.
int const blocksPerGrid_M = (Np_p[0] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
int const blocksPerGrid_N = (Np_p[1] + threadsPerBlockEachDim - 1) / threadsPerBlockEachDim;
int const blocksPerGrid_O = 1;
dim3 const dimBlock(blocksPerGrid_M, blocksPerGrid_N, blocksPerGrid_O);
dim3 const dimThread(threadsPerBlockEachDim, threadsPerBlockEachDim, 1);
checkLastError("after dimThread");
checkLastError("after cudaMemcpyToSymbol");
const bool isFlat = (Ndims == 2);
const bool isComplex = mxGPUGetComplexity(m_obj_proj) == mxCOMPLEX;
// ================== call the right kernel ===================
if (isComplex) {
const float2 * p_obj_proj = (float2 *)mxGPUGetDataReadOnly(m_obj_proj);
float2 * p_object = (float2 *)mxGPUGetData(m_object);
if (Np_pp < MAX_IND_READ)
addToArray_c<true><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
else
addToArray_c<false><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
} else {
const float * p_obj_proj = (float *)mxGPUGetDataReadOnly(m_obj_proj);
float * p_object = (float *)mxGPUGetData(m_object);
if (Np_pp < MAX_IND_READ)
addToArray_r<true><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
else
addToArray_r<false><<<dimBlock, dimThread>>>(p_obj_proj,p_object, p_ind_ok, p_positions_x,p_positions_y ,Np_p[0],Np_p[1],Np_p[2],Np_o[0],Np_o[1], Npos, isFlat);
}
checkLastError("after kernel");
mxGPUDestroyGPUArray(m_object);
mxGPUDestroyGPUArray(m_ind_ok);
}
cudaThreadSynchronize();
// plhs[0] = mxGPUCreateMxArrayOnGPU(m_object);
mxGPUDestroyGPUArray(m_obj_proj);
mxGPUDestroyGPUArray(m_positions_x);
mxGPUDestroyGPUArray(m_positions_y);
return;
}