ProSHADE  0.6.5 (NOV 2018)
Protein Shape Descriptors and Symmetry Detection
ProSHADE_spharmonickit.cpp
Go to the documentation of this file.
1 
20 //============================================ FFTW3 + SOFT
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 #include <fftw3.h>
25 #include <wrap_fftw.h>
26 #include <makeweights.h>
27 #include <s2_primitive.h>
28 #include <s2_cospmls.h>
29 #include <s2_legendreTransforms.h>
30 #include <s2_semi_fly.h>
31 #include <rotate_so3_utils.h>
32 #include <utils_so3.h>
33 #include <soft_fftw.h>
34 #include <rotate_so3_fftw.h>
35 #ifdef __cplusplus
36 }
37 #endif
38 
39 //============================================ RVAPI
40 #include <rvapi_interface.h>
41 
42 //============================================ ProSHADE
43 #include "ProSHADE.h"
44 #include "ProSHADE_internal.h"
45 
61  double theta,
62  double phi,
63  double shellSz,
64  unsigned int manualShells,
65  bool keepInMemory,
66  bool rotDefaults )
67 {
68  //======================================== Sanity check
69  if ( !this->_phaseRemoved )
70  {
71  std::cerr << "!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName << " !!! Attempted to map data onto shell before computing the phaseless data. Call the removePhaseFromMap function BEFORE the mapPhaselessToSphere function." << std::endl;
72 
73  if ( settings->htmlReport )
74  {
75  std::stringstream hlpSS;
76  hlpSS << "<font color=\"red\">" << "Attempted to map data onto shell before computing the phaseless data. This looks like an internal bug, please report this case." << "</font>";
77  rvapi_set_text ( hlpSS.str().c_str(),
78  "ProgressSection",
79  settings->htmlReportLineProgress,
80  1,
81  1,
82  1 );
83  settings->htmlReportLineProgress += 1;
84  rvapi_flush ( );
85  }
86 
87  exit ( -1 );
88  }
89 
90  //======================================== Initialise internal values
91  this->_thetaAngle = theta;
92  this->_phiAngle = phi;
93  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU );
94  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV );
95  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW );
96 
97  //======================================== Initialise local variables
98  double x, y, z;
99  int xBottom, yBottom, zBottom;
100  int xTop, yTop, zTop;
101 
102  std::array<double,4> c000, c001, c010, c011, c100, c101, c110, c111;
103  std::array<double,4> c00, c01, c10, c11;
104  std::array<double,4> c0, c1;
105  double xd, yd, zd;
106 
107  //======================================== How many shells can the map fill?
108  if ( this->_noShellsWithData == 0 )
109  {
110  //==================================== Automatically determine maximum number of shells
111  this->_shellSpacing = shellSz;
112  this->_shellPlacement = std::vector<double> ( std::floor ( this->_maxMapRange / this->_shellSpacing ) );
113 
114  for ( unsigned int shellIter = 0; shellIter < static_cast<unsigned int> ( this->_shellPlacement.size() ); shellIter++ )
115  {
116  this->_shellPlacement.at(shellIter) = (shellIter+1) * this->_shellSpacing;
117  }
118  }
119 
120  if ( !rotDefaults )
121  {
122  unsigned int shellNoHlp = 0;
123  for ( unsigned int sh = 0; sh < static_cast<unsigned int> ( this->_shellPlacement.size() ); sh++ )
124  {
125  if ( ( ( (((this->_maxMapU+1)/2)-1) * this->_xSamplingRate ) > this->_shellPlacement.at(sh) ) ||
126  ( ( (((this->_maxMapV+1)/2)-1) * this->_ySamplingRate ) > this->_shellPlacement.at(sh) ) ||
127  ( ( (((this->_maxMapW+1)/2)-1) * this->_zSamplingRate ) > this->_shellPlacement.at(sh) ) )
128  { shellNoHlp = sh; }
129  else
130  { break; }
131  }
132  if ( shellNoHlp > 0 ) { shellNoHlp -= 1; }
133 
134  if ( manualShells == 0 ) { this->_noShellsWithData = shellNoHlp; }
135  else
136  {
137  this->_noShellsWithData = manualShells;
138  if ( manualShells > shellNoHlp )
139  {
140  std::cerr << "!!! ProSHADE ERROR !!! The required number of shells is larger than the data allows. Either use automatic shell number determination (i.e. manualShells = 0) or decrease the number of required shells." << std::endl;
141 
142  if ( settings->htmlReport )
143  {
144  std::stringstream hlpSS;
145  hlpSS << "<font color=\"red\">" << "The required number of shells is larger than the data allows. Either use automatic shell number determination (i.e. manualShells = 0) or decrease the number of required shells." << "</font>";
146  rvapi_set_text ( hlpSS.str().c_str(),
147  "ProgressSection",
148  settings->htmlReportLineProgress,
149  1,
150  1,
151  1 );
152  settings->htmlReportLineProgress += 1;
153  rvapi_flush ( );
154  }
155 
156  exit ( -1 );
157  }
158  }
159  }
160  else
161  {
162  //==================================== Make sure shells cover the corners
163  unsigned int shellNoHlp = 0;
164  double maxDist = std::max ( sqrt( pow( ( (((this->_maxMapU+1)/2)-1) * this->_xSamplingRate ), 2.0 ) + pow ( ( (((this->_maxMapV+1)/2)-1) * this->_ySamplingRate ), 2.0 ) ),
165  std::max ( sqrt( pow( ( (((this->_maxMapU+1)/2)-1) * this->_xSamplingRate ), 2.0 ) + pow ( ( (((this->_maxMapW+1)/2)-1) * this->_zSamplingRate ), 2.0 ) ),
166  sqrt( pow( ( (((this->_maxMapW+1)/2)-1) * this->_zSamplingRate ), 2.0 ) + pow ( ( (((this->_maxMapV+1)/2)-1) * this->_ySamplingRate ), 2.0 ) ) ) );
167  for ( unsigned int sh = 0; sh < static_cast<unsigned int> ( this->_shellPlacement.size() ); sh++ )
168  {
169  if ( maxDist > this->_shellPlacement.at(sh) ) { shellNoHlp = sh; }
170  else { break; }
171  }
172  shellNoHlp -= 1;
173 
174  if ( manualShells == 0 ) { this->_noShellsWithData = shellNoHlp; }
175  else
176  {
177  this->_noShellsWithData = manualShells;
178  if ( manualShells > shellNoHlp )
179  {
180  std::cerr << "!!! ProSHADE ERROR !!! The required number of shells is larger than the data allows. Either use automatic shell number determination (i.e. manualShells = 0) or decrease the number of required shells." << std::endl;
181 
182  if ( settings->htmlReport )
183  {
184  std::stringstream hlpSS;
185  hlpSS << "<font color=\"red\">" << "The required number of shells is larger than the data allows. Either use automatic shell number determination (i.e. manualShells = 0) or decrease the number of required shells." << "</font>";
186  rvapi_set_text ( hlpSS.str().c_str(),
187  "ProgressSection",
188  settings->htmlReportLineProgress,
189  1,
190  1,
191  1 );
192  settings->htmlReportLineProgress += 1;
193  rvapi_flush ( );
194  }
195 
196  exit ( -1 );
197  }
198  }
199  }
200 
201  if ( this->_noShellsWithData < 2 )
202  {
203  std::cerr << "!!! ProSHADE ERROR !!! Did not find enough shells to which the data could be mapped. Either the structure is rather small and the default values do not work - use the \'sphDistance\' option to adjust, or this is a bug. Terminating..." << std::endl;
204 
205  if ( settings->htmlReport )
206  {
207  std::stringstream hlpSS;
208  hlpSS << "<font color=\"red\">" << "Did not find enough shells to which the data could be mapped. Either the structure is rather small and the default values do not work - use the \'sphDistance\' option to adjust." << "</font>";
209  rvapi_set_text ( hlpSS.str().c_str(),
210  "ProgressSection",
211  settings->htmlReportLineProgress,
212  1,
213  1,
214  1 );
215  settings->htmlReportLineProgress += 1;
216  rvapi_flush ( );
217  }
218 
219  exit ( -1 );
220  }
221 
222  //======================================== Initialise internal values ( and allocate memory )
223  this->_shellMappedData = new double*[this->_noShellsWithData];
224  for ( unsigned int sh = 0; sh < this->_noShellsWithData; sh++ )
225  {
226  this->_shellMappedData[sh] = new double[static_cast<unsigned int> ( this->_thetaAngle * this->_phiAngle )];
227  }
228 
229  //======================================== Find pixelisation cutOffs
230  std::vector<double> lonCO ( this->_thetaAngle + 1 );
231  for ( unsigned int iter = 0; iter <= this->_thetaAngle; iter++ ) { lonCO.at(iter) = static_cast<double> ( iter ) * ( ( static_cast<double> ( M_PI ) * 2.0 ) / static_cast<double> ( this->_thetaAngle ) ) - ( static_cast<double> ( M_PI ) ); }
232  std::vector<double> latCO ( this->_phiAngle + 1 );
233  for ( unsigned int iter = 0; iter <= this->_phiAngle; iter++ ) { latCO.at(iter) = ( static_cast<double> ( iter ) * ( static_cast<double> ( M_PI ) / static_cast<double> ( this->_phiAngle ) ) - ( static_cast<double> ( M_PI ) / 2.0 ) ); }
234 
235  //======================================== Tri-linear interpolation
236  unsigned int posIter;
237 
238  for ( unsigned int sh = 0; sh < this->_noShellsWithData; sh++ )
239  {
240  //==================================== Find pixel centres
241  for ( unsigned int thIt = 0; thIt < this->_thetaAngle; thIt++ )
242  {
243  for ( unsigned int phIt = 0; phIt < this->_phiAngle; phIt++ )
244  {
245  //============================ Get grid point x, y and z
246  x = this->_shellPlacement.at(sh) * cos( ( static_cast<double> ( lonCO.at(thIt) ) + static_cast<double> ( lonCO.at(thIt+1) ) ) / 2.0 ) * cos( ( static_cast<double> ( latCO.at(phIt) ) + static_cast<double> ( latCO.at (phIt+1) ) ) / 2.0 );
247  y = this->_shellPlacement.at(sh) * sin( ( static_cast<double> ( lonCO.at(thIt) ) + static_cast<double> ( lonCO.at(thIt+1) ) ) / 2.0 ) * cos( ( static_cast<double> ( latCO.at(phIt) ) + static_cast<double> ( latCO.at (phIt+1) ) ) / 2.0 );
248  z = this->_shellPlacement.at(sh) * sin( ( static_cast<double> ( latCO.at(phIt) ) + static_cast<double> ( latCO.at(phIt+1) ) ) / 2.0 );
249 
250  //============================ Find 8 closest point around the grid point
251  xBottom = floor ( (x / this->_xSamplingRate) ) + ((this->_maxMapU+1)/2);
252  yBottom = floor ( (y / this->_ySamplingRate) ) + ((this->_maxMapV+1)/2);
253  zBottom = floor ( (z / this->_zSamplingRate) ) + ((this->_maxMapW+1)/2);
254 
255  xTop = xBottom + 1;
256  yTop = yBottom + 1;
257  zTop = zBottom + 1;
258 
259  posIter = zBottom + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xBottom );
260  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
261  c000[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
262  c000[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
263  c000[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
264  c000[3] = this->_densityMapCor[posIter];
265 
266  posIter = zTop + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xBottom );
267  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
268  c001[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
269  c001[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
270  c001[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
271  c001[3] = this->_densityMapCor[posIter];
272 
273  posIter = zBottom + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xBottom );
274  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
275  c010[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
276  c010[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
277  c010[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
278  c010[3] = this->_densityMapCor[posIter];
279 
280  posIter = zTop + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xBottom );
281  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
282  c011[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
283  c011[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
284  c011[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
285  c011[3] = this->_densityMapCor[posIter];
286 
287  posIter = zBottom + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xTop );
288  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
289  c100[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
290  c100[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
291  c100[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
292  c100[3] = this->_densityMapCor[posIter];
293 
294  posIter = zTop + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xTop );
295  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
296  c101[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
297  c101[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
298  c101[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
299  c101[3] = this->_densityMapCor[posIter];
300 
301  posIter = zBottom + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xTop );
302  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
303  c110[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
304  c110[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
305  c110[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
306  c110[3] = this->_densityMapCor[posIter];
307 
308  posIter = zTop + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xTop );
309  if ( posIter > ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) ) { this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = 0.0; continue; }
310  c111[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
311  c111[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
312  c111[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
313  c111[3] = this->_densityMapCor[posIter];
314 
315  //============================ Interpolate along x
316  xd = (x - ( ( xBottom - static_cast<int> ( ((this->_maxMapU+1)/2) ) ) * this->_xSamplingRate ) ) / this->_xSamplingRate;
317  c00[0] = (this->_xSamplingRate * xd) + c000[0]; c00[1] = c000[1]; c00[2] = c000[2]; c00[3] = ( c000[3] * ( 1.0 - xd ) ) + ( c100[3] * xd );
318  c01[0] = (this->_xSamplingRate * xd) + c001[0]; c01[1] = c001[1]; c01[2] = c001[2]; c01[3] = ( c001[3] * ( 1.0 - xd ) ) + ( c101[3] * xd );
319  c10[0] = (this->_xSamplingRate * xd) + c010[0]; c10[1] = c010[1]; c10[2] = c010[2]; c10[3] = ( c010[3] * ( 1.0 - xd ) ) + ( c110[3] * xd );
320  c11[0] = (this->_xSamplingRate * xd) + c011[0]; c11[1] = c011[1]; c11[2] = c011[2]; c11[3] = ( c011[3] * ( 1.0 - xd ) ) + ( c111[3] * xd );
321 
322  //============================ Interpolate along y
323  yd = (y - ( ( yBottom - static_cast<int> ( ((this->_maxMapV+1)/2) ) ) * this->_ySamplingRate ) ) / this->_ySamplingRate;
324  c0[0] = c00[0]; c0[1] = (this->_ySamplingRate * yd) + c00[1]; c0[2] = c00[2]; c0[3] = ( c00[3] * ( 1.0 - yd ) ) + ( c10[3] * yd );
325  c1[0] = c01[0]; c1[1] = (this->_ySamplingRate * yd) + c01[1]; c1[2] = c01[2]; c1[3] = ( c01[3] * ( 1.0 - yd ) ) + ( c11[3] * yd );
326 
327  //============================ Interpolate along z
328  zd = (z - ( ( zBottom - static_cast<int> ( ((this->_maxMapW+1)/2) ) ) * this->_zSamplingRate ) ) / this->_zSamplingRate;
329 
330  //============================ Save results
331  this->_shellMappedData[sh][static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = ( c0[3] * ( 1.0 - zd ) ) + ( c1[3] * zd );
332  }
333  }
334  }
335 
336  //======================================== Free unnecessary memory
337  delete[] this->_densityMapCorCoords;
338  this->_densityMapCorCoords = nullptr;
339 
340  if ( !keepInMemory )
341  {
342  delete[] this->_densityMapCor;
343  this->_densityMapCor = nullptr;
344  }
345 
346  //======================================== Done
347  this->_sphereMapped = true;
348 
349 }
350 
363 {
364  //======================================== Sanity check
365  if ( !this->_sphereMapped )
366  {
367  std::cerr << "!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName << " !!! Attempted to obtain spherical harmonics before mapping the map onto spheres. Call the mapPhaselessToSphere function BEFORE the getSphericalHarmonicsCoeffs function." << std::endl;
368 
369  if ( settings->htmlReport )
370  {
371  std::stringstream hlpSS;
372  hlpSS << "<font color=\"red\">" << "Attempted to obtain spherical harmonics before mapping the map onto spheres. This looks like an internal bug, please report this case." << "</font>";
373  rvapi_set_text ( hlpSS.str().c_str(),
374  "ProgressSection",
375  settings->htmlReportLineProgress,
376  1,
377  1,
378  1 );
379  settings->htmlReportLineProgress += 1;
380  rvapi_flush ( );
381  }
382 
383  exit ( -1 );
384  }
385 
386  //======================================== Initialise internal values
387  this->_bandwidthLimit = bandwidth;
388  this->_oneDimmension = this->_bandwidthLimit * 2;
389 
390  //======================================== Allocate Memory
391  double *inputReal = new double [static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
392  double *inputZeroes = new double [static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
393  this->_realSHCoeffs = new double*[static_cast<unsigned int> ( this->_noShellsWithData )];
394  this->_imagSHCoeffs = new double*[static_cast<unsigned int> ( this->_noShellsWithData )];
395  this->_sphericalHarmonicsWeights = new double [static_cast<unsigned int> ( this->_bandwidthLimit * 4 )];
396  this->_semiNaiveTableSpace = new double [static_cast<unsigned int> ( Reduced_Naive_TableSize ( this->_bandwidthLimit, this->_bandwidthLimit ) +
397  Reduced_SpharmonicTableSize ( this->_bandwidthLimit, this->_bandwidthLimit ) )];
398 
399  this->_shWorkspace = (fftw_complex *) fftw_malloc ( sizeof(fftw_complex) * ( ( 8 * this->_bandwidthLimit * this->_bandwidthLimit ) +
400  ( 10 * this->_bandwidthLimit ) ) );
401 
402  for ( unsigned int shIt = 0; shIt < this->_noShellsWithData; shIt++ )
403  {
404  this->_realSHCoeffs[shIt] = new double [static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
405  this->_imagSHCoeffs[shIt] = new double [static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
406  }
407 
408  //======================================== Check Memory Allocation
409  if ( this->_shWorkspace == nullptr )
410  {
411  std::cerr << "!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName << " !!! malloc (Memory Allocation) failed for _shWorkspace object in function getSphericalHarmonicsCoeffs." << std::endl;
412 
413  if ( settings->htmlReport )
414  {
415  std::stringstream hlpSS;
416  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for spherical harmonics decomposition. Could you have run out of memory?" << "</font>";
417  rvapi_set_text ( hlpSS.str().c_str(),
418  "ProgressSection",
419  settings->htmlReportLineProgress,
420  1,
421  1,
422  1 );
423  settings->htmlReportLineProgress += 1;
424  rvapi_flush ( );
425  }
426 
427  exit( -1 ) ;
428  }
429 
430  //======================================== Generate Seminaive and naive table
431  this->_semiNaiveTable = SemiNaive_Naive_Pml_Table ( this->_bandwidthLimit,
432  this->_bandwidthLimit,
433  this->_semiNaiveTableSpace,
434  reinterpret_cast<double*> ( this->_shWorkspace ) );
435 
436  //======================================== Make weights for spherical transform
437  makeweights ( this->_bandwidthLimit,
438  this->_sphericalHarmonicsWeights );
439 
440  //======================================== Declare pointers to within workspace
441  double *rres;
442  double *ires;
443  double *fltres;
444  double *scratchpad;
445  double *rdataptr;
446  double *idataptr;
447 
448  //======================================== Initialize pointers to within workspace
449  rres = reinterpret_cast<double*> ( this->_shWorkspace );
450  ires = rres + ( this->_oneDimmension * this->_oneDimmension );
451  fltres = ires + ( this->_oneDimmension * this->_oneDimmension );
452  scratchpad = fltres + ( this->_bandwidthLimit );
453 
454  //======================================== Initialize fft plan along phi angles
455  fftw_plan fftPlan;
456  fftw_plan dctPlan;
457 
458  fftw_iodim dims[1];
459  fftw_iodim howmany_dims[1];
460 
461  int rank = 1;
462  int howmany_rank = 1;
463  double normCoeff = ( 1.0 / ( static_cast<double> ( this->_oneDimmension ) ) ) * sqrt( 2.0 * M_PI );
464  double powerOne = 1.0;
465  unsigned int hlp1 = 0;
466  unsigned int hlp2 = 0;
467 
468  dims[0].n = this->_oneDimmension;
469  dims[0].is = 1;
470  dims[0].os = this->_oneDimmension;
471 
472  howmany_dims[0].n = this->_oneDimmension;
473  howmany_dims[0].is = this->_oneDimmension;
474  howmany_dims[0].os = 1;
475 
476  //======================================== Plan fft transform
477  fftPlan = fftw_plan_guru_split_dft ( rank,
478  dims,
479  howmany_rank,
480  howmany_dims,
481  inputReal,
482  inputZeroes,
483  rres,
484  ires,
485  FFTW_ESTIMATE );
486 
487  //======================================== Initialize dct plan for SHT
488  dctPlan = fftw_plan_r2r_1d ( this->_oneDimmension,
489  scratchpad,
490  scratchpad + this->_oneDimmension,
491  FFTW_REDFT10,
492  FFTW_ESTIMATE ) ;
493 
494  //======================================== For each shell
495  for ( unsigned int shIter = 0; shIter < static_cast<unsigned int> ( this->_noShellsWithData ); shIter++ )
496  {
497  //==================================== Load pixel hits to signal array
498  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension ); iter++ )
499  {
500  inputReal[iter] = this->_shellMappedData[shIter][iter];
501  inputZeroes[iter] = 0.0;
502  }
503 
504  //==================================== Execute fft plan along phi
505  fftw_execute_split_dft ( fftPlan, inputReal, inputZeroes, rres, ires ) ;
506 
507  //==================================== Normalize
508  for ( unsigned int iter = 0; iter < ( this->_oneDimmension * this->_oneDimmension ); iter++ )
509  {
510  rres[iter] *= normCoeff;
511  ires[iter] *= normCoeff;
512  }
513 
514  //==================================== Calculate the coefficients for each band
515  rdataptr = this->_realSHCoeffs[shIter];
516  idataptr = this->_imagSHCoeffs[shIter];
517  for ( unsigned int bandIter = 0; bandIter < this->_bandwidthLimit; bandIter++ )
518  {
519  //================================ *real* part calculation
520  SemiNaiveReduced ( rres + ( bandIter * this->_oneDimmension ),
521  this->_bandwidthLimit,
522  bandIter,
523  fltres,
524  scratchpad,
525  this->_semiNaiveTable[bandIter],
526  this->_sphericalHarmonicsWeights,
527  &dctPlan);
528 
529  //================================ Save the *real* results
530  memcpy ( rdataptr, fltres, sizeof(double) * ( this->_bandwidthLimit - bandIter ) );
531  rdataptr += this->_bandwidthLimit - bandIter;
532 
533  //================================ *imaginary* part calculation
534  SemiNaiveReduced ( ires + ( bandIter * this->_oneDimmension ),
535  this->_bandwidthLimit,
536  bandIter,
537  fltres,
538  scratchpad,
539  this->_semiNaiveTable[bandIter],
540  this->_sphericalHarmonicsWeights,
541  &dctPlan );
542 
543  //================================ Save the *imaginary* results
544  memcpy ( idataptr, fltres, sizeof(double) * ( this->_bandwidthLimit - bandIter ) );
545  idataptr += this->_bandwidthLimit - bandIter;
546  }
547 
548  //==================================== Since the data are real, there is no need to calculate negative order data, as there is the equivalence
549  powerOne = 1.0;
550  hlp1 = 0;
551  hlp2 = 0;
552  for( unsigned int order = 1; order < this->_bandwidthLimit; order++)
553  {
554  powerOne *= -1.0;
555  for( unsigned int bandIter = order; bandIter < this->_bandwidthLimit; bandIter++){
556 
557  hlp1 = seanindex ( order, bandIter, this->_bandwidthLimit );
558  hlp2 = seanindex ( -order, bandIter, this->_bandwidthLimit );
559 
560  this->_realSHCoeffs[shIter][hlp2] = powerOne * this->_realSHCoeffs[shIter][hlp1];
561  this->_imagSHCoeffs[shIter][hlp2] = -powerOne * this->_imagSHCoeffs[shIter][hlp1];
562  }
563  }
564  }
565 
566  delete[] inputReal;
567  delete[] inputZeroes;
568 
569  delete[] this->_semiNaiveTable;
570  delete[] this->_semiNaiveTableSpace;
571  delete[] this->_sphericalHarmonicsWeights;
572 
573  fftw_free ( this->_shWorkspace );
574 
575  this->_semiNaiveTable = nullptr;
576  this->_semiNaiveTableSpace = nullptr;
577  this->_sphericalHarmonicsWeights = nullptr;
578  this->_shWorkspace = nullptr;
579 
580  fftw_destroy_plan ( dctPlan );
581  fftw_destroy_plan ( fftPlan );
582 
583  //======================================== Done
584  this->_sphericalCoefficientsComputed = true;
585 
586 }
void mapPhaselessToSphere(ProSHADE::ProSHADE_settings *settings, double theta, double phi, double shellSz, unsigned int manualShells=0, bool keepInMemory=false, bool rotDefaults=false)
This function assumes the data have been processed and maps them onto a set of concentric spheres wit...
bool htmlReport
Should HTML report for the run be created?
Definition: ProSHADE.h:186
The main header file containing all declarations the user of the library needs.
void getSphericalHarmonicsCoeffs(unsigned int bandwidth, ProSHADE::ProSHADE_settings *settings)
This function takes the sphere mapped data and computes spherical harmoncis decomposition for each sh...
The main header file containing all declarations for the innter workings of the library.
int htmlReportLineProgress
Iterator for current HTML line in the progress bar.
Definition: ProSHADE.h:188
This class stores all the settings and is passed to the executive classes instead of multitude of par...
Definition: ProSHADE.h:74