convolution_mex.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /* kernel_readin.c */
  2. #include "mex.h"
  3. #include "defs.h"
  4. #define MATLAB_KERNELS (prhs[0])
  5. #define GEOMETRY (prhs[1])
  6. #define BEAMLETS (plhs[0]) // output structure
  7. /* #define TERMA (plhs[1])
  8. #define KERMAC (plhs[2])
  9. #define DEFF (plhs[3])
  10. #define TERMA_MASK (plhs[4])
  11. #define DOSE_MASK (plhs[5]) */
  12. //function prototypes
  13. void check_MATLAB_KERNELS(const mxArray *);
  14. void check_GEOMETRY(const mxArray *);
  15. void load_kernels(const mxArray *, MONO_KERNELS *);
  16. void load_Geometry(const mxArray *, FLOAT_GRID *);
  17. void load_beam(const mxArray *, int, BEAM *);
  18. int calc_deff(FLOAT_GRID *,FLOAT_GRID *, FLOAT_GRID *, BEAM *);
  19. int terma_kerma(FLOAT_GRID *,FLOAT_GRID *,FLOAT_GRID *,MONO_KERNELS *,FLOAT_GRID *);
  20. int make_poly_kernel(MONO_KERNELS *, KERNEL *);
  21. int calc_dose(FLOAT_GRID *,FLOAT_GRID *,FLOAT_GRID *,KERNEL *,BEAM *, FLOAT_GRID *);
  22. int terma_dose_masks(FLOAT_GRID *, FLOAT_GRID *, BEAM *);
  23. char errstr[200]; // error string that all routines have access to
  24. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  25. {
  26. int dims[3], dims2[2]; // dimensions of input arrays
  27. const int *celldims;
  28. int b, B; // beam indices
  29. const int one = 1;
  30. // matlab arrays for easy output if need be (just comment these lines out and uncomment
  31. // the #define lines above and the mxDestroy lines below).
  32. mxArray *TERMA, *KERMAC, *DEFF, *TERMA_MASK, *DOSE_MASK;
  33. mxArray *DOSE, *cell, *struc, *field, *ind_field, *data_field;
  34. // sparse storage parameters
  35. int Nind, Ntotal, i, j;
  36. int *intPtr;
  37. float *floatPtr;
  38. // information for sparse output data:
  39. int nfields = 5;
  40. const char *field_names[5] = {"x_count","y_count","z_count",
  41. "non_zero_indices","non_zero_values"};
  42. char tmpstr[200];
  43. FLOAT_GRID density;
  44. FLOAT_GRID terma_mask;
  45. FLOAT_GRID dose_mask;
  46. FLOAT_GRID deff;
  47. FLOAT_GRID terma;
  48. FLOAT_GRID kermac;
  49. FLOAT_GRID dose;
  50. MONO_KERNELS mono_kernels;
  51. KERNEL poly_kernel;
  52. BEAM beam;
  53. // check and load-in input data
  54. check_MATLAB_KERNELS(MATLAB_KERNELS); // see function comments for proper input format
  55. check_GEOMETRY(GEOMETRY); // see function comments for proper input format
  56. load_kernels(MATLAB_KERNELS, &mono_kernels);
  57. load_Geometry(GEOMETRY,&density);
  58. // copy density grid geometry information to all other grids of interest
  59. copy_grid_geometry(&density,&terma_mask);
  60. copy_grid_geometry(&density,&dose_mask);
  61. copy_grid_geometry(&density,&deff);
  62. copy_grid_geometry(&density,&terma);
  63. copy_grid_geometry(&density,&kermac);
  64. copy_grid_geometry(&density,&dose);
  65. // Allocate memory for all of the grids
  66. // dimensions of all the grids
  67. dims[0] = density.x_count;
  68. dims[1] = density.y_count;
  69. dims[2] = density.z_count;
  70. Ntotal = dims[0]*dims[1]*dims[2];
  71. // Allocate memory for all of the data grids using Matlab mxArray functions.
  72. // The idea behind this is for the outputs to send the outputs directly to Matlab.
  73. if ((TERMA_MASK = mxCreateNumericArray(3,dims,mxSINGLE_CLASS,mxREAL))==NULL)
  74. mexErrMsgTxt("Could not allocate memory for terma_mask grid");
  75. terma_mask.matrix = (float *)mxGetData(TERMA_MASK);
  76. if ((DOSE_MASK = mxCreateNumericArray(3,dims,mxSINGLE_CLASS,mxREAL))==NULL)
  77. mexErrMsgTxt("Could not allocate memory for dose_mask grid");
  78. dose_mask.matrix = (float *)mxGetData(DOSE_MASK);
  79. if ((DEFF = mxCreateNumericArray(3,dims,mxSINGLE_CLASS,mxREAL))==NULL)
  80. mexErrMsgTxt("Could not allocate memory for deff grid");
  81. deff.matrix = (float *)mxGetData(DEFF);
  82. if ((TERMA = mxCreateNumericArray(3,dims,mxSINGLE_CLASS,mxREAL))==NULL)
  83. mexErrMsgTxt("Could not allocate memory for terma grid");
  84. terma.matrix = (float *)mxGetData(TERMA);
  85. if ((KERMAC = mxCreateNumericArray(3,dims,mxSINGLE_CLASS,mxREAL))==NULL)
  86. mexErrMsgTxt("Could not allocate memory for kermac grid");
  87. kermac.matrix = (float *)mxGetData(KERMAC);
  88. if ((DOSE = mxCreateNumericArray(3,dims,mxSINGLE_CLASS,mxREAL))==NULL)
  89. mexErrMsgTxt("Could not allocate memory for dose matrix");
  90. // Point dose matrix pointer at DOSE Matlab matrix data
  91. dose.matrix = (float *)mxGetData(DOSE);
  92. //create polyenergetic kernel from mono kernels and fluence, mu data
  93. if (SUCCESS != make_poly_kernel(&mono_kernels,&poly_kernel) )
  94. {
  95. sprintf(tmpstr,"Failed making polyenergetic kernel!\n");
  96. strcat(tmpstr,errstr);
  97. strcpy(errstr,tmpstr);
  98. mexErrMsgTxt(errstr);
  99. }
  100. // create the output structure
  101. celldims = mxGetDimensions(mxGetField(GEOMETRY,0,"beam"));
  102. B = celldims[0]*celldims[1]; // number of beams in the calculation
  103. BEAMLETS = mxCreateCellArray(2,celldims);
  104. // do calculations for all beams
  105. for (b=0;b<B;b++)
  106. {
  107. load_beam(GEOMETRY,b,&beam);
  108. // create terma and dose masks
  109. if (SUCCESS != terma_dose_masks(&terma_mask,&dose_mask,&beam))
  110. {
  111. sprintf(tmpstr,"Failed in terma_dose_masks!\n");
  112. strcat(tmpstr,errstr);
  113. strcpy(errstr,tmpstr);
  114. mexErrMsgTxt(errstr);
  115. }
  116. //create effective depth array from density array
  117. if (SUCCESS != calc_deff(&density,&deff,&terma_mask,&beam))
  118. {
  119. sprintf(tmpstr,"Failed in calc_deff!\n");
  120. strcat(tmpstr,errstr);
  121. strcpy(errstr,tmpstr);
  122. mexErrMsgTxt(errstr);
  123. }
  124. //create kerma and terma arrays
  125. //note kerma is collision kerma and is used for a kernel hardening correction
  126. if (SUCCESS != terma_kerma(&deff,&terma,&kermac,&mono_kernels,&terma_mask))
  127. {
  128. sprintf(tmpstr,"Failed in terma_kerma calculation!\n");
  129. strcat(tmpstr,errstr);
  130. strcpy(errstr,tmpstr);
  131. mexErrMsgTxt(errstr);
  132. }
  133. //use all this stuff to calculate dose
  134. if ( (SUCCESS != calc_dose(&density,&terma,&dose,&poly_kernel,&beam,&dose_mask)) )
  135. {
  136. sprintf(tmpstr,"Failed calculating dose!\n");
  137. strcat(tmpstr,errstr);
  138. strcpy(errstr,tmpstr);
  139. mexErrMsgTxt(errstr);
  140. }
  141. FILE *fid;
  142. fid = fopen("dose.bin","wb");
  143. fwrite(dose.matrix,sizeof(float),Ntotal,fid);
  144. fclose(fid);
  145. // count the number of non-zero dose values
  146. Nind = 0;
  147. for (i=0;i<Ntotal;i++)
  148. if (dose.matrix[i] > 0.0)
  149. Nind++;
  150. dims2[0] = 1;
  151. dims2[1] = Nind;
  152. // fill in the sparse matrix structure for this beam
  153. // create the structure that will hold the sparse beamlet
  154. struc = mxCreateStructArray(1,&one,nfields,field_names);
  155. // indices field
  156. ind_field = mxCreateNumericArray(2,dims2,mxINT32_CLASS,mxREAL);
  157. // data field
  158. data_field = mxCreateNumericArray(2,dims2,mxSINGLE_CLASS,mxREAL);
  159. // x, y, and z counts
  160. dims2[0] = 1;
  161. dims2[1] = 1;
  162. field = mxCreateNumericArray(2,dims2,mxINT32_CLASS,mxREAL);
  163. intPtr = (int *)mxGetData(field);
  164. intPtr[0] = dims[0];
  165. mxSetField(struc,0,"x_count",mxDuplicateArray(field));
  166. field = mxCreateNumericArray(2,dims2,mxINT32_CLASS,mxREAL);
  167. intPtr = (int *)mxGetData(field);
  168. intPtr[0] = dims[1];
  169. mxSetField(struc,0,"y_count",mxDuplicateArray(field));
  170. field = mxCreateNumericArray(2,dims2,mxINT32_CLASS,mxREAL);
  171. intPtr = (int *)mxGetData(field);
  172. intPtr[0] = dims[2];
  173. mxSetField(struc,0,"z_count",mxDuplicateArray(field));
  174. intPtr = (int *)mxGetData(ind_field);
  175. floatPtr = (float *)mxGetData(data_field);
  176. // extract the sparse data
  177. j = 0; // index just for the sparse data
  178. for (i=0;i<Ntotal;i++)
  179. if (dose.matrix[i] > 0.0)
  180. {
  181. intPtr[j] = i + 1;
  182. floatPtr[j] = dose.matrix[i];
  183. j++;
  184. }
  185. mxSetField(struc,0,"non_zero_indices",mxDuplicateArray(ind_field));
  186. mxSetField(struc,0,"non_zero_values",mxDuplicateArray(data_field));
  187. mxSetCell(BEAMLETS,b,mxDuplicateArray(struc));
  188. printf("Finished calculating dose with beam %d\n",b+1);
  189. // reset the matrices to zeros
  190. for (i=0;i<Ntotal;i++)
  191. {
  192. terma_mask.matrix[i] = 0.0;
  193. dose_mask.matrix[i] = 0.0;
  194. deff.matrix[i] = 0.0;
  195. terma.matrix[i] = 0.0;
  196. kermac.matrix[i] = 0.0;
  197. dose.matrix[i] = 0.0;
  198. }
  199. }
  200. // destroy the arrays created with mxCreate that are not output matrices
  201. mxDestroyArray(TERMA);
  202. mxDestroyArray(KERMAC);
  203. mxDestroyArray(DEFF);
  204. mxDestroyArray(TERMA_MASK);
  205. mxDestroyArray(DOSE_MASK);
  206. mxDestroyArray(DOSE);
  207. // free the kernels
  208. free(poly_kernel.angular_boundary);
  209. free(poly_kernel.radial_boundary);
  210. // free(poly_kernel.total_matrix);
  211. for (j=0;j<N_KERNEL_CATEGORIES;j++)
  212. free(poly_kernel.matrix[j]);
  213. // cannot free mono_kernels because they are part of a Matlab input structure
  214. }