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> 40 #include <rvapi_interface.h> 64 unsigned int manualShells,
69 if ( !this->_phaseRemoved )
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;
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(),
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 );
99 int xBottom, yBottom, zBottom;
100 int xTop, yTop, zTop;
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;
108 if ( this->_noShellsWithData == 0 )
111 this->_shellSpacing = shellSz;
112 this->_shellPlacement = std::vector<double> ( std::floor ( this->_maxMapRange / this->_shellSpacing ) );
114 for (
unsigned int shellIter = 0; shellIter < static_cast<unsigned int> ( this->_shellPlacement.size() ); shellIter++ )
116 this->_shellPlacement.at(shellIter) = (shellIter+1) * this->_shellSpacing;
122 unsigned int shellNoHlp = 0;
123 for (
unsigned int sh = 0; sh < static_cast<unsigned int> ( this->_shellPlacement.size() ); sh++ )
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) ) )
132 if ( shellNoHlp > 0 ) { shellNoHlp -= 1; }
134 if ( manualShells == 0 ) { this->_noShellsWithData = shellNoHlp; }
137 this->_noShellsWithData = manualShells;
138 if ( manualShells > shellNoHlp )
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;
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(),
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++ )
169 if ( maxDist > this->_shellPlacement.at(sh) ) { shellNoHlp = sh; }
174 if ( manualShells == 0 ) { this->_noShellsWithData = shellNoHlp; }
177 this->_noShellsWithData = manualShells;
178 if ( manualShells > shellNoHlp )
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;
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(),
201 if ( this->_noShellsWithData < 2 )
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;
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(),
223 this->_shellMappedData =
new double*[this->_noShellsWithData];
224 for (
unsigned int sh = 0; sh < this->_noShellsWithData; sh++ )
226 this->_shellMappedData[sh] =
new double[
static_cast<unsigned int> ( this->_thetaAngle * this->_phiAngle )];
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 ) ); }
236 unsigned int posIter;
238 for (
unsigned int sh = 0; sh < this->_noShellsWithData; sh++ )
241 for (
unsigned int thIt = 0; thIt < this->_thetaAngle; thIt++ )
243 for (
unsigned int phIt = 0; phIt < this->_phiAngle; phIt++ )
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 );
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);
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];
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];
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];
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];
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];
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];
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];
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];
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 );
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 );
328 zd = (z - ( ( zBottom -
static_cast<int> ( ((this->_maxMapW+1)/2) ) ) * this->_zSamplingRate ) ) / this->_zSamplingRate;
331 this->_shellMappedData[sh][
static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = ( c0[3] * ( 1.0 - zd ) ) + ( c1[3] * zd );
337 delete[] this->_densityMapCorCoords;
338 this->_densityMapCorCoords =
nullptr;
342 delete[] this->_densityMapCor;
343 this->_densityMapCor =
nullptr;
347 this->_sphereMapped =
true;
365 if ( !this->_sphereMapped )
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;
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(),
387 this->_bandwidthLimit = bandwidth;
388 this->_oneDimmension = this->_bandwidthLimit * 2;
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 ) )];
399 this->_shWorkspace = (fftw_complex *) fftw_malloc (
sizeof(fftw_complex) * ( ( 8 * this->_bandwidthLimit * this->_bandwidthLimit ) +
400 ( 10 * this->_bandwidthLimit ) ) );
402 for (
unsigned int shIt = 0; shIt < this->_noShellsWithData; shIt++ )
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 )];
409 if ( this->_shWorkspace ==
nullptr )
411 std::cerr <<
"!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName <<
" !!! malloc (Memory Allocation) failed for _shWorkspace object in function getSphericalHarmonicsCoeffs." << std::endl;
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(),
431 this->_semiNaiveTable = SemiNaive_Naive_Pml_Table ( this->_bandwidthLimit,
432 this->_bandwidthLimit,
433 this->_semiNaiveTableSpace,
434 reinterpret_cast<double*> ( this->_shWorkspace ) );
437 makeweights ( this->_bandwidthLimit,
438 this->_sphericalHarmonicsWeights );
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 );
459 fftw_iodim howmany_dims[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;
468 dims[0].n = this->_oneDimmension;
470 dims[0].os = this->_oneDimmension;
472 howmany_dims[0].n = this->_oneDimmension;
473 howmany_dims[0].is = this->_oneDimmension;
474 howmany_dims[0].os = 1;
477 fftPlan = fftw_plan_guru_split_dft ( rank,
488 dctPlan = fftw_plan_r2r_1d ( this->_oneDimmension,
490 scratchpad + this->_oneDimmension,
495 for (
unsigned int shIter = 0; shIter < static_cast<unsigned int> ( this->_noShellsWithData ); shIter++ )
498 for (
unsigned int iter = 0; iter < static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension ); iter++ )
500 inputReal[iter] = this->_shellMappedData[shIter][iter];
501 inputZeroes[iter] = 0.0;
505 fftw_execute_split_dft ( fftPlan, inputReal, inputZeroes, rres, ires ) ;
508 for (
unsigned int iter = 0; iter < ( this->_oneDimmension * this->_oneDimmension ); iter++ )
510 rres[iter] *= normCoeff;
511 ires[iter] *= normCoeff;
515 rdataptr = this->_realSHCoeffs[shIter];
516 idataptr = this->_imagSHCoeffs[shIter];
517 for (
unsigned int bandIter = 0; bandIter < this->_bandwidthLimit; bandIter++ )
520 SemiNaiveReduced ( rres + ( bandIter * this->_oneDimmension ),
521 this->_bandwidthLimit,
525 this->_semiNaiveTable[bandIter],
526 this->_sphericalHarmonicsWeights,
530 memcpy ( rdataptr, fltres,
sizeof(
double) * ( this->_bandwidthLimit - bandIter ) );
531 rdataptr += this->_bandwidthLimit - bandIter;
534 SemiNaiveReduced ( ires + ( bandIter * this->_oneDimmension ),
535 this->_bandwidthLimit,
539 this->_semiNaiveTable[bandIter],
540 this->_sphericalHarmonicsWeights,
544 memcpy ( idataptr, fltres,
sizeof(
double) * ( this->_bandwidthLimit - bandIter ) );
545 idataptr += this->_bandwidthLimit - bandIter;
552 for(
unsigned int order = 1; order < this->_bandwidthLimit; order++)
555 for(
unsigned int bandIter = order; bandIter < this->_bandwidthLimit; bandIter++){
557 hlp1 = seanindex ( order, bandIter, this->_bandwidthLimit );
558 hlp2 = seanindex ( -order, bandIter, this->_bandwidthLimit );
560 this->_realSHCoeffs[shIter][hlp2] = powerOne * this->_realSHCoeffs[shIter][hlp1];
561 this->_imagSHCoeffs[shIter][hlp2] = -powerOne * this->_imagSHCoeffs[shIter][hlp1];
567 delete[] inputZeroes;
569 delete[] this->_semiNaiveTable;
570 delete[] this->_semiNaiveTableSpace;
571 delete[] this->_sphericalHarmonicsWeights;
573 fftw_free ( this->_shWorkspace );
575 this->_semiNaiveTable =
nullptr;
576 this->_semiNaiveTableSpace =
nullptr;
577 this->_sphericalHarmonicsWeights =
nullptr;
578 this->_shWorkspace =
nullptr;
580 fftw_destroy_plan ( dctPlan );
581 fftw_destroy_plan ( fftPlan );
584 this->_sphericalCoefficientsComputed =
true;
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?
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.
This class stores all the settings and is passed to the executive classes instead of multitude of par...