ProSHADE  0.7.6.6 (JUL 2022)
Protein Shape Detection
ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup Class Reference

This class contains peak groups detected in the rotation function mapped spheres. More...

#include <ProSHADE_spheres.hpp>

Public Member Functions

proshade_signed angularDistanceWithBorders (proshade_signed origLat, proshade_signed testedLat)
 This function takes two lattitude or longitude positions and finds the smallest distance between them considering the border periodicity. More...
 
void getAllAngleDifferences (std::vector< proshade_double > *angDiffs, std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * > sphereVals)
 This function takes all angles present in this peak group and finds the set of unique angle differeces. More...
 
void getAllPossibleFolds (std::vector< proshade_double > *angDiffs, std::vector< proshade_unsign > *foldsToTry)
 This function angle differences and creates a list of folds that may be present in the group. More...
 
void getSpheresFormingFold (proshade_unsign foldToTry, std::vector< proshade_unsign > *spheresFormingFold, std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * > sphereVals, proshade_double sphereAngleTolerance)
 This function simply finds the indices of the spheres which form the requested form. More...
 
void getBestIndexForFold (proshade_double *bestPosVal, proshade_double *bestLatInd, proshade_double *bestLonInd, std::vector< proshade_unsign > *spheresFormingFold, std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * > sphereVals)
 Function which does simple search through all peak groups indices and saves the index with the highest peak height sum over all spheres. More...
 
 ProSHADE_rotFun_spherePeakGroup (proshade_double lat, proshade_double lon, proshade_unsign sphPos, proshade_unsign angDim)
 Constructor for getting empty ProSHADE_rotFun_spherePeakGroup class. More...
 
 ~ProSHADE_rotFun_spherePeakGroup (void)
 Destructor for the ProSHADE_rotFun_spherePeakGroup class. More...
 
bool checkIfPeakBelongs (proshade_double lat, proshade_double lon, proshade_unsign sphPos, proshade_double cosTol, proshade_signed verbose, proshade_signed messageShift, proshade_double allowedAngle)
 This function takes a new prospective peak and tests if it belongs to this peak group or not. More...
 
void findCyclicPointGroupsGivenFold (std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * > sphereVals, std::vector< proshade_double * > *detectedCs, bool bicubicInterp, proshade_unsign fold, proshade_signed verbose, proshade_signed messageShift)
 Function detecting cyclic point groups with a particular fold in a peak group. More...
 
void computeCornerPositions (void)
 This function computes the group corner vectors, saving results into internal variables.
 
proshade_double getLatFromIndices (void)
 Accessor function for the private variable latFromInds. More...
 
proshade_double getLatToIndices (void)
 Accessor function for the private variable latToInds. More...
 
proshade_double getLonFromIndices (void)
 Accessor function for the private variable lonFromInds. More...
 
proshade_double getLonToIndices (void)
 Accessor function for the private variable lonToInds. More...
 
std::vector< proshade_unsign > getSpherePositions (void)
 Accessor function for the private variable spherePositions. More...
 

Public Attributes

proshade_double latSampling
 
proshade_double lonSampling
 
proshade_unsign dimension
 
proshade_double latFrom
 
proshade_double latTo
 
proshade_double lonFrom
 
proshade_double lonTo
 
proshade_double latFromInds
 
proshade_double latToInds
 
proshade_double lonFromInds
 
proshade_double lonToInds
 
std::vector< proshade_unsign > spherePositions
 
proshade_double * latMinLonMinXYZ
 
proshade_double * latMaxLonMinXYZ
 
proshade_double * latMinLonMaxXYZ
 
proshade_double * latMaxLonMaxXYZ
 

Detailed Description

This class contains peak groups detected in the rotation function mapped spheres.

This class codes the object that contains all the information about a single group of peaks found in the set of ProSHADE_rotFun_sphere objects with mapped rotation function values.

Definition at line 128 of file ProSHADE_spheres.hpp.

Constructor & Destructor Documentation

◆ ProSHADE_rotFun_spherePeakGroup()

ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::ProSHADE_rotFun_spherePeakGroup ( proshade_double  lat,
proshade_double  lon,
proshade_unsign  sphPos,
proshade_unsign  angDim 
)

Constructor for getting empty ProSHADE_rotFun_spherePeakGroup class.

This function simply creates an object of the ProSHADE_rotFun_spherePeakGroup class and fills in the initial data.

Parameters
[in]latThe lattitude value of the first peak of the group.
[in]lonThe longitude value of the first peak of the group.
[in]sphPosThe sphere number of the peak.
[in]angDimThe dimensionality of the sphere grid that we are processing.
[out]XData object with all values set and ready to add new data or search for point groups in the supplied peaks.

Definition at line 1070 of file ProSHADE_spheres.cpp.

