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 this->_shellSpacing = shellSz;
110 unsigned int shellNoHlp = 0;
111 double maxDist = std::max ( sqrt( pow( ( (((this->_maxMapU+1)/2)-1) * this->_xSamplingRate ), 2.0 ) +
112 pow ( ( (((this->_maxMapV+1)/2)-1) * this->_ySamplingRate ), 2.0 ) ),
113 std::max ( sqrt( pow( ( (((this->_maxMapU+1)/2)-1) * this->_xSamplingRate ), 2.0 ) +
114 pow ( ( (((this->_maxMapW+1)/2)-1) * this->_zSamplingRate ), 2.0 ) ),
115 sqrt( pow( ( (((this->_maxMapW+1)/2)-1) * this->_zSamplingRate ), 2.0 ) +
116 pow ( ( (((this->_maxMapV+1)/2)-1) * this->_ySamplingRate ), 2.0 ) ) ) );
117 for (
unsigned int sh = 0; sh < static_cast<unsigned int> ( this->_shellPlacement.size() ); sh++ )
119 if ( maxDist > this->_shellPlacement.at(sh) ) { shellNoHlp = sh; }
124 if ( manualShells == 0 ) { this->_noShellsWithData = shellNoHlp; }
125 else { this->_noShellsWithData = manualShells; }
127 if ( this->_noShellsWithData < 2 )
129 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;
133 std::stringstream hlpSS;
134 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>";
135 rvapi_set_text ( hlpSS.str().c_str(),
149 this->_shellMappedData =
new double*[this->_noShellsWithData];
150 for (
unsigned int sh = 0; sh < this->_noShellsWithData; sh++ )
152 this->_shellMappedData[sh] =
new double[
static_cast<unsigned int> ( this->_thetaAngle * this->_phiAngle )];
156 std::vector<double> lonCO ( this->_thetaAngle + 1 );
157 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 ) ); }
158 std::vector<double> latCO ( this->_phiAngle + 1 );
159 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 ) ); }
162 unsigned int posIter;
164 for (
unsigned int sh = 0; sh < this->_noShellsWithData; sh++ )
167 for (
unsigned int thIt = 0; thIt < this->_thetaAngle; thIt++ )
169 for (
unsigned int phIt = 0; phIt < this->_phiAngle; phIt++ )
172 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 );
173 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 );
174 z = this->_shellPlacement.at(sh) * sin( ( static_cast<double> ( latCO.at(phIt) ) + static_cast<double> ( latCO.at(phIt+1) ) ) / 2.0 );
177 xBottom = floor ( (x / this->_xSamplingRate) ) + ((this->_maxMapU+1)/2);
178 yBottom = floor ( (y / this->_ySamplingRate) ) + ((this->_maxMapV+1)/2);
179 zBottom = floor ( (z / this->_zSamplingRate) ) + ((this->_maxMapW+1)/2);
185 posIter = zBottom + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xBottom );
186 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; }
187 c000[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
188 c000[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
189 c000[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
190 c000[3] = this->_densityMapCor[posIter];
192 posIter = zTop + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xBottom );
193 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; }
194 c001[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
195 c001[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
196 c001[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
197 c001[3] = this->_densityMapCor[posIter];
199 posIter = zBottom + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xBottom );
200 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; }
201 c010[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
202 c010[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
203 c010[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
204 c010[3] = this->_densityMapCor[posIter];
206 posIter = zTop + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xBottom );
207 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; }
208 c011[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
209 c011[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
210 c011[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
211 c011[3] = this->_densityMapCor[posIter];
213 posIter = zBottom + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xTop );
214 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; }
215 c100[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
216 c100[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
217 c100[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
218 c100[3] = this->_densityMapCor[posIter];
220 posIter = zTop + (this->_maxMapW + 1) * ( yBottom + (this->_maxMapV + 1) * xTop );
221 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; }
222 c101[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
223 c101[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
224 c101[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
225 c101[3] = this->_densityMapCor[posIter];
227 posIter = zBottom + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xTop );
228 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; }
229 c110[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
230 c110[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
231 c110[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
232 c110[3] = this->_densityMapCor[posIter];
234 posIter = zTop + (this->_maxMapW + 1) * ( yTop + (this->_maxMapV + 1) * xTop );
235 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; }
236 c111[0] = (this->_densityMapCorCoords[posIter])[0] * this->_xSamplingRate;
237 c111[1] = (this->_densityMapCorCoords[posIter])[1] * this->_ySamplingRate;
238 c111[2] = (this->_densityMapCorCoords[posIter])[2] * this->_zSamplingRate;
239 c111[3] = this->_densityMapCor[posIter];
242 xd = (x - ( ( xBottom -
static_cast<int> ( ((this->_maxMapU+1)/2) ) ) * this->_xSamplingRate ) ) / this->_xSamplingRate;
243 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 );
244 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 );
245 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 );
246 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 );
249 yd = (y - ( ( yBottom -
static_cast<int> ( ((this->_maxMapV+1)/2) ) ) * this->_ySamplingRate ) ) / this->_ySamplingRate;
250 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 );
251 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 );
254 zd = (z - ( ( zBottom -
static_cast<int> ( ((this->_maxMapW+1)/2) ) ) * this->_zSamplingRate ) ) / this->_zSamplingRate;
257 this->_shellMappedData[sh][
static_cast<unsigned int> ( phIt * this->_thetaAngle + thIt)] = ( c0[3] * ( 1.0 - zd ) ) + ( c1[3] * zd );
263 delete[] this->_densityMapCorCoords;
264 this->_densityMapCorCoords =
nullptr;
268 delete[] this->_densityMapCor;
269 this->_densityMapCor =
nullptr;
273 this->_sphereMapped =
true;
291 if ( !this->_sphereMapped )
293 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;
297 std::stringstream hlpSS;
298 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>";
299 rvapi_set_text ( hlpSS.str().c_str(),
313 this->_bandwidthLimit = bandwidth;
314 this->_oneDimmension = this->_bandwidthLimit * 2;
317 double *inputReal =
new double [
static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
318 double *inputZeroes =
new double [
static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
319 this->_realSHCoeffs =
new double*[
static_cast<unsigned int> ( this->_noShellsWithData )];
320 this->_imagSHCoeffs =
new double*[
static_cast<unsigned int> ( this->_noShellsWithData )];
321 this->_sphericalHarmonicsWeights =
new double [
static_cast<unsigned int> ( this->_bandwidthLimit * 4 )];
322 this->_semiNaiveTableSpace =
new double [
static_cast<unsigned int> ( Reduced_Naive_TableSize ( this->_bandwidthLimit, this->_bandwidthLimit ) +
323 Reduced_SpharmonicTableSize ( this->_bandwidthLimit, this->_bandwidthLimit ) )];
325 this->_shWorkspace = (fftw_complex *) fftw_malloc (
sizeof(fftw_complex) * ( ( 8 * this->_bandwidthLimit * this->_bandwidthLimit ) +
326 ( 10 * this->_bandwidthLimit ) ) );
328 for (
unsigned int shIt = 0; shIt < this->_noShellsWithData; shIt++ )
330 this->_realSHCoeffs[shIt] =
new double [
static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
331 this->_imagSHCoeffs[shIt] =
new double [
static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension )];
335 if ( this->_shWorkspace ==
nullptr )
337 std::cerr <<
"!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName <<
" !!! malloc (Memory Allocation) failed for _shWorkspace object in function getSphericalHarmonicsCoeffs." << std::endl;
341 std::stringstream hlpSS;
342 hlpSS <<
"<font color=\"red\">" <<
"Cannot allocate memory for spherical harmonics decomposition. Could you have run out of memory?" <<
"</font>";
343 rvapi_set_text ( hlpSS.str().c_str(),
357 this->_semiNaiveTable = SemiNaive_Naive_Pml_Table ( this->_bandwidthLimit,
358 this->_bandwidthLimit,
359 this->_semiNaiveTableSpace,
360 reinterpret_cast<double*> ( this->_shWorkspace ) );
363 makeweights ( this->_bandwidthLimit,
364 this->_sphericalHarmonicsWeights );
375 rres =
reinterpret_cast<double*
> ( this->_shWorkspace );
376 ires = rres + ( this->_oneDimmension * this->_oneDimmension );
377 fltres = ires + ( this->_oneDimmension * this->_oneDimmension );
378 scratchpad = fltres + ( this->_bandwidthLimit );
385 fftw_iodim howmany_dims[1];
388 int howmany_rank = 1;
389 double normCoeff = ( 1.0 / (
static_cast<double> ( this->_oneDimmension ) ) ) * sqrt( 2.0 * M_PI );
390 double powerOne = 1.0;
391 unsigned int hlp1 = 0;
392 unsigned int hlp2 = 0;
394 dims[0].n = this->_oneDimmension;
396 dims[0].os = this->_oneDimmension;
398 howmany_dims[0].n = this->_oneDimmension;
399 howmany_dims[0].is = this->_oneDimmension;
400 howmany_dims[0].os = 1;
403 fftPlan = fftw_plan_guru_split_dft ( rank,
414 dctPlan = fftw_plan_r2r_1d ( this->_oneDimmension,
416 scratchpad + this->_oneDimmension,
421 for (
unsigned int shIter = 0; shIter < static_cast<unsigned int> ( this->_noShellsWithData ); shIter++ )
424 for (
unsigned int iter = 0; iter < static_cast<unsigned int> ( this->_oneDimmension * this->_oneDimmension ); iter++ )
426 inputReal[iter] = this->_shellMappedData[shIter][iter];
427 inputZeroes[iter] = 0.0;
431 fftw_execute_split_dft ( fftPlan, inputReal, inputZeroes, rres, ires ) ;
434 for (
unsigned int iter = 0; iter < ( this->_oneDimmension * this->_oneDimmension ); iter++ )
436 rres[iter] *= normCoeff;
437 ires[iter] *= normCoeff;
441 rdataptr = this->_realSHCoeffs[shIter];
442 idataptr = this->_imagSHCoeffs[shIter];
443 for (
unsigned int bandIter = 0; bandIter < this->_bandwidthLimit; bandIter++ )
446 SemiNaiveReduced ( rres + ( bandIter * this->_oneDimmension ),
447 this->_bandwidthLimit,
451 this->_semiNaiveTable[bandIter],
452 this->_sphericalHarmonicsWeights,
456 memcpy ( rdataptr, fltres,
sizeof(
double) * ( this->_bandwidthLimit - bandIter ) );
457 rdataptr += this->_bandwidthLimit - bandIter;
460 SemiNaiveReduced ( ires + ( bandIter * this->_oneDimmension ),
461 this->_bandwidthLimit,
465 this->_semiNaiveTable[bandIter],
466 this->_sphericalHarmonicsWeights,
470 memcpy ( idataptr, fltres,
sizeof(
double) * ( this->_bandwidthLimit - bandIter ) );
471 idataptr += this->_bandwidthLimit - bandIter;
478 for(
unsigned int order = 1; order < this->_bandwidthLimit; order++)
481 for(
unsigned int bandIter = order; bandIter < this->_bandwidthLimit; bandIter++){
483 hlp1 = seanindex ( order, bandIter, this->_bandwidthLimit );
484 hlp2 = seanindex ( -order, bandIter, this->_bandwidthLimit );
486 this->_realSHCoeffs[shIter][hlp2] = powerOne * this->_realSHCoeffs[shIter][hlp1];
487 this->_imagSHCoeffs[shIter][hlp2] = -powerOne * this->_imagSHCoeffs[shIter][hlp1];
493 delete[] inputZeroes;
495 delete[] this->_semiNaiveTable;
496 delete[] this->_semiNaiveTableSpace;
497 delete[] this->_sphericalHarmonicsWeights;
499 fftw_free ( this->_shWorkspace );
501 this->_semiNaiveTable =
nullptr;
502 this->_semiNaiveTableSpace =
nullptr;
503 this->_sphericalHarmonicsWeights =
nullptr;
504 this->_shWorkspace =
nullptr;
506 fftw_destroy_plan ( dctPlan );
507 fftw_destroy_plan ( fftPlan );
510 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...