ProSHADE  0.6.5 (NOV 2018)
Protein Shape Descriptors and Symmetry Detection
ProSHADE_clipper.cpp
Go to the documentation of this file.
1 
19 //============================================ Clipper
20 #include <clipper/clipper.h>
21 #include <clipper/clipper-contrib.h>
22 #include <clipper/clipper-ccp4.h>
23 #include <clipper/clipper-mmdb.h>
24 #include <clipper/clipper-minimol.h>
25 
26 //============================================ FFTW3 + SOFT
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 #include <fftw3.h>
31 #include <wrap_fftw.h>
32 #include <makeweights.h>
33 #include <s2_primitive.h>
34 #include <s2_cospmls.h>
35 #include <s2_legendreTransforms.h>
36 #include <s2_semi_fly.h>
37 #include <rotate_so3_utils.h>
38 #include <utils_so3.h>
39 #include <soft_fftw.h>
40 #include <rotate_so3_fftw.h>
41 #ifdef __cplusplus
42 }
43 #endif
44 
45 //============================================ CMAPLIB
46 #include <cmaplib.h>
47 
48 //============================================ RVAPI
49 #include <rvapi_interface.h>
50 
51 //============================================ ProSHADE
52 #include "ProSHADE.h"
53 #include "ProSHADE_internal.h"
54 #include "ProSHADE_misc.h"
55 
78  double *shellDistance,
79  double resolution,
80  unsigned int *bandwidth,
81  unsigned int *theta,
82  unsigned int *phi,
83  unsigned int *glIntegOrder,
84  double *extraSpace,
85  bool mapResDefault,
87  double Bfactor,
88  bool hpFirstLineCom,
89  bool overlayDefaults )
90 {
91  //======================================== Initialise internal values
92  this->_inputFileName = fileName;
93  this->_mapResolution = resolution;
94  if ( mapResDefault && overlayDefaults && resolution == 2.0 ) { this->_mapResolution = 2.0; }
95  this->_shellSpacing = *shellDistance;
96  this->_maxExtraCellularSpace = *extraSpace;
97  this->_firstLineCOM = hpFirstLineCom;
98 
99  //======================================== Read in file
100  clipper::mmdb::CMMDBManager *mfile = new clipper::mmdb::CMMDBManager ( );
101  if ( mfile->ReadCoorFile ( this->_inputFileName.c_str() ) )
102  {
103  std::cerr << "!!! ProSHADE ERROR !!! Cannot read file: " << this->_inputFileName.c_str() << std::endl;
104 
105  if ( settings->htmlReport )
106  {
107  std::stringstream hlpSS;
108  hlpSS << "<font color=\"red\">" << "Cannot open file: " << this->_inputFileName.c_str() << "</font>";
109  rvapi_set_text ( hlpSS.str().c_str(),
110  "ProgressSection",
111  settings->htmlReportLineProgress,
112  1,
113  1,
114  1 );
115  settings->htmlReportLineProgress += 1;
116  rvapi_flush ( );
117  }
118 
119  exit ( -1 );
120  }
121 
122  //======================================== Find axis ranges & change B-factors if required
123  double maxX = 0.0;
124  double minX = 0.0;
125  double maxY = 0.0;
126  double minY = 0.0;
127  double maxZ = 0.0;
128  double minZ = 0.0;
129  bool firstAtom = true;
130 
131  double xVal, yVal, zVal;
132 
133  //======================================== Initialise MMDB crawl
134  int noChains = 0;
135  int noResidues = 0;
136  int noAtoms = 0;
137 
138  clipper::mmdb::PPCChain chain;
139  clipper::mmdb::PPCResidue residue;
140  clipper::mmdb::PPCAtom atom;
141 
142  double pdbXCom = 0.0;
143  double pdbYCom = 0.0;
144  double pdbZCom = 0.0;
145  double bFacTot = 0.0;
146 
147  //======================================== Get all chains
148  mfile->GetChainTable ( 1, chain, noChains );
149  firstAtom = true;
150  for ( unsigned int nCh = 0; nCh < static_cast<unsigned int> ( noChains ); nCh++ )
151  {
152  if ( chain[nCh] )
153  {
154  //================================ Get all residues
155  chain[nCh]->GetResidueTable ( residue, noResidues );
156 
157  for ( unsigned int nRes = 0; nRes < static_cast<unsigned int> ( noResidues ); nRes++ )
158  {
159  if ( residue[nRes] )
160  {
161  //======================== Get all atoms
162  residue[nRes]->GetAtomTable ( atom, noAtoms );
163 
164  for ( unsigned int aNo = 0; aNo < static_cast<unsigned int> ( noAtoms ); aNo++ )
165  {
166  if ( atom[aNo] )
167  {
168  //================ Check for termination 'residue'
169  if ( atom[aNo]->Ter ) { continue; }
170 
171  //================ Find axis maxs and mins
172  if ( firstAtom )
173  {
174  maxX = atom[aNo]->x;
175  minX = atom[aNo]->x;
176  maxY = atom[aNo]->y;
177  minY = atom[aNo]->y;
178  maxZ = atom[aNo]->z;
179  minZ = atom[aNo]->z;
180 
181  pdbXCom += atom[aNo]->x;
182  pdbYCom += atom[aNo]->y;
183  pdbZCom += atom[aNo]->z;
184  if ( Bfactor != 0.0 )
185  {
186  bFacTot += 1.0;
187  }
188  else
189  {
190  bFacTot += atom[aNo]->tempFactor;
191  }
192 
193 
194  firstAtom = false;
195  }
196  else
197  {
198  xVal = atom[aNo]->x;
199  yVal = atom[aNo]->y;
200  zVal = atom[aNo]->z;
201  if ( xVal > maxX ) { maxX = xVal; } if ( xVal < minX ) { minX = xVal; }
202  if ( yVal > maxY ) { maxY = yVal; } if ( yVal < minY ) { minY = yVal; }
203  if ( zVal > maxZ ) { maxZ = zVal; } if ( zVal < minZ ) { minZ = zVal; }
204 
205  if ( Bfactor != 0.0 )
206  {
207  bFacTot += 1.0;
208  pdbXCom += atom[aNo]->x;
209  pdbYCom += atom[aNo]->y;
210  pdbZCom += atom[aNo]->z;
211  }
212  else
213  {
214  bFacTot += atom[aNo]->tempFactor;
215  pdbXCom += atom[aNo]->x * atom[aNo]->tempFactor;
216  pdbYCom += atom[aNo]->y * atom[aNo]->tempFactor;
217  pdbZCom += atom[aNo]->z * atom[aNo]->tempFactor;
218  }
219  }
220  }
221  }
222  }
223  }
224  }
225  }
226 
227  //======================================== Determine original PDB COM
228  pdbXCom /= bFacTot;
229  pdbYCom /= bFacTot;
230  pdbZCom /= bFacTot;
231 
232  //======================================== Determine max dimensions
233  this->_xRange = (maxX - minX);
234  this->_yRange = (maxY - minY);
235  this->_zRange = (maxZ - minZ);
236  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
237 
238  //======================================== Save extracellular space and use internal value to avoid issues with clipper map computation
239  this->_maxExtraCellularSpace = *extraSpace;
240  double ecsHlp = std::floor ( std::max ( 20.0, ( this->_maxMapRange / 4.0 ) ) );
241 
242  //======================================== Determine max dimensions
243  this->_xRange = (maxX - minX) + ecsHlp;
244  this->_yRange = (maxY - minY) + ecsHlp;
245  this->_zRange = (maxZ - minZ) + ecsHlp;
246  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
247 
248  //======================================== Move structure to middle of map
249  double xMov = (ecsHlp/2.0) - minX;
250  double yMov = (ecsHlp/2.0) - minY;
251  double zMov = (ecsHlp/2.0) - minZ;
252 
253  //======================================== Move structure to the center of map
254  mfile->GetChainTable ( 1, chain, noChains );
255  firstAtom = true;
256  for ( unsigned int nCh = 0; nCh < static_cast<unsigned int> ( noChains ); nCh++ )
257  {
258  if ( chain[nCh] )
259  {
260  //================================ Get all residues
261  chain[nCh]->GetResidueTable ( residue, noResidues );
262 
263  for ( unsigned int nRes = 0; nRes < static_cast<unsigned int> ( noResidues ); nRes++ )
264  {
265  if ( residue[nRes] )
266  {
267  //======================== Get all atoms
268  residue[nRes]->GetAtomTable ( atom, noAtoms );
269 
270  for ( unsigned int aNo = 0; aNo < static_cast<unsigned int> ( noAtoms ); aNo++ )
271  {
272  if ( atom[aNo] )
273  {
274  //================ Check for termination 'residue'
275  if ( atom[aNo]->Ter ) { continue; }
276 
277  if ( Bfactor != 0.0 )
278  {
279  atom[aNo]->SetCoordinates ( atom[aNo]->x + xMov,
280  atom[aNo]->y + yMov,
281  atom[aNo]->z + zMov,
282  atom[aNo]->occupancy,
283  Bfactor );
284  }
285  else
286  {
287  atom[aNo]->SetCoordinates ( atom[aNo]->x + xMov,
288  atom[aNo]->y + yMov,
289  atom[aNo]->z + zMov,
290  atom[aNo]->occupancy,
291  atom[aNo]->tempFactor );
292  }
293  }
294 
295  if ( firstAtom )
296  {
297  this->_xCorrErr = atom[aNo]->x;
298  this->_yCorrErr = atom[aNo]->y;
299  this->_zCorrErr = atom[aNo]->z;
300  firstAtom = false;
301  }
302  }
303  }
304  }
305  }
306  }
307 
308  //======================================== Initialise map variables
309  clipper::Spacegroup spgr ( clipper::Spacegroup::P1 );
310  clipper::Cell cell ( clipper::Cell_descr ( this->_xRange, this->_yRange, this->_zRange ) );
311  clipper::Resolution reso = clipper::Resolution ( this->_mapResolution );
312  const clipper::Grid_sampling grid ( spgr, cell, reso );
313  clipper::Xmap<float> *densityMap = new clipper::Xmap<float> ( spgr, cell, grid );
314 
315  //======================================== Get Map
316  int hndl = mfile->NewSelection ( );
317  mfile->SelectAtoms ( hndl, 0, 0, ::mmdb::SKEY_NEW );
318  mfile->GetSelIndex ( hndl, atom, noAtoms );
319  clipper::MMDBAtom_list *aList = new clipper::MMDBAtom_list ( atom, noAtoms );
320  clipper::EDcalc_aniso<clipper::ftype32> edCalc;
321  edCalc ( *densityMap, *aList );
322 
323  //======================================== Free memory
324  delete mfile;
325 
326  //======================================== Find max U, V and W
327  clipper::Xmap_base::Map_reference_index LastPos = (*densityMap).first();
328  clipper::Xmap_base::Map_reference_index PrevPos = (*densityMap).first();
329  for ( LastPos = (*densityMap).first(); !LastPos.last(); LastPos.next() ) { PrevPos = LastPos; }
330  this->_maxMapU = PrevPos.coord().u();
331  this->_maxMapV = PrevPos.coord().v();
332  this->_maxMapW = PrevPos.coord().w();
333 
334  //======================================== Convert clipper Xmap to my map format
335  // ... Allocate map data memory
336  this->_densityMapMap = (float*) malloc ( ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) * sizeof ( float ) );
337  if ( this->_densityMapMap == nullptr )
338  {
339  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
340 
341  if ( settings->htmlReport )
342  {
343  std::stringstream hlpSS;
344  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
345  rvapi_set_text ( hlpSS.str().c_str(),
346  "ProgressSection",
347  settings->htmlReportLineProgress,
348  1,
349  1,
350  1 );
351  settings->htmlReportLineProgress += 1;
352  rvapi_flush ( );
353  }
354 
355  exit ( -1 );
356  }
357 
358  // ... and copy
359  int arrPos = 0;
360  for ( unsigned int uIt = 0; uIt < (this->_maxMapU+1); uIt++ )
361  {
362  for ( unsigned int vIt = 0; vIt < (this->_maxMapV+1); vIt++ )
363  {
364  for ( unsigned int wIt = 0; wIt < (this->_maxMapW+1); wIt++ )
365  {
366  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
367 
368  clipper::Vec3<int> pos ( uIt, vIt, wIt );
369  clipper::Coord_grid cg ( pos );
370 
371  this->_densityMapMap[arrPos] = densityMap->get_data ( cg );
372  }
373  }
374  }
375 
376  //======================================== Free memory
377  if ( densityMap != nullptr )
378  {
379  delete densityMap;
380  densityMap = nullptr;
381  }
382 
383  //======================================== Set internal map parameters
384  this->_xFrom = 0;
385  this->_yFrom = 0;
386  this->_zFrom = 0;
387 
388  this->_xTo = this->_maxMapU;
389  this->_yTo = this->_maxMapV;
390  this->_zTo = this->_maxMapW;
391 
392  //======================================== Remove the extra space added for the map calculation
393  // ... Find new settings
394  maxX = -1.0;
395  maxY = -1.0;
396  maxZ = -1.0;
397 
398  minX = this->_maxMapU;
399  minY = this->_maxMapV;
400  minZ = this->_maxMapW;
401  for ( unsigned int uIt = 0; uIt < (this->_maxMapU+1); uIt++ )
402  {
403  for ( unsigned int vIt = 0; vIt < (this->_maxMapV+1); vIt++ )
404  {
405  for ( unsigned int wIt = 0; wIt < (this->_maxMapW+1); wIt++ )
406  {
407  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
408  if ( this->_densityMapMap[arrPos] > 0.005 )
409  {
410  if ( maxX < uIt ) { maxX = uIt; } if ( minX > uIt ) { minX = uIt; }
411  if ( maxY < vIt ) { maxY = vIt; } if ( minY > vIt ) { minY = vIt; }
412  if ( maxZ < wIt ) { maxZ = wIt; } if ( minZ > wIt ) { minZ = wIt; }
413  }
414  }
415  }
416  }
417 
418  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
419  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
420  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
421 
422  this->_xRange = this->_xRange - ( this->_maxMapU - ( maxX - minX ) ) * this->_xSamplingRate;
423  this->_yRange = this->_yRange - ( this->_maxMapV - ( maxY - minY ) ) * this->_ySamplingRate;
424  this->_zRange = this->_zRange - ( this->_maxMapW - ( maxZ - minZ ) ) * this->_zSamplingRate;
425  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
426 
427  // ... Create new map and fill it with data
428  float *hlpMap = nullptr;
429  hlpMap = (float*) malloc ( static_cast<int>( (maxX - minX + 1) * (maxY - minY + 1) * (maxZ - minZ + 1) ) * sizeof ( float ) );
430  if ( hlpMap == nullptr )
431  {
432  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
433 
434  if ( settings->htmlReport )
435  {
436  std::stringstream hlpSS;
437  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
438  rvapi_set_text ( hlpSS.str().c_str(),
439  "ProgressSection",
440  settings->htmlReportLineProgress,
441  1,
442  1,
443  1 );
444  settings->htmlReportLineProgress += 1;
445  rvapi_flush ( );
446  }
447 
448  exit ( -1 );
449  }
450 
451  unsigned int newU, newV, newW, hlpPos;
452  for ( int uIt = 0; uIt < static_cast<int> (maxX - minX + 1); uIt++ )
453  {
454  for ( int vIt = 0; vIt < static_cast<int> (maxY - minY + 1); vIt++ )
455  {
456  for ( int wIt = 0; wIt < static_cast<int> (maxZ - minZ + 1); wIt++ )
457  {
458  newU = (uIt + minX);
459  newV = (vIt + minY);
460  newW = (wIt + minZ);
461 
462  hlpPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
463  arrPos = wIt + (maxZ - minZ + 1) * ( vIt + (maxY - minY + 1) * uIt );
464 
465  hlpMap[arrPos] = this->_densityMapMap[hlpPos];
466  }
467  }
468  }
469 
470  this->_maxMapU = maxX - minX;
471  this->_maxMapV = maxY - minY;
472  this->_maxMapW = maxZ - minZ;
473 
474  this->_xTo = maxX - minX;
475  this->_yTo = maxY - minY;
476  this->_zTo = maxZ - minZ;
477 
478  // ... Copy
479  if ( this->_densityMapMap != nullptr )
480  {
481  free ( this->_densityMapMap );
482  this->_densityMapMap = nullptr;
483  }
484 
485  this->_densityMapMap = (float*) malloc ( ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ) * sizeof ( float ) );
486  if ( this->_densityMapMap == nullptr )
487  {
488  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
489 
490  if ( settings->htmlReport )
491  {
492  std::stringstream hlpSS;
493  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
494  rvapi_set_text ( hlpSS.str().c_str(),
495  "ProgressSection",
496  settings->htmlReportLineProgress,
497  1,
498  1,
499  1 );
500  settings->htmlReportLineProgress += 1;
501  rvapi_flush ( );
502  }
503 
504  exit ( -1 );
505  }
506 
507  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
508  {
509  this->_densityMapMap[iter] = hlpMap[iter];
510  }
511 
512  if ( hlpMap != nullptr )
513  {
514  free ( hlpMap );
515  hlpMap = nullptr;
516  }
517 
518  if ( this->_maxExtraCellularSpace == -777.7 )
519  {
520  this->_maxExtraCellularSpace = std::max ( 20.0, ( std::max( this->_xRange, std::max ( this->_yRange, this->_zRange ) ) - std::min( this->_xRange, std::min ( this->_yRange, this->_zRange ) ) ) );
521  *extraSpace = this->_maxExtraCellularSpace;
522  }
523 
524  if ( this->_maxExtraCellularSpace != 0.0 )
525  {
526  //==================================== Compute new stats
527  int xDiff = static_cast<int> ( std::ceil ( ( this->_xRange + this->_maxExtraCellularSpace ) / this->_xSamplingRate ) - this->_maxMapU );
528  int yDiff = static_cast<int> ( std::ceil ( ( this->_yRange + this->_maxExtraCellularSpace ) / this->_ySamplingRate ) - this->_maxMapV );
529  int zDiff = static_cast<int> ( std::ceil ( ( this->_zRange + this->_maxExtraCellularSpace ) / this->_zSamplingRate ) - this->_maxMapW );
530 
531  this->_xRange += xDiff * this->_xSamplingRate;
532  this->_yRange += yDiff * this->_ySamplingRate;
533  this->_zRange += zDiff * this->_zSamplingRate;
534 
535  if ( xDiff % 2 != 0 )
536  {
537  this->_xRange += this->_xSamplingRate;
538  xDiff = static_cast<int> ( std::ceil ( this->_xRange / this->_xSamplingRate ) - ( this->_maxMapU + 1 ) );
539  }
540  if ( yDiff % 2 != 0 )
541  {
542  this->_yRange += this->_ySamplingRate;
543  yDiff = static_cast<int> ( std::ceil ( this->_yRange / this->_ySamplingRate ) - ( this->_maxMapV + 1 ) );
544  }
545  if ( zDiff % 2 != 0 )
546  {
547  this->_zRange += this->_zSamplingRate;
548  zDiff = static_cast<int> ( std::ceil ( this->_zRange / this->_zSamplingRate ) - ( this->_maxMapW + 1 ) );
549  }
550  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
551 
552  xDiff /= 2;
553  yDiff /= 2;
554  zDiff /= 2;
555 
556  this->_xFrom -= xDiff;
557  this->_yFrom -= yDiff;
558  this->_zFrom -= zDiff;
559 
560  this->_xTo += xDiff;
561  this->_yTo += yDiff;
562  this->_zTo += zDiff;
563 
564  this->_maxMapU = this->_xTo - this->_xFrom;
565  this->_maxMapV = this->_yTo - this->_yFrom;
566  this->_maxMapW = this->_zTo - this->_zFrom;
567 
568  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
569  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
570  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
571 
572  //==================================== Move the map
573  hlpMap = nullptr;
574  hlpMap = (float*) malloc ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) * sizeof ( float ) );
575  if ( hlpMap == nullptr )
576  {
577  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map moving data. Terminating... " << std::endl;
578 
579  if ( settings->htmlReport )
580  {
581  std::stringstream hlpSS;
582  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for moving the map data. Did you run out of memory?" << "</font>";
583  rvapi_set_text ( hlpSS.str().c_str(),
584  "ProgressSection",
585  settings->htmlReportLineProgress,
586  1,
587  1,
588  1 );
589  settings->htmlReportLineProgress += 1;
590  rvapi_flush ( );
591  }
592 
593  exit ( -1 );
594  }
595  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
596  {
597  hlpMap[iter] = 0.0;
598  }
599 
600  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
601  {
602  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
603  {
604  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
605  {
606  if ( ( uIt < xDiff ) || ( uIt > static_cast<int> ( this->_maxMapU - xDiff ) ) ||
607  ( vIt < yDiff ) || ( vIt > static_cast<int> ( this->_maxMapV - yDiff ) ) ||
608  ( wIt < zDiff ) || ( wIt > static_cast<int> ( this->_maxMapW - zDiff ) ) )
609  {
610  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
611  hlpMap[hlpPos] = 0.0;
612  }
613  else
614  {
615  newU = (uIt - xDiff);
616  newV = (vIt - yDiff);
617  newW = (wIt - zDiff);
618 
619  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
620  arrPos = newW + (this->_maxMapW + 1 - zDiff * 2) * ( newV + (this->_maxMapV + 1 - yDiff * 2) * newU );
621 
622  hlpMap[hlpPos] = this->_densityMapMap[arrPos];
623  }
624  }
625  }
626  }
627 
628  //==================================== Free memory
629  if ( this->_densityMapMap != nullptr )
630  {
631  free ( this->_densityMapMap );
632  this->_densityMapMap = nullptr;
633  }
634 
635  //==================================== Copy
636  this->_densityMapMap = (float*) malloc ( ((this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1)) * sizeof ( float ) );
637  if ( this->_densityMapMap == nullptr )
638  {
639  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
640 
641  if ( settings->htmlReport )
642  {
643  std::stringstream hlpSS;
644  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
645  rvapi_set_text ( hlpSS.str().c_str(),
646  "ProgressSection",
647  settings->htmlReportLineProgress,
648  1,
649  1,
650  1 );
651  settings->htmlReportLineProgress += 1;
652  rvapi_flush ( );
653  }
654 
655  exit ( -1 );
656  }
657  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
658  {
659  this->_densityMapMap[iter] = hlpMap[iter];
660  }
661 
662  //==================================== Free memory
663  if ( hlpMap != nullptr )
664  {
665  free ( hlpMap );
666  hlpMap = nullptr;
667  }
668  }
669 
670  //======================================== Determine sampling ranges
671  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
672  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
673  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
674  double maxSamplingRate = std::max ( this->_xSamplingRate, std::max( this->_ySamplingRate, this->_zSamplingRate ) );
675 
676  //======================================== Make sure map matches original PDB in visualisation
677  double mapXCom = 0.0;
678  double mapYCom = 0.0;
679  double mapZCom = 0.0;
680  double densTot = 0.0;
681  for ( unsigned int uIt = 0; uIt < static_cast<unsigned int> ( (this->_maxMapU+1) ); uIt++ )
682  {
683  for ( unsigned int vIt = 0; vIt < static_cast<unsigned int> ( (this->_maxMapV+1) ); vIt++ )
684  {
685  for ( unsigned int wIt = 0; wIt < static_cast<unsigned int> ( (this->_maxMapW+1) ); wIt++ )
686  {
687  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
688 
689  mapXCom += uIt * this->_densityMapMap[arrPos];
690  mapYCom += vIt * this->_densityMapMap[arrPos];
691  mapZCom += wIt * this->_densityMapMap[arrPos];
692  densTot += this->_densityMapMap[arrPos];
693  }
694  }
695  }
696 
697  mapXCom /= densTot;
698  mapYCom /= densTot;
699  mapZCom /= densTot;
700 
701  mapXCom = ( mapXCom + this->_xFrom ) * this->_xSamplingRate;
702  mapYCom = ( mapYCom + this->_yFrom ) * this->_ySamplingRate;
703  mapZCom = ( mapZCom + this->_zFrom ) * this->_zSamplingRate;
704 
705  double mapXMove = ( pdbXCom - mapXCom ) / this->_xSamplingRate;
706  double mapYMove = ( pdbYCom - mapYCom ) / this->_ySamplingRate;
707  double mapZMove = ( pdbZCom - mapZCom ) / this->_zSamplingRate;
708 
709  this->_xFrom += std::round ( mapXMove );
710  this->_xTo += std::round ( mapXMove );
711  this->_yFrom += std::round ( mapYMove );
712  this->_yTo += std::round ( mapYMove );
713  this->_zFrom += std::round ( mapZMove );
714  this->_zTo += std::round ( mapZMove );
715 
716  bool xFSignChange = false;
717  if ( ( ( ( this->_xFrom - std::round ( mapXMove ) ) < 0 ) && ( this->_xFrom > 0 ) ) ||
718  ( ( ( this->_xFrom - std::round ( mapXMove ) ) > 0 ) && ( this->_xFrom < 0 ) ) ) { xFSignChange = true; }
719  bool xTSignChange = false;
720  if ( ( ( ( this->_xTo - std::round ( mapXMove ) ) < 0 ) && ( this->_xTo > 0 ) ) ||
721  ( ( ( this->_xTo - std::round ( mapXMove ) ) > 0 ) && ( this->_xTo < 0 ) ) ) { xTSignChange = true; }
722 
723  bool yFSignChange = false;
724  if ( ( ( ( this->_yFrom - std::round ( mapYMove ) ) < 0 ) && ( this->_yFrom > 0 ) ) ||
725  ( ( ( this->_yFrom - std::round ( mapYMove ) ) > 0 ) && ( this->_yFrom < 0 ) ) ) { yFSignChange = true; }
726  bool yTSignChange = false;
727  if ( ( ( ( this->_yTo - std::round ( mapYMove ) ) < 0 ) && ( this->_yTo > 0 ) ) ||
728  ( ( ( this->_yTo - std::round ( mapYMove ) ) > 0 ) && ( this->_yTo < 0 ) ) ) { yTSignChange = true; }
729 
730  bool zFSignChange = false;
731  if ( ( ( ( this->_zFrom - std::round ( mapZMove ) ) < 0 ) && ( this->_zFrom > 0 ) ) ||
732  ( ( ( this->_zFrom - std::round ( mapZMove ) ) > 0 ) && ( this->_zFrom < 0 ) ) ) { zFSignChange = true; }
733  bool zTSignChange = false;
734  if ( ( ( ( this->_zTo - std::round ( mapZMove ) ) < 0 ) && ( this->_zTo > 0 ) ) ||
735  ( ( ( this->_zTo - std::round ( mapZMove ) ) > 0 ) && ( this->_zTo < 0 ) ) ) { zTSignChange = true; }
736 
737  if ( ( xFSignChange && !xTSignChange ) || ( !xFSignChange && xTSignChange ) )
738  {
739  this->_xTo += 1;
740  }
741  if ( ( yFSignChange && !yTSignChange ) || ( !yFSignChange && yTSignChange ) )
742  {
743  this->_yTo += 1;
744  }
745  if ( ( zFSignChange && !zTSignChange ) || ( !zFSignChange && zTSignChange ) )
746  {
747  this->_zTo += 1;
748  }
749 
750  //======================================== Decide shell spacing, if not already decided
751  if ( *shellDistance == 0 )
752  {
753  settings->shellSpacing = maxSamplingRate / 2.0;
754  this->_shellSpacing = maxSamplingRate / 2.0;
755  *shellDistance = this->_shellSpacing;
756 
757  if ( overlayDefaults )
758  {
759  settings->shellSpacing *= 2.0;
760  this->_shellSpacing *= 2.0;
761  *shellDistance *= 2.0;
762  }
763 
764  while ( std::floor ( this->_maxMapRange / this->_shellSpacing ) < 20 )
765  {
766  this->_shellSpacing /= 2.0;
767  settings->shellSpacing /= 2.0;
768  *shellDistance /= 2.0;
769  }
770  }
771 
772  //======================================== Automatically determine maximum number of shells
773  this->_shellPlacement = std::vector<double> ( std::floor ( this->_maxMapRange / this->_shellSpacing ) );
774 
775  for ( unsigned int shellIter = 0; shellIter < static_cast<unsigned int> ( this->_shellPlacement.size() ); shellIter++ )
776  {
777  this->_shellPlacement.at(shellIter) = (shellIter+1) * this->_shellSpacing;
778  }
779 
780  //======================================== If bandwidth is not given, determine it
781  if ( *bandwidth == 0 )
782  {
783  *bandwidth = std::ceil ( std::ceil ( ( ( std::ceil ( this->_maxMapRange / this->_shellSpacing ) *
784  this->_shellSpacing ) / maxSamplingRate ) * 2.0 ) / 2.0 );
785  }
786  if ( settings->maxRotError != 0 )
787  {
788  *bandwidth = static_cast<unsigned int> ( 180 / settings->maxRotError );
789  this->_wasBandwithGiven = true;
790  }
791 
792  //======================================== If theta and phi are not given, determine them
793  if ( *theta == 0 ) { *theta = 2 * (*bandwidth); }
794  if ( *phi == 0 ) { *phi = 2 * (*bandwidth); }
795 
796  //======================================== If Gauss-Legendre integration order is not given, decide it
797  if ( *glIntegOrder == 0 )
798  {
799  double distPerPointFraction = ( ( this->_maxMapRange / 2.0 ) / static_cast<double> ( *bandwidth / 2 ) ) / ( this->_maxMapRange / 2.0 );
800 
801  for ( unsigned int iter = 2; iter < static_cast<unsigned int> ( ProSHADE_internal_misc::glIntMaxDists.size() ); iter++ )
802  {
803  if ( ProSHADE_internal_misc::glIntMaxDists.at(iter) >= distPerPointFraction )
804  {
805  *glIntegOrder = iter;
806  }
807  }
808  }
809 
810  //======================================== Done
811  this->_densityMapComputed = true;
812  this->_fromPDB = true;
813 
814 }
815 
836  double *shellDistance,
837  double resolution,
838  unsigned int *bandwidth,
839  unsigned int *theta,
840  unsigned int *phi,
841  unsigned int *glIntegOrder,
842  double *extraSpace,
843  bool mapResDefault,
844  bool rotDefaults,
845  ProSHADE::ProSHADE_settings* settings,
846  bool overlayDefaults )
847 {
848  //======================================== Initialise internal values
849  this->_inputFileName = fileName;
850  this->_shellSpacing = *shellDistance;
851  this->_mapResolution = resolution;
852  if ( mapResDefault && overlayDefaults ) { this->_mapResolution = 3.0; }
853  if ( *extraSpace == -777.7 ) { *extraSpace= 0.0; std::cout << "!!! ProSHADE WARNING !!! Using the overlay mode with no extra space around the map. This can lead to incorrect rotation and translation as well as artefacts, unless your map has enough empty space around it density. If not, please use the \"--cellBorderSpace\" command line option to add some empty space." << std::endl; }
854  this->_maxExtraCellularSpace = *extraSpace;
855  this->_firstLineCOM = false;
856 
857  //======================================== Initialise local variables
858  CMap_io::CMMFile *mapFile = nullptr;
859  float *cell = nullptr;
860  int *dim = nullptr;
861  int *grid = nullptr;
862  int *order = nullptr;
863  int *orig = nullptr;
864  int myMapMode = 0;
865  double cornerAvg = 0.0;
866  double centralAvg = 0.0;
867  double cornerCount = 0.0;
868  double centralCount = 0.0;
869 
870  //======================================== Allocate memory
871  cell = (float*) malloc ( 6 * sizeof ( float ) );
872  dim = (int* ) malloc ( 3 * sizeof ( int ) );
873  grid = (int* ) malloc ( 3 * sizeof ( int ) );
874  order = (int* ) malloc ( 3 * sizeof ( int ) );
875  orig = (int* ) malloc ( 3 * sizeof ( int ) );
876 
877  if ( ( cell == nullptr ) || ( dim == nullptr ) || ( order == nullptr ) || ( orig == nullptr ) || ( grid == nullptr ) )
878  {
879  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory. Terminating... " << std::endl;
880 
881  if ( settings->htmlReport )
882  {
883  std::stringstream hlpSS;
884  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
885  rvapi_set_text ( hlpSS.str().c_str(),
886  "ProgressSection",
887  settings->htmlReportLineProgress,
888  1,
889  1,
890  1 );
891  settings->htmlReportLineProgress += 1;
892  rvapi_flush ( );
893  }
894 
895  exit ( -1 );
896  }
897 
898  //======================================== Read in the MAP file info
899  mapFile = reinterpret_cast<CMap_io::CMMFile*> ( CMap_io::ccp4_cmap_open ( fileName.c_str() , myMapMode ) );
900  if ( mapFile == nullptr )
901  {
902  std::cerr << "!!! ProSHADE ERROR !!! Failed to open the file " << fileName << ". Check for typos and corruption of the file. Terminating..." << std::endl;
903 
904  if ( settings->htmlReport )
905  {
906  std::stringstream hlpSS;
907  hlpSS << "<font color=\"red\">" << "Cannot open the file " << fileName << " . Could it be corrupted?" << "</font>";
908  rvapi_set_text ( hlpSS.str().c_str(),
909  "ProgressSection",
910  settings->htmlReportLineProgress,
911  1,
912  1,
913  1 );
914  settings->htmlReportLineProgress += 1;
915  rvapi_flush ( );
916  }
917 
918  exit ( -1 );
919  }
920 
921  CMap_io::ccp4_cmap_get_cell ( mapFile, cell );
922  CMap_io::ccp4_cmap_get_dim ( mapFile, dim );
923  CMap_io::ccp4_cmap_get_grid ( mapFile, grid );
924  CMap_io::ccp4_cmap_get_order ( mapFile, order );
925  CMap_io::ccp4_cmap_get_origin ( mapFile, orig );
926 
927  //======================================== If CUBIC
928  if ( ( ( cell[3] < (90.0 + 0.1) ) && ( cell[3] > (90.0 - 0.1) ) ) &&
929  ( ( cell[4] < (90.0 + 0.1) ) && ( cell[4] > (90.0 - 0.1) ) ) &&
930  ( ( cell[5] < (90.0 + 0.1) ) && ( cell[5] > (90.0 - 0.1) ) ) )
931  {
932  //==================================== Determine/Save dimmensions
933  this->_xRange = cell[0];
934  this->_yRange = cell[1];
935  this->_zRange = cell[2];
936 
937  //==================================== Maximal cell dimensions
938  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
939 
940  //==================================== Save extracellular space
941  this->_maxExtraCellularSpace = *extraSpace;
942 
943  //==================================== Find max U, V and W
944  if ( order[0] == 1 ) { this->_maxMapU = dim[0] - 1; this->_xFrom = orig[0]; }
945  if ( order[0] == 2 ) { this->_maxMapU = dim[1] - 1; this->_yFrom = orig[0]; }
946  if ( order[0] == 3 ) { this->_maxMapU = dim[2] - 1; this->_zFrom = orig[0]; }
947 
948  if ( order[1] == 1 ) { this->_maxMapV = dim[0] - 1; this->_xFrom = orig[1]; }
949  if ( order[1] == 2 ) { this->_maxMapV = dim[1] - 1; this->_yFrom = orig[1]; }
950  if ( order[1] == 3 ) { this->_maxMapV = dim[2] - 1; this->_zFrom = orig[1]; }
951 
952  if ( order[2] == 1 ) { this->_maxMapW = dim[0] - 1; this->_xFrom = orig[2]; }
953  if ( order[2] == 2 ) { this->_maxMapW = dim[1] - 1; this->_yFrom = orig[2]; }
954  if ( order[2] == 3 ) { this->_maxMapW = dim[2] - 1; this->_zFrom = orig[2]; }
955 
956  //==================================== Get the map start and end
957  this->_xTo = this->_xFrom + this->_maxMapU;
958  this->_yTo = this->_yFrom + this->_maxMapV;
959  this->_zTo = this->_zFrom + this->_maxMapW;
960 
961  //==================================== Allocate map data memory
962  this->_densityMapMap = (float*) malloc ( (dim[0]*dim[1]*dim[2]) * sizeof ( float ) );
963  if ( this->_densityMapMap == nullptr )
964  {
965  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
966 
967  if ( settings->htmlReport )
968  {
969  std::stringstream hlpSS;
970  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
971  rvapi_set_text ( hlpSS.str().c_str(),
972  "ProgressSection",
973  settings->htmlReportLineProgress,
974  1,
975  1,
976  1 );
977  settings->htmlReportLineProgress += 1;
978  rvapi_flush ( );
979  }
980 
981  exit ( -1 );
982  }
983 
984  //==================================== Check if the mode is compatible
985  int mapMode = CMap_io::ccp4_cmap_get_datamode ( mapFile );
986  if ( ( mapMode != 0 ) && ( mapMode != 2 ) )
987  {
988  std::cerr << "!!! ProSHADE ERROR !!! Cannot read from the map file. The map file mode is not supported. Terminating..." << std::endl;
989 
990  if ( settings->htmlReport )
991  {
992  std::stringstream hlpSS;
993  hlpSS << "<font color=\"red\">" << "Cannot read from the map file. The map mode is neither 0, nor 2; other modes are not supperted at the moment." << "</font>";
994  rvapi_set_text ( hlpSS.str().c_str(),
995  "ProgressSection",
996  settings->htmlReportLineProgress,
997  1,
998  1,
999  1 );
1000  settings->htmlReportLineProgress += 1;
1001  rvapi_flush ( );
1002  }
1003 
1004  exit ( -1 );
1005  }
1006 
1007  //==================================== Read in map data
1008  // ... Find the stop positions (start is in orig variables) and the axis order
1009  int maxLim[3];
1010  int XYZOrder[3];
1011  int newU, newV, newW;
1012  int arrPos;
1013 
1014  for ( int iter = 0; iter < 3; iter++ )
1015  {
1016  maxLim[iter] = orig[iter] + dim[iter] - 1;
1017  XYZOrder[order[iter]-1] = iter;
1018  }
1019 
1020  // ... Solve the dimensions and sizes
1021  int fastDimSize = ( maxLim[0] - orig[0] + 1 );
1022  int midDimSize = ( maxLim[1] - orig[1] + 1 ) * fastDimSize;
1023  std::vector<float> section( midDimSize );
1024  int index;
1025  int iters[3];
1026 
1027  // ... Read in the map data
1028  for ( iters[2] = orig[2]; iters[2] <= maxLim[2]; iters[2]++ )
1029  {
1030  index = 0;
1031  CMap_io::ccp4_cmap_read_section( mapFile, &section[0] );
1032 
1033  if ( mapMode == 0 )
1034  {
1035  for ( int iter = ( midDimSize - 1 ); iter >= 0; iter-- )
1036  {
1037  section[iter] = static_cast<float> ( ( reinterpret_cast<unsigned char*> (&section[0]) )[iter] );
1038  }
1039  }
1040 
1041  for ( iters[1] = orig[1]; iters[1] <= maxLim[1]; iters[1]++ )
1042  {
1043  for ( iters[0] = orig[0]; iters[0] <= maxLim[0]; iters[0]++ )
1044  {
1045  newU = iters[XYZOrder[0]] - orig[XYZOrder[0]];
1046  newV = iters[XYZOrder[1]] - orig[XYZOrder[1]];
1047  newW = iters[XYZOrder[2]] - orig[XYZOrder[2]];
1048  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
1049  this->_densityMapMap[arrPos] = static_cast<float> ( section[ index++ ] );
1050  }
1051  }
1052  }
1053 
1054  //==================================== Get values for normalisation
1055  std::vector<double> vals ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) );
1056  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( dim[0] * dim[1] * dim[2] ); iter++ )
1057  {
1058  vals.at(iter) = this->_densityMapMap[iter];
1059  }
1060  std::sort ( vals.begin(), vals.end() );
1061 
1062  //==================================== Find mean and standard deviation for later normalisation
1063  this->_mapMean = std::accumulate ( vals.begin(), vals.end(), 0.0 ) / static_cast<double> ( vals.size() );
1064  this->_mapSdev = std::sqrt ( static_cast<double> ( std::inner_product ( vals.begin(), vals.end(), vals.begin(), 0.0 ) ) / static_cast<double> ( vals.size() ) - this->_mapMean * this->_mapMean );
1065 
1066  //==================================== Check if the map is not absolutely de-centered
1067  int noPToCheckU = static_cast<unsigned int> ( this->_maxMapU / 8.0 );
1068  int noPToCheckV = static_cast<unsigned int> ( this->_maxMapV / 8.0 );
1069  int noPToCheckW = static_cast<unsigned int> ( this->_maxMapW / 8.0 );
1070 
1071  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
1072  {
1073  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
1074  {
1075  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
1076  {
1077  //======================== Initialisation
1078  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
1079 
1080  //======================== Check to which quadrant the value belongs to
1081  if ( ( ( uIt <= static_cast<int> ( this->_maxMapU/2 + noPToCheckU ) ) && ( uIt >= static_cast<int> ( this->_maxMapU/2 - noPToCheckU ) ) ) &&
1082  ( ( vIt <= static_cast<int> ( this->_maxMapV/2 + noPToCheckV ) ) && ( vIt >= static_cast<int> ( this->_maxMapV/2 - noPToCheckV ) ) ) &&
1083  ( ( wIt <= static_cast<int> ( this->_maxMapW/2 + noPToCheckW ) ) && ( wIt >= static_cast<int> ( this->_maxMapW/2 - noPToCheckW ) ) ) )
1084  {
1085  centralAvg += std::max ( this->_densityMapMap[arrPos], static_cast<float>(0.0) );
1086  centralCount += 1.0;
1087  }
1088  if ( ( ( uIt < noPToCheckU ) && ( vIt < noPToCheckV ) && ( wIt < noPToCheckW ) ) ||
1089  ( ( uIt < noPToCheckU ) && ( vIt < noPToCheckV ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
1090  ( ( uIt < noPToCheckU ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt < noPToCheckW ) ) ||
1091  ( ( uIt < noPToCheckU ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
1092  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt < noPToCheckV ) && ( wIt < noPToCheckW ) ) ||
1093  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt < noPToCheckV ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
1094  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt < noPToCheckW ) ) ||
1095  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) )
1096  {
1097  cornerAvg += std::max ( this->_densityMapMap[arrPos], static_cast<float>(0.0) );
1098  cornerCount += 1.0;
1099  }
1100  }
1101  }
1102  }
1103 
1104  cornerAvg /= cornerCount;
1105  centralAvg /= centralCount;
1106 
1107  //==================================== If density is in the corners
1108  if ( cornerAvg > centralAvg )
1109  {
1110  //================================ Initialise required variables
1111  float* hlpMap = nullptr;
1112  hlpMap = (float*) malloc ( (dim[0]*dim[1]*dim[2]) * sizeof ( float ) );
1113  if ( hlpMap == nullptr )
1114  {
1115  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
1116 
1117  if ( settings->htmlReport )
1118  {
1119  std::stringstream hlpSS;
1120  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
1121  rvapi_set_text ( hlpSS.str().c_str(),
1122  "ProgressSection",
1123  settings->htmlReportLineProgress,
1124  1,
1125  1,
1126  1 );
1127  settings->htmlReportLineProgress += 1;
1128  rvapi_flush ( );
1129  }
1130 
1131  exit ( -1 );
1132  }
1133  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( dim[0] * dim[1] * dim[2] ); iter++ )
1134  {
1135  hlpMap[iter] = this->_densityMapMap[iter];
1136  }
1137 
1138  //================================ Transform
1139  unsigned int hlpPos;
1140  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
1141  {
1142  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
1143  {
1144  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
1145  {
1146  //==================== If in lower half, add half; if in upper halp, subtract half
1147  if ( uIt < static_cast<int> (this->_maxMapU+1)/2 ) { newU = uIt + (this->_maxMapU+1)/2; } else { newU = uIt - (this->_maxMapU+1)/2; }
1148  if ( vIt < static_cast<int> (this->_maxMapV+1)/2 ) { newV = vIt + (this->_maxMapV+1)/2; } else { newV = vIt - (this->_maxMapV+1)/2; }
1149  if ( wIt < static_cast<int> (this->_maxMapW+1)/2 ) { newW = wIt + (this->_maxMapW+1)/2; } else { newW = wIt - (this->_maxMapW+1)/2; }
1150 
1151  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
1152  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
1153 
1154  //==================== Set the value into correct coords in the new map
1155  this->_densityMapMap[arrPos] = hlpMap[hlpPos];
1156  }
1157  }
1158  }
1159 
1160  //================================ Free memory
1161  free ( hlpMap );
1162  }
1163  }
1164  else
1165  {
1166  std::cerr << "!!! ProSHADE ERROR !!! Non-orthogonal maps are not yet supported." << std::endl;
1167 
1168  if ( settings->htmlReport )
1169  {
1170  std::stringstream hlpSS;
1171  hlpSS << "<font color=\"red\">" << "Non-orthogonal map detected. Only P1 maps are currently supported." << "</font>";
1172  rvapi_set_text ( hlpSS.str().c_str(),
1173  "ProgressSection",
1174  settings->htmlReportLineProgress,
1175  1,
1176  1,
1177  1 );
1178  settings->htmlReportLineProgress += 1;
1179  rvapi_flush ( );
1180  }
1181 
1182  exit ( -1 );
1183  }
1184 
1185  //======================================== Free memory
1186  if ( cell != nullptr )
1187  {
1188  free ( cell );
1189  cell = nullptr;
1190  }
1191  if ( dim != nullptr )
1192  {
1193  free ( dim );
1194  dim = nullptr;
1195  }
1196  if ( order != nullptr )
1197  {
1198  free ( order );
1199  order = nullptr;
1200  }
1201  if ( orig != nullptr )
1202  {
1203  free ( orig );
1204  orig = nullptr;
1205  }
1206 
1207  //======================================== Close the file
1208  CMap_io::ccp4_cmap_close ( mapFile );
1209 
1210  //======================================== Determine sampling ranges
1211  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
1212  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
1213  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
1214  double maxSamplingRate = std::max ( this->_xSamplingRate, std::max( this->_ySamplingRate, this->_zSamplingRate ) );
1215 
1216  //======================================== If extra cell space is given, apply
1217  this->_maxExtraCellularSpace = *extraSpace;
1218  if ( *extraSpace != 0.0 )
1219  {
1220  //==================================== Compute new stats
1221  int xDiff = static_cast<int> ( std::ceil ( ( this->_xRange + this->_maxExtraCellularSpace ) / this->_xSamplingRate ) - this->_maxMapU );
1222  int yDiff = static_cast<int> ( std::ceil ( ( this->_yRange + this->_maxExtraCellularSpace ) / this->_ySamplingRate ) - this->_maxMapV );
1223  int zDiff = static_cast<int> ( std::ceil ( ( this->_zRange + this->_maxExtraCellularSpace ) / this->_zSamplingRate ) - this->_maxMapW );
1224 
1225  this->_xRange += xDiff * this->_xSamplingRate;
1226  this->_yRange += yDiff * this->_ySamplingRate;
1227  this->_zRange += zDiff * this->_zSamplingRate;
1228 
1229  if ( xDiff % 2 != 0 )
1230  {
1231  this->_xRange += this->_xSamplingRate;
1232  xDiff = static_cast<int> ( std::ceil ( this->_xRange / this->_xSamplingRate ) - ( this->_maxMapU + 1 ) );
1233  }
1234  if ( yDiff % 2 != 0 )
1235  {
1236  this->_yRange += this->_ySamplingRate;
1237  yDiff = static_cast<int> ( std::ceil ( this->_yRange / this->_ySamplingRate ) - ( this->_maxMapV + 1 ) );
1238  }
1239  if ( zDiff % 2 != 0 )
1240  {
1241  this->_zRange += this->_zSamplingRate;
1242  zDiff = static_cast<int> ( std::ceil ( this->_zRange / this->_zSamplingRate ) - ( this->_maxMapW + 1 ) );
1243  }
1244 
1245  xDiff /= 2;
1246  yDiff /= 2;
1247  zDiff /= 2;
1248 
1249  this->_xFrom -= xDiff;
1250  this->_yFrom -= yDiff;
1251  this->_zFrom -= zDiff;
1252 
1253  this->_xTo += xDiff;
1254  this->_yTo += yDiff;
1255  this->_zTo += zDiff;
1256 
1257  this->_maxMapU = this->_xTo - this->_xFrom;
1258  this->_maxMapV = this->_yTo - this->_yFrom;
1259  this->_maxMapW = this->_zTo - this->_zFrom;
1260 
1261  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
1262  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
1263  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
1264 
1265  //==================================== Move the map
1266  float *hlpMap = nullptr;
1267  hlpMap = (float*) malloc ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) * sizeof ( float ) );
1268  if ( hlpMap == nullptr )
1269  {
1270  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map moving data. Terminating... " << std::endl;
1271 
1272  if ( settings->htmlReport )
1273  {
1274  std::stringstream hlpSS;
1275  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
1276  rvapi_set_text ( hlpSS.str().c_str(),
1277  "ProgressSection",
1278  settings->htmlReportLineProgress,
1279  1,
1280  1,
1281  1 );
1282  settings->htmlReportLineProgress += 1;
1283  rvapi_flush ( );
1284  }
1285 
1286  exit ( -1 );
1287  }
1288  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
1289  {
1290  hlpMap[iter] = 0.0;
1291  }
1292 
1293  unsigned int newU, newV, newW, hlpPos, arrPos;
1294  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
1295  {
1296  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
1297  {
1298  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
1299  {
1300  if ( ( uIt < xDiff ) || ( uIt > static_cast<int> ( this->_maxMapU - xDiff ) ) ||
1301  ( vIt < yDiff ) || ( vIt > static_cast<int> ( this->_maxMapV - yDiff ) ) ||
1302  ( wIt < zDiff ) || ( wIt > static_cast<int> ( this->_maxMapW - zDiff ) ) )
1303  {
1304  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
1305  hlpMap[hlpPos] = 0.0;
1306  }
1307  else
1308  {
1309  newU = (uIt - xDiff);
1310  newV = (vIt - yDiff);
1311  newW = (wIt - zDiff);
1312 
1313  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
1314  arrPos = newW + (this->_maxMapW + 1 - zDiff * 2) * ( newV + (this->_maxMapV + 1 - yDiff * 2) * newU );
1315 
1316  hlpMap[hlpPos] = this->_densityMapMap[arrPos];
1317  }
1318  }
1319  }
1320  }
1321 
1322  //==================================== Free memory
1323  if ( this->_densityMapMap != nullptr )
1324  {
1325  free ( this->_densityMapMap );
1326  this->_densityMapMap = nullptr;
1327  }
1328 
1329  //==================================== Copy
1330  this->_densityMapMap = (float*) malloc ( ((this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1)) * sizeof ( float ) );
1331  if ( this->_densityMapMap == nullptr )
1332  {
1333  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
1334 
1335  if ( settings->htmlReport )
1336  {
1337  std::stringstream hlpSS;
1338  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Did you run out of memory?" << "</font>";
1339  rvapi_set_text ( hlpSS.str().c_str(),
1340  "ProgressSection",
1341  settings->htmlReportLineProgress,
1342  1,
1343  1,
1344  1 );
1345  settings->htmlReportLineProgress += 1;
1346  rvapi_flush ( );
1347  }
1348 
1349  exit ( -1 );
1350  }
1351  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
1352  {
1353  this->_densityMapMap[iter] = hlpMap[iter];
1354  }
1355 
1356  //==================================== Free memory
1357  if ( hlpMap != nullptr )
1358  {
1359  free ( hlpMap );
1360  hlpMap = nullptr;
1361  }
1362  }
1363 
1364  //======================================== Deal with oversampling
1365  if ( ( this->_mapResolution / 2.0 ) > maxSamplingRate )
1366  {
1367  maxSamplingRate = ( this->_mapResolution / 2.0 );
1368  }
1369  else
1370  {
1371  this->_mapResolution = maxSamplingRate * 2.0;
1372  }
1373 
1374  //======================================== Decide shell spacing, if not already decided
1375  if ( *shellDistance == 0 )
1376  {
1377  settings->shellSpacing = maxSamplingRate;
1378  this->_shellSpacing = maxSamplingRate;
1379  *shellDistance = maxSamplingRate;
1380 
1381  if ( rotDefaults )
1382  {
1383  settings->shellSpacing = this->_shellSpacing / 2.0;
1384  this->_shellSpacing = this->_shellSpacing / 2.0;
1385  *shellDistance = this->_shellSpacing;
1386  }
1387 
1388  if ( overlayDefaults )
1389  {
1390  settings->shellSpacing *= 2.0;
1391  this->_shellSpacing *= 2.0;
1392  *shellDistance *= 2.0;
1393  }
1394 
1395  while ( std::floor ( this->_maxMapRange / this->_shellSpacing ) < 20 )
1396  {
1397  this->_shellSpacing /= 2.0;
1398  settings->shellSpacing /= 2.0;
1399  *shellDistance /= 2.0;
1400  }
1401  }
1402 
1403  //======================================== Automatically determine maximum number of shells
1404  this->_shellPlacement = std::vector<double> ( std::floor ( this->_maxMapRange / this->_shellSpacing ) );
1405 
1406  for ( unsigned int shellIter = 0; shellIter < static_cast<unsigned int> ( this->_shellPlacement.size() ); shellIter++ )
1407  {
1408  this->_shellPlacement.at(shellIter) = (shellIter+1) * this->_shellSpacing;
1409  }
1410 
1411  //======================================== If bandwidth is not given, determine it
1412  if ( *bandwidth == 0 )
1413  {
1414  *bandwidth = std::ceil ( std::ceil ( ( ( std::ceil ( this->_maxMapRange / this->_shellSpacing ) *
1415  this->_shellSpacing ) / maxSamplingRate ) * 2.0 ) / 2.0 );
1416  this->_wasBandwithGiven = false;
1417 
1418  if ( rotDefaults )
1419  {
1420  *bandwidth = *bandwidth * 1.5;
1421  }
1422  }
1423  if ( settings->maxRotError != 0 )
1424  {
1425  *bandwidth = static_cast<unsigned int> ( 180 / settings->maxRotError );
1426  this->_wasBandwithGiven = true;
1427  }
1428 
1429  //======================================== If theta and phi are not given, determine them
1430  *theta = 2 * (*bandwidth);
1431  this->_wasThetaGiven = false;
1432  *phi = 2 * (*bandwidth);
1433  this->_wasPhiGiven = false;
1434 
1435  //======================================== If Gauss-Legendre integration order is not given, decide it
1436  if ( *glIntegOrder == 0 )
1437  {
1438  double distPerPointFraction = ( ( this->_maxMapRange / 2.0 ) / static_cast<double> ( *bandwidth / 2 ) ) / ( this->_maxMapRange / 2.0 );
1439 
1440  for ( unsigned int iter = 2; iter < static_cast<unsigned int> ( ProSHADE_internal_misc::glIntMaxDists.size() ); iter++ )
1441  {
1442  if ( ProSHADE_internal_misc::glIntMaxDists.at(iter) >= distPerPointFraction )
1443  {
1444  *glIntegOrder = iter;
1445  }
1446  }
1447 
1448  this->_wasGlInterGiven = false;
1449  }
1450 
1451  //======================================== Done
1452  this->_densityMapComputed = true;
1453  this->_fromPDB = false;
1454 
1455 }
1456 
1464 {
1465  //======================================== Sanity checks
1466  if ( this->_densityMapMap == nullptr )
1467  {
1468  std::cerr << "!!! ProSHADE ERROR !!! Attempted to normalise the internal map representation, but the values have already been deleted - either called the normaliseMap function too early or too late. Terminating..." << std::endl;
1469 
1470  if ( settings->htmlReport )
1471  {
1472  std::stringstream hlpSS;
1473  hlpSS << "<font color=\"red\">" << "Attempted to normalise the internal map representation, but the values have already been deleted - either called the normaliseMap function too early or too late. This seems like an internal bug, please report this case." << "</font>";
1474  rvapi_set_text ( hlpSS.str().c_str(),
1475  "ProgressSection",
1476  settings->htmlReportLineProgress,
1477  1,
1478  1,
1479  1 );
1480  settings->htmlReportLineProgress += 1;
1481  rvapi_flush ( );
1482  }
1483 
1484  exit ( -1 );
1485  }
1486 
1487  //======================================== Get values
1488  std::vector<double> vals ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) );
1489  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
1490  {
1491  vals.at(iter) = this->_densityMapMap[iter];
1492  }
1493  std::sort ( vals.begin(), vals.end() );
1494 
1495  //======================================== Find mean and standard deviation for later normalisation
1496  this->_mapMean = std::accumulate ( vals.begin(), vals.end(), 0.0 ) / static_cast<double> ( vals.size() );
1497  this->_mapSdev = std::sqrt ( static_cast<double> ( std::inner_product ( vals.begin(), vals.end(), vals.begin(), 0.0 ) ) / static_cast<double> ( vals.size() ) - this->_mapMean * this->_mapMean );
1498 
1499  //======================================== Apply
1500  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
1501  {
1502  this->_densityMapMap[iter] = this->_densityMapMap[iter] / this->_mapSdev;
1503  }
1504 
1505  //======================================== Done
1506  return ;
1507 }
1508 
1516 {
1517  //======================================== Sanity checks
1518  if ( this->_densityMapMap == nullptr )
1519  {
1520  std::cerr << "!!! ProSHADE ERROR !!! Attempted to get COM and distances for the internal map representation, but the values have already been deleted - either called the getCOMandDist function too early or too late. Terminating..." << std::endl;
1521 
1522  if ( settings->htmlReport )
1523  {
1524  std::stringstream hlpSS;
1525  hlpSS << "<font color=\"red\">" << "Attempted to normalise the internal map representation, but the values have already been deleted - either called the normaliseMap function too early or too late. This seems like an internal bug, please report this case." << "</font>";
1526  rvapi_set_text ( hlpSS.str().c_str(),
1527  "ProgressSection",
1528  settings->htmlReportLineProgress,
1529  1,
1530  1,
1531  1 );
1532  settings->htmlReportLineProgress += 1;
1533  rvapi_flush ( );
1534  }
1535 
1536  exit ( -1 );
1537  }
1538 
1539  //======================================== Get COM
1540  unsigned int arrPos = 0;
1541  double totDens = 0.0;
1542  std::array<double,4> meanVals;
1543  meanVals[0] = 0.0;
1544  meanVals[1] = 0.0;
1545  meanVals[2] = 0.0;
1546  meanVals[3] = 0.0;
1547  std::vector<double> vals ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) );
1548 
1549  for ( unsigned int uIt = 0; uIt < static_cast<unsigned int> ( (this->_maxMapU+1) ); uIt++ )
1550  {
1551  for ( unsigned int vIt = 0; vIt < static_cast<unsigned int> ( (this->_maxMapV+1) ); vIt++ )
1552  {
1553  for ( unsigned int wIt = 0; wIt < static_cast<unsigned int> ( (this->_maxMapW+1) ); wIt++ )
1554  {
1555  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
1556 
1557  if ( this->_densityMapMap[arrPos] > 0.0 )
1558  {
1559  meanVals[0] += this->_densityMapMap[arrPos] * uIt;
1560  meanVals[1] += this->_densityMapMap[arrPos] * vIt;
1561  meanVals[2] += this->_densityMapMap[arrPos] * wIt;
1562 
1563  totDens += this->_densityMapMap[arrPos];
1564  }
1565  }
1566  }
1567  }
1568 
1569  meanVals[0] /= totDens;
1570  meanVals[1] /= totDens;
1571  meanVals[2] /= totDens;
1572 
1573  //======================================== Find distances to borders
1574  double distX = 0.0;
1575  double distY = 0.0;
1576  double distZ = 0.0;
1577 
1578  if ( meanVals[0] <= static_cast<double> ((this->_maxMapU+1)/2) )
1579  {
1580  distX = meanVals[0] * this->_xSamplingRate;
1581  }
1582  else
1583  {
1584  distX = ( static_cast<double> ( this->_maxMapU+1 ) - meanVals[0] ) * this->_xSamplingRate;
1585  }
1586 
1587  if ( meanVals[1] <= static_cast<double> ((this->_maxMapV+1)/2) )
1588  {
1589  distY = meanVals[1] * this->_ySamplingRate;
1590  }
1591  else
1592  {
1593  distY = ( static_cast<double> ( this->_maxMapV+1 ) - meanVals[1] ) * this->_ySamplingRate;
1594  }
1595 
1596  if ( meanVals[2] <= static_cast<double> ((this->_maxMapW+1)/2) )
1597  {
1598  distZ = meanVals[2] * this->_zSamplingRate;
1599  }
1600  else
1601  {
1602  distZ = ( static_cast<double> ( this->_maxMapW+1 ) - meanVals[2] ) * this->_zSamplingRate;
1603  }
1604 
1605  //======================================== Get total distance
1606  meanVals[3] = sqrt ( pow( distX, 2.0 ) + pow ( distY, 2.0 ) + pow ( distZ, 2.0 ) );
1607 
1608  //======================================== Done
1609  return ( meanVals );
1610 }
1611 
1626  int hlpV,
1627  int hlpW,
1628  double blurBy,
1629  double maxMapIQR,
1630  double extraMaskSpace )
1631 {
1632  //================================ Initialise the data structures
1633  fftw_complex* tmpIn;
1634  fftw_complex* tmpOut;
1635  tmpIn = new fftw_complex[hlpU * hlpV * hlpW];
1636  tmpOut = new fftw_complex[hlpU * hlpV * hlpW];
1637  fftw_complex* maskData = new fftw_complex [ hlpU * hlpV * hlpW ];
1638  fftw_complex* maskDataInv = new fftw_complex [ hlpU * hlpV * hlpW ];
1639 
1640  //================================ Initialise local variables
1641  int h, k, l;
1642  int uIt, vIt, wIt;
1643  double mag, phase, S;
1644  double normFactor = (hlpU * hlpV * hlpW);
1645  double bFacChange = blurBy;
1646  double real = 0.0;
1647  double imag = 0.0;
1648  unsigned int hlpIt = 0;
1649  int arrayPos = 0;
1650  fftw_plan p;
1651 
1652  //======================================== Load map data for Fourier
1653  for ( uIt = 0; uIt < hlpU; uIt++ )
1654  {
1655  for ( vIt = 0; vIt < hlpV; vIt++ )
1656  {
1657  for ( wIt = 0; wIt < hlpW; wIt++ )
1658  {
1659  //============================ Initialisation
1660  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
1661 
1662  if ( this->_densityMapCor[arrayPos] == this->_densityMapCor[arrayPos] )
1663  {
1664  tmpIn[arrayPos][0] = ( this->_densityMapCor[arrayPos] - this->_mapMean ) / this->_mapSdev;
1665  tmpIn[arrayPos][1] = 0.0;
1666  }
1667  else
1668  {
1669  tmpIn[arrayPos][0] = 0.0;
1670  tmpIn[arrayPos][1] = 0.0;
1671  }
1672  }
1673  }
1674  }
1675 
1676  //======================================== Create plans (FFTW_MEASURE would change the arrays)
1677  p = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpIn, tmpOut, FFTW_FORWARD, FFTW_ESTIMATE );
1678  fftw_execute ( p );
1679 
1680  //================================ Prepare FFTW plan for mask FFTW
1681  fftw_plan pMaskInv = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, maskDataInv, maskData, FFTW_BACKWARD, FFTW_ESTIMATE );
1682 
1683  for ( uIt = 0; uIt < hlpU; uIt++ )
1684  {
1685  for ( vIt = 0; vIt < hlpV; vIt++ )
1686  {
1687  for ( wIt = 0; wIt < hlpW; wIt++ )
1688  {
1689  //==================== Var init
1690  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
1691  real = tmpOut[arrayPos][0];
1692  imag = tmpOut[arrayPos][1];
1693 
1694  //==================== Change the B-factors, if required
1695  if ( uIt > (hlpU / 2) ) { h = uIt - hlpU; } else { h = uIt; }
1696  if ( vIt > (hlpV / 2) ) { k = vIt - hlpV; } else { k = vIt; }
1697  if ( wIt > (hlpW / 2) ) { l = wIt - hlpW; } else { l = wIt; }
1698 
1699  //==================== Get magnitude and phase with mask parameters
1700  S = ( pow( static_cast<double> ( h ) / this->_xRange, 2.0 ) +
1701  pow( static_cast<double> ( k ) / this->_yRange, 2.0 ) +
1702  pow( static_cast<double> ( l ) / this->_zRange, 2.0 ) );
1703  mag = sqrt ( (real*real) + (imag*imag) ) * std::exp ( - ( ( bFacChange * S ) / 4.0 ) );
1704  phase = atan2 ( imag, real );
1705 
1706  //==================== Save the mask data
1707  maskDataInv[arrayPos][0] = ( mag * cos(phase) ) / normFactor;
1708  maskDataInv[arrayPos][1] = ( mag * sin(phase) ) / normFactor;
1709  }
1710  }
1711  }
1712 
1713  //======================================== Execute the inversions
1714  fftw_execute ( pMaskInv );
1715 
1716  //======================================== Get the map threshold
1717  std::vector<double> maskVals ( hlpU * hlpV * hlpW );
1718  hlpIt = 0;
1719  for ( uIt = 0; uIt < hlpU; uIt++ )
1720  {
1721  for ( vIt = 0; vIt < hlpV; vIt++ )
1722  {
1723  for ( wIt = 0; wIt < hlpW; wIt++ )
1724  {
1725  //============================ Save to vector
1726  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
1727  maskVals.at(hlpIt) = maskData[arrayPos][0];
1728  hlpIt += 1;
1729 
1730  }
1731  }
1732  }
1733 
1734  double medianPos = static_cast<unsigned int> ( maskVals.size() / 2 );
1735  std::sort ( maskVals.begin(), maskVals.end() );
1736 
1737  double interQuartileRange = maskVals.at(medianPos+(medianPos/2)) - maskVals.at(medianPos-(medianPos/2));
1738  double mapThresholdPlus = maskVals.at(medianPos+(medianPos/2)) + ( interQuartileRange * maxMapIQR );
1739  maskVals.clear();
1740 
1741  //======================================== Add extra space to mask
1742  int addPoints = static_cast<int> ( std::max ( std::ceil ( extraMaskSpace / static_cast<double> ( this->_xRange / (hlpU-1) ) ), std::max ( std::ceil ( extraMaskSpace / static_cast<double> ( this->_yRange / (hlpV-1) ) ), std::ceil ( extraMaskSpace / static_cast<double> ( this->_zRange / (hlpW-1) ) ) ) ) );
1743  int arrPosSearch = 0;
1744  int newU, newV, newW;
1745  bool breakOut = false;
1746 
1747  for ( uIt = 0; uIt < hlpU; uIt++ )
1748  {
1749  for ( vIt = 0; vIt < hlpV; vIt++ )
1750  {
1751  for ( wIt = 0; wIt < hlpW; wIt++ )
1752  {
1753  //============================ Var init
1754  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
1755 
1756  //============================ If already in mask, ignore
1757  if ( maskData[arrayPos][0] > mapThresholdPlus )
1758  {
1759  tmpIn[arrayPos][0] = 1.0;
1760  continue;
1761  }
1762 
1763  //============================ If not, find if it is close to mask
1764  tmpIn[arrayPos][0] = 0.0;
1765  breakOut = false;
1766  for ( int uCh = -addPoints; uCh <= addPoints; uCh++ )
1767  {
1768  if ( breakOut ) { break; }
1769  for ( int vCh = -addPoints; vCh <= addPoints; vCh++ )
1770  {
1771  if ( breakOut ) { break; }
1772  for ( int wCh = -addPoints; wCh <= addPoints; wCh++ )
1773  {
1774  if ( breakOut ) { break; }
1775  if ( ( uCh == 0 ) && ( vCh == 0 ) && wCh == 0 ) { continue; }
1776 
1777  newU = uIt + uCh;
1778  newV = vIt + vCh;
1779  newW = wIt + wCh;
1780 
1781  if ( newU < 0 ) { newU += hlpU; } if ( newU >= hlpU ) { newU -= hlpU; }
1782  if ( newV < 0 ) { newV += hlpV; } if ( newV >= hlpV ) { newV -= hlpV; }
1783  if ( newW < 0 ) { newW += hlpW; } if ( newW >= hlpW ) { newW -= hlpW; }
1784 
1785  arrPosSearch = newW + hlpW * ( newV + hlpV * newU );
1786 
1787  if ( maskData[arrPosSearch][0] > mapThresholdPlus )
1788  {
1789  tmpIn[arrayPos][0] = 1.0;
1790  breakOut = true;
1791  }
1792  }
1793  }
1794  }
1795  }
1796  }
1797  }
1798 
1799  //======================================== Apply the mask
1800  for ( uIt = 0; uIt < hlpU; uIt++ )
1801  {
1802  for ( vIt = 0; vIt < hlpV; vIt++ )
1803  {
1804  for ( wIt = 0; wIt < hlpW; wIt++ )
1805  {
1806  //============================ Var init
1807  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
1808 
1809  //============================ Apply mask
1810  if ( tmpIn[arrayPos][0] == 0.0 )
1811  {
1812  this->_densityMapCor[arrayPos] = 0.0;
1813  }
1814  }
1815  }
1816  }
1817 
1818  //================================ Clean up
1819  delete[] maskData;
1820  maskData = nullptr;
1821  delete[] maskDataInv;
1822  maskDataInv = nullptr;
1823  delete[] tmpIn;
1824  tmpIn = nullptr;
1825  delete[] tmpOut;
1826  tmpOut = nullptr;
1827 
1828  //================================ Delete the plans
1829  fftw_destroy_plan ( p );
1830  fftw_destroy_plan ( pMaskInv );
1831 
1832  //================================ Done
1833  return ;
1834 }
1835 
1852  int hlpV,
1853  int hlpW,
1854  int verbose,
1855  bool runAll )
1856 {
1857  //======================================== Get the list of islands
1858  std::vector< std::vector<int> > clusters = this->findMapIslands ( hlpU, hlpV, hlpW, this->_densityMapCor );
1859 
1860  //======================================== Decide which islands to keep
1861  int maxVolume = 0;
1862  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( clusters.size() ); iter++ )
1863  {
1864  maxVolume = std::max ( maxVolume, static_cast<int> ( clusters.at(iter).size() ) );
1865  }
1866 
1867  //======================================== Are there too many islands?
1868  int fracLess10 = 0;
1869  int volTop80 = 0;
1870  int totVol = 0;
1871  int volLow20 = 0;
1872  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( clusters.size() ); iter++ )
1873  {
1874  totVol += clusters.at(iter).size();
1875  if ( static_cast<double> ( clusters.at(iter).size() ) > ( 0.8 * maxVolume ) )
1876  {
1877  volTop80 += clusters.at(iter).size();
1878  }
1879  if ( static_cast<double> ( clusters.at(iter).size() ) < ( 0.1 * maxVolume ) )
1880  {
1881  fracLess10 += 1;
1882  }
1883  if ( static_cast<double> ( clusters.at(iter).size() ) < ( 0.2 * maxVolume ) )
1884  {
1885  volLow20 += clusters.at(iter).size();
1886  }
1887  }
1888 
1889  //======================================== More computations needed?
1890  if ( ( fracLess10 != 0 ) || ( clusters.size() > 5 ) )
1891  {
1892  if ( ( ( static_cast<double> ( fracLess10 ) / static_cast<double> ( clusters.size() ) ) > 0.5 ) ||
1893  ( ( static_cast<double> ( volTop80 ) / static_cast<double> ( totVol ) ) < 0.9 ) ||
1894  ( ( static_cast<double> ( volLow20 ) / static_cast<double> ( totVol ) ) > 0.1 ) )
1895  {
1896  if ( !runAll )
1897  {
1898  return ( true );
1899  }
1900  }
1901  }
1902 
1903  //======================================== Check for corners
1904  if ( verbose > 3 )
1905  {
1906  std::cout << ">>>>>>>> Cluster check started." << std::endl;
1907  }
1908 
1909  //======================================== Apply the islands
1910  double *tmpIn = new double[hlpU * hlpV * hlpW];
1911  std::vector<int> removedClusters;
1912 
1913  for ( unsigned int i = 0; i < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); i++ )
1914  {
1915  tmpIn[i] = this->_densityMapCor[i];
1916  this->_densityMapCor[i] = 0.0;
1917  }
1918 
1919  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( clusters.size() ); iter++ )
1920  {
1921  if ( static_cast<double> ( clusters.at(iter).size() ) < ( 0.3 * static_cast<double> ( maxVolume ) ) )
1922  {
1923  continue;
1924  }
1925  else
1926  {
1927  removedClusters.emplace_back ( iter );
1928  for ( unsigned int it = 0; it < static_cast<unsigned int> ( clusters.at(iter).size() ); it++ )
1929  {
1930  this->_densityMapCor[clusters.at(iter).at(it)] = tmpIn[clusters.at(iter).at(it)];
1931  }
1932  }
1933  }
1934 
1935  //======================================== Check all values for having 3A to passing value
1936  int noPoints = std::ceil ( 3.0 / std::max ( this->_xRange / hlpU, std::max ( this->_yRange / hlpV, this->_zRange / hlpW ) ) );
1937  int arrPos = 0;
1938  int arrPos2 = 0;
1939  bool addPoint = false;
1940  int uIt, vIt, wIt;
1941  int hlpUIt, hlpVIt, hlpWIt;
1942 
1943  for ( unsigned int rIt = 0; rIt < static_cast<unsigned int> ( removedClusters.size() ); rIt++ )
1944  {
1945  for ( int rPt = 0; rPt < static_cast<int> ( clusters.at(removedClusters.at(rIt)).size() ); rPt++ )
1946  {
1947  //================================ Point was removed. Check if it is at least 3A to the closest remaining point
1948  uIt = ( clusters.at(removedClusters.at(rIt)).at(rPt) / ( hlpW * hlpV ) ) % hlpW;
1949  vIt = static_cast<int> ( std::floor ( clusters.at(removedClusters.at(rIt)).at(rPt) / hlpW ) ) % hlpV;
1950  wIt = clusters.at(removedClusters.at(rIt)).at(rPt) - ( uIt * hlpW * hlpV ) - ( vIt * hlpW );
1951 
1952  addPoint = false;
1953  for ( int newX = uIt-noPoints; newX <= uIt+noPoints; newX++ )
1954  {
1955  if ( addPoint ) { break; }
1956  for ( int newY = vIt-noPoints; newY <= vIt+noPoints; newY++ )
1957  {
1958  if ( addPoint ) { break; }
1959  for ( int newZ = wIt-noPoints; newZ <= wIt+noPoints; newZ++ )
1960  {
1961  if ( ( newX == uIt ) && ( newY == vIt ) && ( newZ == wIt ) ) { continue; }
1962 
1963  hlpUIt = newX;
1964  hlpVIt = newY;
1965  hlpWIt = newZ;
1966 
1967  if ( hlpUIt < 0 ) { hlpUIt += hlpU; } if ( hlpUIt >= hlpU ) { hlpUIt -= hlpU; }
1968  if ( hlpVIt < 0 ) { hlpVIt += hlpV; } if ( hlpVIt >= hlpV ) { hlpVIt -= hlpV; }
1969  if ( hlpWIt < 0 ) { hlpWIt += hlpW; } if ( hlpWIt >= hlpW ) { hlpWIt -= hlpW; }
1970 
1971  arrPos2 = hlpWIt + hlpW * ( hlpVIt + hlpV * hlpUIt );
1972  if ( this->_densityMapCor[arrPos2] > 0.0 ) { addPoint = true; break; }
1973  }
1974  }
1975  }
1976 
1977  if ( addPoint )
1978  {
1979  arrPos = wIt + hlpW * ( vIt + hlpV * uIt );
1980  this->_densityMapCor[arrPos] = -999.999;
1981  }
1982  }
1983  }
1984 
1985  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
1986  {
1987  if ( this->_densityMapCor[iter] == -999.999 )
1988  {
1989  this->_densityMapCor[iter] = tmpIn[iter];
1990  }
1991  }
1992 
1993  //======================================== Free memory
1994  delete[] tmpIn;
1995 
1996  //======================================== Done
1997  return ( false );
1998 }
1999 
2013  double yShift,
2014  double zShift )
2015 {
2016  //======================================== Change xFrom, xTo, yFrom, yTo, zFrom and zTo
2017  this->_xFrom += xShift;
2018  this->_xTo += xShift;
2019  this->_yFrom += yShift;
2020  this->_yTo += yShift;
2021  this->_zFrom += zShift;
2022  this->_zTo += zShift;
2023 
2024  //======================================== Done
2025 
2026 }
2027 
2038 {
2039  //======================================== General intialisation
2040  int arrPos = 0;
2041  int hlpPos = 0;
2042 
2043  //======================================== If samling rates are the same - moving str has already been re-sampled
2044  if ( ( this->_xSamplingRate == matchTo->_xSamplingRate ) && ( this->_ySamplingRate == matchTo->_ySamplingRate ) && ( this->_zSamplingRate == matchTo->_zSamplingRate ) )
2045  {
2046  //==================================== Just cut
2047  double *hlpMap = new double [(matchTo->_maxMapU+1) * (matchTo->_maxMapV+1) * (matchTo->_maxMapW+1)];
2048 
2049  for ( int uIt = 0; uIt < static_cast<int> (matchTo->_maxMapU+1); uIt++ )
2050  {
2051  for ( int vIt = 0; vIt < static_cast<int> (matchTo->_maxMapV+1); vIt++ )
2052  {
2053  for ( int wIt = 0; wIt < static_cast<int> (matchTo->_maxMapW+1); wIt++ )
2054  {
2055  arrPos = wIt + (matchTo->_maxMapW+1) * ( vIt + (matchTo->_maxMapV+1) * uIt );
2056  hlpPos = wIt + (this->_maxMapW+1) * ( vIt + (this->_maxMapV+1) * uIt );
2057  hlpMap[arrPos] = this->_densityMapCor[hlpPos];
2058  }
2059  }
2060  }
2061 
2062  //==================================== Copy tmp to object
2063  delete[] this->_densityMapCor;
2064  this->_densityMapCor = new double [(matchTo->_maxMapU+1) * (matchTo->_maxMapV+1) * (matchTo->_maxMapW+1)];
2065  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (matchTo->_maxMapU+1) * (matchTo->_maxMapV+1) * (matchTo->_maxMapW+1) ); iter++ )
2066  {
2067  this->_densityMapCor[iter] = hlpMap[iter];
2068  }
2069  delete[] hlpMap;
2070 
2071  //==================================== Change the cell settings
2072  this->_maxMapU = matchTo->_maxMapU;
2073  this->_maxMapV = matchTo->_maxMapV;
2074  this->_maxMapW = matchTo->_maxMapW;
2075 
2076  this->_xFrom = matchTo->_xFrom;
2077  this->_yFrom = matchTo->_yFrom;
2078  this->_zFrom = matchTo->_zFrom;
2079 
2080  this->_xTo = matchTo->_xTo;
2081  this->_yTo = matchTo->_yTo;
2082  this->_zTo = matchTo->_zTo;
2083 
2084  this->_xRange = matchTo->_xRange;
2085  this->_yRange = matchTo->_yRange;
2086  this->_zRange = matchTo->_zRange;
2087 
2088  //==================================== Done
2089  return ;
2090 
2091  }
2092 
2093  //======================================== Map interpolation intialisation
2094  double *hlpMap = new double [(matchTo->_maxMapU+1) * (matchTo->_maxMapV+1) * (matchTo->_maxMapW+1)];
2095  double newX = 0;
2096  double newY = 0;
2097  double newZ = 0;
2098  int oldX = 0;
2099  int oldY = 0;
2100  int oldZ = 0;
2101  int oldXOver = 0;
2102  int oldYOver = 0;
2103  int oldZOver = 0;
2104  bool xFound = false;
2105  bool yFound = false;
2106  bool zFound = false;
2107  double xd, yd, zd;
2108  std::array<double,4> p000, p001, p010, p011, p100, p101, p110, p111;
2109  std::array<double,3> p00, p01, p10, p11;
2110  std::array<double,2> p0, p1;
2111 
2112  //======================================== Map re-sampling
2113  for ( int uIt = 0; uIt < static_cast<int> (matchTo->_maxMapU+1); uIt++ )
2114  {
2115  for ( int vIt = 0; vIt < static_cast<int> (matchTo->_maxMapV+1); vIt++ )
2116  {
2117  for ( int wIt = 0; wIt < static_cast<int> (matchTo->_maxMapW+1); wIt++ )
2118  {
2119  //============================ Initialise iteration
2120  arrPos = wIt + (matchTo->_maxMapW+1) * ( vIt + (matchTo->_maxMapV+1) * uIt );
2121 
2122  oldX = 0;
2123  oldY = 0;
2124  oldZ = 0;
2125  oldXOver = 0;
2126  oldYOver = 0;
2127  oldZOver = 0;
2128 
2129  //============================ Get new X, Y and Z in angstroms
2130  newX = static_cast<double> ( uIt ) * matchTo->_xSamplingRate;
2131  newY = static_cast<double> ( vIt ) * matchTo->_ySamplingRate;
2132  newZ = static_cast<double> ( wIt ) * matchTo->_zSamplingRate;
2133 
2134  //============================ Find corresponding old X, Y and Z indices
2135  xFound = false;
2136  for ( int iter = 0; iter < static_cast<int> (this->_maxMapU+1); iter++ )
2137  {
2138  if ( ( iter * this->_xSamplingRate ) <= newX )
2139  {
2140  oldX = iter;
2141  xFound = true;
2142  }
2143  }
2144  if ( !xFound ) { hlpMap[arrPos] = 0.0; continue; }
2145 
2146  yFound = false;
2147  for ( int iter = 0; iter < static_cast<int> (this->_maxMapV+1); iter++ )
2148  {
2149  if ( ( iter * this->_ySamplingRate ) <= newY )
2150  {
2151  oldY = iter;
2152  yFound = true;
2153  }
2154  }
2155  if ( !yFound ) { hlpMap[arrPos] = 0.0; continue; }
2156 
2157  zFound = false;
2158  for ( int iter = 0; iter < static_cast<int> (this->_maxMapW+1); iter++ )
2159  {
2160  if ( ( iter * this->_zSamplingRate ) <= newZ )
2161  {
2162  oldZ = iter;
2163  zFound = true;
2164  }
2165  }
2166  if ( !zFound ) { hlpMap[arrPos] = 0.0; continue; }
2167 
2168  if ( ( oldX == static_cast<int> (this->_maxMapU) ) && ( ( (oldX+1) * this->_xSamplingRate ) > newX ) )
2169  {
2170  oldXOver = 0;
2171  }
2172  else
2173  {
2174  xFound = false;
2175  for ( int iter = 0; iter < static_cast<int> (this->_maxMapU+1); iter++ )
2176  {
2177  if ( ( iter * this->_xSamplingRate ) > newX )
2178  {
2179  oldXOver = iter;
2180  xFound = true;
2181  break;
2182  }
2183  }
2184  if ( !xFound ) { hlpMap[arrPos] = 0.0; continue; }
2185  }
2186 
2187  if ( ( oldY == static_cast<int> (this->_maxMapV) ) && ( ( (oldY+1) * this->_ySamplingRate ) > newY ) )
2188  {
2189  oldYOver = 0;
2190  }
2191  else
2192  {
2193  yFound = false;
2194  for ( int iter = 0; iter < static_cast<int> (this->_maxMapV+1); iter++ )
2195  {
2196  if ( ( iter * this->_ySamplingRate ) > newY )
2197  {
2198  oldYOver = iter;
2199  yFound = true;
2200  break;
2201  }
2202  }
2203  if ( !yFound ) { hlpMap[arrPos] = 0.0; continue; }
2204  }
2205 
2206  if ( ( oldZ == static_cast<int> (this->_maxMapW) ) && ( ( (oldZ+1) * this->_zSamplingRate ) > newZ ) )
2207  {
2208  oldZOver = 0;
2209  }
2210  else
2211  {
2212  zFound = false;
2213  for ( int iter = 0; iter < static_cast<int> (this->_maxMapW+1); iter++ )
2214  {
2215  if ( ( iter * this->_zSamplingRate ) > newZ )
2216  {
2217  oldZOver = iter;
2218  zFound = true;
2219  break;
2220  }
2221  }
2222  if ( !zFound ) { hlpMap[arrPos] = 0.0; continue; }
2223  }
2224 
2225  //============================ Get the surrounding values and distances
2226  p000[0] = oldX;
2227  p000[1] = oldY;
2228  p000[2] = oldZ;
2229  hlpPos = p000[2] + (this->_maxMapW+1) * ( p000[1] + (this->_maxMapV+1) * p000[0] );
2230  p000[3] = this->_densityMapCor[hlpPos];
2231 
2232  p001[0] = oldX;
2233  p001[1] = oldY;
2234  p001[2] = oldZOver;
2235  hlpPos = p001[2] + (this->_maxMapW+1) * ( p001[1] + (this->_maxMapV+1) * p001[0] );
2236  p001[3] = this->_densityMapCor[hlpPos];
2237 
2238  p010[0] = oldX;
2239  p010[1] = oldYOver;
2240  p010[2] = oldZ;
2241  hlpPos = p010[2] + (this->_maxMapW+1) * ( p010[1] + (this->_maxMapV+1) * p010[0] );
2242  p010[3] = this->_densityMapCor[hlpPos];
2243 
2244  p011[0] = oldX;
2245  p011[1] = oldYOver;
2246  p011[2] = oldZOver;
2247  hlpPos = p011[2] + (this->_maxMapW+1) * ( p011[1] + (this->_maxMapV+1) * p011[0] );
2248  p011[3] = this->_densityMapCor[hlpPos];
2249 
2250  p100[0] = oldXOver;
2251  p100[1] = oldY;
2252  p100[2] = oldZ;
2253  hlpPos = p100[2] + (this->_maxMapW+1) * ( p100[1] + (this->_maxMapV+1) * p100[0] );
2254  p100[3] = this->_densityMapCor[hlpPos];
2255 
2256  p101[0] = oldXOver;
2257  p101[1] = oldY;
2258  p101[2] = oldZOver;
2259  hlpPos = p101[2] + (this->_maxMapW+1) * ( p101[1] + (this->_maxMapV+1) * p101[0] );
2260  p101[3] = this->_densityMapCor[hlpPos];
2261 
2262  p110[0] = oldXOver;
2263  p110[1] = oldYOver;
2264  p110[2] = oldZ;
2265  hlpPos = p110[2] + (this->_maxMapW+1) * ( p110[1] + (this->_maxMapV+1) * p110[0] );
2266  p110[3] = this->_densityMapCor[hlpPos];
2267 
2268  p111[0] = oldXOver;
2269  p111[1] = oldYOver;
2270  p111[2] = oldZOver;
2271  hlpPos = p111[2] + (this->_maxMapW+1) * ( p111[1] + (this->_maxMapV+1) * p111[0] );
2272  p111[3] = this->_densityMapCor[hlpPos];
2273 
2274  //==================== Interpolate
2275  xd = 1.0 - ( ( newX - ( static_cast<double> ( oldX ) * this->_xSamplingRate ) ) / matchTo->_xSamplingRate );
2276  p00[0] = p000[1]; p00[1] = p000[2]; p00[2] = ( xd * p000[3] ) + ( (1.0 - xd) * p100[3] );
2277  p01[0] = p001[1]; p01[1] = p001[2]; p01[2] = ( xd * p001[3] ) + ( (1.0 - xd) * p101[3] );
2278  p10[0] = p010[1]; p10[1] = p010[2]; p10[2] = ( xd * p010[3] ) + ( (1.0 - xd) * p110[3] );
2279  p11[0] = p011[1]; p11[1] = p011[2]; p11[2] = ( xd * p011[3] ) + ( (1.0 - xd) * p111[3] );
2280 
2281  yd = 1.0 - ( ( newY - ( static_cast<double> ( oldY ) * this->_ySamplingRate ) ) / matchTo->_ySamplingRate );
2282  p0[0] = p00[1]; p0[1] = ( yd * p00[2] ) + ( (1.0 - yd) * p10[2] );
2283  p1[0] = p01[1]; p1[1] = ( yd * p01[2] ) + ( (1.0 - yd) * p11[2] );
2284 
2285  zd = 1.0 - ( ( newZ - ( static_cast<double> ( oldZ ) * this->_zSamplingRate ) ) / matchTo->_zSamplingRate );
2286  hlpMap[arrPos] = ( zd * p0[1] ) + ( (1.0 - zd) * p1[1] );
2287  }
2288  }
2289  }
2290 
2291  //==================================== Copy tmp to object
2292  delete[] this->_densityMapCor;
2293  this->_densityMapCor = new double [(matchTo->_maxMapU+1) * (matchTo->_maxMapV+1) * (matchTo->_maxMapW+1)];
2294  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (matchTo->_maxMapU+1) * (matchTo->_maxMapV+1) * (matchTo->_maxMapW+1) ); iter++ )
2295  {
2296  this->_densityMapCor[iter] = hlpMap[iter];
2297  }
2298  delete[] hlpMap;
2299 
2300  //==================================== Change the cell settings
2301  this->_maxMapU = matchTo->_maxMapU;
2302  this->_maxMapV = matchTo->_maxMapV;
2303  this->_maxMapW = matchTo->_maxMapW;
2304 
2305  this->_xFrom = matchTo->_xFrom;
2306  this->_yFrom = matchTo->_yFrom;
2307  this->_zFrom = matchTo->_zFrom;
2308 
2309  this->_xTo = matchTo->_xTo;
2310  this->_yTo = matchTo->_yTo;
2311  this->_zTo = matchTo->_zTo;
2312 
2313  this->_xRange = matchTo->_xRange;
2314  this->_yRange = matchTo->_yRange;
2315  this->_zRange = matchTo->_zRange;
2316 
2317  //======================================== Done
2318  return ;
2319 
2320 }
2321 
2334  double yShift,
2335  double zShift )
2336 {
2337  //======================================== Initialise
2338  int hlpU = this->_maxMapU + 1;
2339  int hlpV = this->_maxMapV + 1;
2340  int hlpW = this->_maxMapW + 1;
2341 
2342  int arrayPos = 0;
2343  int h, k, l;
2344  double real = 0.0;
2345  double imag = 0.0;
2346  double exponent = 0.0;
2347  double trCoeffReal = 0.0;
2348  double trCoeffImag = 0.0;
2349  double normFactor = static_cast<double> ( hlpU * hlpV * hlpW );
2350  fftw_complex *translatedMap = new fftw_complex [hlpU * hlpV * hlpW];
2351  fftw_complex *fCoeffs = new fftw_complex [hlpU * hlpV * hlpW];
2352  std::array<double,2> hlpArr;
2353  fftw_plan planForwardFourier;
2354  fftw_plan planBackwardFourier;
2355 
2356 
2357  //======================================== Create plans
2358  planForwardFourier = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, translatedMap, fCoeffs, FFTW_FORWARD, FFTW_ESTIMATE );
2359  planBackwardFourier = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, fCoeffs, translatedMap, FFTW_BACKWARD, FFTW_ESTIMATE );
2360 
2361  //======================================== Decide which map variable should be translated
2362  if ( this->_densityMapCor == nullptr )
2363  {
2364  for ( int uIt = 0; uIt < hlpU; uIt++ )
2365  {
2366  for ( int vIt = 0; vIt < hlpV; vIt++ )
2367  {
2368  for ( int wIt = 0; wIt < hlpW; wIt++ )
2369  {
2370  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
2371 
2372  translatedMap[arrayPos][0] = this->_densityMapMap[arrayPos];
2373  translatedMap[arrayPos][1] = 0.0;
2374  }
2375  }
2376  }
2377  }
2378  else
2379  {
2380  for ( int uIt = 0; uIt < hlpU; uIt++ )
2381  {
2382  for ( int vIt = 0; vIt < hlpV; vIt++ )
2383  {
2384  for ( int wIt = 0; wIt < hlpW; wIt++ )
2385  {
2386  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
2387 
2388  translatedMap[arrayPos][0] = this->_densityMapCor[arrayPos];
2389  translatedMap[arrayPos][1] = 0.0;
2390  }
2391  }
2392  }
2393  }
2394 
2395  //======================================== Compute Fourier
2396  fftw_execute ( planForwardFourier );
2397 
2398  for ( int uIt = 0; uIt < hlpU; uIt++ )
2399  {
2400  for ( int vIt = 0; vIt < hlpV; vIt++ )
2401  {
2402  for ( int wIt = 0; wIt < hlpW; wIt++ )
2403  {
2404  //============================ Var init
2405  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
2406  real = fCoeffs[arrayPos][0];
2407  imag = fCoeffs[arrayPos][1];
2408 
2409  //======================== Change the B-factors, if required
2410  if ( uIt > ((hlpU+1) / 2) ) { h = uIt - hlpU; } else { h = uIt; }
2411  if ( vIt > ((hlpV+1) / 2) ) { k = vIt - hlpV; } else { k = vIt; }
2412  if ( wIt > ((hlpW+1) / 2) ) { l = wIt - hlpW; } else { l = wIt; }
2413 
2414  //============================ Get translation coefficient change
2415  exponent = ( ( ( static_cast <double> ( h ) / this->_xRange ) * xShift ) +
2416  ( ( static_cast <double> ( k ) / this->_yRange ) * yShift ) +
2417  ( ( static_cast <double> ( l ) / this->_zRange ) * zShift ) ) * 2.0 * M_PI;
2418 
2419  trCoeffReal = cos ( exponent );
2420  trCoeffImag = sin ( exponent );
2421 
2422  hlpArr = ProSHADE_internal_misc::complexMultiplication ( &real, &imag, &trCoeffReal, &trCoeffImag );
2423 
2424  //============================ Save the mask data
2425  fCoeffs[arrayPos][0] = hlpArr[0] / normFactor;
2426  fCoeffs[arrayPos][1] = hlpArr[1] / normFactor;
2427  }
2428  }
2429  }
2430 
2431  //======================================== Compute inverse Fourier
2432  fftw_execute ( planBackwardFourier );
2433 
2434  //======================================== Decide which map variable should be translated and remove corners (sometimes have HUUUUUGE values for some reason...)
2435  if ( this->_densityMapCor == nullptr )
2436  {
2437  for ( int uIt = 0; uIt < hlpU; uIt++ )
2438  {
2439  for ( int vIt = 0; vIt < hlpV; vIt++ )
2440  {
2441  for ( int wIt = 0; wIt < hlpW; wIt++ )
2442  {
2443  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
2444  this->_densityMapMap[arrayPos] = static_cast<float> ( translatedMap[arrayPos][0] );
2445  }
2446  }
2447  }
2448  }
2449  else
2450  {
2451  for ( int uIt = 0; uIt < hlpU; uIt++ )
2452  {
2453  for ( int vIt = 0; vIt < hlpV; vIt++ )
2454  {
2455  for ( int wIt = 0; wIt < hlpW; wIt++ )
2456  {
2457  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
2458  this->_densityMapCor[arrayPos] = translatedMap[arrayPos][0];
2459  }
2460  }
2461  }
2462  }
2463 
2464  //======================================== Free memory
2465  fftw_destroy_plan ( planForwardFourier );
2466  fftw_destroy_plan ( planBackwardFourier );
2467  delete[] translatedMap;
2468  delete[] fCoeffs;
2469 
2470  //======================================== Done
2471  return ;
2472 }
2473 
2488 std::array<double,6> ProSHADE_internal::ProSHADE_data::getDensityMapFromMAPRebox ( std::string fileName,
2489  double maxMapIQR,
2490  double extraCS,
2491  int verbose,
2492  bool useCubicMaps,
2493  double maskBlurFactor,
2494  bool maskBlurFactorGiven,
2495  ProSHADE::ProSHADE_settings* settings )
2496 {
2497  //======================================== Initialise internal values
2498  this->_inputFileName = fileName;
2499  this->_maxExtraCellularSpace = extraCS;
2500 
2501  //======================================== Initialise local variables
2502  CMap_io::CMMFile *mapFile = nullptr;
2503  float *cell = nullptr;
2504  int *dim = nullptr;
2505  int *order = nullptr;
2506  int *orig = nullptr;
2507  int myMapMode = 0;
2508  double cornerAvg = 0.0;
2509  double centralAvg = 0.0;
2510  double cornerCount = 0.0;
2511  double centralCount = 0.0;
2512  int maxLim[3];
2513  int XYZOrder[3];
2514  std::array<double,6> ret;
2515 
2516  //======================================== Allocate memory
2517  cell = (float*) malloc ( 6 * sizeof ( float ) );
2518  dim = (int* ) malloc ( 3 * sizeof ( int ) );
2519  order = (int* ) malloc ( 3 * sizeof ( int ) );
2520  orig = (int* ) malloc ( 3 * sizeof ( int ) );
2521 
2522  if ( ( cell == nullptr ) || ( dim == nullptr ) || ( order == nullptr ) || ( orig == nullptr ) )
2523  {
2524  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory. Terminating... " << std::endl;
2525 
2526  if ( settings->htmlReport )
2527  {
2528  std::stringstream hlpSS;
2529  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
2530  rvapi_set_text ( hlpSS.str().c_str(),
2531  "ProgressSection",
2532  settings->htmlReportLineProgress,
2533  1,
2534  1,
2535  1 );
2536  settings->htmlReportLineProgress += 1;
2537  rvapi_flush ( );
2538  }
2539 
2540  exit ( -1 );
2541  }
2542 
2543  //======================================== Read in the MAP file info
2544  mapFile = reinterpret_cast<CMap_io::CMMFile*> ( CMap_io::ccp4_cmap_open ( fileName.c_str() , myMapMode ) );
2545  if ( mapFile == nullptr )
2546  {
2547  std::cerr << "!!! ProSHADE ERROR !!! Failed to open the file " << fileName << ". Check for typos and curruption of the file. Terminating..." << std::endl;
2548 
2549  if ( settings->htmlReport )
2550  {
2551  std::stringstream hlpSS;
2552  hlpSS << "<font color=\"red\">" << "Cannot open file " << fileName << ".</font>";
2553  rvapi_set_text ( hlpSS.str().c_str(),
2554  "ProgressSection",
2555  settings->htmlReportLineProgress,
2556  1,
2557  1,
2558  1 );
2559  settings->htmlReportLineProgress += 1;
2560  rvapi_flush ( );
2561  }
2562 
2563  exit ( -1 );
2564  }
2565 
2566  CMap_io::ccp4_cmap_get_cell ( mapFile, cell );
2567  CMap_io::ccp4_cmap_get_dim ( mapFile, dim );
2568  CMap_io::ccp4_cmap_get_order ( mapFile, order );
2569  CMap_io::ccp4_cmap_get_origin ( mapFile, orig );
2570 
2571 
2572  if ( verbose > 2 )
2573  {
2574  std::cout << ">> Map loaded." << std::endl;
2575  }
2576 
2577  //======================================== If CUBIC
2578  if ( ( ( cell[3] < (90.0 + 0.1) ) && ( cell[3] > (90.0 - 0.1) ) ) &&
2579  ( ( cell[4] < (90.0 + 0.1) ) && ( cell[4] > (90.0 - 0.1) ) ) &&
2580  ( ( cell[5] < (90.0 + 0.1) ) && ( cell[5] > (90.0 - 0.1) ) ) )
2581  {
2582  //==================================== Determine/Save dimmensions
2583  this->_xRange = cell[0];
2584  this->_yRange = cell[1];
2585  this->_zRange = cell[2];
2586 
2587  //==================================== Maximal cell dimensions
2588  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
2589 
2590  //==================================== Find max U, V and W
2591  if ( order[0] == 1 ) { this->_maxMapU = dim[0] - 1; this->_xFrom = orig[0]; }
2592  if ( order[0] == 2 ) { this->_maxMapU = dim[1] - 1; this->_yFrom = orig[0]; }
2593  if ( order[0] == 3 ) { this->_maxMapU = dim[2] - 1; this->_zFrom = orig[0]; }
2594 
2595  if ( order[1] == 1 ) { this->_maxMapV = dim[0] - 1; this->_xFrom = orig[1]; }
2596  if ( order[1] == 2 ) { this->_maxMapV = dim[1] - 1; this->_yFrom = orig[1]; }
2597  if ( order[1] == 3 ) { this->_maxMapV = dim[2] - 1; this->_zFrom = orig[1]; }
2598 
2599  if ( order[2] == 1 ) { this->_maxMapW = dim[0] - 1; this->_xFrom = orig[2]; }
2600  if ( order[2] == 2 ) { this->_maxMapW = dim[1] - 1; this->_yFrom = orig[2]; }
2601  if ( order[2] == 3 ) { this->_maxMapW = dim[2] - 1; this->_zFrom = orig[2]; }
2602 
2603  //==================================== Get the map start and end
2604  this->_xTo = this->_xFrom + this->_maxMapU;
2605  this->_yTo = this->_yFrom + this->_maxMapV;
2606  this->_zTo = this->_zFrom + this->_maxMapW;
2607 
2608  //==================================== Allocate map data memory
2609  this->_densityMapMap = (float*) malloc ( (dim[0]*dim[1]*dim[2]) * sizeof ( float ) );
2610  if ( this->_densityMapMap == nullptr )
2611  {
2612  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
2613 
2614  if ( settings->htmlReport )
2615  {
2616  std::stringstream hlpSS;
2617  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
2618  rvapi_set_text ( hlpSS.str().c_str(),
2619  "ProgressSection",
2620  settings->htmlReportLineProgress,
2621  1,
2622  1,
2623  1 );
2624  settings->htmlReportLineProgress += 1;
2625  rvapi_flush ( );
2626  }
2627 
2628  exit ( -1 );
2629  }
2630 
2631  //==================================== Check if the mode is compatible
2632  int mapMode = CMap_io::ccp4_cmap_get_datamode ( mapFile );
2633  if ( ( mapMode != 0 ) && ( mapMode != 2 ) )
2634  {
2635  std::cerr << "!!! ProSHADE ERROR !!! Cannot read from the map file. The map file mode is not supported. Terminating..." << std::endl;
2636 
2637  if ( settings->htmlReport )
2638  {
2639  std::stringstream hlpSS;
2640  hlpSS << "<font color=\"red\">" << "Cannot read from the map file. The map file mode is neither 0, nor 2. Other map modes are not supported at the moment." << "</font>";
2641  rvapi_set_text ( hlpSS.str().c_str(),
2642  "ProgressSection",
2643  settings->htmlReportLineProgress,
2644  1,
2645  1,
2646  1 );
2647  settings->htmlReportLineProgress += 1;
2648  rvapi_flush ( );
2649  }
2650 
2651  exit ( -1 );
2652  }
2653 
2654  //==================================== Read in map data
2655  // ... Find the stop positions (start is in orig variables) and the axis order
2656  int newU, newV, newW;
2657  int arrPos;
2658 
2659  for ( int iter = 0; iter < 3; iter++ )
2660  {
2661  maxLim[iter] = orig[iter] + dim[iter] - 1;
2662  XYZOrder[order[iter]-1] = iter;
2663  }
2664 
2665  // ... Solve the dimensions and sizes
2666  int fastDimSize = ( maxLim[0] - orig[0] + 1 );
2667  int midDimSize = ( maxLim[1] - orig[1] + 1 ) * fastDimSize;
2668  std::vector<float> section( midDimSize );
2669  int index;
2670  int iters[3];
2671 
2672  // ... Read in the map data
2673  for ( iters[2] = orig[2]; iters[2] <= maxLim[2]; iters[2]++ )
2674  {
2675  index = 0;
2676  CMap_io::ccp4_cmap_read_section( mapFile, &section[0] );
2677 
2678  if ( mapMode == 0 )
2679  {
2680  for ( int iter = ( midDimSize - 1 ); iter >= 0; iter-- )
2681  {
2682  section[iter] = static_cast<float> ( ( reinterpret_cast<unsigned char*> (&section[0]) )[iter] );
2683  }
2684  }
2685 
2686  for ( iters[1] = orig[1]; iters[1] <= maxLim[1]; iters[1]++ )
2687  {
2688  for ( iters[0] = orig[0]; iters[0] <= maxLim[0]; iters[0]++ )
2689  {
2690  newU = iters[XYZOrder[0]] - orig[XYZOrder[0]];
2691  newV = iters[XYZOrder[1]] - orig[XYZOrder[1]];
2692  newW = iters[XYZOrder[2]] - orig[XYZOrder[2]];
2693  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
2694  this->_densityMapMap[arrPos] = static_cast<float> ( section[ index++ ] );
2695  }
2696  }
2697  }
2698 
2699  //==================================== Get values for normalisation
2700  std::vector<double> vals ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) );
2701  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( dim[0] * dim[1] * dim[2] ); iter++ )
2702  {
2703  vals.at(iter) = this->_densityMapMap[iter];
2704  }
2705  std::sort ( vals.begin(), vals.end() );
2706 
2707  //==================================== Find mean and standard deviation for later normalisation
2708  this->_mapMean = std::accumulate ( vals.begin(), vals.end(), 0.0 ) / static_cast<double> ( vals.size() );
2709  this->_mapSdev = std::sqrt ( static_cast<double> ( std::inner_product ( vals.begin(), vals.end(), vals.begin(), 0.0 ) ) / static_cast<double> ( vals.size() ) - this->_mapMean * this->_mapMean );
2710  vals.clear ( );
2711 
2712  //==================================== Check if the map is not absolutely de-centered
2713  int noPToCheckU = static_cast<unsigned int> ( this->_maxMapU / 8.0 );
2714  int noPToCheckV = static_cast<unsigned int> ( this->_maxMapV / 8.0 );
2715  int noPToCheckW = static_cast<unsigned int> ( this->_maxMapW / 8.0 );
2716 
2717  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
2718  {
2719  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
2720  {
2721  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
2722  {
2723  //======================== Initialisation
2724  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
2725 
2726  //======================== Check to which quadrant the value belongs to
2727  if ( ( ( uIt <= static_cast<int> ( this->_maxMapU/2 + noPToCheckU ) ) && ( uIt >= static_cast<int> ( this->_maxMapU/2 - noPToCheckU ) ) ) &&
2728  ( ( vIt <= static_cast<int> ( this->_maxMapV/2 + noPToCheckV ) ) && ( vIt >= static_cast<int> ( this->_maxMapV/2 - noPToCheckV ) ) ) &&
2729  ( ( wIt <= static_cast<int> ( this->_maxMapW/2 + noPToCheckW ) ) && ( wIt >= static_cast<int> ( this->_maxMapW/2 - noPToCheckW ) ) ) )
2730  {
2731  centralAvg += std::max ( this->_densityMapMap[arrPos], static_cast<float>(0.0) );
2732  centralCount += 1.0;
2733  }
2734  if ( ( ( uIt < noPToCheckU ) && ( vIt < noPToCheckV ) && ( wIt < noPToCheckW ) ) ||
2735  ( ( uIt < noPToCheckU ) && ( vIt < noPToCheckV ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
2736  ( ( uIt < noPToCheckU ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt < noPToCheckW ) ) ||
2737  ( ( uIt < noPToCheckU ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
2738  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt < noPToCheckV ) && ( wIt < noPToCheckW ) ) ||
2739  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt < noPToCheckV ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
2740  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt < noPToCheckW ) ) ||
2741  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) )
2742  {
2743  cornerAvg += std::max ( this->_densityMapMap[arrPos], static_cast<float>(0.0) );
2744  cornerCount += 1.0;
2745  }
2746  }
2747  }
2748  }
2749 
2750  cornerAvg /= cornerCount;
2751  centralAvg /= centralCount;
2752 
2753  //==================================== If density is in the corners
2754  if ( cornerAvg > centralAvg )
2755  {
2756  //================================ Initialise required variables
2757  float* hlpMap = nullptr;
2758  hlpMap = (float*) malloc ( (dim[0]*dim[1]*dim[2]) * sizeof ( float ) );
2759  if ( hlpMap == nullptr )
2760  {
2761  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
2762 
2763  if ( settings->htmlReport )
2764  {
2765  std::stringstream hlpSS;
2766  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
2767  rvapi_set_text ( hlpSS.str().c_str(),
2768  "ProgressSection",
2769  settings->htmlReportLineProgress,
2770  1,
2771  1,
2772  1 );
2773  settings->htmlReportLineProgress += 1;
2774  rvapi_flush ( );
2775  }
2776 
2777  exit ( -1 );
2778  }
2779  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( dim[0] * dim[1] * dim[2] ); iter++ )
2780  {
2781  hlpMap[iter] = this->_densityMapMap[iter];
2782  }
2783 
2784  //================================ Transform
2785  unsigned int hlpPos;
2786  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
2787  {
2788  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
2789  {
2790  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
2791  {
2792  //==================== If in lower half, add half; if in upper halp, subtract half
2793  if ( uIt < static_cast<int> (this->_maxMapU+1)/2 ) { newU = uIt + (this->_maxMapU+1)/2; } else { newU = uIt - (this->_maxMapU+1)/2; }
2794  if ( vIt < static_cast<int> (this->_maxMapV+1)/2 ) { newV = vIt + (this->_maxMapV+1)/2; } else { newV = vIt - (this->_maxMapV+1)/2; }
2795  if ( wIt < static_cast<int> (this->_maxMapW+1)/2 ) { newW = wIt + (this->_maxMapW+1)/2; } else { newW = wIt - (this->_maxMapW+1)/2; }
2796 
2797  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
2798  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
2799 
2800  //==================== Set the value into correct coords in the new map
2801  this->_densityMapMap[arrPos] = hlpMap[hlpPos];
2802  }
2803  }
2804  }
2805 
2806  //================================ Free memory
2807  free ( hlpMap );
2808  }
2809 
2810  if ( verbose > 3 )
2811  {
2812  std::cout << ">>>>> Density moved from corners to center, if applicable." << std::endl;
2813  }
2814  }
2815  else
2816  {
2817  std::cerr << "!!! ProSHADE ERROR !!! Non-orthogonal maps are not yet supported." << std::endl;
2818 
2819  if ( settings->htmlReport )
2820  {
2821  std::stringstream hlpSS;
2822  hlpSS << "<font color=\"red\">" << "Detected non-orthogonal map. Currently, only the P1 maps are supported." << "</font>";
2823  rvapi_set_text ( hlpSS.str().c_str(),
2824  "ProgressSection",
2825  settings->htmlReportLineProgress,
2826  1,
2827  1,
2828  1 );
2829  settings->htmlReportLineProgress += 1;
2830  rvapi_flush ( );
2831  }
2832 
2833  exit ( -1 );
2834  }
2835 
2836  if ( settings->htmlReport )
2837  {
2838  std::stringstream hlpSS;
2839  hlpSS << "<font color=\"green\">" << "Structure " << settings->structFiles.at(0) << " read in." << "</font>";
2840  rvapi_set_text ( hlpSS.str().c_str(),
2841  "ProgressSection",
2842  settings->htmlReportLineProgress,
2843  1,
2844  1,
2845  1 );
2846  settings->htmlReportLineProgress += 1;
2847  rvapi_flush ( );
2848  }
2849 
2850  if ( settings->htmlReport )
2851  {
2852  rvapi_add_section ( "OrigHeaderSection",
2853  "Original structure header",
2854  "body",
2855  settings->htmlReportLine,
2856  0,
2857  1,
2858  1,
2859  false );
2860  settings->htmlReportLine += 1;
2861 
2862  //==================================== Print max U, V and W
2863  std::stringstream hlpSS;
2864  hlpSS << "<pre><b>" << "Rows, Columns and Sections sizes: " << "</b>";
2865  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
2866  {
2867  hlpSS << ".";
2868  }
2869 
2870  int prec = 6;
2871  int UVWMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapU+1 ), prec ).length(),
2872  std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapV+1 ), prec ).length(),
2873  ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapW+1 ), prec ).length() ) );
2874  int FMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_xFrom, prec ).length(),
2875  std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_yFrom, prec ).length(),
2876  ProSHADE_internal_misc::to_string_with_precision ( this->_zFrom, prec ).length() ) );
2877  int TMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_xTo, prec ).length(),
2878  std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_yTo, prec ).length(),
2879  ProSHADE_internal_misc::to_string_with_precision ( this->_zTo, prec ).length() ) );
2880  int CDMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_xRange, prec ).length(),
2881  std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_yRange, prec ).length(),
2882  ProSHADE_internal_misc::to_string_with_precision ( this->_zRange, prec ).length() ) );
2883  int CAMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( cell[3], prec ).length(),
2884  std::max ( ProSHADE_internal_misc::to_string_with_precision ( cell[4], prec ).length(),
2885  ProSHADE_internal_misc::to_string_with_precision ( cell[5], prec ).length() ) );
2886  int spacer = std::max ( UVWMAX, std::max ( FMAX, std::max ( TMAX, std::max ( CDMAX, CAMAX ) ) ) );
2887  if ( spacer < 5 ) { spacer = 5; }
2888 
2889  hlpSS << std::showpos << std::setprecision ( prec ) << " " << static_cast<int> ( this->_maxMapU+1 );
2890  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapU+1 ), prec ).length() ); iter++ )
2891  {
2892  hlpSS << " ";
2893  }
2894  hlpSS << " ";
2895 
2896  hlpSS << std::showpos << static_cast<int> ( this->_maxMapV+1 );
2897  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapV+1 ), prec ).length() ); iter++ )
2898  {
2899  hlpSS << " ";
2900  }
2901  hlpSS << " ";
2902 
2903  hlpSS << std::showpos << static_cast<int> ( this->_maxMapW+1 );
2904  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapW+1 ), prec ).length() ); iter++ )
2905  {
2906  hlpSS << " ";
2907  }
2908  hlpSS << "</pre>";
2909 
2910  rvapi_set_text ( hlpSS.str().c_str(),
2911  "OrigHeaderSection",
2912  0,
2913  0,
2914  1,
2915  1 );
2916 
2917  //==================================== Print from and to lims
2918  hlpSS.str ( std::string ( ) );
2919  hlpSS << "<pre><b>" << "Start and stop points on columns, rows, sections: " << "</b>";
2920  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
2921  {
2922  hlpSS << ".";
2923  }
2924 
2925  hlpSS << std::showpos << std::setprecision ( prec ) << " " << this->_xFrom;
2926  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_xFrom, prec ).length() ); iter++ )
2927  {
2928  hlpSS << " ";
2929  }
2930  hlpSS << " ";
2931 
2932  hlpSS << std::showpos << this->_xTo;
2933  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_xTo, prec ).length() ); iter++ )
2934  {
2935  hlpSS << " ";
2936  }
2937  hlpSS << " ";
2938 
2939  hlpSS << std::showpos << this->_yFrom;
2940  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_yFrom, prec ).length() ); iter++ )
2941  {
2942  hlpSS << " ";
2943  }
2944  hlpSS << " ";
2945 
2946  hlpSS << std::showpos << this->_yTo;
2947  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_yTo, prec ).length() ); iter++ )
2948  {
2949  hlpSS << " ";
2950  }
2951  hlpSS << " ";
2952 
2953  hlpSS << std::showpos << " " << this->_zFrom;
2954  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_zFrom, prec ).length() ); iter++ )
2955  {
2956  hlpSS << " ";
2957  }
2958  hlpSS << " ";
2959 
2960  hlpSS << std::showpos << this->_zTo;
2961  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_zTo, prec ).length() ); iter++ )
2962  {
2963  hlpSS << " ";
2964  }
2965  hlpSS << "</pre>";
2966 
2967  rvapi_set_text ( hlpSS.str().c_str(),
2968  "OrigHeaderSection",
2969  1,
2970  0,
2971  1,
2972  1 );
2973 
2974  //==================================== Print cell dimensions
2975  hlpSS.str ( std::string ( ) );
2976  hlpSS << "<pre><b>" << "Cell dimensions (Angstrom): " << "</b>";
2977  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
2978  {
2979  hlpSS << ".";
2980  }
2981 
2982  hlpSS << std::showpos << std::setprecision ( prec ) << " " << this->_xRange;
2983  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_xRange, prec ).length() ); iter++ )
2984  {
2985  hlpSS << " ";
2986  }
2987  hlpSS << " ";
2988 
2989  hlpSS << std::showpos << this->_yRange;
2990  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_yRange, prec ).length() ); iter++ )
2991  {
2992  hlpSS << " ";
2993  }
2994  hlpSS << " ";
2995 
2996  hlpSS << std::showpos << this->_zRange;
2997  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_zRange, prec ).length() ); iter++ )
2998  {
2999  hlpSS << " ";
3000  }
3001  hlpSS << "</pre>";
3002 
3003  rvapi_set_text ( hlpSS.str().c_str(),
3004  "OrigHeaderSection",
3005  2,
3006  0,
3007  1,
3008  1 );
3009 
3010  //==================================== Print cell dimensions
3011  hlpSS.str ( std::string ( ) );
3012  hlpSS << "<pre><b>" << "Cell angles (Degrees): " << "</b>";
3013  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3014  {
3015  hlpSS << ".";
3016  }
3017 
3018  hlpSS << std::showpos << std::setprecision ( prec ) << " " << cell[3];
3019  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( cell[3], prec ).length() ); iter++ )
3020  {
3021  hlpSS << " ";
3022  }
3023  hlpSS << " ";
3024 
3025  hlpSS << std::showpos << cell[4];
3026  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( cell[4], prec ).length() ); iter++ )
3027  {
3028  hlpSS << " ";
3029  }
3030  hlpSS << " ";
3031 
3032  hlpSS << std::showpos << cell[5];
3033  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( cell[5], prec ).length() ); iter++ )
3034  {
3035  hlpSS << " ";
3036  }
3037  hlpSS << "</pre>";
3038 
3039  rvapi_set_text ( hlpSS.str().c_str(),
3040  "OrigHeaderSection",
3041  3,
3042  0,
3043  1,
3044  1 );
3045 
3046  //==================================== Print cell dimensions
3047  hlpSS.str ( std::string ( ) );
3048  hlpSS << "<pre><b>" << "Fast, medium, slow axes: " << "</b>";
3049  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3050  {
3051  hlpSS << ".";
3052  }
3053 
3054  if ( XYZOrder[0] == 0 ) { hlpSS << " X"; }
3055  else if ( XYZOrder[0] == 1 ) { hlpSS << " Y"; }
3056  else { hlpSS << " Z"; }
3057  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
3058  {
3059  hlpSS << " ";
3060  }
3061  hlpSS << " ";
3062 
3063  if ( XYZOrder[1] == 0 ) { hlpSS << "X"; }
3064  else if ( XYZOrder[1] == 1 ) { hlpSS << "Y"; }
3065  else { hlpSS << "Z"; }
3066  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
3067  {
3068  hlpSS << " ";
3069  }
3070  hlpSS << " ";
3071 
3072  if ( XYZOrder[2] == 0 ) { hlpSS << "X"; }
3073  else if ( XYZOrder[2] == 1 ) { hlpSS << "Y"; }
3074  else { hlpSS << "Z"; }
3075  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
3076  {
3077  hlpSS << " ";
3078  }
3079  hlpSS << "</pre>";
3080 
3081  rvapi_set_text ( hlpSS.str().c_str(),
3082  "OrigHeaderSection",
3083  4,
3084  0,
3085  1,
3086  1 );
3087 
3088  rvapi_flush ( );
3089  }
3090 
3091  //======================================== Set return values
3092  ret[0] = this->_maxMapU + 1;
3093  ret[1] = this->_maxMapV + 1;
3094  ret[2] = this->_maxMapW + 1;
3095 
3096  //======================================== Free memory
3097  if ( cell != nullptr )
3098  {
3099  free ( cell );
3100  cell = nullptr;
3101  }
3102  if ( dim != nullptr )
3103  {
3104  free ( dim );
3105  dim = nullptr;
3106  }
3107  if ( order != nullptr )
3108  {
3109  free ( order );
3110  order = nullptr;
3111  }
3112  if ( orig != nullptr )
3113  {
3114  free ( orig );
3115  orig = nullptr;
3116  }
3117 
3118  //======================================== Close the file
3119  CMap_io::ccp4_cmap_close ( mapFile );
3120 
3121  //======================================== Local hlp variables
3122  int hlpU = ( this->_maxMapU + 1 );
3123  int hlpV = ( this->_maxMapV + 1 );
3124  int hlpW = ( this->_maxMapW + 1 );
3125 
3126  //======================================== Initialise local variables for Fourier and Inverse Fourier
3127  this->_densityMapCor = new double [hlpU * hlpV * hlpW];
3128 
3129  //======================================== Load map data for Fourier
3130  std::vector<double> vals ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) );
3131 
3132  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
3133  {
3134  if ( this->_densityMapMap[iter] == this->_densityMapMap[iter] )
3135  {
3136  //================================ Map value is NOT nan
3137  this->_densityMapCor[iter] = this->_densityMapMap[iter];
3138  }
3139  else
3140  {
3141  //================================ Map value is nan - this sometimes occurs for a couple of values, I have no clue as to why...
3142  this->_densityMapCor[iter] = 0.0;
3143  }
3144  }
3145  if ( verbose > 3 )
3146  {
3147  std::cout << ">>>>> Map normalised." << std::endl;
3148  }
3149 
3150  //======================================== Map masking
3151  double *tmpMp = new double[hlpU * hlpV * hlpW];
3152  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
3153  {
3154  tmpMp[iter] = this->_densityMapCor[iter];
3155  }
3156 
3157  bool notTooManyIslads = true;
3158  double blFr = 150.0;
3159 
3160  while ( notTooManyIslads )
3161  {
3162  //================================ Do not change user values
3163  blFr += 50.0;
3164  if ( maskBlurFactorGiven )
3165  {
3166  blFr = maskBlurFactor;
3167  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
3168  break;
3169  }
3170 
3171  //================================ Compute mask and apply it
3172  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
3173 
3174  //================================ Detect islands
3175  if ( verbose > 3 )
3176  {
3177  std::cout << ">>>>>>>> Island detection started." << std::endl;
3178  }
3179 
3180  notTooManyIslads = this->removeIslands ( hlpU, hlpV, hlpW, verbose, false );
3181 
3182  if ( verbose > 3 )
3183  {
3184  std::cout << ">>>>> Map masked with factor of " << blFr << " and small islands were then removed.";
3185  }
3186  if ( notTooManyIslads )
3187  {
3188  if ( verbose > 3 )
3189  {
3190  std::cout << " However, too many islands remained. Trying higher blurring factor." << std::endl;
3191  }
3192 
3193  if ( blFr <= 500.0 )
3194  {
3195  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
3196  {
3197  this->_densityMapCor[iter] = tmpMp[iter];
3198  }
3199  }
3200  }
3201  else
3202  {
3203  if ( verbose > 3 )
3204  {
3205  std::cout << std::endl;
3206  }
3207  }
3208 
3209 
3210  if ( blFr > 500.0 )
3211  {
3212  std::cout << "!!! ProSHADE WARNING !!! Even blurring factor of 500 did not remove islands. Will not proceed with what we have, but be warned that either the masking is bugged or yout map has high levels of noise. You can consider using the -y ( or --no_clear ) options to avoid this message and the extra time for testing different blurring factors for this map." << std::endl;
3213 
3214  if ( settings->htmlReport )
3215  {
3216  std::stringstream hlpSS;
3217  hlpSS << "<font color=\"orange\">" << "Even blurring factor of 500 did not remove islands. Will not proceed with what we have, but be warned that either the masking is bugged or yout map has high levels of noise. You can consider using the -y ( or --no_clear ) options to avoid this message and the extra time for testing different blurring factors for this map." << "</font>";
3218  rvapi_set_text ( hlpSS.str().c_str(),
3219  "ProgressSection",
3220  settings->htmlReportLineProgress,
3221  1,
3222  1,
3223  1 );
3224  settings->htmlReportLineProgress += 1;
3225  rvapi_flush ( );
3226  }
3227 
3228  break;
3229  }
3230  }
3231 
3232  //======================================== Once values are decided, run then WITHOUT the island detection
3233  if ( !maskBlurFactorGiven )
3234  {
3235  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
3236  {
3237  this->_densityMapCor[iter] = tmpMp[iter];
3238  }
3239 
3240  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
3241  }
3242 
3243  if ( verbose > 2 )
3244  {
3245  std::cout << ">> Map masked." << std::endl;
3246  }
3247 
3248  if ( settings->htmlReport )
3249  {
3250  std::stringstream hlpSS;
3251  hlpSS << "<font color=\"green\">" << "Map masked." << "</font>";
3252  rvapi_set_text ( hlpSS.str().c_str(),
3253  "ProgressSection",
3254  settings->htmlReportLineProgress,
3255  1,
3256  1,
3257  1 );
3258  settings->htmlReportLineProgress += 1;
3259  rvapi_flush ( );
3260  }
3261 
3262  //======================================== Determine the real size of the shape
3263  int coordPos = 0;
3264  int maxX = hlpU/2;
3265  int minX = hlpU/2;
3266  int maxY = hlpV/2;
3267  int minY = hlpV/2;
3268  int maxZ = hlpW/2;
3269  int minZ = hlpW/2;
3270  int maxXTot = hlpU/2;
3271  int minXTot = hlpU/2;
3272  int maxYTot = hlpV/2;
3273  int minYTot = hlpV/2;
3274  int maxZTot = hlpW/2;
3275  int minZTot = hlpW/2;
3276 
3277  for ( int uIt = 0; uIt < hlpU; uIt++ )
3278  {
3279  for ( int vIt = 0; vIt < hlpV; vIt++ )
3280  {
3281  for ( int wIt = 0; wIt < hlpW; wIt++ )
3282  {
3283  coordPos = wIt + hlpW * ( vIt + hlpV * uIt );
3284 
3285  if ( this->_densityMapCor[coordPos] > 0.0 )
3286  {
3287  maxX = std::max ( maxX, uIt );
3288  minX = std::min ( minX, uIt );
3289  maxY = std::max ( maxY, vIt );
3290  minY = std::min ( minY, vIt );
3291  maxZ = std::max ( maxZ, wIt );
3292  minZ = std::min ( minZ, wIt );
3293  }
3294  maxXTot = std::max ( maxXTot, uIt );
3295  minXTot = std::min ( minXTot, uIt );
3296  maxYTot = std::max ( maxYTot, vIt );
3297  minYTot = std::min ( minYTot, vIt );
3298  maxZTot = std::max ( maxZTot, wIt );
3299  minZTot = std::min ( minZTot, wIt );
3300  }
3301  }
3302  }
3303 
3304  //======================================== Calculate the grid for only the shape
3305  int newUStart = static_cast<int> ( this->_xFrom + ( minXTot + minX ) );
3306  int newUEnd = static_cast<int> ( this->_xTo - ( maxXTot - maxX ) );
3307  int newVStart = static_cast<int> ( this->_yFrom + ( minYTot + minY ) );
3308  int newVEnd = static_cast<int> ( this->_yTo - ( maxYTot - maxY ) );
3309  int newWStart = static_cast<int> ( this->_zFrom + ( minZTot + minZ ) );
3310  int newWEnd = static_cast<int> ( this->_zTo - ( maxZTot - maxZ ) );
3311 
3312  //======================================== Add the extra space
3313  if ( this->_maxExtraCellularSpace > 0.0 )
3314  {
3315  int extraPTs = static_cast<int> ( std::ceil ( this->_maxExtraCellularSpace / ( static_cast<double> ( this->_maxMapRange ) / static_cast<double> ( std::max ( hlpU, std::max ( hlpV, hlpW ) ) ) ) ) );
3316 
3317  if ( (newUStart - extraPTs) > static_cast<int> ( this->_xFrom ) ) { newUStart -= static_cast<int> ( extraPTs ); }
3318  if ( (newVStart - extraPTs) > static_cast<int> ( this->_yFrom ) ) { newVStart -= static_cast<int> ( extraPTs ); }
3319  if ( (newWStart - extraPTs) > static_cast<int> ( this->_zFrom ) ) { newWStart -= static_cast<int> ( extraPTs ); }
3320  if ( (newUEnd + extraPTs) < static_cast<int> ( this->_xTo ) ) { newUEnd += static_cast<int> ( extraPTs ); }
3321  if ( (newVEnd + extraPTs) < static_cast<int> ( this->_yTo ) ) { newVEnd += static_cast<int> ( extraPTs ); }
3322  if ( (newWEnd + extraPTs) < static_cast<int> ( this->_zTo ) ) { newWEnd += static_cast<int> ( extraPTs ); }
3323  }
3324 
3325  //======================================== Free unnecessary memory
3326  if ( this->_densityMapCor != nullptr )
3327  {
3328  delete[] this->_densityMapCor;
3329  this->_densityMapCor = nullptr;
3330  }
3331 
3332  //======================================== Move map
3333  int newXDim = newUEnd - newUStart + 1;
3334  int newYDim = newVEnd - newVStart + 1;
3335  int newZDim = newWEnd - newWStart + 1;
3336 
3337  if ( ( this->_xFrom < 0 ) && ( ( this->_xFrom + newUStart ) >= 0 ) ) { newXDim += 1; }
3338  if ( ( this->_yFrom < 0 ) && ( ( this->_yFrom + newVStart ) >= 0 ) ) { newYDim += 1; }
3339  if ( ( this->_zFrom < 0 ) && ( ( this->_zFrom + newWStart ) >= 0 ) ) { newZDim += 1; }
3340 
3341  this->_densityMapCor = new double [newXDim * newYDim * newZDim];
3342 
3343  int arrPos, hlpPos;
3344  int newU, newV, newW;
3345  for ( int uIt = newUStart; uIt <= newUEnd; uIt++ )
3346  {
3347  for ( int vIt = newVStart; vIt <= newVEnd; vIt++ )
3348  {
3349  for ( int wIt = newWStart; wIt <= newWEnd; wIt++ )
3350  {
3351  newU = uIt - newUStart;
3352  newV = vIt - newVStart;
3353  newW = wIt - newWStart;
3354  hlpPos = newW + newZDim * ( newV + newYDim * newU );
3355 
3356  newU = uIt - this->_xFrom;
3357  newV = vIt - this->_yFrom;
3358  newW = wIt - this->_zFrom;
3359  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
3360 
3361  this->_densityMapCor[hlpPos] = tmpMp[arrPos];
3362  }
3363  }
3364  }
3365 
3366  if ( verbose > 0 )
3367  {
3368  std::cout << "Map re-boxed." << std::endl;
3369  }
3370 
3371  if ( settings->htmlReport )
3372  {
3373  std::stringstream hlpSS;
3374  hlpSS << "<font color=\"green\">" << "Map re-boxed." << "</font>";
3375  rvapi_set_text ( hlpSS.str().c_str(),
3376  "ProgressSection",
3377  settings->htmlReportLineProgress,
3378  1,
3379  1,
3380  1 );
3381  settings->htmlReportLineProgress += 1;
3382  rvapi_flush ( );
3383  }
3384 
3385  //======================================== Clear memory
3386  delete[] tmpMp;
3387 
3388  //======================================== Change the settings
3389  this->_xFrom = newUStart;
3390  this->_yFrom = newVStart;
3391  this->_zFrom = newWStart;
3392 
3393  this->_xTo = newUEnd;
3394  this->_yTo = newVEnd;
3395  this->_zTo = newWEnd;
3396 
3397  this->_xSamplingRate = static_cast<double> ( this->_xRange ) / static_cast<double> ( hlpU );
3398  this->_ySamplingRate = static_cast<double> ( this->_yRange ) / static_cast<double> ( hlpV );
3399  this->_zSamplingRate = static_cast<double> ( this->_zRange ) / static_cast<double> ( hlpW );
3400 
3401  this->_xRange = this->_xSamplingRate * ( newXDim );
3402  this->_yRange = this->_ySamplingRate * ( newYDim );
3403  this->_zRange = this->_zSamplingRate * ( newZDim );
3404 
3405  this->_maxMapU = newXDim - 1;
3406  this->_maxMapV = newYDim - 1;
3407  this->_maxMapW = newZDim - 1;
3408 
3409  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
3410  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
3411  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
3412 
3413  //======================================== Free unnecessary memory
3414  if ( this->_densityMapMap != nullptr )
3415  {
3416  delete this->_densityMapMap;
3417  this->_densityMapMap = nullptr;
3418  }
3419 
3420  //======================================== Report the new structure header
3421  if ( settings->htmlReport )
3422  {
3423  rvapi_add_section ( "NewHeaderSection",
3424  "Re-boxed structure header",
3425  "body",
3426  settings->htmlReportLine,
3427  0,
3428  1,
3429  1,
3430  false );
3431  settings->htmlReportLine += 1;
3432 
3433  //==================================== Print max U, V and W
3434  std::stringstream hlpSS;
3435  hlpSS << "<pre><b>" << "Rows, Columns and Sections sizes: " << "</b>";
3436  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3437  {
3438  hlpSS << ".";
3439  }
3440 
3441  int prec = 6;
3442  int UVWMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapU+1 ), prec ).length(),
3443  std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapV+1 ), prec ).length(),
3444  ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapW+1 ), prec ).length() ) );
3445  int FMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_xFrom, prec ).length(),
3446  std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_yFrom, prec ).length(),
3447  ProSHADE_internal_misc::to_string_with_precision ( this->_zFrom, prec ).length() ) );
3448  int TMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_xTo, prec ).length(),
3449  std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_yTo, prec ).length(),
3450  ProSHADE_internal_misc::to_string_with_precision ( this->_zTo, prec ).length() ) );
3451  int CDMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_xRange, prec ).length(),
3452  std::max ( ProSHADE_internal_misc::to_string_with_precision ( this->_yRange, prec ).length(),
3453  ProSHADE_internal_misc::to_string_with_precision ( this->_zRange, prec ).length() ) );
3454  int CAMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( 90.000, prec ).length(),
3455  std::max ( ProSHADE_internal_misc::to_string_with_precision ( 90.000, prec ).length(),
3456  ProSHADE_internal_misc::to_string_with_precision ( 90.000, prec ).length() ) );
3457  int spacer = std::max ( UVWMAX, std::max ( FMAX, std::max ( TMAX, std::max ( CDMAX, CAMAX ) ) ) );
3458  if ( spacer < 5 ) { spacer = 5; }
3459 
3460  hlpSS << std::showpos << std::setprecision ( prec ) << " " << static_cast<int> ( this->_maxMapU+1 );
3461  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapU+1 ), prec ).length() ); iter++ )
3462  {
3463  hlpSS << " ";
3464  }
3465  hlpSS << " ";
3466 
3467  hlpSS << std::showpos << static_cast<int> ( this->_maxMapV+1 );
3468  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapV+1 ), prec ).length() ); iter++ )
3469  {
3470  hlpSS << " ";
3471  }
3472  hlpSS << " ";
3473 
3474  hlpSS << std::showpos << static_cast<int> ( this->_maxMapW+1 );
3475  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( this->_maxMapW+1 ), prec ).length() ); iter++ )
3476  {
3477  hlpSS << " ";
3478  }
3479  hlpSS << "</pre>";
3480 
3481  rvapi_set_text ( hlpSS.str().c_str(),
3482  "NewHeaderSection",
3483  0,
3484  0,
3485  1,
3486  1 );
3487 
3488  //==================================== Print from and to lims
3489  hlpSS.str ( std::string ( ) );
3490  hlpSS << "<pre><b>" << "Start and stop points on columns, rows, sections: " << "</b>";
3491  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3492  {
3493  hlpSS << ".";
3494  }
3495 
3496  hlpSS << std::showpos << std::setprecision ( prec ) << " " << this->_xFrom;
3497  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_xFrom, prec ).length() ); iter++ )
3498  {
3499  hlpSS << " ";
3500  }
3501  hlpSS << " ";
3502 
3503  hlpSS << std::showpos << this->_xTo;
3504  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_xTo, prec ).length() ); iter++ )
3505  {
3506  hlpSS << " ";
3507  }
3508  hlpSS << " ";
3509 
3510  hlpSS << std::showpos << this->_yFrom;
3511  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_yFrom, prec ).length() ); iter++ )
3512  {
3513  hlpSS << " ";
3514  }
3515  hlpSS << " ";
3516 
3517  hlpSS << std::showpos << this->_yTo;
3518  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_yTo, prec ).length() ); iter++ )
3519  {
3520  hlpSS << " ";
3521  }
3522  hlpSS << " ";
3523 
3524  hlpSS << std::showpos << " " << this->_zFrom;
3525  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_zFrom, prec ).length() ); iter++ )
3526  {
3527  hlpSS << " ";
3528  }
3529  hlpSS << " ";
3530 
3531  hlpSS << std::showpos << this->_zTo;
3532  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_zTo, prec ).length() ); iter++ )
3533  {
3534  hlpSS << " ";
3535  }
3536  hlpSS << "</pre>";
3537 
3538  rvapi_set_text ( hlpSS.str().c_str(),
3539  "NewHeaderSection",
3540  1,
3541  0,
3542  1,
3543  1 );
3544 
3545  //==================================== Print cell dimensions
3546  hlpSS.str ( std::string ( ) );
3547  hlpSS << "<pre><b>" << "Cell dimensions (Angstrom): " << "</b>";
3548  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3549  {
3550  hlpSS << ".";
3551  }
3552 
3553  hlpSS << std::showpos << std::setprecision ( prec ) << " " << this->_xRange;
3554  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_xRange, prec ).length() ); iter++ )
3555  {
3556  hlpSS << " ";
3557  }
3558  hlpSS << " ";
3559 
3560  hlpSS << std::showpos << this->_yRange;
3561  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_yRange, prec ).length() ); iter++ )
3562  {
3563  hlpSS << " ";
3564  }
3565  hlpSS << " ";
3566 
3567  hlpSS << std::showpos << this->_zRange;
3568  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( this->_zRange, prec ).length() ); iter++ )
3569  {
3570  hlpSS << " ";
3571  }
3572  hlpSS << "</pre>";
3573 
3574  rvapi_set_text ( hlpSS.str().c_str(),
3575  "NewHeaderSection",
3576  2,
3577  0,
3578  1,
3579  1 );
3580 
3581  //==================================== Print cell dimensions
3582  hlpSS.str ( std::string ( ) );
3583  hlpSS << "<pre><b>" << "Cell angles (Degrees): " << "</b>";
3584  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3585  {
3586  hlpSS << ".";
3587  }
3588 
3589  hlpSS << std::showpos << std::setprecision ( prec ) << " " << 90.000;
3590  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.000, prec ).length() ); iter++ )
3591  {
3592  hlpSS << " ";
3593  }
3594  hlpSS << " ";
3595 
3596  hlpSS << std::showpos << 90.000;
3597  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.000, prec ).length() ); iter++ )
3598  {
3599  hlpSS << " ";
3600  }
3601  hlpSS << " ";
3602 
3603  hlpSS << std::showpos << 90.000;
3604  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.000, prec ).length() ); iter++ )
3605  {
3606  hlpSS << " ";
3607  }
3608  hlpSS << "</pre>";
3609 
3610  rvapi_set_text ( hlpSS.str().c_str(),
3611  "NewHeaderSection",
3612  3,
3613  0,
3614  1,
3615  1 );
3616 
3617  //==================================== Print cell dimensions
3618  hlpSS.str ( std::string ( ) );
3619  hlpSS << "<pre><b>" << "Fast, medium, slow axes: " << "</b>";
3620  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
3621  {
3622  hlpSS << ".";
3623  }
3624 
3625  if ( XYZOrder[0] == 0 ) { hlpSS << " X"; }
3626  else if ( XYZOrder[0] == 1 ) { hlpSS << " Y"; }
3627  else { hlpSS << " Z"; }
3628  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
3629  {
3630  hlpSS << " ";
3631  }
3632  hlpSS << " ";
3633 
3634  if ( XYZOrder[1] == 0 ) { hlpSS << "X"; }
3635  else if ( XYZOrder[1] == 1 ) { hlpSS << "Y"; }
3636  else { hlpSS << "Z"; }
3637  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
3638  {
3639  hlpSS << " ";
3640  }
3641  hlpSS << " ";
3642 
3643  if ( XYZOrder[2] == 0 ) { hlpSS << "X"; }
3644  else if ( XYZOrder[2] == 1 ) { hlpSS << "Y"; }
3645  else { hlpSS << "Z"; }
3646  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
3647  {
3648  hlpSS << " ";
3649  }
3650  hlpSS << "</pre>";
3651 
3652  rvapi_set_text ( hlpSS.str().c_str(),
3653  "NewHeaderSection",
3654  4,
3655  0,
3656  1,
3657  1 );
3658 
3659  rvapi_flush ( );
3660  }
3661 
3662  //======================================== Set return values
3663  ret[3] = this->_maxMapU + 1;
3664  ret[4] = this->_maxMapV + 1;
3665  ret[5] = this->_maxMapW + 1;
3666 
3667  //======================================== Done
3668  return ( ret );
3669 }
3670 
3706  double *minDensPreNorm,
3707  double *maxDensPreNorm,
3708  double *minDensPostNorm,
3709  double *maxDensPostNorm,
3710  double *postNormMean,
3711  double *postNormSdev,
3712  double *maskVolume,
3713  double* totalVolume,
3714  double *maskMean,
3715  double *maskSdev,
3716  double *maskMin,
3717  double *maskMax,
3718  double *maskDensityRMS,
3719  double *allDensityRMS,
3720  std::array<double,3> *origRanges,
3721  std::array<double,3> *origDims,
3722  double maxMapIQR,
3723  double extraCS,
3724  int verbose,
3725  bool useCubicMaps,
3726  double maskBlurFactor,
3727  bool maskBlurFactorGiven,
3728  bool reboxAtAll,
3729  ProSHADE::ProSHADE_settings* settings )
3730 {
3731  //======================================== Initialise internal values
3732  this->_inputFileName = fileName;
3733 
3734  //======================================== Initialise local variables
3735  CMap_io::CMMFile *mapFile = nullptr;
3736  float *cell = nullptr;
3737  int *dim = nullptr;
3738  int *order = nullptr;
3739  int *orig = nullptr;
3740  int myMapMode = 0;
3741  double cornerAvg = 0.0;
3742  double centralAvg = 0.0;
3743  double cornerCount = 0.0;
3744  double centralCount = 0.0;
3745 
3746  //======================================== Allocate memory
3747  cell = (float*) malloc ( 6 * sizeof ( float ) );
3748  dim = (int* ) malloc ( 3 * sizeof ( int ) );
3749  order = (int* ) malloc ( 3 * sizeof ( int ) );
3750  orig = (int* ) malloc ( 3 * sizeof ( int ) );
3751 
3752  if ( ( cell == nullptr ) || ( dim == nullptr ) || ( order == nullptr ) || ( orig == nullptr ) )
3753  {
3754  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory. Terminating... " << std::endl;
3755 
3756  if ( settings->htmlReport )
3757  {
3758  std::stringstream hlpSS;
3759  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
3760  rvapi_set_text ( hlpSS.str().c_str(),
3761  "ProgressSection",
3762  settings->htmlReportLineProgress,
3763  1,
3764  1,
3765  1 );
3766  settings->htmlReportLineProgress += 1;
3767  rvapi_flush ( );
3768  }
3769 
3770  exit ( -1 );
3771  }
3772 
3773  //======================================== Read in the MAP file info
3774  mapFile = reinterpret_cast<CMap_io::CMMFile*> ( CMap_io::ccp4_cmap_open ( fileName.c_str() , myMapMode ) );
3775  if ( mapFile == nullptr )
3776  {
3777  std::cerr << "!!! ProSHADE ERROR !!! Failed to open the file " << fileName << ". Check for typos and curruption of the file. Terminating..." << std::endl;
3778 
3779  if ( settings->htmlReport )
3780  {
3781  std::stringstream hlpSS;
3782  hlpSS << "<font color=\"red\">" << "Cannot open file " << fileName << ".</font>";
3783  rvapi_set_text ( hlpSS.str().c_str(),
3784  "ProgressSection",
3785  settings->htmlReportLineProgress,
3786  1,
3787  1,
3788  1 );
3789  settings->htmlReportLineProgress += 1;
3790  rvapi_flush ( );
3791  }
3792 
3793  exit ( -1 );
3794  }
3795 
3796  CMap_io::ccp4_cmap_get_cell ( mapFile, cell );
3797  CMap_io::ccp4_cmap_get_dim ( mapFile, dim );
3798  CMap_io::ccp4_cmap_get_order ( mapFile, order );
3799  CMap_io::ccp4_cmap_get_origin ( mapFile, orig );
3800 
3801 
3802  if ( verbose > 2 )
3803  {
3804  std::cout << ">> Map loaded." << std::endl;
3805  }
3806 
3807  //======================================== If CUBIC
3808  if ( ( ( cell[3] < (90.0 + 0.1) ) && ( cell[3] > (90.0 - 0.1) ) ) &&
3809  ( ( cell[4] < (90.0 + 0.1) ) && ( cell[4] > (90.0 - 0.1) ) ) &&
3810  ( ( cell[5] < (90.0 + 0.1) ) && ( cell[5] > (90.0 - 0.1) ) ) )
3811  {
3812  //==================================== Determine/Save dimmensions
3813  this->_xRange = cell[0];
3814  this->_yRange = cell[1];
3815  this->_zRange = cell[2];
3816 
3817  //==================================== Maximal cell dimensions
3818  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
3819 
3820  //==================================== Find max U, V and W
3821  if ( order[0] == 1 ) { this->_maxMapU = dim[0] - 1; this->_xFrom = orig[0]; }
3822  if ( order[0] == 2 ) { this->_maxMapU = dim[1] - 1; this->_yFrom = orig[0]; }
3823  if ( order[0] == 3 ) { this->_maxMapU = dim[2] - 1; this->_zFrom = orig[0]; }
3824 
3825  if ( order[1] == 1 ) { this->_maxMapV = dim[0] - 1; this->_xFrom = orig[1]; }
3826  if ( order[1] == 2 ) { this->_maxMapV = dim[1] - 1; this->_yFrom = orig[1]; }
3827  if ( order[1] == 3 ) { this->_maxMapV = dim[2] - 1; this->_zFrom = orig[1]; }
3828 
3829  if ( order[2] == 1 ) { this->_maxMapW = dim[0] - 1; this->_xFrom = orig[2]; }
3830  if ( order[2] == 2 ) { this->_maxMapW = dim[1] - 1; this->_yFrom = orig[2]; }
3831  if ( order[2] == 3 ) { this->_maxMapW = dim[2] - 1; this->_zFrom = orig[2]; }
3832 
3833  //==================================== Get the map start and end
3834  this->_xTo = this->_xFrom + this->_maxMapU;
3835  this->_yTo = this->_yFrom + this->_maxMapV;
3836  this->_zTo = this->_zFrom + this->_maxMapW;
3837 
3838  //==================================== Allocate map data memory
3839  this->_densityMapMap = (float*) malloc ( (dim[0]*dim[1]*dim[2]) * sizeof ( float ) );
3840  if ( this->_densityMapMap == nullptr )
3841  {
3842  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
3843 
3844  if ( settings->htmlReport )
3845  {
3846  std::stringstream hlpSS;
3847  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
3848  rvapi_set_text ( hlpSS.str().c_str(),
3849  "ProgressSection",
3850  settings->htmlReportLineProgress,
3851  1,
3852  1,
3853  1 );
3854  settings->htmlReportLineProgress += 1;
3855  rvapi_flush ( );
3856  }
3857 
3858  exit ( -1 );
3859  }
3860 
3861  //==================================== Check if the mode is compatible
3862  int mapMode = CMap_io::ccp4_cmap_get_datamode ( mapFile );
3863  if ( ( mapMode != 0 ) && ( mapMode != 2 ) )
3864  {
3865  std::cerr << "!!! ProSHADE ERROR !!! Cannot read from the map file. The map file mode is not supported. Terminating..." << std::endl;
3866 
3867  if ( settings->htmlReport )
3868  {
3869  std::stringstream hlpSS;
3870  hlpSS << "<font color=\"red\">" << "Cannot read from the map file. The map mode is neither 0, nor 2. Other map modes are currently not supported." << "</font>";
3871  rvapi_set_text ( hlpSS.str().c_str(),
3872  "ProgressSection",
3873  settings->htmlReportLineProgress,
3874  1,
3875  1,
3876  1 );
3877  settings->htmlReportLineProgress += 1;
3878  rvapi_flush ( );
3879  }
3880 
3881  exit ( -1 );
3882  }
3883 
3884  //==================================== Read in map data
3885  // ... Find the stop positions (start is in orig variables) and the axis order
3886  int maxLim[3];
3887  int XYZOrder[3];
3888  int newU, newV, newW;
3889  int arrPos;
3890 
3891  for ( int iter = 0; iter < 3; iter++ )
3892  {
3893  maxLim[iter] = orig[iter] + dim[iter] - 1;
3894  XYZOrder[order[iter]-1] = iter;
3895  }
3896 
3897  // ... Solve the dimensions and sizes
3898  int fastDimSize = ( maxLim[0] - orig[0] + 1 );
3899  int midDimSize = ( maxLim[1] - orig[1] + 1 ) * fastDimSize;
3900  std::vector<float> section( midDimSize );
3901  int index;
3902  int iters[3];
3903 
3904  // ... Read in the map data
3905  for ( iters[2] = orig[2]; iters[2] <= maxLim[2]; iters[2]++ )
3906  {
3907  index = 0;
3908  CMap_io::ccp4_cmap_read_section( mapFile, &section[0] );
3909 
3910  if ( mapMode == 0 )
3911  {
3912  for ( int iter = ( midDimSize - 1 ); iter >= 0; iter-- )
3913  {
3914  section[iter] = static_cast<float> ( ( reinterpret_cast<unsigned char*> (&section[0]) )[iter] );
3915  }
3916  }
3917 
3918  for ( iters[1] = orig[1]; iters[1] <= maxLim[1]; iters[1]++ )
3919  {
3920  for ( iters[0] = orig[0]; iters[0] <= maxLim[0]; iters[0]++ )
3921  {
3922  newU = iters[XYZOrder[0]] - orig[XYZOrder[0]];
3923  newV = iters[XYZOrder[1]] - orig[XYZOrder[1]];
3924  newW = iters[XYZOrder[2]] - orig[XYZOrder[2]];
3925  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
3926  this->_densityMapMap[arrPos] = static_cast<float> ( section[ index++ ] );
3927  }
3928  }
3929  }
3930 
3931  //==================================== Get values for normalisation
3932  std::vector<double> vals;
3933  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
3934  {
3935  if ( this->_densityMapMap[iter] != 0.0 )
3936  {
3937  vals.emplace_back ( this->_densityMapMap[iter] );
3938  }
3939  }
3940  std::sort ( vals.begin(), vals.end() );
3941 
3942  *minDensPreNorm = vals.at(0);
3943  *maxDensPreNorm = vals.at(vals.size()-1);
3944 
3945  //==================================== Create results section
3946  if ( settings->htmlReport )
3947  {
3948  //==================================== Create section
3949  rvapi_add_section ( "ResultsSection",
3950  "Results",
3951  "body",
3952  settings->htmlReportLine,
3953  0,
3954  1,
3955  1,
3956  true );
3957  settings->htmlReportLine += 1;
3958 
3959  std::stringstream hlpSS;
3960  hlpSS << "<pre>" << "Min / Max density pre normalisation: ";
3961  int hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
3962  for ( int iter = 0; iter < hlpIt; iter++ )
3963  {
3964  hlpSS << ".";
3965  }
3966 
3967  std::stringstream hlpSS2;
3968  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *minDensPreNorm * 1000.0 ) / 1000.0;
3969  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
3970  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
3971  hlpSS << " " << hlpSS2.str() << " / ";
3972 
3973  hlpSS2.str( std::string ( ) );
3974  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maxDensPreNorm * 1000.0 ) / 1000.0;
3975  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
3976  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
3977  hlpSS << hlpSS2.str() << "</pre>";
3978 
3979  rvapi_set_text ( hlpSS.str().c_str(),
3980  "ResultsSection",
3981  0,
3982  1,
3983  1,
3984  1 );
3985 
3986  rvapi_flush ( );
3987  }
3988 
3989  //==================================== Find mean and standard deviation for later normalisation
3990  this->_mapMean = std::accumulate ( vals.begin(), vals.end(), 0.0 ) / static_cast<double> ( vals.size() );
3991  this->_mapSdev = std::sqrt ( static_cast<double> ( std::inner_product ( vals.begin(), vals.end(), vals.begin(), 0.0 ) ) / static_cast<double> ( vals.size() ) - this->_mapMean * this->_mapMean );
3992  vals.clear ( );
3993 
3994  //==================================== Check if the map is not absolutely de-centered
3995  int noPToCheckU = static_cast<unsigned int> ( this->_maxMapU / 8.0 );
3996  int noPToCheckV = static_cast<unsigned int> ( this->_maxMapV / 8.0 );
3997  int noPToCheckW = static_cast<unsigned int> ( this->_maxMapW / 8.0 );
3998 
3999  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
4000  {
4001  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
4002  {
4003  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
4004  {
4005  //======================== Initialisation
4006  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
4007 
4008  //======================== Check to which quadrant the value belongs to
4009  if ( ( ( uIt <= static_cast<int> ( this->_maxMapU/2 + noPToCheckU ) ) && ( uIt >= static_cast<int> ( this->_maxMapU/2 - noPToCheckU ) ) ) &&
4010  ( ( vIt <= static_cast<int> ( this->_maxMapV/2 + noPToCheckV ) ) && ( vIt >= static_cast<int> ( this->_maxMapV/2 - noPToCheckV ) ) ) &&
4011  ( ( wIt <= static_cast<int> ( this->_maxMapW/2 + noPToCheckW ) ) && ( wIt >= static_cast<int> ( this->_maxMapW/2 - noPToCheckW ) ) ) )
4012  {
4013  centralAvg += std::max ( this->_densityMapMap[arrPos], static_cast<float>(0.0) );
4014  centralCount += 1.0;
4015  }
4016  if ( ( ( uIt < noPToCheckU ) && ( vIt < noPToCheckV ) && ( wIt < noPToCheckW ) ) ||
4017  ( ( uIt < noPToCheckU ) && ( vIt < noPToCheckV ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
4018  ( ( uIt < noPToCheckU ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt < noPToCheckW ) ) ||
4019  ( ( uIt < noPToCheckU ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
4020  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt < noPToCheckV ) && ( wIt < noPToCheckW ) ) ||
4021  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt < noPToCheckV ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) ||
4022  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt < noPToCheckW ) ) ||
4023  ( ( uIt > static_cast<int> (this->_maxMapU-noPToCheckU) ) && ( vIt > static_cast<int> (this->_maxMapV-noPToCheckV) ) && ( wIt > static_cast<int> (this->_maxMapW-noPToCheckW) ) ) )
4024  {
4025  cornerAvg += std::max ( this->_densityMapMap[arrPos], static_cast<float>(0.0) );
4026  cornerCount += 1.0;
4027  }
4028  }
4029  }
4030  }
4031 
4032  cornerAvg /= cornerCount;
4033  centralAvg /= centralCount;
4034 
4035  //==================================== If density is in the corners
4036  if ( cornerAvg > centralAvg )
4037  {
4038  //================================ Initialise required variables
4039  float* hlpMap = nullptr;
4040  hlpMap = (float*) malloc ( (dim[0]*dim[1]*dim[2]) * sizeof ( float ) );
4041  if ( hlpMap == nullptr )
4042  {
4043  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
4044 
4045  if ( settings->htmlReport )
4046  {
4047  std::stringstream hlpSS;
4048  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
4049  rvapi_set_text ( hlpSS.str().c_str(),
4050  "ProgressSection",
4051  settings->htmlReportLineProgress,
4052  1,
4053  1,
4054  1 );
4055  settings->htmlReportLineProgress += 1;
4056  rvapi_flush ( );
4057  }
4058 
4059  exit ( -1 );
4060  }
4061  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( dim[0] * dim[1] * dim[2] ); iter++ )
4062  {
4063  hlpMap[iter] = this->_densityMapMap[iter];
4064  }
4065 
4066  //================================ Transform
4067  unsigned int hlpPos;
4068  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
4069  {
4070  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
4071  {
4072  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
4073  {
4074  //==================== If in lower half, add half; if in upper halp, subtract half
4075  if ( uIt < static_cast<int> (this->_maxMapU+1)/2 ) { newU = uIt + (this->_maxMapU+1)/2; } else { newU = uIt - (this->_maxMapU+1)/2; }
4076  if ( vIt < static_cast<int> (this->_maxMapV+1)/2 ) { newV = vIt + (this->_maxMapV+1)/2; } else { newV = vIt - (this->_maxMapV+1)/2; }
4077  if ( wIt < static_cast<int> (this->_maxMapW+1)/2 ) { newW = wIt + (this->_maxMapW+1)/2; } else { newW = wIt - (this->_maxMapW+1)/2; }
4078 
4079  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
4080  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
4081 
4082  //==================== Set the value into correct coords in the new map
4083  this->_densityMapMap[arrPos] = hlpMap[hlpPos];
4084  }
4085  }
4086  }
4087 
4088  //================================ Free memory
4089  free ( hlpMap );
4090  }
4091 
4092  if ( verbose > 3 )
4093  {
4094  std::cout << ">>>>> Density moved from corners to center, if applicable." << std::endl;
4095  }
4096  }
4097  else
4098  {
4099  std::cerr << "!!! ProSHADE ERROR !!! Non-orthogonal maps are not yet supported." << std::endl;
4100 
4101  if ( settings->htmlReport )
4102  {
4103  std::stringstream hlpSS;
4104  hlpSS << "<font color=\"red\">" << "Detected non-orthogonal map. Currently, only the P1 maps are supported." << "</font>";
4105  rvapi_set_text ( hlpSS.str().c_str(),
4106  "ProgressSection",
4107  settings->htmlReportLineProgress,
4108  1,
4109  1,
4110  1 );
4111  settings->htmlReportLineProgress += 1;
4112  rvapi_flush ( );
4113  }
4114 
4115  exit ( -1 );
4116  }
4117 
4118  if ( settings->htmlReport )
4119  {
4120  std::stringstream hlpSS;
4121  hlpSS << "<font color=\"green\">" << "Structure " << fileName << " read." << "</font>";
4122  rvapi_set_text ( hlpSS.str().c_str(),
4123  "ProgressSection",
4124  settings->htmlReportLineProgress,
4125  1,
4126  1,
4127  1 );
4128  settings->htmlReportLineProgress += 1;
4129  rvapi_flush ( );
4130  }
4131 
4132  //======================================== Free memory
4133  if ( cell != nullptr )
4134  {
4135  free ( cell );
4136  cell = nullptr;
4137  }
4138  if ( dim != nullptr )
4139  {
4140  free ( dim );
4141  dim = nullptr;
4142  }
4143  if ( order != nullptr )
4144  {
4145  free ( order );
4146  order = nullptr;
4147  }
4148  if ( orig != nullptr )
4149  {
4150  free ( orig );
4151  orig = nullptr;
4152  }
4153 
4154  //======================================== Close the file
4155  CMap_io::ccp4_cmap_close ( mapFile );
4156 
4157  //======================================== Determine sampling ranges
4158  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
4159  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
4160  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
4161 
4162  bool addXOne = false;
4163  bool addYOne = false;
4164  bool addZOne = false;
4165 
4166  //======================================== Save ranges and dims
4167  (*origRanges)[0] = this->_xRange;
4168  (*origRanges)[1] = this->_yRange;
4169  (*origRanges)[2] = this->_zRange;
4170 
4171  (*origDims)[0] = this->_maxMapU;
4172  (*origDims)[1] = this->_maxMapV;
4173  (*origDims)[2] = this->_maxMapW;
4174 
4175  //======================================== If extra cell space is given, apply
4176  this->_maxExtraCellularSpace = extraCS;
4177  if ( this->_maxExtraCellularSpace != 0.0 )
4178  {
4179  //==================================== Compute new stats
4180  int xDiff = static_cast<int> ( std::ceil ( ( this->_xRange + this->_maxExtraCellularSpace ) / this->_xSamplingRate ) - this->_maxMapU );
4181  int yDiff = static_cast<int> ( std::ceil ( ( this->_yRange + this->_maxExtraCellularSpace ) / this->_ySamplingRate ) - this->_maxMapV );
4182  int zDiff = static_cast<int> ( std::ceil ( ( this->_zRange + this->_maxExtraCellularSpace ) / this->_zSamplingRate ) - this->_maxMapW );
4183 
4184  if ( ( this->_xFrom >= 0 ) && ( ( this->_xFrom - xDiff ) < 0 ) ) { addXOne = true; }
4185  if ( ( this->_yFrom >= 0 ) && ( ( this->_yFrom - yDiff ) < 0 ) ) { addYOne = true; }
4186  if ( ( this->_zFrom >= 0 ) && ( ( this->_zFrom - zDiff ) < 0 ) ) { addZOne = true; }
4187 
4188  this->_xRange += xDiff * this->_xSamplingRate;
4189  this->_yRange += yDiff * this->_ySamplingRate;
4190  this->_zRange += zDiff * this->_zSamplingRate;
4191 
4192  if ( xDiff % 2 != 0 )
4193  {
4194  this->_xRange += this->_xSamplingRate;
4195  xDiff = static_cast<int> ( std::ceil ( this->_xRange / this->_xSamplingRate ) - ( this->_maxMapU + 1 ) );
4196  }
4197  if ( yDiff % 2 != 0 )
4198  {
4199  this->_yRange += this->_ySamplingRate;
4200  yDiff = static_cast<int> ( std::ceil ( this->_yRange / this->_ySamplingRate ) - ( this->_maxMapV + 1 ) );
4201  }
4202  if ( zDiff % 2 != 0 )
4203  {
4204  this->_zRange += this->_zSamplingRate;
4205  zDiff = static_cast<int> ( std::ceil ( this->_zRange / this->_zSamplingRate ) - ( this->_maxMapW + 1 ) );
4206  }
4207 
4208  xDiff /= 2;
4209  yDiff /= 2;
4210  zDiff /= 2;
4211 
4212  this->_xFrom -= xDiff;
4213  this->_yFrom -= yDiff;
4214  this->_zFrom -= zDiff;
4215 
4216  this->_xTo += xDiff;
4217  this->_yTo += yDiff;
4218  this->_zTo += zDiff;
4219 
4220  this->_maxMapU = this->_xTo - this->_xFrom;
4221  this->_maxMapV = this->_yTo - this->_yFrom;
4222  this->_maxMapW = this->_zTo - this->_zFrom;
4223 
4224  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
4225  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
4226  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
4227 
4228  //==================================== Move the map
4229  float *hlpMap = nullptr;
4230  hlpMap = (float*) malloc ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) * sizeof ( float ) );
4231  if ( hlpMap == nullptr )
4232  {
4233  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map moving data. Terminating... " << std::endl;
4234 
4235  if ( settings->htmlReport )
4236  {
4237  std::stringstream hlpSS;
4238  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
4239  rvapi_set_text ( hlpSS.str().c_str(),
4240  "ProgressSection",
4241  settings->htmlReportLineProgress,
4242  1,
4243  1,
4244  1 );
4245  settings->htmlReportLineProgress += 1;
4246  rvapi_flush ( );
4247  }
4248 
4249  exit ( -1 );
4250  }
4251  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
4252  {
4253  hlpMap[iter] = 0.0;
4254  }
4255 
4256  unsigned int newU, newV, newW, hlpPos, arrPos;
4257  for ( int uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
4258  {
4259  for ( int vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
4260  {
4261  for ( int wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
4262  {
4263  if ( ( uIt < xDiff ) || ( uIt > static_cast<int> ( this->_maxMapU - xDiff ) ) ||
4264  ( vIt < yDiff ) || ( vIt > static_cast<int> ( this->_maxMapV - yDiff ) ) ||
4265  ( wIt < zDiff ) || ( wIt > static_cast<int> ( this->_maxMapW - zDiff ) ) )
4266  {
4267  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
4268  hlpMap[hlpPos] = 0.0;
4269  }
4270  else
4271  {
4272  newU = (uIt - xDiff);
4273  newV = (vIt - yDiff);
4274  newW = (wIt - zDiff);
4275 
4276  hlpPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
4277  arrPos = newW + (this->_maxMapW + 1 - zDiff * 2) * ( newV + (this->_maxMapV + 1 - yDiff * 2) * newU );
4278 
4279  hlpMap[hlpPos] = this->_densityMapMap[arrPos];
4280  }
4281  }
4282  }
4283  }
4284 
4285  //==================================== Free memory
4286  if ( this->_densityMapMap != nullptr )
4287  {
4288  free ( this->_densityMapMap );
4289  this->_densityMapMap = nullptr;
4290  }
4291 
4292  //==================================== Copy
4293  this->_densityMapMap = (float*) malloc ( ((this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1)) * sizeof ( float ) );
4294  if ( this->_densityMapMap == nullptr )
4295  {
4296  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
4297 
4298  if ( settings->htmlReport )
4299  {
4300  std::stringstream hlpSS;
4301  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
4302  rvapi_set_text ( hlpSS.str().c_str(),
4303  "ProgressSection",
4304  settings->htmlReportLineProgress,
4305  1,
4306  1,
4307  1 );
4308  settings->htmlReportLineProgress += 1;
4309  rvapi_flush ( );
4310  }
4311 
4312  exit ( -1 );
4313  }
4314  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
4315  {
4316  this->_densityMapMap[iter] = hlpMap[iter];
4317  }
4318 
4319  //==================================== Free memory
4320  if ( hlpMap != nullptr )
4321  {
4322  free ( hlpMap );
4323  hlpMap = nullptr;
4324  }
4325 
4326  if ( settings->htmlReport )
4327  {
4328  std::stringstream hlpSS;
4329  hlpSS << "<font color=\"green\">" << "Extra cell space added as required." << "</font>";
4330  rvapi_set_text ( hlpSS.str().c_str(),
4331  "ProgressSection",
4332  settings->htmlReportLineProgress,
4333  1,
4334  1,
4335  1 );
4336  settings->htmlReportLineProgress += 1;
4337  rvapi_flush ( );
4338  }
4339  }
4340 
4341  //======================================== Local hlp variables
4342  int hlpU = ( this->_maxMapU + 1 );
4343  int hlpV = ( this->_maxMapV + 1 );
4344  int hlpW = ( this->_maxMapW + 1 );
4345 
4346  //======================================== Initialise local variables for Fourier and Inverse Fourier
4347  int uIt, vIt, wIt;
4348  unsigned int arrayPos = 0;
4349 
4350  this->_densityMapCor = new double [hlpU * hlpV * hlpW];
4351 
4352  //======================================== Load map data for Fourier
4353  std::vector<double> vals;
4354  std::vector<double> valsWZ;
4355 
4356  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (this->_maxMapU+1) * (this->_maxMapV+1) * (this->_maxMapW+1) ); iter++ )
4357  {
4358  if ( this->_densityMapMap[iter] == this->_densityMapMap[iter] )
4359  {
4360  //================================ Map value is NOT nan
4361  if ( this->_densityMapMap[iter] != 0.0 )
4362  {
4363  vals.emplace_back ( ( this->_densityMapMap[iter] - this->_mapMean ) / this->_mapSdev );
4364  }
4365  valsWZ.emplace_back ( ( this->_densityMapMap[iter] - this->_mapMean ) / this->_mapSdev );
4366 
4367  this->_densityMapCor[iter] = ( this->_densityMapMap[iter] - this->_mapMean ) / this->_mapSdev;
4368  }
4369  else
4370  {
4371  //================================ Map value is nan - this sometimes occurs for a couple of values, I have no clue as to why...
4372  this->_densityMapCor[iter] = 0.0;
4373  }
4374  }
4375  if ( verbose > 3 )
4376  {
4377  std::cout << ">>>>> Map normalised." << std::endl;
4378  }
4379 
4380  if ( settings->htmlReport )
4381  {
4382  std::stringstream hlpSS;
4383  hlpSS << "<font color=\"green\">" << "Map normalisation complete." << "</font>";
4384  rvapi_set_text ( hlpSS.str().c_str(),
4385  "ProgressSection",
4386  settings->htmlReportLineProgress,
4387  1,
4388  1,
4389  1 );
4390  settings->htmlReportLineProgress += 1;
4391  rvapi_flush ( );
4392  }
4393 
4394  //======================================== If not required, do not continue
4395  if ( !reboxAtAll )
4396  {
4397  vals.clear ( );
4398  return;
4399  }
4400 
4401  //======================================== Get post normalisation stats
4402  std::sort ( vals.begin(), vals.end() );
4403 
4404  *minDensPostNorm = vals.at(0);
4405  *maxDensPostNorm = vals.at(vals.size()-1);
4406 
4407  *postNormMean = std::accumulate ( vals.begin(), vals.end(), 0.0 ) / static_cast<double> ( vals.size() );
4408  *postNormSdev = std::sqrt ( static_cast<double> ( std::inner_product ( vals.begin(), vals.end(), vals.begin(), 0.0 ) ) / static_cast<double> ( vals.size() ) - *postNormMean * *postNormMean );
4409 
4410  *allDensityRMS = 0.0;
4411  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( valsWZ.size() ); iter++ )
4412  {
4413  *allDensityRMS += pow ( valsWZ.at(iter), 2.0 );
4414  }
4415  *allDensityRMS /= static_cast<double> ( valsWZ.size() - 1 );
4416  *allDensityRMS = sqrt ( *allDensityRMS );
4417 
4418  vals.clear ( );
4419  valsWZ.clear ( );
4420 
4421  //======================================== Print more to the results section
4422  if ( settings->htmlReport )
4423  {
4424  std::stringstream hlpSS;
4425  hlpSS << "<pre>" << "Mean (std. dev.) pre normalisation: ";
4426  int hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4427  for ( int iter = 0; iter < hlpIt; iter++ )
4428  {
4429  hlpSS << ".";
4430  }
4431 
4432  std::stringstream hlpSS2;
4433  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( this->_mapMean * 1000.0 ) / 1000.0;
4434  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4435  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4436  hlpSS << " " << hlpSS2.str() << " ( ";
4437 
4438  hlpSS2.str( std::string ( ) );
4439  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( this->_mapSdev * 1000.0 ) / 1000.0;
4440  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4441  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4442  hlpSS << hlpSS2.str() << " ) " << "</pre>";
4443 
4444  rvapi_set_text ( hlpSS.str().c_str(),
4445  "ResultsSection",
4446  1,
4447  1,
4448  1,
4449  1 );
4450 
4451  hlpSS.str( std::string ( "<pre>" ) );
4452  for ( int iter = 0; iter < 70; iter++ )
4453  {
4454  hlpSS << "=";
4455  }
4456  hlpSS << "</pre>";
4457  rvapi_set_text ( hlpSS.str().c_str(),
4458  "ResultsSection",
4459  2,
4460  1,
4461  1,
4462  1 );
4463 
4464  hlpSS.str( std::string ( ) );
4465  hlpSS << "<pre>" << "Min / Max density post normalisation: ";
4466  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4467  for ( int iter = 0; iter < hlpIt; iter++ )
4468  {
4469  hlpSS << ".";
4470  }
4471 
4472  hlpSS2.str( std::string ( ) );
4473  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *minDensPostNorm * 1000.0 ) / 1000.0;
4474  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4475  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4476  hlpSS << " " << hlpSS2.str() << " / ";
4477 
4478  hlpSS2.str( std::string ( ) );
4479  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maxDensPostNorm * 1000.0 ) / 1000.0;
4480  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4481  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4482  hlpSS << hlpSS2.str() << "</pre>";
4483 
4484  rvapi_set_text ( hlpSS.str().c_str(),
4485  "ResultsSection",
4486  3,
4487  1,
4488  1,
4489  1 );
4490 
4491  hlpSS.str( std::string ( ) );
4492  hlpSS << "<pre>" << "Mean (std. dev.) post normalisation: ";
4493  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4494  for ( int iter = 0; iter < hlpIt; iter++ )
4495  {
4496  hlpSS << ".";
4497  }
4498 
4499  hlpSS2.str( std::string ( ) );
4500  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *postNormMean * 1000.0 ) / 1000.0;
4501  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4502  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4503  hlpSS << " " << hlpSS2.str() << " ( ";
4504 
4505  hlpSS2.str( std::string ( ) );
4506  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *postNormSdev * 1000.0 ) / 1000.0;
4507  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4508  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4509  hlpSS << hlpSS2.str() << " ) " << "</pre>";
4510 
4511  rvapi_set_text ( hlpSS.str().c_str(),
4512  "ResultsSection",
4513  4,
4514  1,
4515  1,
4516  1 );
4517 
4518  hlpSS.str( std::string ( "<pre>" ) );
4519  for ( int iter = 0; iter < 70; iter++ )
4520  {
4521  hlpSS << "=";
4522  }
4523  hlpSS << "</pre>";
4524  rvapi_set_text ( hlpSS.str().c_str(),
4525  "ResultsSection",
4526  5,
4527  1,
4528  1,
4529  1 );
4530 
4531  rvapi_flush ( );
4532  }
4533 
4534  //======================================== Map cleaning
4535  this->_fromPDB = false;
4536  if ( !this->_fromPDB )
4537  {
4538  //==================================== Save original map to restore for each cycle
4539  double *tmpMp = new double[hlpU * hlpV * hlpW];
4540  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
4541  {
4542  tmpMp[iter] = this->_densityMapCor[iter];
4543  }
4544 
4545  bool notTooManyIslads = true;
4546  double blFr = 150.0;
4547 
4548  while ( notTooManyIslads )
4549  {
4550  //================================ Do not change user values
4551  blFr += 50.0;
4552  if ( maskBlurFactorGiven )
4553  {
4554  blFr = maskBlurFactor;
4555  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
4556  this->removeIslands ( hlpU, hlpV, hlpW, verbose, true );
4557  break;
4558  }
4559 
4560  //================================ Compute mask and apply it
4561  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
4562 
4563  //================================ Detect islands
4564  if ( verbose > 3 )
4565  {
4566  std::cout << ">>>>>>>> Island detection started." << std::endl;
4567  }
4568 
4569  notTooManyIslads = this->removeIslands ( hlpU, hlpV, hlpW, verbose, false );
4570 
4571  if ( maskBlurFactorGiven )
4572  {
4573  break;
4574  }
4575 
4576  if ( verbose > 3 )
4577  {
4578  std::cout << ">>>>> Map masked with factor of " << blFr << " and small islands were then removed.";
4579  }
4580  if ( notTooManyIslads )
4581  {
4582  if ( verbose > 3 )
4583  {
4584  std::cout << " However, too many islands remained. Trying higher blurring factor." << std::endl;
4585  }
4586 
4587  if ( blFr <= 500.0 )
4588  {
4589  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
4590  {
4591  this->_densityMapCor[iter] = tmpMp[iter];
4592  }
4593  }
4594  }
4595  else
4596  {
4597  if ( verbose > 3 )
4598  {
4599  std::cout << std::endl;
4600  }
4601  }
4602 
4603 
4604  if ( blFr > 500.0 )
4605  {
4606  std::cout << "!!! ProSHADE WARNING !!! Even blurring factor of 500 did not remove islands. Will not proceed with what we have, but be warned that either the masking is bugged or yout map has high levels of noise. You can consider using the -y ( or --no_clear ) options to avoid this message and the extra time for testing different blurring factors for this map." << std::endl;
4607 
4608  if ( settings->htmlReport )
4609  {
4610  std::stringstream hlpSS;
4611  hlpSS << "<font color=\"orange\">" << "Even blurring factor of 500 did not remove islands. Will not proceed with what we have, but be warned that either the masking is bugged or yout map has high levels of noise. You can consider using the -y ( or --no_clear ) options to avoid this message and the extra time for testing different blurring factors for this map." << "</font>";
4612  rvapi_set_text ( hlpSS.str().c_str(),
4613  "ProgressSection",
4614  settings->htmlReportLineProgress,
4615  1,
4616  1,
4617  1 );
4618  settings->htmlReportLineProgress += 1;
4619  rvapi_flush ( );
4620  }
4621 
4622  break;
4623  }
4624  }
4625  delete[] tmpMp;
4626  }
4627 
4628  if ( verbose > 2 )
4629  {
4630  std::cout << ">> Map masked." << std::endl;
4631  }
4632 
4633  if ( settings->htmlReport )
4634  {
4635  std::stringstream hlpSS;
4636  hlpSS << "<font color=\"green\">" << "Map masking complete." << "</font>";
4637  rvapi_set_text ( hlpSS.str().c_str(),
4638  "ProgressSection",
4639  settings->htmlReportLineProgress,
4640  1,
4641  1,
4642  1 );
4643  settings->htmlReportLineProgress += 1;
4644  rvapi_flush ( );
4645  }
4646 
4647  //======================================== Free unnecessary memory
4648  if ( this->_densityMapMap != nullptr )
4649  {
4650  delete this->_densityMapMap;
4651  this->_densityMapMap = nullptr;
4652  }
4653 
4654  //======================================== Mask stats
4655  vals.clear ( );
4656 
4657  for ( uIt = 0; uIt < hlpU; uIt++ )
4658  {
4659  for ( vIt = 0; vIt < hlpV; vIt++ )
4660  {
4661  for ( wIt = 0; wIt < hlpW; wIt++ )
4662  {
4663  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
4664  if ( this->_densityMapCor[arrayPos] != 0.0 ) { vals.emplace_back ( this->_densityMapCor[arrayPos] ); }
4665  }
4666  }
4667  }
4668 
4669  *maskVolume = static_cast<double> ( vals.size() );
4670  *totalVolume = hlpU * hlpV * hlpW;
4671 
4672  std::sort ( vals.begin(), vals.end() );
4673 
4674  *maskMin = vals.at(0);
4675  *maskMax = vals.at(vals.size()-1);
4676 
4677  //======================================== Find mean and standard deviation for later normalisation
4678  *maskMean = std::accumulate ( vals.begin(), vals.end(), 0.0 ) / static_cast<double> ( vals.size() );
4679  *maskSdev = std::sqrt ( static_cast<double> ( std::inner_product ( vals.begin(), vals.end(), vals.begin(), 0.0 ) ) / static_cast<double> ( vals.size() ) - *maskMean * *maskMean );
4680 
4681  *maskDensityRMS = 0.0;
4682  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( vals.size() ); iter++ )
4683  {
4684  *maskDensityRMS += pow ( vals.at(iter), 2.0 );
4685  }
4686  *maskDensityRMS /= static_cast<double> ( vals.size() - 1 );
4687  *maskDensityRMS = sqrt ( *maskDensityRMS );
4688 
4689  vals.clear ( );
4690 
4691  //======================================== Print after masking results
4692  if ( settings->htmlReport )
4693  {
4694  std::stringstream hlpSS;
4695  hlpSS << "<pre>" << "Min / Max density after masking: ";
4696  int hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4697  for ( int iter = 0; iter < hlpIt; iter++ )
4698  {
4699  hlpSS << ".";
4700  }
4701 
4702  std::stringstream hlpSS2;
4703  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maskMin * 1000.0 ) / 1000.0;
4704  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4705  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4706  hlpSS << " " << hlpSS2.str() << " / ";
4707 
4708  hlpSS2.str( std::string ( ) );
4709  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maskMax * 1000.0 ) / 1000.0;
4710  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4711  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4712  hlpSS << hlpSS2.str() << "</pre>";
4713 
4714  rvapi_set_text ( hlpSS.str().c_str(),
4715  "ResultsSection",
4716  6,
4717  1,
4718  1,
4719  1 );
4720 
4721  hlpSS.str( std::string ( ) );
4722  hlpSS << "<pre>" << "Mean (std. dev.) within mask: ";
4723  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4724  for ( int iter = 0; iter < hlpIt; iter++ )
4725  {
4726  hlpSS << ".";
4727  }
4728 
4729  hlpSS2.str( std::string ( ) );
4730  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maskMean * 1000.0 ) / 1000.0;
4731  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4732  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4733  hlpSS << " " << hlpSS2.str() << " ( ";
4734 
4735  hlpSS2.str( std::string ( ) );
4736  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maskSdev * 1000.0 ) / 1000.0;
4737  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4738  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4739  hlpSS << hlpSS2.str() << " ) " << "</pre>";
4740 
4741  rvapi_set_text ( hlpSS.str().c_str(),
4742  "ResultsSection",
4743  7,
4744  1,
4745  1,
4746  1 );
4747 
4748  hlpSS.str( std::string ( "<pre>" ) );
4749  for ( int iter = 0; iter < 70; iter++ )
4750  {
4751  hlpSS << "=";
4752  }
4753  hlpSS << "</pre>";
4754  rvapi_set_text ( hlpSS.str().c_str(),
4755  "ResultsSection",
4756  8,
4757  1,
4758  1,
4759  1 );
4760 
4761  hlpSS.str( std::string ( ) );
4762  hlpSS << "<pre>" << "Total structure volume: ";
4763  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4764  for ( int iter = 0; iter < hlpIt; iter++ )
4765  {
4766  hlpSS << ".";
4767  }
4768 
4769  hlpSS2.str( std::string ( ) );
4770  hlpSS2 << std::showpos << std::setprecision ( 10 ) << *totalVolume * 1000.0 / 1000.0;
4771  if ( hlpSS2.str().length() != 15 ) { int hlp = 15 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4772  if ( hlpSS2.str().length() > 15 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4773  hlpSS << " " << hlpSS2.str() << " A^3 " << "</pre>";
4774 
4775  rvapi_set_text ( hlpSS.str().c_str(),
4776  "ResultsSection",
4777  9,
4778  1,
4779  1,
4780  1 );
4781 
4782  hlpSS.str( std::string ( ) );
4783  hlpSS << "<pre>" << "Total mask volume: ";
4784  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4785  for ( int iter = 0; iter < hlpIt; iter++ )
4786  {
4787  hlpSS << ".";
4788  }
4789 
4790  hlpSS2.str( std::string ( ) );
4791  hlpSS2 << std::showpos << std::setprecision ( 10 ) << *maskVolume * 1000.0 / 1000.0;
4792  if ( hlpSS2.str().length() != 15 ) { int hlp = 15 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4793  if ( hlpSS2.str().length() > 15 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4794  hlpSS << " " << hlpSS2.str() << " A^3 " << "</pre>";
4795 
4796  rvapi_set_text ( hlpSS.str().c_str(),
4797  "ResultsSection",
4798  10,
4799  1,
4800  1,
4801  1 );
4802 
4803  hlpSS.str( std::string ( "<pre>" ) );
4804  for ( int iter = 0; iter < 70; iter++ )
4805  {
4806  hlpSS << "=";
4807  }
4808  hlpSS << "</pre>";
4809  rvapi_set_text ( hlpSS.str().c_str(),
4810  "ResultsSection",
4811  11,
4812  1,
4813  1,
4814  1 );
4815 
4816  hlpSS.str( std::string ( ) );
4817  hlpSS << "<pre>" << "RMS of complete map: ";
4818  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4819  for ( int iter = 0; iter < hlpIt; iter++ )
4820  {
4821  hlpSS << ".";
4822  }
4823 
4824  hlpSS2.str( std::string ( ) );
4825  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *allDensityRMS * 1000.0 ) / 1000.0;
4826  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4827  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4828  hlpSS << " " << hlpSS2.str() << " " << "</pre>";
4829 
4830  rvapi_set_text ( hlpSS.str().c_str(),
4831  "ResultsSection",
4832  12,
4833  1,
4834  1,
4835  1 );
4836 
4837  hlpSS.str( std::string ( ) );
4838  hlpSS << "<pre>" << "RMS of masked map: ";
4839  hlpIt = static_cast<int> ( 70 - hlpSS.str().length() );
4840  for ( int iter = 0; iter < hlpIt; iter++ )
4841  {
4842  hlpSS << ".";
4843  }
4844 
4845  hlpSS2.str( std::string ( ) );
4846  hlpSS2 << std::showpos << ProSHADE_internal_misc::roundDouble ( *maskDensityRMS * 1000.0 ) / 1000.0;
4847  if ( hlpSS2.str().length() != 6 ) { int hlp = 6 - hlpSS2.str().length(); for ( int i = 0; i < hlp; i++ ) { hlpSS2 << " "; } }
4848  if ( hlpSS2.str().length() > 6 ) { hlpSS2.str( hlpSS2.str().substr( 0, 6 ) ); }
4849  hlpSS << " " << hlpSS2.str() << " " << "</pre>";
4850 
4851  rvapi_set_text ( hlpSS.str().c_str(),
4852  "ResultsSection",
4853  13,
4854  1,
4855  1,
4856  1 );
4857 
4858  rvapi_flush ( );
4859  }
4860 
4861  //======================================== Get real dimensions, instead of unit grid
4862  double xReal = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
4863  double yReal = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
4864  double zReal = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
4865 
4866  //======================================== Find the COM
4867  std::array<double,3> meanVals;
4868  meanVals[0] = 0.0;
4869  meanVals[1] = 0.0;
4870  meanVals[2] = 0.0;
4871 
4872  double totDens = 0.0;
4873 
4874  for ( uIt = 0; uIt < hlpU; uIt++ )
4875  {
4876  for ( vIt = 0; vIt < hlpV; vIt++ )
4877  {
4878  for ( wIt = 0; wIt < hlpW; wIt++ )
4879  {
4880  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
4881 
4882  meanVals[0] += this->_densityMapCor[arrayPos] * uIt;
4883  meanVals[1] += this->_densityMapCor[arrayPos] * vIt;
4884  meanVals[2] += this->_densityMapCor[arrayPos] * wIt;
4885 
4886  totDens += this->_densityMapCor[arrayPos];
4887  }
4888  }
4889  }
4890 
4891  meanVals[0] /= totDens;
4892  meanVals[1] /= totDens;
4893  meanVals[2] /= totDens;
4894 
4895  //======================================== Re-index the map with COM in the centre
4896  this->_xCorrErr = meanVals[0] - static_cast<double> ( this->_maxMapU + 1 )/2.0;
4897  this->_yCorrErr = meanVals[1] - static_cast<double> ( this->_maxMapV + 1 )/2.0;
4898  this->_zCorrErr = meanVals[2] - static_cast<double> ( this->_maxMapW + 1 )/2.0;
4899 
4900  this->_xCorrection = std::ceil ( this->_xCorrErr );
4901  this->_yCorrection = std::ceil ( this->_yCorrErr );
4902  this->_zCorrection = std::ceil ( this->_zCorrErr );
4903 
4904  //======================================== Initialise internal values
4905  this->_densityMapCorCoords = new std::array<double,3> [hlpU * hlpV * hlpW];
4906  int newU, newV, newW, coordPos;
4907 
4908  //======================================== Save the final coords
4909  for ( uIt = 0; uIt < hlpU; uIt++ )
4910  {
4911  for ( vIt = 0; vIt < hlpV; vIt++ )
4912  {
4913  for ( wIt = 0; wIt < hlpW; wIt++ )
4914  {
4915  newU = static_cast<int> ( uIt ) - static_cast<int> ( this->_xCorrection );
4916  newV = static_cast<int> ( vIt ) - static_cast<int> ( this->_yCorrection );
4917  newW = static_cast<int> ( wIt ) - static_cast<int> ( this->_zCorrection );
4918 
4919  if ( newU < 0 ) { newU += hlpU; } if ( newU >= static_cast<int> ( hlpU ) ) { newU -= hlpU; }
4920  if ( newV < 0 ) { newV += hlpV; } if ( newV >= static_cast<int> ( hlpV ) ) { newV -= hlpV; }
4921  if ( newW < 0 ) { newW += hlpW; } if ( newW >= static_cast<int> ( hlpW ) ) { newW -= hlpW; }
4922 
4923  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
4924  coordPos = newW + hlpW * ( newV + hlpV * newU );
4925 
4926  this->_densityMapCorCoords[coordPos][0] = ( static_cast<double> ( newU ) - static_cast<double> ( hlpU ) / 2.0 ) * xReal;
4927  this->_densityMapCorCoords[coordPos][1] = ( static_cast<double> ( newV ) - static_cast<double> ( hlpV ) / 2.0 ) * yReal;
4928  this->_densityMapCorCoords[coordPos][2] = ( static_cast<double> ( newW ) - static_cast<double> ( hlpW ) / 2.0 ) * zReal;
4929  }
4930  }
4931  }
4932  if ( verbose > 2 )
4933  {
4934  std::cout << ">> Map centered." << std::endl;
4935  }
4936 
4937  if ( settings->htmlReport )
4938  {
4939  std::stringstream hlpSS;
4940  hlpSS << "<font color=\"green\">" << "Map centered." << "</font>";
4941  rvapi_set_text ( hlpSS.str().c_str(),
4942  "ProgressSection",
4943  settings->htmlReportLineProgress,
4944  1,
4945  1,
4946  1 );
4947  settings->htmlReportLineProgress += 1;
4948  rvapi_flush ( );
4949  }
4950 
4951  //======================================== Determine the real size of the shape
4952  double maxX = 0.0;
4953  double minX = 0.0;
4954  double maxY = 0.0;
4955  double minY = 0.0;
4956  double maxZ = 0.0;
4957  double minZ = 0.0;
4958  double maxXTot = 0.0;
4959  double minXTot = 0.0;
4960  double maxYTot = 0.0;
4961  double minYTot = 0.0;
4962  double maxZTot = 0.0;
4963  double minZTot = 0.0;
4964 
4965  coordPos = 0;
4966  for ( uIt = 0; uIt < hlpU; uIt++ )
4967  {
4968  for ( vIt = 0; vIt < hlpV; vIt++ )
4969  {
4970  for ( wIt = 0; wIt < hlpW; wIt++ )
4971  {
4972  coordPos = wIt + hlpW * ( vIt + hlpV * uIt );
4973 
4974  if ( this->_densityMapCor[coordPos] > 0.0 )
4975  {
4976  maxX = std::max ( maxX, this->_densityMapCorCoords[coordPos][0] );
4977  minX = std::min ( minX, this->_densityMapCorCoords[coordPos][0] );
4978  maxY = std::max ( maxY, this->_densityMapCorCoords[coordPos][1] );
4979  minY = std::min ( minY, this->_densityMapCorCoords[coordPos][1] );
4980  maxZ = std::max ( maxZ, this->_densityMapCorCoords[coordPos][2] );
4981  minZ = std::min ( minZ, this->_densityMapCorCoords[coordPos][2] );
4982  }
4983  maxXTot = std::max ( maxXTot, this->_densityMapCorCoords[coordPos][0] );
4984  minXTot = std::min ( minXTot, this->_densityMapCorCoords[coordPos][0] );
4985  maxYTot = std::max ( maxYTot, this->_densityMapCorCoords[coordPos][1] );
4986  minYTot = std::min ( minYTot, this->_densityMapCorCoords[coordPos][1] );
4987  maxZTot = std::max ( maxZTot, this->_densityMapCorCoords[coordPos][2] );
4988  minZTot = std::min ( minZTot, this->_densityMapCorCoords[coordPos][2] );
4989  }
4990  }
4991  }
4992 
4993  //======================================== Calculate the grid for only the shape
4994  int newUStart = std::floor ( ( ( minX - minXTot ) / ( maxXTot - minXTot ) ) * ( this->_maxMapU + 1 ) );
4995  int newUEnd = std::ceil ( ( ( maxX - minXTot ) / ( maxXTot - minXTot ) ) * ( this->_maxMapU + 1 ) );
4996  int newVStart = std::floor ( ( ( minY - minYTot ) / ( maxYTot - minYTot ) ) * ( this->_maxMapV + 1 ) );
4997  int newVEnd = std::ceil ( ( ( maxY - minYTot ) / ( maxYTot - minYTot ) ) * ( this->_maxMapV + 1 ) );
4998  int newWStart = std::floor ( ( ( minZ - minZTot ) / ( maxZTot - minZTot ) ) * ( this->_maxMapW + 1 ) );
4999  int newWEnd = std::ceil ( ( ( maxZ - minZTot ) / ( maxZTot - minZTot ) ) * ( this->_maxMapW + 1 ) );
5000 
5001  //======================================== Make cube. If you want rectangle (more efficient), remove the following 6 lines, but beware, the map ordering will be YXZ...
5002  if ( useCubicMaps )
5003  {
5004  newUStart = std::min( newUStart, std::min( newVStart, newWStart ) );
5005  newVStart = std::min( newUStart, std::min( newVStart, newWStart ) );
5006  newWStart = std::min( newUStart, std::min( newVStart, newWStart ) );
5007  newUEnd = std::max( newUEnd , std::max( newVEnd , newWEnd ) );
5008  newVEnd = std::max( newUEnd , std::max( newVEnd , newWEnd ) );
5009  newWEnd = std::max( newUEnd , std::max( newVEnd , newWEnd ) );
5010  }
5011 
5012  //======================================== Move map
5013  int newXDim = newUEnd - newUStart + 1;
5014  int newYDim = newVEnd - newVStart + 1;
5015  int newZDim = newWEnd - newWStart + 1;
5016 
5017  if ( ( this->_xFrom < 0 ) && ( ( this->_xFrom + newUStart ) >= 0 ) ) { newXDim += 1; }
5018  if ( ( this->_yFrom < 0 ) && ( ( this->_yFrom + newVStart ) >= 0 ) ) { newYDim += 1; }
5019  if ( ( this->_zFrom < 0 ) && ( ( this->_zFrom + newWStart ) >= 0 ) ) { newZDim += 1; }
5020 
5021  double *hlpMap = nullptr;
5022  hlpMap = (double*) malloc ( newXDim * newYDim * newZDim * sizeof ( double ) );
5023  if ( hlpMap == nullptr )
5024  {
5025  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map moving data. Terminating... " << std::endl;
5026 
5027  if ( settings->htmlReport )
5028  {
5029  std::stringstream hlpSS;
5030  hlpSS << "<font color=\"red\">" << "Cannot allocate memory for map data. Could you have run out of memory?" << "</font>";
5031  rvapi_set_text ( hlpSS.str().c_str(),
5032  "ProgressSection",
5033  settings->htmlReportLineProgress,
5034  1,
5035  1,
5036  1 );
5037  settings->htmlReportLineProgress += 1;
5038  rvapi_flush ( );
5039  }
5040 
5041  exit ( -1 );
5042  }
5043 
5044  int arrPos, hlpPos;
5045  for ( uIt = this->_xFrom; uIt <= this->_xTo; uIt++ )
5046  {
5047  for ( vIt = this->_yFrom; vIt <= this->_yTo; vIt++ )
5048  {
5049  for ( wIt = this->_zFrom; wIt <= this->_zTo; wIt++ )
5050  {
5051  if ( ( uIt < (this->_xFrom+newUStart) ) || ( uIt > (this->_xFrom+newUEnd) ) ||
5052  ( vIt < (this->_yFrom+newVStart) ) || ( vIt > (this->_yFrom+newVEnd) ) ||
5053  ( wIt < (this->_zFrom+newWStart) ) || ( wIt > (this->_zFrom+newWEnd) ) )
5054  {
5055  continue;
5056  }
5057 
5058  newU = uIt - this->_xFrom;
5059  newV = vIt - this->_yFrom;
5060  newW = wIt - this->_zFrom;
5061  arrPos = newW + (this->_maxMapW + 1) * ( newV + (this->_maxMapV + 1) * newU );
5062 
5063  newU = newU - newUStart;
5064  newV = newV - newVStart;
5065  newW = newW - newWStart;
5066  hlpPos = newW + newZDim * ( newV + newYDim * newU );
5067 
5068  hlpMap[hlpPos] = this->_densityMapCor[arrPos];
5069  }
5070  }
5071  }
5072 
5073  //======================================== Change the settings
5074  if ( addXOne ) { this->_xFrom -= 1; }
5075  if ( addYOne ) { this->_yFrom -= 1; }
5076  if ( addZOne ) { this->_zFrom -= 1; }
5077 
5078  this->_xFrom += newUStart;
5079  this->_yFrom += newVStart;
5080  this->_zFrom += newWStart;
5081 
5082  this->_xTo -= this->_maxMapU - newUEnd;
5083  this->_yTo -= this->_maxMapV - newVEnd;
5084  this->_zTo -= this->_maxMapW - newWEnd;
5085 
5086  this->_maxMapU = newXDim - 1;
5087  this->_maxMapV = newYDim - 1;
5088  this->_maxMapW = newZDim - 1;
5089 
5090  if ( ( this->_xFrom > 0 ) && ( this->_xTo > 0 ) ) { this->_xTo += 1; }
5091  if ( ( this->_yFrom > 0 ) && ( this->_yTo > 0 ) ) { this->_yTo += 1; }
5092  if ( ( this->_zFrom > 0 ) && ( this->_zTo > 0 ) ) { this->_zTo += 1; }
5093 
5094  this->_xRange = this->_xSamplingRate * ( this->_maxMapU + 1 );
5095  this->_yRange = this->_ySamplingRate * ( this->_maxMapV + 1 );
5096  this->_zRange = this->_zSamplingRate * ( this->_maxMapW + 1 );
5097 
5098  //======================================== Copy tmp to holder
5099  delete[] this->_densityMapCor;
5100  this->_densityMapCor = nullptr;
5101  this->_densityMapCor = new double [newXDim * newYDim * newZDim];
5102 
5103  for ( int iter = 0; iter < (newXDim * newYDim * newZDim); iter++ )
5104  {
5105  this->_densityMapCor[iter] = hlpMap[iter];
5106  }
5107 
5108  if ( hlpMap != nullptr )
5109  {
5110  free ( hlpMap );
5111  hlpMap = nullptr;
5112  }
5113 
5114  if ( verbose > 2 )
5115  {
5116  std::cout << ">> Map resized." << std::endl;
5117  }
5118 
5119  if ( settings->htmlReport )
5120  {
5121  std::stringstream hlpSS;
5122  hlpSS << "<font color=\"green\">" << "Map resized." << "</font>";
5123  rvapi_set_text ( hlpSS.str().c_str(),
5124  "ProgressSection",
5125  settings->htmlReportLineProgress,
5126  1,
5127  1,
5128  1 );
5129  settings->htmlReportLineProgress += 1;
5130  rvapi_flush ( );
5131  }
5132 
5133  //======================================== Done
5134 
5135 }
5136 
5149  double bFac,
5150  ProSHADE::ProSHADE_settings* settings )
5151 {
5152  //======================================== Sanity check
5153  if ( !this->_densityMapComputed )
5154  {
5155  std::cerr << "!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName << " !!! Attempted to remove phase information from map before computing the map. Call the getDensityMapFromPDB function BEFORE the removePhaseFromMap function." << std::endl;
5156 
5157  if ( settings->htmlReport )
5158  {
5159  std::stringstream hlpSS;
5160  hlpSS << "<font color=\"red\">" << "Attempted to remove phase information from map before computing the map. Call the getDensityMapFromPDB function BEFORE the removePhaseFromMap function. This looks like an internal bug - please report this case." << "</font>";
5161  rvapi_set_text ( hlpSS.str().c_str(),
5162  "ProgressSection",
5163  settings->htmlReportLineProgress,
5164  1,
5165  1,
5166  1 );
5167  settings->htmlReportLineProgress += 1;
5168  rvapi_flush ( );
5169  }
5170 
5171  exit ( -1 );
5172  }
5173 
5174  //======================================== Initialise internal values
5175  this->_fourierCoeffPower = alpha;
5176  this->_bFactorChange = bFac;
5177 
5178  //======================================== Initialise local variables for Fourier and Inverse Fourier
5179  fftw_complex *tmpOut;
5180  fftw_complex *tmpIn;
5181  fftw_plan p;
5182  fftw_plan pInv;
5183  int uIt, vIt, wIt;
5184  double real, imag;
5185  int hlpU = ( this->_maxMapU + 1 );
5186  int hlpV = ( this->_maxMapV + 1 );
5187  int hlpW = ( this->_maxMapW + 1 );
5188 
5189  this->_densityMapCor = new double [(this->_maxMapU+2) * (this->_maxMapV+2) * (this->_maxMapW+2)];
5190  tmpIn = new fftw_complex[hlpU * hlpV * hlpW];
5191  tmpOut = new fftw_complex[hlpU * hlpV * hlpW];
5192 
5193  //======================================== Create plans (FFTW_MEASURE would change the arrays)
5194  p = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpIn, tmpOut, FFTW_FORWARD, FFTW_ESTIMATE );
5195  pInv = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpOut, tmpIn, FFTW_BACKWARD, FFTW_ESTIMATE );
5196 
5197  //======================================== Load map data for Fourier
5198  unsigned int noMapPoints = 0;
5199 
5200  for ( uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
5201  {
5202  for ( vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
5203  {
5204  for ( wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
5205  {
5206  //============================ Initialisation
5207  noMapPoints = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
5208 
5209  if ( this->_densityMapMap[noMapPoints] == this->_densityMapMap[noMapPoints] )
5210  {
5211  tmpIn[noMapPoints][0] = this->_densityMapMap[noMapPoints];
5212  tmpIn[noMapPoints][1] = 0.0;
5213  }
5214  else
5215  {
5216  tmpIn[noMapPoints][0] = 0.0;
5217  tmpIn[noMapPoints][1] = 0.0;
5218  }
5219  }
5220  }
5221  }
5222 
5223  //======================================== Calculate Fourier
5224  fftw_execute ( p );
5225 
5226  //======================================== Remove phase information
5227  unsigned int arrayPos = 0;
5228  int h, k, l;
5229  double mag, S;
5230  double normFactor = (hlpU * hlpV * hlpW);
5231  for ( uIt = 0; uIt < hlpU; uIt++ )
5232  {
5233  for ( vIt = 0; vIt < hlpV; vIt++ )
5234  {
5235  for ( wIt = 0; wIt < hlpW; wIt++ )
5236  {
5237  //============================ Var init
5238  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5239  real = tmpOut[arrayPos][0];
5240  imag = tmpOut[arrayPos][1];
5241 
5242  //============================ Change the B-factors, if required
5243  if ( uIt > (hlpU / 2) ) { h = uIt - hlpU; } else { h = uIt; }
5244  if ( vIt > (hlpV / 2) ) { k = vIt - hlpV; } else { k = vIt; }
5245  if ( wIt > (hlpW / 2) ) { l = wIt - hlpW; } else { l = wIt; }
5246 
5247  S = pow( static_cast<double> ( h ) / this->_xRange, 2.0 ) + pow( static_cast<double> ( k ) / this->_yRange, 2.0 ) + pow( static_cast<double> ( l ) / this->_zRange, 2.0 );
5248  mag = std::exp ( - ( ( this->_bFactorChange * S ) / 4.0 ) );
5249 
5250  //============================ Get magnitude and phase
5251  mag *= sqrt ( (real*real) + (imag*imag) );
5252 
5253  //============================ Magnitude power alpha
5254  mag = pow ( mag, this->_fourierCoeffPower );
5255 
5256  //============================ Phase removal
5257  tmpOut[arrayPos][0] = mag;
5258  tmpOut[arrayPos][1] = 0.0;
5259 
5260  //============================ Normalize
5261  tmpOut[arrayPos][0] /= normFactor;
5262  }
5263  }
5264  }
5265 
5266  //======================================== Run backward Fourier
5267  fftw_execute ( pInv );
5268 
5269  //======================================== Free allocated memory
5270  fftw_destroy_plan ( p );
5271  fftw_destroy_plan ( pInv );
5272 
5273  //======================================== Initialise internal values
5274  this->_densityMapCorCoords = new std::array<double,3> [(this->_maxMapU+2) * (this->_maxMapV+2) * (this->_maxMapW+2)];
5275 
5276  //======================================== Re-order (i.e. centralise) the Patterson
5277  int newU;
5278  int newV;
5279  int newW;
5280  int cenPosU;
5281  int cenPosV;
5282  int cenPosW;
5283  int nonTranslatedIter = 0;
5284  int coordPos;
5285 
5286  for ( uIt = 0; uIt < static_cast<int> (this->_maxMapU + 2); uIt++ )
5287  {
5288  for ( vIt = 0; vIt < static_cast<int> (this->_maxMapV + 2); vIt++ )
5289  {
5290  for ( wIt = 0; wIt < static_cast<int> (this->_maxMapW + 2); wIt++ )
5291  {
5292  if ( ( uIt == hlpU ) || ( vIt == hlpV ) || ( wIt == hlpW ) ) // Deal with the -x to +x-1 unsymmetric results problem by creating +x and copying values from -x (this is only possible when phases are removed as +x and -x must then by identical by symmetry)
5293  {
5294  newU = uIt; if ( uIt == hlpU ) { newU = 0; }
5295  newV = vIt; if ( vIt == hlpV ) { newV = 0; }
5296  newW = wIt; if ( wIt == hlpW ) { newW = 0; }
5297 
5298  cenPosU = newU + (hlpU / 2); if ( cenPosU >= hlpU ) { cenPosU -= hlpU; }
5299  cenPosV = newV + (hlpV / 2); if ( cenPosV >= hlpV ) { cenPosV -= hlpV; }
5300  cenPosW = newW + (hlpW / 2); if ( cenPosW >= hlpW ) { cenPosW -= hlpW; }
5301 
5302  arrayPos = cenPosW + hlpW * ( cenPosV + hlpV * cenPosU );
5303 
5304  this->_densityMapCor[nonTranslatedIter] = tmpIn[arrayPos][0];
5305  this->_densityMapCorCoords[nonTranslatedIter][0] = uIt - hlpU / 2;
5306  this->_densityMapCorCoords[nonTranslatedIter][1] = vIt - hlpV / 2;
5307  this->_densityMapCorCoords[nonTranslatedIter][2] = wIt - hlpW / 2;
5308  }
5309  else // Proceed normally
5310  {
5311  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5312 
5313  cenPosU = uIt + (hlpU / 2); if ( cenPosU >= hlpU ) { cenPosU -= hlpU; }
5314  cenPosV = vIt + (hlpV / 2); if ( cenPosV >= hlpV ) { cenPosV -= hlpV; }
5315  cenPosW = wIt + (hlpW / 2); if ( cenPosW >= hlpW ) { cenPosW -= hlpW; }
5316  coordPos = cenPosW + (this->_maxMapW + 2) * ( cenPosV + (this->_maxMapV + 2) * cenPosU );
5317 
5318  this->_densityMapCor[coordPos] = tmpIn[arrayPos][0];
5319  this->_densityMapCorCoords[coordPos][0] = cenPosU - hlpU / 2;
5320  this->_densityMapCorCoords[coordPos][1] = cenPosV - hlpV / 2;
5321  this->_densityMapCorCoords[coordPos][2] = cenPosW - hlpW / 2;
5322  }
5323  nonTranslatedIter += 1;
5324  }
5325  }
5326  }
5327 
5328  //======================================== Free allocated memory
5329  delete[] tmpOut;
5330  delete[] tmpIn;
5331 
5332  //======================================== Free unnecessary memory
5333  if ( this->_densityMapMap != nullptr )
5334  {
5335  delete this->_densityMapMap;
5336  this->_densityMapMap = nullptr;
5337  }
5338 
5339  //======================================== Done
5340  this->_phaseRemoved = true;
5341  this->_keepOrRemove = false;
5342  this->_usePhase = false;
5343 
5344 }
5345 
5358  double bFac,
5359  ProSHADE::ProSHADE_settings* settings )
5360 {
5361  //======================================== Sanity check
5362  if ( !this->_densityMapComputed )
5363  {
5364  std::cerr << "!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName << " !!! Attempted to remove phase information from map before computing the map. Call the getDensityMapFromPDB function BEFORE the removePhaseFromMap function." << std::endl;
5365 
5366  if ( settings->htmlReport )
5367  {
5368  std::stringstream hlpSS;
5369  hlpSS << "<font color=\"red\">" << "Attempted to remove phase information from map before computing the map. Call the getDensityMapFromPDB function BEFORE the removePhaseFromMap function. This looks like an internal bug - please report this case." << "</font>";
5370  rvapi_set_text ( hlpSS.str().c_str(),
5371  "ProgressSection",
5372  settings->htmlReportLineProgress,
5373  1,
5374  1,
5375  1 );
5376  settings->htmlReportLineProgress += 1;
5377  rvapi_flush ( );
5378  }
5379 
5380  exit ( -1 );
5381  }
5382 
5383  //======================================== Initialise internal values
5384  this->_fourierCoeffPower = alpha;
5385  this->_bFactorChange = bFac;
5386 
5387  //======================================== Initialise local variables for Fourier and Inverse Fourier
5388  fftw_complex *tmpOut;
5389  fftw_complex *tmpIn;
5390  fftw_plan p;
5391  fftw_plan pInv;
5392  int uIt, vIt, wIt;
5393  double real, imag;
5394  int hlpU = ( this->_maxMapU + 1 );
5395  int hlpV = ( this->_maxMapV + 1 );
5396  int hlpW = ( this->_maxMapW + 1 );
5397 
5398  this->_densityMapCor = new double [hlpU * hlpV * hlpW];
5399  tmpIn = new fftw_complex[hlpU * hlpV * hlpW];
5400  tmpOut = new fftw_complex[hlpU * hlpV * hlpW];
5401 
5402  //======================================== Create plans (FFTW_MEASURE would change the arrays)
5403  p = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpIn, tmpOut, FFTW_FORWARD, FFTW_ESTIMATE );
5404  pInv = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpOut, tmpIn, FFTW_BACKWARD, FFTW_ESTIMATE );
5405 
5406  //======================================== Load map data for Fourier
5407  unsigned int arrayPos = 0;
5408 
5409  for ( uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
5410  {
5411  for ( vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
5412  {
5413  for ( wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
5414  {
5415  //============================ Initialisation
5416  arrayPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
5417 
5418  if ( this->_densityMapMap[arrayPos] == this->_densityMapMap[arrayPos] )
5419  {
5420  tmpIn[arrayPos][0] = this->_densityMapMap[arrayPos];
5421  tmpIn[arrayPos][1] = 0.0;
5422  }
5423  else
5424  {
5425  tmpIn[arrayPos][0] = 0.0;
5426  tmpIn[arrayPos][1] = 0.0;
5427  }
5428  }
5429  }
5430  }
5431 
5432  //======================================== Calculate Fourier
5433  fftw_execute ( p );
5434 
5435  //======================================== Remove phase information
5436  arrayPos = 0;
5437  int h, k, l;
5438  double mag, S;
5439  double normFactor = (hlpU * hlpV * hlpW);
5440  for ( uIt = 0; uIt < hlpU; uIt++ )
5441  {
5442  for ( vIt = 0; vIt < hlpV; vIt++ )
5443  {
5444  for ( wIt = 0; wIt < hlpW; wIt++ )
5445  {
5446  //============================ Var init
5447  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5448  real = tmpOut[arrayPos][0];
5449  imag = tmpOut[arrayPos][1];
5450 
5451  //============================ Change the B-factors, if required
5452  if ( uIt > (hlpU / 2) ) { h = uIt - hlpU; } else { h = uIt; }
5453  if ( vIt > (hlpV / 2) ) { k = vIt - hlpV; } else { k = vIt; }
5454  if ( wIt > (hlpW / 2) ) { l = wIt - hlpW; } else { l = wIt; }
5455 
5456  S = pow( static_cast<double> ( h ) / this->_xRange, 2.0 ) + pow( static_cast<double> ( k ) / this->_yRange, 2.0 ) + pow( static_cast<double> ( l ) / this->_zRange, 2.0 );
5457  mag = std::exp ( - ( ( this->_bFactorChange * S ) / 4.0 ) );
5458 
5459  //============================ Get magnitude and phase
5460  mag *= sqrt ( (real*real) + (imag*imag) );
5461 
5462  //============================ Magnitude power alpha
5463  mag = pow ( mag, this->_fourierCoeffPower );
5464 
5465  //============================ Phase removal
5466  tmpOut[arrayPos][0] = mag;
5467  tmpOut[arrayPos][1] = 0.0;
5468 
5469  //============================ Normalize
5470  tmpOut[arrayPos][0] /= normFactor;
5471  }
5472  }
5473  }
5474 
5475  //======================================== Run backward Fourier
5476  fftw_execute ( pInv );
5477 
5478  //======================================== Free allocated memory
5479  fftw_destroy_plan ( p );
5480  fftw_destroy_plan ( pInv );
5481 
5482  //======================================== Re-order (i.e. centralise) the Patterson
5483  int cenPosU;
5484  int cenPosV;
5485  int cenPosW;
5486  int coordPos;
5487 
5488  for ( uIt = 0; uIt < static_cast<int> (this->_maxMapU + 1); uIt++ )
5489  {
5490  for ( vIt = 0; vIt < static_cast<int> (this->_maxMapV + 1); vIt++ )
5491  {
5492  for ( wIt = 0; wIt < static_cast<int> (this->_maxMapW + 1); wIt++ )
5493  {
5494  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5495 
5496  cenPosU = uIt + (hlpU / 2); if ( cenPosU >= hlpU ) { cenPosU -= hlpU; }
5497  cenPosV = vIt + (hlpV / 2); if ( cenPosV >= hlpV ) { cenPosV -= hlpV; }
5498  cenPosW = wIt + (hlpW / 2); if ( cenPosW >= hlpW ) { cenPosW -= hlpW; }
5499  coordPos = cenPosW + (this->_maxMapW + 1) * ( cenPosV + (this->_maxMapV + 1) * cenPosU );
5500 
5501  this->_densityMapCor[arrayPos]= tmpIn[coordPos][0];
5502  }
5503  }
5504  }
5505 
5506  //======================================== Free allocated memory
5507  delete[] tmpOut;
5508  delete[] tmpIn;
5509 
5510  //======================================== Free unnecessary memory
5511  if ( this->_densityMapMap != nullptr )
5512  {
5513  delete this->_densityMapMap;
5514  this->_densityMapMap = nullptr;
5515  }
5516 
5517  //======================================== Done
5518  this->_phaseRemoved = true;
5519  this->_usePhase = false;
5520  this->_keepOrRemove = false;
5521 
5522 }
5523 
5548  double bFac,
5549  unsigned int *bandwidth,
5550  unsigned int *theta,
5551  unsigned int *phi,
5552  unsigned int *glIntegOrder,
5553  ProSHADE::ProSHADE_settings* settings,
5554  bool useCom,
5555  double maxMapIQR,
5556  int verbose,
5557  bool clearMapData,
5558  bool rotDefaults,
5559  bool overlapDefaults,
5560  double blurFactor,
5561  bool maskBlurFactorGiven )
5562 {
5563  //======================================== Sanity check
5564  if ( !this->_densityMapComputed )
5565  {
5566  std::cerr << "!!! ProSHADE ERROR !!! Error in file " << this->_inputFileName << " !!! Attempted to keep phase information from map before computing the map. Call the getDensityMapFromPDB function BEFORE the keepPhaseInMap function." << std::endl;
5567 
5568  if ( settings->htmlReport )
5569  {
5570  std::stringstream hlpSS;
5571  hlpSS << "<font color=\"red\">" << "Attempted to remove phase information from map before computing the map. Call the getDensityMapFromPDB function BEFORE the keepPhaseInMap function. This looks like an internal bug - please report this case." << "</font>";
5572  rvapi_set_text ( hlpSS.str().c_str(),
5573  "ProgressSection",
5574  settings->htmlReportLineProgress,
5575  1,
5576  1,
5577  1 );
5578  settings->htmlReportLineProgress += 1;
5579  rvapi_flush ( );
5580  }
5581 
5582  exit ( -1 );
5583  }
5584 
5585  //======================================== Initialise internal values
5586  this->_fourierCoeffPower = alpha;
5587  this->_bFactorChange = bFac;
5588 
5589  //======================================== Local hlp variables
5590  int hlpU = ( this->_maxMapU + 1 );
5591  int hlpV = ( this->_maxMapV + 1 );
5592  int hlpW = ( this->_maxMapW + 1 );
5593 
5594  //======================================== Initialise local variables for Fourier and Inverse Fourier
5595  fftw_complex *tmpOut;
5596  fftw_complex *tmpIn;
5597  fftw_plan p;
5598  fftw_plan pInv;
5599  int uIt, vIt, wIt;
5600  double real, imag;
5601  unsigned int arrayPos = 0;
5602  int arrPos = 0;
5603 
5604  this->_densityMapCor = new double [hlpU * hlpV * hlpW];
5605  tmpIn = new fftw_complex[hlpU * hlpV * hlpW];
5606  tmpOut = new fftw_complex[hlpU * hlpV * hlpW];
5607 
5608  //======================================== Create plans (FFTW_MEASURE would change the arrays)
5609  p = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpIn, tmpOut, FFTW_FORWARD, FFTW_ESTIMATE );
5610  pInv = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpOut, tmpIn, FFTW_BACKWARD, FFTW_ESTIMATE );
5611 
5612  //======================================== Load map data for Fourier
5613  for ( uIt = 0; uIt < static_cast<int> (this->_maxMapU+1); uIt++ )
5614  {
5615  for ( vIt = 0; vIt < static_cast<int> (this->_maxMapV+1); vIt++ )
5616  {
5617  for ( wIt = 0; wIt < static_cast<int> (this->_maxMapW+1); wIt++ )
5618  {
5619  //============================ Initialisation
5620  arrPos = wIt + (this->_maxMapW + 1) * ( vIt + (this->_maxMapV + 1) * uIt );
5621 
5622  if ( this->_densityMapMap[arrPos] == this->_densityMapMap[arrPos] )
5623  {
5624  tmpIn[arrPos][0] = this->_densityMapMap[arrPos];
5625  tmpIn[arrPos][1] = 0.0;
5626  }
5627  else
5628  {
5629  tmpIn[arrPos][0] = 0.0;
5630  tmpIn[arrPos][1] = 0.0;
5631  }
5632  }
5633  }
5634  }
5635 
5636  //======================================== Check if alpha or B-factor change is required
5637  if ( ( this->_fourierCoeffPower != 1.0 ) || ( this->_bFactorChange != 0.0 ) )
5638  {
5639  //==================================== Calculate Fourier
5640  fftw_execute ( p );
5641 
5642  //==================================== Manipulate the B-factors and such
5643  int h, k, l;
5644  double mag, phase, S;
5645  double normFactor = (hlpU * hlpV * hlpW);
5646  for ( uIt = 0; uIt < hlpU; uIt++ )
5647  {
5648  for ( vIt = 0; vIt < hlpV; vIt++ )
5649  {
5650  for ( wIt = 0; wIt < hlpW; wIt++ )
5651  {
5652  //======================== Var init
5653  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5654  real = tmpOut[arrayPos][0];
5655  imag = tmpOut[arrayPos][1];
5656 
5657  //======================== Change the B-factors, if required
5658  if ( uIt > (hlpU / 2) ) { h = uIt - hlpU; } else { h = uIt; }
5659  if ( vIt > (hlpV / 2) ) { k = vIt - hlpV; } else { k = vIt; }
5660  if ( wIt > (hlpW / 2) ) { l = wIt - hlpW; } else { l = wIt; }
5661 
5662  S = pow ( static_cast<double> ( h ) / this->_xRange, 2.0 ) +
5663  pow ( static_cast<double> ( k ) / this->_yRange, 2.0 ) +
5664  pow ( static_cast<double> ( l ) / this->_zRange, 2.0 );
5665  mag = std::exp ( - ( ( this->_bFactorChange * S ) / 4.0 ) );
5666 
5667  //======================== Get magnitude and phase
5668  mag *= sqrt ( (real*real) + (imag*imag) );
5669  phase = atan2 ( imag, real );
5670 
5671  //======================== Magnitude power alpha
5672  mag = pow ( mag, this->_fourierCoeffPower );
5673 
5674  //======================== Phase kept
5675  tmpOut[arrayPos][0] = mag * cos(phase);
5676  tmpOut[arrayPos][1] = mag * sin(phase);
5677 
5678  //======================== Normalize
5679  tmpOut[arrayPos][0] /= normFactor;
5680  tmpOut[arrayPos][1] /= normFactor;
5681  }
5682  }
5683  }
5684 
5685  //==================================== Run backward Fourier
5686  fftw_execute ( pInv );
5687  }
5688 
5689  //======================================== Free allocated memory
5690  fftw_destroy_plan ( p );
5691  fftw_destroy_plan ( pInv );
5692 
5693  //======================================== Copy map to new holder
5694  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
5695  {
5696  this->_densityMapCor[iter] = this->_densityMapMap[iter];
5697  }
5698 
5699  //======================================== Free unnecessary memory
5700  if ( this->_densityMapMap != nullptr )
5701  {
5702  free ( this->_densityMapMap );
5703  this->_densityMapMap = nullptr;
5704  }
5705 
5706  //======================================== Map cleaning
5707  if ( !this->_fromPDB )
5708  {
5709  if ( clearMapData )
5710  {
5711  //================================ Save original map to restore for each cycle
5712  double *tmpMp = new double[hlpU * hlpV * hlpW];
5713  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
5714  {
5715  tmpMp[iter] = this->_densityMapCor[iter];
5716  }
5717 
5718  bool notTooManyIslads = true;
5719  double blFr = 150.0;
5720 
5721  while ( notTooManyIslads )
5722  {
5723  //============================ Do not change user values
5724  blFr += 50.0;
5725  if ( maskBlurFactorGiven )
5726  {
5727  blFr = blurFactor;
5728  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
5729  this->removeIslands ( hlpU, hlpV, hlpW, verbose, true );
5730  break;
5731  }
5732 
5733  //============================ Compute mask and apply it
5734  this->maskMap ( hlpU, hlpV, hlpW, blFr, maxMapIQR, 3.0 );
5735 
5736  //============================ Detect islands
5737  if ( verbose > 3 )
5738  {
5739  std::cout << ">>>>>>>> Island detection started." << std::endl;
5740  }
5741 
5742  notTooManyIslads = this->removeIslands ( hlpU, hlpV, hlpW, verbose, false );
5743 
5744  if ( maskBlurFactorGiven )
5745  {
5746  break;
5747  }
5748 
5749  if ( verbose > 3 )
5750  {
5751  std::cout << ">>>>> Map masked with factor of " << blFr << " and small islands were then removed.";
5752  }
5753  if ( notTooManyIslads )
5754  {
5755  if ( verbose > 3 )
5756  {
5757  std::cout << " However, too many islands remained. Trying higher blurring factor." << std::endl;
5758  }
5759 
5760  if ( blFr <= 500.0 )
5761  {
5762  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
5763  {
5764  this->_densityMapCor[iter] = tmpMp[iter];
5765  }
5766  }
5767  }
5768  else
5769  {
5770  if ( verbose > 3 )
5771  {
5772  std::cout << std::endl;
5773  }
5774  }
5775 
5776  if ( blFr > 500.0 )
5777  {
5778  std::cout << "!!! ProSHADE WARNING !!! Even blurring factor of 500 did not remove islands. Will not proceed with what we have, but be warned that either the masking is bugged or yout map has high levels of noise. You can consider using the -y ( or --no_clear ) options to avoid this message and the extra time for testing different blurring factors for this map." << std::endl;
5779 
5780  if ( settings->htmlReport )
5781  {
5782  std::stringstream hlpSS;
5783  hlpSS << "<font color=\"orange\">" << "Even blurring factor of 500 did not remove islands. Will not proceed with what we have, but be warned that either the masking is bugged or yout map has high levels of noise. You can consider using the -y ( or --no_clear ) options to avoid this message and the extra time for testing different blurring factors for this map." << "</font>";
5784  rvapi_set_text ( hlpSS.str().c_str(),
5785  "ProgressSection",
5786  settings->htmlReportLineProgress,
5787  1,
5788  1,
5789  1 );
5790  settings->htmlReportLineProgress += 1;
5791  rvapi_flush ( );
5792  }
5793 
5794  break;
5795  }
5796  }
5797  delete[] tmpMp;
5798  }
5799  }
5800 
5801  //======================================== Get real dimensions, instead of unit grid
5802  double xReal = this->_xRange / static_cast<double> ( this->_maxMapU + 1 );
5803  double yReal = this->_yRange / static_cast<double> ( this->_maxMapV + 1 );
5804  double zReal = this->_zRange / static_cast<double> ( this->_maxMapW + 1 );
5805 
5806  //======================================== Find the COM
5807  std::array<double,3> meanVals;
5808  meanVals[0] = 0.0;
5809  meanVals[1] = 0.0;
5810  meanVals[2] = 0.0;
5811 
5812  if ( !this->_firstLineCOM )
5813  {
5814  if ( useCom )
5815  {
5816  double totDens = 0.0;
5817 
5818  for ( uIt = 0; uIt < hlpU; uIt++ )
5819  {
5820  for ( vIt = 0; vIt < hlpV; vIt++ )
5821  {
5822  for ( wIt = 0; wIt < hlpW; wIt++ )
5823  {
5824  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5825 
5826  if ( !this->_fromPDB )
5827  {
5828  if ( this->_densityMapCor[arrayPos] > 0.0 )
5829  {
5830  meanVals[0] += this->_densityMapCor[arrayPos] * uIt;
5831  meanVals[1] += this->_densityMapCor[arrayPos] * vIt;
5832  meanVals[2] += this->_densityMapCor[arrayPos] * wIt;
5833 
5834  totDens += this->_densityMapCor[arrayPos];
5835  }
5836  }
5837  else
5838  {
5839  if ( tmpIn[arrayPos][0] > 0.0 )
5840  {
5841  meanVals[0] += tmpIn[arrayPos][0] * uIt;
5842  meanVals[1] += tmpIn[arrayPos][0] * vIt;
5843  meanVals[2] += tmpIn[arrayPos][0] * wIt;
5844 
5845  totDens += tmpIn[arrayPos][0];
5846  }
5847  }
5848  }
5849  }
5850  }
5851 
5852  meanVals[0] /= totDens;
5853  meanVals[1] /= totDens;
5854  meanVals[2] /= totDens;
5855  }
5856  else
5857  {
5858  meanVals[0] = static_cast<double> ( this->_maxMapU + 1 )/2.0;
5859  meanVals[1] = static_cast<double> ( this->_maxMapV + 1 )/2.0;
5860  meanVals[2] = static_cast<double> ( this->_maxMapW + 1 )/2.0;
5861  }
5862  }
5863  else
5864  {
5865  meanVals[0] = this->_xCorrErr / xReal;
5866  meanVals[1] = this->_yCorrErr / yReal;
5867  meanVals[2] = this->_zCorrErr / zReal;
5868  }
5869 
5870  //======================================== Re-index the map with COM in the centre
5871  this->_xCorrErr = meanVals[0] - static_cast<double> ( this->_maxMapU + 1 )/2.0;
5872  this->_yCorrErr = meanVals[1] - static_cast<double> ( this->_maxMapV + 1 )/2.0;
5873  this->_zCorrErr = meanVals[2] - static_cast<double> ( this->_maxMapW + 1 )/2.0;
5874 
5875  this->_xCorrection = std::ceil ( this->_xCorrErr );
5876  this->_yCorrection = std::ceil ( this->_yCorrErr );
5877  this->_zCorrection = std::ceil ( this->_zCorrErr );
5878 
5879  //======================================== Initialise internal values
5880  this->_densityMapCorCoords = new std::array<double,3> [hlpU * hlpV * hlpW];
5881  int newU, newV, newW, coordPos;
5882 
5883  if ( this->_fromPDB )
5884  {
5885 
5886  if ( useCom )
5887  {
5888  for ( uIt = 0; uIt < hlpU; uIt++ )
5889  {
5890  for ( vIt = 0; vIt < hlpV; vIt++ )
5891  {
5892  for ( wIt = 0; wIt < hlpW; wIt++ )
5893  {
5894  newU = static_cast<int> ( uIt ) - static_cast<int> ( this->_xCorrection );
5895  newV = static_cast<int> ( vIt ) - static_cast<int> ( this->_yCorrection );
5896  newW = static_cast<int> ( wIt ) - static_cast<int> ( this->_zCorrection );
5897 
5898  if ( newU < 0 ) { newU += hlpU; } if ( newU >= static_cast<int> ( hlpU ) ) { newU -= hlpU; }
5899  if ( newV < 0 ) { newV += hlpV; } if ( newV >= static_cast<int> ( hlpV ) ) { newV -= hlpV; }
5900  if ( newW < 0 ) { newW += hlpW; } if ( newW >= static_cast<int> ( hlpW ) ) { newW -= hlpW; }
5901 
5902  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5903  coordPos = newW + hlpW * ( newV + hlpV * newU );
5904 
5905  this->_densityMapCor[coordPos] = tmpIn[arrayPos][0];
5906 
5907  //======================== Save results
5908  this->_densityMapCorCoords[coordPos][0] = ( static_cast<double> ( newU ) - static_cast<double> ( hlpU ) /2.0 ) * xReal;
5909  this->_densityMapCorCoords[coordPos][1] = ( static_cast<double> ( newV ) - static_cast<double> ( hlpV ) /2.0 ) * yReal;
5910  this->_densityMapCorCoords[coordPos][2] = ( static_cast<double> ( newW ) - static_cast<double> ( hlpW ) /2.0 ) * zReal;
5911  }
5912  }
5913  }
5914  }
5915  else
5916  {
5917  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
5918  {
5919  this->_densityMapCor[iter] = tmpIn[iter][0];
5920  }
5921  }
5922  }
5923  //======================================== Speedup for maps
5924  else
5925  {
5926  if ( !clearMapData )
5927  {
5928  this->_xCorrection = 0.0;
5929  this->_yCorrection = 0.0;
5930  this->_zCorrection = 0.0;
5931  }
5932 
5933  //==================================== Save the final coords
5934  for ( uIt = 0; uIt < hlpU; uIt++ )
5935  {
5936  for ( vIt = 0; vIt < hlpV; vIt++ )
5937  {
5938  for ( wIt = 0; wIt < hlpW; wIt++ )
5939  {
5940  newU = static_cast<int> ( uIt ) - static_cast<int> ( this->_xCorrection );
5941  newV = static_cast<int> ( vIt ) - static_cast<int> ( this->_yCorrection );
5942  newW = static_cast<int> ( wIt ) - static_cast<int> ( this->_zCorrection );
5943 
5944  if ( newU < 0 ) { newU += hlpU; } if ( newU >= static_cast<int> ( hlpU ) ) { newU -= hlpU; }
5945  if ( newV < 0 ) { newV += hlpV; } if ( newV >= static_cast<int> ( hlpV ) ) { newV -= hlpV; }
5946  if ( newW < 0 ) { newW += hlpW; } if ( newW >= static_cast<int> ( hlpW ) ) { newW -= hlpW; }
5947 
5948  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
5949  coordPos = newW + hlpW * ( newV + hlpV * newU );
5950 
5951  this->_densityMapCorCoords[coordPos][0] = ( static_cast<double> ( newU ) - static_cast<double> ( hlpU ) / 2.0 ) * xReal;
5952  this->_densityMapCorCoords[coordPos][1] = ( static_cast<double> ( newV ) - static_cast<double> ( hlpV ) / 2.0 ) * yReal;
5953  this->_densityMapCorCoords[coordPos][2] = ( static_cast<double> ( newW ) - static_cast<double> ( hlpW ) / 2.0 ) * zReal;
5954  }
5955  }
5956  }
5957 
5958  //==================================== Determine the real size of the shape
5959  double maxX = 0.0;
5960  double minX = 0.0;
5961  double maxY = 0.0;
5962  double minY = 0.0;
5963  double maxZ = 0.0;
5964  double minZ = 0.0;
5965  double maxXTot = 0.0;
5966  double minXTot = 0.0;
5967  double maxYTot = 0.0;
5968  double minYTot = 0.0;
5969  double maxZTot = 0.0;
5970  double minZTot = 0.0;
5971 
5972  for ( uIt = 0; uIt < hlpU; uIt++ )
5973  {
5974  for ( vIt = 0; vIt < hlpV; vIt++ )
5975  {
5976  for ( wIt = 0; wIt < hlpW; wIt++ )
5977  {
5978  coordPos = wIt + hlpW * ( vIt + hlpV * uIt );
5979 
5980  if ( this->_densityMapCor[coordPos] > 0.0 )
5981  {
5982  maxX = std::max ( maxX, this->_densityMapCorCoords[coordPos][0] );
5983  minX = std::min ( minX, this->_densityMapCorCoords[coordPos][0] );
5984  maxY = std::max ( maxY, this->_densityMapCorCoords[coordPos][1] );
5985  minY = std::min ( minY, this->_densityMapCorCoords[coordPos][1] );
5986  maxZ = std::max ( maxZ, this->_densityMapCorCoords[coordPos][2] );
5987  minZ = std::min ( minZ, this->_densityMapCorCoords[coordPos][2] );
5988  }
5989  maxXTot = std::max ( maxXTot, this->_densityMapCorCoords[coordPos][0] );
5990  minXTot = std::min ( minXTot, this->_densityMapCorCoords[coordPos][0] );
5991  maxYTot = std::max ( maxYTot, this->_densityMapCorCoords[coordPos][1] );
5992  minYTot = std::min ( minYTot, this->_densityMapCorCoords[coordPos][1] );
5993  maxZTot = std::max ( maxZTot, this->_densityMapCorCoords[coordPos][2] );
5994  minZTot = std::min ( minZTot, this->_densityMapCorCoords[coordPos][2] );
5995  }
5996  }
5997  }
5998 
5999  //==================================== If masking did nothing, submit full map
6000  if ( ( ( maxX == maxXTot ) && ( minX == minXTot ) ) &&
6001  ( ( maxY == maxYTot ) && ( minY == minYTot ) ) &&
6002  ( ( maxZ == maxZTot ) && ( minZ == minZTot ) ) )
6003  {
6004  //================================ Done
6005  this->_phaseRemoved = true;
6006  this->_keepOrRemove = true;
6007  this->_usePhase = true;
6008 
6009  return ;
6010  }
6011 
6012  //==================================== If rotating map, do not change it!
6013  if ( rotDefaults || overlapDefaults )
6014  {
6015  //================================ Done
6016  this->_phaseRemoved = true;
6017  this->_keepOrRemove = true;
6018  this->_usePhase = true;
6019 
6020  return ;
6021  }
6022 
6023  //==================================== Calculate the grid for only the shape
6024  int newUStart = std::floor ( ( ( minX - minXTot ) / ( maxXTot - minXTot ) ) * ( this->_maxMapU + 1 ) );
6025  int newUEnd = std::ceil ( ( ( maxX - minXTot ) / ( maxXTot - minXTot ) ) * ( this->_maxMapU + 1 ) );
6026  int newVStart = std::floor ( ( ( minY - minYTot ) / ( maxYTot - minYTot ) ) * ( this->_maxMapV + 1 ) );
6027  int newVEnd = std::ceil ( ( ( maxY - minYTot ) / ( maxYTot - minYTot ) ) * ( this->_maxMapV + 1 ) );
6028  int newWStart = std::floor ( ( ( minZ - minZTot ) / ( maxZTot - minZTot ) ) * ( this->_maxMapW + 1 ) );
6029  int newWEnd = std::ceil ( ( ( maxZ - minZTot ) / ( maxZTot - minZTot ) ) * ( this->_maxMapW + 1 ) );
6030 
6031  int newURange = std::max ( std::abs ( newUStart - static_cast<int>( this->_maxMapU + 1 )/2 ), std::abs ( newUEnd - static_cast<int>( this->_maxMapU + 1 )/2 ) );
6032  int newVRange = std::max ( std::abs ( newVStart - static_cast<int>( this->_maxMapV + 1 )/2 ), std::abs ( newVEnd - static_cast<int>( this->_maxMapV + 1 )/2 ) );
6033  int newWRange = std::max ( std::abs ( newWStart - static_cast<int>( this->_maxMapW + 1 )/2 ), std::abs ( newWEnd - static_cast<int>( this->_maxMapW + 1 )/2 ) );
6034 
6035  newUStart = ( this->_maxMapU + 1 )/2 - newURange;
6036  newUEnd = ( this->_maxMapU + 1 )/2 + newURange;
6037  newVStart = ( this->_maxMapV + 1 )/2 - newVRange;
6038  newVEnd = ( this->_maxMapV + 1 )/2 + newVRange;
6039  newWStart = ( this->_maxMapW + 1 )/2 - newWRange;
6040  newWEnd = ( this->_maxMapW + 1 )/2 + newWRange;
6041 
6042  newURange = newURange * 2 + 1;
6043  newVRange = newVRange * 2 + 1;
6044  newWRange = newWRange * 2 + 1;
6045 
6046  //==================================== Create new map and coords structures
6047  double* newMapHlp = new double [newURange * newVRange * newWRange];
6048  std::array<double,3>* newMapCoords = new std::array<double,3> [newURange * newVRange * newWRange];
6049 
6050  //==================================== Copy map portion to new structures
6051  unsigned int newUIt, newVIt, newWIt;
6052 
6053  newUIt = 0;
6054  for ( uIt = 0; uIt < hlpU; uIt++ )
6055  {
6056  if ( ( uIt < newUStart ) || ( uIt > newUEnd ) ) { continue; }
6057 
6058  newVIt = 0;
6059  for ( vIt = 0; vIt < hlpV; vIt++ )
6060  {
6061  if ( ( vIt < newVStart ) || ( vIt > newVEnd ) ) { continue; }
6062 
6063  newWIt = 0;
6064  for ( wIt = 0; wIt < hlpW; wIt++ )
6065  {
6066  if ( ( wIt < newWStart ) || ( wIt > newWEnd ) ) { continue; }
6067 
6068  coordPos = wIt + hlpW * ( vIt + hlpV * uIt );
6069  arrayPos = newWIt + newWRange * ( newVIt + newVRange * newUIt );
6070 
6071  newMapHlp[arrayPos] = this->_densityMapCor[coordPos];
6072  newMapCoords[arrayPos][0] = this->_densityMapCorCoords[coordPos][0];
6073  newMapCoords[arrayPos][1] = this->_densityMapCorCoords[coordPos][1];
6074  newMapCoords[arrayPos][2] = this->_densityMapCorCoords[coordPos][2];
6075 
6076  newWIt += 1;
6077  }
6078 
6079  newVIt += 1;
6080  }
6081 
6082  newUIt += 1;
6083  }
6084 
6085  //==================================== Delete old structures
6086  delete this->_densityMapCor;
6087  delete this->_densityMapCorCoords;
6088  this->_densityMapCor = nullptr;
6089  this->_densityMapCorCoords = nullptr;
6090 
6091  //==================================== Copy
6092  this->_densityMapCor = newMapHlp;
6093  newMapHlp = nullptr;
6094  this->_densityMapCorCoords = newMapCoords;
6095  newMapCoords = nullptr;
6096 
6097  //==================================== Re-set internal variables
6098  this->_xRange = ( static_cast<double> (newURange - 1) / static_cast<double> ( this->_maxMapU ) ) * this->_xRange;
6099  this->_yRange = ( static_cast<double> (newVRange - 1) / static_cast<double> ( this->_maxMapV ) ) * this->_yRange;
6100  this->_zRange = ( static_cast<double> (newWRange - 1) / static_cast<double> ( this->_maxMapW ) ) * this->_zRange;
6101  this->_maxMapRange = std::max ( this->_xRange, std::max( this->_yRange, this->_zRange ) );
6102 
6103  this->_maxMapU = newURange - 1;
6104  this->_maxMapV = newVRange - 1;
6105  this->_maxMapW = newWRange - 1;
6106 
6107  //==================================== Automatically determine maximum number of shells
6108  this->_shellPlacement = std::vector<double> ( std::floor ( this->_maxMapRange / this->_shellSpacing ) );
6109 
6110  for ( unsigned int shellIter = 0; shellIter < static_cast<unsigned int> ( this->_shellPlacement.size() ); shellIter++ )
6111  {
6112  this->_shellPlacement.at(shellIter) = (shellIter+1) * this->_shellSpacing;
6113  }
6114 
6115  //==================================== Determine sampling ranges
6116  this->_xSamplingRate = this->_xRange / static_cast<double> ( this->_maxMapU );
6117  this->_ySamplingRate = this->_yRange / static_cast<double> ( this->_maxMapV );
6118  this->_zSamplingRate = this->_zRange / static_cast<double> ( this->_maxMapW );
6119  double maxSamplingRate = std::max ( this->_xSamplingRate, std::max( this->_ySamplingRate, this->_zSamplingRate ) );
6120 
6121  //==================================== Set sampling according to user set resolution and not the real map sampling
6122  if ( ( this->_mapResolution / 2.0 ) > maxSamplingRate )
6123  {
6124  maxSamplingRate = ( this->_mapResolution / 2.0 );
6125  }
6126 
6127  //==================================== If bandwidth is not given, determine it
6128  if ( !this->_wasBandwithGiven )
6129  {
6130  *bandwidth = std::ceil ( std::ceil ( ( ( std::ceil ( this->_maxMapRange / this->_shellSpacing ) * this->_shellSpacing ) / maxSamplingRate ) * 2.0 ) / 2.0 );
6131  }
6132  if ( settings->maxRotError != 0 )
6133  {
6134  *bandwidth = static_cast<unsigned int> ( 180 / settings->maxRotError );
6135  this->_wasBandwithGiven = true;
6136  }
6137 
6138  //==================================== If theta and phi are not given, determine them
6139  if ( !this->_wasThetaGiven ) { *theta = 2 * (*bandwidth); this->_thetaAngle = *theta; }
6140  if ( !this->_wasPhiGiven ) { *phi = 2 * (*bandwidth); this->_phiAngle = *phi; }
6141 
6142  //==================================== If Gauss-Legendre integration order is not given, decide it
6143  double distPerPointFraction;
6144  if ( !this->_wasGlInterGiven )
6145  {
6146  distPerPointFraction = ( ( this->_maxMapRange / 2.0 ) / static_cast<double> ( *bandwidth / 2 ) ) / ( this->_maxMapRange / 2.0 );
6147 
6148  for ( unsigned int iter = 2; iter < static_cast<unsigned int> ( ProSHADE_internal_misc::glIntMaxDists.size() ); iter++ )
6149  {
6150  if ( ProSHADE_internal_misc::glIntMaxDists.at(iter) >= distPerPointFraction )
6151  {
6152  *glIntegOrder = iter;
6153  }
6154  }
6155  }
6156  }
6157 
6158  //======================================== Set internal values
6159  this->_bandwidthLimit = *bandwidth;
6160  this->_thetaAngle = static_cast<double> ( *theta );
6161  this->_phiAngle = static_cast<double> ( *phi );
6162 
6163  //======================================== Free allocated memory
6164  delete[] tmpOut;
6165  delete[] tmpIn;
6166 
6167  //======================================== Done
6168  this->_phaseRemoved = true;
6169  this->_usePhase = true;
6170  this->_keepOrRemove = true;
6171 
6172 }
6173 
6184 {
6185  if ( verbose > 0 )
6186  {
6187  std::cout << "-----------------------------------------------------------" << std::endl;
6188  std::cout << "| RESULTS |" << std::endl;
6189  std::cout << "-----------------------------------------------------------" << std::endl << std::endl;
6190  }
6191 
6192  if ( verbose > -1 )
6193  {
6194  printf ( "File name: %s\n", this->one->_inputFileName.c_str() );
6195  printf ( "\n" );
6196  printf ( "Cell dimmensions (A): %+.1f x %+.1f x %+.1f\n", this->origRanges[0], this->origRanges[1], this->origRanges[2] );
6197  printf ( "Cell U, V and W: %+.1f x %+.1f x %+.1f\n", this->origDims[0]+1, this->origDims[1]+1, this->origDims[2]+1 );
6198  printf ( "\n" );
6199  printf ( "Min/Max density: %+.3f / %+.3f\n", this->minDensPreNorm, this->maxDensPreNorm );
6200  printf ( "Density mean: %+.3f\n", this->one->_mapMean );
6201  printf ( "Density std. dev: %+.3f\n", this->one->_mapSdev );
6202  printf ( "\n" );
6203  printf ( "Min/Max norm density: %+.3f / %+.3f\n", this->minDensPostNorm, this->maxDensPostNorm );
6204  printf ( "Norm. density mean: %+.3f\n", this->postNormMean );
6205  printf ( "Norm. density std. dev: %+.3f\n", this->postNormSdev );
6206  printf ( "\n" );
6207  printf ( "Total volume (A^3): %+.1f\n", this->totalVolume );
6208  printf ( "Mask volume (A^3): %+.1f\n", this->maskVolume );
6209  printf ( "\n" );
6210  printf ( "Min/Max mask density: %+.3f / %+.3f\n", this->maskMin, this->maskMax );
6211  printf ( "Mask density mean: %+.3f\n", this->maskMean );
6212  printf ( "Mask density std. dev: %+.3f\n", this->maskSdev );
6213  printf ( "\n" );
6214  printf ( "All density RMS: %+.3f\n", this->allDensityRMS );
6215  printf ( "Mask density RMS: %+.3f\n", this->maskDensityRMS );
6216  printf ( "\n\n" );
6217  }
6218 
6219 }
6220 
6237 std::vector< std::vector<int> > ProSHADE_internal::ProSHADE_data::findMapIslands ( int hlpU,
6238  int hlpV,
6239  int hlpW,
6240  double *map,
6241  double threshold )
6242 {
6243  //======================================== Initialise local variables
6244  int newU, newV, newW, coordPos, arrayPos;
6245  int uIt, vIt, wIt;
6246 
6247  //======================================== Island detection:
6248  std::vector< std::array<int,5> > clMap ( hlpU * hlpV * hlpW );
6249  std::array<int,5> hlpArr;
6250  for ( uIt = 0; uIt < hlpU; uIt++ )
6251  {
6252  for ( vIt = 0; vIt < hlpV; vIt++ )
6253  {
6254  for ( wIt = 0; wIt < hlpW; wIt++ )
6255  {
6256  hlpArr[0] = uIt;
6257  hlpArr[1] = vIt;
6258  hlpArr[2] = wIt;
6259  hlpArr[3] = wIt + hlpW * ( vIt + hlpV * uIt );
6260 
6261  if ( map[hlpArr[3]] <= threshold )
6262  {
6263  hlpArr[4] = -999;
6264  }
6265  else
6266  {
6267  hlpArr[4] = -1;
6268  }
6269  clMap.at(hlpArr[3]) = hlpArr;
6270  }
6271  }
6272  }
6273 
6274  //======================================== Island detection algorithm
6275  std::vector< std::vector<int> > clusters;
6276  std::vector<int> unclNeigh;
6277  std::vector<int> clNeigh;
6278  std::vector<int> hlpVec;
6279  std::vector<int> XXXVec;
6280  int clusterNo = 0;
6281  bool allSame = false;
6282  int hlpVal = 0;
6283  int minCl = 0;
6284 
6285  for ( uIt = 0; uIt < hlpU; uIt++ )
6286  {
6287  for ( vIt = 0; vIt < hlpV; vIt++ )
6288  {
6289  for ( wIt = 0; wIt < hlpW; wIt++ )
6290  {
6291  //============================ Find current array pos
6292  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
6293 
6294  //============================ If zero, ignore
6295  if ( clMap.at(arrayPos)[4] == -999 ) { continue; }
6296 
6297  //============================ Check neighbours
6298  unclNeigh.clear ( );
6299  clNeigh.clear ( );
6300  for ( int uCh = -1; uCh < 2; uCh++ )
6301  {
6302  for ( int vCh = -1; vCh < 2; vCh++ )
6303  {
6304  for ( int wCh = -1; wCh < 2; wCh++ )
6305  {
6306  if ( ( uCh == 0 ) && ( vCh == 0 ) && ( wCh == 0 ) ) { continue; }
6307 
6308  newU = static_cast<int> ( uIt ) + uCh;
6309  newV = static_cast<int> ( vIt ) + vCh;
6310  newW = static_cast<int> ( wIt ) + wCh;
6311 
6312  if ( newU < 0 ) { newU += hlpU; } if ( newU >= static_cast<int> ( hlpU ) ) { newU -= hlpU; }
6313  if ( newV < 0 ) { newV += hlpV; } if ( newV >= static_cast<int> ( hlpV ) ) { newV -= hlpV; }
6314  if ( newW < 0 ) { newW += hlpW; } if ( newW >= static_cast<int> ( hlpW ) ) { newW -= hlpW; }
6315 
6316  coordPos = newW + hlpW * ( newV + hlpV * newU );
6317 
6318  //================ If zero, ignore
6319  if ( clMap.at(coordPos)[4] == -999 ) { continue; }
6320 
6321  //================ If not clustered to anyone
6322  if ( clMap.at(coordPos)[4] == -1 )
6323  {
6324  unclNeigh.emplace_back ( coordPos );
6325  continue;
6326  }
6327 
6328  clNeigh.emplace_back ( coordPos );
6329  }
6330  }
6331  }
6332 
6333  //============================ If single point
6334  if ( ( unclNeigh.size() == 0 ) && ( clNeigh.size() == 0 ) )
6335  {
6336  //======================== Assign into new cluster
6337  clMap.at(arrayPos)[4] = clusterNo;
6338 
6339  unclNeigh.emplace_back ( arrayPos );
6340  clusters.emplace_back ( unclNeigh );
6341  unclNeigh.clear ( );
6342 
6343  clusterNo += 1;
6344  continue;
6345  }
6346 
6347  //============================ If only unclustered neighbours
6348  if ( ( unclNeigh.size() > 0 ) && ( clNeigh.size() == 0 ) )
6349  {
6350  //======================== Assign all new cluster
6351  clMap.at(arrayPos)[4] = clusterNo;
6352 
6353  clNeigh.emplace_back ( arrayPos );
6354  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( unclNeigh.size() ); iter++ )
6355  {
6356  clNeigh.emplace_back ( clMap.at(unclNeigh.at(iter))[3] );
6357  clMap.at(unclNeigh.at(iter))[4] = clusterNo;
6358  }
6359 
6360  clusters.emplace_back ( clNeigh );
6361  clNeigh.clear ( );
6362 
6363  clusterNo += 1;
6364  continue;
6365  }
6366 
6367  //============================ If some clustered neighbours
6368  if ( clNeigh.size() > 0 )
6369  {
6370  allSame = true;
6371  hlpVal = clMap.at(clNeigh.at(0))[4];
6372  for ( unsigned int iter = 1; iter < static_cast<unsigned int> ( clNeigh.size() ); iter++ )
6373  {
6374  if ( clMap.at(clNeigh.at(iter))[4] != hlpVal )
6375  {
6376  allSame = false;
6377  }
6378  }
6379 
6380  if ( allSame )
6381  {
6382  //==================== Assign this point to the same cluster as neighbours
6383  if ( clMap.at(arrayPos)[4] == -1 )
6384  {
6385  clMap.at(arrayPos)[4] = clMap.at(clNeigh.at(0))[4];
6386  clusters.at(clMap.at(clNeigh.at(0))[4]).emplace_back ( arrayPos );
6387  }
6388 
6389  //==================== Assign all yet unclustered neighbours also
6390  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( unclNeigh.size() ); iter++ )
6391  {
6392  clusters.at(clMap.at(clNeigh.at(0))[4]).emplace_back ( clMap.at(unclNeigh.at(iter))[3] );
6393  clMap.at(unclNeigh.at(iter))[4] = clMap.at(clNeigh.at(0))[4];
6394  }
6395  continue;
6396  }
6397  else
6398  {
6399  //==================== This is where two clusters meet. Start by finding the smalles cluster (smallest ID)
6400  hlpVec.clear ( );
6401  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( clNeigh.size() ); iter++ )
6402  {
6403  hlpVec.emplace_back ( clMap.at(clNeigh.at(iter))[4] );
6404  }
6405 
6406  std::sort ( hlpVec.begin(), hlpVec.end() );
6407  hlpVec.erase ( std::unique( hlpVec.begin(), hlpVec.end() ), hlpVec.end() );
6408 
6409  minCl = hlpVec.at(0);
6410 
6411  //==================== Now, enter this point to the cluster
6412  if ( clMap.at(arrayPos)[4] == -1 )
6413  {
6414  clMap.at(arrayPos)[4] = minCl;
6415  clusters.at(minCl).emplace_back ( arrayPos );
6416  }
6417 
6418  //==================== Then, copy all unclustered points to the smallest ID cluster
6419  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( unclNeigh.size() ); iter++ )
6420  {
6421  clMap.at(unclNeigh.at(iter))[4] = minCl;
6422  clusters.at(minCl).emplace_back ( unclNeigh.at(iter) );
6423  }
6424 
6425  //==================== And copy all other clusters to the one with smallest ID
6426  for ( unsigned int iter = 1; iter < static_cast<unsigned int> ( hlpVec.size() ); iter++ )
6427  {
6428  for ( unsigned int it = 0; it < static_cast<unsigned int> ( clusters.at(hlpVec.at(iter)).size() ); it++ )
6429  {
6430  clMap.at(clusters.at(hlpVec.at(iter)).at(it))[4] = minCl;
6431  clusters.at(minCl).emplace_back ( clusters.at(hlpVec.at(iter)).at(it) );
6432  }
6433  clusters.at(hlpVec.at(iter)).clear();
6434  }
6435  }
6436  }
6437  }
6438  }
6439  }
6440 
6441  //======================================== Find best clusters
6442  std::vector< std::array<double,3> > clVec;
6443  std::array<double,3> hArr;
6444  for ( unsigned int clIt = 0; clIt < static_cast<unsigned int> ( clusters.size() ); clIt++ )
6445  {
6446  if ( clusters.at(clIt).size() > 1 )
6447  {
6448  unsigned int minU = clMap.at(clusters.at(clIt).at(0))[0];
6449  unsigned int maxU = clMap.at(clusters.at(clIt).at(0))[0];
6450  unsigned int minV = clMap.at(clusters.at(clIt).at(0))[1];
6451  unsigned int maxV = clMap.at(clusters.at(clIt).at(0))[1];
6452  unsigned int minW = clMap.at(clusters.at(clIt).at(0))[2];
6453  unsigned int maxW = clMap.at(clusters.at(clIt).at(0))[2];
6454  for ( unsigned int el = 0; el < static_cast<unsigned int> ( clusters.at(clIt).size() ); el++ )
6455  {
6456  minU = std::min ( minU, static_cast<unsigned int> ( clMap.at(clusters.at(clIt).at(el))[0] ) );
6457  maxU = std::max ( maxU, static_cast<unsigned int> ( clMap.at(clusters.at(clIt).at(el))[0] ) );
6458  minV = std::min ( minV, static_cast<unsigned int> ( clMap.at(clusters.at(clIt).at(el))[1] ) );
6459  maxV = std::max ( maxV, static_cast<unsigned int> ( clMap.at(clusters.at(clIt).at(el))[1] ) );
6460  minW = std::min ( minW, static_cast<unsigned int> ( clMap.at(clusters.at(clIt).at(el))[2] ) );
6461  maxW = std::max ( maxW, static_cast<unsigned int> ( clMap.at(clusters.at(clIt).at(el))[2] ) );
6462  }
6463  double encVol = ( maxU - minU + 1 ) * ( maxV - minV + 1 ) * ( maxW - minW + 1 );
6464  hArr[0] = encVol / static_cast<double> ( clusters.at(clIt).size() );
6465  hArr[1] = static_cast<double> ( clusters.at(clIt).size() );
6466  hArr[2] = clIt;
6467  clVec.emplace_back ( hArr );
6468  }
6469  }
6470  std::sort ( clVec.begin(), clVec.end(), [](const std::array<double,3>& a, const std::array<double,3>& b) { return a[1] > b[1]; });
6471 
6472  std::vector<double> hlpVals;
6473  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( clVec.size() ); iter++ )
6474  {
6475  hlpVals.emplace_back ( clVec.at(iter)[1] );
6476  }
6477 
6478  double mean = std::accumulate ( hlpVals.begin(), hlpVals.end(), 0.0 ) / static_cast<double> ( hlpVals.size() );
6479  double sd = sqrt ( std::inner_product( hlpVals.begin(), hlpVals.end(), hlpVals.begin(), 0.0 ) / static_cast<double> ( hlpVals.size() ) - mean * mean );
6480  double thres = 0.0;
6481 
6482  std::vector< std::array<double,3> > hVec;
6483  for ( double iter = 5.0; iter >= 0.0; iter = iter - 0.5 )
6484  {
6485  thres = mean + ( iter * sd );
6486  hVec.clear ( );
6487 
6488  for ( unsigned int it = 0; it < static_cast<unsigned int> ( clVec.size() ); it++ )
6489  {
6490  if ( clVec.at(it)[1] >= thres )
6491  {
6492  hArr[0] = clVec.at(it)[0];
6493  hArr[1] = clVec.at(it)[2];
6494  hVec.emplace_back ( hArr );
6495  }
6496  }
6497 
6498  if ( ( hVec.size() > std::max ( std::floor ( clVec.size() * 0.05 ), 10.0 ) ) && ( hVec.size() < clVec.size() ) )
6499  {
6500  break;
6501  }
6502  }
6503 
6504  std::sort ( hVec.begin(), hVec.end(), [](const std::array<double,3>& a, const std::array<double,3>& b) { return a[0] < b[0]; });
6505  std::vector< std::vector<int> > clusts;
6506 
6507  hlpVals.clear ( );
6508  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hVec.size() ); iter++ )
6509  {
6510  hlpVals.emplace_back ( hVec.at(iter)[0] );
6511  }
6512 
6513  if ( hVec.size() < 5 )
6514  {
6515  mean = hVec.at(hVec.size()-1)[0] + 0.0001;
6516  sd = mean / 12.0;
6517  }
6518  else
6519  {
6520  mean = std::accumulate ( hlpVals.begin(), hlpVals.end(), 0.0 ) / static_cast<double> ( hlpVals.size() );
6521  sd = sqrt ( std::inner_product( hlpVals.begin(), hlpVals.end(), hlpVals.begin(), 0.0 ) / static_cast<double> ( hlpVals.size() ) - mean * mean );
6522  }
6523 
6524  for ( double it = 3.0; it >= 0.0; it = it - 0.25 )
6525  {
6526  thres = mean - ( it * sd );
6527  clusts.clear ( );
6528 
6529  if ( it == 0.0 )
6530  {
6531  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hVec.size() ); iter++ )
6532  {
6533  thres = std::max ( hVec.at(iter)[0], thres );
6534  }
6535  }
6536 
6537  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hVec.size() ); iter++ )
6538  {
6539  if ( hVec.at(iter)[0] <= thres )
6540  {
6541  clusts.emplace_back ( clusters.at(hVec.at(iter)[1]) );
6542  }
6543  }
6544 
6545  if ( ( clusts.size() > 0 ) && ( clusts.size() < 5 ) )
6546  {
6547  if ( ( clusts.size() ) < hVec.size() )
6548  {
6549  if ( ( hVec.at(clusts.size()-1)[0] > 3.0 ) && ( ( 2.0 * hVec.at(clusts.size()-1)[0] ) < hVec.at(clusts.size())[0] ) )
6550  {
6551  break;
6552  }
6553  }
6554  }
6555 
6556  if ( ( clusts.size() > std::max ( std::floor ( hVec.size() * 0.1 ), 5.0 ) ) && ( clusts.size() < hVec.size() ) ) { break; }
6557  }
6558 
6559  //======================================== Done
6560  return ( clusts );
6561 
6562 }
6563 
6576  int verbose,
6577  ProSHADE::ProSHADE_settings* settings )
6578 {
6579  //======================================== Sanity check
6580  if ( this->fragBoxSize <= 0.0 )
6581  {
6582  std::cerr << "!!! ProSHADE ERROR !!! Tried to fragment the map to boxes of size " << this->fragBoxSize << " . Terminating..." << std::endl;
6583 
6584  if ( settings->htmlReport )
6585  {
6586  std::stringstream hlpSS;
6587  hlpSS << "<font color=\"red\">" << "The box size to which the map should be fragmented in not in the allowed range ( " << this->fragBoxSize << " )" << "</font>";
6588  rvapi_set_text ( hlpSS.str().c_str(),
6589  "ProgressSection",
6590  settings->htmlReportLineProgress,
6591  1,
6592  1,
6593  1 );
6594  settings->htmlReportLineProgress += 1;
6595  rvapi_flush ( );
6596  }
6597 
6598  exit ( -1 );
6599  }
6600 
6601  if ( verbose > 0 )
6602  {
6603  std::cout << "-----------------------------------------------------------" << std::endl;
6604  std::cout << "| MAP FRAGMENTATION |" << std::endl;
6605  std::cout << "-----------------------------------------------------------" << std::endl << std::endl;
6606  }
6607 
6608  //======================================== Find X, Y and Z starts and ends of the required boxes
6609  std::vector< std::array<unsigned int,2> > XDim;
6610  std::vector< std::array<unsigned int,2> > YDim;
6611  std::vector< std::array<unsigned int,2> > ZDim;
6612  std::array<unsigned int,2> hlpArrX;
6613  std::array<unsigned int,2> hlpArrY;
6614  std::array<unsigned int,2> hlpArrZ;
6615  double maxMapAngPerIndex = std::max ( this->one->_xRange / static_cast<double> ( this->one->_maxMapU ),
6616  std::max ( this->one->_yRange / static_cast<double> ( this->one->_maxMapV ),
6617  this->one->_zRange / static_cast<double> ( this->one->_maxMapW ) ) );
6618  unsigned int boxDimInIndices = static_cast<unsigned int> ( std::round ( this->fragBoxSize / maxMapAngPerIndex ) );
6619  if ( ( boxDimInIndices % 2 ) == 1 )
6620  {
6621  //==================================== If odd, change to even
6622  boxDimInIndices += 1;
6623  }
6624 
6625  //======================================== Problem! The box is too small
6626  if ( boxDimInIndices < 2 )
6627  {
6628  std::cerr << "!!! ProSHADE ERROR !!! The box size for fragmentation is too small, please increase the box size or submit more detailed map. (Increasing the number of points by interpolation could work without changing the map here...)" << std::endl;
6629 
6630  if ( settings->htmlReport )
6631  {
6632  std::stringstream hlpSS;
6633  hlpSS << "<font color=\"red\">" << "The box size for fragmentation is too small, please increase the box size or submit more detailed map. (Increasing the number of points by interpolation could work without changing the map here...)." << "</font>";
6634  rvapi_set_text ( hlpSS.str().c_str(),
6635  "ProgressSection",
6636  settings->htmlReportLineProgress,
6637  1,
6638  1,
6639  1 );
6640  settings->htmlReportLineProgress += 1;
6641  rvapi_flush ( );
6642  }
6643 
6644  exit ( -1 );
6645  }
6646  if ( ( boxDimInIndices >= this->one->_maxMapU ) || ( boxDimInIndices >= this->one->_maxMapV ) || ( boxDimInIndices >= this->one->_maxMapW ) )
6647  {
6648  std::cerr << "!!! ProSHADE ERROR !!! The box size for fragmentation is too large, please decrease the box size so that it is smaller than the map dimmensions." << std::endl;
6649 
6650  if ( settings->htmlReport )
6651  {
6652  std::stringstream hlpSS;
6653  hlpSS << "<font color=\"red\">" << "The box size for fragmentation is too large, please decrease the box size so that it is smaller than the map dimmensions." << "</font>";
6654  rvapi_set_text ( hlpSS.str().c_str(),
6655  "ProgressSection",
6656  settings->htmlReportLineProgress,
6657  1,
6658  1,
6659  1 );
6660  settings->htmlReportLineProgress += 1;
6661  rvapi_flush ( );
6662  }
6663 
6664  exit ( -1 );
6665  }
6666 
6667  //======================================== Generate box starts and ends
6668  for ( unsigned int xStart = 0; xStart <= ( this->one->_maxMapU - boxDimInIndices ); xStart += ( boxDimInIndices / 2 ) )
6669  {
6670  hlpArrX[0] = xStart;
6671  hlpArrX[1] = xStart + boxDimInIndices;
6672 
6673  //==================================== Check for terminal boxes, they may need to have larger size
6674  if ( ( xStart + ( boxDimInIndices / 2 ) ) > ( this->one->_maxMapU - boxDimInIndices ) )
6675  {
6676  //================================ This is the last X
6677  hlpArrX[1] = this->one->_maxMapU;
6678  }
6679 
6680  for ( unsigned int yStart = 0; yStart <= ( this->one->_maxMapV - boxDimInIndices ); yStart += ( boxDimInIndices / 2 ) )
6681  {
6682  hlpArrY[0] = yStart;
6683  hlpArrY[1] = yStart + boxDimInIndices;
6684 
6685  //================================ Check for terminal boxes, they may need to have larger size
6686  if ( ( yStart + ( boxDimInIndices / 2 ) ) > ( this->one->_maxMapV - boxDimInIndices ) )
6687  {
6688  //============================ This is the last Y
6689  hlpArrY[1] = this->one->_maxMapV;
6690  }
6691 
6692  for ( unsigned int zStart = 0; zStart <= ( this->one->_maxMapW - boxDimInIndices ); zStart += ( boxDimInIndices / 2 ) )
6693  {
6694  hlpArrZ[0] = zStart;
6695  hlpArrZ[1] = zStart + boxDimInIndices;
6696 
6697  //============================ Check for terminal boxes, they may need to have larger size
6698  if ( ( zStart + ( boxDimInIndices / 2 ) ) > ( this->one->_maxMapW - boxDimInIndices ) )
6699  {
6700  //======================== This is the last Z
6701  hlpArrZ[1] = this->one->_maxMapW;
6702  }
6703 
6704  XDim.emplace_back ( hlpArrX );
6705  YDim.emplace_back ( hlpArrY );
6706  ZDim.emplace_back ( hlpArrZ );
6707  }
6708  }
6709  }
6710 
6711  if ( verbose > 2 )
6712  {
6713  std::cout << ">> Box borders generated." << std::endl;
6714  }
6715 
6716  //======================================== If the box has enough density, write it out!
6717  unsigned int noDensityPoints = 0;
6718  unsigned int arrayPos = 0;
6719  unsigned int hlpPos = 0;
6720  int fileIter = 0;
6721  double boxVolume = 0.0;
6722  int newU, newV, newW;
6723  std::string fileName;
6724 
6725  for ( unsigned int boxIt = 0; boxIt < static_cast<unsigned int> ( XDim.size() ); boxIt++ )
6726  {
6727  //==================================== Check the box density fraction
6728  noDensityPoints = 0;
6729  for ( unsigned int x = XDim.at(boxIt)[0]; x <= XDim.at(boxIt)[1]; x++ )
6730  {
6731  for ( unsigned int y = YDim.at(boxIt)[0]; y <= YDim.at(boxIt)[1]; y++ )
6732  {
6733  for ( unsigned int z = ZDim.at(boxIt)[0]; z <= ZDim.at(boxIt)[1]; z++ )
6734  {
6735  arrayPos = z + (this->one->_maxMapW+1) * ( y + (this->one->_maxMapV+1) * x );
6736 
6737  if ( this->one->_densityMapCor[arrayPos] > 0.0 )
6738  {
6739  noDensityPoints += 1;
6740  }
6741  }
6742  }
6743  }
6744 
6745  //==================================== If passing, write out the box
6746  boxVolume = ( ( XDim.at(boxIt)[1] - XDim.at(boxIt)[0] ) + 1 ) * ( ( YDim.at(boxIt)[1] - YDim.at(boxIt)[0] ) + 1 ) * ( ( ZDim.at(boxIt)[1] - ZDim.at(boxIt)[0] ) + 1 );
6747 
6748  if ( ( static_cast<double> ( noDensityPoints ) / boxVolume ) > this->mapFragBoxFraction )
6749  {
6750  //================================ Solve file names
6751  fileName = this->mapFragName + std::to_string ( fileIter ) + ".map";
6752  this->fragFiles.emplace_back ( fileName );
6753  fileIter += 1;
6754  if ( verbose > 3 )
6755  {
6756  std::cout << ">>>>> Writing out box " << fileIter-1 << std::endl;
6757  }
6758 
6759  //================================ Create map fragment
6760  float *boxMap = nullptr;
6761  boxMap = (float*) malloc ( (XDim.at(boxIt)[1]-XDim.at(boxIt)[0]+1) * (YDim.at(boxIt)[1]-YDim.at(boxIt)[0]+1) * (ZDim.at(boxIt)[1]-ZDim.at(boxIt)[0]+1) * sizeof ( float ) );
6762  if ( boxMap == nullptr )
6763  {
6764  std::cerr << "!!! ProSHADE ERROR !!! Cannot allocate memory for map data. Terminating... " << std::endl;
6765 
6766  if ( settings->htmlReport )
6767  {
6768  std::stringstream hlpSS;
6769  hlpSS << "<font color=\"red\">" << "Cannot allocate memory. Could you have run out of memory?" << "</font>";
6770  rvapi_set_text ( hlpSS.str().c_str(),
6771  "ProgressSection",
6772  settings->htmlReportLineProgress,
6773  1,
6774  1,
6775  1 );
6776  settings->htmlReportLineProgress += 1;
6777  rvapi_flush ( );
6778  }
6779 
6780  exit ( -1 );
6781  }
6782 
6783  for ( unsigned int x = XDim.at(boxIt)[0]; x <= XDim.at(boxIt)[1]; x++ )
6784  {
6785  for ( unsigned int y = YDim.at(boxIt)[0]; y <= YDim.at(boxIt)[1]; y++ )
6786  {
6787  for ( unsigned int z = ZDim.at(boxIt)[0]; z <= ZDim.at(boxIt)[1]; z++ )
6788  {
6789  arrayPos = z + (this->one->_maxMapW+1) * ( y + (this->one->_maxMapV+1) * x );
6790 
6791  newU = x - XDim.at(boxIt)[0];
6792  newV = y - YDim.at(boxIt)[0];
6793  newW = z - ZDim.at(boxIt)[0];
6794  hlpPos = newW + (ZDim.at(boxIt)[1]-ZDim.at(boxIt)[0]) * ( newV + (YDim.at(boxIt)[1]-YDim.at(boxIt)[0]) * newU );
6795 
6796  boxMap[hlpPos] = this->one->_densityMapCor[arrayPos];
6797  }
6798  }
6799  }
6800 
6801  float xFrom = XDim.at(boxIt)[0] + this->one->_xFrom;
6802  float xTo = XDim.at(boxIt)[1] + this->one->_xFrom - 1;
6803  float yFrom = YDim.at(boxIt)[0] + this->one->_yFrom;
6804  float yTo = YDim.at(boxIt)[1] + this->one->_yFrom - 1;
6805  float zFrom = ZDim.at(boxIt)[0] + this->one->_zFrom;
6806  float zTo = ZDim.at(boxIt)[1] + this->one->_zFrom - 1;
6807 
6808  this->one->writeMap ( fileName.c_str(),
6809  boxMap,
6810  axOrder,
6811  xFrom,
6812  yFrom,
6813  zFrom,
6814  xTo,
6815  yTo,
6816  zTo,
6817  ( this->one->_xSamplingRate * ( XDim.at(boxIt)[1] - XDim.at(boxIt)[0] ) ),
6818  ( this->one->_ySamplingRate * ( YDim.at(boxIt)[1] - YDim.at(boxIt)[0] ) ),
6819  ( this->one->_zSamplingRate * ( ZDim.at(boxIt)[1] - ZDim.at(boxIt)[0] ) ) );
6820 
6821  free ( boxMap );
6822  boxMap = nullptr;
6823  }
6824  }
6825 
6826  if ( verbose > 0 )
6827  {
6828  if ( fileIter > 0 )
6829  {
6830  std::cout << ">> " << fileIter << " boxes written in " << this->mapFragName << "xx ." << std::endl << std::endl;
6831  }
6832  else
6833  {
6834  std::cout << ">> No boxes conform to your criteria. NO BOXES WRITTEN." << std::endl << std::endl;
6835  }
6836  }
6837  if ( fileIter == 0 )
6838  {
6839  std::cout << "!!! ProSHADE WARNING !!! No map fragments produced - no box passed the required criteria." << std::endl << std::endl;
6840 
6841  if ( settings->htmlReport )
6842  {
6843  std::stringstream hlpSS;
6844  hlpSS << "<font color=\"orange\">" << "No map fragments produced - no box passed the required criteria.." << "</font>";
6845  rvapi_set_text ( hlpSS.str().c_str(),
6846  "ProgressSection",
6847  settings->htmlReportLineProgress,
6848  1,
6849  1,
6850  1 );
6851  settings->htmlReportLineProgress += 1;
6852  rvapi_flush ( );
6853  }
6854  }
6855 
6856  //======================================== Note that fragmentation was attempted
6857  this->fragFilesExist = true;
6858 
6859  //======================================== Done
6860  return ;
6861 
6862 }
6863 
6878  double *xTranslate,
6879  double *yTranslate,
6880  double *zTranslate )
6881 {
6882  //======================================== Initialise local variables
6883  ProSHADE_data* halfMap1 = new ProSHADE_data ();
6884  ProSHADE_data* halfMap2 = new ProSHADE_data ();
6885 
6886  double shSpacing1 = settings->shellSpacing;
6887  double shSpacing2 = settings->shellSpacing;
6888  unsigned int bandwidth1 = settings->bandwidth;
6889  unsigned int bandwidth2 = settings->bandwidth;
6890  unsigned int theta1 = settings->theta;
6891  unsigned int theta2 = settings->theta;
6892  unsigned int phi1 = settings->phi;
6893  unsigned int phi2 = settings->phi;
6894  unsigned int glInteg1 = settings->glIntegOrder;
6895  unsigned int glInteg2 = settings->glIntegOrder;
6896 
6897  //======================================== Read in the first half map
6898  halfMap1->getDensityMapFromMAP ( settings->structFiles.at(0),
6899  &shSpacing1,
6900  settings->mapResolution,
6901  &bandwidth1,
6902  &theta1,
6903  &phi1,
6904  &glInteg1,
6905  &settings->extraSpace,
6906  settings->mapResDefault,
6907  settings->rotChangeDefault,
6908  settings,
6909  settings->overlayDefaults );
6910 
6911  if ( settings->verbose > 0 )
6912  {
6913  std::cout << "Read in the first half map." << std::endl;
6914  }
6915 
6916  if ( settings->htmlReport )
6917  {
6918  std::stringstream hlpSS;
6919  hlpSS << "<font color=\"green\">" << "Read in the first half map." << "</font>";
6920  rvapi_set_text ( hlpSS.str().c_str(),
6921  "ProgressSection",
6922  settings->htmlReportLineProgress,
6923  1,
6924  1,
6925  1 );
6926  settings->htmlReportLineProgress += 1;
6927  rvapi_flush ( );
6928  }
6929 
6930  //======================================== Read in the second half map
6931  halfMap2->getDensityMapFromMAP ( settings->structFiles.at(1),
6932  &shSpacing2,
6933  settings->mapResolution,
6934  &bandwidth2,
6935  &theta2,
6936  &phi2,
6937  &glInteg2,
6938  &settings->extraSpace,
6939  settings->mapResDefault,
6940  settings->rotChangeDefault,
6941  settings,
6942  settings->overlayDefaults );
6943 
6944  if ( settings->verbose > 0 )
6945  {
6946  std::cout << "Read in the second half map." << std::endl;
6947  }
6948 
6949  if ( settings->htmlReport )
6950  {
6951  std::stringstream hlpSS;
6952  hlpSS << "<font color=\"green\">" << "Read in the second half map." << "</font>";
6953  rvapi_set_text ( hlpSS.str().c_str(),
6954  "ProgressSection",
6955  settings->htmlReportLineProgress,
6956  1,
6957  1,
6958  1 );
6959  settings->htmlReportLineProgress += 1;
6960  rvapi_flush ( );
6961  }
6962 
6963  //======================================== Size and sampling checks
6964  bool sizeAndSampleIdentical = true;
6965  if ( ( halfMap1->_xRange != halfMap2->_xRange ) || ( halfMap1->_yRange != halfMap2->_yRange ) || ( halfMap1->_zRange != halfMap2->_zRange ) )
6966  {
6967  std::cout << "!!! ProSHADE WARNING !!! The cell ranges differ between the two half maps - this is not allowed for half maps. Will attempt to re-size and re-sample the maps, but beware this may not be what you wanted. Please check the output manually." << std::endl;
6968 
6969  if ( settings->htmlReport )
6970  {
6971  std::stringstream hlpSS;
6972  hlpSS << "<font color=\"orange\">" << "The cell ranges differ between the two half maps - this is not allowed for half maps. Will attempt to re-size and re-sample the maps, but beware this may not be what you wanted. Please check the output manually." << "</font>";
6973  rvapi_set_text ( hlpSS.str().c_str(),
6974  "ProgressSection",
6975  settings->htmlReportLineProgress,
6976  1,
6977  1,
6978  1 );
6979  settings->htmlReportLineProgress += 1;
6980  rvapi_flush ( );
6981  }
6982 
6983  sizeAndSampleIdentical = false;
6984  }
6985 
6986  if ( ( halfMap1->_maxMapU != halfMap2->_maxMapU ) || ( halfMap1->_maxMapV != halfMap2->_maxMapV ) || ( halfMap1->_maxMapW != halfMap2->_maxMapW ) )
6987  {
6988  std::cout << "!!! ProSHADE WARNING !!! The cell dimensions differ between the two half maps - this is not allowed for half maps. Will attempt to re-size and re-sample the maps, but beware this may not be what you wanted. Please check the output manually." << std::endl;
6989 
6990  if ( settings->htmlReport )
6991  {
6992  std::stringstream hlpSS;
6993  hlpSS << "<font color=\"orange\">" << "The cell dimensions differ between the two half maps - this is not allowed for half maps. Will attempt to re-size and re-sample the maps, but beware this may not be what you wanted. Please check the output manually." << "</font>";
6994  rvapi_set_text ( hlpSS.str().c_str(),
6995  "ProgressSection",
6996  settings->htmlReportLineProgress,
6997  1,
6998  1,
6999  1 );
7000  settings->htmlReportLineProgress += 1;
7001  rvapi_flush ( );
7002  }
7003 
7004  sizeAndSampleIdentical = false;
7005  }
7006 
7007  if ( !sizeAndSampleIdentical )
7008  {
7009  if ( settings->verbose > 0 )
7010  {
7011  std::cout << "Starting the re-sampling and re-sizing procedure. This may take some time." << std::endl;
7012  }
7013 
7014  if ( settings->htmlReport )
7015  {
7016  std::stringstream hlpSS;
7017  hlpSS << "<font color=\"green\">" << "Starting the re-sampling and re-sizing procedure. This may take some time." << "</font>";
7018  rvapi_set_text ( hlpSS.str().c_str(),
7019  "ProgressSection",
7020  settings->htmlReportLineProgress,
7021  1,
7022  1,
7023  1 );
7024  settings->htmlReportLineProgress += 1;
7025  rvapi_flush ( );
7026  }
7027 
7028  //==================================== Copy from initial hoder to full holder
7029  halfMap1->_densityMapCor = new double[(halfMap1->_maxMapU+1)*(halfMap1->_maxMapV+1)*(halfMap1->_maxMapW+1)];
7030  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (halfMap1->_maxMapU+1)*(halfMap1->_maxMapV+1)*(halfMap1->_maxMapW+1) ); iter++ )
7031  {
7032  halfMap1->_densityMapCor[iter] = halfMap1->_densityMapMap[iter];
7033  }
7034  delete[] halfMap1->_densityMapMap;
7035  halfMap1->_densityMapMap = nullptr;
7036 
7037  halfMap2->_densityMapCor = new double[(halfMap2->_maxMapU+1)*(halfMap2->_maxMapV+1)*(halfMap2->_maxMapW+1)];
7038  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( (halfMap2->_maxMapU+1)*(halfMap2->_maxMapV+1)*(halfMap2->_maxMapW+1) ); iter++ )
7039  {
7040  halfMap2->_densityMapCor[iter] = halfMap2->_densityMapMap[iter];
7041  }
7042  delete[] halfMap2->_densityMapMap;
7043  halfMap2->_densityMapMap = nullptr;
7044 
7045  //==================================== Match sampling and sizes
7046  ProSHADE_comparePairwise* cmpObj = new ProSHADE_comparePairwise ( halfMap2,
7047  halfMap2,
7048  settings->mPower,
7049  settings->ignoreLs,
7050  std::max ( glInteg1, glInteg2 ),
7051  settings );
7052  std::array<double,4> translationVec;
7053  double xMapMov, yMapMov, zMapMov;
7054  ProSHADE_data str1Copy = ProSHADE_data ( halfMap1 );
7055  translationVec = cmpObj->getTranslationFunctionMap ( &str1Copy, halfMap2, &xMapMov, &yMapMov, &zMapMov );
7056  halfMap2->matchMap ( halfMap1 );
7057 
7058  delete cmpObj;
7059  }
7060 
7061  //======================================== Print headers of the input files
7062  if ( settings->htmlReport )
7063  {
7064  if ( sizeAndSampleIdentical )
7065  {
7066  rvapi_add_section ( "h1Header",
7067  "Half Map 1 Header",
7068  "body",
7069  settings->htmlReportLine,
7070  0,
7071  1,
7072  1,
7073  false );
7074  }
7075  else
7076  {
7077  rvapi_add_section ( "h1Header",
7078  "Half Map 1 Header (after re-sampling)",
7079  "body",
7080  settings->htmlReportLine,
7081  0,
7082  1,
7083  1,
7084  false );
7085  }
7086  settings->htmlReportLine += 1;
7087 
7088  //==================================== Print max U, V and W
7089  std::stringstream hlpSS;
7090  hlpSS << "<pre><b>" << "Rows, Columns and Sections sizes: " << "</b>";
7091  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7092  {
7093  hlpSS << ".";
7094  }
7095 
7096  int prec = 6;
7097  int UVWMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapU+1 ), prec ).length(),
7098  std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapV+1 ), prec ).length(),
7099  ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapW+1 ), prec ).length() ) );
7100  int FMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xFrom, prec ).length(),
7101  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yFrom, prec ).length(),
7102  ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zFrom, prec ).length() ) );
7103  int TMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xTo, prec ).length(),
7104  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yTo, prec ).length(),
7105  ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zTo, prec ).length() ) );
7106  int CDMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xRange, prec ).length(),
7107  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yRange, prec ).length(),
7108  ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zRange, prec ).length() ) );
7109  int spacer = std::max ( UVWMAX, std::max ( FMAX, std::max ( TMAX, CDMAX ) ) );
7110  if ( spacer < 5 ) { spacer = 5; }
7111 
7112  hlpSS << std::showpos << std::setprecision ( prec ) << " " << static_cast<int> ( halfMap1->_maxMapU+1 );
7113  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapU+1 ), prec ).length() ); iter++ )
7114  {
7115  hlpSS << " ";
7116  }
7117  hlpSS << " ";
7118 
7119  hlpSS << std::showpos << static_cast<int> ( halfMap1->_maxMapV+1 );
7120  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapV+1 ), prec ).length() ); iter++ )
7121  {
7122  hlpSS << " ";
7123  }
7124  hlpSS << " ";
7125 
7126  hlpSS << std::showpos << static_cast<int> ( halfMap1->_maxMapW+1 );
7127  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapW+1 ), prec ).length() ); iter++ )
7128  {
7129  hlpSS << " ";
7130  }
7131  hlpSS << "</pre>";
7132 
7133  rvapi_set_text ( hlpSS.str().c_str(),
7134  "h1Header",
7135  0,
7136  0,
7137  1,
7138  1 );
7139 
7140  //==================================== Print from and to lims
7141  hlpSS.str ( std::string ( ) );
7142  hlpSS << "<pre><b>" << "Start and stop points on columns, rows, sections: " << "</b>";
7143  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7144  {
7145  hlpSS << ".";
7146  }
7147 
7148  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap1->_xFrom;
7149  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xFrom, prec ).length() ); iter++ )
7150  {
7151  hlpSS << " ";
7152  }
7153  hlpSS << " ";
7154 
7155  hlpSS << std::showpos << halfMap1->_xTo;
7156  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xTo, prec ).length() ); iter++ )
7157  {
7158  hlpSS << " ";
7159  }
7160  hlpSS << " ";
7161 
7162  hlpSS << std::showpos << halfMap1->_yFrom;
7163  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yFrom, prec ).length() ); iter++ )
7164  {
7165  hlpSS << " ";
7166  }
7167  hlpSS << " ";
7168 
7169  hlpSS << std::showpos << halfMap1->_yTo;
7170  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yTo, prec ).length() ); iter++ )
7171  {
7172  hlpSS << " ";
7173  }
7174  hlpSS << " ";
7175 
7176  hlpSS << std::showpos << " " << halfMap1->_zFrom;
7177  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zFrom, prec ).length() ); iter++ )
7178  {
7179  hlpSS << " ";
7180  }
7181  hlpSS << " ";
7182 
7183  hlpSS << std::showpos << halfMap1->_zTo;
7184  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zTo, prec ).length() ); iter++ )
7185  {
7186  hlpSS << " ";
7187  }
7188  hlpSS << "</pre>";
7189 
7190  rvapi_set_text ( hlpSS.str().c_str(),
7191  "h1Header",
7192  1,
7193  0,
7194  1,
7195  1 );
7196 
7197  //==================================== Print cell dimensions
7198  hlpSS.str ( std::string ( ) );
7199  hlpSS << "<pre><b>" << "Cell dimensions (Angstrom): " << "</b>";
7200  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7201  {
7202  hlpSS << ".";
7203  }
7204 
7205  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap1->_xRange;
7206  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xRange, prec ).length() ); iter++ )
7207  {
7208  hlpSS << " ";
7209  }
7210  hlpSS << " ";
7211 
7212  hlpSS << std::showpos << halfMap1->_yRange;
7213  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yRange, prec ).length() ); iter++ )
7214  {
7215  hlpSS << " ";
7216  }
7217  hlpSS << " ";
7218 
7219  hlpSS << std::showpos << halfMap1->_zRange;
7220  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zRange, prec ).length() ); iter++ )
7221  {
7222  hlpSS << " ";
7223  }
7224  hlpSS << "</pre>";
7225 
7226  rvapi_set_text ( hlpSS.str().c_str(),
7227  "h1Header",
7228  2,
7229  0,
7230  1,
7231  1 );
7232 
7233  //==================================== Print cell dimensions
7234  hlpSS.str ( std::string ( ) );
7235  hlpSS << "<pre><b>" << "Cell angles (Degrees): " << "</b>";
7236  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7237  {
7238  hlpSS << ".";
7239  }
7240 
7241  hlpSS << std::showpos << std::setprecision ( prec ) << " " << 90.0;
7242  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
7243  {
7244  hlpSS << " ";
7245  }
7246  hlpSS << " ";
7247 
7248  hlpSS << std::showpos << 90.0;
7249  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
7250  {
7251  hlpSS << " ";
7252  }
7253  hlpSS << " ";
7254 
7255  hlpSS << std::showpos << 90.0;
7256  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
7257  {
7258  hlpSS << " ";
7259  }
7260  hlpSS << "</pre>";
7261 
7262  rvapi_set_text ( hlpSS.str().c_str(),
7263  "h1Header",
7264  3,
7265  0,
7266  1,
7267  1 );
7268 
7269  //==================================== Print cell dimensions
7270  hlpSS.str ( std::string ( ) );
7271  hlpSS << "<pre><b>" << "Fast, medium, slow axes: " << "</b>";
7272  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7273  {
7274  hlpSS << ".";
7275  }
7276 
7277  std::string hlpAO = settings->axisOrder;
7278  std::transform ( hlpAO.begin(), hlpAO.end(), hlpAO.begin(), ::toupper);
7279  hlpSS << " " << hlpAO;
7280  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
7281  {
7282  hlpSS << " ";
7283  }
7284  hlpSS << "</pre>";
7285 
7286  rvapi_set_text ( hlpSS.str().c_str(),
7287  "h1Header",
7288  4,
7289  0,
7290  1,
7291  1 );
7292 
7293  rvapi_flush ( );
7294  }
7295 
7296  if ( settings->htmlReport )
7297  {
7298  if ( sizeAndSampleIdentical )
7299  {
7300  rvapi_add_section ( "h2Header",
7301  "Half Map 2 Header",
7302  "body",
7303  settings->htmlReportLine,
7304  0,
7305  1,
7306  1,
7307  false );
7308  }
7309  else
7310  {
7311  rvapi_add_section ( "h2Header",
7312  "Half Map 2 Header (after re-sampling)",
7313  "body",
7314  settings->htmlReportLine,
7315  0,
7316  1,
7317  1,
7318  false );
7319  }
7320  settings->htmlReportLine += 1;
7321 
7322  //==================================== Print max U, V and W
7323  std::stringstream hlpSS;
7324  hlpSS << "<pre><b>" << "Rows, Columns and Sections sizes: " << "</b>";
7325  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7326  {
7327  hlpSS << ".";
7328  }
7329 
7330  int prec = 6;
7331  int UVWMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapU+1 ), prec ).length(),
7332  std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapV+1 ), prec ).length(),
7333  ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapW+1 ), prec ).length() ) );
7334  int FMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xFrom, prec ).length(),
7335  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yFrom, prec ).length(),
7336  ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zFrom, prec ).length() ) );
7337  int TMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xTo, prec ).length(),
7338  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yTo, prec ).length(),
7339  ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zTo, prec ).length() ) );
7340  int CDMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xRange, prec ).length(),
7341  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yRange, prec ).length(),
7342  ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zRange, prec ).length() ) );
7343  int spacer = std::max ( UVWMAX, std::max ( FMAX, std::max ( TMAX, CDMAX ) ) );
7344  if ( spacer < 5 ) { spacer = 5; }
7345 
7346  hlpSS << std::showpos << std::setprecision ( prec ) << " " << static_cast<int> ( halfMap2->_maxMapU+1 );
7347  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapU+1 ), prec ).length() ); iter++ )
7348  {
7349  hlpSS << " ";
7350  }
7351  hlpSS << " ";
7352 
7353  hlpSS << std::showpos << static_cast<int> ( halfMap2->_maxMapV+1 );
7354  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapV+1 ), prec ).length() ); iter++ )
7355  {
7356  hlpSS << " ";
7357  }
7358  hlpSS << " ";
7359 
7360  hlpSS << std::showpos << static_cast<int> ( halfMap2->_maxMapW+1 );
7361  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapW+1 ), prec ).length() ); iter++ )
7362  {
7363  hlpSS << " ";
7364  }
7365  hlpSS << "</pre>";
7366 
7367  rvapi_set_text ( hlpSS.str().c_str(),
7368  "h2Header",
7369  0,
7370  0,
7371  1,
7372  1 );
7373 
7374  //==================================== Print from and to lims
7375  hlpSS.str ( std::string ( ) );
7376  hlpSS << "<pre><b>" << "Start and stop points on columns, rows, sections: " << "</b>";
7377  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7378  {
7379  hlpSS << ".";
7380  }
7381 
7382  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap2->_xFrom;
7383  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xFrom, prec ).length() ); iter++ )
7384  {
7385  hlpSS << " ";
7386  }
7387  hlpSS << " ";
7388 
7389  hlpSS << std::showpos << halfMap2->_xTo;
7390  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xTo, prec ).length() ); iter++ )
7391  {
7392  hlpSS << " ";
7393  }
7394  hlpSS << " ";
7395 
7396  hlpSS << std::showpos << halfMap2->_yFrom;
7397  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yFrom, prec ).length() ); iter++ )
7398  {
7399  hlpSS << " ";
7400  }
7401  hlpSS << " ";
7402 
7403  hlpSS << std::showpos << halfMap2->_yTo;
7404  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yTo, prec ).length() ); iter++ )
7405  {
7406  hlpSS << " ";
7407  }
7408  hlpSS << " ";
7409 
7410  hlpSS << std::showpos << " " << halfMap2->_zFrom;
7411  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zFrom, prec ).length() ); iter++ )
7412  {
7413  hlpSS << " ";
7414  }
7415  hlpSS << " ";
7416 
7417  hlpSS << std::showpos << halfMap2->_zTo;
7418  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zTo, prec ).length() ); iter++ )
7419  {
7420  hlpSS << " ";
7421  }
7422  hlpSS << "</pre>";
7423 
7424  rvapi_set_text ( hlpSS.str().c_str(),
7425  "h2Header",
7426  1,
7427  0,
7428  1,
7429  1 );
7430 
7431  //==================================== Print cell dimensions
7432  hlpSS.str ( std::string ( ) );
7433  hlpSS << "<pre><b>" << "Cell dimensions (Angstrom): " << "</b>";
7434  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7435  {
7436  hlpSS << ".";
7437  }
7438 
7439  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap2->_xRange;
7440  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xRange, prec ).length() ); iter++ )
7441  {
7442  hlpSS << " ";
7443  }
7444  hlpSS << " ";
7445 
7446  hlpSS << std::showpos << halfMap2->_yRange;
7447  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yRange, prec ).length() ); iter++ )
7448  {
7449  hlpSS << " ";
7450  }
7451  hlpSS << " ";
7452 
7453  hlpSS << std::showpos << halfMap2->_zRange;
7454  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zRange, prec ).length() ); iter++ )
7455  {
7456  hlpSS << " ";
7457  }
7458  hlpSS << "</pre>";
7459 
7460  rvapi_set_text ( hlpSS.str().c_str(),
7461  "h2Header",
7462  2,
7463  0,
7464  1,
7465  1 );
7466 
7467  //==================================== Print cell dimensions
7468  hlpSS.str ( std::string ( ) );
7469  hlpSS << "<pre><b>" << "Cell angles (Degrees): " << "</b>";
7470  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7471  {
7472  hlpSS << ".";
7473  }
7474 
7475  hlpSS << std::showpos << std::setprecision ( prec ) << " " << 90.0;
7476  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
7477  {
7478  hlpSS << " ";
7479  }
7480  hlpSS << " ";
7481 
7482  hlpSS << std::showpos << 90.0;
7483  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
7484  {
7485  hlpSS << " ";
7486  }
7487  hlpSS << " ";
7488 
7489  hlpSS << std::showpos << 90.0;
7490  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
7491  {
7492  hlpSS << " ";
7493  }
7494  hlpSS << "</pre>";
7495 
7496  rvapi_set_text ( hlpSS.str().c_str(),
7497  "h2Header",
7498  3,
7499  0,
7500  1,
7501  1 );
7502 
7503  //==================================== Print cell dimensions
7504  hlpSS.str ( std::string ( ) );
7505  hlpSS << "<pre><b>" << "Fast, medium, slow axes: " << "</b>";
7506  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7507  {
7508  hlpSS << ".";
7509  }
7510 
7511  std::string hlpAO = settings->axisOrder;
7512  std::transform ( hlpAO.begin(), hlpAO.end(), hlpAO.begin(), ::toupper);
7513  hlpSS << " " << hlpAO;
7514  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
7515  {
7516  hlpSS << " ";
7517  }
7518  hlpSS << "</pre>";
7519 
7520  rvapi_set_text ( hlpSS.str().c_str(),
7521  "h2Header",
7522  4,
7523  0,
7524  1,
7525  1 );
7526 
7527  rvapi_flush ( );
7528  }
7529 
7530  //======================================== Initialise local variables for Fourier and Inverse Fourier
7531  fftw_complex *tmpOutA;
7532  fftw_complex *tmpInA;
7533  fftw_complex *tmpOutB;
7534  fftw_complex *tmpInB;
7535  fftw_plan pA;
7536  fftw_plan pB;
7537 
7538  int hlpU = halfMap1->_maxMapU + 1;
7539  int hlpV = halfMap1->_maxMapV + 1;
7540  int hlpW = halfMap1->_maxMapW + 1;
7541 
7542  //======================================== Allocate the memory
7543  tmpInA = new fftw_complex[hlpU * hlpV * hlpW];
7544  tmpOutA = new fftw_complex[hlpU * hlpV * hlpW];
7545  tmpInB = new fftw_complex[hlpU * hlpV * hlpW];
7546  tmpOutB = new fftw_complex[hlpU * hlpV * hlpW];
7547 
7548  //======================================== Create plans (FFTW_MEASURE would change the arrays)
7549  pA = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpInA, tmpOutA, FFTW_FORWARD, FFTW_ESTIMATE );
7550  pB = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, tmpInB, tmpOutB, FFTW_FORWARD, FFTW_ESTIMATE );
7551 
7552  //======================================== Load map data for Fourier
7553  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
7554  {
7555  if ( halfMap1->_densityMapCor[iter] == halfMap1->_densityMapCor[iter] )
7556  {
7557  //================================ Map value is NOT nan
7558  tmpInA[iter][0] = halfMap1->_densityMapCor[iter];
7559  tmpInA[iter][1] = 0.0;
7560  }
7561  else
7562  {
7563  //================================ Map value is nan - this sometimes occurs for a couple of values, I have no clue as to why...
7564  tmpInA[iter][0] = 0.0;
7565  tmpInA[iter][1] = 0.0;
7566  }
7567 
7568  if ( halfMap2->_densityMapCor[iter] == halfMap2->_densityMapCor[iter] )
7569  {
7570  //================================ Map value is NOT nan
7571  tmpInB[iter][0] = halfMap2->_densityMapCor[iter];
7572  tmpInB[iter][1] = 0.0;
7573  }
7574  else
7575  {
7576  //================================ Map value is nan - this sometimes occurs for a couple of values, I have no clue as to why...
7577  tmpInB[iter][0] = 0.0;
7578  tmpInB[iter][1] = 0.0;
7579  }
7580  }
7581 
7582  //======================================== Execute FFTs
7583  fftw_execute ( pA );
7584  fftw_execute ( pB );
7585  fftw_destroy_plan ( pA );
7586  fftw_destroy_plan ( pB );
7587 
7588  //======================================== Initialise the mask data structure
7589  fftw_complex* maskDataA = new fftw_complex [ hlpU * hlpV * hlpW ];
7590  fftw_complex* maskDataInvA = new fftw_complex [ hlpU * hlpV * hlpW ];
7591  fftw_complex* maskDataB = new fftw_complex [ hlpU * hlpV * hlpW ];
7592  fftw_complex* maskDataInvB = new fftw_complex [ hlpU * hlpV * hlpW ];
7593 
7594  //======================================== Initialise local variables
7595  int uIt, vIt, wIt;
7596  double real, imag;
7597  unsigned int arrayPos = 0;
7598  double normFactor = (hlpU * hlpV * hlpW);
7599  double bFacChange = settings->maskBlurFactor;
7600  int h, k, l;
7601  double mag, phase, S;
7602 
7603  //======================================== Prepare FFTW plan for mask FFTW
7604  fftw_plan pMaskInvA = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, maskDataInvA, maskDataA, FFTW_BACKWARD, FFTW_ESTIMATE );
7605  fftw_plan pMaskInvB = fftw_plan_dft_3d ( hlpU, hlpV, hlpW, maskDataInvB, maskDataB, FFTW_BACKWARD, FFTW_ESTIMATE );
7606 
7607  for ( uIt = 0; uIt < hlpU; uIt++ )
7608  {
7609  for ( vIt = 0; vIt < hlpV; vIt++ )
7610  {
7611  for ( wIt = 0; wIt < hlpW; wIt++ )
7612  {
7613  //============================ FOR MAP A
7614  // ... Var init
7615  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
7616  real = tmpOutA[arrayPos][0];
7617  imag = tmpOutA[arrayPos][1];
7618 
7619  // ... Change the B-factors, if required
7620  if ( uIt > (hlpU / 2) ) { h = uIt - hlpU; } else { h = uIt; }
7621  if ( vIt > (hlpV / 2) ) { k = vIt - hlpV; } else { k = vIt; }
7622  if ( wIt > (hlpW / 2) ) { l = wIt - hlpW; } else { l = wIt; }
7623 
7624  // ... Get magnitude and phase with mask parameters
7625  S = ( pow( static_cast<double> ( h ) / halfMap1->_xRange, 2.0 ) +
7626  pow( static_cast<double> ( k ) / halfMap1->_yRange, 2.0 ) +
7627  pow( static_cast<double> ( l ) / halfMap1->_zRange, 2.0 ) );
7628  mag = sqrt ( (real*real) + (imag*imag) ) * std::exp ( - ( ( bFacChange * S ) / 4.0 ) );
7629  phase = atan2 ( imag, real );
7630 
7631  // ... Save the mask data
7632  maskDataInvA[arrayPos][0] = ( mag * cos(phase) ) / normFactor;
7633  maskDataInvA[arrayPos][1] = ( mag * sin(phase) ) / normFactor;
7634 
7635  //============================ FOR MAP B
7636  // ... Var init
7637  real = tmpOutB[arrayPos][0];
7638  imag = tmpOutB[arrayPos][1];
7639 
7640  // ... Get magnitude and phase with mask parameters
7641  S = ( pow( static_cast<double> ( h ) / halfMap2->_xRange, 2.0 ) +
7642  pow( static_cast<double> ( k ) / halfMap2->_yRange, 2.0 ) +
7643  pow( static_cast<double> ( l ) / halfMap2->_zRange, 2.0 ) );
7644  mag = sqrt ( (real*real) + (imag*imag) ) * std::exp ( - ( ( bFacChange * S ) / 4.0 ) );
7645  phase = atan2 ( imag, real );
7646 
7647  // ... Save the mask data
7648  maskDataInvB[arrayPos][0] = ( mag * cos(phase) ) / normFactor;
7649  maskDataInvB[arrayPos][1] = ( mag * sin(phase) ) / normFactor;
7650  }
7651  }
7652  }
7653 
7654  //======================================== Execute the inversions
7655  fftw_execute ( pMaskInvA );
7656  fftw_execute ( pMaskInvB );
7657  fftw_destroy_plan ( pMaskInvA );
7658  fftw_destroy_plan ( pMaskInvB );
7659  delete[] maskDataInvA;
7660  delete[] maskDataInvB;
7661  delete[] tmpOutA;
7662  delete[] tmpOutB;
7663 
7664  if ( settings->verbose > 2 )
7665  {
7666  std::cout << ">>>>> Map blurring complete." << std::endl;
7667  }
7668 
7669  if ( settings->htmlReport )
7670  {
7671  std::stringstream hlpSS;
7672  hlpSS << "<font color=\"green\">" << "Map blurring complete." << "</font>";
7673  rvapi_set_text ( hlpSS.str().c_str(),
7674  "ProgressSection",
7675  settings->htmlReportLineProgress,
7676  1,
7677  1,
7678  1 );
7679  settings->htmlReportLineProgress += 1;
7680  rvapi_flush ( );
7681  }
7682 
7683  //======================================== Find mask threshold
7684  double mapThresholdPlusA = 0.0;
7685  double mapThresholdPlusB = 0.0;
7686  unsigned int hlpIt = 0;
7687  std::vector<double> maskValsA ( hlpU * hlpV * hlpW );
7688  std::vector<double> maskValsB ( hlpU * hlpV * hlpW );
7689 
7690  for ( uIt = 0; uIt < hlpU; uIt++ ) { for ( vIt = 0; vIt < hlpV; vIt++ ) { for ( wIt = 0; wIt < hlpW; wIt++ ) { arrayPos = wIt + hlpW * ( vIt + hlpV * uIt ); maskValsA.at(hlpIt) = maskDataA[arrayPos][0]; maskValsB.at(hlpIt) = maskDataB[arrayPos][0]; hlpIt += 1; } } }
7691 
7692  unsigned int medianPos = static_cast<unsigned int> ( maskValsA.size() / 2 );
7693  std::sort ( maskValsA.begin(), maskValsA.end() );
7694  std::sort ( maskValsB.begin(), maskValsB.end() );
7695 
7696  double interQuartileRangeA = maskValsA.at(medianPos+(medianPos/2)) - maskValsA.at(medianPos-(medianPos/2));
7697  mapThresholdPlusA = maskValsA.at(medianPos+(medianPos/2)) + ( interQuartileRangeA * settings->noIQRsFromMap );
7698 
7699  double interQuartileRangeB = maskValsB.at(medianPos+(medianPos/2)) - maskValsB.at(medianPos-(medianPos/2));
7700  mapThresholdPlusB = maskValsB.at(medianPos+(medianPos/2)) + ( interQuartileRangeB * settings->noIQRsFromMap );
7701 
7702  maskValsA.clear ( );
7703  maskValsB.clear ( );
7704 
7705  //======================================== Apply the mask
7706  for ( uIt = 0; uIt < hlpU; uIt++ )
7707  {
7708  for ( vIt = 0; vIt < hlpV; vIt++ )
7709  {
7710  for ( wIt = 0; wIt < hlpW; wIt++ )
7711  {
7712  //============================ Var init
7713  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
7714 
7715  //============================ Apply mask
7716  if ( mapThresholdPlusA >= maskDataA[arrayPos][0] )
7717  {
7718  tmpInA[arrayPos][0] = 0.0;
7719  }
7720  if ( mapThresholdPlusB >= maskDataB[arrayPos][0] )
7721  {
7722  tmpInB[arrayPos][0] = 0.0;
7723  }
7724  }
7725  }
7726  }
7727 
7728  //======================================== Free unnecessary memory
7729  delete[] maskDataA;
7730  delete[] maskDataB;
7731 
7732  if ( settings->htmlReport )
7733  {
7734  std::stringstream hlpSS;
7735  hlpSS << "<font color=\"green\">" << "Map masking complete." << "</font>";
7736  rvapi_set_text ( hlpSS.str().c_str(),
7737  "ProgressSection",
7738  settings->htmlReportLineProgress,
7739  1,
7740  1,
7741  1 );
7742  settings->htmlReportLineProgress += 1;
7743  rvapi_flush ( );
7744  }
7745 
7746 
7747  //======================================== Check for obvious errors
7748  bool atLeastSingleValueA = false;
7749  bool atLeastSingleValueB = false;
7750  for ( uIt = 0; uIt < hlpU; uIt++ )
7751  {
7752  for ( vIt = 0; vIt < hlpV; vIt++ )
7753  {
7754  for ( wIt = 0; wIt < hlpW; wIt++ )
7755  {
7756  //============================ Find current array pos
7757  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
7758 
7759  if ( !atLeastSingleValueA ) { if ( tmpInA[arrayPos][0] > 0.0 ) { atLeastSingleValueA = true; } }
7760  if ( !atLeastSingleValueB ) { if ( tmpInB[arrayPos][0] > 0.0 ) { atLeastSingleValueB = true; } }
7761  }
7762  }
7763  }
7764 
7765  if ( !atLeastSingleValueA || !atLeastSingleValueB )
7766  {
7767  printf ( "!!! ProSHADE ERROR !!! The masking procedure failed to detect any significant density in the map!\n" );
7768 
7769  if ( settings->htmlReport )
7770  {
7771  std::stringstream hlpSS;
7772  hlpSS << "<font color=\"red\">" << "The masking procedure failed to detect any significant density in the map. Please consider changing the blurring coefficient value." << "</font>";
7773  rvapi_set_text ( hlpSS.str().c_str(),
7774  "ProgressSection",
7775  settings->htmlReportLineProgress,
7776  1,
7777  1,
7778  1 );
7779  settings->htmlReportLineProgress += 1;
7780  rvapi_flush ( );
7781  }
7782 
7783  exit ( -1 );
7784  }
7785 
7786  //======================================== Determine the real size of the shape
7787  int maxX = 0;
7788  int minX = hlpU;
7789  int maxY = 0;
7790  int minY = hlpV;
7791  int maxZ = 0;
7792  int minZ = hlpW;
7793  int arrPos = 0;
7794 
7795  for ( uIt = 0; uIt < hlpU; uIt++ )
7796  {
7797  for ( vIt = 0; vIt < hlpV; vIt++ )
7798  {
7799  for ( wIt = 0; wIt < hlpW; wIt++ )
7800  {
7801  arrPos = wIt + hlpW * ( vIt + hlpV * uIt );
7802 
7803  if ( tmpInA[arrPos][0] > 0.0 )
7804  {
7805  maxX = std::max ( maxX, uIt );
7806  minX = std::min ( minX, uIt );
7807  maxY = std::max ( maxY, vIt );
7808  minY = std::min ( minY, vIt );
7809  maxZ = std::max ( maxZ, wIt );
7810  minZ = std::min ( minZ, wIt );
7811  }
7812  if ( tmpInB[arrPos][0] > 0.0 )
7813  {
7814  maxX = std::max ( maxX, uIt );
7815  minX = std::min ( minX, uIt );
7816  maxY = std::max ( maxY, vIt );
7817  minY = std::min ( minY, vIt );
7818  maxZ = std::max ( maxZ, wIt );
7819  minZ = std::min ( minZ, wIt );
7820  }
7821  }
7822  }
7823  }
7824 
7825  delete[] tmpInA;
7826  delete[] tmpInB;
7827 
7828  //======================================== Add 7.5+ angstroms to make sure inter-cell interactions do not occur
7829  maxX += std::ceil ( 7.5 / halfMap1->_xSamplingRate );
7830  maxY += std::ceil ( 7.5 / halfMap1->_ySamplingRate );
7831  maxZ += std::ceil ( 7.5 / halfMap1->_zSamplingRate );
7832  minX -= std::ceil ( 7.5 / halfMap1->_xSamplingRate );
7833  minY -= std::ceil ( 7.5 / halfMap1->_ySamplingRate );
7834  minZ -= std::ceil ( 7.5 / halfMap1->_zSamplingRate );
7835 
7836  if ( maxX > static_cast<int> ( halfMap1->_maxMapU ) ) { maxX = halfMap1->_maxMapU; }
7837  if ( maxY > static_cast<int> ( halfMap1->_maxMapV ) ) { maxY = halfMap1->_maxMapV; }
7838  if ( maxZ > static_cast<int> ( halfMap1->_maxMapW ) ) { maxZ = halfMap1->_maxMapW; }
7839  if ( minX < 0 ) { minX = 0; }
7840  if ( minY < 0 ) { minY = 0; }
7841  if ( minZ < 0 ) { minZ = 0; }
7842 
7843  //======================================== Make cube
7844  if ( settings->useCubicMaps )
7845  {
7846  minX = std::max ( 0, std::min ( minX, std::min ( minY, minZ ) ) );
7847  minY = std::max ( 0, std::min ( minX, std::min ( minY, minZ ) ) );
7848  minZ = std::max ( 0, std::min ( minX, std::min ( minY, minZ ) ) );
7849  maxX = std::min ( hlpU, std::max ( maxX , std::max ( maxY , maxZ ) ) );
7850  maxY = std::min ( hlpV, std::max ( maxX , std::max ( maxY , maxZ ) ) );
7851  maxZ = std::min ( hlpW, std::max ( maxX , std::max ( maxY , maxZ ) ) );
7852 
7853  if ( ( maxX != maxY ) || ( maxX != maxZ ) || ( maxY != maxZ ) )
7854  {
7855  std::cout << "!!! ProSHADE Warning !!! Although cubic map was requested, this cannot be done as the input is not cubic and cutting it to cubic would result in density being removed. Maps will not be cubic." << std::endl;
7856 
7857  if ( settings->htmlReport )
7858  {
7859  std::stringstream hlpSS;
7860  hlpSS << "<font color=\"orange\">" << "Although cubic map was requested, this cannot be done as the input is not cubic and cutting it to cubic would result in density being removed. Maps will not be cubic." << "</font>";
7861  rvapi_set_text ( hlpSS.str().c_str(),
7862  "ProgressSection",
7863  settings->htmlReportLineProgress,
7864  1,
7865  1,
7866  1 );
7867  settings->htmlReportLineProgress += 1;
7868  rvapi_flush ( );
7869  }
7870  }
7871  }
7872 
7873  //======================================== Create new maps
7874  int xDim = 1 + maxX - minX;
7875  int yDim = 1 + maxY - minY;
7876  int zDim = 1 + maxZ - minZ;
7877  int hlpPos = 0;
7878 
7879  double* newHalf1Map = new double[xDim * yDim * zDim];
7880  double* newHalf2Map = new double[xDim * yDim * zDim];
7881 
7882  for ( int xIt = 0; xIt < hlpU; xIt++ )
7883  {
7884  for ( int yIt = 0; yIt < hlpV; yIt++ )
7885  {
7886  for ( int zIt = 0; zIt < hlpW; zIt++ )
7887  {
7888  if ( ( xIt < minX ) || ( xIt > maxX ) ) { continue; }
7889  if ( ( yIt < minY ) || ( yIt > maxY ) ) { continue; }
7890  if ( ( zIt < minZ ) || ( zIt > maxZ ) ) { continue; }
7891 
7892  arrPos = zIt + hlpW * ( yIt + hlpV * xIt );
7893  hlpPos = (zIt - minZ) + zDim * ( (yIt - minY) + yDim * (xIt - minX) );
7894 
7895  newHalf1Map[hlpPos] = halfMap1->_densityMapCor[arrPos];
7896  newHalf2Map[hlpPos] = halfMap2->_densityMapCor[arrPos];
7897  }
7898  }
7899  }
7900 
7901  //======================================== Copy
7902  delete[] halfMap1->_densityMapCor;
7903  delete[] halfMap2->_densityMapCor;
7904  halfMap1->_densityMapCor = new double[xDim * yDim * zDim];
7905  halfMap2->_densityMapCor = new double[xDim * yDim * zDim];
7906  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( xDim * yDim * zDim ); iter++ )
7907  {
7908  halfMap1->_densityMapCor[iter] = newHalf1Map[iter];
7909  halfMap2->_densityMapCor[iter] = newHalf2Map[iter];
7910  }
7911  delete[] newHalf1Map;
7912  delete[] newHalf2Map;
7913 
7914  if ( settings->htmlReport )
7915  {
7916  std::stringstream hlpSS;
7917  hlpSS << "<font color=\"green\">" << "Half maps re-boxed." << "</font>";
7918  rvapi_set_text ( hlpSS.str().c_str(),
7919  "ProgressSection",
7920  settings->htmlReportLineProgress,
7921  1,
7922  1,
7923  1 );
7924  settings->htmlReportLineProgress += 1;
7925  rvapi_flush ( );
7926  }
7927 
7928  //======================================== Set object headers
7929  int oDimX1 = halfMap1->_maxMapU;
7930  int oDimY1 = halfMap1->_maxMapV;
7931  int oDimZ1 = halfMap1->_maxMapW;
7932 
7933  int oDimX2 = halfMap2->_maxMapU;
7934  int oDimY2 = halfMap2->_maxMapV;
7935  int oDimZ2 = halfMap2->_maxMapW;
7936 
7937  halfMap1->_maxMapU = xDim;
7938  halfMap1->_maxMapV = yDim;
7939  halfMap1->_maxMapW = zDim;
7940 
7941  halfMap1->_xTo = maxX + halfMap1->_xFrom;
7942  halfMap1->_yTo = maxY + halfMap1->_yFrom;
7943  halfMap1->_zTo = maxZ + halfMap1->_zFrom;
7944 
7945  halfMap1->_xFrom = minX + halfMap1->_xFrom;
7946  halfMap1->_yFrom = minY + halfMap1->_yFrom;
7947  halfMap1->_zFrom = minZ + halfMap1->_zFrom;
7948 
7949  halfMap1->_xRange = xDim * halfMap1->_xSamplingRate;
7950  halfMap1->_yRange = yDim * halfMap1->_ySamplingRate;
7951  halfMap1->_zRange = zDim * halfMap1->_zSamplingRate;
7952 
7953  halfMap2->_maxMapU = xDim;
7954  halfMap2->_maxMapV = yDim;
7955  halfMap2->_maxMapW = zDim;
7956 
7957  halfMap2->_xTo = maxX + halfMap2->_xFrom;
7958  halfMap2->_yTo = maxY + halfMap2->_yFrom;
7959  halfMap2->_zTo = maxZ + halfMap2->_zFrom;
7960 
7961  halfMap2->_xFrom = minX + halfMap2->_xFrom;
7962  halfMap2->_yFrom = minY + halfMap2->_yFrom;
7963  halfMap2->_zFrom = minZ + halfMap2->_zFrom;
7964 
7965  halfMap2->_xRange = xDim * halfMap2->_xSamplingRate;
7966  halfMap2->_yRange = yDim * halfMap2->_ySamplingRate;
7967  halfMap2->_zRange = zDim * halfMap2->_zSamplingRate;
7968 
7969  //======================================== Print headers of the output files
7970  if ( settings->htmlReport )
7971  {
7972  rvapi_add_section ( "h1OutHeader",
7973  "Half Map 1 Re-boxed Header",
7974  "body",
7975  settings->htmlReportLine,
7976  0,
7977  1,
7978  1,
7979  false );
7980  settings->htmlReportLine += 1;
7981 
7982  //==================================== Print max U, V and W
7983  std::stringstream hlpSS;
7984  hlpSS << "<pre><b>" << "Rows, Columns and Sections sizes: " << "</b>";
7985  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
7986  {
7987  hlpSS << ".";
7988  }
7989 
7990  int prec = 6;
7991  int UVWMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapU+1 ), prec ).length(),
7992  std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapV+1 ), prec ).length(),
7993  ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapW+1 ), prec ).length() ) );
7994  int FMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xFrom, prec ).length(),
7995  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yFrom, prec ).length(),
7996  ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zFrom, prec ).length() ) );
7997  int TMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xTo, prec ).length(),
7998  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yTo, prec ).length(),
7999  ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zTo, prec ).length() ) );
8000  int CDMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xRange, prec ).length(),
8001  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yRange, prec ).length(),
8002  ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zRange, prec ).length() ) );
8003  int spacer = std::max ( UVWMAX, std::max ( FMAX, std::max ( TMAX, CDMAX ) ) );
8004  if ( spacer < 5 ) { spacer = 5; }
8005 
8006  hlpSS << std::showpos << std::setprecision ( prec ) << " " << static_cast<int> ( halfMap1->_maxMapU+1 );
8007  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapU+1 ), prec ).length() ); iter++ )
8008  {
8009  hlpSS << " ";
8010  }
8011  hlpSS << " ";
8012 
8013  hlpSS << std::showpos << static_cast<int> ( halfMap1->_maxMapV+1 );
8014  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapV+1 ), prec ).length() ); iter++ )
8015  {
8016  hlpSS << " ";
8017  }
8018  hlpSS << " ";
8019 
8020  hlpSS << std::showpos << static_cast<int> ( halfMap1->_maxMapW+1 );
8021  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap1->_maxMapW+1 ), prec ).length() ); iter++ )
8022  {
8023  hlpSS << " ";
8024  }
8025  hlpSS << "</pre>";
8026 
8027  rvapi_set_text ( hlpSS.str().c_str(),
8028  "h1OutHeader",
8029  0,
8030  0,
8031  1,
8032  1 );
8033 
8034  //==================================== Print from and to lims
8035  hlpSS.str ( std::string ( ) );
8036  hlpSS << "<pre><b>" << "Start and stop points on columns, rows, sections: " << "</b>";
8037  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8038  {
8039  hlpSS << ".";
8040  }
8041 
8042  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap1->_xFrom;
8043  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xFrom, prec ).length() ); iter++ )
8044  {
8045  hlpSS << " ";
8046  }
8047  hlpSS << " ";
8048 
8049  hlpSS << std::showpos << halfMap1->_xTo;
8050  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xTo, prec ).length() ); iter++ )
8051  {
8052  hlpSS << " ";
8053  }
8054  hlpSS << " ";
8055 
8056  hlpSS << std::showpos << halfMap1->_yFrom;
8057  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yFrom, prec ).length() ); iter++ )
8058  {
8059  hlpSS << " ";
8060  }
8061  hlpSS << " ";
8062 
8063  hlpSS << std::showpos << halfMap1->_yTo;
8064  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yTo, prec ).length() ); iter++ )
8065  {
8066  hlpSS << " ";
8067  }
8068  hlpSS << " ";
8069 
8070  hlpSS << std::showpos << " " << halfMap1->_zFrom;
8071  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zFrom, prec ).length() ); iter++ )
8072  {
8073  hlpSS << " ";
8074  }
8075  hlpSS << " ";
8076 
8077  hlpSS << std::showpos << halfMap1->_zTo;
8078  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zTo, prec ).length() ); iter++ )
8079  {
8080  hlpSS << " ";
8081  }
8082  hlpSS << "</pre>";
8083 
8084  rvapi_set_text ( hlpSS.str().c_str(),
8085  "h1OutHeader",
8086  1,
8087  0,
8088  1,
8089  1 );
8090 
8091  //==================================== Print cell dimensions
8092  hlpSS.str ( std::string ( ) );
8093  hlpSS << "<pre><b>" << "Cell dimensions (Angstrom): " << "</b>";
8094  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8095  {
8096  hlpSS << ".";
8097  }
8098 
8099  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap1->_xRange;
8100  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_xRange, prec ).length() ); iter++ )
8101  {
8102  hlpSS << " ";
8103  }
8104  hlpSS << " ";
8105 
8106  hlpSS << std::showpos << halfMap1->_yRange;
8107  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_yRange, prec ).length() ); iter++ )
8108  {
8109  hlpSS << " ";
8110  }
8111  hlpSS << " ";
8112 
8113  hlpSS << std::showpos << halfMap1->_zRange;
8114  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap1->_zRange, prec ).length() ); iter++ )
8115  {
8116  hlpSS << " ";
8117  }
8118  hlpSS << "</pre>";
8119 
8120  rvapi_set_text ( hlpSS.str().c_str(),
8121  "h1OutHeader",
8122  2,
8123  0,
8124  1,
8125  1 );
8126 
8127  //==================================== Print cell dimensions
8128  hlpSS.str ( std::string ( ) );
8129  hlpSS << "<pre><b>" << "Cell angles (Degrees): " << "</b>";
8130  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8131  {
8132  hlpSS << ".";
8133  }
8134 
8135  hlpSS << std::showpos << std::setprecision ( prec ) << " " << 90.0;
8136  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
8137  {
8138  hlpSS << " ";
8139  }
8140  hlpSS << " ";
8141 
8142  hlpSS << std::showpos << 90.0;
8143  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
8144  {
8145  hlpSS << " ";
8146  }
8147  hlpSS << " ";
8148 
8149  hlpSS << std::showpos << 90.0;
8150  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
8151  {
8152  hlpSS << " ";
8153  }
8154  hlpSS << "</pre>";
8155 
8156  rvapi_set_text ( hlpSS.str().c_str(),
8157  "h1OutHeader",
8158  3,
8159  0,
8160  1,
8161  1 );
8162 
8163  //==================================== Print cell dimensions
8164  hlpSS.str ( std::string ( ) );
8165  hlpSS << "<pre><b>" << "Fast, medium, slow axes: " << "</b>";
8166  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8167  {
8168  hlpSS << ".";
8169  }
8170 
8171  std::string hlpAO = settings->axisOrder;
8172  std::transform ( hlpAO.begin(), hlpAO.end(), hlpAO.begin(), ::toupper);
8173  hlpSS << " " << hlpAO;
8174  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
8175  {
8176  hlpSS << " ";
8177  }
8178  hlpSS << "</pre>";
8179 
8180  rvapi_set_text ( hlpSS.str().c_str(),
8181  "h1OutHeader",
8182  4,
8183  0,
8184  1,
8185  1 );
8186 
8187  rvapi_flush ( );
8188  }
8189 
8190  if ( settings->htmlReport )
8191  {
8192  rvapi_add_section ( "h2OutHeader",
8193  "Half Map 2 Re-boxed Header",
8194  "body",
8195  settings->htmlReportLine,
8196  0,
8197  1,
8198  1,
8199  false );
8200  settings->htmlReportLine += 1;
8201 
8202  //==================================== Print max U, V and W
8203  std::stringstream hlpSS;
8204  hlpSS << "<pre><b>" << "Rows, Columns and Sections sizes: " << "</b>";
8205  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8206  {
8207  hlpSS << ".";
8208  }
8209 
8210  int prec = 6;
8211  int UVWMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapU+1 ), prec ).length(),
8212  std::max ( ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapV+1 ), prec ).length(),
8213  ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapW+1 ), prec ).length() ) );
8214  int FMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xFrom, prec ).length(),
8215  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yFrom, prec ).length(),
8216  ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zFrom, prec ).length() ) );
8217  int TMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xTo, prec ).length(),
8218  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yTo, prec ).length(),
8219  ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zTo, prec ).length() ) );
8220  int CDMAX = std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xRange, prec ).length(),
8221  std::max ( ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yRange, prec ).length(),
8222  ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zRange, prec ).length() ) );
8223  int spacer = std::max ( UVWMAX, std::max ( FMAX, std::max ( TMAX, CDMAX ) ) );
8224  if ( spacer < 5 ) { spacer = 5; }
8225 
8226  hlpSS << std::showpos << std::setprecision ( prec ) << " " << static_cast<int> ( halfMap2->_maxMapU+1 );
8227  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapU+1 ), prec ).length() ); iter++ )
8228  {
8229  hlpSS << " ";
8230  }
8231  hlpSS << " ";
8232 
8233  hlpSS << std::showpos << static_cast<int> ( halfMap2->_maxMapV+1 );
8234  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapV+1 ), prec ).length() ); iter++ )
8235  {
8236  hlpSS << " ";
8237  }
8238  hlpSS << " ";
8239 
8240  hlpSS << std::showpos << static_cast<int> ( halfMap2->_maxMapW+1 );
8241  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( static_cast<int> ( halfMap2->_maxMapW+1 ), prec ).length() ); iter++ )
8242  {
8243  hlpSS << " ";
8244  }
8245  hlpSS << "</pre>";
8246 
8247  rvapi_set_text ( hlpSS.str().c_str(),
8248  "h2OutHeader",
8249  0,
8250  0,
8251  1,
8252  1 );
8253 
8254  //==================================== Print from and to lims
8255  hlpSS.str ( std::string ( ) );
8256  hlpSS << "<pre><b>" << "Start and stop points on columns, rows, sections: " << "</b>";
8257  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8258  {
8259  hlpSS << ".";
8260  }
8261 
8262  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap2->_xFrom;
8263  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xFrom, prec ).length() ); iter++ )
8264  {
8265  hlpSS << " ";
8266  }
8267  hlpSS << " ";
8268 
8269  hlpSS << std::showpos << halfMap2->_xTo;
8270  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xTo, prec ).length() ); iter++ )
8271  {
8272  hlpSS << " ";
8273  }
8274  hlpSS << " ";
8275 
8276  hlpSS << std::showpos << halfMap2->_yFrom;
8277  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yFrom, prec ).length() ); iter++ )
8278  {
8279  hlpSS << " ";
8280  }
8281  hlpSS << " ";
8282 
8283  hlpSS << std::showpos << halfMap2->_yTo;
8284  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yTo, prec ).length() ); iter++ )
8285  {
8286  hlpSS << " ";
8287  }
8288  hlpSS << " ";
8289 
8290  hlpSS << std::showpos << " " << halfMap2->_zFrom;
8291  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zFrom, prec ).length() ); iter++ )
8292  {
8293  hlpSS << " ";
8294  }
8295  hlpSS << " ";
8296 
8297  hlpSS << std::showpos << halfMap2->_zTo;
8298  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zTo, prec ).length() ); iter++ )
8299  {
8300  hlpSS << " ";
8301  }
8302  hlpSS << "</pre>";
8303 
8304  rvapi_set_text ( hlpSS.str().c_str(),
8305  "h2OutHeader",
8306  1,
8307  0,
8308  1,
8309  1 );
8310 
8311  //==================================== Print cell dimensions
8312  hlpSS.str ( std::string ( ) );
8313  hlpSS << "<pre><b>" << "Cell dimensions (Angstrom): " << "</b>";
8314  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8315  {
8316  hlpSS << ".";
8317  }
8318 
8319  hlpSS << std::showpos << std::setprecision ( prec ) << " " << halfMap2->_xRange;
8320  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_xRange, prec ).length() ); iter++ )
8321  {
8322  hlpSS << " ";
8323  }
8324  hlpSS << " ";
8325 
8326  hlpSS << std::showpos << halfMap2->_yRange;
8327  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_yRange, prec ).length() ); iter++ )
8328  {
8329  hlpSS << " ";
8330  }
8331  hlpSS << " ";
8332 
8333  hlpSS << std::showpos << halfMap2->_zRange;
8334  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( halfMap2->_zRange, prec ).length() ); iter++ )
8335  {
8336  hlpSS << " ";
8337  }
8338  hlpSS << "</pre>";
8339 
8340  rvapi_set_text ( hlpSS.str().c_str(),
8341  "h2OutHeader",
8342  2,
8343  0,
8344  1,
8345  1 );
8346 
8347  //==================================== Print cell dimensions
8348  hlpSS.str ( std::string ( ) );
8349  hlpSS << "<pre><b>" << "Cell angles (Degrees): " << "</b>";
8350  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8351  {
8352  hlpSS << ".";
8353  }
8354 
8355  hlpSS << std::showpos << std::setprecision ( prec ) << " " << 90.0;
8356  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
8357  {
8358  hlpSS << " ";
8359  }
8360  hlpSS << " ";
8361 
8362  hlpSS << std::showpos << 90.0;
8363  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
8364  {
8365  hlpSS << " ";
8366  }
8367  hlpSS << " ";
8368 
8369  hlpSS << std::showpos << 90.0;
8370  for ( int iter = 0; iter < static_cast<int> ( spacer - ProSHADE_internal_misc::to_string_with_precision ( 90.0, prec ).length() ); iter++ )
8371  {
8372  hlpSS << " ";
8373  }
8374  hlpSS << "</pre>";
8375 
8376  rvapi_set_text ( hlpSS.str().c_str(),
8377  "h2OutHeader",
8378  3,
8379  0,
8380  1,
8381  1 );
8382 
8383  //==================================== Print cell dimensions
8384  hlpSS.str ( std::string ( ) );
8385  hlpSS << "<pre><b>" << "Fast, medium, slow axes: " << "</b>";
8386  for ( int iter = static_cast<int> ( hlpSS.str().length() ); iter < 70; iter++ )
8387  {
8388  hlpSS << ".";
8389  }
8390 
8391  std::string hlpAO = settings->axisOrder;
8392  std::transform ( hlpAO.begin(), hlpAO.end(), hlpAO.begin(), ::toupper);
8393  hlpSS << " " << hlpAO;
8394  for ( int iter = 0; iter < static_cast<int> ( spacer - 1 ); iter++ )
8395  {
8396  hlpSS << " ";
8397  }
8398  hlpSS << "</pre>";
8399 
8400  rvapi_set_text ( hlpSS.str().c_str(),
8401  "h2OutHeader",
8402  4,
8403  0,
8404  1,
8405  1 );
8406 
8407  rvapi_flush ( );
8408  }
8409 
8410  //======================================== Write out the re-boxed half maps
8411  std::stringstream ss;
8412  ss << settings->clearMapFile << "_half1.map";
8413  halfMap1->writeMap ( ss.str(), halfMap1->_densityMapCor );
8414 
8415  ss.str( std::string ( ) );
8416  ss << settings->clearMapFile << "_half2.map";
8417  halfMap2->writeMap ( ss.str(), halfMap2->_densityMapCor );
8418 
8419  if ( settings->htmlReport )
8420  {
8421  std::stringstream hlpSS;
8422  hlpSS << "<font color=\"green\">" << "Half maps saved." << "</font>";
8423  rvapi_set_text ( hlpSS.str().c_str(),
8424  "ProgressSection",
8425  settings->htmlReportLineProgress,
8426  1,
8427  1,
8428  1 );
8429  settings->htmlReportLineProgress += 1;
8430  rvapi_flush ( );
8431  }
8432 
8433  if ( settings->htmlReport )
8434  {
8435  rvapi_add_section ( "ResultsSection",
8436  "Results",
8437  "body",
8438  settings->htmlReportLine,
8439  0,
8440  1,
8441  1,
8442  true );
8443  settings->htmlReportLine += 1;
8444 
8445  std::stringstream hlpSS;
8446  hlpSS << "<pre><b>" << "The re-boxed structures are available at: </b>" << settings->clearMapFile << "_half1.map" << "</pre>";
8447  rvapi_set_text ( hlpSS.str().c_str(),
8448  "ResultsSection",
8449  0,
8450  0,
8451  1,
8452  1 );
8453 
8454  hlpSS.str ( std::string ( ) );
8455  hlpSS << "<pre><b>" << " ... and : </b>" << settings->clearMapFile << "_half2.map" << "</pre>";
8456  rvapi_set_text ( hlpSS.str().c_str(),
8457  "ResultsSection",
8458  1,
8459  0,
8460  1,
8461  1 );
8462 
8463  hlpSS.str ( std::string ( ) );
8464  hlpSS << "<pre><b>" << "Original structure dims: </b>" << oDimX1+1 << " x " << oDimY1+1 << " x " << oDimZ1+1 << "</pre>";
8465  rvapi_set_text ( hlpSS.str().c_str(),
8466  "ResultsSection",
8467  2,
8468  0,
8469  1,
8470  1 );
8471 
8472  hlpSS.str ( std::string ( ) );
8473  hlpSS << "<pre><b>" << " ... and : </b>" << oDimX2+1 << " x " << oDimY2+1 << " x " << oDimZ2+1 << "</pre>";
8474  rvapi_set_text ( hlpSS.str().c_str(),
8475  "ResultsSection",
8476  3,
8477  0,
8478  1,
8479  1 );
8480 
8481  hlpSS.str ( std::string ( ) );
8482  hlpSS << "<pre><b>" << "Re-boxed structure dims: </b>" << halfMap1->_maxMapU << " x " << halfMap1->_maxMapV << " x " << halfMap1->_maxMapW << "</pre>";
8483  rvapi_set_text ( hlpSS.str().c_str(),
8484  "ResultsSection",
8485  4,
8486  0,
8487  1,
8488  1 );
8489 
8490  hlpSS.str ( std::string ( ) );
8491  hlpSS << "<pre><b>" << " ... and : </b>" << halfMap2->_maxMapU << " x " << halfMap2->_maxMapV << " x " << halfMap2->_maxMapW << "</pre>";
8492  rvapi_set_text ( hlpSS.str().c_str(),
8493  "ResultsSection",
8494  5,
8495  0,
8496  1,
8497  1 );
8498 
8499  hlpSS.str ( std::string ( ) );
8500  hlpSS << "<pre><b>" << "New volume as percentage of old volume: </b>" << ProSHADE_internal_misc::to_string_with_precision ( ( static_cast<double> ( (halfMap1->_maxMapU+1) * (halfMap1->_maxMapV+1) * (halfMap1->_maxMapW+1) ) / static_cast<double> ( (oDimX1+1) * (oDimY1+1) * (oDimZ1+1) ) ) * 100 ) << " %</pre>";
8501  rvapi_set_text ( hlpSS.str().c_str(),
8502  "ResultsSection",
8503  6,
8504  0,
8505  1,
8506  1 );
8507 
8508  hlpSS.str ( std::string ( ) );
8509  hlpSS << "<pre><b>" << "Linear processing speed-up: </b>" << ProSHADE_internal_misc::to_string_with_precision ( ( ( (oDimX1+1) * (oDimY1+1) * (oDimZ1+1) ) / ( (halfMap1->_maxMapU+1) * (halfMap1->_maxMapV+1) * (halfMap1->_maxMapW+1) ) ) - 1.0 ) << " times</pre>";
8510  rvapi_set_text ( hlpSS.str().c_str(),
8511  "ResultsSection",
8512  7,
8513  0,
8514  1,
8515  1 );
8516 
8517  rvapi_flush ( );
8518  }
8519 
8520  //======================================== Release memory
8521  delete halfMap1;
8522  delete halfMap2;
8523 
8524  //======================================== Done
8525  return ;
8526 
8527 }
8528 
8543 std::vector<ProSHADE_internal::ProSHADE_data*> ProSHADE_internal::ProSHADE_data::fragmentMap ( ProSHADE::ProSHADE_settings* settings,
8544  bool userCOM )
8545 {
8546  //======================================== Sanity check
8547  if ( !this->_densityMapComputed )
8548  {
8549  std::cerr << "!!! ProSHADE ERROR !!! Tried to fragment map without first computing it. Terminating..." << std::endl;
8550 
8551  if ( settings->htmlReport )
8552  {
8553  std::stringstream hlpSS;
8554  hlpSS << "<font color=\"red\">" << "Tried to fragment map without first computing it. This looks like an internal bug - please report this case." << "</font>";
8555  rvapi_set_text ( hlpSS.str().c_str(),
8556  "ProgressSection",
8557  settings->htmlReportLineProgress,
8558  1,
8559  1,
8560  1 );
8561  settings->htmlReportLineProgress += 1;
8562  rvapi_flush ( );
8563  }
8564 
8565  exit ( -1 );
8566  }
8567 
8568  if ( settings->verbose > 1 )
8569  {
8570  std::cout << ">> Fragmenting map." << std::endl;
8571  }
8572 
8573  //======================================== Initialise local variables
8574  std::vector<ProSHADE_data*> ret;
8575  std::vector< std::array<unsigned int,2> > XDim;
8576  std::vector< std::array<unsigned int,2> > YDim;
8577  std::vector< std::array<unsigned int,2> > ZDim;
8578  std::array<unsigned int,2> hlpArrX;
8579  std::array<unsigned int,2> hlpArrY;
8580  std::array<unsigned int,2> hlpArrZ;
8581  double maxMapAngPerIndex = std::max ( this->_xRange / static_cast<double> ( this->_maxMapU ),
8582  std::max ( this->_yRange / static_cast<double> ( this->_maxMapV ),
8583  this->_zRange / static_cast<double> ( this->_maxMapW ) ) );
8584 
8585  unsigned int boxDimInIndices = static_cast<unsigned int> ( std::round ( settings->mapFragBoxSize / maxMapAngPerIndex ) );
8586  if ( ( boxDimInIndices % 2 ) == 1 )
8587  {
8588  //==================================== If odd, change to even
8589  boxDimInIndices += 1;
8590  }
8591 
8592  //======================================== Problem! The box is too small
8593  if ( boxDimInIndices < 2 )
8594  {
8595  std::cerr << "!!! ProSHADE ERROR !!! The box size for fragmentation is too small, please increase the box size or submit more detailed map. (Increasing the number of points by interpolation could work without changing the map here...)" << std::endl;
8596 
8597  if ( settings->htmlReport )
8598  {
8599  std::stringstream hlpSS;
8600  hlpSS << "<font color=\"red\">" << "The box size for fragmentation is too small, please increase the box size or submit more detailed map. (Increasing the number of points by interpolation could work without changing the map here...)." << "</font>";
8601  rvapi_set_text ( hlpSS.str().c_str(),
8602  "ProgressSection",
8603  settings->htmlReportLineProgress,
8604  1,
8605  1,
8606  1 );
8607  settings->htmlReportLineProgress += 1;
8608  rvapi_flush ( );
8609  }
8610 
8611  exit ( -1 );
8612  }
8613  if ( ( boxDimInIndices >= this->_maxMapU ) || ( boxDimInIndices >= this->_maxMapV ) || ( boxDimInIndices >= this->_maxMapW ) )
8614  {
8615  std::cerr << "!!! ProSHADE ERROR !!! The box size for fragmentation is too large, please decrease the box size so that it is smaller than the clearmap dimmensions." << std::endl;
8616 
8617  if ( settings->htmlReport )
8618  {
8619  std::stringstream hlpSS;
8620  hlpSS << "<font color=\"red\">" << "The box size for fragmentation is too large, please decrease the box size so that it is smaller than the map dimmensions." << "</font>";
8621  rvapi_set_text ( hlpSS.str().c_str(),
8622  "ProgressSection",
8623  settings->htmlReportLineProgress,
8624  1,
8625  1,
8626  1 );
8627  settings->htmlReportLineProgress += 1;
8628  rvapi_flush ( );
8629  }
8630 
8631  exit ( -1 );
8632  }
8633  if ( settings->verbose > 3 )
8634  {
8635  std::cout << ">>>>>>>> Sanity checks passed." << std::endl;
8636  }
8637 
8638  //======================================== Generate box starts and ends
8639  for ( unsigned int xStart = 0; xStart <= ( this->_maxMapU - boxDimInIndices ); xStart += ( boxDimInIndices / 2 ) )
8640  {
8641  hlpArrX[0] = xStart;
8642  hlpArrX[1] = xStart + boxDimInIndices;
8643 
8644  //==================================== Check for terminal boxes, they may need to have larger size
8645  if ( ( xStart + ( boxDimInIndices / 2 ) ) > ( this->_maxMapU - boxDimInIndices ) )
8646  {
8647  //================================ This is the last X
8648  hlpArrX[1] = this->_maxMapU;
8649  }
8650 
8651  for ( unsigned int yStart = 0; yStart <= ( this->_maxMapV - boxDimInIndices ); yStart += ( boxDimInIndices / 2 ) )
8652  {
8653  hlpArrY[0] = yStart;
8654  hlpArrY[1] = yStart + boxDimInIndices;
8655 
8656  //================================ Check for terminal boxes, they may need to have larger size
8657  if ( ( yStart + ( boxDimInIndices / 2 ) ) > ( this->_maxMapV - boxDimInIndices ) )
8658  {
8659  //============================ This is the last Y
8660  hlpArrY[1] = this->_maxMapV;
8661  }
8662 
8663  for ( unsigned int zStart = 0; zStart <= ( this->_maxMapW - boxDimInIndices ); zStart += ( boxDimInIndices / 2 ) )
8664  {
8665  hlpArrZ[0] = zStart;
8666  hlpArrZ[1] = zStart + boxDimInIndices;
8667 
8668  //============================ Check for terminal boxes, they may need to have larger size
8669  if ( ( zStart + ( boxDimInIndices / 2 ) ) > ( this->_maxMapW - boxDimInIndices ) )
8670  {
8671  //======================== This is the last Z
8672  hlpArrZ[1] = this->_maxMapW;
8673  }
8674 
8675  XDim.emplace_back ( hlpArrX );
8676  YDim.emplace_back ( hlpArrY );
8677  ZDim.emplace_back ( hlpArrZ );
8678  }
8679  }
8680  }
8681  if ( settings->verbose > 2 )
8682  {
8683  std::cout << ">>>>> Box sizes computed." << std::endl;
8684  }
8685 
8686  //======================================== If the box has enough density, create a new object!
8687  unsigned int noDensityPoints = 0;
8688  unsigned int strCounter = 0;
8689  unsigned int arrayPos = 0;
8690  int coordPos = 0;
8691  double boxVolume = 0.0;
8692  double xCOM = 0.0;
8693  double yCOM = 0.0;
8694  double zCOM = 0.0;
8695  double densTot = 0.0;
8696  int newU, newV, newW;
8697  int hlpU, hlpV, hlpW;
8698  std::vector<double> mapVals;
8699  std::string fileName;
8700 
8701  for ( unsigned int boxIt = 0; boxIt < static_cast<unsigned int> ( XDim.size() ); boxIt++ )
8702  {
8703  if ( settings->verbose > 2 )
8704  {
8705  std::cout << ">>>>> Trying box " << boxIt << " ." << std::endl;
8706  }
8707 
8708  //==================================== Check the box density fraction
8709  noDensityPoints = 0;
8710  for ( unsigned int x = XDim.at(boxIt)[0]; x <= XDim.at(boxIt)[1]; x++ )
8711  {
8712  for ( unsigned int y = YDim.at(boxIt)[0]; y <= YDim.at(boxIt)[1]; y++ )
8713  {
8714  for ( unsigned int z = ZDim.at(boxIt)[0]; z <= ZDim.at(boxIt)[1]; z++ )
8715  {
8716  arrayPos = z + (this->_maxMapW+1) * ( y + (this->_maxMapV+1) * x );
8717 
8718  if ( this->_densityMapCor[arrayPos] > 0.0 )
8719  {
8720  noDensityPoints += 1;
8721  }
8722  }
8723  }
8724  }
8725 
8726  //==================================== If passing, write out the box
8727  boxVolume = ( ( XDim.at(boxIt)[1] - XDim.at(boxIt)[0] ) + 1 ) * ( ( YDim.at(boxIt)[1] - YDim.at(boxIt)[0] ) + 1 ) * ( ( ZDim.at(boxIt)[1] - ZDim.at(boxIt)[0] ) + 1 );
8728  if ( ( static_cast<double> ( noDensityPoints ) / boxVolume ) > settings->mapFragBoxFraction )
8729  {
8730  //================================ Create new structure
8731  ret.emplace_back ( new ProSHADE_data () );
8732 
8733  //================================ Fill in the obvious parameters
8734  ret.at(strCounter)->_fromPDB = false;
8735  ret.at(strCounter)->_shellSpacing = settings->shellSpacing;
8736  ret.at(strCounter)->_maxExtraCellularSpace = settings->extraSpace;
8737  ret.at(strCounter)->_xRange = ( XDim.at(boxIt)[1] - XDim.at(boxIt)[0] ) * ( this->_xRange / static_cast<double> ( this->_maxMapU ) );
8738  ret.at(strCounter)->_yRange = ( YDim.at(boxIt)[1] - YDim.at(boxIt)[0] ) * ( this->_yRange / static_cast<double> ( this->_maxMapV ) );
8739  ret.at(strCounter)->_zRange = ( ZDim.at(boxIt)[1] - ZDim.at(boxIt)[0] ) * ( this->_zRange / static_cast<double> ( this->_maxMapW ) );
8740 
8741  //================================ Set xyzFrom and xyzTo
8742  ret.at(strCounter)->_xFrom = XDim.at(boxIt)[0] + this->_xFrom;
8743  ret.at(strCounter)->_yFrom = YDim.at(boxIt)[0] + this->_yFrom;;
8744  ret.at(strCounter)->_zFrom = ZDim.at(boxIt)[0] + this->_zFrom;;
8745 
8746  ret.at(strCounter)->_xTo = XDim.at(boxIt)[1] + this->_xFrom;;
8747  ret.at(strCounter)->_yTo = YDim.at(boxIt)[1] + this->_yFrom;;
8748  ret.at(strCounter)->_zTo = ZDim.at(boxIt)[1] + this->_zFrom;;
8749 
8750  //================================ Automatically determine maximum number of shells
8751  ret.at(strCounter)->_shellPlacement = std::vector<double> ( std::floor ( std::max ( ret.at(strCounter)->_xRange, std::max ( ret.at(strCounter)->_yRange, ret.at(strCounter)->_zRange ) ) / ret.at(strCounter)->_shellSpacing ) );
8752 
8753  for ( unsigned int shellIter = 0; shellIter < static_cast<unsigned int> ( ret.at(strCounter)->_shellPlacement.size() ); shellIter++ )
8754  {
8755  ret.at(strCounter)->_shellPlacement.at(shellIter) = (shellIter+1) * ret.at(strCounter)->_shellSpacing;
8756  }
8757 
8758  //================================ Determine other basic parameters
8759  ret.at(strCounter)->_mapResolution= settings->mapResolution;
8760  ret.at(strCounter)->_maxMapU = ( XDim.at(boxIt)[1] - XDim.at(boxIt)[0] );
8761  ret.at(strCounter)->_maxMapV = ( YDim.at(boxIt)[1] - YDim.at(boxIt)[0] );
8762  ret.at(strCounter)->_maxMapW = ( ZDim.at(boxIt)[1] - ZDim.at(boxIt)[0] );
8763  ret.at(strCounter)->_densityMapComputed = true;
8764 
8765  hlpU = ( ret.at(strCounter)->_maxMapU + 1 );
8766  hlpV = ( ret.at(strCounter)->_maxMapV + 1 );
8767  hlpW = ( ret.at(strCounter)->_maxMapW + 1 );
8768 
8769  //================================ Fill the density map
8770  mapVals.clear ( );
8771  ret.at(strCounter)->_densityMapCor= new double [(ret.at(strCounter)->_maxMapU+1) * (ret.at(strCounter)->_maxMapV+1) * (ret.at(strCounter)->_maxMapW + 1)];
8772  xCOM = 0.0;
8773  yCOM = 0.0;
8774  zCOM = 0.0;
8775  densTot = 0.0;
8776  for ( unsigned int x = XDim.at(boxIt)[0]; x <= XDim.at(boxIt)[1]; x++ )
8777  {
8778  for ( unsigned int y = YDim.at(boxIt)[0]; y <= YDim.at(boxIt)[1]; y++ )
8779  {
8780  for ( unsigned int z = ZDim.at(boxIt)[0]; z <= ZDim.at(boxIt)[1]; z++ )
8781  {
8782  arrayPos = z + (this->_maxMapW+1) * ( y + (this->_maxMapV+1) * x );
8783  coordPos = (z-ZDim.at(boxIt)[0]) + (ret.at(strCounter)->_maxMapW+1) * ( (y-YDim.at(boxIt)[0]) + (ret.at(strCounter)->_maxMapV+1) * (x-XDim.at(boxIt)[0]) );
8784 
8785  ret.at(strCounter)->_densityMapCor[coordPos] = this->_densityMapCor[arrayPos];
8786 
8787  if ( this->_densityMapCor[arrayPos] > 0.0 )
8788  {
8789  mapVals.emplace_back ( this->_densityMapCor[arrayPos] );
8790  xCOM += ( x - XDim.at(boxIt)[0] ) * this->_densityMapCor[arrayPos];
8791  yCOM += ( y - YDim.at(boxIt)[0] ) * this->_densityMapCor[arrayPos];
8792  zCOM += ( z - ZDim.at(boxIt)[0] ) * this->_densityMapCor[arrayPos];
8793  densTot += this->_densityMapCor[arrayPos];
8794  }
8795  }
8796  }
8797  }
8798 
8799  //================================ Determine other parameters
8800  ret.at(strCounter)->_mapMean = std::accumulate ( mapVals.begin(), mapVals.end(), 0.0 ) / static_cast<double> ( mapVals.size() );
8801  ret.at(strCounter)->_mapSdev = std::sqrt ( static_cast<double> ( std::inner_product ( mapVals.begin(), mapVals.end(), mapVals.begin(), 0.0 ) ) /
8802  static_cast<double> ( mapVals.size() ) - ret.at(strCounter)->_mapMean * ret.at(strCounter)->_mapMean );
8803  mapVals.clear ( );
8804 
8805  //====== Determine COM
8806  std::array<double,3> meanVals;
8807  if ( userCOM )
8808  {
8809  meanVals[0] = xCOM / densTot;
8810  meanVals[1] = yCOM / densTot;
8811  meanVals[2] = zCOM / densTot;
8812  }
8813  else
8814  {
8815  meanVals[0] = static_cast<double> ( hlpU ) / 2.0;
8816  meanVals[1] = static_cast<double> ( hlpV ) / 2.0;
8817  meanVals[2] = static_cast<double> ( hlpW ) / 2.0;
8818  }
8819 
8820  //================================ Re-index the map with COM in the centre
8821  ret.at(strCounter)->_xCorrErr = meanVals[0] - static_cast<double> ( hlpU ) / 2.0;
8822  ret.at(strCounter)->_yCorrErr = meanVals[1] - static_cast<double> ( hlpV ) / 2.0;
8823  ret.at(strCounter)->_zCorrErr = meanVals[2] - static_cast<double> ( hlpW ) / 2.0;
8824 
8825  ret.at(strCounter)->_xCorrection = std::ceil ( ret.at(strCounter)->_xCorrErr );
8826  ret.at(strCounter)->_yCorrection = std::ceil ( ret.at(strCounter)->_yCorrErr );
8827  ret.at(strCounter)->_zCorrection = std::ceil ( ret.at(strCounter)->_zCorrErr );
8828 
8829  ret.at(strCounter)->_densityMapCorCoords = new std::array<double,3> [hlpU * hlpV * hlpW];
8830  double *tmpIn = new double [hlpU * hlpV * hlpW];
8831  for ( unsigned int iter = 0; iter < static_cast<unsigned int> ( hlpU * hlpV * hlpW ); iter++ )
8832  {
8833  tmpIn[iter] = ret.at(strCounter)->_densityMapCor[iter];
8834  }
8835 
8836  for ( int uIt = 0; uIt < hlpU; uIt++ )
8837  {
8838  for ( int vIt = 0; vIt < hlpV; vIt++ )
8839  {
8840  for ( int wIt = 0; wIt < hlpW; wIt++ )
8841  {
8842  newU = static_cast<int> ( uIt ) - static_cast<int> ( ret.at(strCounter)->_xCorrection );
8843  newV = static_cast<int> ( vIt ) - static_cast<int> ( ret.at(strCounter)->_yCorrection );
8844  newW = static_cast<int> ( wIt ) - static_cast<int> ( ret.at(strCounter)->_zCorrection );
8845 
8846  if ( newU < 0 ) { newU += hlpU; } if ( newU >= static_cast<int> ( hlpU ) ) { newU -= hlpU; }
8847  if ( newV < 0 ) { newV += hlpV; } if ( newV >= static_cast<int> ( hlpV ) ) { newV -= hlpV; }
8848  if ( newW < 0 ) { newW += hlpW; } if ( newW >= static_cast<int> ( hlpW ) ) { newW -= hlpW; }
8849 
8850  arrayPos = wIt + hlpW * ( vIt + hlpV * uIt );
8851  coordPos = newW + hlpW * ( newV + hlpV * newU );
8852 
8853  ret.at(strCounter)->_densityMapCor[coordPos] = tmpIn[arrayPos];
8854 
8855  //==================== Save results
8856  ret.at(strCounter)->_densityMapCorCoords[coordPos][0] = ( static_cast<double> ( newU ) - static_cast<double> ( hlpU ) /2.0 ) * ( ret.at(strCounter)->_xRange / static_cast<double> ( hlpU ) );
8857  ret.at(strCounter)->_densityMapCorCoords[coordPos][1] = ( static_cast<double> ( newV ) - static_cast<double> ( hlpV ) /2.0 ) * ( ret.at(strCounter)->_yRange / static_cast<double> ( hlpV ) );;
8858  ret.at(strCounter)->_densityMapCorCoords[coordPos][2] = ( static_cast<double> ( newW ) - static_cast<double> ( hlpW ) /2.0 ) * ( ret.at(strCounter)->_zRange / static_cast<double> ( hlpW ) );;
8859  }
8860  }
8861  }
8862  delete[] tmpIn;
8863 
8864  //================================ Set final batch of parameters
8865  ret.at(strCounter)->_fourierCoeffPower = this->_fourierCoeffPower;
8866  ret.at(strCounter)->_bFactorChange= this->_bFactorChange;
8867  ret.at(strCounter)->_maxMapRange = std::max ( ret.at(strCounter)->_xRange, std::max ( ret.at(strCounter)->_yRange, ret.at(strCounter)->_zRange ) );
8868  ret.at(strCounter)->_phaseRemoved = this->_phaseRemoved;
8869  ret.at(strCounter)->_keepOrRemove = this->_keepOrRemove;
8870  ret.at(strCounter)->_thetaAngle = this->_thetaAngle;
8871  ret.at(strCounter)->_phiAngle = this->_phiAngle;
8872  ret.at(strCounter)->_noShellsWithData = 0;
8873  ret.at(strCounter)->_sphereMapped = false;
8874  ret.at(strCounter)->_firstLineCOM = false;
8875  ret.at(strCounter)->_bandwidthLimit = this->_bandwidthLimit;
8876  ret.at(strCounter)->_oneDimmension= ret.at(strCounter)->_bandwidthLimit * 2;
8877  ret.at(strCounter)->_sphericalCoefficientsComputed = false;
8878  ret.at(strCounter)->_rrpMatricesPrecomputed = false;
8879  ret.at(strCounter)->_shellMappedData = nullptr;
8880  ret.at(strCounter)->_realSHCoeffs = nullptr;
8881  ret.at(strCounter)->_imagSHCoeffs = nullptr;
8882  ret.at(strCounter)->_sphericalHarmonicsWeights= nullptr;
8883  ret.at(strCounter)->_semiNaiveTable = nullptr;
8884  ret.at(strCounter)->_semiNaiveTableSpace = nullptr;
8885  ret.at(strCounter)->_shWorkspace = nullptr;
8886  ret.at(strCounter)->_invRealData = nullptr;
8887  ret.at(strCounter)->_invImagData = nullptr;
8888  ret.at(strCounter)->_rrpMatrices = nullptr;
8889 
8890  //================================ Object initialised!
8891  strCounter += 1;
8892  }
8893  else
8894  {
8895  if ( settings->verbose > 3 )
8896  {
8897  std::cout << ">>>>>>>> Density check NOT passed." << std::endl;
8898  }
8899  }
8900 
8901  if ( settings->verbose > 3 )
8902  {
8903  std::cout << ">>>>>>>> Box " << boxIt << " processed." << std::endl;
8904  }
8905  }
8906 
8907  //======================================== Done
8908  return ( ret );
8909 
8910 }
This class deals with reading in the data and computing structure specific information including the ...
double mapResolution
This is the internal resolution at which the calculations are done, not necessarily the resolution of...
Definition: ProSHADE.h:78
double noIQRsFromMap
This is the number of interquartile distances from mean that is used to threshold the map masking...
Definition: ProSHADE.h:93
unsigned int theta
This parameter is the longitude of the spherical grid mapping. It should be 2 * bandwidth unless ther...
Definition: ProSHADE.h:83
std::string clearMapFile
If map features are to be extracted, should the clear map be saved (then give file name here)...
Definition: ProSHADE.h:144
void normaliseMap(ProSHADE::ProSHADE_settings *settings)
This function does normalises the map data.
void translateMap(double xShift, double yShift, double zShift)
This function translates the data along the three coordinate axis by the amount given by the three pa...
bool overlayDefaults
If true, the shell spacing and distances will be doube to their typical values. This is to speed up m...
Definition: ProSHADE.h:176
double mapFragBoxFraction
Fraction of box that needs to have density in order to be passed on.
Definition: ProSHADE.h:153
unsigned int bandwidth
This parameter determines the angular resolution of the spherical harmonics decomposition.
Definition: ProSHADE.h:80
void keepPhaseInMap(double alpha, double bFac, unsigned int *bandwidth, unsigned int *theta, unsigned int *phi, unsigned int *glIntegOrder, ProSHADE::ProSHADE_settings *settings, bool useCom=true, double maxMapIQR=10.0, int verbose=0, bool clearMapData=true, bool rotDefaults=false, bool overlapDefaults=false, double blurFactor=500.0, bool maskBlurFactorGiven=false)
This function keeps the phase information from the density map and prepares the data for SH coefficie...
bool htmlReport
Should HTML report for the run be created?
Definition: ProSHADE.h:186
int verbose
Should the software report on the progress, or just be quiet? Value between 0 (quiet) and 4 (loud) ...
Definition: ProSHADE.h:189
The main header file containing all declarations the user of the library needs.
void getDensityMapFromMAPFeatures(std::string fileName, double *minDensPreNorm, double *maxDensPreNorm, double *minDensPostNorm, double *maxDensPostNorm, double *postNormMean, double *postNormSdev, double *maskVolume, double *totalVolume, double *maskMean, double *maskSdev, double *maskMin, double *maskMax, double *maskDensityRMS, double *allDensityRMS, std::array< double, 3 > *origRanges, std::array< double, 3 > *origDims, double maxMapIQR, double extraCS, int verbose, bool useCubicMaps, double maskBlurFactor, bool maskBlurFactorGiven, bool reboxAtAll, ProSHADE::ProSHADE_settings *settings)
This function reads in the CCP4&#39; MAP formatted file and computes its features.
void fragmentMap(std::string axOrder, int verbose, ProSHADE::ProSHADE_settings *settings)
This function takes the clear map produced already and fragments it into overlapping boxes of given s...
std::vector< std::vector< int > > findMapIslands(int hlpU, int hlpV, int hlpW, double *map, double threshold=0.0)
This function takes a map and a threshold on it and proceeds to detect islands (continuous fragments ...
void matchMap(ProSHADE_data *matchTo)
This function is called on a map to re-size and re-sample it to match the second, parameter input map...
bool useCubicMaps
When saving clear maps, should the rectangular or cubic (older versions of refmac need this) maps be ...
Definition: ProSHADE.h:145
std::vector< int > ignoreLs
This vector lists all the bandwidth values which should be ignored and not part of the computations...
Definition: ProSHADE.h:117
void shiftMap(double xShift, double yShift, double zShift)
This function shifts (changing header) the data along the three coordinate axis by the amount given b...
void getDensityMapFromPDB(std::string fileName, double *shellDistance, double resolution, unsigned int *bandwidth, unsigned int *theta, unsigned int *phi, unsigned int *glIntegOrder, double *extraSpace, bool mapResDefault, ProSHADE::ProSHADE_settings *settings, double Bfactor=80.0, bool hpFirstLineCom=false, bool overlayDefaults=false)
Function to read in the PDB file and compute the theoretical density map.
double shellSpacing
This parameter determines how far the radial shells should be from each other.
Definition: ProSHADE.h:96
std::array< double, 6 > getDensityMapFromMAPRebox(std::string fileName, double maxMapIQR, double extraCS, int verbose, bool useCubicMaps, double maskBlurFactor, bool maskBlurFactorGiven, ProSHADE::ProSHADE_settings *settings)
This function reads in the CCP4&#39; MAP formatted file and re-boxes its contents using the masking proce...
bool mapResDefault
This variable states if default resolution should be used, or whether the user has supplied a differe...
Definition: ProSHADE.h:85
This is the executive class responsible for comparing strictly two structures.
std::vector< ProSHADE_data * > fragmentMap(ProSHADE::ProSHADE_settings *settings, bool userCOM)
This function takes the map and fragments it into boxes of given size, returning vector of data objec...
void printInfo(int verbose)
This is the main information output for the ProSHADE_mapFeatures class.
bool rotChangeDefault
If map rotation is selected, the default automatic parameter decision is changed. This variable state...
Definition: ProSHADE.h:170
void removePhaseFromMapOverlay(double alpha, double bFac, ProSHADE::ProSHADE_settings *settings)
This function removes the phase information from the density map for the overlay purposes.
unsigned int phi
This parameter is the latitudd of the spherical grid mapping. It should be 2 * bandwidth unless there...
Definition: ProSHADE.h:84
unsigned int maxRotError
This is the maximum allowed error in degrees for the rotation computation. This can be used to speed ...
Definition: ProSHADE.h:179
std::string axisOrder
A string specifying the order of the axis. Must have three characters and any permutation of &#39;x&#39;...
Definition: ProSHADE.h:183
The main header file containing all declarations for the innter workings of the library.
int htmlReportLine
Iterator for current HTML line.
Definition: ProSHADE.h:187
int htmlReportLineProgress
Iterator for current HTML line in the progress bar.
Definition: ProSHADE.h:188
void getDensityMapFromMAP(std::string fileName, double *shellDistance, double resolution, unsigned int *bandwidth, unsigned int *theta, unsigned int *phi, unsigned int *glIntegOrder, double *extraSpace, bool mapResDefault, bool rotDefaults, ProSHADE::ProSHADE_settings *settings, bool overlayDefaults=false)
Function to read in the MAP file and provide the basic processing.
void dealWithHalfMaps(ProSHADE::ProSHADE_settings *settings, double *xTranslate, double *yTranslate, double *zTranslate)
This function takes the clear map produced already and fragments it into overlapping boxes of given s...
double mapFragBoxSize
Should the clear map be fragmented into boxes? If so, put box size here, otherwise leave 0...
Definition: ProSHADE.h:151
ProSHADE_data()
Contructor for the ProSHADE_data class.
std::array< double, 4 > getCOMandDist(ProSHADE::ProSHADE_settings *settings)
This function gets COM and its distance to closes border.
This class stores all the settings and is passed to the executive classes instead of multitude of par...
Definition: ProSHADE.h:74
double mPower
This parameter determines the scaling for trace sigma descriptor.
Definition: ProSHADE.h:114
bool removeIslands(int hlpU, int hlpV, int hlpW, int verbose=0, bool runAll=false)
This function does the island detection support and decides whether different masking should be appli...
void maskMap(int hlpU, int hlpV, int hlpW, double blurBy=250.0, double maxMapIQR=3.0, double extraMaskSpace=3.0)
This function does the map masking for cleaning and re-boxing maps.
double maskBlurFactor
The is the amount of blurring to be used to create masks for maps.
Definition: ProSHADE.h:147
std::vector< std::string > structFiles
This vector should contain all the structures that are being dealt with, but this does not yet work! ...
Definition: ProSHADE.h:120
void removePhaseFromMap(double alpha, double bFac, ProSHADE::ProSHADE_settings *settings)
This function removes the phase information from the density map.
std::array< double, 4 > getTranslationFunctionMap(ProSHADE_data *obj1, ProSHADE_data *obj2, double *ob2XMov=nullptr, double *ob2YMov=nullptr, double *ob2ZMov=nullptr)
Computes the translation function for the two objects and returns the position of the highest peak...
This file contains the ProSHADE_internal_misc namespace and its miscellaneous functions.
double extraSpace
What should be the distance added on both sides to the structure, so that the next cell density would...
Definition: ProSHADE.h:109
unsigned int glIntegOrder
This parameter controls the Gauss-Legendre integration order and so the radial resolution.
Definition: ProSHADE.h:82