1071 {
1072  //================================================ Compute the run-specific values
1073  this->dimension = angDim;
1074  this->lonSampling = ( M_PI ) / static_cast<proshade_double> ( this->dimension );
1075  this->latSampling = ( M_PI * 2.0 ) / static_cast<proshade_double> ( this->dimension );
1076 
1077  //================================================ The constructor is called when firstt peak of the group is found. Save the values of this initial peak.
1078  this->latFrom = static_cast<proshade_double> ( lat ) * this->latSampling;
1079  this->latTo = static_cast<proshade_double> ( lat ) * this->latSampling;
1080  this->lonFrom = static_cast<proshade_double> ( lon ) * this->lonSampling;
1081  this->lonTo = static_cast<proshade_double> ( lon ) * this->lonSampling;
1082  this->latFromInds = lat;
1083  this->latToInds = lat;
1084  this->lonFromInds = lon;
1085  this->lonToInds = lon;
1086  ProSHADE_internal_misc::addToUnsignVector ( &this->spherePositions, sphPos );
1087 
1088  //================================================ Allocate memory for similarity positions
1089  this->latMinLonMinXYZ = new proshade_double[3];
1090  this->latMaxLonMinXYZ = new proshade_double[3];
1091  this->latMinLonMaxXYZ = new proshade_double[3];
1092  this->latMaxLonMaxXYZ = new proshade_double[3];
1093  ProSHADE_internal_misc::checkMemoryAllocation ( this->latMinLonMinXYZ, __FILE__, __LINE__, __func__ );
1094  ProSHADE_internal_misc::checkMemoryAllocation ( this->latMaxLonMinXYZ, __FILE__, __LINE__, __func__ );
1095  ProSHADE_internal_misc::checkMemoryAllocation ( this->latMinLonMaxXYZ, __FILE__, __LINE__, __func__ );
1096  ProSHADE_internal_misc::checkMemoryAllocation ( this->latMaxLonMaxXYZ, __FILE__, __LINE__, __func__ );
1097 
1098  //================================================ Compute corner vectors
1099  this->computeCornerPositions ( );
1100 
1101  //================================================ Done
1102 
1103 }

◆ ~ProSHADE_rotFun_spherePeakGroup()

ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::~ProSHADE_rotFun_spherePeakGroup ( void  )

Destructor for the ProSHADE_rotFun_spherePeakGroup class.

This function releases all memory allocated by the ProSHADE_rotFun_spherePeakGroup object.

Definition at line 1109 of file ProSHADE_spheres.cpp.

1110 {
1111  //================================================ Release the XYZ arrays
1112  delete[] this->latMinLonMinXYZ;
1113  delete[] this->latMaxLonMinXYZ;
1114  delete[] this->latMinLonMaxXYZ;
1115  delete[] this->latMaxLonMaxXYZ;
1116 }

Member Function Documentation

◆ angularDistanceWithBorders()

proshade_signed ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::angularDistanceWithBorders ( proshade_signed  newAngul,
proshade_signed  currentAngul 
)

This function takes two lattitude or longitude positions and finds the smallest distance between them considering the border periodicity.

Parameters
[in]newAngulThe first lattitude or longitude value.
[in]currentAngulThe second lattitude or longitude value.
[out]retThe smallest distance between the first and the second lattitude or longitude values.

Definition at line 1150 of file ProSHADE_spheres.cpp.

1151 {
1152  //================================================ Initialise variables
1153  proshade_signed smallerAngul = newAngul - static_cast< proshade_signed > ( this->dimension );
1154  proshade_signed largerAngul = newAngul + static_cast< proshade_signed > ( this->dimension );
1155 
1156  //================================================ Find the smallest distance
1157  proshade_signed ret = std::min ( std::abs ( currentAngul - newAngul ), std::min ( std::abs ( currentAngul - smallerAngul ), std::abs ( currentAngul - largerAngul ) ) );
1158 
1159  //================================================ Done
1160  return ( ret );
1161 
1162 }

◆ checkIfPeakBelongs()

bool ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::checkIfPeakBelongs ( proshade_double  lat,
proshade_double  lon,
proshade_unsign  sphPos,
proshade_double  cosTol,
proshade_signed  verbose,
proshade_signed  messageShift,
proshade_double  allowedAngle 
)

This function takes a new prospective peak and tests if it belongs to this peak group or not.

This function takes a new peak position in terms of lattitude and longitude and proceeds to convert these to XYZ position. It then checks this XYZ position against this group's "corners" (i.e. the group's lattitude and longitude minimum and maximum borders). If the tested position belongs to the group (i.e. it has small cosine distance to one of the corners), then it is added and the group corners are updated. Otherwise, false is returned and nothing changes in the group.

Parameters
[in]latThe lattitude value of the first peak of the group.
[in]lonThe longitude value of the first peak of the group.
[in]sphPosThe sphere number of the peak.
[in]cosTolThe tolerance for cosine distance similarity to consider the two vectors similar.
[in]verboseHow verbose should the run be? Use -1 if you do not want any standard output output.
[in]messageShiftAre we in a subprocess, so that the log should be shifted for this function call? If so, by how much?
[in]allowedAngleThe maximum allowed angle in radians before point stops belonging only because the group would grow too much.
[out]resBoolean value signifying if the peak was added.

Definition at line 1180 of file ProSHADE_spheres.cpp.

