diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h index c9c3cd1f3aa0..db10392f9a8e 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/ConnectedComponentLabeling.h @@ -10,6 +10,12 @@ namespace Mantid { + +namespace API +{ + class Progress; +} + namespace Crystal { namespace ConnectedComponentMappingTypes @@ -58,12 +64,13 @@ namespace Crystal void startLabelingId(const size_t& id); /// Execute and return clusters - boost::shared_ptr execute(Mantid::API::IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy) const; + boost::shared_ptr execute(Mantid::API::IMDHistoWorkspace_sptr ws, + BackgroundStrategy * const strategy, Mantid::API::Progress& progress) const; /// Execute and return clusters, as well as maps to integrated label values boost::shared_ptr executeAndIntegrate( Mantid::API::IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, ConnectedComponentMappingTypes::LabelIdIntensityMap& labelMap, - ConnectedComponentMappingTypes::PositionToLabelIdMap& positionLabelMap) const; + ConnectedComponentMappingTypes::PositionToLabelIdMap& positionLabelMap, Mantid::API::Progress& progress) const; /// Destructor virtual ~ConnectedComponentLabeling(); @@ -74,7 +81,8 @@ namespace Crystal void calculateDisjointTree(Mantid::API::IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, std::vector& neighbourElements, ConnectedComponentMappingTypes::LabelIdIntensityMap& labelMap, - ConnectedComponentMappingTypes::PositionToLabelIdMap& positionLabelMap) const; + ConnectedComponentMappingTypes::PositionToLabelIdMap& positionLabelMap, + Mantid::API::Progress& progress) const; /// Start labeling index size_t m_startId; diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h index a6a59b66ccdd..0b28badf01e6 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/DisjointElement.h @@ -57,6 +57,17 @@ namespace Crystal DisjointElement(const DisjointElement& other); /// Assignment operator. DisjointElement& operator=(const DisjointElement& other); + /// Less than + inline bool operator<(const DisjointElement& other) const + { + return m_id < other.getId(); + } + /// Greater than + inline bool operator>(const DisjointElement& other) const + { + return m_id > other.getId(); + } + private: bool hasParent() const; int compress(); diff --git a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h index 0c5ed1678e41..97027b7fdaa3 100644 --- a/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h +++ b/Code/Mantid/Framework/Crystal/inc/MantidCrystal/PeakBackground.h @@ -2,15 +2,21 @@ #define MANTID_CRYSTAL_PEAKBACKGROUND_H_ #include "MantidKernel/System.h" +#include "MantidKernel/V3D.h" #include "MantidAPI/IPeaksWorkspace.h" #include "MantidAPI/IMDIterator.h" #include "MantidAPI/IMDWorkspace.h" #include "MantidCrystal/HardThresholdBackground.h" +#include namespace Mantid { +namespace API +{ + class IPeak; +} namespace Crystal { @@ -48,6 +54,8 @@ namespace Crystal double m_radiusEstimate; /// MD coordinates to use Mantid::API::SpecialCoordinateSystem m_mdCoordinates; + /// Pointer to member function used for coordinate determination. + boost::function m_coordFunction; public: /// Constructor diff --git a/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp b/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp index fa44db8a159c..332fc16e3024 100644 --- a/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp +++ b/Code/Mantid/Framework/Crystal/src/ConnectedComponentLabeling.cpp @@ -1,9 +1,10 @@ #include "MantidKernel/MultiThreaded.h" #include "MantidKernel/V3D.h" -#include "MantidAPI/IMDHistoWorkspace.h" #include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/IMDHistoWorkspace.h" #include "MantidAPI/IMDIterator.h" +#include "MantidAPI/Progress.h" #include "MantidCrystal/ConnectedComponentLabeling.h" #include "MantidCrystal/BackgroundStrategy.h" #include "MantidCrystal/DisjointElement.h" @@ -12,6 +13,10 @@ #include #include #include +#include +#include + + using namespace Mantid::API; using namespace Mantid::Kernel; @@ -50,6 +55,17 @@ namespace Mantid } return outWS; } + + template + T reportEvery(const T& maxReports, const T& maxIterations) + { + T frequency = maxReports; + if (maxIterations >= maxReports) + { + frequency = maxIterations/maxReports; + } + return frequency; + } } //---------------------------------------------------------------------------------------------- @@ -93,18 +109,21 @@ namespace Mantid void ConnectedComponentLabeling::calculateDisjointTree(IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, VecElements& neighbourElements, LabelIdIntensityMap& labelMap, - PositionToLabelIdMap& positionLabelMap + PositionToLabelIdMap& positionLabelMap, + Progress& progress ) const { VecIndexes allNonBackgroundIndexes; allNonBackgroundIndexes.reserve(ws->getNPoints()); + progress.doReport("Pre-processing to filter background out"); + const size_t nPoints = ws->getNPoints(); + progress.resetNumSteps(10000, 0.0, 0.25); if(m_runMultiThreaded) { - std::vector iterators = ws->createIterators(getNThreads()); - const int nthreads = static_cast(iterators.size()); + const int nthreads = getNThreads(); std::vector manyNonBackgroundIndexes(nthreads); PARALLEL_FOR_NO_WSP_CHECK() @@ -118,6 +137,7 @@ namespace Mantid if(!strategyCopy->isBackground(iterator)) { nonBackgroundIndexes.push_back( iterator->getLinearIndex() ); + progress.report(); } } while(iterator->next()); @@ -131,23 +151,36 @@ namespace Mantid } else { + progress.resetNumSteps(1, 0.0, 0.5); API::IMDIterator *iterator = ws->createIterator(NULL); do { if(!strategy->isBackground(iterator)) { allNonBackgroundIndexes.push_back( iterator->getLinearIndex() ); + progress.report(); } + } while(iterator->next()); } // -------- Perform labeling ----------- + progress.doReport("Perform connected component labeling"); + const size_t maxNeighbours = calculateMaxNeighbours(ws.get()); IMDIterator* iterator = ws->createIterator(NULL); size_t currentLabelCount = m_startId; - for(size_t ii = 0; ii < allNonBackgroundIndexes.size(); ++ii) + const size_t nIndexesToProcess= allNonBackgroundIndexes.size(); + const size_t maxReports = 100; + const size_t frequency = reportEvery(maxReports, nIndexesToProcess); + progress.resetNumSteps(100, 0.25, 0.5); + for(size_t ii = 0; ii < nIndexesToProcess ; ++ii) { + if(ii % frequency == 0) + { + progress.doReport(); + } size_t& currentIndex = allNonBackgroundIndexes[ii]; iterator->jumpTo(currentIndex); @@ -184,17 +217,10 @@ namespace Mantid else { // Choose the lowest neighbour index as the parent. - size_t parentIndex = nonEmptyNeighbourIndexes[0]; - for (size_t i = 1; i < nonEmptyNeighbourIndexes.size(); ++i) - { - size_t neighIndex = nonEmptyNeighbourIndexes[i]; - if (neighbourElements[neighIndex].getId() < neighbourElements[parentIndex].getId()) - { - parentIndex = i; - } - } + const VecElements::iterator& minIt = std::min_element(neighbourElements.begin(), neighbourElements.end()); + const size_t& parentIndex = std::distance(neighbourElements.begin(), minIt); // Get the chosen parent - DisjointElement& parentElement = neighbourElements[parentIndex]; + DisjointElement& parentElement = *minIt; // Make this element a copy of the parent neighbourElements[currentIndex] = parentElement; // Union remainder parents with the chosen parent @@ -213,32 +239,36 @@ namespace Mantid } boost::shared_ptr ConnectedComponentLabeling::execute( - IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy) const + IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, Progress& progress) const { VecElements neighbourElements(ws->getNPoints()); // Perform the bulk of the connected component analysis, but don't collapse the elements yet. LabelIdIntensityMap labelMap; // This will not get used. PositionToLabelIdMap positionLabelMap; // This will not get used. - calculateDisjointTree(ws, strategy, neighbourElements, labelMap, positionLabelMap); + calculateDisjointTree(ws, strategy, neighbourElements, labelMap, positionLabelMap, progress); // Create the output workspace from the input workspace IMDHistoWorkspace_sptr outWS = cloneInputWorkspace(ws); + progress.doReport("Generating cluster image"); + const int nIndexesToProcess = static_cast(neighbourElements.size()); + progress.resetNumSteps(nIndexesToProcess, 0.5, 0.75); // Set each pixel to the root of each disjointed element. PARALLEL_FOR_NO_WSP_CHECK() - for (int i = 0; i < static_cast(neighbourElements.size()); ++i) + for (int i = 0; i < nIndexesToProcess; ++i) { - //std::cout << "Element\t" << i << " Id: \t" << neighbourElements[i].getId() << " This location:\t"<< &neighbourElements[i] << " Root location:\t" << neighbourElements[i].getParent() << " Root Id:\t" << neighbourElements[i].getRoot() << std::endl; if(!neighbourElements[i].isEmpty()) { outWS->setSignalAt(i, neighbourElements[i].getRoot()); + progress.doReport(); } else { outWS->setSignalAt(i, 0); } outWS->setErrorSquaredAt(i, 0); + } return outWS; @@ -246,18 +276,23 @@ namespace Mantid boost::shared_ptr ConnectedComponentLabeling::executeAndIntegrate( IMDHistoWorkspace_sptr ws, BackgroundStrategy * const strategy, LabelIdIntensityMap& labelMap, - PositionToLabelIdMap& positionLabelMap) const + PositionToLabelIdMap& positionLabelMap, Progress& progress) const { VecElements neighbourElements(ws->getNPoints()); // Perform the bulk of the connected component analysis, but don't collapse the elements yet. - calculateDisjointTree(ws, strategy, neighbourElements, labelMap, positionLabelMap); + calculateDisjointTree(ws, strategy, neighbourElements, labelMap, positionLabelMap, progress); // Create the output workspace from the input workspace IMDHistoWorkspace_sptr outWS = cloneInputWorkspace(ws); + progress.doReport("Integrating clusters and generating cluster image"); + const size_t nIterations = neighbourElements.size(); + const size_t maxReports = 100; + const size_t frequency = reportEvery(maxReports, nIterations); + progress.resetNumSteps(maxReports, 0.5, 0.75); // Set each pixel to the root of each disjointed element. - for (size_t i = 0; i < neighbourElements.size(); ++i) + for (size_t i = 0; i < nIterations; ++i) { if(!neighbourElements[i].isEmpty()) { @@ -266,7 +301,7 @@ namespace Mantid errorSQ *=errorSQ; // Error squared at index const size_t& labelId = neighbourElements[i].getRoot(); // Set the output cluster workspace signal value - outWS->setSignalAt(i, labelId); + outWS->setSignalAt(i, static_cast(labelId)); SignalErrorSQPair current = labelMap[labelId]; // Sum labels. This is integration! @@ -279,6 +314,10 @@ namespace Mantid outWS->setSignalAt(i, 0); } outWS->setErrorSquaredAt(i, 0); + if(i % frequency == 0) + { + progress.doReport(); + } } return outWS; diff --git a/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp b/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp index c5e314c0287f..c9ff2872015d 100644 --- a/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp +++ b/Code/Mantid/Framework/Crystal/src/IntegratePeaksUsingClusters.cpp @@ -1,7 +1,15 @@ /*WIKI* -Handles integration of arbitary single crystal peaks shapes. +Integrates arbitary shaped single crystal peaks defined on an [[MDHistoWorkspace]] using connected component analysis to determine +regions of interest around each peak of the [[PeaksWorkspace]]. The output is an integrated [[PeaksWorkspace]] as well as an image +containing the labels assigned to each cluster for diagnostic and visualisation purposes. -Uses connected component analysis to integrate peaks in an PeaksWorkspace over an MDHistoWorkspace of data. +A threshold for the Peak should be defined below which, parts of the image are treated as background. In addition, a radius estimate +is required to dispose of those clusters which are not to do with peaks, and also to associate clusters in the image with a peak center. +You can view the radius estimate as a radius cut-off. + +This algorithm uses an imaging technique, and it is therefore important that the MDHistoWorkspace you are using is binned to a sufficient +resolution via [[BinMD]]. You can overlay the intergrated peaks workspace in the [[MantidPlot:_SliceViewer#Viewing_Peaks_Workspaces|Slice Viewer]] over +the generated Cluster Labeled OutputWorkspaceMD to see what the interation region used for each peak amounts to. *WIKI*/ #include "MantidCrystal/IntegratePeaksUsingClusters.h" @@ -11,6 +19,7 @@ Uses connected component analysis to integrate peaks in an PeaksWorkspace over a #include "MantidAPI/WorkspaceProperty.h" #include "MantidAPI/IMDIterator.h" #include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/Progress.h" #include "MantidKernel/MultiThreaded.h" #include "MantidKernel/CompositeValidator.h" #include "MantidKernel/MandatoryValidator.h" @@ -110,7 +119,7 @@ namespace Mantid declareProperty(new PropertyWithValue("Threshold", 0, positiveValidator->clone(), Direction::Input), "Threshold signal above which to consider peaks"); declareProperty(new WorkspaceProperty("OutputWorkspace","",Direction::Output), "An output integrated peaks workspace."); - declareProperty(new WorkspaceProperty("OutputWorkspaceMD","",Direction::Output), "MDHistoWorkspace containing the clusters."); + declareProperty(new WorkspaceProperty("OutputWorkspaceMD","",Direction::Output), "MDHistoWorkspace containing the labeled clusters used by the algorithm."); } //---------------------------------------------------------------------------------------------- @@ -141,17 +150,21 @@ namespace Mantid const double threshold = getProperty("Threshold"); const double radiusEstimate = getProperty("RadiusEstimate"); - PeakBackground background(peakWS, radiusEstimate, threshold, NoNormalization, mdCoordinates); - //HardThresholdBackground background(threshold, normalization); + PeakBackground backgroundStrategy(peakWS, radiusEstimate, threshold, NoNormalization, mdCoordinates); ConnectedComponentLabeling analysis; LabelIdIntensityMap labelMap; PositionToLabelIdMap positionMap; - IMDHistoWorkspace_sptr clusters = analysis.executeAndIntegrate(mdWS, &background, labelMap, positionMap); + + Progress progress(this, 0, 1, 1); + IMDHistoWorkspace_sptr clusters = analysis.executeAndIntegrate(mdWS, &backgroundStrategy, labelMap, positionMap, progress); // Link integrated values up with peaks. + const size_t nPeaks = peakWS->getNumberPeaks(); + progress.resetNumSteps(nPeaks, 0, 1); + progress.doReport("Writing out PeaksWorkspace"); PARALLEL_FOR1(peakWS) - for(int i =0; i < peakWS->getNumberPeaks(); ++i) + for(int i =0; i < nPeaks; ++i) { PARALLEL_START_INTERUPT_REGION IPeak& peak = peakWS->getPeak(i); @@ -179,6 +192,7 @@ namespace Mantid peak.setIntensity(labelMap[ iterator->second ].get<0>()); peak.setSigmaIntensity(labelMap[ iterator->second ].get<1>()); } + progress.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION diff --git a/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp b/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp index 6dd3ccfba4c5..4c935e4e851c 100644 --- a/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp +++ b/Code/Mantid/Framework/Crystal/src/PeakBackground.cpp @@ -1,5 +1,7 @@ #include "MantidCrystal/PeakBackground.h" #include "MantidAPI/IPeak.h" +#include +#include using namespace Mantid::API; using namespace Mantid::Kernel; @@ -17,10 +19,28 @@ namespace Mantid PeakBackground::PeakBackground(IPeaksWorkspace_const_sptr peaksWS, const double& radiusEstimate, const double& thresholdSignal, const Mantid::API::MDNormalization normalisation, const SpecialCoordinateSystem coordinates) : HardThresholdBackground(thresholdSignal, normalisation), m_peaksWS(peaksWS), m_radiusEstimate(radiusEstimate), m_mdCoordinates(coordinates) { + + if(m_mdCoordinates==QLab) + { + m_coordFunction = &IPeak::getQLabFrame; + } + else if(m_mdCoordinates==QSample) + { + m_coordFunction = &IPeak::getQSampleFrame; + } + else if(m_mdCoordinates==Mantid::API::HKL) + { + m_coordFunction = &IPeak::getHKL; + } + else + { + throw std::invalid_argument("Unknown CoordinateSystem provided to PeakBackground"); + } } PeakBackground::PeakBackground(const PeakBackground& other) - : HardThresholdBackground(other), m_peaksWS(other.m_peaksWS), m_radiusEstimate(other.m_radiusEstimate), m_mdCoordinates(other.m_mdCoordinates) + : HardThresholdBackground(other), m_peaksWS(other.m_peaksWS), m_radiusEstimate(other.m_radiusEstimate) + , m_mdCoordinates(other.m_mdCoordinates), m_coordFunction(other.m_coordFunction) { } @@ -32,6 +52,7 @@ namespace Mantid m_peaksWS = other.m_peaksWS; m_radiusEstimate = other.m_radiusEstimate; m_mdCoordinates = other.m_mdCoordinates; + m_coordFunction = other.m_coordFunction; } return *this; } @@ -59,19 +80,8 @@ namespace Mantid for(int i = 0; i < m_peaksWS->getNumberPeaks(); ++i) { - V3D coords; - if(m_mdCoordinates==QLab) - { - coords= m_peaksWS->getPeak(i).getQLabFrame(); - } - else if(m_mdCoordinates==QSample) - { - coords= m_peaksWS->getPeak(i).getQSampleFrame(); - } - else if(m_mdCoordinates==Mantid::API::HKL) - { - coords= m_peaksWS->getPeak(i).getHKL(); - } + const IPeak& peak = m_peaksWS->getPeak(i); + V3D coords = m_coordFunction(&peak); if(coords.distance(temp) < m_radiusEstimate) { return false; diff --git a/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h b/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h index f63b8d2354dd..0311f9eb19c7 100644 --- a/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h +++ b/Code/Mantid/Framework/Crystal/test/ConnectedComponentLabelingTest.h @@ -10,6 +10,7 @@ #include "MantidAPI/IMDIterator.h" #include "MantidAPI/FrameworkManager.h" +#include "MantidAPI/Progress.h" #include "MantidCrystal/ConnectedComponentLabeling.h" #include "MantidCrystal/BackgroundStrategy.h" #include "MantidCrystal/HardThresholdBackground.h" @@ -110,7 +111,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite ConnectedComponentLabeling ccl(labelingId, multiThreaded); ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); auto uniqueValues = connection_workspace_to_set_of_labels(outWS.get()); TS_ASSERT_EQUALS(1, uniqueValues.size()); @@ -129,7 +131,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 2; bool multiThreaded = false; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); /* * Because all the signal values are identical, and none are below any threshold. We assume that there will only be a single component. All @@ -159,8 +162,9 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 1; bool multiThreaded = false; + Progress prog; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &mockStrategy); + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("2 objects so should have 3 unique entries", 3, uniqueEntries.size()); @@ -190,7 +194,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 1; bool multiThreaded = false; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("3 objects so should have 4 unique entries", 4, uniqueEntries.size()); @@ -212,7 +217,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 1; bool multiThreaded = false; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("Just one object", 1, uniqueEntries.size()); @@ -243,7 +249,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 1; bool multiThreaded = false; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("Just one object, but we have some 'empty' entries too", 2, uniqueEntries.size()); @@ -275,7 +282,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 1; bool multiThreaded = false; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &mockStrategy); + Progress prog; + auto outWS = ccl.execute(inWS, &mockStrategy, prog); std::set uniqueEntries = connection_workspace_to_set_of_labels(outWS.get()); TSM_ASSERT_EQUALS("Just one object, but we have some 'empty' entries too", 2, uniqueEntries.size()); @@ -335,7 +343,8 @@ class ConnectedComponentLabelingTest: public CxxTest::TestSuite size_t labelingId = 1; bool multiThreaded = false; ConnectedComponentLabeling ccl(labelingId, multiThreaded); - auto outWS = ccl.execute(inWS, &strategy); + Progress prog; + auto outWS = ccl.execute(inWS, &strategy, prog); // ----------- Basic cluster checks @@ -419,7 +428,8 @@ class ConnectedComponentLabelingTestPerformance: public CxxTest::TestSuite ConnectedComponentLabeling ccl; size_t labelingId = 1; ccl.startLabelingId(labelingId); - auto outWS = ccl.execute(m_inWS, m_backgroundStrategy.get()); + Progress prog; + auto outWS = ccl.execute(m_inWS, m_backgroundStrategy.get(), prog); // ----------- Basic cluster checks