From b6bcd423a6174314dfb434bd1d98f6ae05df171d Mon Sep 17 00:00:00 2001 From: Michal Tykac Date: Thu, 7 Jul 2022 13:50:02 +0200 Subject: [PATCH 1/4] 1) Changed the internal working of how symmetry results are stored. This allows for multiple symmetry detection runs using different threshold being done on the same structure with only a small amount of re-computation. 2) Modified how the polyhedral symmetry detection is done when multiple 'primers' are found - previously, the primer with the highest peak height was used, but since the over-sampling was implemented, this is no longer the optimal approach. 3) Changed the source codes version and date to the new version values. --- proshade/error_list.txt | 8 +- .../getMaskedSymmetryPredictions.py | 86 +- proshade/src/bin/bin.cpp | 10 +- proshade/src/proshade/ProSHADE.cpp | 157 +--- proshade/src/proshade/ProSHADE.hpp | 7 +- proshade/src/proshade/ProSHADE_data.cpp | 787 ++++++++++-------- proshade/src/proshade/ProSHADE_data.hpp | 58 +- proshade/src/proshade/ProSHADE_distances.cpp | 4 +- proshade/src/proshade/ProSHADE_distances.hpp | 4 +- proshade/src/proshade/ProSHADE_exceptions.cpp | 4 +- proshade/src/proshade/ProSHADE_exceptions.hpp | 4 +- proshade/src/proshade/ProSHADE_io.cpp | 8 +- proshade/src/proshade/ProSHADE_io.hpp | 4 +- proshade/src/proshade/ProSHADE_mapManip.cpp | 21 +- proshade/src/proshade/ProSHADE_mapManip.hpp | 4 +- proshade/src/proshade/ProSHADE_maths.cpp | 4 +- proshade/src/proshade/ProSHADE_maths.hpp | 4 +- proshade/src/proshade/ProSHADE_messages.cpp | 6 +- proshade/src/proshade/ProSHADE_messages.hpp | 4 +- proshade/src/proshade/ProSHADE_misc.cpp | 26 +- proshade/src/proshade/ProSHADE_misc.hpp | 5 +- proshade/src/proshade/ProSHADE_overlay.cpp | 4 +- proshade/src/proshade/ProSHADE_overlay.hpp | 4 +- proshade/src/proshade/ProSHADE_peakSearch.cpp | 4 +- proshade/src/proshade/ProSHADE_peakSearch.hpp | 4 +- .../proshade/ProSHADE_precomputedValues.cpp | 4 +- .../proshade/ProSHADE_precomputedValues.hpp | 4 +- proshade/src/proshade/ProSHADE_settings.hpp | 23 +- proshade/src/proshade/ProSHADE_spheres.cpp | 4 +- proshade/src/proshade/ProSHADE_spheres.hpp | 4 +- .../proshade/ProSHADE_sphericalHarmonics.cpp | 4 +- .../proshade/ProSHADE_sphericalHarmonics.hpp | 4 +- proshade/src/proshade/ProSHADE_symmetry.cpp | 536 ++++-------- proshade/src/proshade/ProSHADE_symmetry.hpp | 8 +- proshade/src/proshade/ProSHADE_tasks.cpp | 118 ++- proshade/src/proshade/ProSHADE_tasks.hpp | 10 +- proshade/src/proshade/ProSHADE_typedefs.hpp | 4 +- proshade/src/proshade/ProSHADE_version.hpp | 6 +- .../src/proshade/ProSHADE_wignerMatrices.cpp | 4 +- .../src/proshade/ProSHADE_wignerMatrices.hpp | 4 +- proshade/src/python/pyProSHADE.cpp | 9 +- proshade/src/python/pyProSHADE_bindings.cpp | 4 +- proshade/src/python/pyProSHADE_data.cpp | 89 +- proshade/src/python/pyProSHADE_distances.cpp | 4 +- proshade/src/python/pyProSHADE_mapManip.cpp | 4 +- proshade/src/python/pyProSHADE_maths.cpp | 4 +- proshade/src/python/pyProSHADE_symmetry.cpp | 66 +- 47 files changed, 983 insertions(+), 1165 deletions(-) diff --git a/proshade/error_list.txt b/proshade/error_list.txt index 8b6c9c1b..6061c0fc 100644 --- a/proshade/error_list.txt +++ b/proshade/error_list.txt @@ -4,7 +4,7 @@ ==================================== ==================================== -== NEXT FREE MESSAGE NUMBER: 00075 == +== NEXT FREE MESSAGE NUMBER: 00076 == ======== GENERAL: @@ -185,6 +185,8 @@ WS00071 Failed to find symmetry in Patterson map. Map rotation centre detection vector with [Inf, Inf, Inf]. WS00072 Failed to find eigenvalue with value 1 for this rotation matrix. Is this a rotation matrix? This warning occurs when eigenvalue with value 1 is not found be LAPACK in the supplied rotation matrix. This should not happen, as all rotation matrices must have at least one eigenvalue with value 1, so this suggests the supplied matrix is not a rotation matrix. WS00073 Requested both symmetry centre detection and COM centering. COM centering turned off. This warning means that symmetry centre detection was done (or at least symmetry centre position was supplied) and still centering on COM was requested - this makes no sense as the COM centering would over-write the previous centre of symmetry search and therefore the COM centering is turned off. +WS00075 Will not search for fold >>X<< as the map sampling does not support its reliable detection. Increase The bandwidth determines the dimensions of rotation function. Thus, if we want to search for fold X, then the bandwidth is required to be at least X/2. + resolution/bandwidth if you suspect this fold could be present in the structure. ======== OVERLAY: @@ -209,3 +211,7 @@ WP00038 The rotation function distances are not available, yet already requeste getRotationFunctionDescrNumpy() function is called. was already called. If this was not the case, please let me know! WP00043 Attempted to access shell index outside of the shell range. This warning occurs when you call the getSphericalHarmonicsForShell() function with shell number argument larger than the largest available shell (or alternatively with negative number). + +======== +GENERAL: +======== diff --git a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py index 2de24e80..8fd4cb8e 100644 --- a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py +++ b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py @@ -80,7 +80,7 @@ comCentering = True verbosity = -1 inputFileName = "emdb_spa_210329.dat" -outputFileName = "V23_results_allKnownEMDB_COM_resol-" +outputFileName = "V29_results_allKnownEMDB_COM_resol-" EMDBDataPath = "/Users/mysak/BioCEV/proshade/xx_EMDBSymmetry" unreleasedIDsList = [ "EMD-10163", "EMD-10165", "EMD-10166", "EMD-10168", "EMD-10169", "EMD-10170", "EMD-10174", "EMD-21320", "EMD-4320", "EMD-4522", "EMD-4523", "EMD-4524", "EMD-4606", "EMD-4607", "EMD-4718", "EMD-5039", "EMD-6758", "EMD-8144", "EMD-8145", "EMD-1300" ] tooLargeIDsList = [ "EMD-0174", "EMD-11111", "EMD-20091", "EMD-21648", "EMD-0880", "EMD-11008", "EMD-0436", "EMD-11040", "EMD-0618", "EMD-10768", "EMD-10926", "EMD-1610", "EMD-23042" ] @@ -95,7 +95,7 @@ ### no user manipulation is required. ### -startFrom = 0 +startFrom = 20 resolutionFilename = resolution outResCondensed = 0 outResAxes = 0 @@ -410,18 +410,43 @@ def runProSHADESymmetry ( mapFile, maskFile, resol, chngSampl, cntrMap, symCenMa pStruct.computeRotationFunction ( pSet ) pStruct.detectSymmetryInStructure ( pSet ) - ### Retrieve results - recSymmetryType = pStruct.getRecommendedSymmetryType ( pSet ) - recSymmetryFold = pStruct.getRecommendedSymmetryFold ( pSet ) - recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( pSet ) - allCAxes = pStruct.getAllCSyms ( pSet ) + ### Retrieve results for default ProSHADE + recSymmetryType = pStruct.getRecommendedSymmetryType ( ) + recSymmetryFold = pStruct.getRecommendedSymmetryFold ( ) + recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( ) + allCAxes = pStruct.getAllCSyms ( ) - ### Convert results for return retList = [] - retList.append ( recSymmetryType ) - retList.append ( recSymmetryFold ) - retList.append ( allCAxes ) - retList.append ( recSymmetryAxes ) + retListOrig = [] + retListOrig.append ( recSymmetryType ) + retListOrig.append ( recSymmetryFold ) + retListOrig.append ( allCAxes ) + retListOrig.append ( recSymmetryAxes ) + retList.append ( retListOrig ) + + ### Re-compute with different thresholds + thresList = [] + thresList.append ( 0.95 ) + thresList.append ( 0.90 ) + thresList.append ( 0.80 ) + thresList.append ( 0.70 ) + thresList.append ( 0.60 ) + thresList.append ( 0.50 ) + thresList.append ( 0.40 ) + + for thr in thresList: + pStruct.reRunSymmetryDetectionThreshold ( pSet, thr ) + recSymmetryType = pStruct.getRecommendedSymmetryType ( ) + recSymmetryFold = pStruct.getRecommendedSymmetryFold ( ) + recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( ) + allCAxes = pStruct.getAllCSyms ( ) + + retListThres = [] + retListThres.append ( recSymmetryType ) + retListThres.append ( recSymmetryFold ) + retListThres.append ( allCAxes ) + retListThres.append ( recSymmetryAxes ) + retList.append ( retListThres ) ### Release memory del pStruct @@ -502,7 +527,7 @@ def runProSHADESymmetry ( mapFile, maskFile, resol, chngSampl, cntrMap, symCenMa ### Run symmetry detection symRes = runProSHADESymmetry ( mapPath, maskPath, compResolution, mapReSampling, comCentering, symmetryCentering, verbosity ) - + ### Stop timer stopTime = time.time ( ) @@ -513,27 +538,36 @@ def runProSHADESymmetry ( mapFile, maskFile, resol, chngSampl, cntrMap, symCenMa ( outResRecom, outResCondensed, outResAxes ) = openOutputFiles ( counter ) ### Write results - if ( symRes[0] == "I" ) or ( symRes[0] == "O" ) or ( symRes[0] == "T" ): - outResCondensed.write ( str( id ) + "\t" + str( declaredSym ) + "\t" + str( symRes[0] ) + "\t" + str( stopTime - startTime ) + "\n" ) - else: - outResCondensed.write ( str( id ) + "\t" + str( declaredSym ) + "\t" + str( symRes[0] ) + str( symRes[1] ) + "\t" + str( stopTime - startTime ) + "\n" ) - + outResCondensed.write ( str( id ) + "\t" + str( declaredSym ) + "\t" ) outResAxes.write ( str( id ) + " :\n==========\n" ) - for ax in range ( 0, len ( symRes[2] ) ): - outResAxes.write ( str ( symRes[2][ax][0] ) + "\t" + str ( symRes[2][ax][1] ) + "\t" + str( symRes[2][ax][2] ) + "\t" + str( symRes[2][ax][3] ) + "\t" + str( symRes[2][ax][4] ) + "\t" + str( symRes[2][ax][5] ) + "\t" + str( symRes[2][ax][6] ) + "\t" + str( mapVolumeInds ) + "\t" + str( compResolution ) + "\n" ) - outResAxes.write ( "\n" ) - outResRecom.write ( str( id ) + " :\n==========\n" ) - for ax in range ( 0, len ( symRes[3] ) ): - outResRecom.write ( str ( symRes[3][ax][0] ) + "\t" + str ( symRes[3][ax][1] ) + "\t" + str( symRes[3][ax][2] ) + "\t" + str( symRes[3][ax][3] ) + "\t" + str( symRes[3][ax][4] ) + "\t" + str( symRes[3][ax][5] ) + "\t" + str( symRes[3][ax][6] ) + "\t" + str( mapVolumeInds ) + "\t" + str( compResolution ) + "\n" ) - outResRecom.write ( "\n" ) + + for thr in range ( 0, len( symRes ) ): + if ( symRes[thr][0] == "I" ) or ( symRes[thr][0] == "O" ) or ( symRes[thr][0] == "T" ): + outResCondensed.write ( str( symRes[thr][0] ) + "\t" ) + else: + outResCondensed.write ( str( symRes[thr][0] ) + str( symRes[thr][1] ) + "\t" ) + + + outResRecom.write ( str( thr ) + " :\n~~~~~~~~~\n" ) + for ax in range ( 0, len ( symRes[thr][3] ) ): + outResRecom.write ( str ( symRes[thr][3][ax][0] ) + "\t" + str ( symRes[thr][3][ax][1] ) + "\t" + str( symRes[thr][3][ax][2] ) + "\t" + str( symRes[thr][3][ax][3] ) + "\t" + str( symRes[thr][3][ax][4] ) + "\t" + str( symRes[thr][3][ax][5] ) + "\t" + str( symRes[thr][3][ax][6] ) + "\t" + str( mapVolumeInds ) + "\t" + str( compResolution ) + "\n" ) + outResRecom.write ( "\n" ) + + outResAxes.write ( str( thr ) + " :\n~~~~~~~~~\n" ) + for ax in range ( 0, len ( symRes[thr][2] ) ): + outResAxes.write ( str ( symRes[thr][2][ax][0] ) + "\t" + str ( symRes[thr][2][ax][1] ) + "\t" + str( symRes[thr][2][ax][2] ) + "\t" + str( symRes[thr][2][ax][3] ) + "\t" + str( symRes[thr][2][ax][4] ) + "\t" + str( symRes[thr][2][ax][5] ) + "\t" + str( symRes[thr][2][ax][6] ) + "\t" + str( mapVolumeInds ) + "\t" + str( compResolution ) + "\n" ) + outResAxes.write ( "\n" ) + + + outResCondensed.write ( str( stopTime - startTime ) + "\n" ) ### Close output files closeOutputFiles ( outResRecom, outResCondensed, outResAxes ) ### Move counter counter = counter + 1 - + ### End of symmetry detection for this structure ### Done diff --git a/proshade/src/bin/bin.cpp b/proshade/src/bin/bin.cpp index 774fbc16..62215422 100644 --- a/proshade/src/bin/bin.cpp +++ b/proshade/src/bin/bin.cpp @@ -19,8 +19,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== DOxygen main page specifications @@ -830,8 +830,8 @@ std::vector< proshade_double* > symAxes; std::vector< std::vector< proshade_double > > allCsFromSettings; simpleSym->detectSymmetryInStructure ( settings, &symAxes, &allCsFromSettings ); - std::string symmetryType = simpleSym->getRecommendedSymmetryType ( settings ); - proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( settings ); + std::string symmetryType = simpleSym->getRecommendedSymmetryType ( ); + proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( ); //================================================ Write out the symmetry detection results std::cout << "Detected symmetry: " << symmetryType << "-" << symmetryFold << " with axes:" << std::endl; @@ -851,7 +851,7 @@ //================================================ Get group elements for the first axis (or any other axis) std::vector< proshade_unsign > axesList; axesList.emplace_back ( 0 ); - std::vector > groupElementsGrp0 = simpleSym->getAllGroupElements ( settings, axesList, "C" ); + std::vector > groupElementsGrp0 = simpleSym->getAllGroupElements ( axesList, "C" ); std::cout << "Group 0 has fold of " << allCs.at(0)[0] << " and ProShade computed " << groupElementsGrp0.size() << " group element (including the identity one), the second being the rotation matrix:" << std::endl; std::cout << groupElementsGrp0.at(1).at(0) << " x " << groupElementsGrp0.at(1).at(1) << " x " << groupElementsGrp0.at(1).at(2) << std::endl; std::cout << groupElementsGrp0.at(1).at(3) << " x " << groupElementsGrp0.at(1).at(4) << " x " << groupElementsGrp0.at(1).at(5) << std::endl; diff --git a/proshade/src/proshade/ProSHADE.cpp b/proshade/src/proshade/ProSHADE.cpp index a74bad0d..87868023 100644 --- a/proshade/src/proshade/ProSHADE.cpp +++ b/proshade/src/proshade/ProSHADE.cpp @@ -18,8 +18,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -50,7 +50,7 @@ __declspec(dllexport) ProSHADE_settings::ProSHADE_settings ( ) this->requestedResolution = -1.0; this->changeMapResolution = false; this->changeMapResolutionTriLinear = false; - this->resolutionOversampling = 0.75; + this->resolutionOversampling = 0.5; //================================================ Settings regarding the PDB B-factor change this->pdbBFactorNewVal = -1.0; @@ -142,11 +142,8 @@ __declspec(dllexport) ProSHADE_settings::ProSHADE_settings ( ) this->axisErrTolerance = 0.01; this->axisErrToleranceDefault = true; this->minSymPeak = 0.5; - this->recommendedSymmetryType = ""; - this->recommendedSymmetryFold = 0; this->requestedSymmetryType = ""; this->requestedSymmetryFold = 0; - this->detectedSymmetry.clear ( ); //================================================ Settings regarding centre of map ProSHADE_internal_misc::addToDoubleVector ( &this->centrePosition, std::numeric_limits< proshade_double >::infinity() ); @@ -284,18 +281,9 @@ __declspec(dllexport) ProSHADE_settings::ProSHADE_settings ( ProSHADE_settings* this->axisErrTolerance = settings->axisErrTolerance; this->axisErrToleranceDefault = settings->axisErrToleranceDefault; this->minSymPeak = settings->minSymPeak; - this->recommendedSymmetryType = settings->recommendedSymmetryType; - this->recommendedSymmetryFold = settings->recommendedSymmetryFold; this->requestedSymmetryType = settings->requestedSymmetryType; this->requestedSymmetryFold = settings->requestedSymmetryFold; - - - this->detectedSymmetry.clear ( ); - for ( size_t dsIt = 0; dsIt < settings->detectedSymmetry.size(); dsIt++ ) - { - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->detectedSymmetry, settings->detectedSymmetry.at(dsIt) ); - } - + //================================================ Settings regarding centre of map this->centrePosition.clear ( ); for ( size_t cpIt = 0; cpIt < settings->centrePosition.size(); cpIt++ ) @@ -339,7 +327,7 @@ __declspec(dllexport) ProSHADE_settings::ProSHADE_settings ( ProSHADE_Task taskT this->requestedResolution = -1.0; this->changeMapResolution = false; this->changeMapResolutionTriLinear = false; - this->resolutionOversampling = 0.75; + this->resolutionOversampling = 0.5; //================================================ Settings regarding the PDB B-factor change this->pdbBFactorNewVal = -1.0; @@ -430,11 +418,8 @@ __declspec(dllexport) ProSHADE_settings::ProSHADE_settings ( ProSHADE_Task taskT this->axisErrTolerance = 0.01; this->axisErrToleranceDefault = true; this->minSymPeak = 0.5; - this->recommendedSymmetryType = ""; - this->recommendedSymmetryFold = 0; this->requestedSymmetryType = ""; this->requestedSymmetryFold = 0; - this->detectedSymmetry.clear ( ); //================================================ Settings regarding centre of map ProSHADE_internal_misc::addToDoubleVector ( &this->centrePosition, std::numeric_limits< proshade_double >::infinity() ); @@ -512,9 +497,6 @@ __declspec(dllexport) ProSHADE_settings::~ProSHADE_settings ( void ) //================================================ Release boundaries variable delete[] this->forceBounds; - //================================================ Release symmetry axes - if ( this->detectedSymmetry.size() > 0 ) { for ( proshade_unsign it = 0; it < static_cast ( this->detectedSymmetry.size() ); it++ ) { if ( this->detectedSymmetry.at(it) != nullptr ) { delete[] this->detectedSymmetry.at(it); } } } - //================================================ Done } @@ -1514,51 +1496,6 @@ void ProSHADE_settings::setMinimumPeakForAxis ( proshade_d } -/*! \brief Sets the ProSHADE detected symmetry type. - - When symmetry detection is done, the resulting recommended symmetry type will be saved in the settings object by this function. - - \param[in] val The recommended symmetry type for the structure. - - \warning This is an internal function and it should not be used by the user. - */ -#if defined ( _WIN64 ) || defined ( _WIN32 ) -void __declspec(dllexport) ProSHADE_settings::setRecommendedSymmetry ( std::string val ) -#else -void ProSHADE_settings::setRecommendedSymmetry ( std::string val ) -#endif -{ - //================================================ Set the value - this->recommendedSymmetryType = val; - - //================================================ Done - return ; - -} - -/*! \brief Sets the ProSHADE detected symmetry fold. - - When symmetry detection is done, the resulting recommended symmetry fold (valid only for C and D symmetry types) will be saved in the - settings object by this function. - - \param[in] val The recommended symmetry fold for the structure. - - \warning This is an internal function and it should not be used by the user. - */ -#if defined ( _WIN64 ) || defined ( _WIN32 ) -void __declspec(dllexport) ProSHADE_settings::setRecommendedFold ( proshade_unsign val ) -#else -void ProSHADE_settings::setRecommendedFold ( proshade_unsign val ) -#endif -{ - //================================================ Set the value - this->recommendedSymmetryFold = val; - - //================================================ Done - return ; - -} - /*! \brief Sets the user requested symmetry type. When symmetry detection is started, this symmetry type will be exclusively sought. @@ -1599,65 +1536,6 @@ void ProSHADE_settings::setRequestedFold ( proshade_unsign } -/*! \brief Sets the final detected symmetry axes information. - - This function copies (deep copy) the detected and recommended (or requested) symmetry axis information into the settings - object variable for further processing. For multiple axes, call this function multiple times - the addition is cumulative. - - \param[in] sym A pointer to single symmetry axis constituting the detected symmetry. - */ -#if defined ( _WIN64 ) || defined ( _WIN32 ) -void __declspec(dllexport) ProSHADE_settings::setDetectedSymmetry ( proshade_double* sym ) -#else -void ProSHADE_settings::setDetectedSymmetry ( proshade_double* sym ) -#endif -{ - //================================================ Allocate memory - proshade_double* hlpAxis = new proshade_double [7]; - ProSHADE_internal_misc::checkMemoryAllocation ( hlpAxis, __FILE__, __LINE__, __func__ ); - - //================================================ Copy (deep) data - hlpAxis[0] = sym[0]; - hlpAxis[1] = sym[1]; - hlpAxis[2] = sym[2]; - hlpAxis[3] = sym[3]; - hlpAxis[4] = sym[4]; - hlpAxis[5] = sym[5]; - hlpAxis[6] = sym[6]; - - //================================================ Save - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->detectedSymmetry, hlpAxis ); - - //================================================ Release memory - delete[] hlpAxis; - - //================================================ Done - return ; - -} - -/*! \brief If the detected symmetry vector needs to be cleared, this is where it is done. - */ -#if defined ( _WIN64 ) || defined ( _WIN32 ) -void __declspec(dllexport) ProSHADE_settings::cleanDetectedSymmetry ( ) -#else -void ProSHADE_settings::cleanDetectedSymmetry ( ) -#endif -{ - //================================================ Release the detected symmetry vector memory - for ( size_t it = 0; it < this->detectedSymmetry.size(); it++ ) - { - delete[] this->detectedSymmetry.at( it ); - } - - //================================================ Empty the vector - this->detectedSymmetry.clear ( ); - - //================================================ Done - return ; - -} - /*! \brief Sets the filename to which the overlay structure is to be save into. \param[in] filename The filename to which the overlay structure is to be saved to. @@ -2039,8 +1917,7 @@ __declspec(dllexport) ProSHADE_run::ProSHADE_run ( ProSHADE_settings* settings ) throw ProSHADE_exception ( "No task has been specified.", "E000001", __FILE__, __LINE__, __func__, "ProSHADE requires to be told which particular functiona-\n : lity (task) is requested from it. In order to do so, the\n : command line arguments specifying task need to be used\n : (if used from command line), or the ProSHADE_settings\n : object needs to have the member variable \'Task\' set to\n : one of the following values: Distances, Symmetry,\n : OverlayMap or MapManip." ); case Symmetry: - ProSHADE_internal_tasks::SymmetryDetectionTask ( settings, &this->RecomSymAxes, &this->allCSymAxes, &this->mapCOMShift ); - this->setSymmetryResults ( settings ); + ProSHADE_internal_tasks::SymmetryDetectionTask ( settings, &this->mapCOMShift ); break; case Distances: @@ -2223,24 +2100,6 @@ void ProSHADE_run::setRecommendedAxis ( proshade_double* sym ) } -/*! \brief Sets the ProSHADE detected symmetry information for easy programmatical output. - - When symmetry detection is done, the resulting recommended symmetry information will be saved in the - ProSHADE object by this function. - - \param[in] settings ProSHADE_settings object where the results are passed through. - */ -void ProSHADE_run::setSymmetryResults ( ProSHADE_settings* settings ) -{ - //================================================ Save type and fold - this->setRecommendedSymmetry ( settings->recommendedSymmetryType ); - this->setRecommendedFold ( settings->recommendedSymmetryFold ); - - //================================================ Done - return ; - -} - /*! \brief This function parses the command line arguments into the settings object. \param[in] argc The count of the command line arguments (as passed to main function by the system). @@ -3103,10 +2962,6 @@ void ProSHADE_settings::printSettings ( ) strstr << this->minSymPeak; printf ( "Min. sym. peak size : %37s\n", strstr.str().c_str() ); - strstr.str(std::string()); - strstr << this->recommendedSymmetryType << "-" << this->recommendedSymmetryFold; - printf ( "Recommended symm. : %37s\n", strstr.str().c_str() ); - strstr.str(std::string()); strstr << this->requestedSymmetryType << "-" << this->requestedSymmetryFold; printf ( "Requested symm. : %37s\n", strstr.str().c_str() ); diff --git a/proshade/src/proshade/ProSHADE.hpp b/proshade/src/proshade/ProSHADE.hpp index be01ef29..ea4e30ad 100644 --- a/proshade/src/proshade/ProSHADE.hpp +++ b/proshade/src/proshade/ProSHADE.hpp @@ -18,8 +18,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE library code @@ -72,9 +72,6 @@ class ProSHADE_run void setRecommendedFold ( proshade_unsign val ); void setRecommendedAxis ( proshade_double* sym ); - //================================================ Task completion functions - void setSymmetryResults ( ProSHADE_settings* settings ); - public: //================================================ Constructors / Destructors #if defined ( _WIN64 ) || defined ( _WIN32 ) diff --git a/proshade/src/proshade/ProSHADE_data.cpp b/proshade/src/proshade/ProSHADE_data.cpp index b36dde11..08e8b3c5 100644 --- a/proshade/src/proshade/ProSHADE_data.cpp +++ b/proshade/src/proshade/ProSHADE_data.cpp @@ -17,8 +17,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -336,6 +336,7 @@ ProSHADE_internal_data::ProSHADE_data::ProSHADE_data ( std::string strName, doub //================================================ Release memory (it was allocated by the PyBind11 lambda function and needs to be released) delete[] mapVals; + mapVals = nullptr; //================================================ Done @@ -353,6 +354,7 @@ ProSHADE_internal_data::ProSHADE_data::~ProSHADE_data ( ) if ( this->internalMap != nullptr ) { delete[] this->internalMap; + this->internalMap = nullptr; } //================================================ Release the sphere mapping @@ -409,6 +411,7 @@ ProSHADE_internal_data::ProSHADE_data::~ProSHADE_data ( ) if ( this->rrpMatrices[bwIt][shIt] != nullptr ) { delete[] this->rrpMatrices[bwIt][shIt]; + this->rrpMatrices[bwIt][shIt] = nullptr; } } @@ -431,6 +434,7 @@ ProSHADE_internal_data::ProSHADE_data::~ProSHADE_data ( ) if ( this->eMatrices[bandIter][band2Iter] != nullptr ) { delete[] this->eMatrices[bandIter][band2Iter]; + this->eMatrices[bandIter][band2Iter] = nullptr; } } @@ -486,6 +490,14 @@ ProSHADE_internal_data::ProSHADE_data::~ProSHADE_data ( ) } } + //================================================ Release symmetry result holders + for ( size_t vIt = 0; vIt < this->cyclicSymmetries.size(); vIt++ ) { if ( this->cyclicSymmetries.at(vIt) != nullptr ) { delete[] this->cyclicSymmetries.at(vIt); } } + for ( size_t vIt = 0; vIt < this->recommendedSymmetryValues.size(); vIt++ ) { if ( this->recommendedSymmetryValues.at(vIt) != nullptr ) { delete[] this->recommendedSymmetryValues.at(vIt); } } + for ( size_t vIt = 0; vIt < this->tetrahedralSymmetries.size(); vIt++ ) { if ( this->tetrahedralSymmetries.at(vIt) != nullptr ) { delete[] this->tetrahedralSymmetries.at(vIt); } } + for ( size_t vIt = 0; vIt < this->octahedralSymmetries.size(); vIt++ ) { if ( this->octahedralSymmetries.at(vIt) != nullptr ) { delete[] this->octahedralSymmetries.at(vIt); } } + for ( size_t vIt = 0; vIt < this->icosahedralSymmetries.size(); vIt++ ) { if ( this->icosahedralSymmetries.at(vIt) != nullptr ) { delete[] this->icosahedralSymmetries.at(vIt); } } + for ( size_t vIt = 0; vIt < this->dihedralSymmetries.size(); vIt++ ) { for ( size_t vIt2 = 0; vIt2 < this->dihedralSymmetries.at(vIt).size(); vIt2++ ) { if ( this->dihedralSymmetries.at(vIt).at(vIt2) != nullptr ) { delete[] this->dihedralSymmetries.at(vIt).at(vIt2); } } } + //================================================ Done } @@ -1163,6 +1175,11 @@ void ProSHADE_internal_data::ProSHADE_data::shiftToRotationCentre ( ProSHADE_set static_cast< proshade_signed > ( this->yDimIndices ), static_cast< proshade_signed > ( this->zDimIndices ) ); + //================================================ Save the shift + this->mapCOMProcessChangeX += settings->centrePosition.at(0); + this->mapCOMProcessChangeY += settings->centrePosition.at(1); + this->mapCOMProcessChangeZ += settings->centrePosition.at(2); + //================================================ Report function completion std::stringstream ss2; ss2 << "Map rotation centre shifted."; @@ -1930,10 +1947,8 @@ bool sortProSHADESymmetryByFSC ( proshade_double* a, proshade_double* b) containing all detected cyclic point groups into the supplied vector pointers. \param[in] settings A pointer to settings class containing all the information required for map symmetry detection. - \param[in] axes A vector to which all the axes of the recommended symmetry (if any) will be saved. - \param[in] allCs A vector to which all the detected cyclic symmetries will be saved into. */ -void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( ProSHADE_settings* settings, std::vector< proshade_double* >* axes, std::vector < std::vector< proshade_double > >* allCs ) +void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( ProSHADE_settings* settings ) { //================================================ Modify axis tolerance and matrix tolerance by sampling, if required by user if ( settings->axisErrToleranceDefault ) @@ -1957,31 +1972,36 @@ void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( P //============================================ Do simplified search only in the applicable data proshade_double symThres = 0.0; - std::vector< proshade_double* > CSyms = this->findRequestedCSymmetryFromAngleAxis ( settings, settings->requestedSymmetryFold, &symThres ); + this->cyclicSymmetries = this->findRequestedCSymmetryFromAngleAxis ( settings, settings->requestedSymmetryFold, &symThres ); //============================================ Compute FSC for all possible axes - for ( size_t cIt = 0; cIt < CSyms.size(); cIt++ ) { const FloatingPoint< proshade_double > lhs ( CSyms.at(cIt)[5] ), rhs ( -999.9 ); if ( ( CSyms.at(cIt)[5] > settings->peakThresholdMin ) || ( lhs.AlmostEquals ( rhs ) ) ) + for ( size_t cIt = 0; cIt < this->cyclicSymmetries.size(); cIt++ ) { - this->computeFSC ( settings, &CSyms, cIt, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - } } + const FloatingPoint< proshade_double > lhs ( this->cyclicSymmetries.at(cIt)[5] ), rhs ( -999.9 ); + if ( ( this->cyclicSymmetries.at(cIt)[5] > settings->peakThresholdMin ) || ( lhs.AlmostEquals ( rhs ) ) ) + { + this->computeFSC ( settings, &this->cyclicSymmetries, cIt, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + } + } //============================================ Sort by FSC - std::sort ( CSyms.begin(), CSyms.end(), sortProSHADESymmetryByFSC ); + std::sort ( this->cyclicSymmetries.begin(), this->cyclicSymmetries.end(), sortProSHADESymmetryByFSC ); //============================================ Save the best axis as the recommended one - if ( settings->detectedSymmetry.size() == 0 ) { if ( CSyms.size() > 0 ) { settings->setDetectedSymmetry ( CSyms.at(0) ); } } - if ( CSyms.size() > 0 ) + if ( this->cyclicSymmetries.size() > 0 ) { bool passedTests = false; - for ( size_t cIt = 0; cIt < CSyms.size(); cIt++ ) + for ( size_t cIt = 0; cIt < this->cyclicSymmetries.size(); cIt++ ) { - if ( CSyms.at(0)[6] > settings->fscThreshold ) + if ( this->cyclicSymmetries.at(0)[6] > settings->fscThreshold ) { - settings->setRecommendedSymmetry ( "C" ); - settings->setRecommendedFold ( settings->requestedSymmetryFold ); + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = settings->requestedSymmetryFold; - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSyms.at(0) ); - this->saveDetectedSymmetries ( settings, &CSyms, allCs ); + proshade_double* hlpSym = new proshade_double[7]; + ProSHADE_internal_misc::checkMemoryAllocation ( hlpSym, __FILE__, __LINE__, __func__ ); + for ( size_t iter = 0; iter < 7; iter++ ) { hlpSym[iter] = this->cyclicSymmetries.at(cIt)[iter]; } + ProSHADE_internal_misc::addToDblPtrVector ( &this->recommendedSymmetryValues, hlpSym ); passedTests = true; break; @@ -1990,14 +2010,14 @@ void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( P if ( !passedTests ) { - settings->setRecommendedSymmetry ( "" ); - settings->setRecommendedFold ( 0 ); + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = 1; } } else { - settings->setRecommendedSymmetry ( "" ); - settings->setRecommendedFold ( 0 ); + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = 1; } //============================================ Release memory after FSC computation @@ -2016,11 +2036,11 @@ void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( P ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting C symmetry detection.", settings->messageShift ); //================================================ Detect cyclic symmetries - std::vector< proshade_double* > CSyms = getCyclicSymmetriesListFromAngleAxis ( settings ); + this->cyclicSymmetries = getCyclicSymmetriesListFromAngleAxis ( settings ); //================================================ Report progress std::stringstream ss; - ss << "Detected " << CSyms.size() << " C symmetries."; + ss << "Detected " << this->cyclicSymmetries.size() << " C symmetries."; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, ss.str(), settings->messageShift ); //================================================ Sanity check - was the rotation function mapped properly? @@ -2030,27 +2050,11 @@ void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( P } //================================================ If only C syms were requested (e.g. rotation centre detection), terminate here! - if ( settings->requestedSymmetryType == "onlyC" ) + if ( settings->requestedSymmetryType == "onlyCandD" ) { - //============================================ Prepare threshold - proshade_double bestHistPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( &CSyms, 5, 0.01, 0.03, 9 ); - if ( bestHistPeakStart > settings->peakThresholdMin ) { bestHistPeakStart = settings->peakThresholdMin; } + //============================================ Detect the Ds + this->getDihedralSymmetriesList ( settings, &this->cyclicSymmetries ); - //============================================ Find FSCs for C syms - for ( size_t cIt = 0; cIt < CSyms.size(); cIt++ ) - { - //======================================== Check the peak height - if ( CSyms.at(cIt)[5] < bestHistPeakStart ) { continue; } - - //======================================== Stop at some point - it is unlikely the true axis would be this far. - if ( cIt > 15 ) { break; } - - //======================================== Compute FSC - this->computeFSC ( settings, &CSyms, cIt, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - } - - //============================================ Save the detected Cs - this->saveDetectedSymmetries ( settings, &CSyms, allCs ); //============================================ Release memory for (size_t binIt = 0; binIt < static_cast< size_t > ( noBins ); binIt++ ) { delete[] bindata[binIt]; } @@ -2073,129 +2077,95 @@ void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( P //================================================ Are we doing general search? if ( settings->requestedSymmetryType == "" ) { - //============================================ Run the symmetry detection functions for C, D, T, O and I symmetries - std::vector< proshade_double* > DSyms = this->getDihedralSymmetriesList ( settings, &CSyms ); - std::vector< proshade_double* > TSyms, OSyms, ISyms; - std::vector < std::vector< proshade_double* > > TSymsHlp = this->getPredictedTetrahedralSymmetriesList ( settings, &CSyms ); - std::vector < std::vector< proshade_double* > > OSymsHlp = this->getPredictedOctahedralSymmetriesList ( settings, &CSyms ); - std::vector < std::vector< proshade_double* > > ISymsHlp = this->getPredictedIcosahedralSymmetriesList ( settings, &CSyms ); - - //============================================ Find which of the polyhedral groups lists is the best one - TSyms = decidePolyFromList ( settings, &TSymsHlp, 7, &CSyms, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - OSyms = decidePolyFromList ( settings, &OSymsHlp, 13, &CSyms, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - ISyms = decidePolyFromList ( settings, &ISymsHlp, 31, &CSyms, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - - //============================================ Release the helper memory - for ( size_t gIt = 0; gIt < TSymsHlp.size(); gIt++ ) { for ( size_t aIt = 0; aIt < TSymsHlp.at(gIt).size(); aIt++ ) { delete[] TSymsHlp[gIt][aIt]; } } - for ( size_t gIt = 0; gIt < OSymsHlp.size(); gIt++ ) { for ( size_t aIt = 0; aIt < OSymsHlp.at(gIt).size(); aIt++ ) { delete[] OSymsHlp[gIt][aIt]; } } - for ( size_t gIt = 0; gIt < ISymsHlp.size(); gIt++ ) { for ( size_t aIt = 0; aIt < ISymsHlp.at(gIt).size(); aIt++ ) { delete[] ISymsHlp[gIt][aIt]; } } - //============================================ Decide on recommended symmetry - this->saveRecommendedSymmetry ( settings, &CSyms, &DSyms, &TSyms, &OSyms, &ISyms, axes, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + this->determineRecommendedSymmetry ( settings, -2.0, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } if ( settings->requestedSymmetryType == "D" ) { //============================================ Run only the D symmetry detection and search for requested fold - std::vector< proshade_double* > DSyms = this->getDihedralSymmetriesList ( settings, &CSyms ); - this->saveRequestedSymmetryD ( settings, &DSyms, axes, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + this->getDihedralSymmetriesList ( settings, &this->cyclicSymmetries ); + this->saveRequestedSymmetryD ( settings, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } if ( settings->requestedSymmetryType == "T" ) { //============================================ Run only the T symmetry detection - std::vector < std::vector< proshade_double* > > TSymsHlp = this->getPredictedTetrahedralSymmetriesList ( settings, &CSyms ); - std::vector< proshade_double* > TSyms = decidePolyFromList ( settings, &TSymsHlp, 7, &CSyms, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + this->getPredictedTetrahedralSymmetriesList ( settings, &this->cyclicSymmetries, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - if ( TSyms.size() == 7 ) + if ( this->tetrahedralSymmetries.size() == 7 ) { //======================================== Initialise decision vars proshade_double fscVal = 0.0; proshade_double fscValAvg = 0.0; //======================================== Check if axes have high enough FSC and peak height - for ( size_t tIt = 0; tIt < 7; tIt++ ) { if ( CSyms.at(settings->allDetectedTAxes.at(tIt))[5] > settings->peakThresholdMin ) { fscVal = this->computeFSC ( settings, &CSyms, settings->allDetectedTAxes.at(tIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); fscValAvg += fscVal; } } + for ( size_t tIt = 0; tIt < this->tetrahedralSymmetries.size(); tIt++ ) { if ( this->tetrahedralSymmetries.at(tIt)[5] > settings->peakThresholdMin ) { fscVal = this->computeFSC ( settings, &this->tetrahedralSymmetries.at(tIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); fscValAvg += fscVal; } } fscValAvg /= 7.0; - //======================================== If C3 and C5 are found and have correct angle (must have if they are both in ISym) - if ( fscValAvg >= ( settings->fscThreshold ) ) + //======================================== If the average is over the threshold, save it + if ( fscValAvg >= settings->fscThreshold ) { //==================================== The decision is T - settings->setRecommendedSymmetry ( "T" ); - settings->setRecommendedFold ( 0 ); - for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedTAxes.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSyms.at(settings->allDetectedTAxes.at(it)) ); } - if ( settings->detectedSymmetry.size() == 0 ) { for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedTAxes.size() ); it++ ) { settings->setDetectedSymmetry ( CSyms.at(settings->allDetectedTAxes.at(it)) ); } } + this->recommendedSymmetryType = "T"; + this->recommendedSymmetryFold = 0; + for ( proshade_unsign it = 0; it < static_cast ( this->tetrahedralSymmetries.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->tetrahedralSymmetries.at(it)[0] ); } } } - - //============================================ Release the helper memory - for ( size_t gIt = 0; gIt < TSymsHlp.size(); gIt++ ) { for ( size_t aIt = 0; aIt < TSymsHlp.at(gIt).size(); aIt++ ) { delete[] TSymsHlp[gIt][aIt]; } } } if ( settings->requestedSymmetryType == "O" ) { //============================================ Run only the O symmetry detection - std::vector < std::vector< proshade_double* > > OSymsHlp = this->getPredictedOctahedralSymmetriesList ( settings, &CSyms ); - std::vector< proshade_double* > OSyms = decidePolyFromList ( settings, &OSymsHlp, 13, &CSyms, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - - if ( OSyms.size() == 13 ) + this->getPredictedOctahedralSymmetriesList ( settings, &this->cyclicSymmetries, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + + if ( this->octahedralSymmetries.size() == 13 ) { //======================================== Initialise decision vars proshade_double fscVal = 0.0; proshade_double fscValAvg = 0.0; - //======================================== Check if at least one C5 and one C3 with the correct angle have high FSC and peak height - for ( size_t oIt = 0; oIt < 13; oIt++ ) { if ( CSyms.at(settings->allDetectedOAxes.at(oIt))[5] > settings->peakThresholdMin ) { fscVal = this->computeFSC ( settings, &CSyms, settings->allDetectedOAxes.at(oIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); fscValAvg += fscVal; } } + //======================================== Find the average FSC + for ( size_t oIt = 0; oIt < this->octahedralSymmetries.size(); oIt++ ) { if ( this->octahedralSymmetries.at(oIt)[5] > settings->peakThresholdMin ) { fscVal = this->computeFSC ( settings, &this->octahedralSymmetries.at(oIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); fscValAvg += fscVal; } } fscValAvg /= 13.0; - //======================================== If C3 and C5 are found and have correct angle (must have if they are both in ISym) + //======================================== If the average FSC is over the threshold, save it. if ( fscValAvg >= ( settings->fscThreshold ) ) { //==================================== The decision is O - settings->setRecommendedSymmetry ( "O" ); - settings->setRecommendedFold ( 0 ); - for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedOAxes.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSyms.at(settings->allDetectedOAxes.at(it)) ); } - if ( settings->detectedSymmetry.size() == 0 ) { for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedOAxes.size() ); it++ ) { settings->setDetectedSymmetry ( CSyms.at(settings->allDetectedOAxes.at(it)) ); } } + this->recommendedSymmetryType = "O"; + this->recommendedSymmetryFold = 0; + for ( proshade_unsign it = 0; it < static_cast ( this->octahedralSymmetries.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->octahedralSymmetries.at(it)[0] ); } } } - - //============================================ Release the helper memory - for ( size_t gIt = 0; gIt < OSymsHlp.size(); gIt++ ) { for ( size_t aIt = 0; aIt < OSymsHlp.at(gIt).size(); aIt++ ) { delete[] OSymsHlp[gIt][aIt]; } } } if ( settings->requestedSymmetryType == "I" ) { - std::vector < std::vector< proshade_double* > > ISymsHlp = this->getPredictedIcosahedralSymmetriesList ( settings, &CSyms ); - std::vector< proshade_double* > ISyms = decidePolyFromList ( settings, &ISymsHlp, 31, &CSyms, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + //============================================ Run only the I symmetry detection + this->getPredictedIcosahedralSymmetriesList ( settings, &this->cyclicSymmetries, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); - if ( ISyms.size() == 31 ) + if ( this->icosahedralSymmetries.size() == 31 ) { //======================================== Initialise decision vars proshade_double fscVal = 0.0; proshade_double fscValAvg = 0.0; - //======================================== Check if at least one C5 and one C3 with the correct angle have high FSC and peak height - for ( size_t iIt = 0; iIt < 31; iIt++ ) { if ( CSyms.at(settings->allDetectedIAxes.at(iIt))[5] > settings->peakThresholdMin ) { fscVal = this->computeFSC ( settings, &CSyms, settings->allDetectedIAxes.at(iIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); fscValAvg += fscVal; } } + //======================================== Compute FSC average over all detected axes + for ( size_t iIt = 0; iIt < this->icosahedralSymmetries.size(); iIt++ ) { if ( this->icosahedralSymmetries.at(iIt)[5] > settings->peakThresholdMin ) { fscVal = this->computeFSC ( settings, &this->icosahedralSymmetries.at(iIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); fscValAvg += fscVal; } } fscValAvg /= 31.0; - //======================================== If C3 and C5 are found and have correct angle (must have if they are both in ISym) + //======================================== If the axes averaged FSC is over the threshold, save it if ( fscValAvg >= ( settings->fscThreshold ) ) { - //==================================== The decision is O - settings->setRecommendedSymmetry ( "I" ); - settings->setRecommendedFold ( 0 ); - for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedOAxes.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSyms.at(settings->allDetectedIAxes.at(it)) ); } - if ( settings->detectedSymmetry.size() == 0 ) { for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedIAxes.size() ); it++ ) { settings->setDetectedSymmetry ( CSyms.at(settings->allDetectedIAxes.at(it)) ); } } + //==================================== The decision is I + this->recommendedSymmetryType = "I"; + this->recommendedSymmetryFold = 0; + for ( proshade_unsign it = 0; it < static_cast ( this->icosahedralSymmetries.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues , &this->icosahedralSymmetries.at(it)[0] ); } } } - - //============================================ Release the helper memory - for ( size_t gIt = 0; gIt < ISymsHlp.size(); gIt++ ) { for ( size_t aIt = 0; aIt < ISymsHlp.at(gIt).size(); aIt++ ) { delete[] ISymsHlp[gIt][aIt]; } } } - //================================================ Save C symmetries to argument and if different from settings, to the settings as well - this->saveDetectedSymmetries ( settings, &CSyms, allCs ); - //================================================ Release memory after FSC computation for (size_t binIt = 0; binIt < static_cast< size_t > ( noBins ); binIt++ ) { delete[] bindata[binIt]; } delete[] bindata; @@ -2208,52 +2178,6 @@ void ProSHADE_internal_data::ProSHADE_data::detectSymmetryFromAngleAxisSpace ( P } -/*! \brief This function takes the results of point group searches and saves then into the output variables. - - This function takes the CSyms as they are returned by the findRequestedCSymmetryFromAngleAxis() or the - getCyclicSymmetriesListFromAngleAxis() functions and re-saves then to the output variables of the detectSymmetryFromAngleAxisSpace() - function. It also releases the memory of the CSyms argument. - - \warning This function releases the memory of the CSyms argument. - - \param[in] settings A pointer to settings class containing all the information required for map symmetry detection. - \param[in] CSyms A pointer to vector - \param[in] axes A pointer to a vector to which all the axes of the recommended symmetry (if any) will be saved. - \param[in] allCs A pointer to a vector to which all the detected cyclic symmetries will be saved into. - */ -void ProSHADE_internal_data::ProSHADE_data::saveDetectedSymmetries ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSyms, std::vector < std::vector< proshade_double > >* allCs ) -{ - //================================================ Initialise variables - bool isArgSameAsSettings = true; - - //================================================ For each detected point group - for ( proshade_unsign cIt = 0; cIt < static_cast ( CSyms->size() ); cIt++ ) - { - //============================================ Create vector to replace the pointer - std::vector< proshade_double > nextSym; - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[0] ); - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[1] ); - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[2] ); - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[3] ); - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[4] ); - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[5] ); - ProSHADE_internal_misc::addToDoubleVector ( &nextSym, CSyms->at(cIt)[6] ); - ProSHADE_internal_misc::addToDoubleVectorVector ( allCs, nextSym ); - - //============================================ Copy the vector to output variable and if different, then also to settings object - if ( ( cIt == 0 ) && ( settings->allDetectedCAxes.size() == 0 ) ) { isArgSameAsSettings = false; } - if ( !isArgSameAsSettings ) { ProSHADE_internal_misc::addToDoubleVectorVector ( &settings->allDetectedCAxes, nextSym ); } - - //============================================ Release memory - nextSym.clear ( ); - delete[] CSyms->at(cIt); - } - - //================================================ Done - return ; - -} - /*! \brief This function allocates the memory and makes all preparations required for FSC computation. This function does all the heavy lifting of the FSC computation that can be done with only the knowledge of the array dimensions. It @@ -2561,12 +2485,7 @@ proshade_double ProSHADE_internal_data::ProSHADE_data::computeFSC ( ProSHADE_set no symmetry will be returned as detected. \param[in] settings A pointer to settings class containing all the information required for map symmetry detection. - \param[in] CSym A vector of pointers to double arrays, each array being a single Cyclic symmetry entry. - \param[in] DSym A vector of pointers to double arrays, each array being a single Dihedral symmetry entry. - \param[in] TSym A vector of pointers to double arrays, all of which together form the axes of tetrahedral symmetry. - \param[in] OSym A vector of pointers to double arrays, all of which together form the axes of octahedral symmetry. - \param[in] ISym A vector of pointers to double arrays, all of which together form the axes of icosahedral symmetry. - \param[in] axes A vector to which all the axes of the recommended symmetry (if any) will be saved. + \param[in] threshold The FSC threshold to which all axes need to be in order to be included in cosideration for the recommended symmetry. \param[in] cutIndices Map of each coefficient index to its correct bin cut to resolution. \param[in] fCoeffsCut The original map Fourier coefficients cut to resolution. \param[in] noBins Number of bins to be used (only up to the cut-off resolution). @@ -2577,40 +2496,59 @@ proshade_double ProSHADE_internal_data::ProSHADE_data::computeFSC ( ProSHADE_set \param[in] yDim The number of indices along the y-axis of the of the array to be rotated. \param[in] zDim The number of indices along the z-axis of the of the array to be rotated. */ -void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSym, std::vector< proshade_double* >* DSym, std::vector< proshade_double* >* TSym, std::vector< proshade_double* >* OSym, std::vector< proshade_double* >* ISym, std::vector< proshade_double* >* axes, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ) +void ProSHADE_internal_data::ProSHADE_data::determineRecommendedSymmetry ( ProSHADE_settings* settings, proshade_double threshold, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed cutXDim, proshade_signed cutYDim, proshade_signed cutZDim ) { //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting recommended symmetry decision procedure.", settings->messageShift ); //================================================ If no C symmetries, nothing to save... - if ( CSym->size() == 0 ) + if ( this->cyclicSymmetries.size() == 0 ) { - settings->setRecommendedSymmetry ( "" ); - settings->setRecommendedFold ( 0 ); + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = 1; return; } + //================================================ Are we in default mode? + if ( threshold < -1.0 ) { threshold = settings->fscThreshold; } + + //================================================ Empty detected values in case this is not the first call to the function + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = 1; + for ( size_t it = 0; it < this->recommendedSymmetryValues.size(); it++ ) { if ( this->recommendedSymmetryValues.at(it) != nullptr ) { delete[] this->recommendedSymmetryValues.at(it); this->recommendedSymmetryValues.at(it) = nullptr; } } + this->recommendedSymmetryValues.clear ( ); + + //================================================ Apply threshold to new C axes + std::vector< proshade_double* > thresholdedCs; + for ( size_t axIt = 0; axIt < this->cyclicSymmetries.size(); axIt++ ) { if ( this->cyclicSymmetries.at(axIt)[6] >= threshold ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &thresholdedCs, &this->cyclicSymmetries.at(axIt)[0] ); } } + + //================================================ Run the symmetry detection functions for C, D, T, O and I symmetries + this->getDihedralSymmetriesList ( settings, &thresholdedCs ); + this->getPredictedTetrahedralSymmetriesList ( settings, &thresholdedCs, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + this->getPredictedOctahedralSymmetriesList ( settings, &thresholdedCs, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + this->getPredictedIcosahedralSymmetriesList ( settings, &thresholdedCs, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + //================================================ Initialise local variables proshade_double step = 0.01; - proshade_double sigma = 0.1; + proshade_double sigma = 0.3; proshade_signed windowSize = 9; proshade_double IFSCAverage = 0.0, OFSCAverage = 0.0, TFSCAverage = 0.0; bool IIsBest = false, OIsBest = false, TIsBest = false; //================================================ Find the top group minimum threshold using smoothened histogram - proshade_double bestHistPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( CSym, 5, step, sigma, windowSize ); + proshade_double bestHistPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( &thresholdedCs, 5, step, sigma, windowSize ); if ( bestHistPeakStart > settings->peakThresholdMin ) { bestHistPeakStart = settings->peakThresholdMin; } //================================================ Report progress - proshade_unsign noPassed = 0; for ( size_t cIt = 0; cIt < CSym->size(); cIt++ ) { if ( CSym->at(cIt)[5] > bestHistPeakStart ) { noPassed += 1; } } + proshade_unsign noPassed = 0; for ( size_t cIt = 0; cIt < thresholdedCs.size(); cIt++ ) { if ( thresholdedCs.at(cIt)[5] > bestHistPeakStart ) { noPassed += 1; } } std::stringstream ss; ss << "Smoothening has resolved in " << noPassed << " C symmetries."; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, ss.str(), settings->messageShift ); ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "Starting FSC computation to confirm the C symmetries existence.", settings->messageShift ); - + //================================================ Decide if I is the answer bool alreadyDecided = false; - if ( ISym->size() == 31 ) + if ( this->icosahedralSymmetries.size() == 31 ) { //============================================ Initialise decision vars proshade_double fscVal = 0.0; @@ -2618,14 +2556,14 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s proshade_unsign lowFSC = 0; //============================================ Find FSCs and their average - for ( size_t iIt = 0; iIt < 31; iIt++ ) { if ( !std::isinf ( ISym->at(iIt)[6] ) ) { fscVal = ISym->at(iIt)[6]; } else { fscVal = this->computeFSC ( settings, CSym, settings->allDetectedIAxes.at(iIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); } fscValAvg += fscVal; if ( fscVal < settings->fscThreshold ) { lowFSC++; } } + for ( size_t iIt = 0; iIt < this->icosahedralSymmetries.size(); iIt++ ) { if ( !std::isinf ( this->icosahedralSymmetries.at(iIt)[6] ) ) { fscVal = this->icosahedralSymmetries.at(iIt)[6]; } else { fscVal = this->computeFSC ( settings, &this->icosahedralSymmetries.at(iIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } fscValAvg += fscVal; if ( fscVal < threshold ) { lowFSC++; } } fscValAvg /= 31.0; IFSCAverage = fscValAvg; - if ( ( IFSCAverage < settings->fscThreshold ) || ( lowFSC > 10 ) ) { IFSCAverage = 0.0; } + if ( ( IFSCAverage < threshold ) || ( lowFSC > 10 ) ) { IFSCAverage = 0.0; } } //================================================ Decide if O is the answer - if ( ( OSym->size() == 13 ) && !alreadyDecided ) + if ( ( this->octahedralSymmetries.size() == 13 ) && !alreadyDecided ) { //============================================ Initialise decision vars proshade_double fscVal = 0.0; @@ -2633,14 +2571,14 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s proshade_unsign lowFSC = 0; //============================================ Find FSCs and their average - for ( size_t oIt = 0; oIt < 13; oIt++ ) { if ( !std::isinf ( OSym->at(oIt)[6] ) ) { fscVal = OSym->at(oIt)[6]; } else { fscVal = this->computeFSC ( settings, CSym, settings->allDetectedOAxes.at(oIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); } fscValAvg += fscVal; if ( fscVal < settings->fscThreshold ) { lowFSC++; } } + for ( size_t oIt = 0; oIt < this->octahedralSymmetries.size(); oIt++ ) { if ( !std::isinf ( this->octahedralSymmetries.at(oIt)[6] ) ) { fscVal = this->octahedralSymmetries.at(oIt)[6]; } else { fscVal = this->computeFSC ( settings, &this->octahedralSymmetries.at(oIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } fscValAvg += fscVal; if ( fscVal < threshold ) { lowFSC++; } } fscValAvg /= 13.0; OFSCAverage = fscValAvg; - if ( ( OFSCAverage < settings->fscThreshold ) || ( lowFSC > 5 ) ) { OFSCAverage = 0.0; } + if ( ( OFSCAverage < threshold ) || ( lowFSC > 5 ) ) { OFSCAverage = 0.0; } } //================================================ Decide if T is the answer - if ( ( TSym->size() == 7 ) && !alreadyDecided ) + if ( ( this->tetrahedralSymmetries.size() == 7 ) && !alreadyDecided ) { //============================================ Initialise decision vars proshade_double fscVal = 0.0; @@ -2648,20 +2586,20 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s proshade_unsign lowFSC = 0; //============================================ Find FSCs and their average - for ( size_t tIt = 0; tIt < 7; tIt++ ) { if ( !std::isinf ( TSym->at(tIt)[6] ) ) { fscVal = TSym->at(tIt)[6]; } else { fscVal = this->computeFSC ( settings, CSym, settings->allDetectedTAxes.at(tIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); } fscValAvg += fscVal; if ( fscVal < settings->fscThreshold ) { lowFSC++; } } + for ( size_t tIt = 0; tIt < this->tetrahedralSymmetries.size(); tIt++ ) { if ( !std::isinf ( this->tetrahedralSymmetries.at(tIt)[6] ) ) { fscVal = this->tetrahedralSymmetries.at(tIt)[6]; } else { fscVal = this->computeFSC ( settings, &this->tetrahedralSymmetries.at(tIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } fscValAvg += fscVal; if ( fscVal < threshold ) { lowFSC++; } } fscValAvg /= 7.0; TFSCAverage = fscValAvg; - if ( ( TFSCAverage < settings->fscThreshold ) || ( lowFSC > 2 ) ) { TFSCAverage = 0.0; } + if ( ( TFSCAverage < threshold ) || ( lowFSC > 2 ) ) { TFSCAverage = 0.0; } } //================================================ If we are using phaseless detection, different threshold needs to be used due to large number of false positives - proshade_double newThres = settings->fscThreshold; + proshade_double newThres = threshold; if ( !settings->usePhase ) { proshade_double phaselessStep = 0.01; proshade_double phaselessSigma = 0.005; proshade_signed phaselessWSize = 5; - newThres = ProSHADE_internal_maths::findTopGroupSmooth ( CSym, 6, phaselessStep, phaselessSigma, phaselessWSize ); + newThres = ProSHADE_internal_maths::findTopGroupSmooth ( &thresholdedCs, 6, phaselessStep, phaselessSigma, phaselessWSize ); } //================================================ Decide between polyhedral @@ -2680,10 +2618,9 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s if ( IIsBest ) { //============================================ The decision is I - settings->setRecommendedSymmetry ( "I" ); - settings->setRecommendedFold ( 0 ); - for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedIAxes.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at(settings->allDetectedIAxes.at(it)) ); } - if ( settings->detectedSymmetry.size() == 0 ) { for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedIAxes.size() ); it++ ) { settings->setDetectedSymmetry ( CSym->at(settings->allDetectedIAxes.at(it)) ); } } + this->recommendedSymmetryType = "I"; + this->recommendedSymmetryFold = 0; + for ( proshade_unsign it = 0; it < static_cast ( this->icosahedralSymmetries.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues , &this->icosahedralSymmetries.at(it)[0] ); } //============================================ Done alreadyDecided = true; @@ -2693,10 +2630,9 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s if ( OIsBest && !alreadyDecided ) { //============================================ The decision is O - settings->setRecommendedSymmetry ( "O" ); - settings->setRecommendedFold ( 0 ); - for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedOAxes.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at(settings->allDetectedOAxes.at(it)) ); } - if ( settings->detectedSymmetry.size() == 0 ) { for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedOAxes.size() ); it++ ) { settings->setDetectedSymmetry ( CSym->at(settings->allDetectedOAxes.at(it)) ); } } + this->recommendedSymmetryType = "O"; + this->recommendedSymmetryFold = 0; + for ( proshade_unsign it = 0; it < static_cast ( this->octahedralSymmetries.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->octahedralSymmetries.at(it)[0] ); } //============================================ Done alreadyDecided = true; @@ -2705,18 +2641,18 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s //================================================ Now we know T is best polyhedral and conforms to threshold if ( TIsBest && !alreadyDecided ) { - settings->setRecommendedSymmetry ( "T" ); - settings->setRecommendedFold ( 0 ); - for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedTAxes.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at(settings->allDetectedTAxes.at(it)) ); } - if ( settings->detectedSymmetry.size() == 0 ) { for ( proshade_unsign it = 0; it < static_cast ( settings->allDetectedTAxes.size() ); it++ ) { settings->setDetectedSymmetry ( CSym->at(settings->allDetectedTAxes.at(it)) ); } } + //============================================ The decision is T + this->recommendedSymmetryType = "T"; + this->recommendedSymmetryFold = 0; + for ( proshade_unsign it = 0; it < static_cast ( this->tetrahedralSymmetries.size() ); it++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->tetrahedralSymmetries.at(it)[0] ); } //============================================ Done alreadyDecided = true; } - + //================================================ Decide if D is the answer proshade_signed bestD = -1; - if ( ( settings->allDetectedDAxes.size() > 0 ) && ( DSym->size() > 0 ) && !alreadyDecided ) + if ( ( this->dihedralSymmetries.size() > 0 ) && !alreadyDecided ) { //============================================ Initialise local variables proshade_unsign bestFold = 0; @@ -2724,29 +2660,33 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s proshade_double bestValPeak = -std::numeric_limits < proshade_double >::infinity(); //============================================ Find FSCs - for ( size_t dIt = 0; dIt < settings->allDetectedDAxes.size(); dIt++ ) + for ( size_t dIt = 0; dIt < this->dihedralSymmetries.size(); dIt++ ) { //======================================== Check the peak heights - const FloatingPoint< proshade_double > lhs999a ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] ), lhs999b ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ), rhs999 ( static_cast< proshade_double > ( -999.9 ) ); - if ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] < bestHistPeakStart ) && !( lhs999a.AlmostEquals( rhs999 ) ) ) { continue; } - if ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] < bestHistPeakStart ) && !( lhs999b.AlmostEquals( rhs999 ) ) ) { continue; } + const FloatingPoint< proshade_double > lhs999a ( this->dihedralSymmetries.at(dIt).at(0)[5] ), lhs999b ( this->dihedralSymmetries.at(dIt).at(1)[5] ), rhs999 ( static_cast< proshade_double > ( -999.9 ) ); + if ( ( this->dihedralSymmetries.at(dIt).at(0)[5] < bestHistPeakStart ) && !( lhs999a.AlmostEquals( rhs999 ) ) ) { continue; } + if ( ( this->dihedralSymmetries.at(dIt).at(1)[5] < bestHistPeakStart ) && !( lhs999b.AlmostEquals( rhs999 ) ) ) { continue; } //======================================== Find FSCs - if ( std::isinf ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6] ) ) { this->computeFSC ( settings, CSym, settings->allDetectedDAxes.at(dIt).at(0), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); } - if ( std::isinf ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] ) ) { this->computeFSC ( settings, CSym, settings->allDetectedDAxes.at(dIt).at(1), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); } + if ( std::isinf ( this->dihedralSymmetries.at(dIt).at(0)[6] ) ) { this->computeFSC ( settings, &this->dihedralSymmetries.at(dIt).at(0)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } + if ( std::isinf ( this->dihedralSymmetries.at(dIt).at(1)[6] ) ) { this->computeFSC ( settings, &this->dihedralSymmetries.at(dIt).at(1)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } } //============================================ Prepare vector to get the smoothened threshold for D's only std::vector< proshade_double* > smootheningHlp; - for ( size_t dIt = 0; dIt < settings->allDetectedDAxes.size(); dIt++ ) + for ( size_t dIt = 0; dIt < this->dihedralSymmetries.size(); dIt++ ) { + //======================================== Apply thresholding + if ( this->dihedralSymmetries.at(dIt).at(0)[6] < threshold ) { continue; } + if ( this->dihedralSymmetries.at(dIt).at(1)[6] < threshold ) { continue; } + //======================================== Create helper axis proshade_double* sym = new proshade_double[7]; ProSHADE_internal_misc::checkMemoryAllocation ( sym, __FILE__, __LINE__, __func__ ); sym[0] = 0.0; sym[1] = 0.0; sym[2] = 0.0; sym[3] = 0.0; sym[4] = 0.0; - sym[5] = ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ) / 2.0;; - sym[6] = ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] ) / 2.0; + sym[5] = ( this->dihedralSymmetries.at(dIt).at(0)[5] + this->dihedralSymmetries.at(dIt).at(1)[5] ) / 2.0; + sym[6] = ( this->dihedralSymmetries.at(dIt).at(0)[6] + this->dihedralSymmetries.at(dIt).at(1)[6] ) / 2.0; //======================================== Deep copy to a vector ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &smootheningHlp, sym ); @@ -2760,43 +2700,47 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s proshade_double onlyDFSCThreshold = ProSHADE_internal_maths::findTopGroupSmooth ( &smootheningHlp, 6, step, sigma, windowSize ); //============================================ Release the helper memory - for ( size_t axIt = 0; axIt < smootheningHlp.size(); axIt++ ) { delete[] smootheningHlp.at(axIt); } + for ( size_t axIt = 0; axIt < smootheningHlp.size(); axIt++ ) { if ( smootheningHlp.at(axIt) != nullptr ) { delete[] smootheningHlp.at(axIt); } } //============================================ Check if both C symmetries are reliable - for ( size_t dIt = 0; dIt < settings->allDetectedDAxes.size(); dIt++ ) + for ( size_t dIt = 0; dIt < this->dihedralSymmetries.size(); dIt++ ) { + //======================================== Apply thresholding + if ( this->dihedralSymmetries.at(dIt).at(0)[6] < threshold ) { continue; } + if ( this->dihedralSymmetries.at(dIt).at(1)[6] < threshold ) { continue; } + //======================================== Check the peak heights - const FloatingPoint< proshade_double > lhs999a2 ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] ), lhs999b2 ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ), rhs999 ( static_cast< proshade_double > ( -999.9 ) ); - if ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] < bestHistPeakStart ) && !( lhs999a2.AlmostEquals( rhs999 ) ) ) { continue; } - if ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] < bestHistPeakStart ) && !( lhs999b2.AlmostEquals( rhs999 ) ) ) { continue; } - if ( std::min ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5], CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ) < ( std::max ( settings->peakThresholdMin, onlyDPeakThreshold ) * 0.90 ) ) { continue; } + const FloatingPoint< proshade_double > lhs999a2 ( this->dihedralSymmetries.at(dIt).at(0)[5] ), lhs999b2 ( this->dihedralSymmetries.at(dIt).at(1)[5] ), rhs999 ( static_cast< proshade_double > ( -999.9 ) ); + if ( ( this->dihedralSymmetries.at(dIt).at(0)[5] < bestHistPeakStart ) && !( lhs999a2.AlmostEquals( rhs999 ) ) ) { continue; } + if ( ( this->dihedralSymmetries.at(dIt).at(1)[5] < bestHistPeakStart ) && !( lhs999b2.AlmostEquals( rhs999 ) ) ) { continue; } + if ( std::min ( this->dihedralSymmetries.at(dIt).at(0)[5], this->dihedralSymmetries.at(dIt).at(1)[5] ) < ( std::max ( settings->peakThresholdMin, onlyDPeakThreshold ) * 0.90 ) ) { continue; } //======================================== Does this improve the best fold? - if ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[0] > static_cast< proshade_double > ( bestFold ) ) || - ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[0] > static_cast< proshade_double > ( bestFold ) ) ) + if ( ( this->dihedralSymmetries.at(dIt).at(0)[0] > static_cast< proshade_double > ( bestFold ) ) || + ( this->dihedralSymmetries.at(dIt).at(1)[0] > static_cast< proshade_double > ( bestFold ) ) ) { //==================================== Check the FSC vals - if ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6] < std::max ( settings->fscThreshold, onlyDFSCThreshold ) ) && - ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] < std::max ( settings->fscThreshold, onlyDFSCThreshold ) ) ) { continue; } - if ( std::min ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6], CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] ) < ( std::max ( settings->fscThreshold, onlyDFSCThreshold ) * 0.70 ) ) { continue; } + if ( ( this->dihedralSymmetries.at(dIt).at(0)[6] < std::max ( threshold, onlyDFSCThreshold ) ) && + ( this->dihedralSymmetries.at(dIt).at(1)[6] < std::max ( threshold, onlyDFSCThreshold ) ) ) { continue; } + if ( std::min ( this->dihedralSymmetries.at(dIt).at(0)[6], this->dihedralSymmetries.at(dIt).at(1)[6] ) < ( std::max ( threshold, onlyDFSCThreshold ) * 0.70 ) ) { continue; } //==================================== All good! - bestValPeak = ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ) / 2.0 ); - bestValFSC = ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] ) / 2.0 ); - bestFold = static_cast< proshade_unsign > ( std::max ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[0], CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[0] ) ); + bestValPeak = ( ( this->dihedralSymmetries.at(dIt).at(0)[5] + this->dihedralSymmetries.at(dIt).at(1)[5] ) / 2.0 ); + bestValFSC = ( ( this->dihedralSymmetries.at(dIt).at(0)[6] + this->dihedralSymmetries.at(dIt).at(1)[6] ) / 2.0 ); + bestFold = static_cast< proshade_unsign > ( std::max ( this->dihedralSymmetries.at(dIt).at(0)[0], this->dihedralSymmetries.at(dIt).at(1)[0] ) ); bestD = static_cast< proshade_signed > ( dIt ); } else { //==================================== If not, is the FSC sum better? - const FloatingPoint< proshade_double > lhs1 ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[0] ), lhs2 ( CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[0] ), rhs ( static_cast< proshade_double > ( bestFold ) ); - if ( ( ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] ) / 2.0 ) > ( bestValFSC * 1.00 ) ) && - ( ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ) / 2.0 ) > ( bestValPeak * 0.95 ) ) && + const FloatingPoint< proshade_double > lhs1 ( this->dihedralSymmetries.at(dIt).at(0)[0] ), lhs2 ( this->dihedralSymmetries.at(dIt).at(1)[0] ), rhs ( static_cast< proshade_double > ( bestFold ) ); + if ( ( ( ( this->dihedralSymmetries.at(dIt).at(0)[6] + this->dihedralSymmetries.at(dIt).at(1)[6] ) / 2.0 ) > ( bestValFSC * 1.00 ) ) && + ( ( ( this->dihedralSymmetries.at(dIt).at(0)[5] + this->dihedralSymmetries.at(dIt).at(1)[5] ) / 2.0 ) > ( bestValPeak * 0.95 ) ) && ( ( lhs1.AlmostEquals ( rhs ) ) || ( lhs2.AlmostEquals ( rhs ) ) ) ) { - bestValPeak = ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[5] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[5] ) / 2.0 ); - bestValFSC = ( ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[6] + CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[6] ) / 2.0 ); - bestFold = static_cast< proshade_unsign > ( std::max ( CSym->at(settings->allDetectedDAxes.at(dIt).at(0))[0], CSym->at(settings->allDetectedDAxes.at(dIt).at(1))[0] ) ); + bestValPeak = ( ( this->dihedralSymmetries.at(dIt).at(0)[5] + this->dihedralSymmetries.at(dIt).at(1)[5] ) / 2.0 ); + bestValFSC = ( ( this->dihedralSymmetries.at(dIt).at(0)[6] + this->dihedralSymmetries.at(dIt).at(1)[6] ) / 2.0 ); + bestFold = static_cast< proshade_unsign > ( std::max ( this->dihedralSymmetries.at(dIt).at(0)[0], this->dihedralSymmetries.at(dIt).at(1)[0] ) ); bestD = static_cast< proshade_signed > ( dIt ); } } @@ -2806,131 +2750,79 @@ void ProSHADE_internal_data::ProSHADE_data::saveRecommendedSymmetry ( ProSHADE_s if ( bestD != -1 ) { //======================================== The decision is D - settings->setRecommendedSymmetry ( "D" ); - settings->setRecommendedFold ( static_cast< proshade_unsign > ( std::max ( CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(0))[0], CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(1))[0] ) ) ); - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(0)) ); - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(1)) ); - if ( settings->detectedSymmetry.size() == 0 ) - { - settings->setDetectedSymmetry ( CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(0)) ); - settings->setDetectedSymmetry ( CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(1)) ); - } + this->recommendedSymmetryType = "D"; + this->recommendedSymmetryFold = static_cast< proshade_unsign > ( std::max ( this->dihedralSymmetries.at( static_cast< size_t> ( bestD ) ).at(0)[0], this->dihedralSymmetries.at( static_cast< size_t> ( bestD ) ).at(0)[1] ) ); + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->dihedralSymmetries.at( static_cast< size_t> ( bestD ) ).at(0)[0] ); + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->dihedralSymmetries.at( static_cast< size_t> ( bestD ) ).at(1)[0] ); } } //================================================ Decide if C is the answer - if ( ( CSym->size() > 0 ) && !alreadyDecided ) + if ( ( this->cyclicSymmetries.size() > 0 ) && !alreadyDecided ) { //============================================ Initialise decision vars proshade_signed bestC = -1; proshade_unsign bestFold = 0; //============================================ Find FSCs for C syms - for ( size_t cIt = 0; cIt < CSym->size(); cIt++ ) + for ( size_t cIt = 0; cIt < this->cyclicSymmetries.size(); cIt++ ) { //======================================== Do not consider more than top 20, takes time and is unlikely to produce anything... - if ( ( cIt > 20 ) && ( CSym->at(cIt)[5] < 0.95 ) ) { break; } + if ( ( cIt > 20 ) && ( this->cyclicSymmetries.at(cIt)[5] < 0.95 ) ) { break; } //======================================== Check the peak height - if ( CSym->at(cIt)[5] < bestHistPeakStart ) { continue; } + if ( this->cyclicSymmetries.at(cIt)[5] < bestHistPeakStart ) { continue; } //======================================== Compute FSC - if ( std::isinf ( CSym->at(cIt)[6] ) ) { this->computeFSC ( settings, CSym, cIt, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); } + if ( std::isinf ( this->cyclicSymmetries.at(cIt)[6] ) ) { this->computeFSC ( settings, &this->cyclicSymmetries.at(cIt)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); } } //============================================ Find FSC top group threshold - proshade_double bestHistFSCStart = ProSHADE_internal_maths::findTopGroupSmooth ( CSym, 6, step, sigma, windowSize ); + proshade_double bestHistFSCStart = ProSHADE_internal_maths::findTopGroupSmooth ( &this->cyclicSymmetries, 6, step, sigma, windowSize ); + if ( static_cast< proshade_signed > ( threshold * 100.0 ) > static_cast< proshade_signed > ( settings->fscThreshold * 100.0 ) ) { bestHistFSCStart = threshold; } //============================================ Find reliable C syms (this makes the assumption that the input C axes list is FSC sorted!) - for ( size_t cIt = 0; cIt < CSym->size(); cIt++ ) + for ( size_t cIt = 0; cIt < this->cyclicSymmetries.size(); cIt++ ) { //======================================== Check if this improves the best already found fold - if ( CSym->at(cIt)[0] > static_cast< proshade_double > ( bestFold ) ) + if ( this->cyclicSymmetries.at(cIt)[0] > static_cast< proshade_double > ( bestFold ) ) { //==================================== If FSC passes - if ( CSym->at(cIt)[6] > std::max ( bestHistFSCStart, settings->fscThreshold ) ) + if ( this->cyclicSymmetries.at(cIt)[6] > std::max ( bestHistFSCStart, threshold ) ) { - bestFold = static_cast< proshade_unsign > ( CSym->at(cIt)[0] ); + bestFold = static_cast< proshade_unsign > ( this->cyclicSymmetries.at(cIt)[0] ); bestC = static_cast< proshade_signed > ( cIt ); } } } //============================================ Anything? - if ( ( bestC != -1 ) && ( settings->recommendedSymmetryType == "D" ) ) + if ( ( bestC != -1 ) && ( this->recommendedSymmetryType == "D" ) ) { //======================================== Decide if C or D is more appropriate - if ( ( ( CSym->at( static_cast< size_t > ( bestC ) )[6] * 0.80 ) > ( ( CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(0))[6] + CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(1))[6] ) / 2.0 ) ) && - ( ( CSym->at( static_cast< size_t > ( bestC ) )[5] * 0.95 ) > ( ( CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(0))[5] + CSym->at(settings->allDetectedDAxes.at( static_cast< size_t > ( bestD ) ).at(1))[5] ) / 2.0 ) ) ) + if ( ( ( this->cyclicSymmetries.at( static_cast< size_t > ( bestC ) )[6] * 0.80 ) > std::min ( this->dihedralSymmetries.at( static_cast< size_t > ( bestD ) ).at(0)[6], this->dihedralSymmetries.at( static_cast< size_t > ( bestD ) ).at(1)[6] ) ) && + ( ( this->cyclicSymmetries.at( static_cast< size_t > ( bestC ) )[5] * 0.95 ) > std::min ( this->dihedralSymmetries.at( static_cast< size_t > ( bestD ) ).at(0)[5], this->dihedralSymmetries.at( static_cast< size_t > ( bestD ) ).at(1)[5] ) ) ) { - settings->cleanDetectedSymmetry ( ); - settings->recommendedSymmetryType = ""; + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = 1; + for ( size_t iter = 0; iter < this->recommendedSymmetryValues.size(); iter++ ) { if ( this->recommendedSymmetryValues.at(iter) != nullptr ) { delete[] this->recommendedSymmetryValues.at(iter); this->recommendedSymmetryValues.at(iter) = nullptr; } } + this->recommendedSymmetryValues.clear ( ); } } - if ( ( bestC != -1 ) && ( settings->recommendedSymmetryType != "D" ) ) + if ( ( bestC != -1 ) && ( this->recommendedSymmetryType != "D" ) ) { //======================================== The decision is C - settings->setRecommendedSymmetry ( "C" ); - settings->setRecommendedFold ( static_cast< proshade_unsign > ( CSym->at( static_cast< size_t > ( bestC ) )[0] ) ); - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at( static_cast< size_t > ( bestC ) ) ); - if ( settings->detectedSymmetry.size() == 0 ) { settings->setDetectedSymmetry ( CSym->at( static_cast< size_t > ( bestC ) ) ); } + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = static_cast< proshade_unsign > ( this->cyclicSymmetries.at( static_cast< size_t > ( bestC ) )[0] ); + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->cyclicSymmetries.at( static_cast< size_t > ( bestC ) )[0] ); //======================================== Done alreadyDecided = true; } } - //================================================ Done - return ; - -} - -/*! \brief This function takes the C symmetries and searched for the requested symmetry. - - This is a simple search function, which searches the symmetry results for the requested symmetry fold, and if more such - symmetries are found, takes the one with the highest average peak height. If the requested fold was found, it will save - it to the settings object, while it will set the object to fold 0 if the requested symmetry was not found (although there - may be other symmetries present). - - \param[in] settings A pointer to settings class containing all the information required for map symmetry detection. - \param[in] CSym A vector of pointers to double arrays, each array being a single Cyclic symmetry entry. - \param[in] axes A vector to which all the axes of the requested symmetry (if any) will be saved. - */ -void ProSHADE_internal_data::ProSHADE_data::saveRequestedSymmetryC ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSym, std::vector< proshade_double* >* axes ) -{ - //================================================ Initialise variables - proshade_unsign bestIndex = 0; - proshade_double highestSym = 0.0; - - //================================================ Search for best fold - for ( proshade_unsign iter = 0; iter < static_cast ( CSym->size() ); iter++ ) - { - //============================================ Check if it is tbe correct fold - const FloatingPoint< proshade_double > lhs1 ( CSym->at(iter)[0] ), rhs1 ( static_cast< proshade_double > ( settings->requestedSymmetryFold ) ); - if ( !lhs1.AlmostEquals ( rhs1 ) ) { continue; } - - //============================================ If correct, is it the highest found? - if ( CSym->at(iter)[5] > highestSym ) - { - highestSym = CSym->at(iter)[5]; - bestIndex = iter; - } - } - - //================================================ Found? - if ( highestSym > 0.0 ) - { - settings->setRecommendedSymmetry ( "C" ); - settings->setRecommendedFold ( static_cast< proshade_unsign > ( CSym->at(bestIndex)[0] ) ); - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, CSym->at(bestIndex) ); - - if ( settings->detectedSymmetry.size() == 0 ) { settings->setDetectedSymmetry ( CSym->at(bestIndex) ); } - } - else - { - settings->setRecommendedSymmetry ( "" ); - settings->setRecommendedFold ( 0 ); - } + //================================================ Release memory + for ( size_t iter = 0; iter < thresholdedCs.size(); iter++ ) { if ( thresholdedCs.at(iter) != nullptr ) { delete[] thresholdedCs.at(iter); } } //================================================ Done return ; @@ -2945,8 +2837,6 @@ void ProSHADE_internal_data::ProSHADE_data::saveRequestedSymmetryC ( ProSHADE_se there may be other symmetries present). \param[in] settings A pointer to settings class containing all the information required for map symmetry detection. - \param[in] DSym A vector of pointers to double arrays, each array being a single Dihedral symmetry entry. - \param[in] axes A vector to which all the axes of the requested symmetry (if any) will be saved. \param[in] cutIndices Map of each coefficient index to its correct bin cut to resolution. \param[in] fCoeffsCut The original map Fourier coefficients cut to resolution. \param[in] noBins Number of bins to be used (only up to the cut-off resolution). @@ -2957,32 +2847,32 @@ void ProSHADE_internal_data::ProSHADE_data::saveRequestedSymmetryC ( ProSHADE_se \param[in] yDim The number of indices along the y-axis of the of the array to be rotated. \param[in] zDim The number of indices along the z-axis of the of the array to be rotated. */ -void ProSHADE_internal_data::ProSHADE_data::saveRequestedSymmetryD ( ProSHADE_settings* settings, std::vector< proshade_double* >* DSym, std::vector< proshade_double* >* axes, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ) +void ProSHADE_internal_data::ProSHADE_data::saveRequestedSymmetryD ( ProSHADE_settings* settings, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ) { //================================================ Initialise variables proshade_unsign bestIndex = 0; proshade_double highestSym = 0.0; //================================================ Search for best fold - for ( proshade_unsign iter = 0; iter < static_cast ( DSym->size() ); iter++ ) + for ( proshade_unsign iter = 0; iter < static_cast ( this->dihedralSymmetries.size() ); iter++ ) { //============================================ Check if it is tbe correct fold - const FloatingPoint< proshade_double > lhs1 ( std::max ( DSym->at(iter)[0], DSym->at(iter)[7] ) ), rhs1 ( static_cast< proshade_double > ( settings->requestedSymmetryFold ) ); + const FloatingPoint< proshade_double > lhs1 ( std::max ( this->dihedralSymmetries.at(iter).at(0)[0], this->dihedralSymmetries.at(iter).at(1)[0] ) ), rhs1 ( static_cast< proshade_double > ( settings->requestedSymmetryFold ) ); if ( !lhs1.AlmostEquals ( rhs1 ) ) { continue; } //============================================ Check if peak height is decent - const FloatingPoint< proshade_double > lhs999a ( DSym->at(iter)[5] ), lhs999b ( DSym->at(iter)[12] ), rhs999 ( static_cast< proshade_double > ( -999.9 ) ); - if ( ( DSym->at(iter)[5] < settings->peakThresholdMin ) && !( lhs999a.AlmostEquals( rhs999 ) ) ) { continue; } - if ( ( DSym->at(iter)[12] < settings->peakThresholdMin ) && !( lhs999b.AlmostEquals( rhs999 ) ) ) { continue; } + const FloatingPoint< proshade_double > lhs999a ( this->dihedralSymmetries.at(iter).at(0)[5] ), lhs999b ( this->dihedralSymmetries.at(iter).at(1)[5] ), rhs999 ( static_cast< proshade_double > ( -999.9 ) ); + if ( ( this->dihedralSymmetries.at(iter).at(0)[5] < settings->peakThresholdMin ) && !( lhs999a.AlmostEquals( rhs999 ) ) ) { continue; } + if ( ( this->dihedralSymmetries.at(iter).at(1)[5] < settings->peakThresholdMin ) && !( lhs999b.AlmostEquals( rhs999 ) ) ) { continue; } //============================================ If correct, compute FSC - this->computeFSC ( settings, &DSym->at(iter)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); - this->computeFSC ( settings, &DSym->at(iter)[7], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); + this->computeFSC ( settings, &this->dihedralSymmetries.at(iter).at(0)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); + this->computeFSC ( settings, &this->dihedralSymmetries.at(iter).at(1)[0], cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); //============================================ If best, store it - if ( ( DSym->at(iter)[6] + DSym->at(iter)[13] ) > highestSym ) + if ( ( this->dihedralSymmetries.at(iter).at(0)[6] + this->dihedralSymmetries.at(iter).at(1)[6] ) > highestSym ) { - highestSym = ( DSym->at(iter)[6] + DSym->at(iter)[13] ); + highestSym = ( this->dihedralSymmetries.at(iter).at(0)[6] + this->dihedralSymmetries.at(iter).at(1)[6] ); bestIndex = iter; } } @@ -2990,21 +2880,16 @@ void ProSHADE_internal_data::ProSHADE_data::saveRequestedSymmetryD ( ProSHADE_se //================================================ Found? if ( highestSym > 0.0 ) { - settings->setRecommendedSymmetry ( "D" ); - settings->setRecommendedFold ( static_cast< proshade_unsign > ( std::max ( DSym->at(bestIndex)[0], DSym->at(bestIndex)[7] ) ) ); - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, &DSym->at(bestIndex)[0] ); - ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( axes, &DSym->at(bestIndex)[7] ); - - if ( settings->detectedSymmetry.size() == 0 ) - { - settings->setDetectedSymmetry ( &DSym->at(bestIndex)[0] ); - settings->setDetectedSymmetry ( &DSym->at(bestIndex)[7] ); - } + this->recommendedSymmetryType = "D"; + this->recommendedSymmetryFold = static_cast< proshade_unsign > ( std::max ( this->dihedralSymmetries.at(bestIndex).at(0)[0], this->dihedralSymmetries.at(bestIndex).at(1)[0] ) ); + + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->dihedralSymmetries.at(bestIndex).at(0)[0] ); + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &this->recommendedSymmetryValues, &this->dihedralSymmetries.at(bestIndex).at(1)[0] ); } else { - settings->setRecommendedSymmetry ( "" ); - settings->setRecommendedFold ( 0 ); + this->recommendedSymmetryType = "C"; + this->recommendedSymmetryFold = 1; } //================================================ Done @@ -3226,16 +3111,28 @@ std::vector > ProSHADE_internal_data::joinElement This function is essentially a wrapper for the overloaded version of this function. The purpose of this function is allow getting point group elements for axes detected in a particular structure. - \param[in] settings A pointer to settings class containing all the information required for map symmetry detection. \param[in] axesList A vector of ints specifying which C axes from the full list are members of the group. \param[in] groupType An optional string specifying for which symmetry type the group elements are to be computed. Leave empty if you want to use the supplied axes without any questions being asked. \param[in] matrixTolerance The maximum allowed trace difference for two matrices to still be considered the same. \param[out] val A vector containing a vector of 9 doubles (rotation matrix) for each group element for the requested group. */ -std::vector > ProSHADE_internal_data::ProSHADE_data::getAllGroupElements ( ProSHADE_settings* settings, std::vector< proshade_unsign > axesList, std::string groupType, proshade_double matrixTolerance ) +std::vector > ProSHADE_internal_data::ProSHADE_data::getAllGroupElements ( std::vector< proshade_unsign > axesList, std::string groupType, proshade_double matrixTolerance ) { //================================================ Initialise variables - std::vector > ret = this->getAllGroupElements ( &settings->allDetectedCAxes, axesList, groupType, matrixTolerance ); + std::vector< std::vector< proshade_double > > hlpVec; + std::vector< proshade_double > hlpVec2; + for ( size_t it1 = 0; it1 < this->cyclicSymmetries.size(); it1++ ) + { + hlpVec2.clear ( ); + for ( size_t it2 = 0; it2 < 7; it2++ ) + { + ProSHADE_internal_misc::addToDoubleVector ( &hlpVec2, this->cyclicSymmetries.at(it1)[it2] ); + } + ProSHADE_internal_misc::addToDoubleVectorVector ( &hlpVec, hlpVec2 ); + } + + //================================================ Get group elements + std::vector< std::vector< proshade_double > > ret = this->getAllGroupElements ( &hlpVec, axesList, groupType, matrixTolerance ); //================================================ Done return ( ret ); @@ -3554,7 +3451,7 @@ void ProSHADE_internal_data::ProSHADE_data::deepCopyMap ( proshade_double*& save } -/*! \brief This function takes prints the report for symmetry detection. +/*! \brief This function prints the report for symmetry detection. This is a very simple function which provides the basic textual output for the symmetry detection task. @@ -3563,7 +3460,7 @@ void ProSHADE_internal_data::ProSHADE_data::deepCopyMap ( proshade_double*& save void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResults ( ProSHADE_settings* settings ) { //================================================ Improve this! - if ( settings->recommendedSymmetryType == "" ) + if ( this->recommendedSymmetryType == "" || ( this->recommendedSymmetryType == "C" && this->recommendedSymmetryFold == 1 ) ) { ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, "", settings->messageShift ); ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, "Cannot predict any symmetry! There may still be symmetries detected, but ProSHADE algorithm does not consider them reliable.", settings->messageShift ); @@ -3572,19 +3469,19 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResults ( ProSHADE_set { std::stringstream ssHlp; std::vector< proshade_double > comMove = this->getMapCOMProcessChange ( ); - ssHlp << std::endl << "Detected " << settings->recommendedSymmetryType << " symmetry with fold " << settings->recommendedSymmetryFold << " about point [" << comMove.at(0) << " , " << comMove.at(1) << " , " << comMove.at(2) << "] away from centre of mass ."; + ssHlp << std::endl << "Detected " << this->recommendedSymmetryType << " symmetry with fold " << this->recommendedSymmetryFold << " about point [" << comMove.at(0) << " , " << comMove.at(1) << " , " << comMove.at(2) << "] away from centre of mass ."; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); - if ( settings->detectedSymmetry.size() > 0 ) + if ( this->recommendedSymmetryValues.size() > 0 ) { ssHlp.clear(); ssHlp.str ( "" ); ssHlp << " Fold X Y Z Angle Height Average FSC"; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); } - for ( proshade_unsign symIt = 0; symIt < static_cast ( settings->detectedSymmetry.size() ); symIt++ ) + for ( size_t symIt = 0; symIt < this->recommendedSymmetryValues.size(); symIt++ ) { ssHlp.clear(); ssHlp.str ( "" ); - ssHlp << std::showpos << std::fixed << std::setprecision(0) << " " << settings->detectedSymmetry.at(symIt)[0] << std::setprecision(5) << " " << settings->detectedSymmetry.at(symIt)[1] << " " << settings->detectedSymmetry.at(symIt)[2] << " " << settings->detectedSymmetry.at(symIt)[3] << " " << settings->detectedSymmetry.at(symIt)[4] << " " << settings->detectedSymmetry.at(symIt)[5] << " " << settings->detectedSymmetry.at(symIt)[6]; + ssHlp << std::showpos << std::fixed << std::setprecision(0) << " " << this->recommendedSymmetryValues.at(symIt)[0] << std::setprecision(5) << " " << this->recommendedSymmetryValues.at(symIt)[1] << " " << this->recommendedSymmetryValues.at(symIt)[2] << " " << this->recommendedSymmetryValues.at(symIt)[3] << " " << this->recommendedSymmetryValues.at(symIt)[4] << " " << this->recommendedSymmetryValues.at(symIt)[5] << " " << this->recommendedSymmetryValues.at(symIt)[6]; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); } } @@ -3594,16 +3491,16 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResults ( ProSHADE_set hlpSS3 << std::endl << "To facilitate manual checking for symmetries, the following is a list of all detected C symmetries:"; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, hlpSS3.str(), settings->messageShift ); - if ( settings->allDetectedCAxes.size() > 0 ) + if ( this->cyclicSymmetries.size() > 0 ) { ssHlp.clear(); ssHlp.str ( "" ); ssHlp << " Fold X Y Z Angle Height Average FSC"; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); } - for ( proshade_unsign symIt = 0; symIt < static_cast ( settings->allDetectedCAxes.size() ); symIt++ ) + for ( size_t symIt = 0; symIt < this->cyclicSymmetries.size(); symIt++ ) { ssHlp.clear(); ssHlp.str ( "" ); - ssHlp << std::showpos << std::fixed << std::setprecision(0) << " " << settings->allDetectedCAxes.at(symIt)[0] << std::setprecision(5) << " " << settings->allDetectedCAxes.at(symIt)[1] << " " << settings->allDetectedCAxes.at(symIt)[2] << " " << settings->allDetectedCAxes.at(symIt)[3] << " " << settings->allDetectedCAxes.at(symIt)[4] << " " << settings->allDetectedCAxes.at(symIt)[5] << " " << settings->allDetectedCAxes.at(symIt)[6]; + ssHlp << std::showpos << std::fixed << std::setprecision(0) << " " << this->cyclicSymmetries.at(symIt)[0] << std::setprecision(5) << " " << this->cyclicSymmetries.at(symIt)[1] << " " << this->cyclicSymmetries.at(symIt)[2] << " " << this->cyclicSymmetries.at(symIt)[3] << " " << this->cyclicSymmetries.at(symIt)[4] << " " << this->cyclicSymmetries.at(symIt)[5] << " " << this->cyclicSymmetries.at(symIt)[6]; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); } @@ -3612,6 +3509,160 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResults ( ProSHADE_set } +/*! \brief This function prints a single line of the symmetry detection results for a particular threshold. + + This is a very simple function which provides the advanced textual output for the symmetry detection task. + + \param[in] settings A pointer to settings class containing all the information required for map symmetry detection reporting. + \param[in] threshold The threshold to which the results are to be determined. + \param[in] cutIndices Map of each coefficient index to its correct bin cut to resolution. + \param[in] fCoeffsCut The original map Fourier coefficients cut to resolution. + \param[in] noBins Number of bins to be used (only up to the cut-off resolution). + \param[in] bindata Pre-allocated array of dimensions noBins x 12 serving as workspace for the bin summation and FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] binCounts Pre-allocated array of dimension noBins serving to store the bin sizes for FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] fscByBin This array will hold FSC values for each bin. This is useful in further computations, but could be internal for FSC only computation. + \param[in] xDim The number of indices along the x-axis of the of the array to be rotated. + \param[in] yDim The number of indices along the y-axis of the of the array to be rotated. + \param[in] zDim The number of indices along the z-axis of the of the array to be rotated. + */ +void ProSHADE_internal_data::ProSHADE_data::reportCurrentSymmetryResults ( ProSHADE_settings* settings, proshade_double threshold, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed cutXDim, proshade_signed cutYDim, proshade_signed cutZDim ) +{ + //================================================ Find results for the given threshold + this->determineRecommendedSymmetry ( settings, threshold, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + + //================================================ Improve this! + if ( this->recommendedSymmetryType == "" || ( this->recommendedSymmetryType == "C" && this->recommendedSymmetryFold == 1 ) ) + { + std::stringstream ssHlp; + ssHlp << std::showpos << std::fixed << std::setprecision(2) << " " << threshold << " C +1 +0.00000 +0.00000 +0.00000 +0.00000 +1.00000 +1.00000" << std::endl << "==========================================================================================================="; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + else + { + for ( size_t symIt = 0; symIt < this->recommendedSymmetryValues.size(); symIt++ ) + { + std::stringstream ssHlp; + ssHlp << std::showpos << std::fixed << std::setprecision(2) << " " << threshold << " " << this->recommendedSymmetryType << " " << std::showpos << std::fixed << std::setprecision(0) << " " << this->recommendedSymmetryValues.at(symIt)[0] << std::setprecision(5) << " " << this->recommendedSymmetryValues.at(symIt)[1] << " " << this->recommendedSymmetryValues.at(symIt)[2] << " " << this->recommendedSymmetryValues.at(symIt)[3] << " " << this->recommendedSymmetryValues.at(symIt)[4] << " " << this->recommendedSymmetryValues.at(symIt)[5] << " " << this->recommendedSymmetryValues.at(symIt)[6]; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + std::stringstream ssHlp; + ssHlp << "==========================================================================================================="; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + + //================================================ Done + return ; +} + +/*! \brief This function takes prints the report for symmetry detection using multiple thresholds.. + + This is a very simple function which provides the advanced textual output for the symmetry detection task. + + \param[in] settings A pointer to settings class containing all the information required for map symmetry detection reporting. + */ +void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResultsList ( ProSHADE_settings* settings ) +{ + //================================================ Initialise variables + std::stringstream ssHlp; + std::vector< proshade_double > thrLevels; + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.95 ); + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.90 ); + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.80 ); + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.70 ); + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.60 ); + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.50 ); + ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.40 ); + + //================================================ Silence the search + proshade_signed origVerbose = settings->verbose; + settings->verbose = 0; + + //================================================ Prepare FSC computation memory and variables + fftw_complex* fCoeffsCut; + proshade_double **bindata, *fscByBin; + proshade_signed *cutIndices, *binCounts, noBins, cutXDim, cutYDim, cutZDim; + this->prepareFSCFourierMemory ( cutIndices, fCoeffsCut, &noBins, bindata, binCounts, fscByBin, settings->requestedResolution, &cutXDim, &cutYDim, &cutZDim ); + + //================================================ Print intro to symmetry detection + ssHlp.clear(); ssHlp.str ( "" ); + std::vector< proshade_double > comMove = this->getMapCOMProcessChange ( ); + ssHlp << std::endl << "Detecting symmetries about point [" << comMove.at(0) << " , " << comMove.at(1) << " , " << comMove.at(2) << "] away from centre of mass ."; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + + //================================================ Run default detection + this->determineRecommendedSymmetry ( settings, settings->fscThreshold, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + + //================================================ Print intro to proshade default + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << std::endl << "ProSHADE default symmetry detection algorithm claims the symmetry to be " << this->recommendedSymmetryType << "-" << this->recommendedSymmetryFold << " with axes:" << std::endl << "======================================================================================"; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + + if ( this->recommendedSymmetryValues.size() > 0 ) + { + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << " Type Fold X Y Z Angle Height Average FSC"; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + else + { + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << " Type Fold X Y Z Angle Height Average FSC" << std::endl << " C +1 +0.00000 +0.00000 +0.00000 +0.00000 +1.00000 +1.00000"; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + for ( size_t symIt = 0; symIt < this->recommendedSymmetryValues.size(); symIt++ ) + { + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << " " << this->recommendedSymmetryType << " " << std::showpos << std::fixed << std::setprecision(0) << " " << this->recommendedSymmetryValues.at(symIt)[0] << std::setprecision(5) << " " << this->recommendedSymmetryValues.at(symIt)[1] << " " << this->recommendedSymmetryValues.at(symIt)[2] << " " << this->recommendedSymmetryValues.at(symIt)[3] << " " << this->recommendedSymmetryValues.at(symIt)[4] << " " << this->recommendedSymmetryValues.at(symIt)[5] << " " << this->recommendedSymmetryValues.at(symIt)[6]; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + + //================================================ Print intro to table + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << std::endl << std::endl << "Symmetry detection results per FSC threshold levels:" << std::endl << "====================================================";; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << std::endl << " Threshold Type Fold X Y Z Angle Height Average FSC" << std::endl << "==========================================================================================================="; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + + //================================================ For each requested level, get the results + for ( size_t lIt = 0; lIt < thrLevels.size(); lIt++ ) + { + this->reportCurrentSymmetryResults ( settings, thrLevels.at(lIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + } + + //================================================ Release FSC computation memory + for (size_t binIt = 0; binIt < static_cast< size_t > ( noBins ); binIt++ ) { delete[] bindata[binIt]; } + delete[] bindata; + delete[] binCounts; + delete[] cutIndices; + fftw_free ( fCoeffsCut ); + + //================================================ Set verbosity back + settings->verbose = origVerbose; + + //================================================ Print all axes + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << std::endl << std::endl << "To facilitate manual checking for symmetries, the following is a list of all detected C symmetries:"; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + + if ( this->cyclicSymmetries.size() > 0 ) + { + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << " Type Fold X Y Z Angle Height Average FSC"; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + for ( size_t symIt = 0; symIt < this->cyclicSymmetries.size(); symIt++ ) + { + ssHlp.clear(); ssHlp.str ( "" ); + ssHlp << " C " << std::showpos << std::fixed << std::setprecision(0) << " " << this->cyclicSymmetries.at(symIt)[0] << std::setprecision(5) << " " << this->cyclicSymmetries.at(symIt)[1] << " " << this->cyclicSymmetries.at(symIt)[2] << " " << this->cyclicSymmetries.at(symIt)[3] << " " << this->cyclicSymmetries.at(symIt)[4] << " " << this->cyclicSymmetries.at(symIt)[5] << " " << this->cyclicSymmetries.at(symIt)[6]; + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); + } + + //================================================ Done + return ; +} + /*! \brief This function finds the centre of mass of the internal map representation. This function simply computes the centre of mass for the given ProSHADE_data object map in the "real space" (i.e. the space that counts Angstroms from the bottom left further corner). These are then saved into the ProSHADE_data object. @@ -4102,6 +4153,7 @@ proshade_signed* ProSHADE_internal_data::ProSHADE_data::getZToPtr ( ) { //================================================ Return the requested value return ( &this->zTo ); + } /*! \brief This function allows access to the map X axis origin value. @@ -4112,6 +4164,7 @@ proshade_signed* ProSHADE_internal_data::ProSHADE_data::getXAxisOrigin ( ) { //================================================ Return the requested value return ( &this->xAxisOrigin ); + } /*! \brief This function allows access to the map Y axis origin value. @@ -4122,6 +4175,7 @@ proshade_signed* ProSHADE_internal_data::ProSHADE_data::getYAxisOrigin ( ) { //================================================ Return the requested value return ( &this->yAxisOrigin ); + } /*! \brief This function allows access to the map Z axis origin value. @@ -4132,6 +4186,7 @@ proshade_signed* ProSHADE_internal_data::ProSHADE_data::getZAxisOrigin ( ) { //================================================ Return the requested value return ( &this->zAxisOrigin ); + } /*! \brief This function allows access to the first map array value address. @@ -4142,6 +4197,7 @@ proshade_double*& ProSHADE_internal_data::ProSHADE_data::getInternalMap ( ) { //================================================ Return the requested value return ( this->internalMap ); + } /*! \brief This function allows access to the translation function through a pointer. @@ -4152,6 +4208,7 @@ proshade_complex* ProSHADE_internal_data::ProSHADE_data::getTranslationFnPointer { //================================================ Return the requested value return ( this->translationMap ); + } /*! \brief This function allows access to the translation caused by structure processing. @@ -4170,6 +4227,29 @@ std::vector< proshade_double > ProSHADE_internal_data::ProSHADE_data::getMapCOMP //================================================ Return the requested value return ( ret ); + +} + +/*! \brief This function allows access to the list of detected cyclic axes. + + \param[out] cyclicSymmetries Vector of the cyclic axes detected in the structure. +*/ +std::vector< proshade_double* >* ProSHADE_internal_data::ProSHADE_data::getCyclicAxes ( void ) +{ + //================================================ Return the requested value + return ( &this->cyclicSymmetries ); + +} + +/*! \brief This function allows access to the list of detected dihedral axes. + + \param[out] dihedralSymmetries Vector of vectors containing the list of detected dihedral symmetries. +*/ +std::vector< std::vector< proshade_double* > >* ProSHADE_internal_data::ProSHADE_data::getDihedralAxes ( void ) +{ + //================================================ Return the requested value + return ( &this->dihedralSymmetries ); + } /*! \brief This function allows setting the integration weight for the object. @@ -4470,36 +4550,31 @@ void ProSHADE_internal_data::ProSHADE_data::getRotMatrixFromRotFunInds ( proshad } /*! \brief This function simply returns the detected recommended symmetry type. - - \param[in] settings A pointer to settings class containing all the information required for map manipulation. */ -std::string ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryType ( ProSHADE_settings* settings ) +std::string ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryType ( ) { //================================================ Return the value - return ( settings->recommendedSymmetryType ); + return ( this->recommendedSymmetryType ); } /*! \brief This function simply returns the detected recommended symmetry fold. - - \param[in] settings A pointer to settings class containing all the information required for map manipulation. */ -proshade_unsign ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryFold ( ProSHADE_settings* settings ) +proshade_unsign ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryFold ( ) { //================================================ Return the value - return ( settings->recommendedSymmetryFold ); + return ( this->recommendedSymmetryFold ); } /*! \brief This function returns the number of detected recommended symmetry axes. - \param[in] settings A pointer to settings class containing all the information required for map manipulation. \param[out] val The length of the recommended symmetry axes vector. */ -proshade_unsign ProSHADE_internal_data::ProSHADE_data::getNoRecommendedSymmetryAxes ( ProSHADE_settings* settings ) +proshade_unsign ProSHADE_internal_data::ProSHADE_data::getNoRecommendedSymmetryAxes ( ) { //================================================ Return the value - return ( static_cast ( settings->detectedSymmetry.size() ) ); + return ( static_cast< proshade_unsign > ( this->recommendedSymmetryValues.size() ) ); } /*! \brief This function returns a single symmetry axis as a vector of strings from the recommended symmetry axes list. @@ -4511,7 +4586,7 @@ proshade_unsign ProSHADE_internal_data::ProSHADE_data::getNoRecommendedSymmetryA std::vector< std::string > ProSHADE_internal_data::ProSHADE_data::getSymmetryAxis ( ProSHADE_settings* settings, proshade_unsign axisNo ) { //================================================ Sanity checks - if ( static_cast ( settings->detectedSymmetry.size() ) <= axisNo ) + if ( static_cast ( this->recommendedSymmetryValues.size() ) <= axisNo ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Requested symmetry index does not exist. Returning empty vector.", "WS00039" ); return ( std::vector< std::string > ( ) ); @@ -4522,31 +4597,31 @@ std::vector< std::string > ProSHADE_internal_data::ProSHADE_data::getSymmetryAxi //================================================ Input the axis data as strings std::stringstream ssHlp; - ssHlp << settings->detectedSymmetry.at(axisNo)[0]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[0]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); - ssHlp << settings->detectedSymmetry.at(axisNo)[1]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[1]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); - ssHlp << settings->detectedSymmetry.at(axisNo)[2]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[2]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); - ssHlp << settings->detectedSymmetry.at(axisNo)[3]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[3]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); - ssHlp << settings->detectedSymmetry.at(axisNo)[4]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[4]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); - ssHlp << settings->detectedSymmetry.at(axisNo)[5]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[5]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); - ssHlp << settings->detectedSymmetry.at(axisNo)[6]; + ssHlp << this->recommendedSymmetryValues.at(axisNo)[6]; ProSHADE_internal_misc::addToStringVector ( &ret, ssHlp.str() ); ssHlp.str ( "" ); diff --git a/proshade/src/proshade/ProSHADE_data.hpp b/proshade/src/proshade/ProSHADE_data.hpp index b4cbd775..11a89932 100644 --- a/proshade/src/proshade/ProSHADE_data.hpp +++ b/proshade/src/proshade/ProSHADE_data.hpp @@ -17,8 +17,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -139,6 +139,17 @@ namespace ProSHADE_internal_data bool isEmpty; //!< This variable stated whether the class contains any information. proshade_unsign inputOrder; //!< This value is the input order - it is useful to know for writing out files, so that they would not overwrite the same name multiple times. + public: + //============================================ Symmetry results holding vactors + std::vector< proshade_double* > cyclicSymmetries; //!< This is where the detected cyclic ("C") symmetries will be kept. + std::vector< std::vector< proshade_double* > > dihedralSymmetries; //!< This is where the detected dihedral ("D") symmetries will be kept. + std::vector< proshade_double* > tetrahedralSymmetries; //!< This is where the detected tetrahedral ("T") symmetries will be kept. + std::vector< proshade_double* > octahedralSymmetries; //!< This is where the detected octahedral ("O") symmetries will be kept. + std::vector< proshade_double* > icosahedralSymmetries; //!< This is where the detected icosahedral ("I") symmetries will be kept. + std::vector< proshade_double* > recommendedSymmetryValues; //!< The axes and other info of the recommended symmetry for the structure. + std::string recommendedSymmetryType; //!< The symmetry type that ProSHADE finds the best fitting for the structure. Possible values are "" for none, "C" for cyclic, "D" for Dihedral, "T" for Tetrahedral, "O" for Octahedral and "I" for Icosahedral. C and D types also have fold value associated. + proshade_unsign recommendedSymmetryFold; //!< The fold of the recommended symmetry C or D type, 0 otherwise. + protected: void figureIndexStartStop ( void ); void setPDBMapValues ( void ); @@ -210,25 +221,25 @@ namespace ProSHADE_internal_data void getRealTranslationFunction ( double *trsFunReal, int len ); void getImagTranslationFunction ( double *trsFunImag, int len ); void getRotMatrixFromRotFunInds ( proshade_signed aI, proshade_signed bI, proshade_signed gI, double *rotMat, int len ); - int so3CoeffsArrayIndex ( proshade_signed order1, proshade_signed order2, proshade_signed band ); - std::vector< proshade_double* > getDihedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); - std::vector< proshade_double* > getTetrahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); - std::vector< proshade_double* > getOctahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); - std::vector< proshade_double* > getIcosahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); + int so3CoeffsArrayIndex ( proshade_signed order1, proshade_signed order2, proshade_signed band ); + void getDihedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); std::vector< proshade_double* > decidePolyFromList ( ProSHADE_settings* settings, std::vector < std::vector< proshade_double* > >* polyList, size_t fullGroupSize, std::vector< proshade_double* >* CSyms, proshade_double tolerance, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ); - std::vector< std::vector< proshade_double* > > getPredictedIcosahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); - std::vector< std::vector< proshade_double* > > getPredictedOctahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); - std::vector< std::vector< proshade_double* > > getPredictedTetrahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ); - void detectSymmetryFromAngleAxisSpace ( ProSHADE_settings* settings, std::vector< proshade_double* >* axes, std::vector < std::vector< proshade_double > >* allCs ); + void getPredictedIcosahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, + proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ); + void getPredictedOctahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, + proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ); + void getPredictedTetrahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, + proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ); + void detectSymmetryFromAngleAxisSpace ( ProSHADE_settings* settings ); std::vector< proshade_double* > getCyclicSymmetriesListFromAngleAxis ( ProSHADE_settings* settings ); std::vector< proshade_double* > findRequestedCSymmetryFromAngleAxis ( ProSHADE_settings* settings, proshade_unsign fold, proshade_double* peakThres ); - void saveDetectedSymmetries ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSyms, std::vector < std::vector< proshade_double > >* allCs ); - std::string getRecommendedSymmetryType ( ProSHADE_settings* settings ); - proshade_unsign getRecommendedSymmetryFold ( ProSHADE_settings* settings ); + std::string getRecommendedSymmetryType ( void ); + proshade_unsign getRecommendedSymmetryFold ( void ); proshade_unsign getNoRecommendedSymmetryAxes ( ProSHADE_settings* settings ); + proshade_unsign getNoRecommendedSymmetryAxes ( void ); std::vector< std::string > getSymmetryAxis ( ProSHADE_settings* settings, proshade_unsign axisNo ); void prepareFSCFourierMemory ( proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed* noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_single resolution, @@ -239,18 +250,17 @@ namespace ProSHADE_internal_data proshade_double computeFSC ( ProSHADE_settings* settings, proshade_double* sym, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim, proshade_unsign rotNumber = 1 ); - void saveRecommendedSymmetry ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSym, std::vector< proshade_double* >* DSym, - std::vector< proshade_double* >* TSym, std::vector< proshade_double* >* OSym, - std::vector< proshade_double* >* ISym, std::vector< proshade_double* >* axes, proshade_signed*& cutIndices, - fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, + void determineRecommendedSymmetry ( ProSHADE_settings* settings, proshade_double threshold, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ); - void saveRequestedSymmetryC ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSym, std::vector< proshade_double* >* axes ); - void saveRequestedSymmetryD ( ProSHADE_settings* settings, std::vector< proshade_double* >* DSym, std::vector< proshade_double* >* axes, proshade_signed*& cutIndices, - fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, - proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ); - std::vector > getAllGroupElements ( ProSHADE_settings* settings, std::vector< proshade_unsign > axesList, std::string groupType = "", proshade_double matrixTolerance = 0.05 ); + void saveRequestedSymmetryD ( ProSHADE_settings* settings, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, + proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed cutXDim, proshade_signed cutYDim, proshade_signed cutZDim ); + std::vector > getAllGroupElements ( std::vector< proshade_unsign > axesList, std::string groupType = "", proshade_double matrixTolerance = 0.05 ); std::vector > getAllGroupElements ( std::vector < std::vector< proshade_double > >* allCs, std::vector< proshade_unsign > axesList, std::string groupType = "", proshade_double matrixTolerance = 0.05 ); void reportSymmetryResults ( ProSHADE_settings* settings ); + void reportCurrentSymmetryResults ( ProSHADE_settings* settings, proshade_double threshold, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, + proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed cutXDim, + proshade_signed cutYDim, proshade_signed cutZDim ); + void reportSymmetryResultsList ( ProSHADE_settings* settings ); //============================================ Map overlay functions void getOverlayRotationFunction ( ProSHADE_settings* settings, ProSHADE_internal_data::ProSHADE_data* obj2 ); @@ -312,6 +322,8 @@ namespace ProSHADE_internal_data proshade_double*& getInternalMap ( void ); proshade_complex* getTranslationFnPointer ( void ); std::vector< proshade_double > getMapCOMProcessChange ( void ); + std::vector< proshade_double* >* getCyclicAxes ( void ); + std::vector< std::vector< proshade_double* > >* getDihedralAxes ( void ); //============================================ Mutator functions void setIntegrationWeight ( proshade_double intW ); diff --git a/proshade/src/proshade/ProSHADE_distances.cpp b/proshade/src/proshade/ProSHADE_distances.cpp index c6a436f4..01e374d0 100644 --- a/proshade/src/proshade/ProSHADE_distances.cpp +++ b/proshade/src/proshade/ProSHADE_distances.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_distances.hpp b/proshade/src/proshade/ProSHADE_distances.hpp index bad13ce7..2d68b6c8 100644 --- a/proshade/src/proshade/ProSHADE_distances.hpp +++ b/proshade/src/proshade/ProSHADE_distances.hpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //============================================ ProSHADE diff --git a/proshade/src/proshade/ProSHADE_exceptions.cpp b/proshade/src/proshade/ProSHADE_exceptions.cpp index a6781759..9614022f 100644 --- a/proshade/src/proshade/ProSHADE_exceptions.cpp +++ b/proshade/src/proshade/ProSHADE_exceptions.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_exceptions.hpp b/proshade/src/proshade/ProSHADE_exceptions.hpp index 0ac097e4..8bec6961 100644 --- a/proshade/src/proshade/ProSHADE_exceptions.hpp +++ b/proshade/src/proshade/ProSHADE_exceptions.hpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_io.cpp b/proshade/src/proshade/ProSHADE_io.cpp index b12241c2..7d6019e6 100644 --- a/proshade/src/proshade/ProSHADE_io.cpp +++ b/proshade/src/proshade/ProSHADE_io.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -304,7 +304,7 @@ void ProSHADE_internal_io::applyMask ( proshade_double*& map, std::string maskFi //================================================ Report progress std::stringstream hlpSS; hlpSS << "Reading mask " << maskFile; - ProSHADE_internal_messages::printProgressMessage ( verbose, 2, hlpSS.str() ); + ProSHADE_internal_messages::printProgressMessage ( verbose, 2, hlpSS.str(), messageShift ); //================================================ Are we reading from array or from file? if ( ( maskArray != nullptr ) && ( maXInds != 0 ) && ( maYInds != 0 ) && ( maZInds != 0 ) ) @@ -590,7 +590,7 @@ void ProSHADE_internal_io::applyWeights ( proshade_double*& map, std::string wei //================================================ Report progress std::stringstream hlpSS; hlpSS << "Reading weights " << weightsFile; - ProSHADE_internal_messages::printProgressMessage ( verbose, 2, hlpSS.str() ); + ProSHADE_internal_messages::printProgressMessage ( verbose, 2, hlpSS.str(), messageShift ); //================================================ Are we reading from file, or from array? if ( ( weightsArray != nullptr ) && ( waXInds != 0 ) && ( waYInds != 0 ) && ( waZInds != 0 ) ) diff --git a/proshade/src/proshade/ProSHADE_io.hpp b/proshade/src/proshade/ProSHADE_io.hpp index edf27fd0..633ee2c3 100644 --- a/proshade/src/proshade/ProSHADE_io.hpp +++ b/proshade/src/proshade/ProSHADE_io.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_mapManip.cpp b/proshade/src/proshade/ProSHADE_mapManip.cpp index 63581c71..a9ca2854 100644 --- a/proshade/src/proshade/ProSHADE_mapManip.cpp +++ b/proshade/src/proshade/ProSHADE_mapManip.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -1454,12 +1454,9 @@ void ProSHADE_internal_mapManip::reSampleMapToResolutionFourier ( proshade_doubl if ( newZDim % 2 != 0 ) { newZDim += 1; } proshade_signed preXChange, preYChange, preZChange; - if ( ( xDimS % 2 ) == 0 ) { preXChange = static_cast< proshade_signed > ( std::ceil ( ( static_cast ( xDimS ) - static_cast ( newXDim ) ) / 2 ) ); } - else { preXChange = static_cast< proshade_signed > ( std::floor ( ( static_cast ( xDimS ) - static_cast ( newXDim ) ) / 2 ) ); } - if ( ( yDimS % 2 ) == 0 ) { preYChange = static_cast< proshade_signed > ( std::ceil ( ( static_cast ( yDimS ) - static_cast ( newYDim ) ) / 2 ) ); } - else { preYChange = static_cast< proshade_signed > ( std::floor ( ( static_cast ( yDimS ) - static_cast ( newYDim ) ) / 2 ) ); } - if ( ( zDimS % 2 ) == 0 ) { preZChange = static_cast< proshade_signed > ( std::ceil ( ( static_cast ( zDimS ) - static_cast ( newZDim ) ) / 2 ) ); } - else { preZChange = static_cast< proshade_signed > ( std::floor ( ( static_cast ( zDimS ) - static_cast ( newZDim ) ) / 2 ) ); } + preXChange = static_cast< proshade_signed > ( std::floor ( ( static_cast ( xDimS ) - static_cast ( newXDim ) ) / 2.0f ) ); + preYChange = static_cast< proshade_signed > ( std::floor ( ( static_cast ( yDimS ) - static_cast ( newYDim ) ) / 2.0f ) ); + preZChange = static_cast< proshade_signed > ( std::floor ( ( static_cast ( zDimS ) - static_cast ( newZDim ) ) / 2.0f ) ); proshade_signed postXChange = static_cast ( xDimS ) - ( preXChange + static_cast ( newXDim ) ); proshade_signed postYChange = static_cast ( yDimS ) - ( preYChange + static_cast ( newYDim ) ); @@ -1467,17 +1464,17 @@ void ProSHADE_internal_mapManip::reSampleMapToResolutionFourier ( proshade_doubl proshade_unsign origSizeArr = 0, newSizeArr = 0; proshade_double normFactor = static_cast ( xDimS * yDimS * zDimS ); - + //================================================ Manage memory fftw_complex *origMap, *fCoeffs, *newFCoeffs, *newMap; fftw_plan planForwardFourier, planBackwardRescaledFourier; allocateResolutionFourierMemory ( origMap, fCoeffs, newFCoeffs, newMap, planForwardFourier, planBackwardRescaledFourier, xDimS, yDimS, zDimS, newXDim, newYDim, newZDim ); - + //================================================ Fill maps with data and zeroes - for ( proshade_unsign iter = 0; iter < static_cast ( xDimS * yDimS * zDimS ); iter++ ) { origMap[iter][0] = map[iter]; origMap[iter][1] = 0.0; } + for ( proshade_unsign iter = 0; iter < static_cast ( normFactor ); iter++ ) { origMap[iter][0] = map[iter]; origMap[iter][1] = 0.0; } for ( proshade_unsign iter = 0; iter < static_cast ( newXDim * newYDim * newZDim ); iter++ ) { newFCoeffs[iter][0] = 0.0; newFCoeffs[iter][1] = 0.0; } - + //================================================ Get the Fourier coeffs fftw_execute ( planForwardFourier ); diff --git a/proshade/src/proshade/ProSHADE_mapManip.hpp b/proshade/src/proshade/ProSHADE_mapManip.hpp index d4c60061..68308872 100644 --- a/proshade/src/proshade/ProSHADE_mapManip.hpp +++ b/proshade/src/proshade/ProSHADE_mapManip.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_maths.cpp b/proshade/src/proshade/ProSHADE_maths.cpp index e4ef4747..e5201713 100644 --- a/proshade/src/proshade/ProSHADE_maths.cpp +++ b/proshade/src/proshade/ProSHADE_maths.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_maths.hpp b/proshade/src/proshade/ProSHADE_maths.hpp index 54ef5f37..50ca3edc 100644 --- a/proshade/src/proshade/ProSHADE_maths.hpp +++ b/proshade/src/proshade/ProSHADE_maths.hpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_messages.cpp b/proshade/src/proshade/ProSHADE_messages.cpp index df76c822..58742ff4 100644 --- a/proshade/src/proshade/ProSHADE_messages.cpp +++ b/proshade/src/proshade/ProSHADE_messages.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -237,7 +237,7 @@ void ProSHADE_internal_messages::printHelp [[noreturn]] ( void ) std::cout << " to be detected between structures that appear identical. By " << std::endl; std::cout << " default negative density is removed, this option keeps it in. " << std::endl; std::cout << " " << std::endl; - std::cout << " -K or --oversamplRate [DEFAULT: 0.75] " << std::endl; + std::cout << " -K or --oversamplRate [DEFAULT: 0.50] " << std::endl; std::cout << " The rate at which the map resolution will be over-sampled compared " << std::endl; std::cout << " to the standard sampling of resolution / 2 indices per Angstrom. " << std::endl; std::cout << " Note, that this will only take effect if either the Fourier or the " << std::endl; diff --git a/proshade/src/proshade/ProSHADE_messages.hpp b/proshade/src/proshade/ProSHADE_messages.hpp index ce5a5b1d..256d32b2 100644 --- a/proshade/src/proshade/ProSHADE_messages.hpp +++ b/proshade/src/proshade/ProSHADE_messages.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //============================================ ProSHADE diff --git a/proshade/src/proshade/ProSHADE_misc.cpp b/proshade/src/proshade/ProSHADE_misc.cpp index d1bb89d0..bd064d4d 100644 --- a/proshade/src/proshade/ProSHADE_misc.cpp +++ b/proshade/src/proshade/ProSHADE_misc.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -244,6 +244,28 @@ void ProSHADE_internal_misc::addToDoubleVectorVector ( std::vector < std::vector } +/*! \brief Adds the element to the vector of vectors of double pointers. + + This function takes a pointer to a vector of vectors of double pointers and a single vector of double pointers and adds this element to the end of + the vector of vectors of pointers. The reason for this function is to make vector elongation C++ standard independent (push_back vs. emplace_back) + + \param[in] vecToAddTo Pointer to vector of vectors of double pointers which should be elongated. + \param[in] elementToAdd vector of double pointers to be added to the back of the vector. + */ +void ProSHADE_internal_misc::addToDblPtrVectorVector ( std::vector < std::vector < proshade_double* > >* vecToAddTo, std::vector < proshade_double* > elementToAdd ) +{ + //================================================ Based on the compiler C++11 support, use the correct vector addition function. +#if __cplusplus >= 201103L + vecToAddTo->emplace_back ( elementToAdd ); +#else + vecToAddTo->push_back ( elementToAdd ); +#endif + + //================================================ Done + return ; + +} + /*! \brief This function compares two arrays of two based on the fifth number, sorting lowest first. \param[in] a The first array to compare. diff --git a/proshade/src/proshade/ProSHADE_misc.hpp b/proshade/src/proshade/ProSHADE_misc.hpp index f8df5893..2f098e21 100644 --- a/proshade/src/proshade/ProSHADE_misc.hpp +++ b/proshade/src/proshade/ProSHADE_misc.hpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -46,6 +46,7 @@ namespace ProSHADE_internal_misc void addToUnsPtrVector ( std::vector < proshade_unsign* >* vecToAddTo, proshade_unsign* elementToAdd ); void addToUnsignVectorVector ( std::vector < std::vector < proshade_unsign > >* vecToAddTo, std::vector < proshade_unsign > elementToAdd ); void addToDoubleVectorVector ( std::vector < std::vector < proshade_double > >* vecToAddTo, std::vector < proshade_double > elementToAdd ); + void addToDblPtrVectorVector ( std::vector < std::vector < proshade_double* > >* vecToAddTo, std::vector < proshade_double* > elementToAdd ); bool sortSymHlp ( const proshade_double* a, const proshade_double* b ); bool sortSymHlpInv ( const proshade_double* a, const proshade_double* b ); diff --git a/proshade/src/proshade/ProSHADE_overlay.cpp b/proshade/src/proshade/ProSHADE_overlay.cpp index 07800044..e9a2a7de 100644 --- a/proshade/src/proshade/ProSHADE_overlay.cpp +++ b/proshade/src/proshade/ProSHADE_overlay.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_overlay.hpp b/proshade/src/proshade/ProSHADE_overlay.hpp index 16a83f17..acf18900 100644 --- a/proshade/src/proshade/ProSHADE_overlay.hpp +++ b/proshade/src/proshade/ProSHADE_overlay.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_peakSearch.cpp b/proshade/src/proshade/ProSHADE_peakSearch.cpp index f55e2a27..d7be12ad 100644 --- a/proshade/src/proshade/ProSHADE_peakSearch.cpp +++ b/proshade/src/proshade/ProSHADE_peakSearch.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_peakSearch.hpp b/proshade/src/proshade/ProSHADE_peakSearch.hpp index 36f6266d..d54d9174 100644 --- a/proshade/src/proshade/ProSHADE_peakSearch.hpp +++ b/proshade/src/proshade/ProSHADE_peakSearch.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_precomputedValues.cpp b/proshade/src/proshade/ProSHADE_precomputedValues.cpp index 3a8266a6..3d5ca199 100644 --- a/proshade/src/proshade/ProSHADE_precomputedValues.cpp +++ b/proshade/src/proshade/ProSHADE_precomputedValues.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_precomputedValues.hpp b/proshade/src/proshade/ProSHADE_precomputedValues.hpp index a8c02230..797e9ee2 100644 --- a/proshade/src/proshade/ProSHADE_precomputedValues.hpp +++ b/proshade/src/proshade/ProSHADE_precomputedValues.hpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_settings.hpp b/proshade/src/proshade/ProSHADE_settings.hpp index 0b07c222..68b45c56 100644 --- a/proshade/src/proshade/ProSHADE_settings.hpp +++ b/proshade/src/proshade/ProSHADE_settings.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -132,8 +132,6 @@ class ProSHADE_settings proshade_double axisErrTolerance; //!< Allowed error on vector axis in in dot product ( acos ( 1 - axErr ) is the allowed difference in radians ). bool axisErrToleranceDefault; proshade_double minSymPeak; //!< Minimum average peak for symmetry axis to be considered as "real". - std::string recommendedSymmetryType; //!< The symmetry type that ProSHADE finds the best fitting for the structure. Possible values are "" for none, "C" for cyclic, "D" for Dihedral, "T" for Tetrahedral, "O" for Octahedral and "I" for Icosahedral. C and D types also have fold value associated. - proshade_unsign recommendedSymmetryFold; //!< The fold of the recommended symmetry C or D type, 0 otherwise. std::string requestedSymmetryType; //!< The symmetry type requested by the user. Allowed values are C, D, T, O and I. proshade_unsign requestedSymmetryFold; //!< The fold of the requested symmetry (only applicable to C and D symmetry types). bool useBiCubicInterpolationOnPeaks; //!< This variable switch decides whether best symmetry is detected from peak indices, or whether bicubic interpolation is done to seatch for better axis between indices. @@ -153,15 +151,6 @@ class ProSHADE_settings //================================================ Settings regarding verbosity of the program proshade_signed verbose; //!< Should the software report on the progress, or just be quiet? Value between -1 (nothing) and 4 (loud) proshade_signed messageShift; //!< This value allows shifting the messages to create more readable log for sub-processes. - -public: - //================================================ Symmetry results holding values. This is required for Python being able to access the results without having the ProSHADE_run object. - std::vector < proshade_double* > detectedSymmetry; //!< The vector of detected symmetry axes. - std::vector < std::vector< proshade_double > > allDetectedCAxes; //!< The vector of all detected cyclic symmetry axes. - std::vector < std::vector< proshade_unsign > > allDetectedDAxes; //!< The vector of all detected dihedral symmetry axes indices in allDetectedCAxes. - std::vector < proshade_unsign > allDetectedTAxes; //!< The vector of all detected tetrahedral symmetry axes indices in allDetectedCAxes. - std::vector < proshade_unsign > allDetectedOAxes; //!< The vector of all detected octahedral symmetry axes indices in allDetectedCAxes. - std::vector < proshade_unsign > allDetectedIAxes; //!< The vector of all detected icosahedral symmetry axes indices in allDetectedCAxes. public: // maybe make this protected? //================================================ Variable modifying functions @@ -236,12 +225,8 @@ class ProSHADE_settings void __declspec(dllexport) setAxisComparisonThreshold ( proshade_double axThres ); void __declspec(dllexport) setAxisComparisonThresholdBehaviour ( bool behav ); void __declspec(dllexport) setMinimumPeakForAxis ( proshade_double minSP ); - void __declspec(dllexport) setRecommendedSymmetry ( std::string val ); - void __declspec(dllexport) setRecommendedFold ( proshade_unsign val ); void __declspec(dllexport) setRequestedSymmetry ( std::string val ); void __declspec(dllexport) setRequestedFold ( proshade_unsign val ); - void __declspec(dllexport) setDetectedSymmetry ( proshade_double* sym ); - void __declspec(dllexport) cleanDetectedSymmetry ( void ); void __declspec(dllexport) setOverlaySaveFile ( std::string filename ); void __declspec(dllexport) setOverlayJsonFile ( std::string filename ); void __declspec(dllexport) setBicubicInterpolationSearch ( bool bicubPeaks ); @@ -297,12 +282,8 @@ class ProSHADE_settings void setAxisComparisonThreshold ( proshade_double axThres ); void setAxisComparisonThresholdBehaviour ( bool behav ); void setMinimumPeakForAxis ( proshade_double minSP ); - void setRecommendedSymmetry ( std::string val ); - void setRecommendedFold ( proshade_unsign val ); void setRequestedSymmetry ( std::string val ); void setRequestedFold ( proshade_unsign val ); - void setDetectedSymmetry ( proshade_double* sym ); - void cleanDetectedSymmetry ( void ); void setOverlaySaveFile ( std::string filename ); void setOverlayJsonFile ( std::string filename ); void setBicubicInterpolationSearch ( bool bicubPeaks ); diff --git a/proshade/src/proshade/ProSHADE_spheres.cpp b/proshade/src/proshade/ProSHADE_spheres.cpp index 78d9032f..35f64cab 100644 --- a/proshade/src/proshade/ProSHADE_spheres.cpp +++ b/proshade/src/proshade/ProSHADE_spheres.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //============================================ ProSHADE diff --git a/proshade/src/proshade/ProSHADE_spheres.hpp b/proshade/src/proshade/ProSHADE_spheres.hpp index 3a8245da..589faf8a 100644 --- a/proshade/src/proshade/ProSHADE_spheres.hpp +++ b/proshade/src/proshade/ProSHADE_spheres.hpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_sphericalHarmonics.cpp b/proshade/src/proshade/ProSHADE_sphericalHarmonics.cpp index 1bc645ca..6b02fcfc 100644 --- a/proshade/src/proshade/ProSHADE_sphericalHarmonics.cpp +++ b/proshade/src/proshade/ProSHADE_sphericalHarmonics.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_sphericalHarmonics.hpp b/proshade/src/proshade/ProSHADE_sphericalHarmonics.hpp index 5b90a558..33e03955 100644 --- a/proshade/src/proshade/ProSHADE_sphericalHarmonics.hpp +++ b/proshade/src/proshade/ProSHADE_sphericalHarmonics.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_symmetry.cpp b/proshade/src/proshade/ProSHADE_symmetry.cpp index badfa913..7e6edd82 100644 --- a/proshade/src/proshade/ProSHADE_symmetry.cpp +++ b/proshade/src/proshade/ProSHADE_symmetry.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -312,19 +312,18 @@ bool ProSHADE_internal_symmetry::isSymmetrySame ( std::vector< proshade_double* is listed first in this format. \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. + \param[in] CSymList Vector of double pointers to the list of axes in which the detection of dihedral symmetries is to be done. */ -std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getDihedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) +void ProSHADE_internal_data::ProSHADE_data::getDihedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) { //================================================ Initialise variables - std::vector< proshade_double* > ret; proshade_double dotProduct; //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting D symmetry detection.", settings->messageShift ); //================================================If not enough axes, just end here - if ( CSymList->size() < 2 ) { return ( ret ); } + if ( CSymList->size() < 2 ) { return ; } //================================================ For each unique pair of axes for ( proshade_unsign ax1 = 0; ax1 < static_cast ( CSymList->size() ); ax1++ ) @@ -353,22 +352,35 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getDihedr //==================================== Save if ( CSymList->at(ax1)[0] >= CSymList->at(ax2)[0] ) { - ProSHADE_internal_symmetry::saveDSymmetry ( &ret, CSymList, ax1, ax2 ); + std::vector< proshade_double* > hlpVec; - std::vector< proshade_unsign > DSymInd; - ProSHADE_internal_misc::addToUnsignVector ( &DSymInd, ax1 ); - ProSHADE_internal_misc::addToUnsignVector ( &DSymInd, ax2 ); - ProSHADE_internal_misc::addToUnsignVectorVector ( &settings->allDetectedDAxes, DSymInd ); + proshade_double* hlpSym = new proshade_double[7]; + ProSHADE_internal_misc::checkMemoryAllocation ( hlpSym, __FILE__, __LINE__, __func__ ); + for ( size_t iter = 0; iter < 7; iter++ ) { hlpSym[iter] = CSymList->at(ax1)[iter]; } + ProSHADE_internal_misc::addToDblPtrVector ( &hlpVec, hlpSym ); + + proshade_double* hlpSym2 = new proshade_double[7]; + ProSHADE_internal_misc::checkMemoryAllocation ( hlpSym2, __FILE__, __LINE__, __func__ ); + for ( size_t iter = 0; iter < 7; iter++ ) { hlpSym2[iter] = CSymList->at(ax2)[iter]; } + ProSHADE_internal_misc::addToDblPtrVector ( &hlpVec, hlpSym2 ); + ProSHADE_internal_misc::addToDblPtrVectorVector ( &this->dihedralSymmetries, hlpVec ); } else { - ProSHADE_internal_symmetry::saveDSymmetry ( &ret, CSymList, ax2, ax1 ); + std::vector< proshade_double* > hlpVec; + + proshade_double* hlpSym = new proshade_double[7]; + ProSHADE_internal_misc::checkMemoryAllocation ( hlpSym, __FILE__, __LINE__, __func__ ); + for ( size_t iter = 0; iter < 7; iter++ ) { hlpSym[iter] = CSymList->at(ax2)[iter]; } + ProSHADE_internal_misc::addToDblPtrVector ( &hlpVec, hlpSym ); + + proshade_double* hlpSym2 = new proshade_double[7]; + ProSHADE_internal_misc::checkMemoryAllocation ( hlpSym2, __FILE__, __LINE__, __func__ ); + for ( size_t iter = 0; iter < 7; iter++ ) { hlpSym2[iter] = CSymList->at(ax1)[iter]; } + ProSHADE_internal_misc::addToDblPtrVector ( &hlpVec, hlpSym2 ); - std::vector< proshade_unsign > DSymInd; - ProSHADE_internal_misc::addToUnsignVector ( &DSymInd, ax2 ); - ProSHADE_internal_misc::addToUnsignVector ( &DSymInd, ax1 ); - ProSHADE_internal_misc::addToUnsignVectorVector ( &settings->allDetectedDAxes, DSymInd ); + ProSHADE_internal_misc::addToDblPtrVectorVector ( &this->dihedralSymmetries, hlpVec ); } } } @@ -376,119 +388,14 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getDihedr //================================================ Report progress std::stringstream hlpSS; - hlpSS << "Detected " << ret.size() << " D symmetries."; + hlpSS << "Detected " << this->dihedralSymmetries.size() << " D symmetries."; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, hlpSS.str(), settings->messageShift ); - //================================================ Done - return ( ret ); - -} - -/*! \brief This function saves a detected dihedral symmetry to the dihedral symmetries list. - - This function takes two C symmetry axes as supplied by the calling function and the list of the detected C symmetries. It then - produces the saving structure for a dihedral symmetry formed by the two supplied axes and saves this structure to the supplied - dihedral symmetry list vector - ret. - - \param[in] ret The vector of double pointers to which the symmetry is to be saved to. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - \param[in] axisOne The index of the first C symmetry forming the dihedral symmetry. - \param[in] axisTwo The index of the second C symmetry forming the dihedral symmetry. - */ -void ProSHADE_internal_symmetry::saveDSymmetry ( std::vector< proshade_double* >* ret, std::vector< proshade_double* >* CSymList, proshade_unsign axisOne, proshade_unsign axisTwo ) -{ - //================================================ Allocate the memory - proshade_double* hlpP = new proshade_double [14]; - ProSHADE_internal_misc::checkMemoryAllocation ( hlpP, __FILE__, __LINE__, __func__ ); - - //================================================ Set the axis and heights - hlpP[0] = CSymList->at(axisOne)[0]; - hlpP[1] = CSymList->at(axisOne)[1]; - hlpP[2] = CSymList->at(axisOne)[2]; - hlpP[3] = CSymList->at(axisOne)[3]; - hlpP[4] = CSymList->at(axisOne)[4]; - hlpP[5] = CSymList->at(axisOne)[5]; - hlpP[6] = CSymList->at(axisOne)[6]; - hlpP[7] = CSymList->at(axisTwo)[0]; - hlpP[8] = CSymList->at(axisTwo)[1]; - hlpP[9] = CSymList->at(axisTwo)[2]; - hlpP[10] = CSymList->at(axisTwo)[3]; - hlpP[11] = CSymList->at(axisTwo)[4]; - hlpP[12] = CSymList->at(axisTwo)[5]; - hlpP[13] = CSymList->at(axisTwo)[6]; - - //================================================ Save to ret - ProSHADE_internal_misc::addToDblPtrVector ( ret, hlpP ); - //================================================ Done return ; } -/*! \brief This function obtains a list of all T symmetry axes from the already computed C symmetries list. - - This function starts by checking if there are two C3 symmetries with the tetrahedral dihedral angle. If so, it proceeds to search for all seven symmetry axes - expected to form a full tetrahedral symmetry. It then returns the list of found symmetries; if full tetrahedral symmetry was found, seven axes (four C3s and - three C2s) are returned. If less than seven symmetries are returned, the procedure has failed and no tetrahedral symmetry was found. - - \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - */ -std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getTetrahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) -{ - //================================================ Initialise variables - std::vector< proshade_double* > ret; - - //================================================ Report progress - ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting T symmetry detection.", settings->messageShift ); - - //================================================ Are the basic requirements for tetrahedral symmetry met? - if ( ProSHADE_internal_symmetry::detectTetrahedralSymmetry ( CSymList, settings->axisErrTolerance, settings->minSymPeak ) ) - { - //============================================ Search for all the symmetry axes - ProSHADE_internal_symmetry::findTetra4C3s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 4 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - - ProSHADE_internal_symmetry::findTetra3C2s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 7 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - else - { - for ( proshade_unsign csIt = 0; csIt < static_cast ( CSymList->size() ); csIt++ ) - { - for ( proshade_unsign retIt = 0; retIt < static_cast ( ret.size() ); retIt++ ) - { - //======================================== Sort ret by fold - std::sort ( ret.begin(), ret.end(), ProSHADE_internal_misc::sortSymInvFoldHlp ); - - //======================================== Save indices - const FloatingPoint< proshade_double > lhs1 ( CSymList->at(csIt)[0] ), rhs1 ( ret.at(retIt)[0] ); - const FloatingPoint< proshade_double > lhs2 ( CSymList->at(csIt)[1] ), rhs2 ( ret.at(retIt)[1] ); - const FloatingPoint< proshade_double > lhs3 ( CSymList->at(csIt)[2] ), rhs3 ( ret.at(retIt)[2] ); - const FloatingPoint< proshade_double > lhs4 ( CSymList->at(csIt)[3] ), rhs4 ( ret.at(retIt)[3] ); - const FloatingPoint< proshade_double > lhs5 ( CSymList->at(csIt)[4] ), rhs5 ( ret.at(retIt)[4] ); - const FloatingPoint< proshade_double > lhs6 ( CSymList->at(csIt)[5] ), rhs6 ( ret.at(retIt)[5] ); - if ( ( lhs1.AlmostEquals ( rhs1 ) ) && - ( lhs2.AlmostEquals ( rhs2 ) ) && - ( lhs3.AlmostEquals ( rhs3 ) ) && - ( lhs4.AlmostEquals ( rhs4 ) ) && - ( lhs5.AlmostEquals ( rhs5 ) ) && - ( lhs6.AlmostEquals ( rhs6 ) ) ) - { - ProSHADE_internal_misc::addToUnsignVector ( &settings->allDetectedTAxes, csIt ); - } - } - } - } - } - - //================================================ Report progress - ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "T symmetry detection complete.", settings->messageShift ); - - //================================================ Done - return ( ret ); - -} - /*! \brief This function takes the list of C symmetries and decides whether basic requirements for tetrahedral symmetry are there. This function first finds all the C3 symmetries in the C symmetries list and then it checks all pais of such present C3s for have the angle @@ -1206,74 +1113,6 @@ bool ProSHADE_internal_symmetry::testGroupAgainstGroup ( std::vector< proshade_d } -/*! \brief This function obtains a list of all O symmetry axes from the already computed C symmetries list. - - This function starts by checking if there is a pair of C3 and C4 symmetries with the octahedron dihedral angle ( acos ( 1/sqrt(3) ) ). If so, it will - then assume existence of octahedral symmetry and it will search for three C4 axes, four C3 axes and six C2 axes with the correct angle to each other - and within the group. If all required axes are detected, it will return a list of 13 axes, otherwise it will return empty or shorter list. Automated - missing symmetry axis detection is also included. - - \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - */ -std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getOctahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) -{ - //================================================ Initialise variables - std::vector< proshade_double* > ret; - - //================================================ Report progress - ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting O symmetry detection.", settings->messageShift ); - - //================================================ Are the basic requirements for tetrahedral symmetry met? - if ( ProSHADE_internal_symmetry::detectOctahedralSymmetry ( CSymList, settings->axisErrTolerance, settings->minSymPeak ) ) - { - //============================================ Search for all the symmetry axes - ProSHADE_internal_symmetry::findOcta3C4s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 3 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - - ProSHADE_internal_symmetry::findOcta4C3s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 7 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - - ProSHADE_internal_symmetry::findOcta6C2s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 13 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - else - { - for ( proshade_unsign csIt = 0; csIt < static_cast ( CSymList->size() ); csIt++ ) - { - for ( proshade_unsign retIt = 0; retIt < static_cast ( ret.size() ); retIt++ ) - { - //======================================== Sort ret by fold - std::sort ( ret.begin(), ret.end(), ProSHADE_internal_misc::sortSymInvFoldHlp ); - - //======================================== Save indices - const FloatingPoint< proshade_double > lhs1 ( CSymList->at(csIt)[0] ), rhs1 ( ret.at(retIt)[0] ); - const FloatingPoint< proshade_double > lhs2 ( CSymList->at(csIt)[1] ), rhs2 ( ret.at(retIt)[1] ); - const FloatingPoint< proshade_double > lhs3 ( CSymList->at(csIt)[2] ), rhs3 ( ret.at(retIt)[2] ); - const FloatingPoint< proshade_double > lhs4 ( CSymList->at(csIt)[3] ), rhs4 ( ret.at(retIt)[3] ); - const FloatingPoint< proshade_double > lhs5 ( CSymList->at(csIt)[4] ), rhs5 ( ret.at(retIt)[4] ); - const FloatingPoint< proshade_double > lhs6 ( CSymList->at(csIt)[5] ), rhs6 ( ret.at(retIt)[5] ); - if ( lhs1.AlmostEquals ( rhs1 ) && - lhs2.AlmostEquals ( rhs2 ) && - lhs3.AlmostEquals ( rhs3 ) && - lhs4.AlmostEquals ( rhs4 ) && - lhs5.AlmostEquals ( rhs5 ) && - lhs6.AlmostEquals ( rhs6 ) ) - { - ProSHADE_internal_misc::addToUnsignVector ( &settings->allDetectedOAxes, csIt ); - } - } - } - } - } - - //================================================ Report progress - ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "O symmetry detection complete.", settings->messageShift ); - - //================================================ Done - return ( ret ); - -} - /*! \brief This function takes the list of C symmetries and decides whether basic requirements for octahhedral symmetry are there. This function first finds all the C4 symmetries in the C symmetries list and then it checks each present C4 against all C3 symmetries for having @@ -1810,74 +1649,6 @@ bool ProSHADE_internal_symmetry::checkFittingAxisDualAndSave ( std::vector< pros } -/*! \brief This function obtains a list of all I symmetry axes from the already computed C symmetries list. - - This function starts by checking if there is a pair of C3 and C4 symmetries with the octahedron dihedral angle ( acos ( 1/sqrt(3) ) ). If so, it will - then assume existence of octahedral symmetry and it will search for three C4 axes, four C3 axes and six C2 axes with the correct angle to each other - and within the group. If all required axes are detected, it will return a list of 13 axes, otherwise it will return empty or shorter list. Automated - missing symmetry axis detection is also included. - - \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - */ -std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getIcosahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) -{ - //================================================ Initialise variables - std::vector< proshade_double* > ret; - - //================================================ Report progress - ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting I symmetry detection.", settings->messageShift ); - - //================================================ Are the basic requirements for icosahedral symmetry met? - if ( ProSHADE_internal_symmetry::detectIcosahedralSymmetry ( CSymList, settings->axisErrTolerance, settings->minSymPeak ) ) - { - //============================================ Search for all the symmetry axes - ProSHADE_internal_symmetry::findIcos6C5s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 6 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - - ProSHADE_internal_symmetry::findIcos10C3s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 16 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - - ProSHADE_internal_symmetry::findIcos15C2s ( CSymList, &ret, settings->axisErrTolerance, this, settings->verbose, settings->messageShift, settings->minSymPeak ); - if ( ret.size() != 31 ) { ProSHADE_internal_messages::printWarningMessage ( settings->verbose, "!!! ProSHADE WARNING !!! Failed to detect some of the polyhedral symmetries, while detecting the correct dihedral angles.", "WS00031" ); return ( ret ); } - else - { - //======================================== Sort ret by fold - std::sort ( ret.begin(), ret.end(), ProSHADE_internal_misc::sortSymInvFoldHlp ); - - //======================================== Save indices - for ( proshade_unsign csIt = 0; csIt < static_cast ( CSymList->size() ); csIt++ ) - { - for ( proshade_unsign retIt = 0; retIt < static_cast ( ret.size() ); retIt++ ) - { - const FloatingPoint< proshade_double > lhs1 ( CSymList->at(csIt)[0] ), rhs1 ( ret.at(retIt)[0] ); - const FloatingPoint< proshade_double > lhs2 ( CSymList->at(csIt)[1] ), rhs2 ( ret.at(retIt)[1] ); - const FloatingPoint< proshade_double > lhs3 ( CSymList->at(csIt)[2] ), rhs3 ( ret.at(retIt)[2] ); - const FloatingPoint< proshade_double > lhs4 ( CSymList->at(csIt)[3] ), rhs4 ( ret.at(retIt)[3] ); - const FloatingPoint< proshade_double > lhs5 ( CSymList->at(csIt)[4] ), rhs5 ( ret.at(retIt)[4] ); - const FloatingPoint< proshade_double > lhs6 ( CSymList->at(csIt)[5] ), rhs6 ( ret.at(retIt)[5] ); - if ( lhs1.AlmostEquals ( rhs1 ) && - lhs2.AlmostEquals ( rhs2 ) && - lhs3.AlmostEquals ( rhs3 ) && - lhs4.AlmostEquals ( rhs4 ) && - lhs5.AlmostEquals ( rhs5 ) && - lhs6.AlmostEquals ( rhs6 ) ) - { - ProSHADE_internal_misc::addToUnsignVector ( &settings->allDetectedIAxes, csIt ); - } - } - } - } - } - - //================================================ Report progress - ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "I symmetry detection complete.", settings->messageShift ); - - //================================================ Done - return ( ret ); - -} - /*! \brief This function takes a list of predicted polyheral groups and decides which is most likely using the FSC of the constituent axes. ... @@ -1909,14 +1680,20 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::decidePol for ( size_t aIt = 0; aIt < polyList->at(gIt).size(); aIt++ ) { //======================================== Match to CSyms - matchedPos = ProSHADE_internal_symmetry::addAxisUnlessSame ( static_cast< proshade_unsign > ( polyList->at(gIt).at(aIt)[0] ), polyList->at(gIt).at(aIt)[1], polyList->at(gIt).at(aIt)[2], polyList->at(gIt).at(aIt)[3], polyList->at(gIt).at(aIt)[5], polyList->at(gIt).at(aIt)[6], CSyms, tolerance ); + matchedPos = ProSHADE_internal_symmetry::addAxisUnlessSame ( static_cast< proshade_unsign > ( polyList->at(gIt).at(aIt)[0] ), polyList->at(gIt).at(aIt)[1], polyList->at(gIt).at(aIt)[2], polyList->at(gIt).at(aIt)[3], polyList->at(gIt).at(aIt)[5], polyList->at(gIt).at(aIt)[6], CSyms, tolerance ); //======================================== Compute FSC fscVal = this->computeFSC ( settings, CSyms, static_cast< size_t > ( matchedPos ), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); polyList->at(gIt).at(aIt)[6] = fscVal; fscValAvg += fscVal; + + //======================================== If not required, do not compute more + if ( settings->fastISearch ) { if ( fscVal < ( settings->fscThreshold / 2.0 ) ) { break; } } } + //============================================ If not required, do not compute more + if ( settings->fastISearch ) { if ( fscVal < ( settings->fscThreshold / 2.0 ) ) { continue; } } + //============================================ Get FSC average over all axes fscValAvg /= static_cast< proshade_double > ( fullGroupSize ); @@ -1926,9 +1703,6 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::decidePol fscMax = fscValAvg; fscMaxInd = gIt; } - - //============================================ If not required, do not compute - if ( settings->fastISearch ) { fscMaxInd = 0; break; } } //================================================ If at least one poly group was found @@ -1939,9 +1713,6 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::decidePol { //======================================== Add the correct index to the settings object matchedPos = ProSHADE_internal_symmetry::addAxisUnlessSame ( static_cast< proshade_unsign > ( polyList->at(fscMaxInd).at(retIt)[0] ), polyList->at(fscMaxInd).at(retIt)[1], polyList->at(fscMaxInd).at(retIt)[2], polyList->at(fscMaxInd).at(retIt)[3], polyList->at(fscMaxInd).at(retIt)[5], polyList->at(fscMaxInd).at(retIt)[6], CSyms, tolerance ); - if ( fullGroupSize == 7 ) { ProSHADE_internal_misc::addToUnsignVector ( &settings->allDetectedTAxes, static_cast < proshade_unsign > ( matchedPos ) ); } - if ( fullGroupSize == 13 ) { ProSHADE_internal_misc::addToUnsignVector ( &settings->allDetectedOAxes, static_cast < proshade_unsign > ( matchedPos ) ); } - if ( fullGroupSize == 31 ) { ProSHADE_internal_misc::addToUnsignVector ( &settings->allDetectedIAxes, static_cast < proshade_unsign > ( matchedPos ) ); } //============================================ Set single group list for saving ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &ret, polyList->at(fscMaxInd).at(retIt) ); @@ -1964,13 +1735,21 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::decidePol which symmetry was found. \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - \param[out] ret A vector of all the detected axes in the standard ProSHADE format with height either the detected value (for the detected ones) or 0 for the predicted ones. + \param[in] CSymList A vector of double pointers containing the list of axes on which the icosahedral symmetry detection is to be attempted. + \param[in] cutIndices Map of each coefficient index to its correct bin cut to resolution. + \param[in] fCoeffsCut The original map Fourier coefficients cut to resolution. + \param[in] noBins Number of bins to be used (only up to the cut-off resolution). + \param[in] bindata Pre-allocated array of dimensions noBins x 12 serving as workspace for the bin summation and FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] binCounts Pre-allocated array of dimension noBins serving to store the bin sizes for FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] fscByBin This array will hold FSC values for each bin. This is useful in further computations, but could be internal for FSC only computation. + \param[in] xDim The number of indices along the x-axis of the of the array to be rotated. + \param[in] yDim The number of indices along the y-axis of the of the array to be rotated. + \param[in] zDim The number of indices along the z-axis of the of the array to be rotated. */ -std::vector < std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE_data::getPredictedIcosahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) +void ProSHADE_internal_data::ProSHADE_data::getPredictedIcosahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ) { //================================================ Initialise variables - std::vector< std::vector< proshade_double* > > ret; + std::vector< std::vector< proshade_double* > > hlpVec; //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting I symmetry prediction.", settings->messageShift ); @@ -1979,24 +1758,27 @@ std::vector < std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE if ( ProSHADE_internal_symmetry::detectIcosahedralSymmetry ( CSymList, settings->axisErrTolerance, settings->minSymPeak ) ) { //============================================ Generate the rest of the axes - ProSHADE_internal_symmetry::predictIcosAxes ( CSymList, &ret, settings->axisErrTolerance, settings->minSymPeak ); + ProSHADE_internal_symmetry::predictIcosAxes ( CSymList, &hlpVec, settings->axisErrTolerance, settings->minSymPeak ); //============================================ For each possible axes pair - for ( size_t pIt = 0; pIt < ret.size(); pIt++ ) + for ( size_t pIt = 0; pIt < hlpVec.size(); pIt++ ) { //======================================== Get heights for the predicted axes - ProSHADE_internal_symmetry::findPredictedAxesHeights ( &(ret.at(pIt)), this, settings ); + ProSHADE_internal_symmetry::findPredictedAxesHeights ( &(hlpVec.at(pIt)), this, settings ); } } //================================================ Sort by best peak height sum - std::sort ( ret.begin(), ret.end(), ProSHADE_internal_misc::sortISymByPeak ); + this->icosahedralSymmetries = ProSHADE_data::decidePolyFromList ( settings, &hlpVec, 31, CSymList, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); + + //================================================ Release hlpVec memory + for ( size_t gIt = 0; gIt < hlpVec.size(); gIt++ ) { for ( size_t aIt = 0; aIt < hlpVec.at(gIt).size(); aIt++ ) { if ( hlpVec.at(gIt).at(aIt) != nullptr ) { delete[] hlpVec.at(gIt).at(aIt); } } } //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "I symmetry prediction complete.", settings->messageShift ); //================================================ Done - return ( ret ); + return ; } @@ -2011,13 +1793,21 @@ std::vector < std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE which symmetry was found. \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - \param[out] ret A vector of all the detected axes in the standard ProSHADE format with height either the detected value (for the detected ones) or 0 for the predicted ones. + \param[in] CSymList A vector of double pointers containing the list of axes on which the octahedral symmetry detection is to be attempted. + \param[in] cutIndices Map of each coefficient index to its correct bin cut to resolution. + \param[in] fCoeffsCut The original map Fourier coefficients cut to resolution. + \param[in] noBins Number of bins to be used (only up to the cut-off resolution). + \param[in] bindata Pre-allocated array of dimensions noBins x 12 serving as workspace for the bin summation and FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] binCounts Pre-allocated array of dimension noBins serving to store the bin sizes for FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] fscByBin This array will hold FSC values for each bin. This is useful in further computations, but could be internal for FSC only computation. + \param[in] xDim The number of indices along the x-axis of the of the array to be rotated. + \param[in] yDim The number of indices along the y-axis of the of the array to be rotated. + \param[in] zDim The number of indices along the z-axis of the of the array to be rotated. */ -std::vector< std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE_data::getPredictedOctahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) +void ProSHADE_internal_data::ProSHADE_data::getPredictedOctahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ) { //================================================ Initialise variables - std::vector< std::vector< proshade_double* > > ret; + std::vector< std::vector< proshade_double* > > hlpVec; //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting O symmetry prediction.", settings->messageShift ); @@ -2026,24 +1816,27 @@ std::vector< std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE_ if ( ProSHADE_internal_symmetry::detectOctahedralSymmetry ( CSymList, settings->axisErrTolerance, settings->minSymPeak ) ) { //============================================ Generate the rest of the axes - ProSHADE_internal_symmetry::predictOctaAxes ( CSymList, &ret, settings->axisErrTolerance, settings->minSymPeak ); + ProSHADE_internal_symmetry::predictOctaAxes ( CSymList, &hlpVec, settings->axisErrTolerance, settings->minSymPeak ); //============================================ For each possible axes pair - for ( size_t pIt = 0; pIt < ret.size(); pIt++ ) + for ( size_t pIt = 0; pIt < hlpVec.size(); pIt++ ) { //======================================== Get heights for the predicted axes - ProSHADE_internal_symmetry::findPredictedAxesHeights ( &(ret.at(pIt)), this, settings ); + ProSHADE_internal_symmetry::findPredictedAxesHeights ( &(hlpVec.at(pIt)), this, settings ); } } //================================================ Sort by best peak height sum - std::sort ( ret.begin(), ret.end(), ProSHADE_internal_misc::sortISymByPeak ); + this->octahedralSymmetries = ProSHADE_data::decidePolyFromList ( settings, &hlpVec, 13, CSymList, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); + + //================================================ Release hlpVec memory + for ( size_t gIt = 0; gIt < hlpVec.size(); gIt++ ) { for ( size_t aIt = 0; aIt < hlpVec.at(gIt).size(); aIt++ ) { if ( hlpVec.at(gIt).at(aIt) != nullptr ) { delete[] hlpVec.at(gIt).at(aIt); } } } //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "O symmetry prediction complete.", settings->messageShift ); //================================================ Done - return ( ret ); + return ; } @@ -2089,10 +1882,7 @@ bool ProSHADE_internal_symmetry::detectIcosahedralSymmetry ( std::vector< prosha &CSymList->at(cSym)[3] ); //======================================== Is the angle approximately the dihedral angle - if ( std::abs ( std::abs( std::sqrt ( ( 1.0 + 2.0 / std::sqrt ( 5.0 ) ) / 3.0 ) ) - std::abs( dotProduct ) ) < axErr ) - { - return ( true ); - } + if ( std::abs ( std::abs( std::sqrt ( ( 1.0 + 2.0 / std::sqrt ( 5.0 ) ) / 3.0 ) ) - std::abs( dotProduct ) ) < axErr ) { return ( true ); } } } @@ -2296,7 +2086,7 @@ void ProSHADE_internal_symmetry::predictIcosAxes ( std::vector< proshade_double* //============================================ Release memory delete[] rotMatHlp; - //============================================ For the rotation matrix along the detected C5 axis with the same anlge as is between the rotated model C3 and the detected C3 axes. + //============================================ For the rotation matrix along the detected C5 axis with the same angle as is between the rotated model C3 and the detected C3 axes. proshade_double* rotMat2 = new proshade_double[9]; ProSHADE_internal_misc::checkMemoryAllocation ( rotMat2, __FILE__, __LINE__, __func__ ); ProSHADE_internal_maths::getRotationMatrixFromAngleAxis ( rotMat2, CSymList->at(initAxes.at(pIt).first)[1], CSymList->at(initAxes.at(pIt).first)[2], CSymList->at(initAxes.at(pIt).first)[3], bestAng ); @@ -2896,7 +2686,8 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getCyclic ProSHADE_internal_misc::addToSignedVector ( &divisAll, static_cast< proshade_signed > ( primes.at(prIt) - 1 ) ); for ( proshade_unsign pfIt = primes.at(prIt) + 4; pfIt >= ( std::max ( primes.at(prIt) - 4, settings->supportedSymmetryFold ) ); pfIt-- ) { - if ( pfIt == primes.at(prIt) ) { continue; } + if ( pfIt == primes.at(prIt) ) { continue; } + if ( pfIt < 2 ) { continue; } std::vector< proshade_signed > divis = ProSHADE_internal_maths::primeFactorsDecomp ( static_cast< proshade_signed > ( pfIt ) ); for ( size_t iter = 0; iter < divis.size(); iter++ ) { ProSHADE_internal_misc::addToSignedVector ( &divisAll, divis.at(iter) ); } } @@ -2945,7 +2736,7 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getCyclic this->computeFSC ( settings, prSyms.at(axIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim, rotationNumber ); //======================== If high FSC and undersampled map, check the FSC with full computation - if ( ( primes.at(prIt) >= settings->supportedSymmetryFold ) && ( prSyms.at(axIt)[6] >= settings->fscThreshold ) ) + if ( ( primes.at(prIt) >= settings->supportedSymmetryFold ) || ( prSyms.at(axIt)[6] >= settings->fscThreshold ) ) { prSyms.at(axIt)[6] = -std::numeric_limits < proshade_double >::infinity(); this->computeFSC ( settings, prSyms.at(axIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim, 0 ); @@ -2965,7 +2756,8 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getCyclic if ( ret.size() < 1 ) { return ( ret ); } //================================================ Compute the FSC threshold - proshade_double bestFSCPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( &ret, 6, 0.02, 0.1, 9 ); + proshade_double bestFSCPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( &ret, 6, 0.01, 0.3, 9 ); + proshade_double dotProduct = 0.0; //================================================ Check for prime symmetry fold multiples while ( anyNewSyms ) @@ -2988,6 +2780,15 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getCyclic if ( !ProSHADE_internal_maths::isPrime ( static_cast< proshade_unsign > ( ret.at(axIt1)[0] ) ) && !ProSHADE_internal_maths::isPrime ( static_cast< proshade_unsign > ( ret.at(axIt2)[0] ) ) ) { continue; } + //==================================== Is the axis the same? + dotProduct = ProSHADE_internal_maths::computeDotProduct ( &ret.at(axIt1)[1], + &ret.at(axIt1)[2], + &ret.at(axIt1)[3], + &ret.at(axIt2)[1], + &ret.at(axIt2)[2], + &ret.at(axIt2)[3] ); + if ( std::abs ( dotProduct ) < ( 1.0 - settings->axisErrTolerance ) ) { continue; } + //==================================== Initialise iteration foldToTest = static_cast< proshade_unsign > ( ret.at(axIt1)[0] * ret.at(axIt2)[0] ); @@ -3057,7 +2858,7 @@ std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getCyclic this->computeFSC ( settings, prSyms.at(newAxIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim, rotationNumber ); //======================== If high FSC and undersampled map, check the FSC with full computation - if ( ( foldToTest >= settings->supportedSymmetryFold ) && ( prSyms.at(newAxIt)[6] >= bestFSCPeakStart ) ) + if ( ( foldToTest >= settings->supportedSymmetryFold ) || ( prSyms.at(newAxIt)[6] >= bestFSCPeakStart ) ) { prSyms.at(newAxIt)[6] = -std::numeric_limits < proshade_double >::infinity(); this->computeFSC ( settings, prSyms.at(newAxIt), cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim, 0 ); @@ -3143,6 +2944,16 @@ std::vector < proshade_double* > ProSHADE_internal_data::ProSHADE_data::findRequ std::vector< ProSHADE_internal_spheres::ProSHADE_rotFun_spherePeakGroup* > peakGroups; std::vector< proshade_double* > ret; bool newPeak; + + //================================================ Sanity check + if ( ( M_PI / static_cast < proshade_double > ( this->maxShellBand ) ) >= ( M_PI / static_cast< proshade_double > ( fold ) ) ) + { + //============================================ Not enough points to produce all the spheres meaningfully. Issue warning and ignore this fold. + std::stringstream hlpSS; + hlpSS << "!!! ProSHADE WARNING !!! Will not search for fold " << fold << " as the map sampling does not support its reliable detection. Increase resolution/bandwidth if you suspect this fold could be present in the structure."; + ProSHADE_internal_messages::printWarningMessage ( settings->verbose, hlpSS.str(), "WS00075" ); + return ( ret ); + } //================================================ Make sure we have a clean start this->sphereMappedRotFun.clear(); @@ -3467,22 +3278,18 @@ void ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( std::vecto proshade_double *crossProd, *perpVec, normFactor; size_t higherRFIndex = 0; - // ... Find vector perperndicular to the plane given by the two axes + //================================================ Find vector perperndicular to the plane given by the two axes crossProd = ProSHADE_internal_maths::computeCrossProduct ( &ret->at(0).at(1), &ret->at(0).at(2), &ret->at(0).at(3), &ret->at(1).at(1), &ret->at(1).at(2), &ret->at(1).at(3) ); - // ... Find a vector perpendicular to the plane between the new vector and the vector with higher rotation function value + //================================================ Find a vector perpendicular to the plane between the new vector and the vector with higher rotation function value if ( ret->at(1).at(5) > ret->at(0).at(5) ) { higherRFIndex = 1; } perpVec = ProSHADE_internal_maths::computeCrossProduct ( &ret->at(higherRFIndex).at(1), &ret->at(higherRFIndex).at(2), &ret->at(higherRFIndex).at(3), &crossProd[0], &crossProd[1], &crossProd[2] ); - // ... Normalise the new vector + //================================================ Normalise the new vector normFactor = std::sqrt ( pow ( perpVec[0], 2.0 ) + pow ( perpVec[1], 2.0 ) + pow ( perpVec[2], 2.0 ) ); perpVec[0] /= normFactor; perpVec[1] /= normFactor; perpVec[2] /= normFactor; - - // ... Which vector are we to over-write? - if ( higherRFIndex == 0 ) { higherRFIndex = 1; } - else { higherRFIndex = 0; } - - // ... Set largest axis element to positive + + //================================================ Set largest axis element to positive const FloatingPoint< proshade_double > lhs1 ( std::max ( std::abs ( perpVec[0] ), std::max( std::abs ( perpVec[1] ), std::abs ( perpVec[2] ) ) ) ); const FloatingPoint< proshade_double > rhs1 ( std::abs ( perpVec[0] )); const FloatingPoint< proshade_double > rhs2 ( std::abs ( perpVec[1] ) ); @@ -3496,10 +3303,14 @@ void ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( std::vecto perpVec[2] *= -1.0; } - // ... Over-write the old vector with the better one + //================================================ Which vector are we to over-write? + if ( higherRFIndex == 0 ) { higherRFIndex = 1; } + else { higherRFIndex = 0; } + + //================================================ Over-write the old vector with the better one ret->at(higherRFIndex).at(1) = perpVec[0]; ret->at(higherRFIndex).at(2) = perpVec[1]; ret->at(higherRFIndex).at(3) = perpVec[2]; - // ... Release memory + //================================================ Release memory delete[] perpVec; delete[] crossProd; @@ -3530,7 +3341,7 @@ void ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( std::vecto //============================================ Copy values for ( size_t elIt = 0; elIt < 7; elIt++ ) { - ret->at(axIt).at(elIt) = convVec.at(axIt)[elIt]; + ret->at(axIt).at(elIt) = convVec.at(axIt)[elIt]; } //============================================ Release memory @@ -3728,13 +3539,21 @@ std::vector < std::pair< proshade_unsign, proshade_unsign > > findBestTetraDihed which symmetry was found. \param[in] settings A pointer to settings class containing all the information required for symmetry detection. - \param[in] CSymList A vector containing the already detected Cyclic symmetries. - \param[out] ret A vector of all the detected axes in the standard ProSHADE format with height either the detected value (for the detected ones) or 0 for the predicted ones. + \param[in] CSymList Vector of double pointers containing the list of axes on which the tetrahedral symmetry detection is to be attempted. + \param[in] cutIndices Map of each coefficient index to its correct bin cut to resolution. + \param[in] fCoeffsCut The original map Fourier coefficients cut to resolution. + \param[in] noBins Number of bins to be used (only up to the cut-off resolution). + \param[in] bindata Pre-allocated array of dimensions noBins x 12 serving as workspace for the bin summation and FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] binCounts Pre-allocated array of dimension noBins serving to store the bin sizes for FSC computation. This array is modified by the function in case the caller would be interested in these results. + \param[in] fscByBin This array will hold FSC values for each bin. This is useful in further computations, but could be internal for FSC only computation. + \param[in] xDim The number of indices along the x-axis of the of the array to be rotated. + \param[in] yDim The number of indices along the y-axis of the of the array to be rotated. + \param[in] zDim The number of indices along the z-axis of the of the array to be rotated. */ -std::vector< std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE_data::getPredictedTetrahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList ) +void ProSHADE_internal_data::ProSHADE_data::getPredictedTetrahedralSymmetriesList ( ProSHADE_settings* settings, std::vector< proshade_double* >* CSymList, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed xDim, proshade_signed yDim, proshade_signed zDim ) { //================================================ Initialise variables - std::vector< std::vector< proshade_double* > > ret; + std::vector< std::vector< proshade_double* > > hlpVec; //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 1, "Starting T symmetry prediction.", settings->messageShift ); @@ -3743,24 +3562,27 @@ std::vector< std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE_ if ( ProSHADE_internal_symmetry::detectTetrahedralSymmetry ( CSymList, settings->axisErrTolerance, settings->minSymPeak ) ) { //============================================ Generate the rest of the axes - ProSHADE_internal_symmetry::predictTetraAxes ( CSymList, &ret, settings->axisErrTolerance, settings->minSymPeak ); + ProSHADE_internal_symmetry::predictTetraAxes ( CSymList, &hlpVec, settings->axisErrTolerance, settings->minSymPeak ); //============================================ For each possible axes pair - for ( size_t pIt = 0; pIt < ret.size(); pIt++ ) + for ( size_t pIt = 0; pIt < hlpVec.size(); pIt++ ) { //======================================== Get heights for the predicted axes - ProSHADE_internal_symmetry::findPredictedAxesHeights ( &(ret.at(pIt)), this, settings ); + ProSHADE_internal_symmetry::findPredictedAxesHeights ( &(hlpVec.at(pIt)), this, settings ); } } - //================================================ Sort by best peak height sum - std::sort ( ret.begin(), ret.end(), ProSHADE_internal_misc::sortTSymByPeak ); + //================================================ Find the best T group of all detected + this->tetrahedralSymmetries = ProSHADE_data::decidePolyFromList ( settings, &hlpVec, 7, CSymList, settings->axisErrTolerance, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, xDim, yDim, zDim ); + + //================================================ Release hlpVec memory + for ( size_t gIt = 0; gIt < hlpVec.size(); gIt++ ) { for ( size_t aIt = 0; aIt < hlpVec.at(gIt).size(); aIt++ ) { if ( hlpVec.at(gIt).at(aIt) != nullptr ) { delete[] hlpVec.at(gIt).at(aIt); } } } //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, "T symmetry prediction complete.", settings->messageShift ); //================================================ Done - return ( ret ); + return ; } @@ -3903,13 +3725,14 @@ void ProSHADE_internal_symmetry::predictTetraAxes ( std::vector< proshade_double \warning This function is intended to be used internally and specifically with phase-less symmetry detection, but it does not check for these conditions to be met! \param[in] allCs A list of all detected symmetries in the phase-less map. + \param[in] allDs A list of all detected dohedral symmetries in the phase-less map. \param[in] verbose How loud the function should be in the standard output? \param[in] messageShift Are we in a subprocess, so that the log should be shifted for this function call? If so, by how much? \param[in] tolerance What is the tolerance on the perpendicularity of two axes in terms of the dot product? \param[out] ret A vector containing a) zero entries if no reliable symmetry axis was found, b) a single symmetry axis index if only a reliable cyclic symmetry axis was found or c) two axes indices in the case where two perpendicular reliable axes were detected. */ -std::vector< proshade_unsign > ProSHADE_internal_symmetry::findReliableUnphasedSymmetries ( std::vector < std::vector< proshade_double > >* allCs, proshade_signed verbose, proshade_signed messageShift, proshade_double tolerance ) +std::vector< proshade_unsign > ProSHADE_internal_symmetry::findReliableUnphasedSymmetries ( std::vector < proshade_double* >* allCs, std::vector < std::vector < proshade_double* > >* allDs, proshade_signed verbose, proshade_signed messageShift, proshade_double tolerance ) { //================================================ Report progress ProSHADE_internal_messages::printProgressMessage ( verbose, 2, "Deciding whether any axis(es) is/are reliable.", messageShift ); @@ -3917,48 +3740,37 @@ std::vector< proshade_unsign > ProSHADE_internal_symmetry::findReliableUnphasedS //================================================ Initialise local variables std::vector< proshade_unsign > ret; - //================================================ Find the threshold - proshade_double bestHistPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( allCs, 5, 0.02, 0.03, 5 ); - proshade_double bestFSCPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( allCs, 6, 0.02, 0.01, 5 ); + //================================================ Find the thresholds + proshade_double bestHistPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( allCs, 5, 0.01, 0.1, 9 ); + proshade_double bestFSCPeakStart = ProSHADE_internal_maths::findTopGroupSmooth ( allCs, 6, 0.01, 0.1, 9 ); if ( bestHistPeakStart > 0.9 ) { bestHistPeakStart = 0.9; } - //================================================ Are any axes orthogonal - proshade_double dotProduct, maxOrtSum = 0.0, curOrtSum = 0.0; - proshade_unsign maxOrtAx1 = 0, maxOrtAx2 = 0; - for ( size_t relAx1 = 0; relAx1 < allCs->size(); relAx1++ ) + //================================================ Are there any dihedral axes? + proshade_double maxOrtSum = 0.0, curOrtSum = 0.0; + proshade_signed maxOrtAx1 = 0, maxOrtAx2 = 0; + for ( size_t relAx = 0; relAx < allDs->size(); relAx++ ) { - //============================================ Consider only reliable axes - if ( allCs->at(relAx1)[5] < bestHistPeakStart ) { continue; } - if ( allCs->at(relAx1)[6] < bestFSCPeakStart ) { continue; } + //============================================ Check if they are reliable + if ( allDs->at(relAx).at(0)[5] < bestHistPeakStart ) { continue; } + if ( allDs->at(relAx).at(1)[5] < bestHistPeakStart ) { continue; } + if ( allDs->at(relAx).at(0)[6] < bestFSCPeakStart ) { continue; } + if ( allDs->at(relAx).at(1)[6] < bestFSCPeakStart ) { continue; } - for ( size_t relAx2 = 1; relAx2 < allCs->size(); relAx2++ ) + //============================================ They are! Save if the sum is the best + curOrtSum = allDs->at(relAx).at(0)[6] + allDs->at(relAx).at(1)[6]; + if ( curOrtSum > maxOrtSum ) { - //======================================== Ignore same axes - if ( relAx1 >= relAx2 ) { continue; } - - //======================================== Consider only reliable axes - if ( allCs->at(relAx2)[5] < bestHistPeakStart ) { continue; } - if ( allCs->at(relAx2)[6] < bestFSCPeakStart ) { continue; } - - //======================================== Are the two axes orthogonal? - dotProduct = ProSHADE_internal_maths::computeDotProduct ( &allCs->at(relAx1)[1], &allCs->at(relAx1)[2], - &allCs->at(relAx1)[3], &allCs->at(relAx2)[1], - &allCs->at(relAx2)[2], &allCs->at(relAx2)[3] ); - - //======================================== If close to zero, these two axes are perpendicular - if ( std::abs( dotProduct ) < tolerance ) - { - //==================================== Find sum - curOrtSum = allCs->at(relAx1)[5] + allCs->at(relAx1)[6] + allCs->at(relAx2)[5] + allCs->at(relAx2)[6]; - - //==================================== If best, save it - if ( curOrtSum > maxOrtSum ) - { - maxOrtSum = curOrtSum; - maxOrtAx1 = static_cast< proshade_unsign > ( relAx1 ); - maxOrtAx2 = static_cast< proshade_unsign > ( relAx2 ); - } - } + maxOrtSum = curOrtSum; + maxOrtAx1 = ProSHADE_internal_symmetry::addAxisUnlessSame ( static_cast< proshade_unsign > ( allDs->at(relAx).at(0)[0] ), + allDs->at(relAx).at(0)[1], + allDs->at(relAx).at(0)[2], + allDs->at(relAx).at(0)[3], + allDs->at(relAx).at(0)[5], allCs, tolerance ); + maxOrtAx2 = ProSHADE_internal_symmetry::addAxisUnlessSame ( static_cast< proshade_unsign > ( allDs->at(relAx).at(1)[0] ), + allDs->at(relAx).at(1)[1], + allDs->at(relAx).at(1)[2], + allDs->at(relAx).at(1)[3], + allDs->at(relAx).at(1)[5], allCs, tolerance ); } } @@ -3966,39 +3778,39 @@ std::vector< proshade_unsign > ProSHADE_internal_symmetry::findReliableUnphasedS if ( maxOrtAx2 != 0 ) { //================================================ Report progress - ProSHADE_internal_misc::addToUnsignVector ( &ret, maxOrtAx1 ); - ProSHADE_internal_misc::addToUnsignVector ( &ret, maxOrtAx2 ); + ProSHADE_internal_misc::addToUnsignVector ( &ret, static_cast< proshade_unsign > ( maxOrtAx1 ) ); + ProSHADE_internal_misc::addToUnsignVector ( &ret, static_cast< proshade_unsign > ( maxOrtAx2 ) ); return ( ret ); } //================================================ Well, no orthogonal axes. Is there at least one good axis? - curOrtSum = 0.0; maxOrtSum = 0.0; - for ( size_t relAx1 = 0; relAx1 < allCs->size(); relAx1++ ) + curOrtSum = 0.0; maxOrtSum = 0.0; maxOrtAx1 = -1; + for ( size_t relAx = 0; relAx < allCs->size(); relAx++ ) { //============================================ Consider only reliable axes in terms of RF - if ( allCs->at(relAx1)[5] < bestHistPeakStart ) { continue; } + if ( allCs->at(relAx)[5] < bestHistPeakStart ) { continue; } //============================================ Consider only reasonable axes in terms of FSC - if ( allCs->at(relAx1)[6] < 0.3 ) { continue; } + if ( allCs->at(relAx)[6] < bestFSCPeakStart ) { continue; } //============================================ Get the sum - curOrtSum = allCs->at(relAx1)[5] + allCs->at(relAx1)[6]; + curOrtSum = allCs->at(relAx)[6]; //============================================ If highest sum, save if ( curOrtSum > maxOrtSum ) { maxOrtSum = curOrtSum; - maxOrtAx1 = static_cast< proshade_unsign > ( relAx1 ); + maxOrtAx1 = static_cast< proshade_signed > ( relAx ); } } //================================================ If anything was found, save it - if ( maxOrtSum > 0.1 ) + if ( maxOrtAx1 >= 0 ) { //============================================ Report progress ProSHADE_internal_messages::printProgressMessage ( verbose, 3, "Found single reliable axis.", messageShift ); - ProSHADE_internal_misc::addToUnsignVector ( &ret, maxOrtAx1 ); + ProSHADE_internal_misc::addToUnsignVector ( &ret, static_cast< proshade_unsign > ( maxOrtAx1 ) ); } else { diff --git a/proshade/src/proshade/ProSHADE_symmetry.hpp b/proshade/src/proshade/ProSHADE_symmetry.hpp index 99526c7a..bc69a85f 100644 --- a/proshade/src/proshade/ProSHADE_symmetry.hpp +++ b/proshade/src/proshade/ProSHADE_symmetry.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -36,8 +36,6 @@ namespace ProSHADE_internal_symmetry { bool isSymmetrySame ( std::vector< proshade_double* >* ret, proshade_double* sym, proshade_double simThres, proshade_signed* matchedPos ); bool isSymmetrySame ( std::vector< proshade_double* >* ret, proshade_double* sym, proshade_double simThres, proshade_signed* matchedPos, proshade_double fscVal ); - void saveDSymmetry ( std::vector< proshade_double* >* ret, std::vector< proshade_double* >* CSymList, - proshade_unsign axisOne, proshade_unsign axisTwo ); bool detectTetrahedralSymmetry ( std::vector< proshade_double* >* CSymList, proshade_double axErr, proshade_double minPeakHeight ); void findTetra4C3s ( std::vector< proshade_double* >* CSymList, std::vector< proshade_double* >* ret, proshade_double axErr, ProSHADE_internal_data::ProSHADE_data* dataObj, @@ -120,7 +118,7 @@ namespace ProSHADE_internal_symmetry void predictIcosAxes ( std::vector< proshade_double* >* CSymList, std::vector< std::vector< proshade_double* > >* ret, proshade_double axErr, proshade_double minPeakHeight ); void predictOctaAxes ( std::vector< proshade_double* >* CSymList, std::vector< std::vector< proshade_double* > >* ret, proshade_double axErr, proshade_double minPeakHeight ); void predictTetraAxes ( std::vector< proshade_double* >* CSymList, std::vector< std::vector< proshade_double* > >* ret, proshade_double axErr, proshade_double minPeakHeight ); - std::vector< proshade_unsign > findReliableUnphasedSymmetries ( std::vector < std::vector< proshade_double > >* allCs, proshade_signed verbose, proshade_signed messageShift, proshade_double tolerance ); + std::vector< proshade_unsign > findReliableUnphasedSymmetries ( std::vector < proshade_double* >* allCs, std::vector < std::vector < proshade_double* > >* allDs, proshade_signed verbose, proshade_signed messageShift, proshade_double tolerance ); void allocateCentreOfMapFourierTransforms ( proshade_unsign xDim, proshade_unsign yDim, proshade_unsign zDim, fftw_complex *&origMap, fftw_complex *&origCoeffs, fftw_complex *&rotMapComplex, fftw_complex *&rotCoeffs, fftw_complex *&trFunc, fftw_complex *&trFuncCoeffs, fftw_plan *planForwardFourier, fftw_plan *planForwardFourierRot, fftw_plan *planReverseFourierComb ); diff --git a/proshade/src/proshade/ProSHADE_tasks.cpp b/proshade/src/proshade/ProSHADE_tasks.cpp index 3c99e4c0..d2772002 100644 --- a/proshade/src/proshade/ProSHADE_tasks.cpp +++ b/proshade/src/proshade/ProSHADE_tasks.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -285,7 +285,7 @@ void ProSHADE_internal_tasks::checkDistancesSettings ( ProSHADE_settings* settin \param[in] allCs A pointer to a vector to which all the detected cyclic symmetries will be saved into. \param[in] mapCOMShift A pointer to a vector containing the distance from the centre of the map to the point about which the symmetry detection was done. */ -void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double* >* axes, std::vector < std::vector< proshade_double > >* allCs, std::vector< proshade_double >* mapCOMShift ) +void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double >* mapCOMShift ) { //================================================ Check the settings are complete and meaningful checkSymmetrySettings ( settings ); @@ -310,7 +310,7 @@ void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* setting rotCenSettings->messageShift = 1; //======================================== Run the detection - SymmetryCentreDetectionTask ( rotCenSettings, allCs, axes, iter ); + SymmetryCentreDetectionTask ( rotCenSettings, iter ); //======================================== Save the results settings->centrePosition.at(0) = rotCenSettings->centrePosition.at(0); @@ -319,7 +319,7 @@ void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* setting //======================================== Report progress std::stringstream ss; - ss << "Detected symmetry centre at " << settings->centrePosition.at(0) << " ; " << settings->centrePosition.at(1) << " ; " << settings->centrePosition.at(2) << std::endl; + ss << "Detected symmetry centre at " << settings->centrePosition.at(0) << " ; " << settings->centrePosition.at(1) << " ; " << settings->centrePosition.at(2); ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, ss.str(), settings->messageShift ); } @@ -336,10 +336,10 @@ void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* setting symmetryStructure->computeRotationFunction ( settings ); //======================================== Detect point groups in the angle-axis space - symmetryStructure->detectSymmetryFromAngleAxisSpace ( settings, axes, allCs ); + symmetryStructure->detectSymmetryFromAngleAxisSpace ( settings ); //============================================ Report results - symmetryStructure->reportSymmetryResults ( settings ); + symmetryStructure->reportSymmetryResultsList ( settings ); //============================================ Save internal map shift to run object, ProSHADE_internal_misc::addToDoubleVector ( mapCOMShift, symmetryStructure->mapCOMProcessChangeX ); @@ -363,14 +363,14 @@ void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* setting \param[in] settings ProSHADE_settings object specifying the details of how symmetry centre detection should be done. \param[in] strIndex The index of the structure to be read from the structure list available in the settings object. */ -void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* settings, std::vector < std::vector< proshade_double > >* allCs, std::vector< proshade_double* >* axes, proshade_unsign strIndex ) +void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* settings, proshade_unsign strIndex ) { //================================================ Keep original settings for the phased reading ProSHADE_settings* tmpSettings = new ProSHADE_settings ( settings ); //================================================ Enforce the necessary settings tmpSettings->usePhase = false; - tmpSettings->requestedSymmetryType = "onlyC"; + tmpSettings->requestedSymmetryType = "onlyCandD"; tmpSettings->moveToCOM = false; tmpSettings->addExtraSpace = tmpSettings->addExtraSpace * 5.0f; settings->moveToCOM = false; @@ -382,11 +382,19 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s symStr->mapToSpheres ( tmpSettings ); symStr->computeSphericalHarmonics ( tmpSettings ); symStr->computeRotationFunction ( tmpSettings ); - symStr->detectSymmetryFromAngleAxisSpace ( tmpSettings, axes, allCs ); + symStr->detectSymmetryFromAngleAxisSpace ( tmpSettings ); //================================================ Find reliable symmetries in the Patterson map - std::vector< proshade_unsign > relSym = ProSHADE_internal_symmetry::findReliableUnphasedSymmetries ( allCs, tmpSettings->verbose, settings->messageShift, tmpSettings->axisErrTolerance ); - + std::vector< proshade_unsign > relSym = ProSHADE_internal_symmetry::findReliableUnphasedSymmetries ( symStr->getCyclicAxes(), symStr->getDihedralAxes(), tmpSettings->verbose, settings->messageShift, tmpSettings->axisErrTolerance ); + std::vector< std::vector< proshade_double > > allCs; + std::vector< proshade_double > hlpVec; + for ( size_t it1 = 0; it1 < symStr->getCyclicAxes()->size(); it1++ ) + { + hlpVec.clear ( ); + for ( size_t it2 = 0; it2 < 7; it2++ ) { ProSHADE_internal_misc::addToDoubleVector ( &hlpVec, symStr->getCyclicAxes()->at(it1)[it2] ); } + ProSHADE_internal_misc::addToDoubleVectorVector ( &allCs, hlpVec ); + } + //================================================ If no symmetries are found, inform the user if ( relSym.size() == 0 ) { @@ -402,23 +410,27 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s std::stringstream ssHlp2; if ( relSym.size() == 1 ) { - ssHlp << "Decided that there is one reliable axis forming C" << allCs->at(relSym.at(0))[0]; - ssHlp2 << "The axis is: [" << allCs->at(relSym.at(0))[1] << " , " << allCs->at(relSym.at(0))[2] << " , " << allCs->at(relSym.at(0))[3] << "] with angle " << allCs->at(relSym.at(0))[4] << " peak height " << allCs->at(relSym.at(0))[5] << " and average FSC of " << allCs->at(relSym.at(0))[6] << std::endl; + ssHlp << "Decided that there is one reliable axis forming C" << allCs.at(relSym.at(0))[0]; + ssHlp2 << "The axis is: [" << allCs.at(relSym.at(0))[1] << " , " << allCs.at(relSym.at(0))[2] << " , " << allCs.at(relSym.at(0))[3] << "] with angle " << allCs.at(relSym.at(0))[4] << " peak height " << allCs.at(relSym.at(0))[5] << " and average FSC of " << allCs.at(relSym.at(0))[6]; } else { - ssHlp << "Decided that there are two reliable axes forming D" << std::max ( allCs->at(relSym.at(0))[0], allCs->at(relSym.at(1))[0] ); - ssHlp2 << "The first axis is: [" << allCs->at(relSym.at(0))[1] << " , " << allCs->at(relSym.at(0))[2] << " , " << allCs->at(relSym.at(0))[3] << "] with angle " << allCs->at(relSym.at(0))[4] << " peak height " << allCs->at(relSym.at(0))[5] << " and average FSC of " << allCs->at(relSym.at(0))[6] << std::endl; - ssHlp2 << " and the second axis is: [" << allCs->at(relSym.at(1))[1] << " , " << allCs->at(relSym.at(1))[2] << " , " << allCs->at(relSym.at(1))[3] << "] with angle " << allCs->at(relSym.at(1))[4] << " peak height " << allCs->at(relSym.at(1))[5] << " and average FSC of " << allCs->at(relSym.at(1))[6] << std::endl; + ssHlp << "Decided that there are two reliable axes forming D" << std::max ( allCs.at(relSym.at(0))[0], allCs.at(relSym.at(1))[0] ); + ssHlp2 << "The first axis is: [" << allCs.at(relSym.at(0))[1] << " , " << allCs.at(relSym.at(0))[2] << " , " << allCs.at(relSym.at(0))[3] << "] with angle " << allCs.at(relSym.at(0))[4] << " peak height " << allCs.at(relSym.at(0))[5] << " and average FSC of " << allCs.at(relSym.at(0))[6] << std::endl; + for ( size_t it = 0; it < static_cast< size_t > ( settings->verbose + settings->messageShift ); it++ ) { ssHlp2 << " ..."; } + ssHlp2 << " and the second axis is: [" << allCs.at(relSym.at(1))[1] << " , " << allCs.at(relSym.at(1))[2] << " , " << allCs.at(relSym.at(1))[3] << "] with angle " << allCs.at(relSym.at(1))[4] << " peak height " << allCs.at(relSym.at(1))[5] << " and average FSC of " << allCs.at(relSym.at(1))[6]; } ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 2, ssHlp.str(), settings->messageShift ); + ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 5, ssHlp2.str(), settings->messageShift ); + + } //================================================ Optimise the orthogonal pair, if there is one if ( relSym.size() == 2 ) { //============================================ Optimise the orthogonal pair - ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( allCs, relSym, symStr, tmpSettings ); + ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( &allCs, relSym, symStr, tmpSettings ); } //================================================ Re-read the map, this time with phases @@ -435,21 +447,7 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s //================================================ Compute Fourier for the original map for ( size_t it = 0; it < static_cast< size_t > ( symStr->getXDim() * symStr->getYDim() * symStr->getZDim() ); it++ ) { origMap[it][0] = symStr->getMapValue( it ); origMap[it][1] = 0.0; } fftw_execute ( planForwardFourier ); - -// //== Allocate Fourier coefficients array for the translation optimisation -// proshade_complex* trsOptMap = new proshade_complex[symStr->getXDim() * symStr->getYDim() * symStr->getZDim()]; -// proshade_complex* trsOptCoeffs = new proshade_complex[symStr->getXDim() * symStr->getYDim() * symStr->getZDim()]; -// ProSHADE_internal_misc::checkMemoryAllocation ( trsOptMap, __FILE__, __LINE__, __func__ ); -// ProSHADE_internal_misc::checkMemoryAllocation ( trsOptCoeffs, __FILE__, __LINE__, __func__ ); -// fftw_plan planForwardOptimisation = fftw_plan_dft_3d ( static_cast< int > ( symStr->getXDim() ), static_cast< int > ( symStr->getYDim() ), static_cast< int > ( symStr->getZDim() ), trsOptMap, trsOptCoeffs, FFTW_FORWARD, FFTW_ESTIMATE ); - - //== Prepare FSC computation memory and variables -// fftw_complex *FSCmapData, *FSCorigCoeffs, *FSCfCoeffs; -// fftw_plan FSCplanForwardFourier; -// proshade_double **binDataFSC, *fscByBin; -// proshade_signed *binIndexing, *binCounts, noBins; -// symStr->prepareFSCFourierMemory ( FSCmapData, FSCorigCoeffs, FSCfCoeffs, binIndexing, &noBins, binDataFSC, binCounts, &FSCplanForwardFourier, fscByBin ); - + //================================================ If single C was found if ( relSym.size() == 1 ) { @@ -460,7 +458,7 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s //============================================ Find the point ProSHADE_internal_misc::addToUnsignVector ( &axLst, static_cast< proshade_unsign > ( relSym.at(0) ) ); - symElems = symStr->getAllGroupElements ( allCs, axLst, "C", tmpSettings->axisErrTolerance ); + symElems = symStr->getAllGroupElements ( &allCs, axLst, "C", tmpSettings->axisErrTolerance ); std::vector< proshade_double > pointPos = ProSHADE_internal_symmetry::findPointFromTranslations ( symStr, symElems, origCoeffs, rotMapComplex, @@ -477,28 +475,28 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s proshade_double zBoxCentre = ( ( static_cast< proshade_double > ( symStr->zTo ) - static_cast< proshade_double > ( symStr->zFrom ) ) / 2.0 ) + static_cast< proshade_double > ( symStr->zFrom ); //============================================ Determine distance from COM in indices to box centre in indices - proshade_double xCOMFromBoxCen = xBoxCentre - ( xMapCOM / static_cast< proshade_double > ( symStr->xDimSize ) / static_cast< proshade_double > ( symStr->xDimIndices ) ); - proshade_double yCOMFromBoxCen = yBoxCentre - ( yMapCOM / static_cast< proshade_double > ( symStr->yDimSize ) / static_cast< proshade_double > ( symStr->yDimIndices ) ); - proshade_double zCOMFromBoxCen = zBoxCentre - ( zMapCOM / static_cast< proshade_double > ( symStr->zDimSize ) / static_cast< proshade_double > ( symStr->zDimIndices ) ); + proshade_double xCOMFromBoxCen = xBoxCentre - ( xMapCOM / ( static_cast< proshade_double > ( symStr->xDimSize ) / static_cast< proshade_double > ( symStr->xDimIndices ) ) ); + proshade_double yCOMFromBoxCen = yBoxCentre - ( yMapCOM / ( static_cast< proshade_double > ( symStr->yDimSize ) / static_cast< proshade_double > ( symStr->yDimIndices ) ) ); + proshade_double zCOMFromBoxCen = zBoxCentre - ( zMapCOM / ( static_cast< proshade_double > ( symStr->zDimSize ) / static_cast< proshade_double > ( symStr->zDimIndices ) ) ); //============================================ Determine the coefficient of mapping of the COM point to the line proshade_double alpha1 = ProSHADE_internal_maths::computeDotProduct ( pointPos.at(0) - xCOMFromBoxCen, pointPos.at(1) - yCOMFromBoxCen, pointPos.at(2) - zCOMFromBoxCen, - allCs->at(relSym.at(0))[1], - allCs->at(relSym.at(0))[2], - allCs->at(relSym.at(0))[3] ) / - ProSHADE_internal_maths::computeDotProduct ( allCs->at(relSym.at(0))[1], - allCs->at(relSym.at(0))[2], - allCs->at(relSym.at(0))[3], - allCs->at(relSym.at(0))[1], - allCs->at(relSym.at(0))[2], - allCs->at(relSym.at(0))[3] ); + allCs.at(relSym.at(0))[1], + allCs.at(relSym.at(0))[2], + allCs.at(relSym.at(0))[3] ) / + ProSHADE_internal_maths::computeDotProduct ( allCs.at(relSym.at(0))[1], + allCs.at(relSym.at(0))[2], + allCs.at(relSym.at(0))[3], + allCs.at(relSym.at(0))[1], + allCs.at(relSym.at(0))[2], + allCs.at(relSym.at(0))[3] ); //============================================ Determine point on the axis closest to COM - settings->centrePosition.at(0) = pointPos.at(0) + ( alpha1 * allCs->at(relSym.at(0))[1] ); - settings->centrePosition.at(1) = pointPos.at(1) + ( alpha1 * allCs->at(relSym.at(0))[2] ); - settings->centrePosition.at(2) = pointPos.at(2) + ( alpha1 * allCs->at(relSym.at(0))[3] ); + settings->centrePosition.at(0) = pointPos.at(0) + ( alpha1 * allCs.at(relSym.at(0))[1] ); + settings->centrePosition.at(1) = pointPos.at(1) + ( alpha1 * allCs.at(relSym.at(0))[2] ); + settings->centrePosition.at(2) = pointPos.at(2) + ( alpha1 * allCs.at(relSym.at(0))[3] ); } //================================================ If D was found else @@ -509,7 +507,7 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s //============================================ Find the first point ProSHADE_internal_misc::addToUnsignVector ( &axLst, static_cast< proshade_unsign > ( relSym.at(0) ) ); - symElems = symStr->getAllGroupElements ( allCs, axLst, "C", tmpSettings->axisErrTolerance ); + symElems = symStr->getAllGroupElements ( &allCs, axLst, "C", tmpSettings->axisErrTolerance ); std::vector< proshade_double > point1Pos = ProSHADE_internal_symmetry::findPointFromTranslations ( symStr, symElems, origCoeffs, rotMapComplex, @@ -519,7 +517,7 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s //============================================ Find the second point axLst.at(0) = static_cast< proshade_unsign > ( relSym.at(1) ); - symElems = symStr->getAllGroupElements ( allCs, axLst, "C", tmpSettings->axisErrTolerance ); + symElems = symStr->getAllGroupElements ( &allCs, axLst, "C", tmpSettings->axisErrTolerance ); std::vector< proshade_double > point2Pos = ProSHADE_internal_symmetry::findPointFromTranslations ( symStr, symElems, origCoeffs, rotMapComplex, @@ -528,13 +526,13 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s planReverseFourierComb ); //============================================ Compute the tangents - proshade_double* tangentToAxes = ProSHADE_internal_maths::computeCrossProduct ( allCs->at(relSym.at(0))[1], allCs->at(relSym.at(0))[2], allCs->at(relSym.at(0))[3], - allCs->at(relSym.at(1))[1], allCs->at(relSym.at(1))[2], allCs->at(relSym.at(1))[3] ); + proshade_double* tangentToAxes = ProSHADE_internal_maths::computeCrossProduct ( allCs.at(relSym.at(0))[1], allCs.at(relSym.at(0))[2], allCs.at(relSym.at(0))[3], + allCs.at(relSym.at(1))[1], allCs.at(relSym.at(1))[2], allCs.at(relSym.at(1))[3] ); - proshade_double* correctedSecondAxis = ProSHADE_internal_maths::computeCrossProduct ( allCs->at(relSym.at(0))[1], allCs->at(relSym.at(0))[2], allCs->at(relSym.at(0))[3], + proshade_double* correctedSecondAxis = ProSHADE_internal_maths::computeCrossProduct ( allCs.at(relSym.at(0))[1], allCs.at(relSym.at(0))[2], allCs.at(relSym.at(0))[3], tangentToAxes[0], tangentToAxes[1], tangentToAxes[2] ); - proshade_double* correctedFirstAxis = ProSHADE_internal_maths::computeCrossProduct ( allCs->at(relSym.at(1))[1], allCs->at(relSym.at(1))[2], allCs->at(relSym.at(1))[3], + proshade_double* correctedFirstAxis = ProSHADE_internal_maths::computeCrossProduct ( allCs.at(relSym.at(1))[1], allCs.at(relSym.at(1))[2], allCs.at(relSym.at(1))[3], tangentToAxes[0], tangentToAxes[1], tangentToAxes[2] ); //============================================ Compute mappings @@ -542,19 +540,19 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s point2Pos.at(1) - point1Pos.at(1), point2Pos.at(2) - point1Pos.at(2), correctedFirstAxis[0], correctedFirstAxis[1], correctedFirstAxis[2] ) / - ProSHADE_internal_maths::computeDotProduct ( allCs->at(relSym.at(0))[1], allCs->at(relSym.at(0))[2], allCs->at(relSym.at(0))[3], + ProSHADE_internal_maths::computeDotProduct ( allCs.at(relSym.at(0))[1], allCs.at(relSym.at(0))[2], allCs.at(relSym.at(0))[3], correctedFirstAxis[0], correctedFirstAxis[1], correctedFirstAxis[2] ); proshade_double alpha2 = ProSHADE_internal_maths::computeDotProduct ( point1Pos.at(0) - point2Pos.at(0), point1Pos.at(1) - point2Pos.at(1), point1Pos.at(2) - point2Pos.at(2), correctedSecondAxis[0], correctedSecondAxis[1], correctedSecondAxis[2] ) / - ProSHADE_internal_maths::computeDotProduct ( allCs->at(relSym.at(1))[1], allCs->at(relSym.at(1))[2], allCs->at(relSym.at(1))[3], + ProSHADE_internal_maths::computeDotProduct ( allCs.at(relSym.at(1))[1], allCs.at(relSym.at(1))[2], allCs.at(relSym.at(1))[3], correctedSecondAxis[0], correctedSecondAxis[1], correctedSecondAxis[2] ); //============================================ Find the intersect point (averaged) - settings->centrePosition.at(0) = ( ( point1Pos.at(0) + ( alpha1 * allCs->at(relSym.at(0))[1] ) ) + ( point2Pos.at(0) + ( alpha2 * allCs->at(relSym.at(1))[1] ) ) ) / 2.0; - settings->centrePosition.at(1) = ( ( point1Pos.at(1) + ( alpha1 * allCs->at(relSym.at(0))[2] ) ) + ( point2Pos.at(1) + ( alpha2 * allCs->at(relSym.at(1))[2] ) ) ) / 2.0; - settings->centrePosition.at(2) = ( ( point1Pos.at(2) + ( alpha1 * allCs->at(relSym.at(0))[3] ) ) + ( point2Pos.at(2) + ( alpha2 * allCs->at(relSym.at(1))[3] ) ) ) / 2.0; + settings->centrePosition.at(0) = ( ( point1Pos.at(0) + ( alpha1 * allCs.at(relSym.at(0))[1] ) ) + ( point2Pos.at(0) + ( alpha2 * allCs.at(relSym.at(1))[1] ) ) ) / 2.0; + settings->centrePosition.at(1) = ( ( point1Pos.at(1) + ( alpha1 * allCs.at(relSym.at(0))[2] ) ) + ( point2Pos.at(1) + ( alpha2 * allCs.at(relSym.at(1))[2] ) ) ) / 2.0; + settings->centrePosition.at(2) = ( ( point1Pos.at(2) + ( alpha1 * allCs.at(relSym.at(0))[3] ) ) + ( point2Pos.at(2) + ( alpha2 * allCs.at(relSym.at(1))[3] ) ) ) / 2.0; //============================================ Release memory delete[] tangentToAxes; diff --git a/proshade/src/proshade/ProSHADE_tasks.hpp b/proshade/src/proshade/ProSHADE_tasks.hpp index c86f7541..7e3f020c 100644 --- a/proshade/src/proshade/ProSHADE_tasks.hpp +++ b/proshade/src/proshade/ProSHADE_tasks.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -40,12 +40,10 @@ namespace ProSHADE_internal_tasks std::vector < proshade_signed* >* reboxedBounds, std::vector < proshade_double* >* manipulatedMaps ); void DistancesComputationTask ( ProSHADE_settings* settings, std::vector< proshade_double >* enLevs, std::vector< proshade_double >* trSigm, std::vector< proshade_double >* rotFun ); - void SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double* >* axes, std::vector < std::vector< proshade_double > >* allCs, - std::vector< proshade_double >* mapCOMShift ); + void SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double >* mapCOMShift ); void MapOverlayTask ( ProSHADE_settings* settings, std::vector < proshade_double >* rotationCentre, std::vector < proshade_double >* eulerAngles, std::vector < proshade_double >* finalTranslation ); - void SymmetryCentreDetectionTask ( ProSHADE_settings* settings, std::vector < std::vector< proshade_double > >* allCs, std::vector< proshade_double* >* axes, - proshade_unsign strIndex = 0 ); + void SymmetryCentreDetectionTask ( ProSHADE_settings* settings, proshade_unsign strIndex = 0 ); void ReportDistancesResults ( ProSHADE_settings* settings, std::string str1, std::string str2, proshade_double enLevDist, proshade_double trSigmDist, proshade_double rotFunDist ); diff --git a/proshade/src/proshade/ProSHADE_typedefs.hpp b/proshade/src/proshade/ProSHADE_typedefs.hpp index 9cddd723..259b3d10 100644 --- a/proshade/src/proshade/ProSHADE_typedefs.hpp +++ b/proshade/src/proshade/ProSHADE_typedefs.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_version.hpp b/proshade/src/proshade/ProSHADE_version.hpp index 13358411..f2b9b3e5 100644 --- a/proshade/src/proshade/ProSHADE_version.hpp +++ b/proshade/src/proshade/ProSHADE_version.hpp @@ -14,12 +14,12 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Overinclusion protection #ifndef PROSHADE_VERSION -#define PROSHADE_VERSION "0.7.6.5 (JUN 2022)" +#define PROSHADE_VERSION "0.7.6.6 (JUL 2022)" #endif diff --git a/proshade/src/proshade/ProSHADE_wignerMatrices.cpp b/proshade/src/proshade/ProSHADE_wignerMatrices.cpp index 2f0eeb05..1c719448 100644 --- a/proshade/src/proshade/ProSHADE_wignerMatrices.cpp +++ b/proshade/src/proshade/ProSHADE_wignerMatrices.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/src/proshade/ProSHADE_wignerMatrices.hpp b/proshade/src/proshade/ProSHADE_wignerMatrices.hpp index 8d9175bb..d100f5fe 100644 --- a/proshade/src/proshade/ProSHADE_wignerMatrices.hpp +++ b/proshade/src/proshade/ProSHADE_wignerMatrices.hpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE library code diff --git a/proshade/src/python/pyProSHADE.cpp b/proshade/src/python/pyProSHADE.cpp index 7ba7e6ee..51d07f7f 100644 --- a/proshade/src/python/pyProSHADE.cpp +++ b/proshade/src/python/pyProSHADE.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Include PyBind11 header @@ -108,8 +108,6 @@ void add_settingsClass ( pybind11::module& pyProSHADE ) .def_readwrite ( "axisErrTolerance", &ProSHADE_settings::axisErrTolerance ) .def_readwrite ( "axisErrToleranceDefault", &ProSHADE_settings::axisErrToleranceDefault ) .def_readwrite ( "minSymPeak", &ProSHADE_settings::minSymPeak ) - .def_readwrite ( "recommendedSymmetryType", &ProSHADE_settings::recommendedSymmetryType ) - .def_readwrite ( "recommendedSymmetryFold", &ProSHADE_settings::recommendedSymmetryFold ) .def_readwrite ( "requestedSymmetryType", &ProSHADE_settings::requestedSymmetryType ) .def_readwrite ( "requestedSymmetryFold", &ProSHADE_settings::requestedSymmetryFold ) .def_readwrite ( "maxSymmetryFold", &ProSHADE_settings::maxSymmetryFold ) @@ -174,11 +172,8 @@ void add_settingsClass ( pybind11::module& pyProSHADE ) .def ( "setAxisComparisonThreshold", &ProSHADE_settings::setAxisComparisonThreshold, "Sets the threshold for matching symmetry axes.", pybind11::arg ( "axThres" ) ) .def ( "setAxisComparisonThresholdBehaviour", &ProSHADE_settings::setAxisComparisonThresholdBehaviour, "Sets the automatic symmetry axis tolerance decreasing.", pybind11::arg ( "behav" ) ) .def ( "setMinimumPeakForAxis", &ProSHADE_settings::setMinimumPeakForAxis, "Sets the minimum peak height for symmetry axis to be considered.", pybind11::arg ( "minSP" ) ) - .def ( "setRecommendedSymmetry", &ProSHADE_settings::setRecommendedSymmetry, "Sets the ProSHADE detected symmetry type.", pybind11::arg ( "val" ) ) - .def ( "setRecommendedFold", &ProSHADE_settings::setRecommendedFold, "Sets the ProSHADE detected symmetry fold.", pybind11::arg ( "val" ) ) .def ( "setRequestedSymmetry", &ProSHADE_settings::setRequestedSymmetry, "Sets the user requested symmetry type.", pybind11::arg ( "val" ) ) .def ( "setRequestedFold", &ProSHADE_settings::setRequestedFold, "Sets the user requested symmetry fold.", pybind11::arg ( "val" ) ) - .def ( "setDetectedSymmetry", &ProSHADE_settings::setDetectedSymmetry, "Sets the final detected symmetry axes information.", pybind11::arg ( "sym" ) ) .def ( "setOverlaySaveFile", &ProSHADE_settings::setOverlaySaveFile, "Sets the filename to which the overlay structure is to be save into.", pybind11::arg ( "filename" ) ) .def ( "setOverlayJsonFile", &ProSHADE_settings::setOverlayJsonFile, "Sets the filename to which the overlay operations are to be save into.", pybind11::arg ( "filename" ) ) .def ( "setBicubicInterpolationSearch", &ProSHADE_settings::setBicubicInterpolationSearch, "Sets the bicubic interpolation on peaks.", pybind11::arg ( "bicubPeaks" ) ) diff --git a/proshade/src/python/pyProSHADE_bindings.cpp b/proshade/src/python/pyProSHADE_bindings.cpp index e8b2df6a..097ef7de 100644 --- a/proshade/src/python/pyProSHADE_bindings.cpp +++ b/proshade/src/python/pyProSHADE_bindings.cpp @@ -14,8 +14,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Do not use the following flags for the included files - this causes a lot of warnings that have nothing to do with ProSHADE diff --git a/proshade/src/python/pyProSHADE_data.cpp b/proshade/src/python/pyProSHADE_data.cpp index 8010ab09..383b15b7 100644 --- a/proshade/src/python/pyProSHADE_data.cpp +++ b/proshade/src/python/pyProSHADE_data.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Include PyBind11 header @@ -278,25 +278,44 @@ void add_dataClass ( pybind11::module& pyProSHADE ) [] ( ProSHADE_internal_data::ProSHADE_data &self, ProSHADE_settings* settings ) { //== Call the appropriate C++ function - self.detectSymmetryFromAngleAxisSpace ( settings, &settings->detectedSymmetry, &settings->allDetectedCAxes ); + self.detectSymmetryFromAngleAxisSpace ( settings ); }, "This function runs the symmetry detection algorithms on this structure and saves the results in the settings object.", pybind11::arg ( "settings" ) ) - .def ( "getRecommendedSymmetryType", &ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryType, "This function simply returns the detected recommended symmetry type.", pybind11::arg ( "settings" ) ) - .def ( "getRecommendedSymmetryFold", &ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryFold, "This function simply returns the detected recommended symmetry fold.", pybind11::arg ( "settings" ) ) + .def ( "reRunSymmetryDetectionThreshold", + [] ( ProSHADE_internal_data::ProSHADE_data &self, ProSHADE_settings* settings, proshade_double threshold ) + { + //== Prepare FSC computation memory and variables + fftw_complex* fCoeffsCut; + proshade_double **bindata, *fscByBin; + proshade_signed *cutIndices, *binCounts, noBins, cutXDim, cutYDim, cutZDim; + self.prepareFSCFourierMemory ( cutIndices, fCoeffsCut, &noBins, bindata, binCounts, fscByBin, settings->requestedResolution, &cutXDim, &cutYDim, &cutZDim ); + + //== Run detection with threshold + self.determineRecommendedSymmetry ( settings, threshold, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + + //== Release FSC computation memory + for (size_t binIt = 0; binIt < static_cast< size_t > ( noBins ); binIt++ ) { delete[] bindata[binIt]; } + delete[] bindata; + delete[] binCounts; + delete[] cutIndices; + fftw_free ( fCoeffsCut ); + }, "This function runs the symmetry detection algorithms on this structure and saves the results in the settings object.", pybind11::arg ( "settings" ), pybind11::arg ( "threshold" ) ) + .def ( "getRecommendedSymmetryType", &ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryType, "This function simply returns the detected recommended symmetry type." ) + .def ( "getRecommendedSymmetryFold", &ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryFold, "This function simply returns the detected recommended symmetry fold." ) .def ( "getRecommendedSymmetryAxes", - [] ( ProSHADE_internal_data::ProSHADE_data &self, ProSHADE_settings* settings ) -> pybind11::array_t < float > + [] ( ProSHADE_internal_data::ProSHADE_data &self ) -> pybind11::array_t < float > { //== Allocate memory for the numpy values - float* npVals = new float[static_cast ( settings->detectedSymmetry.size() * 7 )]; + float* npVals = new float[static_cast ( self.recommendedSymmetryValues.size() * 7 )]; ProSHADE_internal_misc::checkMemoryAllocation ( npVals, __FILE__, __LINE__, __func__ ); //== Copy values - for ( proshade_unsign iter = 0; iter < static_cast ( settings->detectedSymmetry.size() ); iter++ ) { for ( proshade_unsign it = 0; it < 7; it++ ) { npVals[(iter*7)+it] = static_cast< float > ( settings->detectedSymmetry.at(iter)[it] ); } } + for ( proshade_unsign iter = 0; iter < static_cast ( self.recommendedSymmetryValues.size() ); iter++ ) { for ( proshade_unsign it = 0; it < 7; it++ ) { npVals[(iter*7)+it] = static_cast< float > ( self.recommendedSymmetryValues.at(iter)[it] ); } } //== Create capsules to make sure memory is released properly from the allocating language (C++ in this case) pybind11::capsule pyCapsuleStrRecSym ( npVals, []( void *f ) { float* foo = reinterpret_cast< float* > ( f ); delete foo; } ); //== Copy the value - pybind11::array_t < float > retArr = pybind11::array_t ( { static_cast ( settings->detectedSymmetry.size() ), static_cast ( 7 ) }, // Shape + pybind11::array_t < float > retArr = pybind11::array_t ( { static_cast ( self.recommendedSymmetryValues.size() ), static_cast ( 7 ) }, // Shape { 7 * sizeof(float), sizeof(float) }, // C-stype strides npVals, // Data pyCapsuleStrRecSym ); // Capsule @@ -305,20 +324,20 @@ void add_dataClass ( pybind11::module& pyProSHADE ) return ( retArr ); }, "This function returns the recommended symmetry axes as a 2D numpy array." ) .def ( "getAllCSyms", - [] ( ProSHADE_internal_data::ProSHADE_data &self, ProSHADE_settings* settings ) -> pybind11::array_t < float > + [] ( ProSHADE_internal_data::ProSHADE_data &self ) -> pybind11::array_t < float > { //== Allocate memory for the numpy values - float* npVals = new float[static_cast ( settings->allDetectedCAxes.size() * 7 )]; + float* npVals = new float[static_cast ( self.cyclicSymmetries.size() * 7 )]; ProSHADE_internal_misc::checkMemoryAllocation ( npVals, __FILE__, __LINE__, __func__ ); //== Copy values - for ( proshade_unsign iter = 0; iter < static_cast ( settings->allDetectedCAxes.size() ); iter++ ) { for ( proshade_unsign it = 0; it < 7; it++ ) { npVals[(iter*7)+it] = static_cast< float > ( settings->allDetectedCAxes.at(iter).at(it) ); } } + for ( proshade_unsign iter = 0; iter < static_cast ( self.cyclicSymmetries.size() ); iter++ ) { for ( proshade_unsign it = 0; it < 7; it++ ) { npVals[(iter*7)+it] = static_cast< float > ( self.cyclicSymmetries.at(iter)[it] ); } } //== Create capsules to make sure memory is released properly from the allocating language (C++ in this case) pybind11::capsule pyCapsuleStrSymList ( npVals, []( void *f ) { float* foo = reinterpret_cast< float* > ( f ); delete foo; } ); //== Copy the value - pybind11::array_t < float > retArr = pybind11::array_t ( { static_cast ( settings->allDetectedCAxes.size() ), 7 }, // Shape + pybind11::array_t < float > retArr = pybind11::array_t ( { static_cast ( self.cyclicSymmetries.size() ), 7 }, // Shape { 7 * sizeof(float), sizeof(float) }, // C-stype strides npVals, // Data pyCapsuleStrSymList ); // Capsule @@ -327,41 +346,49 @@ void add_dataClass ( pybind11::module& pyProSHADE ) return ( retArr ); }, "This function returns all symmetry axes as a 2D numpy array." ) .def ( "getNonCSymmetryAxesIndices", - [] ( ProSHADE_internal_data::ProSHADE_data &self, ProSHADE_settings* settings ) -> pybind11::dict + [] ( ProSHADE_internal_data::ProSHADE_data &self ) -> pybind11::dict { //== Initialise local variables pybind11::dict retDict; pybind11::list dList, tList, oList, iList; - + //== Fill in the D list - for ( proshade_unsign dIt = 0; dIt < static_cast ( settings->allDetectedDAxes.size() ); dIt++ ) + for ( proshade_unsign dIt = 0; dIt < static_cast ( self.dihedralSymmetries.size() ); dIt++ ) { pybind11::list memList; - for ( proshade_unsign memIt = 0; memIt < static_cast ( settings->allDetectedDAxes.at(dIt).size() ); memIt++ ) + for ( proshade_unsign memIt = 0; memIt < static_cast ( self.dihedralSymmetries.at(dIt).size() ); memIt++ ) { - memList.append ( settings->allDetectedDAxes.at(dIt).at(memIt) ); + pybind11::list axList; + for ( size_t vIt = 0; vIt < 7; vIt++ ) { axList.append ( self.dihedralSymmetries.at(dIt).at(memIt)[vIt] ); } + memList.append ( axList ); } dList.append ( memList ); } - + //== Fill in the T list - for ( proshade_unsign tIt = 0; tIt < static_cast ( settings->allDetectedTAxes.size() ); tIt++ ) + for ( proshade_unsign tIt = 0; tIt < static_cast ( self.tetrahedralSymmetries.size() ); tIt++ ) { - tList.append ( settings->allDetectedTAxes.at ( tIt ) ); + pybind11::list axList; + for ( size_t vIt = 0; vIt < 7; vIt++ ) { axList.append ( self.tetrahedralSymmetries.at(tIt)[vIt] ); } + tList.append ( axList ); } - + //== Fill in the O list - for ( proshade_unsign oIt = 0; oIt < static_cast ( settings->allDetectedOAxes.size() ); oIt++ ) + for ( proshade_unsign oIt = 0; oIt < static_cast ( self.octahedralSymmetries.size() ); oIt++ ) { - oList.append ( settings->allDetectedOAxes.at ( oIt ) ); + pybind11::list axList; + for ( size_t vIt = 0; vIt < 7; vIt++ ) { axList.append ( self.octahedralSymmetries.at(oIt)[vIt] ); } + oList.append ( axList ); } - + //== Fill in the T list - for ( proshade_unsign iIt = 0; iIt < static_cast ( settings->allDetectedIAxes.size() ); iIt++ ) + for ( proshade_unsign iIt = 0; iIt < static_cast ( self.icosahedralSymmetries.size() ); iIt++ ) { - iList.append ( settings->allDetectedIAxes.at ( iIt ) ); + pybind11::list axList; + for ( size_t vIt = 0; vIt < 7; vIt++ ) { axList.append ( self.icosahedralSymmetries.at(iIt)[vIt] ); } + iList.append ( axList ); } - + //== Save the lists to the dict retDict[ pybind11::handle ( pybind11::str ( "D" ).ptr ( ) ) ] = dList; retDict[ pybind11::handle ( pybind11::str ( "T" ).ptr ( ) ) ] = tList; @@ -372,7 +399,7 @@ void add_dataClass ( pybind11::module& pyProSHADE ) return ( retDict ); }, "This function returns array of non-C axes indices." ) .def ( "getAllGroupElements", - [] ( ProSHADE_internal_data::ProSHADE_data &self, ProSHADE_settings* settings, pybind11::array_t < int > axList, std::string groupType, proshade_double matrixTolerance ) -> pybind11::list + [] ( ProSHADE_internal_data::ProSHADE_data &self, pybind11::array_t < int > axList, std::string groupType, proshade_double matrixTolerance ) -> pybind11::list { //== Sanity check pybind11::buffer_info buf = axList.request(); @@ -383,7 +410,7 @@ void add_dataClass ( pybind11::module& pyProSHADE ) for ( proshade_unsign iter = 0; iter < static_cast ( axList.size() ); iter++ ) { ProSHADE_internal_misc::addToUnsignVector ( &axesList, static_cast< proshade_unsign > ( axList.at(iter) ) ); } //== Get the results - std::vector < std::vector< proshade_double > > vals = self.getAllGroupElements ( settings, axesList, groupType, matrixTolerance ); + std::vector < std::vector< proshade_double > > vals = self.getAllGroupElements ( axesList, groupType, matrixTolerance ); //== Initialise return variable pybind11::list retList; @@ -413,7 +440,7 @@ void add_dataClass ( pybind11::module& pyProSHADE ) //== Done return ( retList ); - }, "This function returns the group elements as rotation matrices of any point group described by the detected axes.", pybind11::arg ( "settings" ), pybind11::arg ( "axList" ), pybind11::arg ( "groupType" ) = "", pybind11::arg( "matrixTolerance" ) = 0.05 ) + }, "This function returns the group elements as rotation matrices of any point group described by the detected axes.", pybind11::arg ( "axList" ), pybind11::arg ( "groupType" ) = "", pybind11::arg( "matrixTolerance" ) = 0.05 ) .def ( "getMapCOMProcessChange", [] ( ProSHADE_internal_data::ProSHADE_data &self ) -> pybind11::array_t < float > diff --git a/proshade/src/python/pyProSHADE_distances.cpp b/proshade/src/python/pyProSHADE_distances.cpp index 379bfa0a..22368372 100644 --- a/proshade/src/python/pyProSHADE_distances.cpp +++ b/proshade/src/python/pyProSHADE_distances.cpp @@ -14,8 +14,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Include PyBind11 header diff --git a/proshade/src/python/pyProSHADE_mapManip.cpp b/proshade/src/python/pyProSHADE_mapManip.cpp index d959776d..a1d32ac9 100644 --- a/proshade/src/python/pyProSHADE_mapManip.cpp +++ b/proshade/src/python/pyProSHADE_mapManip.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Include PyBind11 header diff --git a/proshade/src/python/pyProSHADE_maths.cpp b/proshade/src/python/pyProSHADE_maths.cpp index f4a4844f..bf9ee29e 100644 --- a/proshade/src/python/pyProSHADE_maths.cpp +++ b/proshade/src/python/pyProSHADE_maths.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Include PyBind11 header diff --git a/proshade/src/python/pyProSHADE_symmetry.cpp b/proshade/src/python/pyProSHADE_symmetry.cpp index 5fe9927b..e050b7c8 100644 --- a/proshade/src/python/pyProSHADE_symmetry.cpp +++ b/proshade/src/python/pyProSHADE_symmetry.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== Include PyBind11 header @@ -27,31 +27,31 @@ //==================================================== Add the ProSHADE_settings and ProSHADE_run classes to the PyBind11 module void add_symmetryNamespace ( pybind11::module& pyProSHADE ) { - pyProSHADE.def ( "findReliableUnphasedSymmetries", - [] ( ProSHADE_settings* settings, proshade_signed verbose, proshade_signed messageShift, proshade_double tolerance ) -> pybind11::array_t < proshade_unsign > - { - //== Run the detection - std::vector< proshade_unsign > rels = ProSHADE_internal_symmetry::findReliableUnphasedSymmetries ( &settings->allDetectedCAxes, verbose, messageShift, tolerance ); - - //== Allocate memory for the numpy values - proshade_unsign* npVals = new proshade_unsign[static_cast ( rels.size() )]; - ProSHADE_internal_misc::checkMemoryAllocation ( npVals, __FILE__, __LINE__, __func__ ); - - //== Copy values - for ( proshade_unsign iter = 0; iter < static_cast ( rels.size() ); iter++ ) { npVals[iter] = static_cast< proshade_unsign > ( rels.at(iter) ); } - - //== Create capsules to make sure memory is released properly from the allocating language (C++ in this case) - pybind11::capsule pyCapsuleRelSyms ( npVals, []( void *f ) { proshade_unsign* foo = reinterpret_cast< proshade_unsign* > ( f ); delete foo; } ); - - //== Copy the value - pybind11::array_t < proshade_unsign > retArr = pybind11::array_t< proshade_unsign > ( { static_cast ( rels.size() ) }, // Shape - { sizeof(proshade_unsign) }, // C-stype strides - npVals, // Data - pyCapsuleRelSyms ); // Capsule - - //== Done - return ( retArr ); - }, "This function checks the list of detected axes (presumably from phaseless symmetry detection) and returns the best dihedral (or cyclic, if no dihedral is found) point group, or empty vector if nothing is found.", pybind11::arg ( "settings" ), pybind11::arg ( "verbose" ), pybind11::arg ( "messageShift" ) = 1, pybind11::arg ( "tolerance" ) = 0.1 ); +// pyProSHADE.def ( "findReliableUnphasedSymmetries", +// [] ( ProSHADE_settings* settings, proshade_signed verbose, proshade_signed messageShift, proshade_double tolerance ) -> pybind11::array_t < proshade_unsign > +// { +// //== Run the detection +// std::vector< proshade_unsign > rels = ProSHADE_internal_symmetry::findReliableUnphasedSymmetries ( &settings->allDetectedCAxes, verbose, messageShift, tolerance ); +// +// //== Allocate memory for the numpy values +// proshade_unsign* npVals = new proshade_unsign[static_cast ( rels.size() )]; +// ProSHADE_internal_misc::checkMemoryAllocation ( npVals, __FILE__, __LINE__, __func__ ); +// +// //== Copy values +// for ( proshade_unsign iter = 0; iter < static_cast ( rels.size() ); iter++ ) { npVals[iter] = static_cast< proshade_unsign > ( rels.at(iter) ); } +// +// //== Create capsules to make sure memory is released properly from the allocating language (C++ in this case) +// pybind11::capsule pyCapsuleRelSyms ( npVals, []( void *f ) { proshade_unsign* foo = reinterpret_cast< proshade_unsign* > ( f ); delete foo; } ); +// +// //== Copy the value +// pybind11::array_t < proshade_unsign > retArr = pybind11::array_t< proshade_unsign > ( { static_cast ( rels.size() ) }, // Shape +// { sizeof(proshade_unsign) }, // C-stype strides +// npVals, // Data +// pyCapsuleRelSyms ); // Capsule +// +// //== Done +// return ( retArr ); +// }, "This function checks the list of detected axes (presumably from phaseless symmetry detection) and returns the best dihedral (or cyclic, if no dihedral is found) point group, or empty vector if nothing is found.", pybind11::arg ( "settings" ), pybind11::arg ( "verbose" ), pybind11::arg ( "messageShift" ) = 1, pybind11::arg ( "tolerance" ) = 0.1 ); pyProSHADE.def ( "optimiseDGroupAngleFromAxesHeights", [] ( pybind11::array_t < proshade_unsign > selection, ProSHADE_internal_data::ProSHADE_data* dataObj, ProSHADE_settings* settings ) @@ -67,8 +67,18 @@ void add_symmetryNamespace ( pybind11::module& pyProSHADE ) ProSHADE_internal_misc::addToUnsignVector ( &sel, arrStart[0] ); ProSHADE_internal_misc::addToUnsignVector ( &sel, arrStart[1] ); + //== Convert data type + std::vector< std::vector< proshade_double > > allCs; + std::vector< proshade_double > hlpVec; + for ( size_t it1 = 0; it1 < dataObj->getCyclicAxes()->size(); it1++ ) + { + hlpVec.clear ( ); + for ( size_t it2 = 0; it2 < 7; it2++ ) { ProSHADE_internal_misc::addToDoubleVector ( &hlpVec, dataObj->getCyclicAxes()->at(it1)[it2] ); } + ProSHADE_internal_misc::addToDoubleVectorVector ( &allCs, hlpVec ); + } + //== Call the C++ function - ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( &settings->allDetectedCAxes, sel, dataObj, settings ); + ProSHADE_internal_symmetry::optimiseDGroupAngleFromAxesHeights ( &allCs, sel, dataObj, settings ); //== Done (all changes are in the data object, so nothing needs to be passed to Python) return ; From 5ecc36e5dcb95637c9117a362c7287e0b3e8dada Mon Sep 17 00:00:00 2001 From: Michal Tykac Date: Mon, 11 Jul 2022 23:50:47 +0200 Subject: [PATCH 2/4] Modified all the examples to now use the new function calls and to have the correct expected output values written into them. --- .../libproshade/advancedAccess_distances.cpp | 6 +- .../libproshade/advancedAccess_overlay.cpp | 16 +-- .../libproshade/advancedAccess_reboxing.cpp | 4 +- .../libproshade/advancedAccess_symmetry.cpp | 123 ++++++++++++------ .../examples/libproshade/proshadeBinary.cpp | 4 +- .../libproshade/simpleAccess_distances.cpp | 6 +- .../libproshade/simpleAccess_overlay.cpp | 16 +-- .../libproshade/simpleAccess_reboxing.cpp | 4 +- .../libproshade/simpleAccess_symmetry.cpp | 10 +- .../python/advancedAccess_distances.py | 6 +- .../examples/python/advancedAccess_overlay.py | 16 +-- .../examples/python/advancedAccess_reBox.py | 4 +- .../python/advancedAccess_symmetry.py | 85 +++++++----- proshade/examples/python/directAccess.py | 62 ++++----- .../python/howto_accessInterimResults.py | 18 +-- .../examples/python/howto_passProcessedMap.py | 28 ++-- .../examples/python/simpleAccess_distances.py | 6 +- .../examples/python/simpleAccess_overlay.py | 16 +-- .../examples/python/simpleAccess_reBox.py | 4 +- .../examples/python/simpleAccess_symmetry.py | 12 +- .../getMaskedSymmetryPredictions.py | 2 +- proshade/src/proshade/ProSHADE.cpp | 5 +- proshade/src/proshade/ProSHADE.hpp | 6 +- proshade/src/proshade/ProSHADE_data.cpp | 82 ++++++++++-- proshade/src/proshade/ProSHADE_data.hpp | 3 + proshade/src/proshade/ProSHADE_tasks.cpp | 16 ++- proshade/src/proshade/ProSHADE_tasks.hpp | 2 +- 27 files changed, 348 insertions(+), 214 deletions(-) diff --git a/proshade/examples/libproshade/advancedAccess_distances.cpp b/proshade/examples/libproshade/advancedAccess_distances.cpp index 1db3f8c6..571a7b28 100644 --- a/proshade/examples/libproshade/advancedAccess_distances.cpp +++ b/proshade/examples/libproshade/advancedAccess_distances.cpp @@ -17,8 +17,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -128,7 +128,7 @@ int main ( int argc, char **argv ) //================================================ Expected output // Energy levels distance : 0.85561 // Trace sigma distance : 0.97777 -// Rotation function distance : 0.59682 +// Rotation function distance : 0.599 //================================================ Release the settings and runProshade objects delete structure1; diff --git a/proshade/examples/libproshade/advancedAccess_overlay.cpp b/proshade/examples/libproshade/advancedAccess_overlay.cpp index 308a979f..9cdc387b 100644 --- a/proshade/examples/libproshade/advancedAccess_overlay.cpp +++ b/proshade/examples/libproshade/advancedAccess_overlay.cpp @@ -18,8 +18,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -126,10 +126,10 @@ int main ( int argc, char **argv ) std::cout << " : " << rotMat[6] << " ; " << rotMat[7] << " ; " << rotMat[8] << std::endl; //================================================ Expected output -// Optimal rotation Euler angles are: 3.92784 ; 0.706802 ; 5.49658 -// Optimal rotation matrix is : -0.880467 ; 0.120094 ; -0.458645 -// : 0.119463 ; -0.879976 ; -0.459751 -// : -0.45881 ; -0.459587 ; 0.760443 +// Optimal rotation Euler angles are: 3.9268 ; 0.71992 ; 5.49648 +// Optimal rotation matrix is : -0.876066 ; 0.125383 ; -0.465604 +// : 0.122759 ; -0.87579 ; -0.466821 +// : -0.466302 ; -0.466124 ; 0.751858 //================================================ Delete the Patterson maps. They are no longer needed as we will now proceed with phased maps. delete staticStr; @@ -185,8 +185,8 @@ int main ( int argc, char **argv ) std::cout << "Rot. Centre to optimal overlay translation: " << optimalTranslation.at(0) << " ; " << optimalTranslation.at(1) << " ; " << optimalTranslation.at(2) << std::endl; //================================================ Expected output -// Rot. Centre to origin translation: 13.0909 ; 19.3846 ; 19.3846 -// Rot. Centre to optimal overlay translation: 12 ; 18 ; -6 +// Rot. Centre to origin translation: 12.7059 ; 16.8421 ; 16.7619 +// Rot. Centre to optimal overlay translation: 12 ; 20 ; -4 //================================================ Write out the output files movingStr->writeOutOverlayFiles ( settings, optimalEulerRot.at(0), optimalEulerRot.at(1), optimalEulerRot.at(2), &rotationCentre, &optimalTranslation ); diff --git a/proshade/examples/libproshade/advancedAccess_reboxing.cpp b/proshade/examples/libproshade/advancedAccess_reboxing.cpp index b8c40136..cf066f2c 100644 --- a/proshade/examples/libproshade/advancedAccess_reboxing.cpp +++ b/proshade/examples/libproshade/advancedAccess_reboxing.cpp @@ -18,8 +18,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/examples/libproshade/advancedAccess_symmetry.cpp b/proshade/examples/libproshade/advancedAccess_symmetry.cpp index caf71555..054f3750 100644 --- a/proshade/examples/libproshade/advancedAccess_symmetry.cpp +++ b/proshade/examples/libproshade/advancedAccess_symmetry.cpp @@ -19,8 +19,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -116,31 +116,28 @@ int main ( int argc, char **argv ) //================================================ Compute self-rotation function simpleSym->computeRotationFunction ( settings ); // This function computes the self-rotation function for the structure calling it. - //================================================ Prepare variables for results - std::vector< proshade_double* > recomSymAxes; - std::vector< std::vector< proshade_double > > allCSymAxes; - //================================================ Detect point groups in the angle-axis space - simpleSym->detectSymmetryFromAngleAxisSpace ( settings, &recomSymAxes, &allCSymAxes ); + simpleSym->detectSymmetryFromAngleAxisSpace ( settings ); //================================================ Access symmetry detection results - std::string symmetryType = simpleSym->getRecommendedSymmetryType ( settings ); // This is how the recommended symmetry type can be obtained. - proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( settings ); // This is how the recommended symmetry fold can be obtained. + std::string symmetryType = simpleSym->getRecommendedSymmetryType ( ); // This is how the recommended symmetry type can be obtained. + proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( ); // This is how the recommended symmetry fold can be obtained. + std::vector< proshade_double* > symAxes = simpleSym->getRecommendedSymmetryValues ( ); // This is how the recommended symmetry axes can be obtained. YOU ARE RESPONSIBLE FOR RELEASING THIS MEMORY, PROSHADE WILL NOT DO THIS FOR YOU. //================================================ Write out the symmetry detection results std::cout << "Detected symmetry: " << symmetryType << "-" << symmetryFold << " with axes:" << std::endl; - for ( proshade_unsign axIt = 0; axIt < static_cast ( recomSymAxes.size() ); axIt++ ) + for ( proshade_unsign axIt = 0; axIt < static_cast ( symAxes.size() ); axIt++ ) { - std::cout << "Symmetry axis number " << axIt << ": Fold " << recomSymAxes.at(axIt)[0] << " XYZ: " << recomSymAxes.at(axIt)[1] << " ; " << recomSymAxes.at(axIt)[2] << " ; " << recomSymAxes.at(axIt)[3] << " Angle (radians): " << recomSymAxes.at(axIt)[4] << " , axis peak: " << recomSymAxes.at(axIt)[5] << " and averaged FSC of " << recomSymAxes.at(axIt)[6] << std::endl; + std::cout << "Symmetry axis number " << axIt << ": Fold " << symAxes.at(axIt)[0] << " XYZ: " << symAxes.at(axIt)[1] << " ; " << symAxes.at(axIt)[2] << " ; " << symAxes.at(axIt)[3] << " Angle (radians): " << symAxes.at(axIt)[4] << " , axis peak: " << symAxes.at(axIt)[5] << " and averaged FSC of " << symAxes.at(axIt)[6] << std::endl; } //================================================ Expected output // Detected symmetry: D-6 with axes: -// Symmetry axis number 0: Fold 6 XYZ: 0 ; 0 ; 1 Angle (radians): 1.0472 , axis peak: 0.991699 and averaged FSC of 0.972365 -// Symmetry axis number 1: Fold 2 XYZ: 0.00688279 ; 0.999976 ; 6.12323e-17 Angle (radians): 3.14159 , axis peak: 1 and averaged FSC of 0.921126 +// Symmetry axis number 0: Fold 6 XYZ: 0 ; 0 ; 1 Angle (radians): 1.0472 , axis peak: 0.989191 and averaged FSC of 0.977248 +// Symmetry axis number 1: Fold 2 XYZ: 0.00602995 ; 0.999982 ; 6.12323e-17 Angle (radians): 3.14159 , axis peak: 0.995933 and averaged FSC of 0.941248 //================================================ Find all C axes - std::vector < std::vector< proshade_double > > allCs = settings->allDetectedCAxes; + std::vector< proshade_double* > allCs = simpleSym->getCyclicAxesCopy ( ); // This is how all the detected cyclic axes can be accessed. YOU ARE RESPONSIBLE FOR RELEASING THIS MEMORY, PROSHADE WILL NOT DO THIS FOR YOU. std::cout << "Found total of " << allCs.size() << " cyclic symmetry axes." << std::endl; //================================================ Expected output @@ -151,7 +148,11 @@ int main ( int argc, char **argv ) std::cout << "Internal map processing shifted the map COM by: [" << comMove.at(0) << " , " << comMove.at(1) << " , " << comMove.at(2) << "]." << std::endl; //================================================ Expected output -// Internal map processing shifted the map COM by: [4.40036 , 4.40876 , 2.70331]. +// Internal map processing shifted the map COM by: [2.50868 , 2.50839 , 0.801306]. + + //================================================ Release the symmetry memory + for ( size_t aIt = 0; aIt < allCs.size(); aIt++ ) { if ( allCs.at( aIt ) != nullptr ) { delete[] allCs.at( aIt ); allCs.at( aIt ) = nullptr; } } + for ( size_t aIt = 0; aIt < symAxes.size(); aIt++ ) { if ( symAxes.at( aIt ) != nullptr ) { delete[] symAxes.at( aIt ); symAxes.at( aIt ) = nullptr; } } //================================================ Release the object delete simpleSym; @@ -167,15 +168,15 @@ int main ( int argc, char **argv ) requestSym->computeRotationFunction ( settings ); //================================================ Prepare variables for results - std::vector< proshade_double* > reqSymAxes; - allCSymAxes.clear(); + allCs.clear(); //================================================ Detect point groups in the angle-axis space - requestSym->detectSymmetryFromAngleAxisSpace ( settings, &reqSymAxes, &allCSymAxes ); + requestSym->detectSymmetryFromAngleAxisSpace ( settings ); //================================================ Save results - symmetryType = requestSym->getRecommendedSymmetryType ( settings ); - symmetryFold = requestSym->getRecommendedSymmetryFold ( settings ); + symmetryType = requestSym->getRecommendedSymmetryType ( ); + symmetryFold = requestSym->getRecommendedSymmetryFold ( ); + std::vector< proshade_double* > reqSymAxes = requestSym->getRecommendedSymmetryValues ( ); // YOU ARE RESPONSIBLE FOR RELEASING THIS MEMORY, PROSHADE WILL NOT DO THIS FOR YOU. //================================================ Report the results for the requested symmetry if ( ( symmetryType == settings->requestedSymmetryType ) && ( symmetryFold == settings->requestedSymmetryFold ) ) @@ -183,7 +184,7 @@ int main ( int argc, char **argv ) std::cout << "Detected symmetry: " << symmetryType << "-" << symmetryFold << " as requested. The axes are:" << std::endl; for ( proshade_unsign axIt = 0; axIt < static_cast ( reqSymAxes.size() ); axIt++ ) { - std::cout << "Symmetry axis number " << axIt << ": Fold " << reqSymAxes.at(axIt)[0] << " XYZ: " << reqSymAxes.at(axIt)[1] << " ; " << reqSymAxes.at(axIt)[2] << " ; " << reqSymAxes.at(axIt)[3] << " Angle (radians): " << reqSymAxes.at(axIt)[4] << " and axis peak: " << reqSymAxes.at(axIt)[5] << std::endl; + std::cout << "Symmetry axis number " << axIt << ": Fold " << reqSymAxes.at(axIt)[0] << " XYZ: " << reqSymAxes.at(axIt)[1] << " ; " << reqSymAxes.at(axIt)[2] << " ; " << reqSymAxes.at(axIt)[3] << " Angle (radians): " << reqSymAxes.at(axIt)[4] << ", axis peak: " << reqSymAxes.at(axIt)[5] << " and averaged FSC of " << reqSymAxes.at(axIt)[6] << std::endl; } } else @@ -193,8 +194,8 @@ int main ( int argc, char **argv ) //================================================ Expected output // Detected symmetry: D-3 as requested. The axes are: -// Symmetry axis number 0: Fold 3 XYZ: 0 ; 0 ; 1 Angle (radians): 2.0944 and axis peak: 0.991521 -// Symmetry axis number 1: Fold 2 XYZ: 0.00688279 ; 0.999976 ; 6.12323e-17 Angle (radians): 3.14159 and axis peak: 1 +// Symmetry axis number 0: Fold 3 XYZ: 0 ; 0 ; 1 Angle (radians): 2.0944, axis peak: 0.989019 and averaged FSC of 0.971794 +// Symmetry axis number 1: Fold 2 XYZ: 0.00602995 ; 0.999982 ; 6.12323e-17 Angle (radians): 3.14159, axis peak: 0.995933 and averaged FSC of 0.941248 // NOTE: To get all the point group elements, one needs to supply the list of all cyclic point groups which comprise the @@ -214,23 +215,31 @@ int main ( int argc, char **argv ) // The only problem comes when D is to be used, as ProSHADE gives a vector of all combinations (also as vector) of cyclic point groups which form // D point groups. Therefore, to select the recommended D point group from this list, a search needs to be done. This is shown in the following code. + //================================================ Get a list of all detected C and D symmetries + allCs = requestSym->getCyclicAxesCopy ( ); // This is how all the detected cyclic axes can be accessed. YOU ARE RESPONSIBLE FOR RELEASING THIS MEMORY, PROSHADE WILL NOT DO THIS FOR YOU. + std::vector< std::vector< proshade_double* > > DSyms = requestSym->getDihedralAxesCopy ( ); // YOU ARE RESPONSIBLE FOR RELEASING THIS MEMORY, PROSHADE WILL NOT DO THIS FOR YOU. + //================================================ Find which D axes combination was reported as best std::vector< proshade_unsign > bestDAxesList; + size_t firstReq = 0, secondReq = 0; bool firstMatch = false; bool secondMatch = false; - for ( int dIt = 0; dIt < static_cast ( settings->allDetectedDAxes.size() ); dIt++ ) + for ( size_t dIt = 0; dIt < DSyms.size(); dIt++ ) { firstMatch = false; secondMatch = false; for ( proshade_unsign recIt = 0; recIt < static_cast ( reqSymAxes.size() ); recIt++ ) { - if ( ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(0))[1], reqSymAxes.at(recIt)[1] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(0))[2], reqSymAxes.at(recIt)[2] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(0))[3], reqSymAxes.at(recIt)[3] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(0))[4], reqSymAxes.at(recIt)[4] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(0))[5], reqSymAxes.at(recIt)[5] ) ) ) + if ( ( approxEqual ( DSyms.at(dIt).at(0)[0], reqSymAxes.at(recIt)[0] ) ) && + ( approxEqual ( DSyms.at(dIt).at(0)[1], reqSymAxes.at(recIt)[1] ) ) && + ( approxEqual ( DSyms.at(dIt).at(0)[2], reqSymAxes.at(recIt)[2] ) ) && + ( approxEqual ( DSyms.at(dIt).at(0)[3], reqSymAxes.at(recIt)[3] ) ) && + ( approxEqual ( DSyms.at(dIt).at(0)[4], reqSymAxes.at(recIt)[4] ) ) && + ( approxEqual ( DSyms.at(dIt).at(0)[5], reqSymAxes.at(recIt)[5] ) ) && + ( approxEqual ( DSyms.at(dIt).at(0)[6], reqSymAxes.at(recIt)[6] ) ) ) { firstMatch = true; + firstReq = recIt; } } @@ -238,28 +247,56 @@ int main ( int argc, char **argv ) { for ( proshade_unsign recIt = 0; recIt < static_cast ( reqSymAxes.size() ); recIt++ ) { - if ( ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(1))[1], reqSymAxes.at(recIt)[1] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(1))[2], reqSymAxes.at(recIt)[2] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(1))[3], reqSymAxes.at(recIt)[3] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(1))[4], reqSymAxes.at(recIt)[4] ) ) && - ( approxEqual ( allCSymAxes.at(settings->allDetectedDAxes.at(dIt).at(1))[5], reqSymAxes.at(recIt)[5] ) ) ) + if ( ( approxEqual ( DSyms.at(dIt).at(1)[0], reqSymAxes.at(recIt)[0] ) ) && + ( approxEqual ( DSyms.at(dIt).at(1)[1], reqSymAxes.at(recIt)[1] ) ) && + ( approxEqual ( DSyms.at(dIt).at(1)[2], reqSymAxes.at(recIt)[2] ) ) && + ( approxEqual ( DSyms.at(dIt).at(1)[3], reqSymAxes.at(recIt)[3] ) ) && + ( approxEqual ( DSyms.at(dIt).at(1)[4], reqSymAxes.at(recIt)[4] ) ) && + ( approxEqual ( DSyms.at(dIt).at(1)[5], reqSymAxes.at(recIt)[5] ) ) && + ( approxEqual ( DSyms.at(dIt).at(1)[6], reqSymAxes.at(recIt)[6] ) ) ) { - secondMatch = true; + secondMatch = true; + secondReq = recIt; } } } if ( ( firstMatch && secondMatch ) && ( bestDAxesList.size() == 0 ) ) { - bestDAxesList.emplace_back ( settings->allDetectedDAxes.at(dIt).at(0) ); - bestDAxesList.emplace_back ( settings->allDetectedDAxes.at(dIt).at(1) ); + for ( size_t aIt = 0; aIt < allCs.size(); aIt++ ) + { + if ( ( approxEqual ( allCs.at(aIt)[0], reqSymAxes.at(firstReq)[0] ) ) && + ( approxEqual ( allCs.at(aIt)[1], reqSymAxes.at(firstReq)[1] ) ) && + ( approxEqual ( allCs.at(aIt)[2], reqSymAxes.at(firstReq)[2] ) ) && + ( approxEqual ( allCs.at(aIt)[3], reqSymAxes.at(firstReq)[3] ) ) && + ( approxEqual ( allCs.at(aIt)[4], reqSymAxes.at(firstReq)[4] ) ) && + ( approxEqual ( allCs.at(aIt)[5], reqSymAxes.at(firstReq)[5] ) ) && + ( approxEqual ( allCs.at(aIt)[6], reqSymAxes.at(firstReq)[6] ) ) ) + { + bestDAxesList.emplace_back ( aIt ); + } + + if ( ( approxEqual ( allCs.at(aIt)[0], reqSymAxes.at(secondReq)[0] ) ) && + ( approxEqual ( allCs.at(aIt)[1], reqSymAxes.at(secondReq)[1] ) ) && + ( approxEqual ( allCs.at(aIt)[2], reqSymAxes.at(secondReq)[2] ) ) && + ( approxEqual ( allCs.at(aIt)[3], reqSymAxes.at(secondReq)[3] ) ) && + ( approxEqual ( allCs.at(aIt)[4], reqSymAxes.at(secondReq)[4] ) ) && + ( approxEqual ( allCs.at(aIt)[5], reqSymAxes.at(secondReq)[5] ) ) && + ( approxEqual ( allCs.at(aIt)[6], reqSymAxes.at(secondReq)[6] ) ) ) + { + bestDAxesList.emplace_back ( aIt ); + } + } } } - + + //================================================ Release the pointers + for ( size_t axIt = 0; axIt < DSyms.size(); axIt++ ) { if ( DSyms.at( axIt ).at(0) != nullptr ) { delete[] DSyms.at( axIt ).at(0); DSyms.at( axIt ).at(0) = nullptr; } if ( DSyms.at( axIt ).at(1) != nullptr ) { delete[] DSyms.at( axIt ).at(1); DSyms.at( axIt ).at(1) = nullptr; } } + //================================================ Get point group elements for the best D point group - std::vector > groupElements = simpleSym->getAllGroupElements ( settings, bestDAxesList, "D" ); + std::vector > groupElements = requestSym->getAllGroupElements ( bestDAxesList, "D" ); std::cout << "Found a total of " << groupElements.size() << " group elements." << std::endl; - + //================================================ Expected output // Found a total of 6 group elements. @@ -274,7 +311,11 @@ int main ( int argc, char **argv ) // -0.50 | +0.87 | +0.00 // -0.87 | -0.50 | +0.00 // +0.00 | +0.00 | +1.00 - + + //================================================ Release the symmetry memory + for ( size_t aIt = 0; aIt < reqSymAxes.size(); aIt++ ) { if ( reqSymAxes.at( aIt ) != nullptr ) { delete[] reqSymAxes.at( aIt ); reqSymAxes.at( aIt ) = nullptr; } } + for ( size_t aIt = 0; aIt < allCs.size(); aIt++ ) { if ( allCs.at( aIt ) != nullptr ) { delete[] allCs.at( aIt ); allCs.at( aIt ) = nullptr; } } + //================================================ Release the settings and runProshade objects delete requestSym; delete settings; diff --git a/proshade/examples/libproshade/proshadeBinary.cpp b/proshade/examples/libproshade/proshadeBinary.cpp index c01dc341..0c5f4bc3 100644 --- a/proshade/examples/libproshade/proshadeBinary.cpp +++ b/proshade/examples/libproshade/proshadeBinary.cpp @@ -15,8 +15,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/examples/libproshade/simpleAccess_distances.cpp b/proshade/examples/libproshade/simpleAccess_distances.cpp index 750013eb..bc38286a 100644 --- a/proshade/examples/libproshade/simpleAccess_distances.cpp +++ b/proshade/examples/libproshade/simpleAccess_distances.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -112,7 +112,7 @@ int main ( int argc, char **argv ) //================================================ Expected output // Energy levels distances : 0.85561 and 0.56064 // Trace sigma distances : 0.97777 and 0.63716 -// Rotation function distances : 0.59682 and 0.33717 +// Rotation function distances : 0.599 and 0.33717 //================================================ Release the settings and runProshade objects delete runProshade; diff --git a/proshade/examples/libproshade/simpleAccess_overlay.cpp b/proshade/examples/libproshade/simpleAccess_overlay.cpp index a698272b..7a86a285 100644 --- a/proshade/examples/libproshade/simpleAccess_overlay.cpp +++ b/proshade/examples/libproshade/simpleAccess_overlay.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -112,12 +112,12 @@ int main ( int argc, char **argv ) std::cout << "Rot. Centre to optimal overlay translation: " << originToOverlay.at(0) << " ; " << originToOverlay.at(1) << " ; " << originToOverlay.at(2) << std::endl; //================================================ Expected out is (except for the output files, which will be named overlayResuls.map and overlayResuls.pdb) -// Optimal rotation Euler angles are: 3.92784 ; 0.706802 ; 5.49658 -// Optimal rotation matrix is : -0.880467 ; 0.120094 ; -0.458645 -// : 0.119463 ; -0.879976 ; -0.459751 -// : -0.45881 ; -0.459587 ; 0.760443 -// Rot. Centre to origin translation: -13.0909 ; -19.3846 ; -19.3846 -// Rot. Centre to optimal overlay translation: 12 ; 18 ; -6 +// Optimal rotation Euler angles are: 3.9268 ; 0.71992 ; 5.49648 +// Optimal rotation matrix is : -0.876066 ; 0.125383 ; -0.465604 +// : 0.122759 ; -0.87579 ; -0.466821 +// : -0.466302 ; -0.466124 ; 0.751858 +// Rot. Centre to origin translation: -12.7059 ; -16.8421 ; -16.7619 +// Rot. Centre to optimal overlay translation: 12 ; 20 ; -4 //================================================ DONE return ( EXIT_SUCCESS ); diff --git a/proshade/examples/libproshade/simpleAccess_reboxing.cpp b/proshade/examples/libproshade/simpleAccess_reboxing.cpp index b2eee1f8..37a85e0a 100644 --- a/proshade/examples/libproshade/simpleAccess_reboxing.cpp +++ b/proshade/examples/libproshade/simpleAccess_reboxing.cpp @@ -17,8 +17,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE diff --git a/proshade/examples/libproshade/simpleAccess_symmetry.cpp b/proshade/examples/libproshade/simpleAccess_symmetry.cpp index 8555740f..6172e517 100644 --- a/proshade/examples/libproshade/simpleAccess_symmetry.cpp +++ b/proshade/examples/libproshade/simpleAccess_symmetry.cpp @@ -16,8 +16,8 @@ \author Michal Tykac \author Garib N. Murshudov - \version 0.7.6.5 - \date JUN 2022 + \version 0.7.6.6 + \date JUL 2022 */ //==================================================== ProSHADE @@ -106,21 +106,21 @@ int main ( int argc, char **argv ) //================================================ Expected output // Detected symmetry C of fold 12. The symmetry axes are: -// ... FOLD: 12 | XYZ: 0 ; 0 ; 1 | Angle: 0.523599 | Peak: 0.994557 | Average FSC: 0.992264 +// ... FOLD: 12 | XYZ: 0 ; 0 ; 1 | Angle: 0.523599 | Peak: 0.996047 | Average FSC: 0.992328 //================================================ Get list of all detected cyclic symmetries std::vector < std::vector< proshade_double > > allCs = runProshade->getAllCSyms ( ); std::cout << "Found a total of " << allCs.size() << " cyclic symmetries." << std::endl; //================================================ Expected output -// Found a total of 22 cyclic symmetries. +// Found a total of 5 cyclic symmetries. //================================================ Find the internal map processing COM shift std::vector< proshade_double > comMove = runProshade->getMapCOMProcessChange ( ); std::cout << "Internal map processing shifted the map COM by: [" << comMove.at(0) << " , " << comMove.at(1) << " , " << comMove.at(2) << "]." << std::endl; //================================================ Expected output -// Internal map processing shifted the map COM by: [-0.0347284 , -0.0296968 , 13.0487]. +// Internal map processing shifted the map COM by: [-0.00527658 , -0.00468209 , 11.8497]. //================================================ Release the settings and runProshade objects delete runProshade; diff --git a/proshade/examples/python/advancedAccess_distances.py b/proshade/examples/python/advancedAccess_distances.py index a1c7c916..7a55ef26 100644 --- a/proshade/examples/python/advancedAccess_distances.py +++ b/proshade/examples/python/advancedAccess_distances.py @@ -19,8 +19,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -85,7 +85,7 @@ ### Expected output # The energy levels distance is +0.852 # The trace sigma distance is +0.911 -# The rotation function distance is +0.616 +# The rotation function distance is +0.620 ###################################################### ### Release C++ pointers diff --git a/proshade/examples/python/advancedAccess_overlay.py b/proshade/examples/python/advancedAccess_overlay.py index 4dc3ce30..22e71270 100644 --- a/proshade/examples/python/advancedAccess_overlay.py +++ b/proshade/examples/python/advancedAccess_overlay.py @@ -21,8 +21,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -154,12 +154,12 @@ ###################################################### ### Expected output -# Optimal Euler angles : +3.890 +0.748 +5.461 -# Optimal Euler rotation matrix : -0.864 +0.197 -0.463 -# : +0.070 -0.864 -0.498 -# : -0.498 -0.463 +0.733 -# Rot. centre to origin translation : +18.857 +18.783 +21.840 -# Rot. centre to overlay translation : +3.000 +12.000 -3.000 +# Optimal Euler angles : +3.927 +0.753 +5.433 +# Optimal Euler rotation matrix : -0.872 +0.191 -0.451 +# : +0.079 -0.854 -0.514 +# : -0.483 -0.483 +0.730 +# Rot. centre to origin translation : +18.545 +20.541 +20.513 +# Rot. centre to overlay translation : +2.000 +8.000 -4.000 ###################################################### diff --git a/proshade/examples/python/advancedAccess_reBox.py b/proshade/examples/python/advancedAccess_reBox.py index 7a9801dc..877e0b42 100644 --- a/proshade/examples/python/advancedAccess_reBox.py +++ b/proshade/examples/python/advancedAccess_reBox.py @@ -21,8 +21,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### diff --git a/proshade/examples/python/advancedAccess_symmetry.py b/proshade/examples/python/advancedAccess_symmetry.py index f3a56ab7..6bf7d6c2 100644 --- a/proshade/examples/python/advancedAccess_symmetry.py +++ b/proshade/examples/python/advancedAccess_symmetry.py @@ -19,8 +19,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -76,9 +76,9 @@ ###################################################### ### Retrieve the results -recSymmetryType = pStruct.getRecommendedSymmetryType ( pSet ) -recSymmetryFold = pStruct.getRecommendedSymmetryFold ( pSet ) -recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( pSet ) +recSymmetryType = pStruct.getRecommendedSymmetryType ( ) +recSymmetryFold = pStruct.getRecommendedSymmetryFold ( ) +recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( ) ###################################################### ### Print results @@ -97,12 +97,12 @@ ### Expected output # Detected D-6 symetry. # Fold x y z Angle Height Average FSC -# 6.0 +0.000 +0.000 +1.000 +1.047 +0.9795 +0.9726 -# 2.0 +0.006 +1.000 +0.000 +3.142 +1.0000 +0.9201 +# 6.0 +0.000 +0.000 +1.000 +1.047 +0.9918 +0.9776 +# 2.0 +0.005 +1.000 +0.000 +3.142 +1.0000 +0.9347 ###################################################### ### Get list of all cyclic axes detected -allCAxes = pStruct.getAllCSyms ( pSet ) +allCAxes = pStruct.getAllCSyms ( ) print ( "Found a total of " + str( len ( allCAxes ) ) + " cyclic point groups." ) ###################################################### @@ -111,8 +111,8 @@ ###################################################### ### Get indices of which C axes form any detected non-C symmetry -allNonCAxesIndices = pStruct.getNonCSymmetryAxesIndices ( pSet ) -print ( "Found a total of " + str( len ( allNonCAxesIndices["D"] ) ) + " dihedral point groups." ) +allNonCAxes = pStruct.getNonCSymmetryAxesIndices ( ) +print ( "Found a total of " + str( len ( allNonCAxes["D"] ) ) + " dihedral point groups." ) ###################################################### ### Expected output @@ -125,16 +125,16 @@ ###################################################### ### Expected output -# The internal map has been shifted by 3.264023 , 3.2652297 , 1.5624605 +# The internal map has been shifted by 0.24491179 , 0.2442931 , -1.4583219 ###################################################### # NOTE: To get all the point group elements, one needs to supply the list of all cyclic point groups which comprise the # requested point group. This is relatively simple for T, O and I symmetries, as such a list is already produced by # ProSHADE - see the following examples: # -# allGroupElements = proshade.getAllGroupElements ( pSet, pStruct, allNonCAxesIndices['T'], "T" ) -# allGroupElements = proshade.getAllGroupElements ( pSet, pStruct, allNonCAxesIndices['O'], "O" ) -# allGroupElements = proshade.getAllGroupElements ( pSet, pStruct, allNonCAxesIndices['I'], "I" ) +# allGroupElements = proshade.getAllGroupElements ( pSet, pStruct, allNonCAxes['T'], "T" ) +# allGroupElements = proshade.getAllGroupElements ( pSet, pStruct, allNonCAxes['O'], "O" ) +# allGroupElements = proshade.getAllGroupElements ( pSet, pStruct, allNonCAxes['I'], "I" ) # # For cyclic point groups, this is also simple, as one can select the required >index< from the allCs variable and use # NOTE: The [] around index is required, as the function expects an array (list) and not an int! @@ -156,32 +156,51 @@ def isclose ( a, b, tol = 1e-04 ): ###################################################### ### Find the indices of the best dihedral combination bestDCombination = [] -for dIt in range ( 0, len ( allNonCAxesIndices['D'] ) ): +bestDCombinationHlp = [] +for dIt in range ( 0, len ( allNonCAxes['D'] ) ): + firstMatch = False secondMatch = False + for recIt in range ( 0, len( recSymmetryAxes ) ): - if ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][0]][1], recSymmetryAxes[0][1] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][0]][2], recSymmetryAxes[0][2] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][0]][3], recSymmetryAxes[0][3] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][0]][4], recSymmetryAxes[0][4] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][0]][5], recSymmetryAxes[0][5] ) ): + if ( isclose ( allNonCAxes['D'][dIt][0][0], recSymmetryAxes[0][0] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][0][1], recSymmetryAxes[0][1] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][0][2], recSymmetryAxes[0][2] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][0][3], recSymmetryAxes[0][3] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][0][4], recSymmetryAxes[0][4] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][0][5], recSymmetryAxes[0][5] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][0][6], recSymmetryAxes[0][6] ) ): firstMatch = True - - if ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][1]][1], recSymmetryAxes[1][1] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][1]][2], recSymmetryAxes[1][2] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][1]][3], recSymmetryAxes[1][3] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][1]][4], recSymmetryAxes[1][4] ) ) and \ - ( isclose ( allCAxes[allNonCAxesIndices['D'][dIt][1]][5], recSymmetryAxes[1][5] ) ): + + if ( isclose ( allNonCAxes['D'][dIt][1][0], recSymmetryAxes[1][0] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][1][1], recSymmetryAxes[1][1] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][1][2], recSymmetryAxes[1][2] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][1][3], recSymmetryAxes[1][3] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][1][4], recSymmetryAxes[1][4] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][1][5], recSymmetryAxes[1][5] ) ) and \ + ( isclose ( allNonCAxes['D'][dIt][1][6], recSymmetryAxes[1][6] ) ): secondMatch = True - + if (firstMatch and secondMatch) and (len(bestDCombination)==0): - bestDCombination.append ( allNonCAxesIndices['D'][dIt][0] ) - bestDCombination.append ( allNonCAxesIndices['D'][dIt][1] ) + bestDCombinationHlp.append ( allNonCAxes['D'][dIt][0] ) + bestDCombinationHlp.append ( allNonCAxes['D'][dIt][1] ) + +for DSwitch in range ( 0, 2 ): + for cIt in range ( 0, len ( allCAxes ) ): + if ( isclose ( bestDCombinationHlp[DSwitch][0], allCAxes[cIt][0] ) ) and \ + ( isclose ( bestDCombinationHlp[DSwitch][1], allCAxes[cIt][1] ) ) and \ + ( isclose ( bestDCombinationHlp[DSwitch][2], allCAxes[cIt][2] ) ) and \ + ( isclose ( bestDCombinationHlp[DSwitch][3], allCAxes[cIt][3] ) ) and \ + ( isclose ( bestDCombinationHlp[DSwitch][4], allCAxes[cIt][4] ) ) and \ + ( isclose ( bestDCombinationHlp[DSwitch][5], allCAxes[cIt][5] ) ) and \ + ( isclose ( bestDCombinationHlp[DSwitch][6], allCAxes[cIt][6] ) ): + bestDCombination.append ( cIt ) + ###################################################### ### Get the group elements for the best dihedral group -allGroupElements = pStruct.getAllGroupElements ( pSet, bestDCombination, "D" ) +allGroupElements = pStruct.getAllGroupElements ( bestDCombination, "D" ) ###################################################### ### Print the first non-identity element @@ -195,9 +214,9 @@ def isclose ( a, b, tol = 1e-04 ): ### Expected output # Found a total of 12 group [1, 3] elements. # The first non-identity element is: -# +0.500 +0.866 +0.000 -# -0.866 +0.500 +0.000 -# +0.000 +0.000 +1.000 +# +0.500 +0.866 +0.000 +# -0.866 +0.500 +0.000 +# +0.000 +0.000 +1.000 ###################################################### ### Assuming you have modifiex / created your own C groups diff --git a/proshade/examples/python/directAccess.py b/proshade/examples/python/directAccess.py index 49f8bd06..fc011a10 100644 --- a/proshade/examples/python/directAccess.py +++ b/proshade/examples/python/directAccess.py @@ -34,8 +34,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -609,7 +609,7 @@ Band4OrderOneMin2OrderTwo3EMatrixValue = eMat[4][2][7] # Band = 4, Order1 = -2 and Order2 = 3 print ( Band4OrderOneMin2OrderTwo3EMatrixValue ) -# Expected output: (9.420746147584e-12-1.3175153955845695e-10j) +# Expected output: (-2.581088525336602e-11-2.1131647889196217e-11j) ###################################################### ### Accessing SO(3) coefficients @@ -641,7 +641,7 @@ Band4OrderOneMin2OrderTwo3SO3CoeffsValue = so3Coeffs[4][2][7] # Band = 4, Order1 = -2 and Order2 = 3 print ( Band4OrderOneMin2OrderTwo3SO3CoeffsValue ) -# Expected output: (-2.7903514882548074e-11+3.902377781202436e-10j) +# Expected output: (7.64498278072955e-11+6.259029190805342e-11j) ###################################################### ### Accessing self-rotation function @@ -666,15 +666,15 @@ ### Find maximum value print ( "Rotation map maximum is: " + str( selfRotationFunction[rotMapMax[0][0]][rotMapMax[1][0]][rotMapMax[2][0]] ) ) -### Expected output: Rotation map maximum is: (0.9968216589292499+1.2456859553989e-17j) +### Expected output: Rotation map maximum is: (0.9972513939198606+4.8181172914305494e-17j) ### Find rotation matrix for the maximum rotMatMaxVal = pStruct.getRotationMatrixFromSOFTCoordinates ( rotMapMax[0][0], rotMapMax[1][0], rotMapMax[2][0] ) print ( rotMatMaxVal ) -# Expected output: [[ 1.0000000e+00 -2.4459601e-16 -0.0000000e+00] -# Expected output: [ 2.4459601e-16 1.0000000e+00 0.0000000e+00] -# Expected output: [ 0.0000000e+00 -0.0000000e+00 1.0000000e+00]] +# Expected output: [[-1.00000000e+00 -1.00613962e-16 -0.00000000e+00] +# Expected output: [ 1.00613962e-16 -1.00000000e+00 0.00000000e+00] +# Expected output: [-0.00000000e+00 0.00000000e+00 1.00000000e+00]] ###################################################### ### Run symmetry detection @@ -694,9 +694,9 @@ pStruct.detectSymmetryInStructure ( pSet ) ### Retrieve results -recSymmetryType = pStruct.getRecommendedSymmetryType ( pSet ) -recSymmetryFold = pStruct.getRecommendedSymmetryFold ( pSet ) -recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( pSet ) +recSymmetryType = pStruct.getRecommendedSymmetryType ( ) +recSymmetryFold = pStruct.getRecommendedSymmetryFold ( ) +recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( ) ### Print results print ( "Detected " + str( recSymmetryType ) + "-" + str( recSymmetryFold ) + " symetry." ) @@ -709,8 +709,8 @@ print ( " %s %+1.3f %+1.3f %+1.3f %+1.3f %+1.4f %+1.4f" % ( recSymmetryAxes[iter][0], recSymmetryAxes[iter][1], recSymmetryAxes[iter][2], recSymmetryAxes[iter][3], recSymmetryAxes[iter][4], recSymmetryAxes[iter][5], recSymmetryAxes[iter][6] ) ) # Expected output: Fold x y z Angle Height Average FSC -# Expected output: 3.0 +0.000 +0.000 +1.000 +2.094 +0.9791 +0.9729 -# Expected output: 2.0 +0.005 +1.000 +0.000 +3.142 +1.0000 +0.9158 +# Expected output: 3.0 +0.000 +0.000 +1.000 +2.094 +0.9935 +0.9725 +# Expected output: 2.0 +0.005 +1.000 +0.000 +3.142 +1.0000 +0.9141 ###################################################### ### Get more symmetry results @@ -729,22 +729,22 @@ ### ### Get list of all cyclic point groups -allCAxes = pStruct.getAllCSyms ( pSet ) +allCAxes = pStruct.getAllCSyms ( ) print ( "Found a total of " + str( len ( allCAxes ) ) + " cyclic point groups." ) # Expected output: Found a total of 9 cyclic point groups. ### Get a list of all non-cyclic point groups detected and indices of the cyclic groups forming them -allNonCAxesIndices = pStruct.getNonCSymmetryAxesIndices ( pSet ) +allNonCAxesIndices = pStruct.getNonCSymmetryAxesIndices ( ) print ( "Found a total of " + str( len ( allNonCAxesIndices["D"] ) ) + " dihedral point groups." ) # Expected output: Found a total of 21 dihedral point groups. ### Get group elements for the best dihedral symmetry (indices 2 and 26) bestDCombination = [] -bestDCombination.append ( allNonCAxesIndices["D"][12][0] ) -bestDCombination.append ( allNonCAxesIndices["D"][12][1] ) -allGroupElements = pStruct.getAllGroupElements ( pSet, bestDCombination, "D" ) +bestDCombination.append ( 2 ) +bestDCombination.append ( 5 ) +allGroupElements = pStruct.getAllGroupElements ( bestDCombination, "D" ) print ( "Found a total of " + str( len ( allGroupElements ) ) + " elements." ) # Found a total of 6 elements. @@ -897,13 +897,13 @@ Band4OrderOneMin2OrderTwo3EMatrixValue = eMat[4][2][7] # Band = 4, Order1 = -2 and Order2 = 3 print ( Band4OrderOneMin2OrderTwo3EMatrixValue ) -# Expected output: (0.001037857266646908-0.002938145399903594j) +# Expected output: (0.00028359312882706236-0.00396898791633267j) so3Coeffs = pStruct_moving.getSO3Coefficients ( ) Band4OrderOneMin2OrderTwo3SO3CoeffsValue = so3Coeffs[4][2][7] # Band = 4, Order1 = -2 and Order2 = 3 print ( Band4OrderOneMin2OrderTwo3SO3CoeffsValue ) -# Expected output: (-0.003074052228152817+0.008702557378040111j) +# Expected output: (-0.0008399807156298019+0.011755832463487428j) ###################################################### ### Acceasing rotation function and etc. @@ -930,15 +930,15 @@ ### Find maximum value print ( "Rotation map maximum is: " + str( rotationFunction[rotMapMax[0][0]][rotMapMax[1][0]][rotMapMax[2][0]] ) ) -### Expected output: Rotation map maximum is: (0.965989577718074+1.534533665701149e-17j) +### Expected output: Rotation map maximum is: (0.9592313161286188+0j) ### Find rotation matrix for the maximum rotMatMaxVal = pStruct_moving.getRotationMatrixFromSOFTCoordinates ( rotMapMax[0][0], rotMapMax[1][0], rotMapMax[2][0] ) print ( rotMatMaxVal ) -# Expected output: [[-0.88020298 0.11979702 -0.45922912] -# Expected output: [ 0.11979702 -0.88020298 -0.45922912] -# Expected output: [-0.45922912 -0.45922912 0.76040597]] +# Expected output: [[-0.8759199 0.1240801 -0.4662279 ] +# Expected output: [ 0.1240801 -0.8759199 -0.4662279 ] +# Expected output: [-0.4662279 -0.4662279 0.75183981]] ###################################################### ### Finding optimal rotation @@ -956,9 +956,9 @@ optimalRotationMatrix = pStruct_moving.getBestRotationMapPeaksRotationMatrix ( pSet ) print ( optimalRotationMatrix ) -# Expected output: [[-0.88041782 0.11956812 -0.45887682] -# Expected output: [ 0.12002093 -0.8799927 -0.45957352] -# Expected output: [-0.45875859 -0.45969154 0.76041058]] +# Expected output: [[-0.87606511 0.12513834 -0.4656719 ] +# Expected output: [ 0.12299418 -0.87580092 -0.46673887] +# Expected output: [-0.46624281 -0.46616857 0.75186735]] ###################################################### ### Delete the phase-less data @@ -1037,7 +1037,7 @@ ### pStruct_moving.rotateMapRealSpaceInPlace ( optimalRotationAngles[0], optimalRotationAngles[1], optimalRotationAngles[2] ) -# Expected output: [13.090909957885742, 19.384613037109375, 19.384613037109375] +# Expected output: [12.705883026123047, 16.842103958129883, 16.761905670166016] ###################################################### ### Zero padd the maps @@ -1096,7 +1096,7 @@ ### Find maximum value print ( "Translation map maximum is: " + str( translationFunction[rotMapMax[0][0]][rotMapMax[1][0]][rotMapMax[2][0]] ) ) -### Expected output: Translation map maximum is: (6.426196189545484+0j) +### Expected output: Translation map maximum is: (27.43836352639635-7.611834130769223e-17j) ###################################################### ### Obtaining the optimal translation @@ -1130,8 +1130,8 @@ print ( "The centre of rotation to optimal overlay translation is: " + str( translationVecs["rotCenToOverlay"][0] ) + " ; " + str( translationVecs["rotCenToOverlay"][1] ) + " ; " + str( translationVecs["rotCenToOverlay"][2] ) ) ### Expected output -# The centre of rotation is: -13.090909957885742 ; -19.384613037109375 ; -19.384613037109375 -# The centre of rotation to optimal overlay translation is: 12.0 ; 18.0 ; -6.0 +# The centre of rotation is: -12.705883026123047 ; -16.842103958129883 ; -16.761905670166016 +# The centre of rotation to optimal overlay translation is: 12.0 ; 20.0 ; -4.0 ###################################################### ### Writing out the final structures diff --git a/proshade/examples/python/howto_accessInterimResults.py b/proshade/examples/python/howto_accessInterimResults.py index 07b2a60d..5b279521 100644 --- a/proshade/examples/python/howto_accessInterimResults.py +++ b/proshade/examples/python/howto_accessInterimResults.py @@ -28,8 +28,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -119,7 +119,7 @@ order = -2 Shell3Band4OrderMin2Value = sphericalHarmonics[shell][pStruct.findSHIndex(shell, band, order)] print ( Shell3Band4OrderMin2Value ) -# Expected output: (-235.24818424993876+47.16991316171293j) +# Expected output: (-127.77624547146776+25.628635834474466j) ###################################################### ### Computing self-rotation function @@ -164,7 +164,7 @@ Band4OrderOneMin2OrderTwo3EMatrixValue = eMat[4][2][7] # Band = 4, Order1 = -2 and Order2 = 3 print ( Band4OrderOneMin2OrderTwo3EMatrixValue ) -# Expected output: (1.6559145729437165e-06+7.758352155718928e-07j) +# Expected output: (6.779507998412581e-07+1.1580647039238433e-06j) ###################################################### ### Accessing SO(3) coefficients @@ -191,7 +191,7 @@ Band4OrderOneMin2OrderTwo3SO3CoeffsValue = so3Coeffs[4][2][7] # Band = 4, Order1 = -2 and Order2 = 3 print ( Band4OrderOneMin2OrderTwo3SO3CoeffsValue ) -# Expected output: (-4.904689735452957e-06-2.297963361391187e-06j) +# Expected output: (-2.0080373610170287e-06-3.430097276231109e-06j) ###################################################### ### Accessing self-rotation function @@ -216,15 +216,15 @@ ### Find maximum value print ( "Rotation map maximum is: " + str( selfRotationFunction[rotMapMax[0][0]][rotMapMax[1][0]][rotMapMax[2][0]] ) ) -### Expected output: Rotation map maximum is: (0.9944907463315484+1.325608478502007e-17j) +### Expected output: Rotation map maximum is: (0.9923989120515847-3.989699808661867e-17j) ### Find rotation matrix for the maximum (uses only the real parts, using magnitudes would be better) rotMatMaxVal = pStruct.getRotationMatrixFromSOFTCoordinates ( rotMapMax[0][0], rotMapMax[1][0], rotMapMax[2][0] ) print ( rotMatMaxVal ) -### Expected output: [[ 1.00000000e+00 2.01227923e-16 0.00000000e+00] -### Expected output: [-2.01227923e-16 1.00000000e+00 -0.00000000e+00] -### Expected output: [-0.00000000e+00 0.00000000e+00 1.00000000e+00]] +### Expected output: [[ 1.00000000e+00 6.41847686e-16 0.00000000e+00] +### Expected output: [-6.41847686e-16 1.00000000e+00 0.00000000e+00] +### Expected output: [-0.00000000e+00 -0.00000000e+00 1.00000000e+00]] ###################################################### ### Release ProSHADE memory diff --git a/proshade/examples/python/howto_passProcessedMap.py b/proshade/examples/python/howto_passProcessedMap.py index 7fadbe48..fac87593 100644 --- a/proshade/examples/python/howto_passProcessedMap.py +++ b/proshade/examples/python/howto_passProcessedMap.py @@ -22,8 +22,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -126,10 +126,10 @@ ###################################################### ### Retrieve results -recSymmetryType = pStruct.getRecommendedSymmetryType ( pSet ) -recSymmetryFold = pStruct.getRecommendedSymmetryFold ( pSet ) -recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( pSet ) -allCAxes = pStruct.getAllCSyms ( pSet ) +recSymmetryType = pStruct.getRecommendedSymmetryType ( ) +recSymmetryFold = pStruct.getRecommendedSymmetryFold ( ) +recSymmetryAxes = pStruct.getRecommendedSymmetryAxes ( ) +allCAxes = pStruct.getAllCSyms ( ) ###################################################### ### Print results @@ -146,16 +146,16 @@ ### EXPECTED OUTPUT: Recommended symmetry: ### EXPECTED OUTPUT: D3 -### EXPECTED OUTPUT: +### EXPECTED OUTPUT: ### EXPECTED OUTPUT: Recommended axes: -### EXPECTED OUTPUT: 3.0 | 0.9999329 x -0.011586841 x -6.123234e-17 || 0.9128239 -### EXPECTED OUTPUT: 2.0 | 0.0008414974 x -9.441583e-07 x 0.99999964 || 0.9980464 -### EXPECTED OUTPUT: +### EXPECTED OUTPUT: 3.0 | 0.9999328 x -0.011591071 x -6.123234e-17 || 0.9127528 +### EXPECTED OUTPUT: 2.0 | 0.0007012483 x 0.0 x 0.99999976 || 0.998042 +### EXPECTED OUTPUT: ### EXPECTED OUTPUT: All axes: -### EXPECTED OUTPUT: 2.0 | 0.0008414974 x -9.441583e-07 x 0.99999964 || 0.9980464 -### EXPECTED OUTPUT: 3.0 | 0.9999329 x -0.011586841 x -6.123234e-17 || 0.9128239 -### EXPECTED OUTPUT: 2.0 | 0.00974076 x 0.8641076 x 0.50321287 || 0.9079414 -### EXPECTED OUTPUT: 2.0 | 0.009739787 x 0.8641073 x -0.50321335 || 0.9079347 +### EXPECTED OUTPUT: 2.0 | 0.0007012483 x 0.0 x 0.99999976 || 0.998042 +### EXPECTED OUTPUT: 3.0 | 0.9999328 x -0.011591071 x -6.123234e-17 || 0.9127528 +### EXPECTED OUTPUT: 2.0 | 0.009986875 x 0.8641762 x -0.5030902 || 0.90472996 +### EXPECTED OUTPUT: 2.0 | 0.009988657 x 0.8641767 x 0.5030893 || 0.9047275 ###################################################### ### Release ProSHADE memory diff --git a/proshade/examples/python/simpleAccess_distances.py b/proshade/examples/python/simpleAccess_distances.py index 383e7ce2..f9ec4c1b 100644 --- a/proshade/examples/python/simpleAccess_distances.py +++ b/proshade/examples/python/simpleAccess_distances.py @@ -19,8 +19,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -120,7 +120,7 @@ ### Expected output # Energy levels distance : 0.8556063 0.5606434 # Trace sigma distance : 0.977767 0.63715816 -# Full rotation function distance : 0.5968159 0.3371659 +# Full rotation function distance : 0.59899515 0.3371659 ###################################################### ### Release memory diff --git a/proshade/examples/python/simpleAccess_overlay.py b/proshade/examples/python/simpleAccess_overlay.py index 602d03fe..f0f9d564 100644 --- a/proshade/examples/python/simpleAccess_overlay.py +++ b/proshade/examples/python/simpleAccess_overlay.py @@ -20,8 +20,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -121,12 +121,12 @@ ###################################################### ### Expected outuput -# Optimal rotation Euler angles : 3.8903248 0.7479983 5.4608274 -# Optimal rotation matrix : -0.8642176 0.19721524 -0.46285436 -# : 0.06973293 -0.86413914 -0.4983983 -# : -0.4982623 -0.46300077 0.73305184 -# Translation to origin : -18.857141 -18.782608 -21.839998 -# Translation to overlay : 3.0 12.0 -3.0 +# Optimal rotation Euler angles : 3.9270046 0.75265783 5.432715 +# Optimal rotation matrix : -0.871892 0.19100872 -0.4509103 +# : 0.07854472 -0.85432297 -0.51377326 +# : -0.4833582 -0.4833714 0.7298746 +# Translation to origin : -18.545456 -20.54054 -20.512821 +# Translation to overlay : 2.0 8.0 -4.0 ###################################################### ### Release memory diff --git a/proshade/examples/python/simpleAccess_reBox.py b/proshade/examples/python/simpleAccess_reBox.py index ed920794..1c69de06 100644 --- a/proshade/examples/python/simpleAccess_reBox.py +++ b/proshade/examples/python/simpleAccess_reBox.py @@ -19,8 +19,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### diff --git a/proshade/examples/python/simpleAccess_symmetry.py b/proshade/examples/python/simpleAccess_symmetry.py index 39e9809c..411b816c 100644 --- a/proshade/examples/python/simpleAccess_symmetry.py +++ b/proshade/examples/python/simpleAccess_symmetry.py @@ -18,8 +18,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### @@ -114,7 +114,7 @@ ############################################## ### Expected output -# Found a total of 13 cyclic symmetries. +# Found a total of 4 cyclic symmetries. ###################################################### ### Print results @@ -130,9 +130,9 @@ ###################################################### ### Expected outuput -# Detected symmetry C-4 with axes: +# Detected symmetry C-4 with axes: # Fold x y z Angle Height Averaged FSC -# 4.0 +0.000 +0.000 +1.000 +1.571 +0.9689 +0.9985 +# 4.0 +0.000 +0.000 +1.000 +1.571 +0.9956 +0.9975 ###################################################### ### Find the internal map COM shift @@ -141,7 +141,7 @@ ###################################################### ### Expected outuput -# Internal map COM shift: 0.0 , 0.0 , 0.0 +# Internal map COM shift: 0.0 , 0.0 , 0.6972794 ###################################################### ### Release memory diff --git a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py index 8fd4cb8e..00317cf8 100644 --- a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py +++ b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py @@ -95,7 +95,7 @@ ### no user manipulation is required. ### -startFrom = 20 +startFrom = 359 resolutionFilename = resolution outResCondensed = 0 outResAxes = 0 diff --git a/proshade/src/proshade/ProSHADE.cpp b/proshade/src/proshade/ProSHADE.cpp index 87868023..62b51175 100644 --- a/proshade/src/proshade/ProSHADE.cpp +++ b/proshade/src/proshade/ProSHADE.cpp @@ -1917,7 +1917,8 @@ __declspec(dllexport) ProSHADE_run::ProSHADE_run ( ProSHADE_settings* settings ) throw ProSHADE_exception ( "No task has been specified.", "E000001", __FILE__, __LINE__, __func__, "ProSHADE requires to be told which particular functiona-\n : lity (task) is requested from it. In order to do so, the\n : command line arguments specifying task need to be used\n : (if used from command line), or the ProSHADE_settings\n : object needs to have the member variable \'Task\' set to\n : one of the following values: Distances, Symmetry,\n : OverlayMap or MapManip." ); case Symmetry: - ProSHADE_internal_tasks::SymmetryDetectionTask ( settings, &this->mapCOMShift ); + ProSHADE_internal_tasks::SymmetryDetectionTask ( settings, &this->mapCOMShift, &this->symRecommType, &this->symRecommFold, &this->RecomSymAxes, &this->allCSymAxes ); + break; case Distances: @@ -2010,7 +2011,7 @@ __declspec(dllexport) ProSHADE_run::~ProSHADE_run ( ) //================================================ Delete symmetry axes memory if ( this->RecomSymAxes.size() > 0 ) { - for ( proshade_unsign iter = 0; iter < static_cast ( this->RecomSymAxes.size() ); iter++ ) + for ( size_t iter = 0; iter < this->RecomSymAxes.size(); iter++ ) { delete[] this->RecomSymAxes.at(iter); } diff --git a/proshade/src/proshade/ProSHADE.hpp b/proshade/src/proshade/ProSHADE.hpp index ea4e30ad..842c973c 100644 --- a/proshade/src/proshade/ProSHADE.hpp +++ b/proshade/src/proshade/ProSHADE.hpp @@ -47,10 +47,6 @@ class ProSHADE_run std::vector < proshade_double > trSigm; //!< Vector holding trace sigma distances from the first to all other supplied structures. std::vector < proshade_double > rotFun; //!< Vector holding full rotation function distances from the first to all other supplied structures. - //================================================ Variables regarding symmetry detection - std::vector< proshade_double* > RecomSymAxes; //!< Vector holding the recommended symmetry axes information. - std::vector < std::vector< proshade_double > > allCSymAxes; //!< Vector holding all detected cyclic symmetry axes information. - //================================================ Variables regarding re-boxing task std::vector < proshade_signed* > originalBounds; //!< Original boundaries of the map. std::vector < proshade_signed* > reboxedBounds; //!< Re-boxed boundaries of the map. @@ -64,6 +60,8 @@ class ProSHADE_run //================================================ Variables regarding symmetry detection std::string symRecommType; //!< The resulting recommended symmetry type for the symmetry detection task. proshade_unsign symRecommFold; //!< The resulting recommended symmetry fold foe the symmetry detection task. + std::vector< proshade_double* > RecomSymAxes; //!< Vector holding the recommended symmetry axes information. + std::vector < std::vector< proshade_double > > allCSymAxes; //!< Vector holding all detected cyclic symmetry axes information. std::vector< proshade_double > mapCOMShift; //!< Vector containing the shift applied to get the COM of the internal map to the centre of the box. private: diff --git a/proshade/src/proshade/ProSHADE_data.cpp b/proshade/src/proshade/ProSHADE_data.cpp index 08e8b3c5..a8c07963 100644 --- a/proshade/src/proshade/ProSHADE_data.cpp +++ b/proshade/src/proshade/ProSHADE_data.cpp @@ -178,6 +178,9 @@ ProSHADE_internal_data::ProSHADE_data::ProSHADE_data ( ) this->maxEMatDim = 0; this->translationMap = nullptr; + // ... Symmetry detectino + this->recommendedSymmetryFold = 1; + this->recommendedSymmetryType = 'C'; // ... Control variables this->isEmpty = true; @@ -3528,7 +3531,10 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResults ( ProSHADE_set void ProSHADE_internal_data::ProSHADE_data::reportCurrentSymmetryResults ( ProSHADE_settings* settings, proshade_double threshold, proshade_signed*& cutIndices, fftw_complex*& fCoeffsCut, proshade_signed noBins, proshade_double**& bindata, proshade_signed*& binCounts, proshade_double*& fscByBin, proshade_signed cutXDim, proshade_signed cutYDim, proshade_signed cutZDim ) { //================================================ Find results for the given threshold + proshade_signed origVerbose = settings->verbose; + settings->verbose = -999; this->determineRecommendedSymmetry ( settings, threshold, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + settings->verbose = origVerbose; //================================================ Improve this! if ( this->recommendedSymmetryType == "" || ( this->recommendedSymmetryType == "C" && this->recommendedSymmetryFold == 1 ) ) @@ -3572,11 +3578,7 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResultsList ( ProSHADE ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.60 ); ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.50 ); ProSHADE_internal_misc::addToDoubleVector ( &thrLevels, 0.40 ); - - //================================================ Silence the search - proshade_signed origVerbose = settings->verbose; - settings->verbose = 0; - + //================================================ Prepare FSC computation memory and variables fftw_complex* fCoeffsCut; proshade_double **bindata, *fscByBin; @@ -3589,8 +3591,11 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResultsList ( ProSHADE ssHlp << std::endl << "Detecting symmetries about point [" << comMove.at(0) << " , " << comMove.at(1) << " , " << comMove.at(2) << "] away from centre of mass ."; ProSHADE_internal_messages::printProgressMessage ( settings->verbose, 0, ssHlp.str(), settings->messageShift ); - //================================================ Run default detection + //================================================ Run default detection in silence + proshade_signed origVerbose = settings->verbose; + settings->verbose = -999; this->determineRecommendedSymmetry ( settings, settings->fscThreshold, cutIndices, fCoeffsCut, noBins, bindata, binCounts, fscByBin, cutXDim, cutYDim, cutZDim ); + settings->verbose = origVerbose; //================================================ Print intro to proshade default ssHlp.clear(); ssHlp.str ( "" ); @@ -3638,9 +3643,6 @@ void ProSHADE_internal_data::ProSHADE_data::reportSymmetryResultsList ( ProSHADE delete[] cutIndices; fftw_free ( fCoeffsCut ); - //================================================ Set verbosity back - settings->verbose = origVerbose; - //================================================ Print all axes ssHlp.clear(); ssHlp.str ( "" ); ssHlp << std::endl << std::endl << "To facilitate manual checking for symmetries, the following is a list of all detected C symmetries:"; @@ -4241,6 +4243,27 @@ std::vector< proshade_double* >* ProSHADE_internal_data::ProSHADE_data::getCycli } + +/*! \brief This function allows access to the list of detected cyclic axes in non-overwrite fashion. + + \param[out] cyclicSymmetries Vector of the cyclic axes detected in the structure. +*/ +std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getCyclicAxesCopy ( void ) +{ + //================================================ Initialise variables + std::vector< proshade_double* > ret; + + //================================================ Copy values + for ( size_t aIt = 0; aIt < this->cyclicSymmetries.size(); aIt++ ) + { + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &ret, &this->cyclicSymmetries.at( aIt )[0] ); + } + + //================================================ Return the requested value + return ( ret ); + +} + /*! \brief This function allows access to the list of detected dihedral axes. \param[out] dihedralSymmetries Vector of vectors containing the list of detected dihedral symmetries. @@ -4252,6 +4275,29 @@ std::vector< std::vector< proshade_double* > >* ProSHADE_internal_data::ProSHADE } +/*! \brief This function allows access to the list of detected dihedral axes in a non-over-write fashion. + + \param[out] dihedralSymmetries Vector of vectors containing the list of detected dihedral symmetries. +*/ +std::vector< std::vector< proshade_double* > > ProSHADE_internal_data::ProSHADE_data::getDihedralAxesCopy ( void ) +{ + //================================================ Initialise variables + std::vector< std::vector< proshade_double* > > ret; + + //================================================ Copy values + for ( size_t aIt = 0; aIt < this->dihedralSymmetries.size(); aIt++ ) + { + std::vector< proshade_double* > hlpVec; + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &hlpVec, &this->dihedralSymmetries.at( aIt ).at(0)[0] ); + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &hlpVec, &this->dihedralSymmetries.at( aIt ).at(1)[0] ); + ProSHADE_internal_misc::addToDblPtrVectorVector ( &ret, hlpVec ); + } + + //================================================ Return the requested value + return ( ret ); + +} + /*! \brief This function allows setting the integration weight for the object. \param[in] intW The integration weight to be set for this object. @@ -4567,6 +4613,24 @@ proshade_unsign ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryFol } +/*! \brief This function simply returns the detected recommended symmetry axes. +*/ +std::vector< proshade_double* > ProSHADE_internal_data::ProSHADE_data::getRecommendedSymmetryValues ( ) +{ + //================================================ Initialise variables + std::vector< proshade_double* > ret; + + //================================================ Copy results + for ( size_t aIt = 0; aIt < this->recommendedSymmetryValues.size(); aIt++ ) + { + ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( &ret, &this->recommendedSymmetryValues.at( aIt )[0] ); + } + + //================================================ Return the value + return ( ret ); + +} + /*! \brief This function returns the number of detected recommended symmetry axes. \param[out] val The length of the recommended symmetry axes vector. diff --git a/proshade/src/proshade/ProSHADE_data.hpp b/proshade/src/proshade/ProSHADE_data.hpp index 11a89932..91bdc6d4 100644 --- a/proshade/src/proshade/ProSHADE_data.hpp +++ b/proshade/src/proshade/ProSHADE_data.hpp @@ -238,6 +238,7 @@ namespace ProSHADE_internal_data std::vector< proshade_double* > findRequestedCSymmetryFromAngleAxis ( ProSHADE_settings* settings, proshade_unsign fold, proshade_double* peakThres ); std::string getRecommendedSymmetryType ( void ); proshade_unsign getRecommendedSymmetryFold ( void ); + std::vector< proshade_double* > getRecommendedSymmetryValues ( void ); proshade_unsign getNoRecommendedSymmetryAxes ( ProSHADE_settings* settings ); proshade_unsign getNoRecommendedSymmetryAxes ( void ); std::vector< std::string > getSymmetryAxis ( ProSHADE_settings* settings, proshade_unsign axisNo ); @@ -323,7 +324,9 @@ namespace ProSHADE_internal_data proshade_complex* getTranslationFnPointer ( void ); std::vector< proshade_double > getMapCOMProcessChange ( void ); std::vector< proshade_double* >* getCyclicAxes ( void ); + std::vector< proshade_double* > getCyclicAxesCopy ( void ); std::vector< std::vector< proshade_double* > >* getDihedralAxes ( void ); + std::vector< std::vector< proshade_double* > > getDihedralAxesCopy ( void ); //============================================ Mutator functions void setIntegrationWeight ( proshade_double intW ); diff --git a/proshade/src/proshade/ProSHADE_tasks.cpp b/proshade/src/proshade/ProSHADE_tasks.cpp index d2772002..156ec42f 100644 --- a/proshade/src/proshade/ProSHADE_tasks.cpp +++ b/proshade/src/proshade/ProSHADE_tasks.cpp @@ -281,11 +281,13 @@ void ProSHADE_internal_tasks::checkDistancesSettings ( ProSHADE_settings* settin the settings object passed as the first argument. \param[in] settings ProSHADE_settings object specifying the details of how distances computation should be done. - \param[in] axes A pointer to a vector to which all the axes of the recommended symmetry (if any) will be saved. - \param[in] allCs A pointer to a vector to which all the detected cyclic symmetries will be saved into. \param[in] mapCOMShift A pointer to a vector containing the distance from the centre of the map to the point about which the symmetry detection was done. + \param[in] symT Pointer to string that will hold the determined symmetry type. + \param[in] symF Pointer to unsigned int that will hold the determined symmetry fold. + \param[in] symA Pointer to a vector of doubles that will hold the determined symmetry axes in the proshade format. + \param[in] allCs A pointer to a vector of vectors containing all the detected C axes. */ -void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double >* mapCOMShift ) +void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double >* mapCOMShift, std::string* symT, proshade_unsign* symF, std::vector< proshade_double* >* symA, std::vector < std::vector< proshade_double > >* allCs ) { //================================================ Check the settings are complete and meaningful checkSymmetrySettings ( settings ); @@ -341,7 +343,13 @@ void ProSHADE_internal_tasks::SymmetryDetectionTask ( ProSHADE_settings* setting //============================================ Report results symmetryStructure->reportSymmetryResultsList ( settings ); - //============================================ Save internal map shift to run object, + //============================================ Save symmetry results + *symT = symmetryStructure->getRecommendedSymmetryType ( ); + *symF = symmetryStructure->getRecommendedSymmetryFold ( ); + for ( size_t aIt = 0; aIt < symmetryStructure->recommendedSymmetryValues.size(); aIt++ ) { ProSHADE_internal_misc::deepCopyAxisToDblPtrVector ( symA, &symmetryStructure->recommendedSymmetryValues.at( aIt )[0] ); } + for ( size_t aIt = 0; aIt < symmetryStructure->cyclicSymmetries.size(); aIt++ ) { std::vector< proshade_double > hlpVec; for ( size_t vIt = 0; vIt < 7; vIt++ ) { ProSHADE_internal_misc::addToDoubleVector ( &hlpVec, symmetryStructure->cyclicSymmetries.at(aIt)[vIt] ); } ProSHADE_internal_misc::addToDoubleVectorVector ( allCs, hlpVec ); } + + //============================================ Save internal map shift to run object ProSHADE_internal_misc::addToDoubleVector ( mapCOMShift, symmetryStructure->mapCOMProcessChangeX ); ProSHADE_internal_misc::addToDoubleVector ( mapCOMShift, symmetryStructure->mapCOMProcessChangeY ); ProSHADE_internal_misc::addToDoubleVector ( mapCOMShift, symmetryStructure->mapCOMProcessChangeZ ); diff --git a/proshade/src/proshade/ProSHADE_tasks.hpp b/proshade/src/proshade/ProSHADE_tasks.hpp index 7e3f020c..9ce1dede 100644 --- a/proshade/src/proshade/ProSHADE_tasks.hpp +++ b/proshade/src/proshade/ProSHADE_tasks.hpp @@ -40,7 +40,7 @@ namespace ProSHADE_internal_tasks std::vector < proshade_signed* >* reboxedBounds, std::vector < proshade_double* >* manipulatedMaps ); void DistancesComputationTask ( ProSHADE_settings* settings, std::vector< proshade_double >* enLevs, std::vector< proshade_double >* trSigm, std::vector< proshade_double >* rotFun ); - void SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double >* mapCOMShift ); + void SymmetryDetectionTask ( ProSHADE_settings* settings, std::vector< proshade_double >* mapCOMShift, std::string* symT, proshade_unsign* symF, std::vector< proshade_double* >* symA, std::vector < std::vector< proshade_double > >* allCs ); void MapOverlayTask ( ProSHADE_settings* settings, std::vector < proshade_double >* rotationCentre, std::vector < proshade_double >* eulerAngles, std::vector < proshade_double >* finalTranslation ); void SymmetryCentreDetectionTask ( ProSHADE_settings* settings, proshade_unsign strIndex = 0 ); From ad7909a0d4138119f32d605455253da1c551fd24 Mon Sep 17 00:00:00 2001 From: Michal Tykac Date: Tue, 12 Jul 2022 14:08:05 +0200 Subject: [PATCH 3/4] Minor changes to remove warning produced by Gemmi included code when the cl.exe (VS2022 compiler) is used as well as a few warning caused by the ProSHADE code. --- README.md | 117 +++++++++++------- .../getMaskedSymmetryPredictions.py | 2 +- proshade/src/bin/bin.cpp | 117 +++++++++++------- proshade/src/proshade/ProSHADE_maths.cpp | 4 +- proshade/src/proshade/ProSHADE_tasks.cpp | 2 +- proshade/src/proshade/ProSHADE_typedefs.hpp | 12 +- 6 files changed, 156 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index 88779c59..b270572d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ProSHADE ======== -Protein Shape Description and Symmetry Detection version 0.7.6.5 (JUN 2022) +Protein Shape Description and Symmetry Detection version 0.7.6.6 (JUL 2022) # Introduction @@ -185,21 +185,21 @@ As mentioned above, ProSHADE currently only supports Windows10 64-bit systems an ### Installing CMake -CMake can be installed on Windows using the 64-bit MSI installer available from https://cmake.org/download . During the installation, please make sure that the option to *Add CMake to the system PATH* is selected (it does not matter to ProSHADE if it is for all users or just for the current user). +CMake can be installed on Windows using the 64-bit MSI installer (binary distribution) available from https://cmake.org/download . During the installation, please make sure that the option to *Add CMake to the system PATH* is selected (it does not matter to ProSHADE if it is for all users or just for the current user). ### Installing git -Git can be installed on Windows by downloading the 64-bit Windows Setup installer from https://git-scm.com/download/win . The installer asks for many options, the only important one for ProSHADE installation is that in the section "Adjusting you PATH environment" it is required that the option *Use Git from Git Bash only* is **NOT** selected. This makes sure that the git executable is in the system PATH. +Git can be installed on Windows by downloading the 64-bit Windows Setup installer from https://git-scm.com/download/win . The installer asks for many options, the only important one for ProSHADE installation is that in the section "Adjusting your PATH environment" it is required that the option *Use Git from Git Bash only* is **NOT** selected. This makes sure that the git executable is in the system PATH. ### Installing Build Tools for Visual Studio -Sadly, the Authors are not aware of any simple way of installing the Microsoft C and C++ compilers and linker controlling tool - **cl.exe** except for installing the full Visual Studio or the Build Tools for Visual Studio. This will require well over 6GB of space on your hard-drive and the download is well over 1.5GB. Nonetheless, it is the main Windows compiler and linker and therefore ProSHADE cannot be installed on Windows without it. +Sadly, the Authors are not aware of any simple way of installing the Microsoft C and C++ compilers and linker controlling tool - **cl.exe** except for installing the full Visual Studio or the Build Tools for Visual Studio. This will require well over 7.5GB of space on your hard-drive and the download is well over 1.5GB. Nonetheless, it is the main Windows compiler and linker and therefore ProSHADE cannot be installed on Windows without it. -To install the Build Tools for Visual Studio, please download the installer from Microsoft at https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019 and in the Workload selection screen select the *C++ Build Tools* option. The rest of the installtion should be automatic. +To install the Build Tools for Visual Studio, please download the installer from Microsoft at https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022 and in the Workload selection screen select the *Desktop development with C++* option. The rest of the installtion should be automatic. ### Installing ProSHADE -Once all of the above dependencies are installed, the ProSHADE python module can now be installed using the pip installation as described in the [Installing using pip ](#installing-using-pip) section. Should the user require installation from the Command Prompt, they will need to open the *Developer Command Prompt for VS 2019* (or the appropriate version the MS Visual Studio they have installed) and type the following commands (replacing the \path\to\proshade with the appropriate path on their machine to the location where they want ProSHADE codes to be stored). Please note that you may need to run the command prompt as an administrator in order to be able to install into the system folders (i.e. C:\Program Files). Also, the same CMake options apply as discussed in section [CMake options](#cmake-options): +Once all of the above dependencies are installed, the ProSHADE python module can now be installed using the pip installation as described in the [Installing using pip ](#installing-using-pip) section. Should the user require installation from the Command Prompt, they will need to open the *Developer Command Prompt for VS 2022* (or the appropriate version the MS Visual Studio they have installed) and type the following commands (replacing the \path\to\proshade with the appropriate path on their machine to the location where they want ProSHADE codes to be stored). Please note that you may need to run the command prompt as an administrator in order to be able to install into the system folders (i.e. C:\Program Files). Also, the same CMake options apply as discussed in section [CMake options](#cmake-options): ``` cd \path\to\proshade @@ -313,17 +313,17 @@ In order to detect symmetry in either a co-ordinate input file or in a map input One particular option regarding the symmetry detection mode should be noted; the **--reqSym** (or **-u**) option, which allows the user to state which symmetry they believe to exist in the structure. The allowed values for this command line argument are "Cx", "Dx", "T", "O" and "I", where the *x* should be an integer number specifying the fold of the requested symmetry. When this option is used, it removes the default behaviour of returning the "best" detected symmetry and instead the symmetry requested by the user is returned, if it can be found in the structure. -Another noteworthy option is the **--center** or **-c** option, which tells ProSHADE **NOT** to center the internal map representation over the centre of density before running any processing of the map (default is centering and adding this option will turn centering off). This may be important as ProSHADE detects symmetries over the centre of the co-ordinates and therefore a non-centered map (map which does not have the centre of mass at the centre of box) will be found to have no symmetries even if these are present, just not over the co-ordinate/box centre. Alternatively, ProSHADE can attempt a procedure for finding the symmetry centre itself - to enable this procedure, please supply the **--symCentre** or **-I** option. This procedure will firstly remove phase from the internal density map and attempt symmetry detection over the Patterson map. Then, by applying the symmetry that is known from the Patterson map to be there, the symmetry centre can be found; however, please note that this will consume considerable extra computation time (approximately 3-4 times slower than when the procedure is disabled). +Another noteworthy option is the **--center** or **-c** option, which tells ProSHADE **NOT** to center the internal map representation over the centre of density before running any processing of the map (default is centering and adding this option will turn centering off). This may be important as ProSHADE detects symmetries over the centre of the co-ordinates and therefore a non-centered map (map which does not have the centre of mass at the centre of box) will be found to have no symmetries even if these are present, just not over the co-ordinate/box centre. Alternatively, ProSHADE can attempt a procedure for finding the symmetry centre itself - to enable this procedure, please supply the **--symCentre** or **-I** option. This procedure will firstly remove phase from the internal density map and attempt symmetry detection over the Patterson map. Then, by applying the symmetry that is found in the Patterson map (if any), the symmetry centre can be found; however, please note that this will consume considerable extra computation time (approximately 3-4 times slower than when the procedure is disabled). It is also worth noting that there are several extra functionalities available for the symmetry detection mode when accessed programmatically (**i.e.** either through the dynamic C++ library or through the Python language module). These extra functionalities include direct access to a vector/list of all detected cyclic symmetries, list/vector of all other symmetry type detections (meaning a list of all detected dihedral, tetrahedral, ... symmetries and the cyclic axes forming them) and also the ability to compute all point group elements for any point group formed by a combination of ProSHADE detected cyclic point groups. For more details on these functinoalities, the users are invited to consult the *advancedAccess_symmetry.cpp/py* example files in the **examples** folder. -To demonstrate how the tool can be run and the standard output for the symmetry mode of operation, the current version of the ProSHADE executable was used to detect the symmetry of a density map of the bacteriophage T4 portal protein with the PDB accession code 3JA7 (EMDB accession code 6324), which has the *C12* symmetry. The visualisation of the structure is shown in the following figure, while the output of the ProSHADE tool follows: +To demonstrate how the tool can be run and the standard output for the symmetry mode of operation, the current version of the ProSHADE executable was used to detect the symmetry of a density map of the bacteriophage T4 portal protein with the PDB accession code 3JA7 (EMDB accession code 6324), which has the *C12* symmetry. The visualisation of the structure is shown in the following figure, while the output of the ProSHADE tool follows. It is also worth noting that ProSHADE will output its prediction as well as table showing how different FSC average threshold values would change its prediction. This table can be used by the user to manually decide if they agree with the ProSHADE prediction or if thay suspect a different symmetry may indeed be real. Finally, ProSHADE will also output the list of all detected symmetries, so that experienced user could manually check for any particuar symmetry they are interested in and also check for how much they trust the ProSHADE prediction overall. ![T4 Portal Protein](https://github.com/michaltykac/proshade/blob/experimental/proshade/documentation/ProSHADE_3JA7.jpg) ``` $: ./proshade -S -f ./emd_6324.map -ProSHADE 0.7.6.5 (JUN 2022): +ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./emd_6324.map @@ -340,40 +340,65 @@ ProSHADE 0.7.6.5 (JUN 2022): ... Starting spherical harmonics decomposition. ... Starting self-rotation function computation. ... Starting C symmetry detection. + ... Starting recommended symmetry decision procedure. ... Starting D symmetry detection. ... Starting T symmetry prediction. ... Starting O symmetry prediction. ... Starting I symmetry prediction. - ... Starting recommended symmetry decision procedure. -Detected C symmetry with fold 12 about point [-0.00969196 , -0.008841 , 12.1956] away from centre of mass . - Fold X Y Z Angle Height Average FSC - +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99810 +0.99447 +Detecting symmetries about point [-0.00105446 , -0.00106463 , 11.3385] away from centre of mass . + +ProSHADE default symmetry detection algorithm claims the symmetry to be C-12 with axes: +====================================================================================== + Type Fold X Y Z Angle Height Average FSC + C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + + +Symmetry detection results per FSC threshold levels: +==================================================== + + Threshold Type Fold X Y Z Angle Height Average FSC +=========================================================================================================== + +0.95 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 +=========================================================================================================== + +0.90 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 +=========================================================================================================== + +0.80 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 +=========================================================================================================== + +0.70 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 +=========================================================================================================== + +0.60 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 +=========================================================================================================== + +0.50 C +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.92159 +0.50824 +=========================================================================================================== + +0.40 C +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.92159 +0.50824 +=========================================================================================================== + To facilitate manual checking for symmetries, the following is a list of all detected C symmetries: - Fold X Y Z Angle Height Average FSC - +4 +0.00000 +0.00000 +1.00000 +1.57080 +0.99981 +0.99915 - +2 +0.00080 -0.00000 +1.00000 +3.14159 +0.99984 +0.99843 - +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99810 +0.99447 - +6 +0.00000 +0.00000 +1.00000 +1.04720 +0.99793 +0.99440 - +3 +0.00000 +0.00000 +1.00000 +2.09440 +0.99746 +0.99380 - +13 +0.00000 +0.00000 +1.00000 +0.48332 +0.94064 +0.82881 - +11 +0.00000 +0.00000 +1.00000 +0.57120 +0.93974 +0.77292 - +29 +0.00000 +0.00000 +1.00000 +0.21666 +0.94337 +0.34082 - +23 +0.00000 +0.00000 +1.00000 +0.27318 +0.94269 +0.33481 - +19 +0.00000 +0.00000 +1.00000 +0.33069 +0.94215 +0.32833 - +7 +0.00000 +0.00000 +1.00000 +0.89760 +0.93615 +0.15763 - +17 +0.00000 +0.00000 +1.00000 +0.36960 +0.94179 +0.14640 - +9 +0.00000 +0.00000 +1.00000 +0.69813 +0.93840 +0.10686 - +36 +0.00000 +0.00000 +1.00000 +0.17453 +0.94366 +0.10686 - +18 +0.00000 +0.00000 +1.00000 +0.34907 +0.94201 +0.10616 - +5 +0.00000 +0.00000 +1.00000 +1.25664 +0.93167 +0.07275 - +8 +0.00000 +0.00000 +1.00000 +0.78540 +0.93923 +0.06234 - +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.94370 +0.06234 + Type Fold X Y Z Angle Height Average FSC + C +4 +0.00080 +0.00000 +1.00000 +1.57080 +0.99941 +0.99878 + C +2 +0.00080 +0.00000 +1.00000 +3.14159 +0.99990 +0.99846 + C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + C +6 +0.00000 +0.00000 +1.00000 +1.04720 +0.99945 +0.99494 + C +3 +0.00000 +0.00000 +1.00000 +2.09440 +0.99934 +0.99384 + C +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.92159 +0.50824 + C +36 +0.00000 +0.00000 +1.00000 +0.17453 +0.92093 +0.38773 + C +29 +0.00000 +0.00000 +1.00000 +0.21666 +0.92031 +0.34380 + C +23 +0.00000 +0.00000 +1.00000 +0.27318 +0.91955 +0.33786 + C +19 +0.00000 +0.00000 +1.00000 +0.33069 +0.91877 +0.33139 + C +13 +0.00000 +0.00000 +1.00000 +0.48332 +0.91664 +0.31361 + C +11 +0.00000 +0.00000 +1.00000 +0.57120 +0.91537 +0.30339 + C +7 +0.01187 +0.00273 +0.99993 -0.89760 +0.91028 +0.16016 + C +17 +0.00000 +0.00000 +1.00000 +0.36960 +0.91836 +0.14969 + C +9 +0.00000 +0.00000 +1.00000 +0.69813 +0.91369 +0.10910 + C +18 +0.00000 +0.00000 +1.00000 +0.34907 +0.91876 +0.10859 + C +5 +0.01370 -0.00450 +0.99990 -1.25664 +0.90434 +0.07497 + C +8 +0.00000 +0.00000 +1.00000 +0.78540 +0.91432 +0.06175 ====================== ProSHADE run complete. -Time taken: 120 seconds. +Time taken: 210 seconds. ====================== ``` @@ -389,7 +414,7 @@ Time taken: 120 seconds. ``` $: ./proshade -D -f ./1BFO_A_dom_1.pdb -f ./1H8N_A_dom_1.pdb -f ./3IGU_A_dom_1.pdb -r 6 - ProSHADE 0.7.6.5 (JUN 2022): + ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./1BFO_A_dom_1.pdb @@ -422,7 +447,7 @@ Time taken: 120 seconds. Distances between ./1BFO_A_dom_1.pdb and ./1H8N_A_dom_1.pdb Energy levels distance : 0.851642 Trace sigma distance : 0.910876 - Rotation function distance: 0.616275 + Rotation function distance: 0.619839 ... Starting to read the structure: ./3IGU_A_dom_1.pdb ... Map left at original position. ... Map rotation centre not shifted. @@ -445,7 +470,7 @@ Time taken: 120 seconds. ====================== ProSHADE run complete. - Time taken: 0 seconds. + Time taken: 2 seconds. ====================== ``` @@ -463,7 +488,7 @@ Time taken: 120 seconds. ``` $ ./proshade -RMf ./emd_5762.map.gz -ProSHADE 0.7.6.5 (JUN 2022): +ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./emd_5762.map.gz @@ -481,7 +506,7 @@ ProSHADE 0.7.6.5 (JUN 2022): ====================== ProSHADE run complete. -Time taken: 9 seconds. +Time taken: 14 seconds. ====================== ``` @@ -507,7 +532,7 @@ Time taken: 9 seconds. ``` $ ./proshade -O -f ./1BFO_A_dom_1.pdb -f ./1H8N_A_dom_1.pdb -r 1 - ProSHADE 0.7.6.5 (JUN 2022): + ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./1BFO_A_dom_1.pdb @@ -558,15 +583,15 @@ Time taken: 9 seconds. ... Adding extra 10 angstroms. ... Starting translation function computation. - The rotation centre to origin translation vector is: -18.4 -21.4 -22.9 - The rotation matrix about origin is : -0.852 +0.205 -0.481 - : +0.0745 -0.863 -0.499 - : -0.517 -0.462 +0.721 - The rotation centre to overlay translation vector is: +3 +4.5 -4.5 + The rotation centre to origin translation vector is: -18.3 -21.3 -23.3 + The rotation matrix about origin is : -0.854 +0.192 -0.484 + : +0.0836 -0.867 -0.492 + : -0.514 -0.46 +0.724 + The rotation centre to overlay translation vector is: +3 +5 -5 ====================== ProSHADE run complete. - Time taken: 17 seconds. + Time taken: 34 seconds. ====================== ``` # Using the ProSHADE library @@ -623,7 +648,7 @@ $ cl.exe /I "\path\to\proshade\extern\gemmi\include" "\path\to\proshade\install\lib\proshade.lib" !!! NOTE: The x64 Native version of cl.exe (or Visual Studio Command Prompt) needs to be used for this to work. 32-bit version of ProSHADE library is not available currently. -!!! To do this, use the "x64 Native Tools Command Prompt for VS2019" +!!! To do this, use the "x64 Native Tools Command Prompt for VS2022" ``` ## Examples of ProSHADE library usage diff --git a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py index 00317cf8..b91096d7 100644 --- a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py +++ b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py @@ -95,7 +95,7 @@ ### no user manipulation is required. ### -startFrom = 359 +startFrom = 382 resolutionFilename = resolution outResCondensed = 0 outResAxes = 0 diff --git a/proshade/src/bin/bin.cpp b/proshade/src/bin/bin.cpp index 62215422..2ed4bca4 100644 --- a/proshade/src/bin/bin.cpp +++ b/proshade/src/bin/bin.cpp @@ -218,23 +218,23 @@ * * \b Installing CMake * - * CMake can be installed on Windows using the 64-bit MSI installer available from https://cmake.org/download . During the installation, please make sure that the option to \e Add \e CMake \e to + * CMake can be installed on Windows using the 64-bit MSI installer (binary distribution) available from https://cmake.org/download . During the installation, please make sure that the option to \e Add \e CMake \e to * \e the \e system \e PATH is selected (it does not matter to ProSHADE if it is for all users or just for the current user). * * \b Installing \b git * * Git can be installed on Windows by downloading the 64-bit Windows Setup installer from https://git-scm.com/download/win . The installer asks for many options, the only important one for ProSHADE - * installation is that in the section \e Adjusting \e you \e PATH \e environment it is required that the option \e Use \e Git \e from \e Git \e Bash \e only is \b NOT selected. This makes sure that the + * installation is that in the section \e Adjusting \e your \e PATH \e environment it is required that the option \e Use \e Git \e from \e Git \e Bash \e only is \b NOT selected. This makes sure that the * git executable is in the system PATH. * * \b Installing \b Build \b Tools \b for \b Visual \b Studio * * Sadly, the Authors are not aware of any simple way of installing the Microsoft C and C++ compilers and linker controlling tool - \b cl.exe except for installing the full Visual Studio or the Build Tools for Visual - * Studio. This will require well over 6GB of space on your hard-drive and the download is well over 1.5GB. Nonetheless, it is the main Windows compiler and linker and therefore ProSHADE cannot be installed + * Studio. This will require well over 7.5GB of space on your hard-drive and the download is well over 1.5GB. Nonetheless, it is the main Windows compiler and linker and therefore ProSHADE cannot be installed * on Windows without it. * - * To install the Build Tools for Visual Studio, please download the installer from Microsoft at https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019 and in - * the Workload selection screen select the \e C++ \e Build \e Tools option. The rest of the installtion should be automatic. + * To install the Build Tools for Visual Studio, please download the installer from Microsoft at https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022 and in + * the Workload selection screen select the \e Desktop \e development \e with \e C++ option. The rest of the installtion should be automatic. * * \b Installing \b ProSHADE * @@ -394,7 +394,7 @@ * is centering and adding this option will turn centering off). This may be important as ProSHADE detects symmetries over the centre of the co-ordinates and therefore a non-centered map (map which does not * have the centre of mass at the centre of box) will be found to have no symmetries even if these are present, just not over the co-ordinate/box centre. Alternatively, ProSHADE can attempt a procedure for finding the * symmetry centre itself - to enable this procedure, please supply the \b --symCentre or \b -I option. This procedure will firstly remove phase from the internal density map and attempt symmetry detection over the - * Patterson map. Then, by applying the symmetry that is known from the Patterson map to be there, the symmetry centre can be found; however, please note that this will consume considerable extra computation time + * Patterson map. Then, by applying the symmetry that is found in the Patterson map (if any), the symmetry centre can be found; however, please note that this will consume considerable extra computation time * (approximately 3-4 times slower than when the procedure is disabled). * * It is also worth noting that there are several extra functionalities available for the symmetry detection mode when accessed programmatically (\e i.e. either through the dynamic C++ library or through @@ -404,13 +404,16 @@ * * To demonstrate how the tool can be run and the standard output for the symmetry mode of operation, the current version of the ProSHADE executable was used to detect the * symmetry of a density map of the bacteriophage T4 portal protein with the PDB accession code 3JA7 (EMDB accession code 6324), which has the \e C12 symmetry. The visualisation of the structure is - * shown in the following figure, while the output of the ProSHADE tool follows: + * shown in the following figure, while the output of the ProSHADE tool follows. It is also worth noting that ProSHADE will output its prediction as well as table showing how different FSC average threshold + * values would change its prediction. This table can be used by the user to manually decide if they agree with the ProSHADE prediction or if thay suspect a different symmetry may indeed be real. Finally, + * ProSHADE will also output the list of all detected symmetries, so that experienced user could manually check for any particuar symmetry they are interested in and also check for how much they trust + * the ProSHADE prediction overall. * * \image html ProSHADE_3JA7.jpg width=500cm * *\code{.sh} $: ./proshade -S -f ./emd_6324.map - ProSHADE 0.7.6.5 (JUN 2022): + ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./emd_6324.map @@ -427,40 +430,65 @@ ... Starting spherical harmonics decomposition. ... Starting self-rotation function computation. ... Starting C symmetry detection. + ... Starting recommended symmetry decision procedure. ... Starting D symmetry detection. ... Starting T symmetry prediction. ... Starting O symmetry prediction. ... Starting I symmetry prediction. - ... Starting recommended symmetry decision procedure. - Detected C symmetry with fold 12 about point [-0.00969196 , -0.008841 , 12.1956] away from centre of mass . - Fold X Y Z Angle Height Average FSC - +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99810 +0.99447 + Detecting symmetries about point [-0.00105446 , -0.00106463 , 11.3385] away from centre of mass . + + ProSHADE default symmetry detection algorithm claims the symmetry to be C-12 with axes: + ====================================================================================== + Type Fold X Y Z Angle Height Average FSC + C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + + + Symmetry detection results per FSC threshold levels: + ==================================================== + + Threshold Type Fold X Y Z Angle Height Average FSC + =========================================================================================================== + +0.95 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + =========================================================================================================== + +0.90 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + =========================================================================================================== + +0.80 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + =========================================================================================================== + +0.70 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + =========================================================================================================== + +0.60 C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + =========================================================================================================== + +0.50 C +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.92159 +0.50824 + =========================================================================================================== + +0.40 C +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.92159 +0.50824 + =========================================================================================================== + To facilitate manual checking for symmetries, the following is a list of all detected C symmetries: - Fold X Y Z Angle Height Average FSC - +4 +0.00000 +0.00000 +1.00000 +1.57080 +0.99981 +0.99915 - +2 +0.00080 -0.00000 +1.00000 +3.14159 +0.99984 +0.99843 - +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99810 +0.99447 - +6 +0.00000 +0.00000 +1.00000 +1.04720 +0.99793 +0.99440 - +3 +0.00000 +0.00000 +1.00000 +2.09440 +0.99746 +0.99380 - +13 +0.00000 +0.00000 +1.00000 +0.48332 +0.94064 +0.82881 - +11 +0.00000 +0.00000 +1.00000 +0.57120 +0.93974 +0.77292 - +29 +0.00000 +0.00000 +1.00000 +0.21666 +0.94337 +0.34082 - +23 +0.00000 +0.00000 +1.00000 +0.27318 +0.94269 +0.33481 - +19 +0.00000 +0.00000 +1.00000 +0.33069 +0.94215 +0.32833 - +7 +0.00000 +0.00000 +1.00000 +0.89760 +0.93615 +0.15763 - +17 +0.00000 +0.00000 +1.00000 +0.36960 +0.94179 +0.14640 - +9 +0.00000 +0.00000 +1.00000 +0.69813 +0.93840 +0.10686 - +36 +0.00000 +0.00000 +1.00000 +0.17453 +0.94366 +0.10686 - +18 +0.00000 +0.00000 +1.00000 +0.34907 +0.94201 +0.10616 - +5 +0.00000 +0.00000 +1.00000 +1.25664 +0.93167 +0.07275 - +8 +0.00000 +0.00000 +1.00000 +0.78540 +0.93923 +0.06234 - +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.94370 +0.06234 + Type Fold X Y Z Angle Height Average FSC + C +4 +0.00080 +0.00000 +1.00000 +1.57080 +0.99941 +0.99878 + C +2 +0.00080 +0.00000 +1.00000 +3.14159 +0.99990 +0.99846 + C +12 +0.00000 +0.00000 +1.00000 +0.52360 +0.99912 +0.99533 + C +6 +0.00000 +0.00000 +1.00000 +1.04720 +0.99945 +0.99494 + C +3 +0.00000 +0.00000 +1.00000 +2.09440 +0.99934 +0.99384 + C +24 +0.00000 +0.00000 +1.00000 +0.26180 +0.92159 +0.50824 + C +36 +0.00000 +0.00000 +1.00000 +0.17453 +0.92093 +0.38773 + C +29 +0.00000 +0.00000 +1.00000 +0.21666 +0.92031 +0.34380 + C +23 +0.00000 +0.00000 +1.00000 +0.27318 +0.91955 +0.33786 + C +19 +0.00000 +0.00000 +1.00000 +0.33069 +0.91877 +0.33139 + C +13 +0.00000 +0.00000 +1.00000 +0.48332 +0.91664 +0.31361 + C +11 +0.00000 +0.00000 +1.00000 +0.57120 +0.91537 +0.30339 + C +7 +0.01187 +0.00273 +0.99993 -0.89760 +0.91028 +0.16016 + C +17 +0.00000 +0.00000 +1.00000 +0.36960 +0.91836 +0.14969 + C +9 +0.00000 +0.00000 +1.00000 +0.69813 +0.91369 +0.10910 + C +18 +0.00000 +0.00000 +1.00000 +0.34907 +0.91876 +0.10859 + C +5 +0.01370 -0.00450 +0.99990 -1.25664 +0.90434 +0.07497 + C +8 +0.00000 +0.00000 +1.00000 +0.78540 +0.91432 +0.06175 ====================== ProSHADE run complete. - Time taken: 120 seconds. + Time taken: 210 seconds. ====================== *\endcode * @@ -482,7 +510,7 @@ * *\code{.sh} $: ./proshade -D -f ./1BFO_A_dom_1.pdb -f ./1H8N_A_dom_1.pdb -f ./3IGU_A_dom_1.pdb -r 6 - ProSHADE 0.7.6.5 (JUN 2022): + ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./1BFO_A_dom_1.pdb @@ -515,7 +543,7 @@ Distances between ./1BFO_A_dom_1.pdb and ./1H8N_A_dom_1.pdb Energy levels distance : 0.851642 Trace sigma distance : 0.910876 - Rotation function distance: 0.616275 + Rotation function distance: 0.619839 ... Starting to read the structure: ./3IGU_A_dom_1.pdb ... Map left at original position. ... Map rotation centre not shifted. @@ -538,8 +566,9 @@ ====================== ProSHADE run complete. - Time taken: 0 seconds. + Time taken: 2 seconds. ====================== + *\endcode * * \subsection reboxingUsage Re-boxing structures @@ -562,7 +591,7 @@ * *\code{.sh} $ ./proshade -RMf ./emd_5762.map.gz - ProSHADE 0.7.6.5 (JUN 2022): + ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./emd_5762.map.gz @@ -580,7 +609,7 @@ ====================== ProSHADE run complete. - Time taken: 9 seconds. + Time taken: 14 seconds. ====================== \endcode * @@ -625,7 +654,7 @@ * *\code{.sh} $ ./proshade -O -f ./1BFO_A_dom_1.pdb -f ./1H8N_A_dom_1.pdb -r 1 - ProSHADE 0.7.6.5 (JUN 2022): + ProSHADE 0.7.6.6 (JUL 2022): ============================ ... Starting to read the structure: ./1BFO_A_dom_1.pdb @@ -676,15 +705,15 @@ ... Adding extra 10 angstroms. ... Starting translation function computation. - The rotation centre to origin translation vector is: -18.4 -21.4 -22.9 - The rotation matrix about origin is : -0.852 +0.205 -0.481 - : +0.0745 -0.863 -0.499 - : -0.517 -0.462 +0.721 - The rotation centre to overlay translation vector is: +3 +4.5 -4.5 + The rotation centre to origin translation vector is: -18.3 -21.3 -23.3 + The rotation matrix about origin is : -0.854 +0.192 -0.484 + : +0.0836 -0.867 -0.492 + : -0.514 -0.46 +0.724 + The rotation centre to overlay translation vector is: +3 +5 -5 ====================== ProSHADE run complete. - Time taken: 17 seconds. + Time taken: 34 seconds. ====================== \endcode * diff --git a/proshade/src/proshade/ProSHADE_maths.cpp b/proshade/src/proshade/ProSHADE_maths.cpp index e5201713..fae5e68a 100644 --- a/proshade/src/proshade/ProSHADE_maths.cpp +++ b/proshade/src/proshade/ProSHADE_maths.cpp @@ -4150,7 +4150,7 @@ proshade_double ProSHADE_internal_maths::findTopGroupSmooth ( std::vector< prosh //================================================ Determine threshold from the peaks size_t bestHistPos; if ( peaks.size() > 0 ) { bestHistPos = hist.size() - ( ( smoothened.size() - static_cast< size_t > ( peaks.at(peaks.size()-1) ) ) + ( ( static_cast< size_t > ( windowSize ) + 1 ) / 2 ) ); } - else { bestHistPos = 0.0; } + else { bestHistPos = 0; } threshold = ( static_cast< proshade_double > ( bestHistPos ) * step ); //================================================ Check that the threshold is not higher than the highest value @@ -4217,7 +4217,7 @@ proshade_double ProSHADE_internal_maths::findTopGroupSmooth ( std::vector< std:: //================================================ Determine threshold from the peaks size_t bestHistPos; if ( peaks.size() > 0 ) { bestHistPos = hist.size() - ( ( smoothened.size() - static_cast< size_t > ( peaks.at(peaks.size()-1) ) ) + ( ( static_cast< size_t > ( windowSize ) + 1 ) / 2 ) ); } - else { bestHistPos = 0.0; } + else { bestHistPos = 0; } threshold = ( static_cast< proshade_double > ( bestHistPos ) * step ); //================================================ Check that the threshold is not higher than the highest value diff --git a/proshade/src/proshade/ProSHADE_tasks.cpp b/proshade/src/proshade/ProSHADE_tasks.cpp index 156ec42f..14cc69fb 100644 --- a/proshade/src/proshade/ProSHADE_tasks.cpp +++ b/proshade/src/proshade/ProSHADE_tasks.cpp @@ -453,7 +453,7 @@ void ProSHADE_internal_tasks::SymmetryCentreDetectionTask ( ProSHADE_settings* s ProSHADE_internal_symmetry::allocateCentreOfMapFourierTransforms ( symStr->getXDim(), symStr->getYDim(), symStr->getZDim(), origMap, origCoeffs, rotMapComplex, rotCoeffs, trFunc, trFuncCoeffs, &planForwardFourier, &planForwardFourierRot, &planReverseFourierComb ); //================================================ Compute Fourier for the original map - for ( size_t it = 0; it < static_cast< size_t > ( symStr->getXDim() * symStr->getYDim() * symStr->getZDim() ); it++ ) { origMap[it][0] = symStr->getMapValue( it ); origMap[it][1] = 0.0; } + for ( proshade_unsign it = 0; it < static_cast< proshade_unsign > ( symStr->getXDim() * symStr->getYDim() * symStr->getZDim() ); it++ ) { origMap[it][0] = symStr->getMapValue( it ); origMap[it][1] = 0.0; } fftw_execute ( planForwardFourier ); //================================================ If single C was found diff --git a/proshade/src/proshade/ProSHADE_typedefs.hpp b/proshade/src/proshade/ProSHADE_typedefs.hpp index 259b3d10..30b4a046 100644 --- a/proshade/src/proshade/ProSHADE_typedefs.hpp +++ b/proshade/src/proshade/ProSHADE_typedefs.hpp @@ -58,9 +58,11 @@ #pragma clang diagnostic ignored "-Weverything" #endif -//==================================================== Remove MSVC C4996 Warnings caused by Gemmi code +//==================================================== Remove MSVC C4127, C4244, C4996 Warnings caused by Gemmi code #if defined ( _MSC_VER ) - #pragma warning ( disable:4996 ) + #pragma warning ( disable : 4127 ) + #pragma warning ( disable : 4244 ) + #pragma warning ( disable : 4996 ) #endif //==================================================== Gemmi @@ -74,9 +76,11 @@ #include #endif -//==================================================== Enable MSVC C4996 Warnings for the rest of the code +//==================================================== Enable MSVC C4127, C4244, C4996 Warnings for the rest of the code #if defined ( _MSC_VER ) - #pragma warning ( default:4996 ) + #pragma warning ( default : 4127 ) + #pragma warning ( default : 4244 ) + #pragma warning ( default : 4996 ) #endif //==================================================== FFTW3 From 4c4e62c7aae4d180bdcda1b743ead1aa1492673e Mon Sep 17 00:00:00 2001 From: Michal Tykac Date: Tue, 12 Jul 2022 16:42:58 +0200 Subject: [PATCH 4/4] Checked all the examples in the README.MD and bin.cpp files as well as all the file version (such as in the CMakeLists.txt file). This should now all be ready for the version 0.7.6.6 --- README.md | 26 ++++++++++--------- proshade/CMakeLists.txt | 2 +- .../libproshade/advancedAccess_symmetry.cpp | 6 ++--- .../getMaskedSymmetryPredictions.py | 4 +-- proshade/src/bin/bin.cpp | 26 ++++++++++--------- setup.py | 6 ++--- 6 files changed, 37 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index b270572d..c5576452 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ Once the path is set, you can use ProSHADE from any Command Prompt window (not o **-DCUSTOM_FFTW3_LIB_PATH=/path** - This option is used to supply the path to the libfftw3.a/so/dylib in the case where ProSHADE CMake installation fails to detect the FFTW3 dependency. This is typically the case when FFTW3 is installed outside of the standard FFTW3 installation locations. - **-CUSTOM_FFTW3_INC_PATH=/path** + **-DCUSTOM_FFTW3_INC_PATH=/path** - This option is used to supply the path to the fftw3.h file in the case where ProSHADE CMake installation fails to detect the FFTW3 dependency. This is typically the case when FFTW3 is installed outside of the standard FFTW3 installation locations. **-DCUSTOM_LAPACK_LIB_PATH=/path** @@ -722,11 +722,10 @@ int main ( int argc, char **argv ) simpleSym->computeRotationFunction ( settings ); //================================================ Detect the recommended symmetry - std::vector< proshade_double* > symAxes; - std::vector< std::vector< proshade_double > > allCsFromSettings; - simpleSym->detectSymmetryInStructure ( settings, &symAxes, &allCsFromSettings ); - std::string symmetryType = simpleSym->getRecommendedSymmetryType ( settings ); - proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( settings ); + simpleSym->detectSymmetryFromAngleAxisSpace ( settings ); + std::string symmetryType = simpleSym->getRecommendedSymmetryType ( ); + proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( ); + std::vector< proshade_double* > symAxes = simpleSym->getRecommendedSymmetryValues ( ); //================================================ Write out the symmetry detection results std::cout << "Detected symmetry: " << symmetryType << "-" << symmetryFold << " with axes:" << std::endl; @@ -737,22 +736,25 @@ int main ( int argc, char **argv ) std::cout << " ... XYZ: " << symAxes.at(axIt)[1] << " ; " << symAxes.at(axIt)[2] << " ; " << symAxes.at(axIt)[3] << std::endl; std::cout << " ... Angle (radians): " << symAxes.at(axIt)[4] << std::endl; std::cout << " ... Axis peak: " << symAxes.at(axIt)[5] << std::endl; + std::cout << " ... Averaged FSC: " << symAxes.at(axIt)[6] << std::endl; } //================================================ Find all C axes - std::vector < std::vector< proshade_double > > allCs = settings->allDetectedCAxes; + std::vector< proshade_double* > allCs = simpleSym->getCyclicAxesCopy ( ); std::cout << "Found total of " << allCs.size() << " cyclic symmetry axes." << std::endl; //================================================ Get group elements for the first axis (or any other axis) std::vector< proshade_unsign > axesList; axesList.emplace_back ( 0 ); - std::vector > groupElementsGrp0 = simpleSym->getAllGroupElements ( settings, axesList, "C" ); - std::cout << "Group 0 has fold of " << allCs.at(0)[0] << " and ProShade computed " << groupElementsGrp0.size() << " group element (including the identity one), the second being the rotation matrix:" << std::endl; - std::cout << groupElementsGrp0.at(1).at(0) << " x " << groupElementsGrp0.at(1).at(1) << " x " << groupElementsGrp0.at(1).at(2) << std::endl; - std::cout << groupElementsGrp0.at(1).at(3) << " x " << groupElementsGrp0.at(1).at(4) << " x " << groupElementsGrp0.at(1).at(5) << std::endl; - std::cout << groupElementsGrp0.at(1).at(6) << " x " << groupElementsGrp0.at(1).at(7) << " x " << groupElementsGrp0.at(1).at(8) << std::endl; + std::vector > groupElementsGrp0 = simpleSym->getAllGroupElements ( axesList, "C" ); + std::cout << "Group 0 has fold of " << allCs.at(0)[0] << " and ProShade computed " << groupElementsGrp0.size() << " group element (including the identity one), the first being the rotation matrix:" << std::endl; + std::cout << groupElementsGrp0.at(0).at(0) << " x " << groupElementsGrp0.at(0).at(1) << " x " << groupElementsGrp0.at(0).at(2) << std::endl; + std::cout << groupElementsGrp0.at(0).at(3) << " x " << groupElementsGrp0.at(0).at(4) << " x " << groupElementsGrp0.at(0).at(5) << std::endl; + std::cout << groupElementsGrp0.at(0).at(6) << " x " << groupElementsGrp0.at(0).at(7) << " x " << groupElementsGrp0.at(0).at(8) << std::endl; //================================================ Release the memory + for ( size_t aIt = 0; aIt < symAxes.size(); aIt++ ) { if ( symAxes.at( aIt ) != nullptr ) { delete[] symAxes.at( aIt ); symAxes.at( aIt ) = nullptr; } } + for ( size_t aIt = 0; aIt < allCs.size(); aIt++ ) { if ( allCs.at( aIt ) != nullptr ) { delete[] allCs.at( aIt ); allCs.at( aIt ) = nullptr; } } delete simpleSym; delete settings; diff --git a/proshade/CMakeLists.txt b/proshade/CMakeLists.txt index 0ef13bcd..68c07205 100644 --- a/proshade/CMakeLists.txt +++ b/proshade/CMakeLists.txt @@ -47,7 +47,7 @@ endif ( ${PRODUCE_PYTHON_BINDINGS} MATCHES 1 ) ########################################################################################## ################################### Set project name -project ( proshade VERSION 0.7.6.5 LANGUAGES CXX C ) +project ( proshade VERSION 0.7.6.6 LANGUAGES CXX C ) ########################################################################################## ################################### Force C++11 diff --git a/proshade/examples/libproshade/advancedAccess_symmetry.cpp b/proshade/examples/libproshade/advancedAccess_symmetry.cpp index 054f3750..5e640917 100644 --- a/proshade/examples/libproshade/advancedAccess_symmetry.cpp +++ b/proshade/examples/libproshade/advancedAccess_symmetry.cpp @@ -202,9 +202,9 @@ int main ( int argc, char **argv ) // requested point group. This is relatively simple for T, O and I symmetries, as such list is already produced by // ProSHADE - see the following examples: // - // std::vector > groupElements = symmetryStructure->getAllGroupElements ( settings, settings->allDetectedTAxes, "T" ); - // std::vector > groupElements = symmetryStructure->getAllGroupElements ( settings, settings->allDetectedOAxes, "O" ); - // std::vector > groupElements = symmetryStructure->getAllGroupElements ( settings, settings->allDetectedIAxes, "I" ); + // std::vector > groupElements = symmetryStructure->getAllGroupElements ( settings->allDetectedTAxes, "T" ); + // std::vector > groupElements = symmetryStructure->getAllGroupElements ( settings->allDetectedOAxes, "O" ); + // std::vector > groupElements = symmetryStructure->getAllGroupElements ( settings->allDetectedIAxes, "I" ); // // For C point groups, this is also simple, as one can select the required >index< from the allCs variable and use // diff --git a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py index b91096d7..aa25cd46 100644 --- a/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py +++ b/proshade/interfacedCodes/EMDA/symmetryPredictions/getMaskedSymmetryPredictions.py @@ -30,8 +30,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ###################################################### ###################################################### diff --git a/proshade/src/bin/bin.cpp b/proshade/src/bin/bin.cpp index 2ed4bca4..5782b218 100644 --- a/proshade/src/bin/bin.cpp +++ b/proshade/src/bin/bin.cpp @@ -27,7 +27,7 @@ /*! \mainpage ProSHADE Documentation * - * Protein Shape Description and Symmetry Detection version 0.7.6.5 (JUN 2022) + * Protein Shape Description and Symmetry Detection version 0.7.6.6 (JUL 2022) * * \section intro Introduction * @@ -301,7 +301,7 @@ * - This option is used to supply the path to the libfftw3.a/so/dylib in the case where ProSHADE CMake installation fails to detect the FFTW3 dependency. This is typically the case when FFTW3 is installed outside of the * standard FFTW3 installation locations. * - * \b -CUSTOM_FFTW3_INC_PATH=/path + * \b -DCUSTOM_FFTW3_INC_PATH=/path * - This option is used to supply the path to the fftw3.h file in the case where ProSHADE CMake installation fails to detect the FFTW3 dependency. This is typically the case when FFTW3 is installed outside of the * standard FFTW3 installation locations. * @@ -856,11 +856,10 @@ simpleSym->computeRotationFunction ( settings ); //================================================ Detect the recommended symmetry - std::vector< proshade_double* > symAxes; - std::vector< std::vector< proshade_double > > allCsFromSettings; - simpleSym->detectSymmetryInStructure ( settings, &symAxes, &allCsFromSettings ); - std::string symmetryType = simpleSym->getRecommendedSymmetryType ( ); - proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( ); + simpleSym->detectSymmetryFromAngleAxisSpace ( settings ); + std::string symmetryType = simpleSym->getRecommendedSymmetryType ( ); + proshade_unsign symmetryFold = simpleSym->getRecommendedSymmetryFold ( ); + std::vector< proshade_double* > symAxes = simpleSym->getRecommendedSymmetryValues ( ); //================================================ Write out the symmetry detection results std::cout << "Detected symmetry: " << symmetryType << "-" << symmetryFold << " with axes:" << std::endl; @@ -871,22 +870,25 @@ std::cout << " ... XYZ: " << symAxes.at(axIt)[1] << " ; " << symAxes.at(axIt)[2] << " ; " << symAxes.at(axIt)[3] << std::endl; std::cout << " ... Angle (radians): " << symAxes.at(axIt)[4] << std::endl; std::cout << " ... Axis peak: " << symAxes.at(axIt)[5] << std::endl; + std::cout << " ... Averaged FSC: " << symAxes.at(axIt)[6] << std::endl; } //================================================ Find all C axes - std::vector < std::vector< proshade_double > > allCs = settings->allDetectedCAxes; + std::vector< proshade_double* > allCs = simpleSym->getCyclicAxesCopy ( ); std::cout << "Found total of " << allCs.size() << " cyclic symmetry axes." << std::endl; //================================================ Get group elements for the first axis (or any other axis) std::vector< proshade_unsign > axesList; axesList.emplace_back ( 0 ); std::vector > groupElementsGrp0 = simpleSym->getAllGroupElements ( axesList, "C" ); - std::cout << "Group 0 has fold of " << allCs.at(0)[0] << " and ProShade computed " << groupElementsGrp0.size() << " group element (including the identity one), the second being the rotation matrix:" << std::endl; - std::cout << groupElementsGrp0.at(1).at(0) << " x " << groupElementsGrp0.at(1).at(1) << " x " << groupElementsGrp0.at(1).at(2) << std::endl; - std::cout << groupElementsGrp0.at(1).at(3) << " x " << groupElementsGrp0.at(1).at(4) << " x " << groupElementsGrp0.at(1).at(5) << std::endl; - std::cout << groupElementsGrp0.at(1).at(6) << " x " << groupElementsGrp0.at(1).at(7) << " x " << groupElementsGrp0.at(1).at(8) << std::endl; + std::cout << "Group 0 has fold of " << allCs.at(0)[0] << " and ProShade computed " << groupElementsGrp0.size() << " group element (including the identity one), the first being the rotation matrix:" << std::endl; + std::cout << groupElementsGrp0.at(0).at(0) << " x " << groupElementsGrp0.at(0).at(1) << " x " << groupElementsGrp0.at(0).at(2) << std::endl; + std::cout << groupElementsGrp0.at(0).at(3) << " x " << groupElementsGrp0.at(0).at(4) << " x " << groupElementsGrp0.at(0).at(5) << std::endl; + std::cout << groupElementsGrp0.at(0).at(6) << " x " << groupElementsGrp0.at(0).at(7) << " x " << groupElementsGrp0.at(0).at(8) << std::endl; //================================================ Release the memory + for ( size_t aIt = 0; aIt < symAxes.size(); aIt++ ) { if ( symAxes.at( aIt ) != nullptr ) { delete[] symAxes.at( aIt ); symAxes.at( aIt ) = nullptr; } } + for ( size_t aIt = 0; aIt < allCs.size(); aIt++ ) { if ( allCs.at( aIt ) != nullptr ) { delete[] allCs.at( aIt ); allCs.at( aIt ) = nullptr; } } delete simpleSym; delete settings; diff --git a/setup.py b/setup.py index 775596ce..b0ca1a41 100644 --- a/setup.py +++ b/setup.py @@ -18,8 +18,8 @@ # # \author Michal Tykac # \author Garib N. Murshudov -# \version 0.7.6.5 -# \date JUN 2022 +# \version 0.7.6.6 +# \date JUL 2022 ############################################## ############################################## @@ -28,7 +28,7 @@ ##### Global settings ########################################################################################## ########################################################################################## -gl_version = '0.7.6.5' +gl_version = '0.7.6.6' gl_download = 'https://github.com/michaltykac/proshade/archive/v{0}.tar.gz'.format(gl_version)