1181 {
1182  //================================================ Initialise local variables
1183  bool peakAdded = false;
1184  std::stringstream hlpSS;
1185  std::stringstream hlpSS2;
1186 
1187  //================================================ Compute peaks XYZ and its cosine distance to group corners
1188  proshade_double xPos = 1.0 * std::sin ( lon * this->lonSampling ) * std::cos ( lat * this->latSampling );
1189  proshade_double yPos = 1.0 * std::sin ( lon * this->lonSampling ) * std::sin ( lat * this->latSampling );
1190  proshade_double zPos = 1.0 * std::cos ( lon * this->lonSampling );
1191  hlpSS2 << "Peak " << xPos << " ; " << yPos << " ; " << zPos << " is close enough to group with corner ";
1192 
1193  if ( ProSHADE_internal_maths::vectorOrientationSimilaritySameDirection ( xPos, yPos, zPos, this->latMinLonMinXYZ[0], this->latMinLonMinXYZ[1], this->latMinLonMinXYZ[2], cosTol ) ) { peakAdded = true; hlpSS2 << this->latMinLonMinXYZ[0] << " ; " << this->latMinLonMinXYZ[1] << " ; " << this->latMinLonMinXYZ[2]; }
1194  if ( ProSHADE_internal_maths::vectorOrientationSimilaritySameDirection ( xPos, yPos, zPos, this->latMaxLonMinXYZ[0], this->latMaxLonMinXYZ[1], this->latMaxLonMinXYZ[2], cosTol ) && !peakAdded ) { peakAdded = true; hlpSS2 << this->latMaxLonMinXYZ[0] << " ; " << this->latMaxLonMinXYZ[1] << " ; " << this->latMaxLonMinXYZ[2]; }
1195  if ( ProSHADE_internal_maths::vectorOrientationSimilaritySameDirection ( xPos, yPos, zPos, this->latMinLonMaxXYZ[0], this->latMinLonMaxXYZ[1], this->latMinLonMaxXYZ[2], cosTol ) && !peakAdded ) { peakAdded = true; hlpSS2 << this->latMinLonMaxXYZ[0] << " ; " << this->latMinLonMaxXYZ[1] << " ; " << this->latMinLonMaxXYZ[2]; }
1196  if ( ProSHADE_internal_maths::vectorOrientationSimilaritySameDirection ( xPos, yPos, zPos, this->latMaxLonMaxXYZ[0], this->latMaxLonMaxXYZ[1], this->latMaxLonMaxXYZ[2], cosTol ) && !peakAdded ) { peakAdded = true; hlpSS2 << this->latMaxLonMaxXYZ[0] << " ; " << this->latMaxLonMaxXYZ[1] << " ; " << this->latMaxLonMaxXYZ[2]; }
1197 
1198  //================================================ If group grows over allowedAngle radians, do not add to it
1199  if ( peakAdded )
1200  {
1201  proshade_double lenPos = std::sqrt ( std::pow ( xPos, 2.0 ) + std::pow ( yPos, 2.0 ) + std::pow( zPos, 2.0 ) );
1202  proshade_double minMinPos = std::sqrt ( std::pow ( this->latMinLonMinXYZ[0], 2.0 ) + std::pow ( this->latMinLonMinXYZ[1], 2.0 ) + std::pow( this->latMinLonMinXYZ[2], 2.0 ) );
1203  proshade_double minMaxPos = std::sqrt ( std::pow ( this->latMinLonMaxXYZ[0], 2.0 ) + std::pow ( this->latMinLonMaxXYZ[1], 2.0 ) + std::pow( this->latMinLonMaxXYZ[2], 2.0 ) );
1204  proshade_double maxMinPos = std::sqrt ( std::pow ( this->latMaxLonMinXYZ[0], 2.0 ) + std::pow ( this->latMaxLonMinXYZ[1], 2.0 ) + std::pow( this->latMaxLonMinXYZ[2], 2.0 ) );
1205  proshade_double maxMaxPos = std::sqrt ( std::pow ( this->latMaxLonMaxXYZ[0], 2.0 ) + std::pow ( this->latMaxLonMaxXYZ[1], 2.0 ) + std::pow( this->latMaxLonMaxXYZ[2], 2.0 ) );
1206 
1207  if ( ( std::acos ( ( xPos * this->latMinLonMinXYZ[0] + yPos * this->latMinLonMinXYZ[1] + zPos * this->latMinLonMinXYZ[2] ) / ( lenPos * minMinPos ) ) > allowedAngle ) ||
1208  ( std::acos ( ( xPos * this->latMinLonMaxXYZ[0] + yPos * this->latMinLonMaxXYZ[1] + zPos * this->latMinLonMaxXYZ[2] ) / ( lenPos * minMaxPos ) ) > allowedAngle ) ||
1209  ( std::acos ( ( xPos * this->latMaxLonMinXYZ[0] + yPos * this->latMaxLonMinXYZ[1] + zPos * this->latMaxLonMinXYZ[2] ) / ( lenPos * maxMinPos ) ) > allowedAngle ) ||
1210  ( std::acos ( ( xPos * this->latMaxLonMaxXYZ[0] + yPos * this->latMaxLonMaxXYZ[1] + zPos * this->latMaxLonMaxXYZ[2] ) / ( lenPos * maxMaxPos ) ) > allowedAngle ) )
1211  {
1212  peakAdded = false;
1213  }
1214  }
1215 
1216  //================================================ If peak within corners, add it
1217  if ( peakAdded )
1218  {
1219  //============================================ Report progress
1220  hlpSS << "Peak group dimensions changed from LAT " << this->latFromInds << " - " << this->latToInds << " and LON " << this->lonFromInds << " - " << this->lonToInds << " to ";
1221  ProSHADE_internal_messages::printProgressMessage ( verbose, 6, hlpSS2.str(), messageShift );
1222 
1223  //============================================ Initialise local variables
1224  proshade_signed largerCorner, smallerCorner;
1225  bool latCornersDone = false;
1226  bool lonCornersDone = false;
1227 
1228  //============================================ Check if lattitude boundaries need to be modified
1229  if ( ( this->latFromInds <= this->latToInds ) && !( ( lat >= this->latFromInds ) && ( lat <= this->latToInds ) ) )
1230  {
1231  //======================================== Lattitude is outside of group boundaries
1232  smallerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lat ), static_cast< proshade_signed > ( this->latFromInds ) );
1233  largerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lat ), static_cast< proshade_signed > ( this->latToInds ) );
1234 
1235  if ( smallerCorner < largerCorner )
1236  {
1237  this->latFromInds = lat;
1238  latCornersDone = true;
1239  }
1240  if ( smallerCorner > largerCorner )
1241  {
1242  this->latToInds = lat;
1243  latCornersDone = true;
1244  }
1245  if ( smallerCorner == largerCorner )
1246  {
1247  if ( lat < this->latFromInds ) { this->latFromInds = lat; latCornersDone = true; }
1248  else if ( lat > this->latToInds ) { this->latToInds = lat; latCornersDone = true; }
1249  }
1250  }
1251 
1252  if ( ( this->latFromInds > this->latToInds ) && !( ( lat >= this->latFromInds ) || ( lat <= this->latToInds ) ) )
1253  {
1254  //======================================== Lattitude is outside of group boundaries
1255  smallerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lat ), static_cast< proshade_signed > ( this->latFromInds ) );
1256  largerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lat ), static_cast< proshade_signed > ( this->latToInds ) );
1257 
1258  if ( smallerCorner < largerCorner )
1259  {
1260  this->latFromInds = lat;
1261  latCornersDone = true;
1262  }
1263  if ( smallerCorner > largerCorner )
1264  {
1265  this->latToInds = lat;
1266  latCornersDone = true;
1267  }
1268  if ( smallerCorner == largerCorner )
1269  {
1270  if ( lat < this->latFromInds ) { this->latFromInds = lat; latCornersDone = true; }
1271  else if ( lat > this->latToInds ) { this->latToInds = lat; latCornersDone = true; }
1272  }
1273  }
1274 
1275 
1276  //============================================ Check if longitude boundaries need to be modified
1277  if ( ( this->lonFromInds <= this->lonToInds ) && !( ( lon >= this->lonFromInds ) && ( lon <= this->lonToInds ) ) )
1278  {
1279  //======================================== Lattitude is outside of group boundaries
1280  smallerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lon ), static_cast< proshade_signed > ( this->lonFromInds ) );
1281  largerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lon ), static_cast< proshade_signed > ( this->lonToInds ) );
1282 
1283  if ( smallerCorner < largerCorner )
1284  {
1285  this->lonFromInds = lon;
1286  lonCornersDone = true;
1287  }
1288  if ( smallerCorner > largerCorner )
1289  {
1290  this->lonToInds = lon;
1291  lonCornersDone = true;
1292  }
1293  if ( smallerCorner == largerCorner )
1294  {
1295  if ( lon < this->lonFromInds ) { this->lonFromInds = lon; lonCornersDone = true; }
1296  else if ( lon > this->lonToInds ) { this->lonToInds = lon; lonCornersDone = true; }
1297  }
1298  }
1299 
1300  if ( ( this->lonFromInds > this->lonToInds ) && !( ( lon >= this->lonFromInds ) || ( lon <= this->lonToInds ) ) )
1301  {
1302  //======================================== Lattitude is outside of group boundaries
1303  smallerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lon ), static_cast< proshade_signed > ( this->lonFromInds ) );
1304  largerCorner = angularDistanceWithBorders ( static_cast< proshade_signed > ( lon ), static_cast< proshade_signed > ( this->lonToInds ) );
1305 
1306  if ( smallerCorner < largerCorner )
1307  {
1308  this->lonFromInds = lon;
1309  lonCornersDone = true;
1310  }
1311  if ( smallerCorner > largerCorner )
1312  {
1313  this->lonToInds = lon;
1314  lonCornersDone = true;
1315  }
1316  if ( smallerCorner == largerCorner )
1317  {
1318  if ( lon < this->lonFromInds ) { this->lonFromInds = lon; lonCornersDone = true; }
1319  else if ( lon > this->lonToInds ) { this->lonToInds = lon; lonCornersDone = true; }
1320  }
1321  }
1322 
1323  //============================================ Modify corner positions
1324  if ( latCornersDone )
1325  {
1326  this->latFrom = static_cast<proshade_double> ( this->latFromInds ) * this->latSampling;
1327  this->latTo = static_cast<proshade_double> ( this->latToInds ) * this->latSampling;
1328  }
1329 
1330  if ( lonCornersDone )
1331  {
1332  this->lonFrom = static_cast<proshade_double> ( this->lonFromInds ) * this->lonSampling;
1333  this->lonTo = static_cast<proshade_double> ( this->lonToInds ) * this->lonSampling;
1334  }
1335 
1336  //============================================ Compute corner vectors
1337  this->computeCornerPositions ( );
1338  hlpSS << "LAT " << this->latFromInds << " - " << this->latToInds << " and LON " << this->lonFromInds << " - " << this->lonToInds << " ( peak position LAT " << lat << " LON " << lon << " )";
1339  ProSHADE_internal_messages::printProgressMessage ( verbose, 7, hlpSS.str(), messageShift );
1340 
1341  //============================================ If new sphere, add it to the list
1342  bool isSphereNew = true;
1343  for ( proshade_unsign iter = 0; iter < static_cast<proshade_unsign> ( this->spherePositions.size() ); iter++ ) { if ( this->spherePositions.at(iter) == sphPos ) { isSphereNew = false; } }
1344  if ( isSphereNew ) { ProSHADE_internal_misc::addToUnsignVector ( &this->spherePositions, sphPos ); }
1345  }
1346 
1347  //================================================ Done
1348  return ( peakAdded );
1349 
1350 }

◆ findCyclicPointGroupsGivenFold()

void ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::findCyclicPointGroupsGivenFold ( std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * >  sphereVals,
std::vector< proshade_double * > *  detectedCs,
bool  bicubicInterp,
proshade_unsign  fold,
proshade_signed  verbose,
proshade_signed  messageShift 
)

Function detecting cyclic point groups with a particular fold in a peak group.

This function is a simplification of the findCyclicPointGroups function for the cases where the required fold is known. It simply assumes that all the supplied mapped spheres are to be used to find the fold, i.e. that fold-1 is equal to the length of sphereVals. With this assumption, the function can go directly for finding the peak index with highest peak height sum.

At this point, this function can also optionally do bi-cubic interpolation around this index with highest peak sum to try to improve the symmetry axis by searching between the lattitude and longitude indices. Finally, this function will create the ProSHADE formatted array of symmetry group information and save it into the supplied vector, terminating thereafter.

Warning
This function assumes that the supplied sphereVals argument contains only the spheres relating to the required fold and no other spheres - this assumption does not hold if the convertRotationFunction() function was called - consider yourself warned.
Parameters
[in]sphereValsA vector of spheres with mapped rotation function values.
[in]detectedCsA vector of double pointers pointer to which any detected axis will be added in the ProSHADE format - [0] = fold, [1] = x-axis, [2] = y-axis, [3] = z-axis, [4] = angle, [5] = average peak height.
[in]bicubicInterpShould the bicubic interpolation between the peak indices be done?
[in]foldThe fold for which we are searching for cyclic point groups.
[in]verboseThe verbosity of the run.
[in]messageShiftAre we in a subprocess, so that the log should be shifted for this function call? If so, by how much?

Definition at line 1427 of file ProSHADE_spheres.cpp.

1428 {
1429  //================================================ Initialise variables
1430  proshade_double bestPosVal, bestLatInd, bestLonInd;
1431  std::vector< proshade_unsign > spheresFormingFold;
1432 
1433  //================================================ Set all supplied spheres to be required to form the fold
1434  for ( proshade_unsign shIt = 0; shIt < static_cast<proshade_unsign> ( sphereVals.size() ); shIt++ )
1435  {
1436  ProSHADE_internal_misc::addToUnsignVector ( &spheresFormingFold, shIt );
1437  }
1438 
1439  //================================================ Find the index with the highest peak height sum
1440  this->getBestIndexForFold ( &bestPosVal, &bestLatInd, &bestLonInd, &spheresFormingFold, sphereVals );
1441 
1442  //================================================ Optimise by bicubic interpolation if required
1443  if ( bicubicInterp )
1444  {
1445  ProSHADE_internal_maths::optimiseAxisBiCubicInterpolation ( &bestLatInd, &bestLonInd, &bestPosVal, &spheresFormingFold, &sphereVals );
1446  }
1447 
1448  //================================================ Create ProSHADE symmetry axis array and save it
1449  proshade_double* detectedSymmetry = new proshade_double[7];
1450  ProSHADE_internal_misc::checkMemoryAllocation ( detectedSymmetry, __FILE__, __LINE__, __func__ );
1451 
1452  detectedSymmetry[0] = static_cast<proshade_double> ( fold );
1453  detectedSymmetry[1] = 1.0 * std::sin ( bestLonInd * this->lonSampling ) * std::cos ( bestLatInd * this->latSampling );
1454  detectedSymmetry[2] = 1.0 * std::sin ( bestLonInd * this->lonSampling ) * std::sin ( bestLatInd * this->latSampling );
1455  detectedSymmetry[3] = 1.0 * std::cos ( bestLonInd * this->lonSampling );
1456  detectedSymmetry[4] = ( 2.0 * M_PI ) / detectedSymmetry[0];
1457  detectedSymmetry[5] = std::min ( ( bestPosVal - 1.0 ) / ( detectedSymmetry[0] - 1 ), 1.0 );
1458  detectedSymmetry[6] = -std::numeric_limits < proshade_double >::infinity();
1459 
1460  //================================================ Make sure max is positive
1461  const FloatingPoint< proshade_double > lhs1 ( std::max ( std::abs ( detectedSymmetry[1] ), std::max ( std::abs ( detectedSymmetry[2] ), std::abs ( detectedSymmetry[3] ) ) ) );
1462  const FloatingPoint< proshade_double > rhs1 ( std::abs ( detectedSymmetry[1] ) );
1463  const FloatingPoint< proshade_double > rhs2 ( std::abs ( detectedSymmetry[2] ) );
1464  const FloatingPoint< proshade_double > rhs3 ( std::abs ( detectedSymmetry[3] ) );
1465  if ( ( lhs1.AlmostEquals ( rhs1 ) && ( detectedSymmetry[1] < 0.0 ) ) ||
1466  ( lhs1.AlmostEquals ( rhs2 ) && ( detectedSymmetry[2] < 0.0 ) ) ||
1467  ( lhs1.AlmostEquals ( rhs3 ) && ( detectedSymmetry[3] < 0.0 ) ) )
1468  {
1469  detectedSymmetry[1] *= -1.0;
1470  detectedSymmetry[2] *= -1.0;
1471  detectedSymmetry[3] *= -1.0;
1472  detectedSymmetry[4] *= -1.0;
1473  }
1474 
1475  //================================================ Check for decimal underflows. They are not an issue as rounding to zero is fine, but having negative sign to zero will switch the signs and cause problems.
1476  const FloatingPoint< proshade_double > llhs1 ( detectedSymmetry[1] ), llhs2 ( detectedSymmetry[2] ), llhs3 ( detectedSymmetry[3] ), rrhs1 ( 0.0 );
1477  if ( llhs1.AlmostEquals ( rrhs1 ) ) { detectedSymmetry[1] = 0.0; }
1478  if ( llhs2.AlmostEquals ( rrhs1 ) ) { detectedSymmetry[2] = 0.0; }
1479  if ( llhs3.AlmostEquals ( rrhs1 ) ) { detectedSymmetry[3] = 0.0; }
1480 
1481  //================================================ Save detected point group
1482  ProSHADE_internal_misc::addToDblPtrVector ( detectedCs, detectedSymmetry );
1483 
1484  //================================================ Report progress
1485  std::stringstream hlpSS;
1486  hlpSS << "Detected group with fold " << detectedSymmetry[0] << " along axis " << detectedSymmetry[1] << " ; " << detectedSymmetry[2] << " ; " << detectedSymmetry[3] << " and with peak height " << detectedSymmetry[5];
1487  ProSHADE_internal_messages::printProgressMessage ( verbose, 4, hlpSS.str(), messageShift );
1488 
1489  //================================================ Done
1490  return ;
1491 
1492 }

◆ getAllAngleDifferences()

void ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getAllAngleDifferences ( std::vector< proshade_double > *  angDiffs,
std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * >  sphereVals 
)

This function takes all angles present in this peak group and finds the set of unique angle differeces.

Parameters
[in]angDiffsA pointer to a vector to which all angle differences will be saved into.
[in]sphereValsA vector of spheres with mapped rotation function values.

Definition at line 1499 of file ProSHADE_spheres.cpp.

1500 {
1501  //================================================ Initialise local variables
1502  std::vector< proshade_double > angs;
1503 
1504  //================================================ Find all present angles
1505  for ( proshade_unsign shPos = 0; shPos < static_cast<proshade_unsign> ( this->spherePositions.size() ); shPos++ )
1506  {
1507  ProSHADE_internal_misc::addToDoubleVector ( &angs, sphereVals.at(this->spherePositions.at(shPos))->getRadius() );
1508  }
1509 
1510  //================================================ Find all angle differences
1511  for ( proshade_unsign ang1It = 0; ang1It < static_cast<proshade_unsign> ( angs.size() ); ang1It++ )
1512  {
1513  for ( proshade_unsign ang2It = 1; ang2It < static_cast<proshade_unsign> ( angs.size() ); ang2It++ )
1514  {
1515  //======================================== Use unique combinations only
1516  if ( ang1It >= ang2It ) { continue; }
1517 
1518  //======================================== Add angle difference rounded to 5 decimal places
1519  ProSHADE_internal_misc::addToDoubleVector ( angDiffs, std::floor ( std::abs ( angs.at(ang1It) - angs.at(ang2It) ) * 100000.0 ) / 100000.0 );
1520  }
1521  }
1522 
1523  //================================================ Sort and remove duplicates
1524  std::sort ( (*angDiffs).begin(), (*angDiffs).end() );
1525  (*angDiffs).erase ( std::unique ( (*angDiffs).begin(), (*angDiffs).end() ), (*angDiffs).end() );
1526 
1527  //================================================ Done
1528  return ;
1529 
1530 }

◆ getAllPossibleFolds()

void ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getAllPossibleFolds ( std::vector< proshade_double > *  angDiffs,
std::vector< proshade_unsign > *  foldsToTry 
)

This function angle differences and creates a list of folds that may be present in the group.

The function starts by taking each detected angle difference and checking how well it divides a circle (2 Pi). The remainder of this division is then check against a tolerance threshold, which takes into account how many peaks in the rotation function space is the distance off from the theoretical exact value.

Parameters
[in]angDiffsA pointer to a vector containing all the unique angle differences for this peak group.
[in]foldsToTryA pointer to a vector to which the predicted fold to try to find are to be saved into.

Definition at line 1541 of file ProSHADE_spheres.cpp.

1542 {
1543  //================================================ Initialise local variables
1544  proshade_double divRem, divBasis, symmErr, angTolerance, angToleranceNext;
1545  proshade_double peakErr = ( M_PI * 2.0 ) / ( static_cast<proshade_double> ( this->dimension ) );
1546 
1547  //================================================ For each angle difference in the group
1548  for ( proshade_unsign diffIt = 0; diffIt < static_cast<proshade_unsign> ( angDiffs->size() ); diffIt++ )
1549  {
1550  //============================================ Find the basis and remainder of the 2pi/dist equation
1551  divRem = std::modf ( static_cast<proshade_double> ( ( 2.0 * M_PI ) / std::abs ( angDiffs->at(diffIt) ) ), &divBasis );
1552 
1553  //============================================ If the remainder would be smaller for larger basis, so change the basis
1554  if ( divRem > 0.5 )
1555  {
1556  divRem -= 1.0;
1557  divBasis += 1.0;
1558  }
1559 
1560  //============================================ Remove fold 1, that is not really what we are after here ...
1561  const FloatingPoint< proshade_double > lhs1 ( divBasis ), rhs1 ( 1.0 );
1562  if ( lhs1.AlmostEquals ( rhs1 ) ) { continue; }
1563 
1564  //============================================ Is there enough angles in the group for such a fold?
1565  if ( static_cast< proshade_double > ( this->spherePositions.size() ) < ( divBasis - 1.0 ) ) { continue; }
1566 
1567  //============================================ Determine errors on peaks and on folds
1568  symmErr = divRem * ( ( 2.0 * M_PI ) / static_cast<proshade_double> ( divBasis ) );
1569  angTolerance = std::abs( symmErr / peakErr );
1570  angToleranceNext = ( ( ( 2.0 * M_PI ) / static_cast<proshade_double> ( divBasis ) ) - ( ( 2.0 * M_PI ) / static_cast<proshade_double> ( divBasis + 1 ) ) ) / peakErr;
1571 
1572  //============================================ Is remainder small enough?
1573  if ( angTolerance < std::max ( 3.0, ( 0.1 / peakErr ) ) )
1574  {
1575  //======================================== Is the next symmetry close enough? If so, test previous and next folds as well.
1576  if ( angToleranceNext < std::max ( 1.5, ( 0.1 / peakErr ) ) )
1577  {
1578  //==================================== The next fold would pass as well. Use one previous and one following fold as well to cover for errors
1579  ProSHADE_internal_misc::addToUnsignVector ( foldsToTry, static_cast< proshade_unsign > ( divBasis - 1 ) );
1580  ProSHADE_internal_misc::addToUnsignVector ( foldsToTry, static_cast< proshade_unsign > ( divBasis + 1 ) );
1581  }
1582 
1583  //======================================== This fold seems reasonable, save it
1584  ProSHADE_internal_misc::addToUnsignVector ( foldsToTry, static_cast< proshade_unsign > ( divBasis ) );
1585  }
1586  }
1587 
1588  //================================================ Sort and remove duplicates
1589  std::sort ( (*foldsToTry).begin(), (*foldsToTry).end(), std::greater <proshade_unsign>() );
1590  foldsToTry->erase ( std::unique ( (*foldsToTry).begin(), (*foldsToTry).end() ), (*foldsToTry).end() );
1591 
1592  //================================================ Done
1593  return ;
1594 
1595 }

◆ getBestIndexForFold()

void ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getBestIndexForFold ( proshade_double *  bestPosVal,
proshade_double *  bestLatInd,
proshade_double *  bestLonInd,
std::vector< proshade_unsign > *  spheresFormingFold,
std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * >  sphereVals 
)

Function which does simple search through all peak groups indices and saves the index with the highest peak height sum over all spheres.

Parameters
[in]bestPosValPointer to double where the highest sum of heights will be stored.
[in]bestLatIndPointer to double where the highest values lattitude index will be held.
[in]bestLonIndPointer to double where the highest values longitude index will be held.
[in]spheresFormingFoldA vector pointer to a vector containing the indices of the spheres forming this fold.
[in]sphereValsA vector of spheres with mapped rotation function values.

Definition at line 1652 of file ProSHADE_spheres.cpp.

1653 {
1654  //================================================ Initialise variables
1655  proshade_double curPosVal;
1656  *bestPosVal = -1.0;
1657  if ( this->latFromInds > this->latToInds ) { this->latToInds += static_cast< proshade_double > ( this->dimension ); }
1658  if ( this->lonFromInds > this->lonToInds ) { this->lonToInds += static_cast< proshade_double > ( this->dimension ); }
1659 
1660  //================================================ Compute the best average peak height axis for peak indices
1661  for ( proshade_unsign latIt = static_cast< proshade_unsign > ( this->latFromInds ); latIt <= static_cast< proshade_unsign > ( this->latToInds ); latIt++ )
1662  {
1663  //============================================ Deal with boundaries
1664  if ( latIt >= this->dimension ) { latIt -= this->dimension; this->latToInds -= static_cast< proshade_double > ( this->dimension ); }
1665 
1666  for ( proshade_unsign lonIt = static_cast< proshade_unsign > ( this->lonFromInds ); lonIt <= static_cast< proshade_unsign > ( this->lonToInds ); lonIt++ )
1667  {
1668  //======================================== Deal with boundaries
1669  if ( lonIt >= this->dimension ) { lonIt -= this->dimension; this->lonToInds -= static_cast< proshade_double > ( this->dimension ); }
1670 
1671  //======================================== Initialise variables
1672  curPosVal = 1.0;
1673 
1674  //======================================== Find this indices value
1675  for ( proshade_unsign sphIt = 0; sphIt < static_cast<proshade_unsign> ( spheresFormingFold->size() ); sphIt++ )
1676  {
1677  curPosVal += sphereVals.at(spheresFormingFold->at(sphIt))->getSphereLatLonPosition ( latIt, lonIt );
1678  }
1679 
1680  //======================================== If best, save it
1681  if ( curPosVal > *bestPosVal )
1682  {
1683  *bestPosVal = curPosVal;
1684  *bestLatInd = static_cast< proshade_double > ( latIt );
1685  *bestLonInd = static_cast< proshade_double > ( lonIt );
1686  }
1687  }
1688  }
1689 
1690  //================================================ Done
1691  return ;
1692 
1693 }

◆ getLatFromIndices()

proshade_double ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getLatFromIndices ( void  )

Accessor function for the private variable latFromInds.

Parameters
[out]latFromIndsThe lattitude index start for the group.

Definition at line 1356 of file ProSHADE_spheres.cpp.

1357 {
1358  //================================================ Done
1359  return ( this->latFromInds );
1360 
1361 }

◆ getLatToIndices()

proshade_double ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getLatToIndices ( void  )

Accessor function for the private variable latToInds.

Parameters
[out]latToIndsThe lattitude index end for the group.

Definition at line 1367 of file ProSHADE_spheres.cpp.

1368 {
1369  //================================================ Done
1370  return ( this->latToInds );
1371 
1372 }

◆ getLonFromIndices()

proshade_double ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getLonFromIndices ( void  )

Accessor function for the private variable lonFromInds.

Parameters
[out]lonFromIndsThe longitude index start for the group.

Definition at line 1378 of file ProSHADE_spheres.cpp.

1379 {
1380  //================================================ Done
1381  return ( this->lonFromInds );
1382 
1383 }

◆ getLonToIndices()

proshade_double ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getLonToIndices ( void  )

Accessor function for the private variable lonToInds.

Parameters
[out]lonToIndsThe longitude index end for the group.

Definition at line 1389 of file ProSHADE_spheres.cpp.

1390 {
1391  //================================================ Done
1392  return ( this->lonToInds );
1393 
1394 }

◆ getSpherePositions()

std::vector< proshade_unsign > ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getSpherePositions ( void  )

Accessor function for the private variable spherePositions.

Parameters
[out]spherePositionsA vector of all angles (spheres) indices present in this group.

Definition at line 1400 of file ProSHADE_spheres.cpp.

1401 {
1402  //================================================ Done
1403  return ( this->spherePositions );
1404 
1405 }

◆ getSpheresFormingFold()

void ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getSpheresFormingFold ( proshade_unsign  foldToTry,
std::vector< proshade_unsign > *  spheresFormingFold,
std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * >  sphereVals,
proshade_double  sphereAngleTolerance 
)

This function simply finds the indices of the spheres which form the requested form.

Parameters
[in]foldToTryThe value of the fold for which all the required spheres are to be sought.
[in]spheresFormingFoldA pointer to vector to which the sphere indices of spheres forming this fold will be saved into.
[in]sphereValsA vector of spheres with mapped rotation function values.
[in]sphereAngleToleranceThe tolerance for how different the sphere angle can be for the sphere to be still considered.

Definition at line 1604 of file ProSHADE_spheres.cpp.

1605 {
1606  //================================================ Initialise local variables
1607  proshade_double soughtAngle, minSphereVal;
1608  proshade_unsign minSpherePos = 0;
1609 
1610  //================================================ Generate expected angles and check if close-by sphere exists
1611  for ( proshade_double fIt = 1.0; fIt < static_cast<proshade_double> ( foldToTry ); fIt += 1.0 )
1612  {
1613  //============================================ Set variables for the iteration
1614  minSphereVal = 999.9;
1615  soughtAngle = fIt * ( 2.0 * M_PI / static_cast<proshade_double> ( foldToTry ) );
1616 
1617  //============================================ Find the closest sphere passing conditions
1618  for ( proshade_unsign angsIt = 0; angsIt < static_cast<proshade_unsign> ( this->spherePositions.size() ); angsIt++ )
1619  {
1620  if ( std::abs ( sphereVals.at(this->spherePositions.at(angsIt))->getRepresentedAngle() - soughtAngle ) < sphereAngleTolerance )
1621  {
1622  if ( minSphereVal > 1.0 - std::cos ( std::abs ( sphereVals.at(this->spherePositions.at(angsIt))->getRepresentedAngle() - soughtAngle ) ) )
1623  {
1624  minSphereVal = 1.0 - std::cos ( std::abs ( sphereVals.at(this->spherePositions.at(angsIt))->getRepresentedAngle() - soughtAngle ) );
1625  minSpherePos = angsIt;
1626  }
1627  }
1628  }
1629 
1630  //============================================ If no passing sphere, test next fold
1631  const FloatingPoint< proshade_double > lhs1 ( minSphereVal ), rhs1 ( 999.9 );
1632  if ( lhs1.AlmostEquals ( rhs1 ) ) { break; }
1633 
1634  //============================================ Save best position
1635  ProSHADE_internal_misc::addToUnsignVector ( spheresFormingFold, this->spherePositions.at(minSpherePos) );
1636  }
1637 
1638  //================================================ Done
1639  return ;
1640 
1641 }

The documentation for this class was generated from the following files:
ProSHADE_internal_misc::addToDblPtrVector
void addToDblPtrVector(std::vector< proshade_double * > *vecToAddTo, proshade_double *elementToAdd)
Adds the element to the vector.
Definition: ProSHADE_misc.cpp:143
ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::angularDistanceWithBorders
proshade_signed angularDistanceWithBorders(proshade_signed origLat, proshade_signed testedLat)
This function takes two lattitude or longitude positions and finds the smallest distance between them...
Definition: ProSHADE_spheres.cpp:1150
ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::computeCornerPositions
void computeCornerPositions(void)
This function computes the group corner vectors, saving results into internal variables.
Definition: ProSHADE_spheres.cpp:1120
ProSHADE_internal_maths::optimiseAxisBiCubicInterpolation
void optimiseAxisBiCubicInterpolation(proshade_double *bestLattitude, proshade_double *bestLongitude, proshade_double *bestSum, std::vector< proshade_unsign > *sphereList, std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * > *sphereMappedRotFun, proshade_double step=0.05)
This function provides axis optimisation given starting lattitude and longitude indices.
Definition: ProSHADE_maths.cpp:2744
ProSHADE_internal_misc::addToDoubleVector
void addToDoubleVector(std::vector< proshade_double > *vecToAddTo, proshade_double elementToAdd)
Adds the element to the vector.
Definition: ProSHADE_misc.cpp:77
ProSHADE_internal_maths::vectorOrientationSimilaritySameDirection
bool vectorOrientationSimilaritySameDirection(proshade_double a1, proshade_double a2, proshade_double a3, proshade_double b1, proshade_double b2, proshade_double b3, proshade_double tolerance=0.1)
This function compares two vectors using cosine distance and decides if they are similar using tolera...
Definition: ProSHADE_maths.cpp:2714
ProSHADE_internal_misc::checkMemoryAllocation
void checkMemoryAllocation(chVar checkVar, std::string fileP, unsigned int lineP, std::string funcP, std::string infoP="This error may occurs when ProSHADE requests memory to be\n : allocated to it and this operation fails. This could\n : happen when not enough memory is available, either due to\n : other processes using a lot of memory, or when the machine\n : does not have sufficient memory available. Re-run to see\n : if this problem persists.")
Checks if memory was allocated properly.
Definition: ProSHADE_misc.hpp:73
ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup::getBestIndexForFold
void getBestIndexForFold(proshade_double *bestPosVal, proshade_double *bestLatInd, proshade_double *bestLonInd, std::vector< proshade_unsign > *spheresFormingFold, std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_sphere * > sphereVals)
Function which does simple search through all peak groups indices and saves the index with the highes...
Definition: ProSHADE_spheres.cpp:1652
ProSHADE_internal_misc::addToUnsignVector
void addToUnsignVector(std::vector< proshade_unsign > *vecToAddTo, proshade_unsign elementToAdd)
Adds the element to the vector.
Definition: ProSHADE_misc.cpp:99
ProSHADE_internal_messages::printProgressMessage
void printProgressMessage(proshade_signed verbose, proshade_signed messageLevel, std::string message, proshade_signed messageShift=0)
General stdout message printing.
Definition: ProSHADE_messages.cpp:71