From 4eab409cfdd73cfbdfcba5c88d2ff36e076ee881 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Tue, 29 Aug 2023 15:46:09 +0200 Subject: [PATCH 01/17] Uniform lighting model handles negative cross section (sigma). --- src/dataanalytics/HDA_SimStepRecorder.cpp | 30 ++++++++++++++++------- src/main/helios_version.cpp | 2 +- src/scanner/ScanningDevice.cpp | 15 +++++++++--- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/dataanalytics/HDA_SimStepRecorder.cpp b/src/dataanalytics/HDA_SimStepRecorder.cpp index 9f164ea07..fc37c1e46 100644 --- a/src/dataanalytics/HDA_SimStepRecorder.cpp +++ b/src/dataanalytics/HDA_SimStepRecorder.cpp @@ -326,9 +326,16 @@ void HDA_SimStepRecorder::recordScanner(){ scannerPositionZ->push(pos.z); // Record scanner angles double roll, pitch, yaw; - s.getHeadRelativeEmitterAttitude().getAngles( - &RotationOrder::XYZ, roll, pitch, yaw - ); + try { + s.getHeadRelativeEmitterAttitude().getAngles( + &RotationOrder::XYZ, roll, pitch, yaw + ); + } + catch(HeliosException &hex){ + roll = std::numeric_limits::quiet_NaN(); + pitch = std::numeric_limits::quiet_NaN(); + yaw = std::numeric_limits::quiet_NaN(); + } scannerRoll->push(roll); scannerPitch->push(pitch); scannerYaw->push(yaw); @@ -398,15 +405,18 @@ void HDA_SimStepRecorder::recordStochastic(){ // Obtain parallel randomness generator RandomnessGenerator *rg1Par = nullptr; + size_t nthreads = 0; WarehouseScanningPulseProcess * wspp = dynamic_cast(spp); if(wspp != nullptr){ rg1Par = wspp->pool.randGens; + nthreads = wspp->pool.getPoolSize(); } else{ BuddingScanningPulseProcess *bspp = dynamic_cast(spp); rg1Par = bspp->pool.randGens; + nthreads = wspp->pool.getPoolSize(); } // Prepare fake pulse @@ -434,12 +444,14 @@ void HDA_SimStepRecorder::recordStochastic(){ } // Record parallel measurement error - for(size_t i = 0 ; i < N_SAMPLES ; ++i) { - err = ERR_BASE; - fwpr.applyMeasurementError( - *rg1Par, err, fakePulse.getOriginRef(), fakePulse.getOriginRef() - ); - measErrPar->push(err-ERR_BASE); + if(nthreads > 0) { // There is no parallelism for empty thread pools + for (size_t i = 0; i < N_SAMPLES; ++i) { + err = ERR_BASE; + fwpr.applyMeasurementError( + *rg1Par, err, fakePulse.getOriginRef(), fakePulse.getOriginRef() + ); + measErrPar->push(err - ERR_BASE); + } } diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index 1d7f655bb..85cad96ce 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "03b19a3a"; +const char * HELIOS_GIT_HASH = "a3909937"; const char * getHeliosVersion(){ return HELIOS_VERSION; diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index b39356ec3..085196463 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -323,19 +323,29 @@ double ScanningDevice::calcIntensity( double const targetArea, double const radius ) const { - double bdrf = 0; + double bdrf = 0, sigma = 0; if(mat.isPhong()) { bdrf = mat.reflectance * EnergyMaths::phongBDRF( incidenceAngle, mat.specularity, mat.specularExponent ); + sigma = EnergyMaths::calcCrossSection( + bdrf, targetArea, incidenceAngle + ); } else if(mat.isLambert()){ bdrf = mat.reflectance * std::cos(incidenceAngle); + sigma = EnergyMaths::calcCrossSection( + bdrf, targetArea, incidenceAngle + ); } else if(mat.isUniform()){ bdrf = mat.reflectance; + sigma = EnergyMaths::calcCrossSection( + bdrf, targetArea, incidenceAngle + ); + if(sigma < 0) sigma = -sigma; } else{ std::stringstream ss; @@ -343,9 +353,6 @@ double ScanningDevice::calcIntensity( << mat.name << "\""; logging::ERR(ss.str()); } - double const sigma = EnergyMaths::calcCrossSection( - bdrf, targetArea, incidenceAngle - ); return EnergyMaths::calcReceivedPower( averagePower_w, wavelength_m, From 9f5ba7f67eadca32879058f1f6a45a8fcf30fcbc Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Mon, 18 Sep 2023 15:40:22 +0200 Subject: [PATCH 02/17] Extended HDA with PulseRecorder --- src/dataanalytics/HDA_PulseRecorder.cpp | 35 ++++++++ src/dataanalytics/HDA_PulseRecorder.h | 82 +++++++++++++++++++ src/dataanalytics/HDA_Recorder.cpp | 36 ++++++++ src/dataanalytics/HDA_Recorder.h | 61 ++++++++++++++ src/dataanalytics/HDA_SimStepRecorder.cpp | 23 +----- src/dataanalytics/HDA_SimStepRecorder.h | 40 +++------ src/main/helios_version.cpp | 2 +- src/scanner/BuddingScanningPulseProcess.cpp | 18 ++++ src/scanner/BuddingScanningPulseProcess.h | 9 ++ src/scanner/Scanner.cpp | 6 ++ src/scanner/WarehouseScanningPulseProcess.cpp | 26 +++++- src/scanner/WarehouseScanningPulseProcess.h | 12 +++ .../detector/FullWaveformPulseRunnable.cpp | 20 ++++- .../detector/FullWaveformPulseRunnable.h | 12 +++ src/scanner/detector/PulseTask.h | 7 ++ src/scanner/detector/PulseTaskDropper.h | 16 ++++ src/scanner/detector/PulseThreadPool.h | 46 +++++++++++ .../detector/PulseThreadPoolInterface.h | 20 +++++ .../detector/PulseWarehouseThreadPool.h | 35 ++++++++ 19 files changed, 449 insertions(+), 57 deletions(-) create mode 100644 src/dataanalytics/HDA_PulseRecorder.cpp create mode 100644 src/dataanalytics/HDA_PulseRecorder.h create mode 100644 src/dataanalytics/HDA_Recorder.cpp create mode 100644 src/dataanalytics/HDA_Recorder.h diff --git a/src/dataanalytics/HDA_PulseRecorder.cpp b/src/dataanalytics/HDA_PulseRecorder.cpp new file mode 100644 index 000000000..53981ab78 --- /dev/null +++ b/src/dataanalytics/HDA_PulseRecorder.cpp @@ -0,0 +1,35 @@ +#ifdef DATA_ANALYTICS +#include + +using namespace helios::analytics; + + +// *** RECORDER METHODS *** // +// ************************** // +bool HDA_PulseRecorder::isAnyBufferOpen(){ + bool anyOpen = false; + anyOpen |= incidenceAngle_rad->isOpen(); + return anyOpen; +} + +void HDA_PulseRecorder::openBuffers(){ + // Open subray related buffers + incidenceAngle_rad = std::make_shared>( + craftOutputPath("incidence_angle_rad.csv") + ); +} + +void HDA_PulseRecorder::closeBuffers(){ + // Close subray buffers + incidenceAngle_rad->close(); +} + + +// *** RECORD METHODS *** // +// ************************ // +void HDA_PulseRecorder::recordIncidenceAngle(double const _incidenceAngle_rad){ + std::unique_lock lock(incidenceAngle_rad_mutex); + incidenceAngle_rad->push(_incidenceAngle_rad); +} + +#endif diff --git a/src/dataanalytics/HDA_PulseRecorder.h b/src/dataanalytics/HDA_PulseRecorder.h new file mode 100644 index 000000000..e3b9a792f --- /dev/null +++ b/src/dataanalytics/HDA_PulseRecorder.h @@ -0,0 +1,82 @@ +#ifdef DATA_ANALYTICS +#pragma once + +#include +#include + +#include +#include +#include + +namespace helios { namespace analytics{ + +/** + * @author Alberto M. Esmoris Pena + * @version 1.0 + * @brief The HeliosDataAnalytics recorder for pulses (more concretely, pulse + * tasks / runnables). It is a class which records relevant data from the + * many pulse computations. + * @see FullWaveformPulseRunnable + */ +class HDA_PulseRecorder : public HDA_Recorder{ +protected: + // *** ATTRIBUTES *** // + // ******************** // + /** + * @brief The record buffer for the incidence angles (in radians). + */ + std::shared_ptr> incidenceAngle_rad; + /** + * @brief The mutex to handle concurrent writes to the incidenceAngle_rad + * record buffer. + */ + std::mutex incidenceAngle_rad_mutex; + +public: + // *** CONSTRUCTION / DESTRUCTION *** // + // ************************************ // + /** + * @brief Build a HDA_PulseRecorder so pulse computations are written to + * data files in the directory specified through given path. + * @param path Path of the directory where simulation records will be + * written. + */ + HDA_PulseRecorder(std::string const &path) : HDA_Recorder(path){ + openBuffers(); + } + + virtual ~HDA_PulseRecorder() { + if(isAnyBufferOpen()) closeBuffers(); + } + + // *** RECORDER METHODS *** // + // ************************** // + /** + * @brief Check whether there are opened buffers or not + * @return True if there is at least one opened buffer, false if there is + * not even a single opened buffer + */ + bool isAnyBufferOpen(); + /** + * @brief Open all the record buffers so the HDA_SimStepRecord can record + */ + void openBuffers(); + /** + * @brief Close all the record buffers. Once it is done, the + * HDA_SimStepRecorder will not be able to properly handle any new + * record. + */ + void closeBuffers(); + + + // *** RECORD METHODS *** // + // ************************ // + /** + * @brief Handle all the records for the current simulation step. + */ + virtual void recordIncidenceAngle(double const incidenceAngle_rad); + +}; + +}} +#endif \ No newline at end of file diff --git a/src/dataanalytics/HDA_Recorder.cpp b/src/dataanalytics/HDA_Recorder.cpp new file mode 100644 index 000000000..3618c668c --- /dev/null +++ b/src/dataanalytics/HDA_Recorder.cpp @@ -0,0 +1,36 @@ +#ifdef DATA_ANALYTICS + +#include +#include + +#include + +#include + + +using namespace helios::analytics; + +// *** RECORDER METHODS *** // +// ************************** // +void HDA_Recorder::validateOutDir(){ + // Check directory exists + if(!boost::filesystem::exists(outdir)){ + if(!boost::filesystem::create_directory(outdir)){ + std::stringstream ss; + ss << "HDA_SimStepRecorder::validateOutDir thrown an exception " + << "because the output directory does not exist and cannot be" + << "created.\noutdir: \"" << outdir << "\""; + throw HeliosException(ss.str()); + } + } +} + +std::string HDA_Recorder::craftOutputPath(std::string const &fname){ + std::stringstream ss; + ss << outdir + << boost::filesystem::path::preferred_separator + << fname; + return ss.str(); +} + +#endif diff --git a/src/dataanalytics/HDA_Recorder.h b/src/dataanalytics/HDA_Recorder.h new file mode 100644 index 000000000..dc51e69fa --- /dev/null +++ b/src/dataanalytics/HDA_Recorder.h @@ -0,0 +1,61 @@ +#ifdef DATA_ANALYTICS +#pragma once + +#include + +namespace helios { namespace analytics{ + +/** + * @author Alberto M. Esmoris Pena + * @version 1.0 + * @brief The HeliosDataAnalytics abstract recorder. It is, an abstract class + * that handle only the common baseline logic for any recorder. + */ +class HDA_Recorder{ +protected: + // *** ATTRIBUTES *** // + // ******************** // + /** + * @brief Path to the output directory where the different outputs will be + * stored + */ + std::string outdir; + + // *** CONSTRUCTION / DESTRUCTION *** // + // ************************************ // + /** + * @brief Build a HDA_Recorder to write data files inside given output + * directory. + * @param path Path to the output directory. + */ + HDA_Recorder(std::string const &path) : outdir(path) { + validateOutDir(); + } + + virtual ~HDA_Recorder(){} + + // *** RECORDER METHODS *** // + // ************************** // + /** + * @brief Check whether the output directory is a valid one or not. If not, + * an exception will be thrown. + * + * This method can be overriden by derived classes when necessary, but it + * is not a must. + */ + virtual void validateOutDir(); + + /** + * @brief Craft the full output path considering the output directory and + * the given file name + * @param fname The given filename + * @return Full output path considering the output directory and the given + * file name + */ + virtual std::string craftOutputPath(std::string const &fname); + +}; + +}} + +#endif \ No newline at end of file diff --git a/src/dataanalytics/HDA_SimStepRecorder.cpp b/src/dataanalytics/HDA_SimStepRecorder.cpp index fc37c1e46..cd8a174e4 100644 --- a/src/dataanalytics/HDA_SimStepRecorder.cpp +++ b/src/dataanalytics/HDA_SimStepRecorder.cpp @@ -34,21 +34,9 @@ void HDA_SimStepRecorder::delayedRecord(){ recordStochastic(); } + // *** RECORDER METHODS *** // // ************************** // -void HDA_SimStepRecorder::validateOutDir(){ - // Check directory exists - if(!boost::filesystem::exists(outdir)){ - if(!boost::filesystem::create_directory(outdir)){ - std::stringstream ss; - ss << "HDA_SimStepRecorder::validateOutDir thrown an exception " - << "because the output directory does not exist and cannot be" - << "created.\noutdir: \"" << outdir << "\""; - throw HeliosException(ss.str()); - } - } -} - bool HDA_SimStepRecorder::isAnyBufferOpen(){ bool anyOpen = false; anyOpen |= platformPositionX->isOpen(); @@ -453,16 +441,7 @@ void HDA_SimStepRecorder::recordStochastic(){ measErrPar->push(err - ERR_BASE); } } - - } -std::string HDA_SimStepRecorder::craftOutputPath(std::string const &fname){ - std::stringstream ss; - ss << outdir - << boost::filesystem::path::preferred_separator - << fname; - return ss.str(); -} #endif \ No newline at end of file diff --git a/src/dataanalytics/HDA_SimStepRecorder.h b/src/dataanalytics/HDA_SimStepRecorder.h index d2e474d21..fcb15a0a3 100644 --- a/src/dataanalytics/HDA_SimStepRecorder.h +++ b/src/dataanalytics/HDA_SimStepRecorder.h @@ -1,6 +1,7 @@ #ifdef DATA_ANALYTICS #pragma once +#include #include #include @@ -16,7 +17,7 @@ namespace helios { namespace analytics{ * which records the data representing the state of simulation components at * a certain simulation step. */ -class HDA_SimStepRecorder{ +class HDA_SimStepRecorder : public HDA_Recorder { protected: // *** ATTRIBUTES *** // // ******************** // @@ -24,11 +25,6 @@ class HDA_SimStepRecorder{ * @brief The SurveyPlayback which simulation steps must be recorded */ SurveyPlayback *sp; - /** - * @brief Path to the output directory where the different outputs will be - * stored - */ - std::string outdir; /** * @brief The record buffer for the x coordinate of the platform position */ @@ -198,23 +194,20 @@ class HDA_SimStepRecorder{ SurveyPlayback *sp, std::string const &path ) : - sp(sp), - outdir(path) + HDA_Recorder(path), + sp(sp) { - validateOutDir(); openBuffers(); } virtual ~HDA_SimStepRecorder() { - if(isAnyBufferOpen()){ - closeBuffers(); - } + if(isAnyBufferOpen()) closeBuffers(); } // *** MAIN RECORD METHOD *** // // **************************** // /** - * @brief Handle all the records for the current simulation step + * @brief Handle all the records for the current simulation step. */ virtual void record(); /** @@ -226,27 +219,22 @@ class HDA_SimStepRecorder{ // *** RECORDER METHODS *** // // ************************** // - /** - * @brief Check whether the output directory is a valid one or not. If not, - * an exception will be thrown - */ - virtual void validateOutDir(); /** * @brief Check whether there are opened buffers or not * @return True if there is at least one opened buffer, false if there is * not even a single opened buffer */ - virtual bool isAnyBufferOpen(); + bool isAnyBufferOpen(); /** * @brief Open all the record buffers so the HDA_SimStepRecord can record */ - virtual void openBuffers(); + void openBuffers(); /** * @brief Close all the record buffers. Once it is done, the * HDA_SimStepRecorder will not be able to properly handle any new - * record + * record. */ - virtual void closeBuffers(); + void closeBuffers(); protected: // *** CONCRETE RECORD METHODS *** // @@ -286,14 +274,6 @@ class HDA_SimStepRecorder{ * current simulation step */ virtual void recordStochastic(); - /** - * @brief Craft the full output path considering the output directory and - * the given file name - * @param fname The given filename - * @return Full output path considering the output directory and the given - * file name - */ - virtual std::string craftOutputPath(std::string const &fname); }; diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index 85cad96ce..d9e40f4bd 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "a3909937"; +const char * HELIOS_GIT_HASH = "4eab409c"; const char * getHeliosVersion(){ return HELIOS_VERSION; diff --git a/src/scanner/BuddingScanningPulseProcess.cpp b/src/scanner/BuddingScanningPulseProcess.cpp index 410f0b756..56a9ecfd5 100644 --- a/src/scanner/BuddingScanningPulseProcess.cpp +++ b/src/scanner/BuddingScanningPulseProcess.cpp @@ -10,6 +10,9 @@ BuddingScanningPulseProcess::BuddingScanningPulseProcess( RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) : ScanningPulseProcess(scanner), dropper(dropper), @@ -17,6 +20,9 @@ BuddingScanningPulseProcess::BuddingScanningPulseProcess( randGen1(randGen1), randGen2(randGen2), intersectionHandlingNoiseSource(intersectionHandlingNoiseSource) +#ifdef DATA_ANALYTICS + ,pulseRecorder(pulseRecorder) +#endif { if(pool.getPoolSize() > 0){ if(pool.isDynamic()){ // Dynamic chunk schedule @@ -51,6 +57,9 @@ void BuddingScanningPulseProcess::onLegComplete(){ randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); #ifdef BUDDING_METRICS ofsBudding.flush(); @@ -79,6 +88,9 @@ void BuddingScanningPulseProcess::handlePulseComputationSequential( randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } void BuddingScanningPulseProcess::handlePulseComputationParallelDynamic( @@ -132,6 +144,9 @@ void BuddingScanningPulseProcess::handlePulseComputationParallelDynamic( randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } } @@ -177,6 +192,9 @@ void BuddingScanningPulseProcess::handlePulseComputationParallelStatic( randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } } diff --git a/src/scanner/BuddingScanningPulseProcess.h b/src/scanner/BuddingScanningPulseProcess.h index f0e5ea279..bf1a3e216 100644 --- a/src/scanner/BuddingScanningPulseProcess.h +++ b/src/scanner/BuddingScanningPulseProcess.h @@ -17,6 +17,12 @@ class BuddingScanningPulseProcess : public ScanningPulseProcess { #ifdef DATA_ANALYTICS public: + /** + * @brief The helios::analytics::PulseRecorder to be used to handle the + * records representing the computed pulse tasks. + * @see helios::analytics::PulseRecorder + */ + std::shared_ptr pulseRecorder; #else protected: #endif @@ -109,6 +115,9 @@ class BuddingScanningPulseProcess : public ScanningPulseProcess { RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ); virtual ~BuddingScanningPulseProcess() = default; diff --git a/src/scanner/Scanner.cpp b/src/scanner/Scanner.cpp index 1a6a2410f..a3fd1fd31 100644 --- a/src/scanner/Scanner.cpp +++ b/src/scanner/Scanner.cpp @@ -403,6 +403,9 @@ void Scanner::buildScanningPulseProcess( *randGen1, *randGen2, *intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pool->getPulseRecorder() +#endif ) ); } @@ -415,6 +418,9 @@ void Scanner::buildScanningPulseProcess( *randGen1, *randGen2, *intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pool->getPulseRecorder() +#endif ) ); } diff --git a/src/scanner/WarehouseScanningPulseProcess.cpp b/src/scanner/WarehouseScanningPulseProcess.cpp index 561d20757..458bba1fe 100644 --- a/src/scanner/WarehouseScanningPulseProcess.cpp +++ b/src/scanner/WarehouseScanningPulseProcess.cpp @@ -11,6 +11,9 @@ WarehouseScanningPulseProcess::WarehouseScanningPulseProcess( RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) : ScanningPulseProcess(scanner), dropper(dropper), @@ -18,8 +21,11 @@ WarehouseScanningPulseProcess::WarehouseScanningPulseProcess( randGen1(randGen1), randGen2(randGen2), intersectionHandlingNoiseSource(intersectionHandlingNoiseSource) -{ - if(pool.getPoolSize() > 0){ // Parallel computation +#ifdef DATA_ANALYTICS + ,pulseRecorder(pulseRecorder) +#endif + { + if(pool.getPoolSize() > 0){ // Parallel computation handler = [&] (SimulatedPulse const &sp) -> void { handlePulseComputationParallel(sp); }; @@ -43,12 +49,20 @@ void WarehouseScanningPulseProcess::onLegComplete(){ randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); // Assist thread pool with pending tasks (on WarehouseThreadPool::join atm) shared_ptr task; while( (task=pool.get()) != nullptr){ - (*task)(apMatrix, randGen1, randGen2, intersectionHandlingNoiseSource); + (*task)( + apMatrix, randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif + ); } // Wait for threads to finish @@ -70,6 +84,9 @@ void WarehouseScanningPulseProcess::handlePulseComputationSequential( randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } @@ -93,6 +110,9 @@ void WarehouseScanningPulseProcess::handlePulseComputationParallel( randGen1, randGen2, intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } } diff --git a/src/scanner/WarehouseScanningPulseProcess.h b/src/scanner/WarehouseScanningPulseProcess.h index a7ebfe27c..0723504b2 100644 --- a/src/scanner/WarehouseScanningPulseProcess.h +++ b/src/scanner/WarehouseScanningPulseProcess.h @@ -3,6 +3,9 @@ #include #include #include +#ifdef DATA_ANALYTICS +#include +#endif #include @@ -18,6 +21,12 @@ class WarehouseScanningPulseProcess : public ScanningPulseProcess { #ifdef DATA_ANALYTICS public: + /** + * @brief The helios::analytics::PulseRecorder to be used to handle the + * records representing the computed pulse tasks. + * @see helios::analytics::PulseRecorder + */ + std::shared_ptr pulseRecorder; #else protected: #endif @@ -82,6 +91,9 @@ class WarehouseScanningPulseProcess : public ScanningPulseProcess { RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ); virtual ~WarehouseScanningPulseProcess() = default; diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index dc799aa3e..fbbb0b561 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -30,6 +30,9 @@ void FullWaveformPulseRunnable::operator()( RandomnessGenerator &randGen, RandomnessGenerator &randGen2, NoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ){ // Deferred/lazy initialization initialize(); @@ -60,6 +63,9 @@ void FullWaveformPulseRunnable::operator()( intersectionHandlingNoiseSource, reflections, intersects +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); // Digest intersections @@ -89,6 +95,9 @@ void FullWaveformPulseRunnable::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ){ scanner->computeSubrays( [&] ( @@ -100,7 +109,7 @@ void FullWaveformPulseRunnable::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects - ) -> void{ + ) -> void { handleSubray( _tMinMax, circleStep, @@ -110,6 +119,9 @@ void FullWaveformPulseRunnable::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); }, tMinMax, @@ -129,6 +141,9 @@ void FullWaveformPulseRunnable::handleSubray( NoiseSource &intersectionHandlingNoiseSource, map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ){ // Rotate around the circle: vector tMinMax = _tMinMax; @@ -158,6 +173,9 @@ void FullWaveformPulseRunnable::handleSubray( subrayDirection, intersect->point ); +#ifdef DATA_ANALYTICS + pulseRecorder->recordIncidenceAngle(incidenceAngle); +#endif } // Distance between beam origin and intersection: diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index ab5ea00a3..06ba25c78 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -8,6 +8,9 @@ #include "ScenePart.h" #include #include +#ifdef DATA_ANALYTICS +#include +#endif #include @@ -83,6 +86,9 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ); /** * @brief Handle sub-rays along the circle @@ -104,6 +110,9 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ); /** * @brief Digest intersections found through ray casting @@ -293,5 +302,8 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { RandomnessGenerator &randGen, RandomnessGenerator &randGen2, NoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) override; }; \ No newline at end of file diff --git a/src/scanner/detector/PulseTask.h b/src/scanner/detector/PulseTask.h index 182c30c94..5a935c5c3 100644 --- a/src/scanner/detector/PulseTask.h +++ b/src/scanner/detector/PulseTask.h @@ -2,6 +2,10 @@ #include #include +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_PulseRecorder; +#endif #include @@ -33,5 +37,8 @@ class PulseTask{ RandomnessGenerator &randGen, RandomnessGenerator &randGen2, NoiseSource &intersectionHandlingNoiseSource +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) = 0; }; \ No newline at end of file diff --git a/src/scanner/detector/PulseTaskDropper.h b/src/scanner/detector/PulseTaskDropper.h index a6a1cb3ff..c2199d621 100644 --- a/src/scanner/detector/PulseTaskDropper.h +++ b/src/scanner/detector/PulseTaskDropper.h @@ -6,6 +6,10 @@ #include #include #include +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_PulseRecorder; +#endif /** @@ -24,6 +28,9 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >{ public: // *** CONSTRUCTION / DESTRUCTION *** // @@ -49,6 +56,9 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >(maxTasks, delta1, initDelta1, delta2, lastSign) {} virtual ~PulseTaskDropper() = default; @@ -62,6 +72,9 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >::drop; // To avoid overriding hides drop overloads using TaskDropper< PulseTask, @@ -70,6 +83,9 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >::tryDrop; // To avoid override hides tryDrop overloads /** * @brief Like TaskDropper::drop but dropping all pulse tasks through a diff --git a/src/scanner/detector/PulseThreadPool.h b/src/scanner/detector/PulseThreadPool.h index f541aae0c..0e61c4b70 100644 --- a/src/scanner/detector/PulseThreadPool.h +++ b/src/scanner/detector/PulseThreadPool.h @@ -5,6 +5,9 @@ #include #include #include +#ifdef DATA_ANALYTICS +#include +#endif /** * @version 1.0 @@ -17,11 +20,15 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >, public PulseThreadPoolInterface { #ifdef DATA_ANALYTICS public: + std::shared_ptr pulseRecorder; #else protected: #endif @@ -86,10 +93,18 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >(_pool_size), dynamic(dynamic) { // Allocate +#ifdef DATA_ANALYTICS + pulseRecorder = std::make_shared( + "helios_pulse_records" + ); +#endif apMatrices = new std::vector>[this->pool_size]; randGens = new RandomnessGenerator[this->pool_size]; randGens2 = new RandomnessGenerator[this->pool_size]; @@ -110,6 +125,10 @@ class PulseThreadPool : } virtual ~PulseThreadPool(){ +#ifdef DATA_ANALYTICS + // Flush and close pulse recorder + this->pulseRecorder->closeBuffers(); +#endif // Release memory delete[] apMatrices; delete[] randGens; @@ -130,6 +149,9 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif > &dropper ) override { run_res_task(dropper); @@ -145,6 +167,9 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif > &dropper ) override { return try_run_res_task(dropper); @@ -158,9 +183,21 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif >::join(); } +#ifdef DATA_ANALYTICS + /** + * @see PulseThreadPoolInterface::getPulseRecorder + */ + std::shared_ptr getPulseRecorder() override{ + return pulseRecorder; + } +#endif + protected: // *** M E T H O D S *** // // *********************** // @@ -175,6 +212,9 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif )> &task, int const resourceIdx ) override{ @@ -183,6 +223,9 @@ class PulseThreadPool : randGens[resourceIdx], randGens2[resourceIdx], intersectionHandlingNoiseSources[resourceIdx] +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } /** @@ -196,6 +239,9 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif )> &task, int const resourceIdx ) override { diff --git a/src/scanner/detector/PulseThreadPoolInterface.h b/src/scanner/detector/PulseThreadPoolInterface.h index e3d7a6b76..5b2a7a457 100644 --- a/src/scanner/detector/PulseThreadPoolInterface.h +++ b/src/scanner/detector/PulseThreadPoolInterface.h @@ -4,6 +4,11 @@ #include #include #include +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_PulseRecorder; +#endif + #include @@ -37,6 +42,9 @@ class PulseThreadPoolInterface{ RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif > &dropper ) = 0; /** @@ -59,6 +67,9 @@ class PulseThreadPoolInterface{ RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif > &dropper ) = 0; /** @@ -66,4 +77,13 @@ class PulseThreadPoolInterface{ */ virtual void join() = 0; +#ifdef DATA_ANALYTICS + /** + * @brief Obtain the pointer to the pulse recorder being used by the + * pulse thread pool. + * @return The pulse recorder used by the pulse thread pool. + * @see helios::analytics::HDA_PulseRecorder + */ + virtual std::shared_ptr getPulseRecorder() = 0; +#endif }; \ No newline at end of file diff --git a/src/scanner/detector/PulseWarehouseThreadPool.h b/src/scanner/detector/PulseWarehouseThreadPool.h index 24a601475..ee278eaa9 100644 --- a/src/scanner/detector/PulseWarehouseThreadPool.h +++ b/src/scanner/detector/PulseWarehouseThreadPool.h @@ -5,6 +5,9 @@ #include #include #include +#ifdef DATA_ANALYTICS +#include +#endif #include @@ -23,6 +26,12 @@ class PulseWarehouseThreadPool : { #ifdef DATA_ANALYTICS public: + /** + * @brief The helios::analytics::PulseRecorder to be used to handle the + * records representing the computed pulse tasks. + * @see helios::analytics::PulseRecorder + */ + std::shared_ptr pulseRecorder; #else protected: #endif @@ -70,6 +79,11 @@ class PulseWarehouseThreadPool : randGens2 = new RandomnessGenerator[this->pool_size]; intersectionHandlingNoiseSources = new UniformNoiseSource[this->pool_size]; +#ifdef DATA_ANALYTICS + pulseRecorder = std::make_shared( + "helios_pulse_records" + ); +#endif // Initialize for (std::size_t i = 0; i < this->pool_size; ++i){ @@ -85,6 +99,10 @@ class PulseWarehouseThreadPool : } virtual ~PulseWarehouseThreadPool(){ +#ifdef DATA_ANALYTICS + // Flush and close pulse recorder + this->pulseRecorder->closeBuffers(); +#endif // Release memory delete[] apMatrices; delete[] randGens; @@ -105,6 +123,9 @@ class PulseWarehouseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif > &dropper ) override { throw HeliosException( @@ -123,6 +144,9 @@ class PulseWarehouseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& +#ifdef DATA_ANALYTICS + ,std::shared_ptr +#endif > &dropper ) override { return post(make_shared( @@ -135,6 +159,14 @@ class PulseWarehouseThreadPool : inline void join() override{ WarehouseThreadPool::join(); } +#ifdef DATA_ANALYTICS + /** + * @see PulseThreadPoolInterface::getPulseRecorder + */ + std::shared_ptr getPulseRecorder() override{ + return pulseRecorder; + } +#endif protected: // *** WAREHOUSE THREADPOOL *** // @@ -154,6 +186,9 @@ class PulseWarehouseThreadPool : randGens[tid], randGens2[tid], intersectionHandlingNoiseSources[tid] +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } }; \ No newline at end of file From 59339e44bd69fb83e40321f343ef76d9ba091966 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Mon, 18 Sep 2023 19:56:31 +0200 Subject: [PATCH 03/17] Improved HDA wrt PulseRecorder. Added script to plot pulse records. --- scripts/debug/fullwave_plotter.py | 0 scripts/debug/hda_diff_report.py | 0 scripts/debug/hda_pulse_records_plotter.py | 385 ++++++++++++++++++ scripts/debug/hda_simstep_plotter.py | 2 +- scripts/debug/hda_xyzcloud_report.py | 0 scripts/debug/plot_budding_metrics.py | 0 scripts/debug/plot_log_data.py | 0 src/dataanalytics/HDA_OfstreamWrapper.h | 63 +++ src/dataanalytics/HDA_PulseRecorder.cpp | 31 +- src/dataanalytics/HDA_PulseRecorder.h | 38 +- src/dataanalytics/HDA_RecordBuffer.h | 50 +-- src/main/helios_version.cpp | 2 +- src/scanner/MultiScanner.cpp | 6 + src/scanner/MultiScanner.h | 3 + src/scanner/Scanner.h | 3 + src/scanner/ScanningDevice.cpp | 12 +- src/scanner/ScanningDevice.h | 7 + src/scanner/SingleScanner.cpp | 6 + src/scanner/SingleScanner.h | 3 + .../detector/FullWaveformPulseRunnable.cpp | 6 +- 20 files changed, 561 insertions(+), 56 deletions(-) mode change 100644 => 100755 scripts/debug/fullwave_plotter.py mode change 100644 => 100755 scripts/debug/hda_diff_report.py create mode 100755 scripts/debug/hda_pulse_records_plotter.py mode change 100644 => 100755 scripts/debug/hda_simstep_plotter.py mode change 100644 => 100755 scripts/debug/hda_xyzcloud_report.py mode change 100644 => 100755 scripts/debug/plot_budding_metrics.py mode change 100644 => 100755 scripts/debug/plot_log_data.py create mode 100644 src/dataanalytics/HDA_OfstreamWrapper.h diff --git a/scripts/debug/fullwave_plotter.py b/scripts/debug/fullwave_plotter.py old mode 100644 new mode 100755 diff --git a/scripts/debug/hda_diff_report.py b/scripts/debug/hda_diff_report.py old mode 100644 new mode 100755 diff --git a/scripts/debug/hda_pulse_records_plotter.py b/scripts/debug/hda_pulse_records_plotter.py new file mode 100755 index 000000000..ba7a972db --- /dev/null +++ b/scripts/debug/hda_pulse_records_plotter.py @@ -0,0 +1,385 @@ +import sys +import os +import time +import numpy as np +import matplotlib.pyplot as plt + + +# --- FUNCTIONS --- # +# ------------------- # +def print_help(): + print( +''' +Input arguments: + 1 -> Path to the first directory containing simulation records + 2 -> Path to the second directory containing simulation records + 3 -> Path to the directory where plots will be stored +''' + ) + + +def parse_args(helpf=print_help): + """Parse input arguments. Raise an exception if not correct arguments were + given""" + if len(sys.argv) == 1: + helpf() + exit(0) + elif len(sys.argv) < 4: + raise Exception( + '{m} arguments were given but 3 are required' + .format(m=len(sys.argv)-1) + ) + dira_path = sys.argv[1] + if not validate_directory(dira_path): + raise Exception( + 'The directory "{d}"\n' + 'was given as the first directory of records, but it is not valid' + ) + dirb_path = sys.argv[2] + if not validate_directory(dirb_path): + raise Exception( + 'The directory "{d}"\n' + 'was given as the second directory of records, but it is not valid' + ) + dirout_path = sys.argv[3] + if not validate_directory(dirout_path): + raise Exception( + 'The directory "{d}"\n' + 'was given as the third directory for plots, but it is not valid' + ) + return { + 'dira_path': dira_path, + 'dirb_path': dirb_path, + 'dirout_path': dirout_path + } + + +def validate_directory(path): + """Check path points to a valid existent directory. + If it does not exist and it cannot be created, then it is not valid""" + if os.path.exists(path): + if os.path.isdir(path): + return True + else: + return False + else: + os.mkdir(path, mode=0o775) + if os.path.exists(path): + return True + return False + + +def read_records(path, sep=','): + """Read all record files contained in the directory pointed by given + path""" + # Read vectorial records + intensity_calc = read_record(os.path.join( + path, 'intensity_calc.csv' + ), sep) + # Return key-word records + return { + # Intensity calculation records + 'incidence_angle_rad': intensity_calc[:, 0], + 'target_range_m': intensity_calc[:, 1], + 'target_area_m2': intensity_calc[:, 2], + 'radius_m': intensity_calc[:, 3], + 'bdrf': intensity_calc[:, 4], + 'cross_section': intensity_calc[:, 5], + 'received_power': intensity_calc[:, 6] + } + + +def read_record(path, sep): + """Read given record file + :param path: The path to the record file to be read + :param sep: The separator used in the record file + :return: None if the record file could not be read, the data as a numpy + array otherwise + """ + if os.path.exists(path) and os.path.isfile(path): + return np.loadtxt(path, delimiter=sep) + return None + + +def plot_records(arec, brec, outdir): + """Do plots for each case and export them in given output directory + :param arec: The records of the first case + :param brec: The records of the second case + :param outdir: The output directory where generated plots must be + written + """ + do_incidence_angle_plots(arec, brec, outdir) + do_by_incidence_angle_plots(arec, brec, outdir) + + +def validate_record(key, rec, recid): + """Check that the record with given key is available + :return: True if the record is valid (available data), False otherwise + """ + if key not in rec or rec.get(key, None) is None: + print( + 'Record "{key}" is not available for {recid} records' + .format( + key=key, + recid=recid + ) + ) + return False + return True + + +def init_figure(figsize=(20, 12)): + """Initialize a matplotlib's figure context""" + fig = plt.figure( + figsize=figsize + ) + return fig + + +def do_incidence_angle_subplot( + fig, ax, phi, label=None, title=None, xlabel=None, ylabel=None, bins=32, + log=False +): + if title is not None: + ax.set_title(title, fontsize=20) + hist = ax.hist(phi, bins=bins, label=label, log=log) + ax.axvline(x=np.mean(phi), color='tab:orange', lw=3, label='$\\mu$') + if xlabel is not None: + ax.set_xlabel(xlabel, fontsize=16) + if ylabel is not None: + ax.set_ylabel(ylabel, fontsize=16) + ax.tick_params(axis='both', which='both', labelsize=14) + ax.legend(loc='upper right', fontsize=14) + ax.grid('both') + ax.set_axisbelow(True) + + +def do_incidence_angle_plots(arec, brec, outdir): + # Validate incidence angle data + if not validate_record('incidence_angle_rad', arec, 'a') or \ + not validate_record('incidence_angle_rad', brec, 'b'): + print('Cannot do incidence angle plots') + return + + # Do the incidence angle plots + fig = init_figure() # Initialize figure + ax = fig.add_subplot(2, 2, 1) # Initialize phi(a) subplot + do_incidence_angle_subplot( + fig, ax, arec['incidence_angle_rad'], + label='$\\varphi(a)$', + title='A-Incidence angle ($\\varphi$) in rad', + xlabel='$\\varphi(a)$', + ylabel='cases' + ) + ax = fig.add_subplot(2, 2, 3) # Initialize phi(a) log subplot + do_incidence_angle_subplot( + fig, ax, arec['incidence_angle_rad'], + label='$\\varphi(a)$', + title='A-Incidence angle ($\\varphi$) in rad (logarithmic)', + xlabel='$\\varphi(a)$', + ylabel='cases', + log=True + ) + ax = fig.add_subplot(2, 2, 2) # Initialize phi(b) subplot + do_incidence_angle_subplot( + fig, ax, brec['incidence_angle_rad'], + label='$\\varphi(b)$', + title='B-Incidence angle ($\\varphi$) in rad', + xlabel='$\\varphi(b)$', + ylabel='cases' + ) + ax = fig.add_subplot(2, 2, 4) # Initialize phi(a) log subplot + do_incidence_angle_subplot( + fig, ax, brec['incidence_angle_rad'], + label='$\\varphi(b)$', + title='B-Incidence angle ($\\varphi$) in rad (logarithmic)', + xlabel='$\\varphi(b)$', + ylabel='cases', + log=True + ) + fig.tight_layout() + # Save figure to file and remove it from memory + fig.savefig( + os.path.join(outdir, 'incidence_angle_distribution.png') + ) + fig.clear() + plt.close(fig) + + +def do_y_by_x_subplot( + fig, ax, x, y, title=None, xlabel=None, ylabel=None, + color='black' +): + if title is not None: + ax.set_title(title, fontsize=14) + ax.scatter(x, y, c=color, s=8) + if xlabel is not None: + ax.set_xlabel(xlabel, fontsize=12) + if ylabel is not None: + ax.set_ylabel(ylabel, fontsize=12) + ax.tick_params(axis='both', which='both', labelsize=12) + ax.grid('both') + ax.set_axisbelow(True) + + +def do_by_incidence_angle_plots(arec, brec, outdir): + # Validate classification calculation data + if not validate_record('incidence_angle_rad', arec, 'a') or \ + not validate_record('target_range_m', arec, 'a') or \ + not validate_record('target_area_m2', arec, 'a') or \ + not validate_record('radius_m', arec, 'a') or \ + not validate_record('bdrf', arec, 'a') or \ + not validate_record('cross_section', arec, 'a') or \ + not validate_record('received_power', arec, 'a') or \ + not validate_record('incidence_angle_rad', brec, 'b') or \ + not validate_record('target_range_m', brec, 'b') or \ + not validate_record('target_area_m2', brec, 'b') or \ + not validate_record('radius_m', brec, 'b') or \ + not validate_record('bdrf', brec, 'b') or \ + not validate_record('cross_section', brec, 'b') or \ + not validate_record('received_power', brec, 'b'): + print('Cannot do by incidence angle plots') + return + # Do the "by incidence angle" plots + fig = init_figure() # Initialize figure + ax = fig.add_subplot(3, 4, 1) # Initialize target range A subplot + do_y_by_x_subplot( + fig, ax, arec['incidence_angle_rad'], arec['target_range_m'], + title='A-Target range (m)', + xlabel='Incidence angle (rad)', + ylabel='Target range (m)', + color='black' + ) + ax = fig.add_subplot(3, 4, 2) # Initialize target area A subplot + do_y_by_x_subplot( + fig, ax, arec['incidence_angle_rad'], arec['target_area_m2'], + title='A-Target area ($m^2$)', + xlabel='Incidence angle (rad)', + ylabel='Target area ($m^2$)', + color='tab:blue' + ) + ax = fig.add_subplot(3, 4, 5) # Initialize radius A subplot + do_y_by_x_subplot( + fig, ax, arec['incidence_angle_rad'], arec['radius_m'], + title='A-Radius (m)', + xlabel='Incidence angle (rad)', + ylabel='Radius (m)', + color='tab:red' + ) + ax = fig.add_subplot(3, 4, 6) # Initialize BDRF A subplot + do_y_by_x_subplot( + fig, ax, arec['incidence_angle_rad'], arec['bdrf'], + title='A-BDRF', + xlabel='Incidence angle (rad)', + ylabel='BDRF', + color='tab:green' + ) + ax = fig.add_subplot(3, 4, 9) # Initialize Cross-section A subplot + do_y_by_x_subplot( + fig, ax, arec['incidence_angle_rad'], arec['cross_section'], + title='A-Cross-section ($m^2$)', + xlabel='Incidence angle (rad)', + ylabel='Cross-section ($m^2$)', + color='tab:orange' + ) + ax = fig.add_subplot(3, 4, 10) # Initialize received power A subplot + do_y_by_x_subplot( + fig, ax, arec['incidence_angle_rad'], arec['received_power'], + title='A-Received power', + xlabel='Incidence angle (rad)', + ylabel='Received power', + color='tab:purple' + ) + ax = fig.add_subplot(3, 4, 3) # Initialize target range B subplot + do_y_by_x_subplot( + fig, ax, brec['incidence_angle_rad'], brec['target_range_m'], + title='B-Target range (m)', + xlabel='Incidence angle (rad)', + ylabel='Target range (m)', + color='black' + ) + ax = fig.add_subplot(3, 4, 4) # Initialize target area B subplot + do_y_by_x_subplot( + fig, ax, brec['incidence_angle_rad'], brec['target_area_m2'], + title='B-Target area ($m^2$)', + xlabel='Incidence angle (rad)', + ylabel='Target area ($m^2$)', + color='tab:blue' + ) + ax = fig.add_subplot(3, 4, 7) # Initialize radius B subplot + do_y_by_x_subplot( + fig, ax, brec['incidence_angle_rad'], brec['radius_m'], + title='B-Radius (m)', + xlabel='Incidence angle (rad)', + ylabel='Radius (m)', + color='tab:red' + ) + ax = fig.add_subplot(3, 4, 8) # Initialize BDRF B subplot + do_y_by_x_subplot( + fig, ax, brec['incidence_angle_rad'], brec['bdrf'], + title='B-BDRF', + xlabel='Incidence angle (rad)', + ylabel='BDRF', + color='tab:green' + ) + ax = fig.add_subplot(3, 4, 11) # Initialize Cross-section B subplot + do_y_by_x_subplot( + fig, ax, brec['incidence_angle_rad'], brec['cross_section'], + title='B-Cross-section ($m^2$)', + xlabel='Incidence angle (rad)', + ylabel='Cross-section ($m^2$)', + color='tab:orange' + ) + ax = fig.add_subplot(3, 4, 12) # Initialize received power B subplot + do_y_by_x_subplot( + fig, ax, brec['incidence_angle_rad'], brec['received_power'], + title='B-Received power', + xlabel='Incidence angle (rad)', + ylabel='Received power', + color='tab:purple' + ) + fig.tight_layout() + # Save figure to file and remove it from memory + fig.savefig( + os.path.join(outdir, 'plots_by_incidence_angle.png') + ) + fig.clear() + plt.close(fig) + + + +# --- M A I N --- # +# ------------------- # +if __name__ == '__main__': + # Prepare plotter + args = parse_args() + sep = ',' + # Read A records + print( + 'Reading A-records from "{path}" ...' + .format(path=args['dira_path']) + ) + start = time.perf_counter() + arec = read_records(args['dira_path'], sep=sep) + end = time.perf_counter() + print('Read A-records in {t} seconds'.format(t=end-start)) + # Read B records + print( + 'Reading B-records from "{path}" ...' + .format(path=args['dirb_path']) + ) + start = time.perf_counter() + brec = read_records(args['dirb_path'], sep=sep) + end = time.perf_counter() + print('Read B-records in {t} seconds'.format(t=end-start)) + # Plot records + print( + 'Generating plots at "{path}" ...' + .format( + path=args['dirout_path'] + ) + ) + start = time.perf_counter() + plot_records(arec, brec, args['dirout_path']) + end = time.perf_counter() + print('Generated plots in {t} seconds'.format(t=end-start)) diff --git a/scripts/debug/hda_simstep_plotter.py b/scripts/debug/hda_simstep_plotter.py old mode 100644 new mode 100755 index 92d8e0e43..9ce472fd7 --- a/scripts/debug/hda_simstep_plotter.py +++ b/scripts/debug/hda_simstep_plotter.py @@ -45,7 +45,7 @@ def parse_args(helpf=print_help): if not validate_directory(dirout_path): raise Exception( 'The directory "{d}"\n' - 'was given as the third directory of records, but it is not valid' + 'was given as the third directory for plots, but it is not valid' ) return { 'dira_path': dira_path, diff --git a/scripts/debug/hda_xyzcloud_report.py b/scripts/debug/hda_xyzcloud_report.py old mode 100644 new mode 100755 diff --git a/scripts/debug/plot_budding_metrics.py b/scripts/debug/plot_budding_metrics.py old mode 100644 new mode 100755 diff --git a/scripts/debug/plot_log_data.py b/scripts/debug/plot_log_data.py old mode 100644 new mode 100755 diff --git a/src/dataanalytics/HDA_OfstreamWrapper.h b/src/dataanalytics/HDA_OfstreamWrapper.h new file mode 100644 index 000000000..bcec285d9 --- /dev/null +++ b/src/dataanalytics/HDA_OfstreamWrapper.h @@ -0,0 +1,63 @@ +#ifdef DATA_ANALYTICS + +#include +#include +#include + +// TODO Rethink : Document + +namespace helios { namespace analytics{ + +class HDA_OfstreamWrapper{ +protected: + // *** ATTRIBUTES *** // + // ******************** // + std::ofstream ofs; + /** + * @brief The separator between recorded elements + */ + std::string sep; + bool hasWrittenSomething; + +public: + // *** CONSTRUCTION / DESTRUCTION *** // + // ************************************ // + HDA_OfstreamWrapper(std::string const &outpath, std::string const &sep=",") : + ofs(outpath, std::ios_base::out), + sep(sep), + hasWrittenSomething(false) + {} + virtual ~HDA_OfstreamWrapper() = default; + + // *** OUTPUT FILE STREAM METHODS *** // + // ************************************ // + inline bool is_open() {return ofs.is_open();} + inline void close() {return ofs.close();} + + // *** OUTPUT FILE STREAM OPERATORS *** // + // ************************************** // + template + HDA_OfstreamWrapper & operator <<(T const &elem){ + if(hasWrittenSomething){ + ofs << sep << elem; + } + else{ + ofs << elem; + hasWrittenSomething = true; + } + return *this; + } + + HDA_OfstreamWrapper & operator <<(std::vector const &elem){ + ofs << elem[0]; + for(size_t i = 1 ; i < elem.size(); ++i){ + ofs << sep << elem[i]; + } + ofs << "\n"; + return *this; + } + +}; + +}} +#endif \ No newline at end of file diff --git a/src/dataanalytics/HDA_PulseRecorder.cpp b/src/dataanalytics/HDA_PulseRecorder.cpp index 53981ab78..fcb6e9151 100644 --- a/src/dataanalytics/HDA_PulseRecorder.cpp +++ b/src/dataanalytics/HDA_PulseRecorder.cpp @@ -8,28 +8,45 @@ using namespace helios::analytics; // ************************** // bool HDA_PulseRecorder::isAnyBufferOpen(){ bool anyOpen = false; - anyOpen |= incidenceAngle_rad->isOpen(); + anyOpen |= intensityCalc->isOpen(); return anyOpen; } void HDA_PulseRecorder::openBuffers(){ // Open subray related buffers - incidenceAngle_rad = std::make_shared>( - craftOutputPath("incidence_angle_rad.csv") + size_t const maxSize = 256; + std::string const sep = ","; + intensityCalc = std::make_shared>>( + craftOutputPath("intensity_calc.csv"), + maxSize, + sep, + true // vectorial flag ); } void HDA_PulseRecorder::closeBuffers(){ // Close subray buffers - incidenceAngle_rad->close(); + std::unique_lock lock(intensityCalcMutex); + intensityCalc->close(); } // *** RECORD METHODS *** // // ************************ // -void HDA_PulseRecorder::recordIncidenceAngle(double const _incidenceAngle_rad){ - std::unique_lock lock(incidenceAngle_rad_mutex); - incidenceAngle_rad->push(_incidenceAngle_rad); +void HDA_PulseRecorder::recordIntensityCalculation( + double const incidenceAngle_rad, + double const targetRange_m, + double const targetArea_m2, + double const radius_m, + double const bdrf, + double const crossSection, + double const receivedPower +){ + std::unique_lock lock(intensityCalcMutex); + intensityCalc->push(std::vector({ + incidenceAngle_rad, targetRange_m, targetArea_m2, radius_m, bdrf, + crossSection, receivedPower + })); } #endif diff --git a/src/dataanalytics/HDA_PulseRecorder.h b/src/dataanalytics/HDA_PulseRecorder.h index e3b9a792f..1fa1f20f2 100644 --- a/src/dataanalytics/HDA_PulseRecorder.h +++ b/src/dataanalytics/HDA_PulseRecorder.h @@ -23,14 +23,32 @@ class HDA_PulseRecorder : public HDA_Recorder{ // *** ATTRIBUTES *** // // ******************** // /** - * @brief The record buffer for the incidence angles (in radians). + * @brief The vector which components are variables involved on a + * particular intensity calculation for a given subray. + * + * [0] -> Incidence angle in radians. + * + * [1] -> The target range in meters, i.e., the distance between the beam's + * origin and the intersection point. + * + * [2] -> The target area in squared meters. + * + * [3] -> The radius in meters, i.e., the distance between the beam's + * center line and the intersection point. + * + * [4] -> The bidirectional reflectance function (BDRF). + * + * [5] -> The cross-section in squared meters. + * + * [6] -> The calculated received power, i.e., intensity. */ - std::shared_ptr> incidenceAngle_rad; + std::shared_ptr>> intensityCalc; + /** - * @brief The mutex to handle concurrent writes to the incidenceAngle_rad - * record buffer. + * @brief The mutex to handle concurrent writes to the buffers related to + * intensity calculation. */ - std::mutex incidenceAngle_rad_mutex; + std::mutex intensityCalcMutex; public: // *** CONSTRUCTION / DESTRUCTION *** // @@ -74,7 +92,15 @@ class HDA_PulseRecorder : public HDA_Recorder{ /** * @brief Handle all the records for the current simulation step. */ - virtual void recordIncidenceAngle(double const incidenceAngle_rad); + virtual void recordIntensityCalculation( + double const incidenceAngle_rad, + double const targetRange_m, + double const targetArea_m2, + double const radius_m, + double const bdrf, + double const crossSection, + double const receivedPower + ); }; diff --git a/src/dataanalytics/HDA_RecordBuffer.h b/src/dataanalytics/HDA_RecordBuffer.h index 10283743d..6ee1de8ff 100644 --- a/src/dataanalytics/HDA_RecordBuffer.h +++ b/src/dataanalytics/HDA_RecordBuffer.h @@ -1,6 +1,8 @@ #ifdef DATA_ANALYTICS #pragma once +#include + #include #include #include @@ -34,18 +36,9 @@ class HDA_RecordBuffer { */ std::string outpath; /** - * @brief The output stream to write the contents of the buffer - */ - std::ofstream ofs; - /** - * @brief The separator between recorded elements - */ - std::string sep; - /** - * @brief The function to write the content of the buffer through the - * output stream + * @brief The wrapped output stream to write the contents of the buffer */ - std::function write; + HDA_OfstreamWrapper ofsw; public: // *** CONSTRUCTION / DESTRUCTION *** // @@ -59,15 +52,13 @@ class HDA_RecordBuffer { HDA_RecordBuffer( std::string const &outpath, size_t const maxSize=256, - std::string const &sep="," + std::string const &sep=",", + bool const vectorial=false ) : maxSize(maxSize), outpath(outpath), - ofs(outpath, std::ios_base::out), - sep(sep) - { - write = [&](void) -> void {this->firstWrite();}; - } + ofsw(outpath, sep) + {} virtual ~HDA_RecordBuffer(){ if(isOpen()) close(); @@ -80,32 +71,17 @@ class HDA_RecordBuffer { * not * @return True if the output stream is opened, false otherwise */ - inline bool isOpen() {return ofs.is_open();} - /** - * @brief Write the contents of the buffer through the output stream for - * the first time - */ - inline void firstWrite() { - size_t numElems = buff.size(); - ofs << buff[0]; - for(size_t i = 1 ; i < numElems ; ++i){ - ofs << sep << buff[i]; - } - this->write = [&] (void) -> void {this->nextWrite();}; - } + inline bool isOpen() {return ofsw.is_open();} /** - * @brief Write the contents of the buffer through the output stream after - * the first time + * @brief Method to write the elements of the buffer to a file. */ - inline void nextWrite() { - for(T const & elem : buff) ofs << sep << elem; - } + inline void write() {for(T const & elem : buff) ofsw << elem;} /** * @brief Write all the contents of the buffer and then make it empty */ inline void flush(){ if(buff.size() > 0){ - this->write(); + write(); buff.clear(); } } @@ -115,7 +91,7 @@ class HDA_RecordBuffer { */ inline void close(){ flush(); - if(isOpen()) ofs.close(); + if(isOpen()) ofsw.close(); } /** * @brief Insert given element in the buffer. If the buffer is full, it diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index d9e40f4bd..481e9f2cb 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "4eab409c"; +const char * HELIOS_GIT_HASH = "9f5ba7f6"; const char * getHeliosVersion(){ return HELIOS_VERSION; diff --git a/src/scanner/MultiScanner.cpp b/src/scanner/MultiScanner.cpp index 85c455774..6d07e9526 100644 --- a/src/scanner/MultiScanner.cpp +++ b/src/scanner/MultiScanner.cpp @@ -212,6 +212,9 @@ double MultiScanner::calcIntensity( double const targetArea, double const radius, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const{ return scanDevs[idx].calcIntensity( incidenceAngle, @@ -219,6 +222,9 @@ double MultiScanner::calcIntensity( mat, targetArea, radius +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } diff --git a/src/scanner/MultiScanner.h b/src/scanner/MultiScanner.h index 2b9cf43b8..37bab0cb6 100644 --- a/src/scanner/MultiScanner.h +++ b/src/scanner/MultiScanner.h @@ -196,6 +196,9 @@ class MultiScanner : public Scanner{ double const targetArea, double const radius, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const override; /** * @see Scanner::calcIntensity diff --git a/src/scanner/Scanner.h b/src/scanner/Scanner.h index c27a091c1..922737de4 100644 --- a/src/scanner/Scanner.h +++ b/src/scanner/Scanner.h @@ -499,6 +499,9 @@ class Scanner : public Asset { double const targetArea, double const radius, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const = 0; /** * @brief Handle to which scanning device request the intensity computation diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index 085196463..b383d0728 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -322,6 +322,9 @@ double ScanningDevice::calcIntensity( Material const &mat, double const targetArea, double const radius +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const { double bdrf = 0, sigma = 0; if(mat.isPhong()) { @@ -353,7 +356,7 @@ double ScanningDevice::calcIntensity( << mat.name << "\""; logging::ERR(ss.str()); } - return EnergyMaths::calcReceivedPower( + double const receivedPower = EnergyMaths::calcReceivedPower( averagePower_w, wavelength_m, targetRange, @@ -366,6 +369,13 @@ double ScanningDevice::calcIntensity( atmosphericExtinction, sigma ) * 1000000000.0; +#ifdef DATA_ANALYTICS + pulseRecorder->recordIntensityCalculation( + incidenceAngle, targetRange, targetArea, radius, bdrf, sigma, + receivedPower + ); +#endif + return receivedPower; } double ScanningDevice::calcIntensity( double const targetRange, diff --git a/src/scanner/ScanningDevice.h b/src/scanner/ScanningDevice.h index c30be2321..69e0c557b 100644 --- a/src/scanner/ScanningDevice.h +++ b/src/scanner/ScanningDevice.h @@ -11,6 +11,10 @@ class AbstractDetector; #include #include #include +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_PulseRecorder; +#endif #include @@ -377,6 +381,9 @@ class ScanningDevice : public Asset { Material const &mat, double const targetArea, double const radius +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const; /** diff --git a/src/scanner/SingleScanner.cpp b/src/scanner/SingleScanner.cpp index a7dd9dd7b..df9bb25d5 100644 --- a/src/scanner/SingleScanner.cpp +++ b/src/scanner/SingleScanner.cpp @@ -248,6 +248,9 @@ double SingleScanner::calcIntensity( double const targetArea, double const radius, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const { return scanDev.calcIntensity( incidenceAngle, @@ -255,6 +258,9 @@ double SingleScanner::calcIntensity( mat, targetArea, radius +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } double SingleScanner::calcIntensity( diff --git a/src/scanner/SingleScanner.h b/src/scanner/SingleScanner.h index a21b6043d..c565df7c1 100644 --- a/src/scanner/SingleScanner.h +++ b/src/scanner/SingleScanner.h @@ -169,6 +169,9 @@ class SingleScanner : public Scanner{ double const targetArea, double const radius, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) const override; /** * @see Scanner::calcIntensity diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index fbbb0b561..20f4adb81 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -173,9 +173,6 @@ void FullWaveformPulseRunnable::handleSubray( subrayDirection, intersect->point ); -#ifdef DATA_ANALYTICS - pulseRecorder->recordIncidenceAngle(incidenceAngle); -#endif } // Distance between beam origin and intersection: @@ -211,6 +208,9 @@ void FullWaveformPulseRunnable::handleSubray( targetArea, radius, pulse.getDeviceIndex() +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } From cf5b171853de6146f451d8e08028088856d40394 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Mon, 18 Sep 2023 21:03:05 +0200 Subject: [PATCH 04/17] Documented HDA_OfstreamWrapper --- src/dataanalytics/HDA_OfstreamWrapper.h | 38 +++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/dataanalytics/HDA_OfstreamWrapper.h b/src/dataanalytics/HDA_OfstreamWrapper.h index bcec285d9..b9fb094d1 100644 --- a/src/dataanalytics/HDA_OfstreamWrapper.h +++ b/src/dataanalytics/HDA_OfstreamWrapper.h @@ -12,17 +12,32 @@ class HDA_OfstreamWrapper{ protected: // *** ATTRIBUTES *** // // ******************** // + /** + * @brief The output file stream used to write to a file. + */ std::ofstream ofs; /** - * @brief The separator between recorded elements + * @brief The separator between recorded elements. */ std::string sep; + /** + * @brief Boolean flag to control whether the HDA_OfstreamWrapper has + * written something or not. Once something has been written, the flag + * will be set to true. By default, it is initialized to false. + */ bool hasWrittenSomething; public: // *** CONSTRUCTION / DESTRUCTION *** // // ************************************ // - HDA_OfstreamWrapper(std::string const &outpath, std::string const &sep=",") : + /** + * @brief Build a HDA_OfstreamWrapper to handle writing records to files. + * @param outpath The path to the output file. + * @see HDA_OfstreamWrapper::sep + */ + HDA_OfstreamWrapper( + std::string const &outpath, std::string const &sep="," + ) : ofs(outpath, std::ios_base::out), sep(sep), hasWrittenSomething(false) @@ -31,11 +46,24 @@ class HDA_OfstreamWrapper{ // *** OUTPUT FILE STREAM METHODS *** // // ************************************ // + /** + * @brief Wraps the is_open method of the output file stream class. + */ inline bool is_open() {return ofs.is_open();} + /** + * @brief Wraps the close method of the output file stream class. + */ inline void close() {return ofs.close();} // *** OUTPUT FILE STREAM OPERATORS *** // // ************************************** // + /** + * @brief Default stream input operator, i.e., <<. + * @tparam T The type of element to be written. + * @param elem The element to be written. + * @return A reference to the HDA_OfstreamWrapper itself for fluent + * programming purposes. + */ template HDA_OfstreamWrapper & operator <<(T const &elem){ if(hasWrittenSomething){ @@ -48,6 +76,12 @@ class HDA_OfstreamWrapper{ return *this; } + /** + * @brief Stream input operator to handle vectors of doubles as element. + * @param elem The vector of doubles as element. + * @return A reference to the HDA_OfstreamWrapper itself for fluent + * programming purposes. + */ HDA_OfstreamWrapper & operator <<(std::vector const &elem){ ofs << elem[0]; for(size_t i = 1 ; i < elem.size(); ++i){ From 2b0c9a0fa6d6261b6e16ccfe52c06b5bbffdcadd Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Tue, 19 Sep 2023 16:37:32 +0200 Subject: [PATCH 05/17] Extended pulse recording to generate output point clouds. --- .../hda_pulse_calc_intensity_csv_to_laz.sh | 52 ++++++ scripts/debug/hda_pulse_records_plotter.py | 14 +- src/dataanalytics/HDA_PulseRecorder.cpp | 21 +-- src/dataanalytics/HDA_PulseRecorder.h | 33 ++-- src/scanner/MultiScanner.cpp | 4 +- src/scanner/MultiScanner.h | 2 +- src/scanner/Scanner.h | 2 +- src/scanner/ScanningDevice.cpp | 16 +- src/scanner/ScanningDevice.h | 2 +- src/scanner/SingleScanner.cpp | 4 +- src/scanner/SingleScanner.h | 2 +- .../detector/AbstractPulseRunnable.cpp | 8 + src/scanner/detector/AbstractPulseRunnable.h | 7 + .../detector/FullWaveformPulseRunnable.cpp | 172 ++++++++++++++---- .../detector/FullWaveformPulseRunnable.h | 47 ++++- 15 files changed, 302 insertions(+), 84 deletions(-) create mode 100755 scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh diff --git a/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh b/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh new file mode 100755 index 000000000..5e5b1af17 --- /dev/null +++ b/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh @@ -0,0 +1,52 @@ +#!/bin/bash + +# ######################################################################## +# # +# AUTHOR : Alberto M. Esmorís Pena # +# # +# Script to transform an input CSV file, which rows are pulse records # +# written by the HDA_PulseRecorder component of HELIOS++, to a LAS/LAZ # +# file. # +# # +# ######################################################################## + +# Path or alias to TXT2LAS util +TXT2LAS='txt2las' + +# Function to show help +function show_help { + cat << EOF + +hda_pulse_calc_intensity_csv_to_laz.sh + + Argument 1: Path to the input CSV file + + Argument 2: Path to the output LAZ file + + +EOF +} + +# Handle input arguments +if [[ $# -ne 2 ]]; then + echo -e 'ERROR: Exactly two arguments must be provided\n' + show_help + exit 1 +fi + + +echo -e "Transforming \"$1\" to \"$2\" ..." +mkdir -p $(dirname "$2") +${TXT2LAS} -i "$1" \ + -set_version 1.4 -parse xyz01234567 \ + -add_attribute 10 'incidence_angle_rad' 'incidence_angle_rad' \ + -add_attribute 10 'target_range_m' 'target_range_m' \ + -add_attribute 10 'target_area_m2' 'target_area_m2' \ + -add_attribute 10 'radius_m' 'radius_m' \ + -add_attribute 10 'bdrf' 'bdrf' \ + -add_attribute 10 'cross_section_m2' 'cross_section_m2' \ + -add_attribute 10 'received_power' 'received_power' \ + -add_attribute 2 'captured' 'captured' \ + -o "$2" + + diff --git a/scripts/debug/hda_pulse_records_plotter.py b/scripts/debug/hda_pulse_records_plotter.py index ba7a972db..0633cfdc2 100755 --- a/scripts/debug/hda_pulse_records_plotter.py +++ b/scripts/debug/hda_pulse_records_plotter.py @@ -79,13 +79,13 @@ def read_records(path, sep=','): # Return key-word records return { # Intensity calculation records - 'incidence_angle_rad': intensity_calc[:, 0], - 'target_range_m': intensity_calc[:, 1], - 'target_area_m2': intensity_calc[:, 2], - 'radius_m': intensity_calc[:, 3], - 'bdrf': intensity_calc[:, 4], - 'cross_section': intensity_calc[:, 5], - 'received_power': intensity_calc[:, 6] + 'incidence_angle_rad': intensity_calc[:, 3], + 'target_range_m': intensity_calc[:, 4], + 'target_area_m2': intensity_calc[:, 5], + 'radius_m': intensity_calc[:, 6], + 'bdrf': intensity_calc[:, 7], + 'cross_section': intensity_calc[:, 8], + 'received_power': intensity_calc[:, 9] } diff --git a/src/dataanalytics/HDA_PulseRecorder.cpp b/src/dataanalytics/HDA_PulseRecorder.cpp index fcb6e9151..715d683a2 100644 --- a/src/dataanalytics/HDA_PulseRecorder.cpp +++ b/src/dataanalytics/HDA_PulseRecorder.cpp @@ -34,19 +34,18 @@ void HDA_PulseRecorder::closeBuffers(){ // *** RECORD METHODS *** // // ************************ // void HDA_PulseRecorder::recordIntensityCalculation( - double const incidenceAngle_rad, - double const targetRange_m, - double const targetArea_m2, - double const radius_m, - double const bdrf, - double const crossSection, - double const receivedPower + std::vector const &record ){ std::unique_lock lock(intensityCalcMutex); - intensityCalc->push(std::vector({ - incidenceAngle_rad, targetRange_m, targetArea_m2, radius_m, bdrf, - crossSection, receivedPower - })); + intensityCalc->push(record); +} +void HDA_PulseRecorder::recordIntensityCalculation( + std::vector> const &records +){ + std::unique_lock lock(intensityCalcMutex); + for(std::vector const & record : records) { + intensityCalc->push(record); + } } #endif diff --git a/src/dataanalytics/HDA_PulseRecorder.h b/src/dataanalytics/HDA_PulseRecorder.h index 1fa1f20f2..b96cddbdd 100644 --- a/src/dataanalytics/HDA_PulseRecorder.h +++ b/src/dataanalytics/HDA_PulseRecorder.h @@ -26,21 +26,25 @@ class HDA_PulseRecorder : public HDA_Recorder{ * @brief The vector which components are variables involved on a * particular intensity calculation for a given subray. * - * [0] -> Incidence angle in radians. + * [0, 1, 2] -> \f$(x, y, z)\f$ * - * [1] -> The target range in meters, i.e., the distance between the beam's + * [3] -> Incidence angle in radians. + * + * [4] -> The target range in meters, i.e., the distance between the beam's * origin and the intersection point. * - * [2] -> The target area in squared meters. + * [5] -> The target area in squared meters. * - * [3] -> The radius in meters, i.e., the distance between the beam's + * [6] -> The radius in meters, i.e., the distance between the beam's * center line and the intersection point. * - * [4] -> The bidirectional reflectance function (BDRF). + * [7] -> The bidirectional reflectance function (BDRF). + * + * [8] -> The cross-section in squared meters. * - * [5] -> The cross-section in squared meters. + * [9] -> The calculated received power, i.e., intensity. * - * [6] -> The calculated received power, i.e., intensity. + * [10] -> 1 if the point was captured, 0 otherwise. */ std::shared_ptr>> intensityCalc; @@ -92,14 +96,15 @@ class HDA_PulseRecorder : public HDA_Recorder{ /** * @brief Handle all the records for the current simulation step. */ + virtual void recordIntensityCalculation(std::vector const &record); + /** + * @brief Like + * HDA_PulseRecorder::recordIntensityCalculation(std::vector) + * but receiving many records at once. + * @see HDA_PulseRecorder::recordIntensityCalculation(std::vector) + */ virtual void recordIntensityCalculation( - double const incidenceAngle_rad, - double const targetRange_m, - double const targetArea_m2, - double const radius_m, - double const bdrf, - double const crossSection, - double const receivedPower + std::vector> const &records ); }; diff --git a/src/scanner/MultiScanner.cpp b/src/scanner/MultiScanner.cpp index 6d07e9526..c12dc2e36 100644 --- a/src/scanner/MultiScanner.cpp +++ b/src/scanner/MultiScanner.cpp @@ -213,7 +213,7 @@ double MultiScanner::calcIntensity( double const radius, size_t const idx #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const{ return scanDevs[idx].calcIntensity( @@ -223,7 +223,7 @@ double MultiScanner::calcIntensity( targetArea, radius #ifdef DATA_ANALYTICS - ,pulseRecorder + ,calcIntensityRecords #endif ); } diff --git a/src/scanner/MultiScanner.h b/src/scanner/MultiScanner.h index 37bab0cb6..5c6c578cc 100644 --- a/src/scanner/MultiScanner.h +++ b/src/scanner/MultiScanner.h @@ -197,7 +197,7 @@ class MultiScanner : public Scanner{ double const radius, size_t const idx #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const override; /** diff --git a/src/scanner/Scanner.h b/src/scanner/Scanner.h index 922737de4..85c0fadcf 100644 --- a/src/scanner/Scanner.h +++ b/src/scanner/Scanner.h @@ -500,7 +500,7 @@ class Scanner : public Asset { double const radius, size_t const idx #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const = 0; /** diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index b383d0728..fd516fb02 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -323,7 +323,7 @@ double ScanningDevice::calcIntensity( double const targetArea, double const radius #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const { double bdrf = 0, sigma = 0; @@ -370,10 +370,18 @@ double ScanningDevice::calcIntensity( sigma ) * 1000000000.0; #ifdef DATA_ANALYTICS - pulseRecorder->recordIntensityCalculation( - incidenceAngle, targetRange, targetArea, radius, bdrf, sigma, - receivedPower + std::vector calcIntensityRecord( + 11, std::numeric_limits::quiet_NaN() ); + calcIntensityRecord[3] = incidenceAngle; + calcIntensityRecord[4] = targetRange; + calcIntensityRecord[5] = targetArea; + calcIntensityRecord[6] = radius; + calcIntensityRecord[7] = bdrf; + calcIntensityRecord[8] = sigma; + calcIntensityRecord[9] = receivedPower; + calcIntensityRecord[10] = 0; // By default, assume the point isn't captured + calcIntensityRecords.push_back(calcIntensityRecord); #endif return receivedPower; } diff --git a/src/scanner/ScanningDevice.h b/src/scanner/ScanningDevice.h index 69e0c557b..5f8c111a7 100644 --- a/src/scanner/ScanningDevice.h +++ b/src/scanner/ScanningDevice.h @@ -382,7 +382,7 @@ class ScanningDevice : public Asset { double const targetArea, double const radius #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const; diff --git a/src/scanner/SingleScanner.cpp b/src/scanner/SingleScanner.cpp index df9bb25d5..d1372e820 100644 --- a/src/scanner/SingleScanner.cpp +++ b/src/scanner/SingleScanner.cpp @@ -249,7 +249,7 @@ double SingleScanner::calcIntensity( double const radius, size_t const idx #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const { return scanDev.calcIntensity( @@ -259,7 +259,7 @@ double SingleScanner::calcIntensity( targetArea, radius #ifdef DATA_ANALYTICS - ,pulseRecorder + ,calcIntensityRecords #endif ); } diff --git a/src/scanner/SingleScanner.h b/src/scanner/SingleScanner.h index c565df7c1..3776c156b 100644 --- a/src/scanner/SingleScanner.h +++ b/src/scanner/SingleScanner.h @@ -170,7 +170,7 @@ class SingleScanner : public Scanner{ double const radius, size_t const idx #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ) const override; /** diff --git a/src/scanner/detector/AbstractPulseRunnable.cpp b/src/scanner/detector/AbstractPulseRunnable.cpp index 6bae9fd0b..583a7fa3c 100644 --- a/src/scanner/detector/AbstractPulseRunnable.cpp +++ b/src/scanner/detector/AbstractPulseRunnable.cpp @@ -62,6 +62,10 @@ void AbstractPulseRunnable::capturePoint( std::mutex *allMeasurementsMutex, std::vector *cycleMeasurements, std::mutex *cycleMeasurementsMutex +#ifdef DATA_ANALYTICS + ,std::vector &calcIntensityRecord, + std::shared_ptr pulseRecorder +#endif ) { // Abort if point distance is below mininum scanner range: // TODO Pending : This check is already done in FullWaveformPulseRunnable @@ -77,6 +81,10 @@ void AbstractPulseRunnable::capturePoint( // TODO Pending : Is it necessary to compute position again? Notice it is // known from ray intersection point at FullWaveformPulseRunnable m.position = m.beamOrigin + m.beamDirection * m.distance; +#ifdef DATA_ANALYTICS + calcIntensityRecord[10] = 1; + pulseRecorder->recordIntensityCalculation(calcIntensityRecord); +#endif if(allMeasurements != nullptr){ std::unique_lock lock(*allMeasurementsMutex); allMeasurements->push_back(m); diff --git a/src/scanner/detector/AbstractPulseRunnable.h b/src/scanner/detector/AbstractPulseRunnable.h index 90727e758..8ff5e41f6 100644 --- a/src/scanner/detector/AbstractPulseRunnable.h +++ b/src/scanner/detector/AbstractPulseRunnable.h @@ -7,6 +7,9 @@ class Measurement; #include "LasSpecification.h" class Scanner; #include +#ifdef DATA_ANALYTICS +#include +#endif #include @@ -90,6 +93,10 @@ class AbstractPulseRunnable : public PulseTask{ std::mutex *allMeasurementsMutex, std::vector *cycleMeasurements, std::mutex *cycleMeasurementsMutex +#ifdef DATA_ANALYTICS + ,std::vector &calcIntensityRecord, + std::shared_ptr pulseRecorder +#endif ); /** diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index 20f4adb81..b9b706ce6 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -9,7 +9,6 @@ #include "maths/Rotation.h" #include -#include "MarquardtFitter.h" #include #include #include @@ -58,13 +57,16 @@ void FullWaveformPulseRunnable::operator()( // Ray casting (find intersections) map reflections; vector intersects; +#ifdef DATA_ANALYTICS + std::vector> calcIntensityRecords; +#endif computeSubrays( tMinMax, intersectionHandlingNoiseSource, reflections, intersects #ifdef DATA_ANALYTICS - ,pulseRecorder + ,calcIntensityRecords #endif ); @@ -76,6 +78,10 @@ void FullWaveformPulseRunnable::operator()( beamDir, reflections, intersects +#ifdef DATA_ANALYTICS + ,calcIntensityRecords, + pulseRecorder +#endif ); } @@ -96,7 +102,7 @@ void FullWaveformPulseRunnable::computeSubrays( std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ){ scanner->computeSubrays( @@ -120,7 +126,7 @@ void FullWaveformPulseRunnable::computeSubrays( reflections, intersects #ifdef DATA_ANALYTICS - ,pulseRecorder + ,calcIntensityRecords #endif ); }, @@ -142,7 +148,7 @@ void FullWaveformPulseRunnable::handleSubray( map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ){ // Rotate around the circle: @@ -209,7 +215,7 @@ void FullWaveformPulseRunnable::handleSubray( radius, pulse.getDeviceIndex() #ifdef DATA_ANALYTICS - ,pulseRecorder + ,calcIntensityRecords #endif ); } @@ -256,17 +262,28 @@ void FullWaveformPulseRunnable::handleSubray( ); intersects.push_back(*intersect); } +#ifdef DATA_ANALYTICS + std::vector &calcIntensityRecord = + calcIntensityRecords.back(); + calcIntensityRecord[0] = intersect->point.x; + calcIntensityRecord[1] = intersect->point.y; + calcIntensityRecord[2] = intersect->point.z; +#endif } } } void FullWaveformPulseRunnable::digestIntersections( - std::vector>& apMatrix, + std::vector> &apMatrix, RandomnessGenerator &randGen, RandomnessGenerator &randGen2, glm::dvec3 &beamDir, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder +#endif ){ // Find maximum hit distances double minHitDist_m, maxHitDist_m; @@ -275,6 +292,11 @@ void FullWaveformPulseRunnable::digestIntersections( // If nothing was hit, get out of here if (maxHitDist_m < 0) { scanner->setLastPulseWasHit(false, pulse.getDeviceIndex()); +#ifdef DATA_ANALYTICS + if(!calcIntensityRecords.empty()) { + pulseRecorder->recordIntensityCalculation(calcIntensityRecords); + } +#endif return; } @@ -290,7 +312,12 @@ void FullWaveformPulseRunnable::digestIntersections( distanceThreshold, peakIntensityIndex, numFullwaveBins - )) return; + )){ +#ifdef DATA_ANALYTICS + pulseRecorder->recordIntensityCalculation(calcIntensityRecords); +#endif + return; + } std::vector fullwave(numFullwaveBins, 0.0); // Populate full waveform @@ -317,6 +344,10 @@ void FullWaveformPulseRunnable::digestIntersections( numFullwaveBins, peakIntensityIndex, minHitTime_ns +#ifdef DATA_ANALYTICS + ,calcIntensityRecords, + pulseRecorder +#endif ); // Export measurements and full waveform data @@ -329,6 +360,10 @@ void FullWaveformPulseRunnable::digestIntersections( maxHitTime_ns, randGen, randGen2 +#ifdef DATA_ANALYTICS + ,calcIntensityRecords, + pulseRecorder +#endif ); } @@ -422,6 +457,10 @@ void FullWaveformPulseRunnable::digestFullWaveform( int const numFullwaveBins, int const peakIntensityIndex, double const minHitTime_ns +#ifdef DATA_ANALYTICS + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder +#endif ){ // Extract points from waveform data via Gaussian decomposition size_t const devIdx = pulse.getDeviceIndex(); @@ -437,31 +476,20 @@ void FullWaveformPulseRunnable::digestFullWaveform( double echo_width = 0.0; - for (int i = 0; i < numFullwaveBins; ++i) { - if (fullwave[i] < eps) continue; - - // Continue with next iteration if there is no peak - if(!detectPeak(i, win_size, fullwave)) continue; - - // Gaussian model fitting - if (scanner->isCalcEchowidth()) { - try { - fit.setParameters( - vector{0, fullwave[i], (double) i, 1} - ); - fit.fitData(); - } - catch (std::exception &e) { - logging::ERR(e.what()); - continue; - } - echo_width = fit.getParameters()[3]; - echo_width = echo_width * nsPerBin; +#ifdef DATA_ANALYTICS + std::unordered_set capturedIndices; +#endif - if (echo_width < 0.1) { // TODO Pending : 0.1 to threshold variable - continue; - } - } + for (int i = 0; i < numFullwaveBins; ++i) { + // Skip iteration if the handling of the bin_i does not accept the hit + if(handleFullWaveformBin( + fullwave, + fit, + echo_width, + i, + win_size, + nsPerBin + )) continue; // Compute distance double distance = SPEEDofLIGHT_mPerNanosec * @@ -471,6 +499,10 @@ void FullWaveformPulseRunnable::digestFullWaveform( double minDifference = numeric_limits::max(); shared_ptr closestIntersection = nullptr; +#ifdef DATA_ANALYTICS + size_t intersectionIdx = 0; + size_t closestIntersectionIdx = 0; +#endif for (RaySceneIntersection intersect : intersects) { double const intersectDist = glm::distance( intersect.point, pulse.getOriginRef()); @@ -480,7 +512,13 @@ void FullWaveformPulseRunnable::digestFullWaveform( minDifference = absDistDiff; closestIntersection = make_shared( intersect); +#ifdef DATA_ANALYTICS + closestIntersectionIdx = intersectionIdx; +#endif } +#ifdef DATA_ANALYTICS + ++intersectionIdx; +#endif } string hitObject; @@ -519,11 +557,65 @@ void FullWaveformPulseRunnable::digestFullWaveform( pointsMeasurement.push_back(tmp); ++numReturns; +#ifdef DATA_ANALYTICS + capturedIndices.insert(closestIntersectionIdx); +#endif // Check if maximum number of returns per pulse has been reached if(!scanner->checkMaxNOR(numReturns, devIdx)) break; } +#ifdef DATA_ANALYTICS + // Record all non captured points and remove them from records + size_t const numRecords = calcIntensityRecords.size(); + size_t nonCapturedCount = 0; + for(size_t i = 0 ; i < numRecords ; ++i){ + if(capturedIndices.find(i) == capturedIndices.end()){ + pulseRecorder->recordIntensityCalculation( + calcIntensityRecords[i-nonCapturedCount] + ); + calcIntensityRecords.erase( + calcIntensityRecords.begin()+i-nonCapturedCount + ); + ++nonCapturedCount; + } + } +#endif +} + +bool FullWaveformPulseRunnable::handleFullWaveformBin( + std::vector const &fullwave, + MarquardtFitter &fit, + double &echoWidth, + int const binIndex, + int const winSize, + double const nsPerBin +){ + if (fullwave[binIndex] < eps) return true; + + // Continue with next iteration if there is no peak + if(!detectPeak(binIndex, winSize, fullwave)) return true; + // Gaussian model fitting + if (scanner->isCalcEchowidth()) { + try { + fit.setParameters( + vector{0, fullwave[binIndex], (double) binIndex, 1} + ); + fit.fitData(); + } + catch (std::exception &e) { + logging::ERR(e.what()); + return true; + } + echoWidth = fit.getParameters()[3]; + echoWidth = echoWidth * nsPerBin; + + if (echoWidth < 0.1) { // TODO Pending : 0.1 to threshold variable + return true; + } + } + // Return false as the bin corresponds to an accepted hit + return false; } void FullWaveformPulseRunnable::exportOutput( @@ -535,9 +627,16 @@ void FullWaveformPulseRunnable::exportOutput( double const maxHitTime_ns, RandomnessGenerator &randGen, RandomnessGenerator &randGen2 +#ifdef DATA_ANALYTICS + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder +#endif ){ // ############ END Extract points from waveform data ################ if (numReturns > 0) { +#ifdef DATA_ANALYTICS + size_t i = 0; +#endif for (Measurement & pm : pointsMeasurement) { pm.pulseReturnNumber = numReturns; capturePoint( @@ -547,7 +646,14 @@ void FullWaveformPulseRunnable::exportOutput( scanner->allMeasurementsMutex.get(), scanner->cycleMeasurements.get(), scanner->cycleMeasurementsMutex.get() +#ifdef DATA_ANALYTICS + ,calcIntensityRecords[i], + pulseRecorder +#endif ); +#ifdef DATA_ANALYTICS + ++i; +#endif } if(scanner->isWriteWaveform()) { scanner->setLastPulseWasHit(true, pulse.getDeviceIndex()); @@ -624,7 +730,7 @@ bool FullWaveformPulseRunnable::detectPeak( } } - int size = fullwave.size(); + int const size = fullwave.size(); for (int j = std::min(size, i + 1); j < std::min(size, i + win_size); j++){ if (fullwave[j] < eps || fullwave[j] >= fullwave[i]) { return false; diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index 06ba25c78..f796b0956 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -1,11 +1,12 @@ #pragma once #include -#include "AbstractDetector.h" -#include "AbstractPulseRunnable.h" -#include "FullWaveformPulseDetector.h" -#include "RaySceneIntersection.h" -#include "ScenePart.h" +#include +#include +#include +#include +#include +#include #include #include #ifdef DATA_ANALYTICS @@ -87,7 +88,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ); /** @@ -111,7 +112,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::shared_ptr pulseRecorder + ,std::vector> &calcIntensityRecords #endif ); /** @@ -135,6 +136,10 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { glm::dvec3 &beamDir, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder +#endif ); /** * @brief Find min and max hit distances in meters @@ -206,6 +211,30 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { int const numFullwaveBins, int const peakIntensityIndex, double const minHitTime_ns +#ifdef DATA_ANALYTICS + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder +#endif + ); + /** + * @brief Handle the bin of the fullwave that corresponds to the given + * bin index. + * @param fullwave The fullwave vector. + * @param fit Reference to the MarquardFitter object used to handle the + * fullwave. + * @param echoWidth Output variable to store the echo width. + * @param binIndex Index of the bin to be handled. + * @return True when the handled bin does not correspond to an accepted + * hit, i.e., true to skip the current iteration. False to proceed with + * the computation of the current iteration. + */ + bool handleFullWaveformBin( + std::vector const &fullwave, + MarquardtFitter &fit, + double &echoWidth, + int const binIndex, + int const winSize, + double const nsPerBin ); /** * @brief Export measurements and full waveform data @@ -222,6 +251,10 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { double const maxHitTime_ns, RandomnessGenerator &randGen, RandomnessGenerator &randGen2 +#ifdef DATA_ANALYTICS + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder +#endif ); // *** ASSISTANCE METHODS *** // From 28bb2e3cf4d818385aa5467ea408093bca36b99e Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Wed, 20 Sep 2023 11:30:53 +0200 Subject: [PATCH 06/17] Pulse records plots are now generated in rad and deg. --- .../hda_pulse_calc_intensity_csv_to_laz.sh | 2 +- scripts/debug/hda_pulse_records_plotter.py | 97 ++++++++++++++++--- 2 files changed, 82 insertions(+), 17 deletions(-) diff --git a/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh b/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh index 5e5b1af17..46fca7b98 100755 --- a/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh +++ b/scripts/debug/hda_pulse_calc_intensity_csv_to_laz.sh @@ -38,7 +38,7 @@ fi echo -e "Transforming \"$1\" to \"$2\" ..." mkdir -p $(dirname "$2") ${TXT2LAS} -i "$1" \ - -set_version 1.4 -parse xyz01234567 \ + -set_version 1.4 -parse xyz01234567 -rescale 1e-5 1e-5 1e-5 \ -add_attribute 10 'incidence_angle_rad' 'incidence_angle_rad' \ -add_attribute 10 'target_range_m' 'target_range_m' \ -add_attribute 10 'target_area_m2' 'target_area_m2' \ diff --git a/scripts/debug/hda_pulse_records_plotter.py b/scripts/debug/hda_pulse_records_plotter.py index 0633cfdc2..bae72139b 100755 --- a/scripts/debug/hda_pulse_records_plotter.py +++ b/scripts/debug/hda_pulse_records_plotter.py @@ -161,7 +161,7 @@ def do_incidence_angle_plots(arec, brec, outdir): print('Cannot do incidence angle plots') return - # Do the incidence angle plots + # Do the incidence angle plots (rads) fig = init_figure() # Initialize figure ax = fig.add_subplot(2, 2, 1) # Initialize phi(a) subplot do_incidence_angle_subplot( @@ -200,7 +200,50 @@ def do_incidence_angle_plots(arec, brec, outdir): fig.tight_layout() # Save figure to file and remove it from memory fig.savefig( - os.path.join(outdir, 'incidence_angle_distribution.png') + os.path.join(outdir, 'incidence_angle_distribution_rad.png') + ) + fig.clear() + plt.close(fig) + # Do the incidence angle plots (degrees) + fig = init_figure() # Initialize figure + ax = fig.add_subplot(2, 2, 1) # Initialize phi(a) subplot + do_incidence_angle_subplot( + fig, ax, arec['incidence_angle_rad']*180/np.pi, + label='$\\varphi(a)$', + title='A-Incidence angle ($\\varphi$) in rad', + xlabel='$\\varphi(a)$', + ylabel='cases' + ) + ax = fig.add_subplot(2, 2, 3) # Initialize phi(a) log subplot + do_incidence_angle_subplot( + fig, ax, arec['incidence_angle_rad']*180/np.pi, + label='$\\varphi(a)$', + title='A-Incidence angle ($\\varphi$) in rad (logarithmic)', + xlabel='$\\varphi(a)$', + ylabel='cases', + log=True + ) + ax = fig.add_subplot(2, 2, 2) # Initialize phi(b) subplot + do_incidence_angle_subplot( + fig, ax, brec['incidence_angle_rad']*180/np.pi, + label='$\\varphi(b)$', + title='B-Incidence angle ($\\varphi$) in rad', + xlabel='$\\varphi(b)$', + ylabel='cases' + ) + ax = fig.add_subplot(2, 2, 4) # Initialize phi(a) log subplot + do_incidence_angle_subplot( + fig, ax, brec['incidence_angle_rad']*180/np.pi, + label='$\\varphi(b)$', + title='B-Incidence angle ($\\varphi$) in rad (logarithmic)', + xlabel='$\\varphi(b)$', + ylabel='cases', + log=True + ) + fig.tight_layout() + # Save figure to file and remove it from memory + fig.savefig( + os.path.join(outdir, 'incidence_angle_distribution_degrees.png') ) fig.clear() plt.close(fig) @@ -240,11 +283,34 @@ def do_by_incidence_angle_plots(arec, brec, outdir): not validate_record('received_power', brec, 'b'): print('Cannot do by incidence angle plots') return + # Plot by radians + _do_by_incidence_angle_plots( + arec['incidence_angle_rad'], + brec['incidence_angle_rad'], + arec, + brec, + outdir, + fname='plot_by_incidence_angle_rad.png' + ) + # Plot by degrees + _do_by_incidence_angle_plots( + arec['incidence_angle_rad']*180/np.pi, + brec['incidence_angle_rad']*180/np.pi, + arec, + brec, + outdir, + fname='plot_by_incidence_angle_degrees.png' + ) + + +def _do_by_incidence_angle_plots( + incidence_angle_a, incidence_angle_b, arec, brec, outdir, fname +): # Do the "by incidence angle" plots fig = init_figure() # Initialize figure ax = fig.add_subplot(3, 4, 1) # Initialize target range A subplot do_y_by_x_subplot( - fig, ax, arec['incidence_angle_rad'], arec['target_range_m'], + fig, ax, incidence_angle_a, arec['target_range_m'], title='A-Target range (m)', xlabel='Incidence angle (rad)', ylabel='Target range (m)', @@ -252,7 +318,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 2) # Initialize target area A subplot do_y_by_x_subplot( - fig, ax, arec['incidence_angle_rad'], arec['target_area_m2'], + fig, ax, incidence_angle_a, arec['target_area_m2'], title='A-Target area ($m^2$)', xlabel='Incidence angle (rad)', ylabel='Target area ($m^2$)', @@ -260,7 +326,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 5) # Initialize radius A subplot do_y_by_x_subplot( - fig, ax, arec['incidence_angle_rad'], arec['radius_m'], + fig, ax, incidence_angle_a, arec['radius_m'], title='A-Radius (m)', xlabel='Incidence angle (rad)', ylabel='Radius (m)', @@ -268,7 +334,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 6) # Initialize BDRF A subplot do_y_by_x_subplot( - fig, ax, arec['incidence_angle_rad'], arec['bdrf'], + fig, ax, incidence_angle_a, arec['bdrf'], title='A-BDRF', xlabel='Incidence angle (rad)', ylabel='BDRF', @@ -276,7 +342,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 9) # Initialize Cross-section A subplot do_y_by_x_subplot( - fig, ax, arec['incidence_angle_rad'], arec['cross_section'], + fig, ax, incidence_angle_a, arec['cross_section'], title='A-Cross-section ($m^2$)', xlabel='Incidence angle (rad)', ylabel='Cross-section ($m^2$)', @@ -284,7 +350,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 10) # Initialize received power A subplot do_y_by_x_subplot( - fig, ax, arec['incidence_angle_rad'], arec['received_power'], + fig, ax, incidence_angle_a, arec['received_power'], title='A-Received power', xlabel='Incidence angle (rad)', ylabel='Received power', @@ -292,7 +358,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 3) # Initialize target range B subplot do_y_by_x_subplot( - fig, ax, brec['incidence_angle_rad'], brec['target_range_m'], + fig, ax, incidence_angle_b, brec['target_range_m'], title='B-Target range (m)', xlabel='Incidence angle (rad)', ylabel='Target range (m)', @@ -300,7 +366,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 4) # Initialize target area B subplot do_y_by_x_subplot( - fig, ax, brec['incidence_angle_rad'], brec['target_area_m2'], + fig, ax, incidence_angle_b, brec['target_area_m2'], title='B-Target area ($m^2$)', xlabel='Incidence angle (rad)', ylabel='Target area ($m^2$)', @@ -308,7 +374,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 7) # Initialize radius B subplot do_y_by_x_subplot( - fig, ax, brec['incidence_angle_rad'], brec['radius_m'], + fig, ax, incidence_angle_b, brec['radius_m'], title='B-Radius (m)', xlabel='Incidence angle (rad)', ylabel='Radius (m)', @@ -316,7 +382,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 8) # Initialize BDRF B subplot do_y_by_x_subplot( - fig, ax, brec['incidence_angle_rad'], brec['bdrf'], + fig, ax, incidence_angle_b, brec['bdrf'], title='B-BDRF', xlabel='Incidence angle (rad)', ylabel='BDRF', @@ -324,7 +390,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 11) # Initialize Cross-section B subplot do_y_by_x_subplot( - fig, ax, brec['incidence_angle_rad'], brec['cross_section'], + fig, ax, incidence_angle_b, brec['cross_section'], title='B-Cross-section ($m^2$)', xlabel='Incidence angle (rad)', ylabel='Cross-section ($m^2$)', @@ -332,7 +398,7 @@ def do_by_incidence_angle_plots(arec, brec, outdir): ) ax = fig.add_subplot(3, 4, 12) # Initialize received power B subplot do_y_by_x_subplot( - fig, ax, brec['incidence_angle_rad'], brec['received_power'], + fig, ax, incidence_angle_b, brec['received_power'], title='B-Received power', xlabel='Incidence angle (rad)', ylabel='Received power', @@ -341,13 +407,12 @@ def do_by_incidence_angle_plots(arec, brec, outdir): fig.tight_layout() # Save figure to file and remove it from memory fig.savefig( - os.path.join(outdir, 'plots_by_incidence_angle.png') + os.path.join(outdir, fname) ) fig.clear() plt.close(fig) - # --- M A I N --- # # ------------------- # if __name__ == '__main__': From 70ebc53336b676bea44854cd791f960bf66b1701 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Wed, 20 Sep 2023 17:18:12 +0200 Subject: [PATCH 07/17] HDA now handles subray simulation records. --- scripts/debug/hda_pulse_records_plotter.py | 208 +++++++++++++++++- src/dataanalytics/HDA_GlobalVars.cpp | 118 ++++++++++ src/dataanalytics/HDA_GlobalVars.h | 79 +++++++ src/dataanalytics/HDA_GlobalVarsReporter.h | 55 +++++ src/dataanalytics/HDA_OfstreamWrapper.h | 1 - src/dataanalytics/HDA_PulseRecorder.cpp | 23 ++ src/dataanalytics/HDA_PulseRecorder.h | 35 ++- src/main/Main.cpp | 12 + src/main/helios_version.cpp | 2 +- src/scanner/MultiScanner.cpp | 9 + src/scanner/MultiScanner.h | 6 + src/scanner/Scanner.h | 6 + src/scanner/ScanningDevice.cpp | 26 +++ src/scanner/ScanningDevice.h | 6 + src/scanner/SingleScanner.cpp | 9 + src/scanner/SingleScanner.h | 6 + .../detector/FullWaveformPulseRunnable.cpp | 64 ++++-- .../detector/FullWaveformPulseRunnable.h | 6 +- 18 files changed, 651 insertions(+), 20 deletions(-) create mode 100644 src/dataanalytics/HDA_GlobalVars.cpp create mode 100644 src/dataanalytics/HDA_GlobalVars.h create mode 100644 src/dataanalytics/HDA_GlobalVarsReporter.h diff --git a/scripts/debug/hda_pulse_records_plotter.py b/scripts/debug/hda_pulse_records_plotter.py index bae72139b..524871fd4 100755 --- a/scripts/debug/hda_pulse_records_plotter.py +++ b/scripts/debug/hda_pulse_records_plotter.py @@ -76,6 +76,9 @@ def read_records(path, sep=','): intensity_calc = read_record(os.path.join( path, 'intensity_calc.csv' ), sep) + subray_sim = read_record(os.path.join( + path, 'subray_sim.csv' + ), sep) # Return key-word records return { # Intensity calculation records @@ -85,7 +88,13 @@ def read_records(path, sep=','): 'radius_m': intensity_calc[:, 6], 'bdrf': intensity_calc[:, 7], 'cross_section': intensity_calc[:, 8], - 'received_power': intensity_calc[:, 9] + 'received_power': intensity_calc[:, 9], + # Subray simulation records + 'subray_hit': subray_sim[:, 0].astype(bool), + 'radius_step': subray_sim[:, 1], + 'circle_steps': subray_sim[:, 2], + 'circle_step': subray_sim[:, 3], + 'divergence_angle_rad': subray_sim[:, 4] } @@ -110,6 +119,7 @@ def plot_records(arec, brec, outdir): """ do_incidence_angle_plots(arec, brec, outdir) do_by_incidence_angle_plots(arec, brec, outdir) + do_subray_hit_plots(arec, brec, outdir) def validate_record(key, rec, recid): @@ -413,6 +423,202 @@ def _do_by_incidence_angle_plots( plt.close(fig) +def do_subray_hit_subplot_hist2d( + fig, ax, x, y, title=None, xlabel=None, ylabel=None, bins="auto" +): + if title is not None: + ax.set_title(title, fontsize=15) + if bins == "auto": + bins = [len(np.unique(x)), len(np.unique(y))] + hist2d = ax.hist2d( + x, y, bins=bins, cmap='viridis', + weights=100*np.ones_like(x)/len(x), + edgecolors='black' + ) + fig.colorbar(hist2d[3]) + if xlabel is not None: + ax.set_xlabel(xlabel, fontsize=14) + if ylabel is not None: + ax.set_ylabel(ylabel, fontsize=14) + ax.tick_params(axis='both', which='both', labelsize=12) + ax.grid('both') + ax.set_axisbelow(True) + + +def do_subray_hit_subplot_hist( + fig, ax, hit, x, title=None, xlabel=None, ylabel=None, bins=7, + relative=False +): + # TODO Rethink : Implement + if title is not None: + ax.set_title(title, fontsize=15) + x_hit = x[hit] + x_nohit = x[~hit] + weights = [ + 100*np.ones_like(x_hit)/len(x_hit), + 100*np.ones_like(x_nohit)/len(x_nohit) + ] if relative else None + hist = ax.hist( + [x_hit, x_nohit], bins=bins, label=['hit', 'miss'], weights=weights + ) + if xlabel is not None: + ax.set_xlabel(xlabel, fontsize=14) + if ylabel is not None: + ax.set_ylabel(ylabel, fontsize=14) + ax.tick_params(axis='both', which='both', labelsize=14) + ax.legend(loc='upper right', fontsize=12) + ax.grid('both') + ax.set_axisbelow(True) + + +def do_subray_hit_plots(arec, brec, outdir): + # Validate subray hit data + if(not validate_record('subray_hit', arec, 'a') or + not validate_record('radius_step', arec, 'a') or + not validate_record('circle_steps', arec, 'a') or + not validate_record('circle_step', arec, 'a') or + not validate_record('divergence_angle_rad', arec, 'a') or + not validate_record('subray_hit', brec, 'b') or + not validate_record('radius_step', brec, 'b') or + not validate_record('circle_steps', brec, 'b') or + not validate_record('circle_step', brec, 'b') or + not validate_record('divergence_angle_rad', brec, 'b') + ): + print('Cannot do subray hit plots') + return + + # Do the subray hit plots + fig = init_figure() # Initialize figure + # CASE A + ax = fig.add_subplot(4, 5, 1) # Initialize hit2Dhist on (radstep,circstep) + do_subray_hit_subplot_hist2d( + fig, ax, + arec['circle_step'][arec['subray_hit']], + arec['radius_step'][arec['subray_hit']], + title='Hit distribution (100%) (A)', + ) + ax = fig.add_subplot(4, 5, 2) # Initialize a hist on radius step by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['radius_step'], + ylabel='Absolute' + ) + ax = fig.add_subplot(4, 5, 3) # Initialize a hist on circle steps by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['circle_steps'], + ) + ax = fig.add_subplot(4, 5, 4) # Initialize a hist on circle step by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['circle_step'], + ) + ax = fig.add_subplot(4, 5, 5) # Initialize a hist on div. angle by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], + 1e03*arec['divergence_angle_rad']*180/np.pi, + ) + ax = fig.add_subplot(4, 5, 6) # Initialize non-hit 2D hist on (rs, cs) + do_subray_hit_subplot_hist2d( + fig, ax, + arec['circle_step'][~arec['subray_hit']], + arec['radius_step'][~arec['subray_hit']], + title='No-hit distribution (100%)', + xlabel='Circle step', + ylabel='Radius step' + ) + ax = fig.add_subplot(4, 5, 7) # Initialize a hist on radius step by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['radius_step'], + ylabel='Relative ($100\\%$)', + relative=True, + xlabel='Radius step' + ) + ax = fig.add_subplot(4, 5, 8) # Initialize a hist on circle steps by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['circle_steps'], + relative=True, + xlabel='Circle steps' + ) + ax = fig.add_subplot(4, 5, 9) # Initialize a hist on circle step by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['circle_step'], + relative=True, + xlabel='Circle step' + ) + ax = fig.add_subplot(4, 5, 10) # Initialize a hist on div. angle by hit + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], + 1e03*arec['divergence_angle_rad']*180/np.pi, + relative=True, + xlabel='Divergence angle (deg $\\times 10^{-3}$)' + ) + # CASE B + ax = fig.add_subplot(4, 5, 11) # Initialize hit2Dhist on (radstep,circstep) + do_subray_hit_subplot_hist2d( + fig, ax, + brec['circle_step'][brec['subray_hit']], + brec['radius_step'][brec['subray_hit']], + title='Hit distribution (100%) (B)', + ) + ax = fig.add_subplot(4, 5, 12) # Initialize a hist on radius step by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], brec['radius_step'], + ylabel='Absolute' + ) + ax = fig.add_subplot(4, 5, 13) # Initialize a hist on circle steps by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], brec['circle_steps'], + ) + ax = fig.add_subplot(4, 5, 14) # Initialize a hist on circle step by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], brec['circle_step'], + ) + ax = fig.add_subplot(4, 5, 15) # Initialize a hist on div. angle by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], + 1e03*brec['divergence_angle_rad']*180/np.pi, + ) + ax = fig.add_subplot(4, 5, 16) # Initialize non-hit 2D hist on (rs, cs) + do_subray_hit_subplot_hist2d( + fig, ax, + brec['circle_step'][~brec['subray_hit']], + brec['radius_step'][~brec['subray_hit']], + title='No-hit distribution (100%)', + xlabel='Circle step', + ylabel='Radius step' + ) + ax = fig.add_subplot(4, 5, 17) # Initialize a hist on radius step by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], brec['radius_step'], + ylabel='Relative ($100\\%$)', + relative=True, + xlabel='Radius step' + ) + ax = fig.add_subplot(4, 5, 18) # Initialize a hist on circle steps by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], brec['circle_steps'], + relative=True, + xlabel='Circle steps' + ) + ax = fig.add_subplot(4, 5, 19) # Initialize a hist on circle step by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], brec['circle_step'], + relative=True, + xlabel='Circle step' + ) + ax = fig.add_subplot(4, 5, 20) # Initialize a hist on div. angle by hit + do_subray_hit_subplot_hist( + fig, ax, brec['subray_hit'], + 1e03*brec['divergence_angle_rad']*180/np.pi, + relative=True, + xlabel='Divergence angle (deg $\\times 10^{-3}$)' + ) + # TODO Rethink : Implement + fig.tight_layout() + # Save figure to file and remove it from memory + fig.savefig(os.path.join(outdir, 'subray_hit_plots.png')) + fig.clear() + plt.close(fig) + + # --- M A I N --- # # ------------------- # if __name__ == '__main__': diff --git a/src/dataanalytics/HDA_GlobalVars.cpp b/src/dataanalytics/HDA_GlobalVars.cpp new file mode 100644 index 000000000..f3964f8e6 --- /dev/null +++ b/src/dataanalytics/HDA_GlobalVars.cpp @@ -0,0 +1,118 @@ +#ifdef DATA_ANALYTICS +#include + +namespace helios { namespace analytics{ + + +// *** GLOBAL OBJECT *** // +// *********************** // +HDA_GlobalVars HDA_GV; + +// *** WRITE METHODS *** // +// *********************** // +HDA_GlobalVars & HDA_GlobalVars::incrementGeneratedSubraysCount(){ + std::unique_lock lock(generatedSubraysCount_mutex); + ++generatedSubraysCount; + return *this; +} + +HDA_GlobalVars & + HDA_GlobalVars::incrementGeneratedRaysBeforeEarlyAbortCount(){ + std::unique_lock lock( + generatedRaysBeforeEarlyAbortCount_mutex + ); + ++generatedRaysBeforeEarlyAbortCount; + return *this; +} + +HDA_GlobalVars & + HDA_GlobalVars::incrementGeneratedRaysAfterEarlyAbortCount(){ + std::unique_lock lock( + generatedRaysAfterEarlyAbortCount_mutex + ); + ++generatedRaysAfterEarlyAbortCount; + return *this; +} + +HDA_GlobalVars & + HDA_GlobalVars::incrementIntensityComputationsCount() { + std::unique_lock lock(intensityComputationsCount_mutex); + ++intensityComputationsCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementIntersectiveSubraysCount(){ + std::unique_lock lock(intersectiveSubraysCount_mutex); + ++intersectiveSubraysCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementNonIntersectiveSubraysCount(){ + std::unique_lock lock(nonIntersectiveSubraysCount_mutex); + ++nonIntersectiveSubraysCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementSubrayIntersectionCount() { + std::unique_lock lock(subrayIntersectionCount_mutex); + ++subrayIntersectionCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementSubrayNonIntersectionCount() { + std::unique_lock lock(subrayNonIntersectionCount_mutex); + ++subrayNonIntersectionCount; + return *this; +} + +// *** READ METHODS *** // +// ********************** // +std::size_t HDA_GlobalVars::getGeneratedSubraysCount(){ + std::unique_lock lock(generatedSubraysCount_mutex); + return generatedSubraysCount; +} + +std::size_t HDA_GlobalVars::getGeneratedRaysBeforeEarlyAbortCount(){ + std::unique_lock lock( + generatedRaysBeforeEarlyAbortCount_mutex + ); + return generatedRaysBeforeEarlyAbortCount; +} + +std::size_t HDA_GlobalVars::getGeneratedRaysAfterEarlyAbortCount(){ + std::unique_lock lock( + generatedRaysAfterEarlyAbortCount_mutex + ); + return generatedRaysAfterEarlyAbortCount; +} + +std::size_t HDA_GlobalVars::getIntersectiveSubraysCount() { + std::unique_lock lock(intersectiveSubraysCount_mutex); + return intersectiveSubraysCount; +} + +std::size_t HDA_GlobalVars::getNonIntersectiveSubraysCount() { + std::unique_lock lock(nonIntersectiveSubraysCount_mutex); + return nonIntersectiveSubraysCount; +} + +std::size_t HDA_GlobalVars::getSubrayIntersectionCount() { + std::unique_lock lock(subrayIntersectionCount_mutex); + return subrayIntersectionCount; +} + +std::size_t HDA_GlobalVars::getSubrayNonIntersectionCount() { + std::unique_lock lock(subrayNonIntersectionCount_mutex); + return subrayNonIntersectionCount; +} + +std::size_t HDA_GlobalVars::getIntensityComputationsCount(){ + std::unique_lock lock(intensityComputationsCount_mutex); + return intensityComputationsCount; +} + + + +}} + +#endif diff --git a/src/dataanalytics/HDA_GlobalVars.h b/src/dataanalytics/HDA_GlobalVars.h new file mode 100644 index 000000000..024f97e91 --- /dev/null +++ b/src/dataanalytics/HDA_GlobalVars.h @@ -0,0 +1,79 @@ +#ifdef DATA_ANALYTICS +#pragma once +#include +#include + +namespace helios { namespace analytics{ + +// *** GLOBAL OBJECT *** // +// *********************** // +extern class HDA_GlobalVars HDA_GV; + +// TODO Rethink : Document +class HDA_GlobalVars{ +public: + // *** ATTRIBUTES *** // + // ******************** // + std::size_t generatedRaysBeforeEarlyAbortCount; + std::size_t generatedRaysAfterEarlyAbortCount; + std::size_t generatedSubraysCount; + std::size_t intersectiveSubraysCount; + std::size_t nonIntersectiveSubraysCount; + std::size_t subrayIntersectionCount; + std::size_t subrayNonIntersectionCount; + std::size_t intensityComputationsCount; + +protected: + // *** CONCURRENCY HANDLING ATTRIBUTES *** // + // ***************************************** // + std::mutex generatedRaysBeforeEarlyAbortCount_mutex; + std::mutex generatedRaysAfterEarlyAbortCount_mutex; + std::mutex generatedSubraysCount_mutex; + std::mutex intersectiveSubraysCount_mutex; + std::mutex nonIntersectiveSubraysCount_mutex; + std::mutex subrayIntersectionCount_mutex; + std::mutex subrayNonIntersectionCount_mutex; + std::mutex intensityComputationsCount_mutex; + +public: + // *** CONSTRUCTION / DESTRUCTION *** // + // ************************************ // + HDA_GlobalVars() : + generatedRaysBeforeEarlyAbortCount(0), + generatedRaysAfterEarlyAbortCount(0), + generatedSubraysCount(0), + intersectiveSubraysCount(0), + nonIntersectiveSubraysCount(0), + subrayIntersectionCount(0), + subrayNonIntersectionCount(0), + intensityComputationsCount(0) + {} + virtual ~HDA_GlobalVars() = default; + + // *** WRITE METHODS *** // + // *********************** // + HDA_GlobalVars & incrementGeneratedRaysBeforeEarlyAbortCount(); + HDA_GlobalVars & incrementGeneratedRaysAfterEarlyAbortCount(); + HDA_GlobalVars & incrementGeneratedSubraysCount(); + HDA_GlobalVars & incrementIntersectiveSubraysCount(); + HDA_GlobalVars & incrementNonIntersectiveSubraysCount(); + HDA_GlobalVars & incrementSubrayIntersectionCount(); + HDA_GlobalVars & incrementSubrayNonIntersectionCount(); + HDA_GlobalVars & incrementIntensityComputationsCount(); + + // *** READ METHODS *** // + // ********************** // + std::size_t getGeneratedSubraysCount(); + std::size_t getGeneratedRaysBeforeEarlyAbortCount(); + std::size_t getGeneratedRaysAfterEarlyAbortCount(); + std::size_t getIntersectiveSubraysCount(); + std::size_t getNonIntersectiveSubraysCount(); + std::size_t getSubrayIntersectionCount(); + std::size_t getSubrayNonIntersectionCount(); + std::size_t getIntensityComputationsCount(); + +}; + +}} + +#endif diff --git a/src/dataanalytics/HDA_GlobalVarsReporter.h b/src/dataanalytics/HDA_GlobalVarsReporter.h new file mode 100644 index 000000000..4f03dc431 --- /dev/null +++ b/src/dataanalytics/HDA_GlobalVarsReporter.h @@ -0,0 +1,55 @@ +#ifdef DATA_ANALYTICS +#pragma once +#include +#include + +#include +#include + +namespace helios { namespace analytics{ + +// TODO Rethink : Document +class HDA_GlobalVarsReporter{ +protected: + // *** ATTRIBUTES *** // + // ******************** // + HDA_GlobalVars & gv; + +public: + // *** CONSTRUCTION / DESTRUCTION *** // + // ************************************ // + explicit HDA_GlobalVarsReporter(HDA_GlobalVars &gv) : gv(gv) {} + virtual ~HDA_GlobalVarsReporter() = default; + + // *** PRINT *** // + // ***************** // + void print(){ + // Initialize string stream to build the print + std::stringstream ss; + + // Print global variables + ss << "HDA GLOBAL VARS REPORT:\n\n"; + ss << "Generated rays before early abort: " + << gv.getGeneratedRaysBeforeEarlyAbortCount() << "\n"; + ss << "Generated rays after early abort: " + << gv.getGeneratedRaysAfterEarlyAbortCount() << "\n"; + ss << "Generated subrays: " << gv.getGeneratedSubraysCount() << "\n"; + ss << "Intersective subrays: " + << gv.getIntersectiveSubraysCount() << "\n"; + ss << "Non-intersective subrays: " + << gv.getNonIntersectiveSubraysCount() << "\n"; + ss << "Subray intersections: " + << gv.getSubrayIntersectionCount() << "\n"; + ss << "Subray non-intersections: " + << gv.getSubrayNonIntersectionCount() << "\n"; + ss << "Number of computed intensities: " + << gv.getIntensityComputationsCount() << "\n"; + // Print through info logging level system + std::string text = ss.str(); + logging::INFO(ss.str()); + } +}; + +}} + +#endif diff --git a/src/dataanalytics/HDA_OfstreamWrapper.h b/src/dataanalytics/HDA_OfstreamWrapper.h index b9fb094d1..88df13ac2 100644 --- a/src/dataanalytics/HDA_OfstreamWrapper.h +++ b/src/dataanalytics/HDA_OfstreamWrapper.h @@ -4,7 +4,6 @@ #include #include -// TODO Rethink : Document namespace helios { namespace analytics{ diff --git a/src/dataanalytics/HDA_PulseRecorder.cpp b/src/dataanalytics/HDA_PulseRecorder.cpp index 715d683a2..e8518898d 100644 --- a/src/dataanalytics/HDA_PulseRecorder.cpp +++ b/src/dataanalytics/HDA_PulseRecorder.cpp @@ -9,6 +9,7 @@ using namespace helios::analytics; bool HDA_PulseRecorder::isAnyBufferOpen(){ bool anyOpen = false; anyOpen |= intensityCalc->isOpen(); + anyOpen |= subraySim->isOpen(); return anyOpen; } @@ -22,12 +23,19 @@ void HDA_PulseRecorder::openBuffers(){ sep, true // vectorial flag ); + subraySim = std::make_shared>>( + craftOutputPath("subray_sim.csv"), + maxSize, + sep, + true // vectorial flag + ); } void HDA_PulseRecorder::closeBuffers(){ // Close subray buffers std::unique_lock lock(intensityCalcMutex); intensityCalc->close(); + subraySim->close(); } @@ -48,4 +56,19 @@ void HDA_PulseRecorder::recordIntensityCalculation( } } +void HDA_PulseRecorder::recordSubraySimuilation( + std::vector const &record +){ + std::unique_lock lock(subraySimMutex); + subraySim->push(record); +} + +void HDA_PulseRecorder::recordSubraySimulation( + std::vector> const &records +){ + std::unique_lock lock(subraySimMutex); + for(std::vector const & record : records){ + subraySim->push(record); + } +} #endif diff --git a/src/dataanalytics/HDA_PulseRecorder.h b/src/dataanalytics/HDA_PulseRecorder.h index b96cddbdd..fa862732d 100644 --- a/src/dataanalytics/HDA_PulseRecorder.h +++ b/src/dataanalytics/HDA_PulseRecorder.h @@ -23,7 +23,7 @@ class HDA_PulseRecorder : public HDA_Recorder{ // *** ATTRIBUTES *** // // ******************** // /** - * @brief The vector which components are variables involved on a + * @brief The vectors which components are variables involved on a * particular intensity calculation for a given subray. * * [0, 1, 2] -> \f$(x, y, z)\f$ @@ -47,12 +47,32 @@ class HDA_PulseRecorder : public HDA_Recorder{ * [10] -> 1 if the point was captured, 0 otherwise. */ std::shared_ptr>> intensityCalc; + /** + * @brief The vectors which components are variables involved on the + * subray simulation. + * + * [0] -> Subray hit (0 does not hit, 1 hit) + * + * [1] -> Radius step + * + * [2] -> Circle steps + * + * [3] -> Circle step + * + * [4] -> Divergence angle (in rad) + */ + std::shared_ptr>> subraySim; /** * @brief The mutex to handle concurrent writes to the buffers related to * intensity calculation. */ std::mutex intensityCalcMutex; + /** + * @brief The mutex to handle concurrent writes to the buffers related to + * subray simulation. + */ + std::mutex subraySimMutex; public: // *** CONSTRUCTION / DESTRUCTION *** // @@ -106,6 +126,19 @@ class HDA_PulseRecorder : public HDA_Recorder{ virtual void recordIntensityCalculation( std::vector> const &records ); + /** + * @brief Handle all the records for the current subray simulation. + */ + virtual void recordSubraySimuilation(std::vector const &record); + /** + * @brief Like + * HDA_PulseRecorder::recordSubraySimulation(std::vector) + * but receiving many records at once. + * @see HDA_PulseRecorder::recordSubraySimulation(std::vector) + */ + virtual void recordSubraySimulation( + std::vector> const &records + ); }; diff --git a/src/main/Main.cpp b/src/main/Main.cpp index 7644a18f8..ceeb82479 100644 --- a/src/main/Main.cpp +++ b/src/main/Main.cpp @@ -9,6 +9,11 @@ #include #endif +#ifdef DATA_ANALYTICS +#include +#include +#endif + #include #include @@ -161,6 +166,13 @@ int main(int argc, char** argv) { ); } +#ifdef DATA_ANALYTICS + helios::analytics::HDA_GlobalVarsReporter reporter( + helios::analytics::HDA_GV + ); + reporter.print(); +#endif + // Return successful exit status code (0) return EXIT_SUCCESS; } diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index 481e9f2cb..e8e4a5cc4 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "9f5ba7f6"; +const char * HELIOS_GIT_HASH = "28bb2e3c"; const char * getHeliosVersion(){ return HELIOS_VERSION; diff --git a/src/scanner/MultiScanner.cpp b/src/scanner/MultiScanner.cpp index c12dc2e36..e60eaa2a5 100644 --- a/src/scanner/MultiScanner.cpp +++ b/src/scanner/MultiScanner.cpp @@ -166,12 +166,18 @@ void MultiScanner::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ){ scanDevs[idx].computeSubrays( handleSubray, @@ -179,6 +185,9 @@ void MultiScanner::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } diff --git a/src/scanner/MultiScanner.h b/src/scanner/MultiScanner.h index 5c6c578cc..f04c47341 100644 --- a/src/scanner/MultiScanner.h +++ b/src/scanner/MultiScanner.h @@ -165,12 +165,18 @@ class MultiScanner : public Scanner{ NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) override; /** * @see Scanner::initializeFullWaveform diff --git a/src/scanner/Scanner.h b/src/scanner/Scanner.h index 85c0fadcf..78bb769eb 100644 --- a/src/scanner/Scanner.h +++ b/src/scanner/Scanner.h @@ -450,12 +450,18 @@ class Scanner : public Asset { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) = 0; /** diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index fd516fb02..5e61ce83e 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -3,6 +3,10 @@ #include #include #include +#ifdef DATA_ANALYTICS +#include +using namespace helios::analytics; +#endif // *** CONSTRUCTION / DESTRUCTION *** // // ************************************ // @@ -222,12 +226,21 @@ void ScanningDevice::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, std::vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, std::vector &intersects +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ){ +#ifdef DATA_ANALYTICS + bool subrayHit; +#endif int const beamSampleQuality = FWF_settings.beamSampleQuality; double const radiusStep_rad = beamDivergence_rad/beamSampleQuality; @@ -260,7 +273,20 @@ void ScanningDevice::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects +#ifdef DATA_ANALYTICS + ,subrayHit +#endif ); +#ifdef DATA_ANALYTICS + HDA_GV.incrementGeneratedSubraysCount(); + pulseRecorder->recordSubraySimuilation(std::vector({ + (double)subrayHit, + (double) radiusStep, + (double) circleSteps, + (double) circleStep, + subrayDivergenceAngle_rad + })); +#endif } } } diff --git a/src/scanner/ScanningDevice.h b/src/scanner/ScanningDevice.h index 5f8c111a7..4e919c1d5 100644 --- a/src/scanner/ScanningDevice.h +++ b/src/scanner/ScanningDevice.h @@ -308,11 +308,17 @@ class ScanningDevice : public Asset { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, std::vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, std::vector &intersects +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ); /** * @see Scanner::initializeFullWaveform diff --git a/src/scanner/SingleScanner.cpp b/src/scanner/SingleScanner.cpp index d1372e820..1a7c11b80 100644 --- a/src/scanner/SingleScanner.cpp +++ b/src/scanner/SingleScanner.cpp @@ -202,12 +202,18 @@ void SingleScanner::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ){ scanDev.computeSubrays( handleSubray, @@ -215,6 +221,9 @@ void SingleScanner::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } diff --git a/src/scanner/SingleScanner.h b/src/scanner/SingleScanner.h index 3776c156b..34bb88bcb 100644 --- a/src/scanner/SingleScanner.h +++ b/src/scanner/SingleScanner.h @@ -138,12 +138,18 @@ class SingleScanner : public Scanner{ NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif )> handleSubray, vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, size_t const idx +#ifdef DATA_ANALYTICS + ,std::shared_ptr pulseRecorder +#endif ) override; /** * @see Scanner::initializeFullWaveform diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index b9b706ce6..aac64abba 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -15,6 +15,11 @@ #include #include +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_GV; +#endif + using namespace std; // *** CONSTANTS *** // @@ -48,11 +53,17 @@ void FullWaveformPulseRunnable::operator()( pulse.getOriginRef(), beamDir ); +#ifdef DATA_ANALYTICS + HDA_GV.incrementGeneratedRaysBeforeEarlyAbortCount(); +#endif if (tMinMax.empty()) { logging::DEBUG("Early abort - beam does not intersect with the scene"); scanner->setLastPulseWasHit(false, pulse.getDeviceIndex()); return; } +#ifdef DATA_ANALYTICS + HDA_GV.incrementGeneratedRaysAfterEarlyAbortCount(); +#endif // Ray casting (find intersections) map reflections; @@ -66,7 +77,8 @@ void FullWaveformPulseRunnable::operator()( reflections, intersects #ifdef DATA_ANALYTICS - ,calcIntensityRecords + ,calcIntensityRecords, + pulseRecorder #endif ); @@ -102,7 +114,8 @@ void FullWaveformPulseRunnable::computeSubrays( std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::vector> &calcIntensityRecords + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder #endif ){ scanner->computeSubrays( @@ -115,6 +128,9 @@ void FullWaveformPulseRunnable::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects +#ifdef DATA_ANALYTICS + ,bool &subrayHit +#endif ) -> void { handleSubray( _tMinMax, @@ -126,7 +142,8 @@ void FullWaveformPulseRunnable::computeSubrays( reflections, intersects #ifdef DATA_ANALYTICS - ,calcIntensityRecords + ,subrayHit, + calcIntensityRecords #endif ); }, @@ -135,6 +152,9 @@ void FullWaveformPulseRunnable::computeSubrays( reflections, intersects, pulse.getDeviceIndex() +#ifdef DATA_ANALYTICS + ,pulseRecorder +#endif ); } @@ -148,9 +168,13 @@ void FullWaveformPulseRunnable::handleSubray( map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::vector> &calcIntensityRecords + ,bool &subrayHit, + std::vector> &calcIntensityRecords #endif ){ +#ifdef DATA_ANALYTICS + subrayHit = false; +#endif // Rotate around the circle: vector tMinMax = _tMinMax; Rotation r2 = Rotation(Directions::forward, circleStep_rad * circleStep); @@ -171,8 +195,12 @@ void FullWaveformPulseRunnable::handleSubray( ); if (intersect != nullptr && intersect->prim != nullptr) { +#ifdef DATA_ANALYTICS + HDA_GV.incrementSubrayIntersectionCount(); + subrayHit = true; +#endif // Incidence angle: - if(!scanner->isFixedIncidenceAngle()) { + if (!scanner->isFixedIncidenceAngle()) { incidenceAngle = intersect->prim->getIncidenceAngle_rad( pulse.getOriginRef(), @@ -188,7 +216,7 @@ void FullWaveformPulseRunnable::handleSubray( ); // Distance must be inside [rangeMin, rangeMax] interval - if(detector->isDistanceNotInRange(distance)) continue; + if (detector->isDistanceNotInRange(distance)) continue; // Distance between beam's center line and intersection point: double const radius = sin(divergenceAngle) * distance; @@ -196,7 +224,7 @@ void FullWaveformPulseRunnable::handleSubray( distance, pulse.getDeviceIndex() ); double intensity = 0.0; - if(intersect->prim->canComputeSigmaWithLadLut()){ + if (intersect->prim->canComputeSigmaWithLadLut()) { // LadLut based intensity computation double sigma = intersect->prim->computeSigmaWithLadLut( subrayDirection @@ -204,9 +232,11 @@ void FullWaveformPulseRunnable::handleSubray( intensity = scanner->calcIntensity( distance, radius, sigma, pulse.getDeviceIndex() ); - } - else{ + } else { // Lighting-based intensity computation +#ifdef DATA_ANALYTICS + HDA_GV.incrementIntensityComputationsCount(); +#endif intensity = scanner->calcIntensity( incidenceAngle, distance, @@ -215,14 +245,14 @@ void FullWaveformPulseRunnable::handleSubray( radius, pulse.getDeviceIndex() #ifdef DATA_ANALYTICS - ,calcIntensityRecords + , calcIntensityRecords #endif ); } // Intersection handling - if(intersect->prim->canHandleIntersections()) { + if (intersect->prim->canHandleIntersections()) { glm::dvec3 outsideIntersectionPoint = RayUtils::obtainPointAfterTraversing( *intersect->prim->getAABB(), @@ -247,15 +277,14 @@ void FullWaveformPulseRunnable::handleSubray( subrayDirection ); rayContinues = true; - } - else{ // Update distance considering noise + } else { // Update distance considering noise distance = glm::distance( ihr.getIntersectionPoint(), pulse.getOriginRef() ); } } - if(!rayContinues) { // If ray is not continuing + if (!rayContinues) { // If ray is not continuing // Then register hit by default reflections.insert( pair(distance, intensity) @@ -268,9 +297,16 @@ void FullWaveformPulseRunnable::handleSubray( calcIntensityRecord[0] = intersect->point.x; calcIntensityRecord[1] = intersect->point.y; calcIntensityRecord[2] = intersect->point.z; + } + else { + HDA_GV.incrementSubrayNonIntersectionCount(); #endif } } +#ifdef DATA_ANALYTICS + if(subrayHit) HDA_GV.incrementIntersectiveSubraysCount(); + else HDA_GV.incrementNonIntersectiveSubraysCount(); +#endif } void FullWaveformPulseRunnable::digestIntersections( diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index f796b0956..0ca586486 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -88,7 +88,8 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::vector> &calcIntensityRecords + ,std::vector> &calcIntensityRecords, + std::shared_ptr pulseRecorder #endif ); /** @@ -112,7 +113,8 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,std::vector> &calcIntensityRecords + ,bool &subrayHit, + std::vector> &calcIntensityRecords #endif ); /** From 401f71220a3b0e3956bd8c9bbaa6e206ceb3ef7f Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Mon, 25 Sep 2023 13:45:39 +0200 Subject: [PATCH 08/17] Solved ray-box intersection issue for early aborts --- scripts/debug/hda_pulse_records_plotter.py | 217 +++++++++++++++++- src/alg/raycast/GroveKDTreeRaycaster.h | 8 + src/alg/raycast/KDGroveRaycaster.cpp | 10 +- src/alg/raycast/KDGroveRaycaster.h | 4 + src/alg/raycast/KDTreeRaycaster.cpp | 157 ++++++++++++- src/alg/raycast/KDTreeRaycaster.h | 14 ++ src/alg/raycast/Raycaster.h | 4 + src/dataanalytics/HDA_GlobalVars.cpp | 117 ++++++++++ src/dataanalytics/HDA_GlobalVars.h | 38 ++- src/dataanalytics/HDA_GlobalVarsReporter.h | 40 ++++ src/dataanalytics/HDA_PulseRecorder.cpp | 2 +- src/dataanalytics/HDA_PulseRecorder.h | 45 +++- src/scanner/MultiScanner.cpp | 3 +- src/scanner/MultiScanner.h | 3 +- src/scanner/Scanner.h | 3 +- src/scanner/ScanningDevice.cpp | 27 ++- src/scanner/ScanningDevice.h | 3 +- src/scanner/SingleScanner.cpp | 3 +- src/scanner/SingleScanner.h | 3 +- .../detector/DynFullWaveformPulseRunnable.cpp | 7 + .../detector/DynFullWaveformPulseRunnable.h | 3 + .../detector/FullWaveformPulseRunnable.cpp | 59 ++++- .../detector/FullWaveformPulseRunnable.h | 6 +- src/scene/Scene.cpp | 43 ++++ src/scene/Scene.h | 4 + src/scene/primitives/AABB.cpp | 5 +- src/scene/primitives/AABB.h | 21 ++ 27 files changed, 811 insertions(+), 38 deletions(-) diff --git a/scripts/debug/hda_pulse_records_plotter.py b/scripts/debug/hda_pulse_records_plotter.py index 524871fd4..ecff9d91c 100755 --- a/scripts/debug/hda_pulse_records_plotter.py +++ b/scripts/debug/hda_pulse_records_plotter.py @@ -94,7 +94,20 @@ def read_records(path, sep=','): 'radius_step': subray_sim[:, 1], 'circle_steps': subray_sim[:, 2], 'circle_step': subray_sim[:, 3], - 'divergence_angle_rad': subray_sim[:, 4] + 'divergence_angle_rad': subray_sim[:, 4], + 'ray_dir_norm': subray_sim[:, 5], + 'subray_dir_norm': subray_sim[:, 6], + 'ray_subray_angle_rad': subray_sim[:, 7], + 'ray_subray_sign_check': subray_sim[:, 8], + 'subray_tmin': subray_sim[:, 9], + 'subray_tmax': subray_sim[:, 10], + 'subray_rt_pos_dir': subray_sim[:, 11], # Ray-tracing positive dir. + 'subray_rt_neg_dir': subray_sim[:, 12], # Ray-tracing negative dir. + 'subray_rt_par_dir': subray_sim[:, 13], # Ray-tracing parallel dir. + 'subray_rt_no_second': subray_sim[:, 14], # Ray-tracing no second half + 'subray_rt_no_first': subray_sim[:, 15], # Ray-tracing no first half + 'subray_rt_both': subray_sim[:, 16], # Ray-tracing both sides + 'subray_rt_both2': subray_sim[:, 17] # Ray-tracing both, second try } @@ -120,6 +133,8 @@ def plot_records(arec, brec, outdir): do_incidence_angle_plots(arec, brec, outdir) do_by_incidence_angle_plots(arec, brec, outdir) do_subray_hit_plots(arec, brec, outdir) + do_ray_subray_plots(arec, brec, outdir) + do_raytracing_plots(arec, brec, outdir) def validate_record(key, rec, recid): @@ -614,7 +629,205 @@ def do_subray_hit_plots(arec, brec, outdir): # TODO Rethink : Implement fig.tight_layout() # Save figure to file and remove it from memory - fig.savefig(os.path.join(outdir, 'subray_hit_plots.png')) + fig.savefig(os.path.join(outdir, 'subray_hit.png')) + fig.clear() + plt.close(fig) + + +def do_ray_subray_plots(arec, brec, outdir): + # Validate ray subray data + if( + not validate_record('ray_dir_norm', arec, 'a') or + not validate_record('subray_dir_norm', arec, 'a') or + not validate_record('ray_subray_angle_rad', arec, 'a') or + not validate_record('ray_subray_sign_check', arec, 'a') or + not validate_record('subray_tmin', arec, 'a') or + not validate_record('subray_tmax', arec, 'a') or + not validate_record('ray_dir_norm', brec, 'b') or + not validate_record('subray_dir_norm', brec, 'b') or + not validate_record('ray_subray_angle_rad', brec, 'b') or + not validate_record('ray_subray_sign_check', brec, 'b') or + not validate_record('subray_tmin', brec, 'b') or + not validate_record('subray_tmax', brec, 'b') + ): + print('Cannot do ray-subray plots') + return + # Do the ray subray plots + fig = init_figure() # Initialize figure + # CASE A + ax = fig.add_subplot(3, 4, 1) # Initialize ray norm subplot + do_incidence_angle_subplot( + fig, ax, arec['ray_dir_norm'], + xlabel='Ray direction norm' + ) + ax = fig.add_subplot(3, 4, 2) # Initialize subray norm subplot + do_incidence_angle_subplot( + fig, ax, arec['subray_dir_norm'], + xlabel='Subay direction norm' + ) + ax = fig.add_subplot(3, 4, 5) # Initialize ray-subray angle subplot + do_incidence_angle_subplot( + fig, ax, arec['ray_subray_angle_rad']*180/np.pi, + xlabel='Ray-subray angle (deg)' + ) + ax = fig.add_subplot(3, 4, 6) # Initialize ray-subray sign check subplot + do_incidence_angle_subplot( + fig, ax, arec['ray_subray_sign_check'], + xlabel='Sign equality check' + ) + ax = fig.add_subplot(3, 4, 9) # Initialize subray tmin subplot + do_incidence_angle_subplot( + fig, ax, arec['subray_tmin'], + xlabel='Subray $t_{\\mathrm{min}}$' + ) + ax = fig.add_subplot(3, 4, 10) # Initialize subray tmin subplot + do_incidence_angle_subplot( + fig, ax, arec['subray_tmax'], + xlabel='Subray $t_{\\mathrm{max}}$' + ) + # CASE B + ax = fig.add_subplot(3, 4, 3) # Initialize ray norm subplot + do_incidence_angle_subplot( + fig, ax, brec['ray_dir_norm'], + xlabel='Ray direction norm' + ) + ax = fig.add_subplot(3, 4, 4) # Initialize subray norm subplot + do_incidence_angle_subplot( + fig, ax, brec['subray_dir_norm'], + xlabel='Subay direction norm' + ) + ax = fig.add_subplot(3, 4, 7) # Initialize ray-subray angle subplot + do_incidence_angle_subplot( + fig, ax, brec['ray_subray_angle_rad']*180/np.pi, + xlabel='Ray-subray angle (deg)' + ) + ax = fig.add_subplot(3, 4, 8) # Initialize ray-subray sign check subplot + do_incidence_angle_subplot( + fig, ax, brec['ray_subray_sign_check'], + xlabel='Sign equality check' + ) + ax = fig.add_subplot(3, 4, 11) # Initialize subray tmin subplot + do_incidence_angle_subplot( + fig, ax, brec['subray_tmin'], + xlabel='Subray $t_{\\mathrm{min}}$' + ) + ax = fig.add_subplot(3, 4, 12) # Initialize subray tmin subplot + do_incidence_angle_subplot( + fig, ax, brec['subray_tmax'], + xlabel='Subray $t_{\\mathrm{max}}$' + ) + fig.tight_layout() + # Save figure to file and remove it from memory + fig.savefig( + os.path.join(outdir, 'ray_subray.png') + ) + fig.clear() + plt.close(fig) + + +def do_raytracing_plots(arec, brec, outdir): + # TODO Rethink : Implement + if( + not validate_record('subray_hit', arec, 'a') or + not validate_record('subray_rt_pos_dir', arec, 'a') or + not validate_record('subray_rt_neg_dir', arec, 'a') or + not validate_record('subray_rt_par_dir', arec, 'a') or + not validate_record('subray_rt_no_second', arec, 'a') or + not validate_record('subray_rt_no_first', arec, 'a') or + not validate_record('subray_rt_both', arec, 'a') or + not validate_record('subray_rt_both2', arec, 'a') or + not validate_record('subray_hit', brec, 'b') or + not validate_record('subray_rt_pos_dir', brec, 'b') or + not validate_record('subray_rt_neg_dir', brec, 'b') or + not validate_record('subray_rt_par_dir', brec, 'b') or + not validate_record('subray_rt_no_second', brec, 'b') or + not validate_record('subray_rt_no_first', brec, 'b') or + not validate_record('subray_rt_both', brec, 'b') or + not validate_record('subray_rt_both2', brec, 'b') + ): + print('Cannot do ray-tracing plots') + return + # Do the ray-tracing plots + fig = init_figure() # Initialize figure + # CASE A + ax = fig.add_subplot(4, 7, 1) # Initialize positive direction hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_pos_dir'], + ylabel='Absolute' + ) + ax = fig.add_subplot(4, 7, 2) # Initialize negative direction hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_neg_dir'], + ) + ax = fig.add_subplot(4, 7, 3) # Initialize parallel direction hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_par_dir'], + ) + ax = fig.add_subplot(4, 7, 4) # Initialize no second half hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_no_second'], + ) + ax = fig.add_subplot(4, 7, 5) # Initialize no second half hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_no_first'], + ) + ax = fig.add_subplot(4, 7, 6) # Initialize both sides hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_both'], + ) + ax = fig.add_subplot(4, 7, 7) # Initialize both sides hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_both2'], + ) + ax = fig.add_subplot(4, 7, 8) # Initialize positive direction hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_pos_dir'], + relative=True, + xlabel='Positive direction', + ylabel='Relative (100%)' + ) + ax = fig.add_subplot(4, 7, 9) # Initialize negative direction hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_neg_dir'], + relative=True, + xlabel='Negative direction', + ) + ax = fig.add_subplot(4, 7, 10) # Initialize parallel direction hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_par_dir'], + relative=True, + xlabel='Parallel direction', + ) + ax = fig.add_subplot(4, 7, 11) # Initialize no second half hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_no_second'], + relative=True, + xlabel='No second half', + ) + ax = fig.add_subplot(4, 7, 12) # Initialize no second half hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_no_first'], + relative=True, + xlabel='No first half', + ) + ax = fig.add_subplot(4, 7, 13) # Initialize both sides hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_both'], + relative=True, + xlabel='Both sides', + ) + ax = fig.add_subplot(4, 7, 14) # Initialize both sides hist + do_subray_hit_subplot_hist( + fig, ax, arec['subray_hit'], arec['subray_rt_both2'], + relative=True, + xlabel='Both sides ($2^{\mathrm{nd}}$ try)', + ) + # CASE B + fig.tight_layout() + # Save figure to file and remove it from memory + fig.savefig( + os.path.join(outdir, 'subray_ray_tracing.png') + ) fig.clear() plt.close(fig) diff --git a/src/alg/raycast/GroveKDTreeRaycaster.h b/src/alg/raycast/GroveKDTreeRaycaster.h index 85ceac12e..031fb7bb1 100644 --- a/src/alg/raycast/GroveKDTreeRaycaster.h +++ b/src/alg/raycast/GroveKDTreeRaycaster.h @@ -80,8 +80,16 @@ class GroveKDTreeRaycaster : double tmin, double tmax, bool groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray=false +#endif ) override {return KDTreeRaycaster::search( rayOrigin, rayDir, tmin, tmax, groundOnly +#ifdef DATA_ANALYTICS + ,subraySimRecord, + isSubray +#endif );} // *** GROVE DYNAMIC TREE METHODS *** // diff --git a/src/alg/raycast/KDGroveRaycaster.cpp b/src/alg/raycast/KDGroveRaycaster.cpp index 002fcd6fb..007e57159 100644 --- a/src/alg/raycast/KDGroveRaycaster.cpp +++ b/src/alg/raycast/KDGroveRaycaster.cpp @@ -26,13 +26,21 @@ RaySceneIntersection * KDGroveRaycaster::search( double tmin, double tmax, bool groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray +#endif ){ std::map out; size_t const m = grove->getNumTrees(); - RaySceneIntersection *bestRSI = nullptr, *rsi = nullptr; + RaySceneIntersection *bestRSI = nullptr, *rsi; for(size_t i = 0 ; i < m ; ++i){ rsi = grove->getTreeShared(i)->search( rayOrigin, rayDir, tmin, tmax, groundOnly +#ifdef DATA_ANALYTICS + ,subraySimRecord, + isSubray +#endif ); if( bestRSI==nullptr || diff --git a/src/alg/raycast/KDGroveRaycaster.h b/src/alg/raycast/KDGroveRaycaster.h index 943dcfbef..8dc4a18b0 100644 --- a/src/alg/raycast/KDGroveRaycaster.h +++ b/src/alg/raycast/KDGroveRaycaster.h @@ -56,6 +56,10 @@ class KDGroveRaycaster : public Raycaster{ double tmin, double tmax, bool groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray=false +#endif ) override; // *** KDGROVE RELATED METHODS *** // diff --git a/src/alg/raycast/KDTreeRaycaster.cpp b/src/alg/raycast/KDTreeRaycaster.cpp index 70bdc048a..ccd860ce7 100644 --- a/src/alg/raycast/KDTreeRaycaster.cpp +++ b/src/alg/raycast/KDTreeRaycaster.cpp @@ -1,6 +1,11 @@ #include "KDTreeRaycaster.h" #include "logging.hpp" +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_GV; +#endif + using namespace std; map KDTreeRaycaster::searchAll( @@ -32,6 +37,10 @@ RaySceneIntersection* KDTreeRaycaster::search( double const tmin, double const tmax, bool const groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray +#endif ){ // Prepare search KDTreeRaycasterSearch search(rayDir, rayOrigin, groundOnly); @@ -43,12 +52,38 @@ RaySceneIntersection* KDTreeRaycaster::search( search.rayOriginArray.push_back(rayOrigin.z); // Do recursive search +#ifdef DATA_ANALYTICS + std::size_t positiveDirectionCount = 0, negativeDirectionCount = 0; + std::size_t noSecondHalfCount = 0, noFirstHalfCount = 0; + std::size_t parallelDirectionCount = 0, bothSidesCount = 0; + std::size_t bothSidesSecondTryCount = 0; +#endif Primitive* prim = this->search_recursive( this->root.get(), tmin-epsilon, tmax+epsilon, search +#ifdef DATA_ANALYTICS + ,positiveDirectionCount, + negativeDirectionCount, + parallelDirectionCount, + noSecondHalfCount, + noFirstHalfCount, + bothSidesCount, + bothSidesSecondTryCount, + isSubray +#endif ); +#ifdef DATA_ANALYTICS + // Write counts to subray simulation record + subraySimRecord[11] = (double) positiveDirectionCount; + subraySimRecord[12] = (double) negativeDirectionCount; + subraySimRecord[13] = (double) parallelDirectionCount; + subraySimRecord[14] = (double) noSecondHalfCount; + subraySimRecord[15] = (double) noFirstHalfCount; + subraySimRecord[16] = (double) bothSidesCount; + subraySimRecord[17] = (double) bothSidesSecondTryCount; +#endif // Handle search output if (prim == nullptr) return nullptr; @@ -170,13 +205,22 @@ Primitive* KDTreeRaycaster::search_recursive( double const tmin, double const tmax, KDTreeRaycasterSearch &search +#ifdef DATA_ANALYTICS + ,size_t &positiveDirectionCount, + size_t &negativeDirectionCount, + size_t ¶llelDirectionCount, + size_t &noSecondHalfCount, + size_t &noFirstHalfCount, + size_t &bothSidesCount, + size_t &bothSidesSecondTryCount, + bool const isSubray +#endif ) const { if(node==nullptr) return nullptr; // Null nodes cannot contain primitives Primitive* hitPrim = nullptr; // ######### BEGIN If node is a leaf, perform ray-primitive intersection on all primitives in the leaf's bucket ########### if (node->splitAxis == -1) { - //logging::DEBUG("leaf node:"); for (auto prim : *node->primitives) { double const newDistance = prim->getRayIntersectionDistance( search.rayOrigin, search.rayDir @@ -198,10 +242,43 @@ Primitive* KDTreeRaycaster::search_recursive( // (in other leaves, with other primitives) that are *closer* to // the ray originWaypoint. If this was the case, the returned intersection // would be wrong. - - if( - (newDistance > 0 && newDistance < search.closestHitDistance) && - (newDistance >= tmin && newDistance <= tmax) +#ifdef DATA_ANALYTICS + bool const nonNegativeDistance = newDistance > 0; + bool const closerThanClosest = + newDistance < search.closestHitDistance; + bool const tminCheck = newDistance >= tmin; + bool const tmaxCheck = newDistance <= tmax; + if(!nonNegativeDistance){ // For any traced ray + HDA_GV.incrementRaycasterLeafNegativeDistancesCount(); + } else if(!closerThanClosest){ + HDA_GV.incrementRaycasterLeafFurtherThanClosestCount(); + } else if(!tminCheck){ + HDA_GV.incrementRaycasterLeafFailedTminCheckCount(); + } + else if(!tmaxCheck){ + HDA_GV.incrementRaycasterLeafFailedTmaxCheckCount(); + } + if(isSubray){ // For any traced ray that is a subray + if(!nonNegativeDistance){ + HDA_GV.incrementSubrayLeafNegativeDistancesCount(); + } else if(!closerThanClosest){ + HDA_GV.incrementSubrayLeafFurtherThanClosestCount(); + } else if(!tminCheck){ + HDA_GV.incrementSubrayLeafFailedTminCheckCount(); + } + else if(!tmaxCheck){ + HDA_GV.incrementSubrayLeafFailedTmaxCheckCount(); + } + + } + if( + nonNegativeDistance && closerThanClosest && + tminCheck && tmaxCheck +#else + if( + newDistance > 0 && newDistance < search.closestHitDistance && + newDistance >= tmin && newDistance <= tmax +#endif ){ if( !search.groundOnly || @@ -229,6 +306,9 @@ Primitive* KDTreeRaycaster::search_recursive( // Case 1: Ray goes in positive direction - it passes through the left side first, then through the right: if (search.rayDirArray[a] > 0) { +#ifdef DATA_ANALYTICS + ++positiveDirectionCount; +#endif first = node->left; second = node->right; @@ -237,6 +317,9 @@ Primitive* KDTreeRaycaster::search_recursive( } // Case 2: Ray goes in negative direction - it passes through the right side first, then through the left: else if (search.rayDirArray[a] < 0) { +#ifdef DATA_ANALYTICS + ++negativeDirectionCount; +#endif first = node->right; second = node->left; @@ -245,6 +328,9 @@ Primitive* KDTreeRaycaster::search_recursive( } // Case 3: Ray goes parallel to the split plane - it passes through only one side, depending on it's originWaypoint: else { +#ifdef DATA_ANALYTICS + ++parallelDirectionCount; +#endif first = (search.rayOriginArray[a] < node->splitPos) ? node->left : node->right; second = (search.rayOriginArray[a] < node->splitPos) ? @@ -257,22 +343,75 @@ Primitive* KDTreeRaycaster::search_recursive( // thit >= tmax means that the ray crosses the split plane *after it has already left the volume*. // In this case, it never enters the second half. if (thit >= tmax) { - hitPrim = search_recursive(first, tmin, tmax, search); +#ifdef DATA_ANALYTICS + ++noSecondHalfCount; +#endif + hitPrim = search_recursive( + first, tmin, tmax, search +#ifdef DATA_ANALYTICS + ,positiveDirectionCount, + negativeDirectionCount, + parallelDirectionCount, + noSecondHalfCount, + noFirstHalfCount, + bothSidesCount, + bothSidesSecondTryCount +#endif + ); } // thit <= tmin means that the ray crosses the split plane *before it enters the volume*. // In this case, it never enters the first half: else if (thit <= tmin) { - hitPrim = search_recursive(second, tmin, tmax, search); +#ifdef DATA_ANALYTICS + ++noFirstHalfCount; +#endif + hitPrim = search_recursive( + second, tmin, tmax, search +#ifdef DATA_ANALYTICS + ,positiveDirectionCount, + negativeDirectionCount, + parallelDirectionCount, + noSecondHalfCount, + noFirstHalfCount, + bothSidesCount, + bothSidesSecondTryCount +#endif + ); } // Otherwise, the ray crosses the split plane within the volume. // This means that it passes through both sides: else { - hitPrim = search_recursive(first, tmin, thit+epsilon, search); +#ifdef DATA_ANALYTICS + ++bothSidesCount; +#endif + hitPrim = search_recursive( + first, tmin, thit+epsilon, search +#ifdef DATA_ANALYTICS + ,positiveDirectionCount, + negativeDirectionCount, + parallelDirectionCount, + noSecondHalfCount, + noFirstHalfCount, + bothSidesCount, + bothSidesSecondTryCount +#endif + ); if (hitPrim == nullptr) { - hitPrim = search_recursive(second, thit-epsilon, tmax, search); + hitPrim = search_recursive( + second, thit-epsilon, tmax, search +#ifdef DATA_ANALYTICS + ,positiveDirectionCount, + negativeDirectionCount, + parallelDirectionCount, + noSecondHalfCount, + noFirstHalfCount, + bothSidesCount, + bothSidesSecondTryCount +#endif + ); } } diff --git a/src/alg/raycast/KDTreeRaycaster.h b/src/alg/raycast/KDTreeRaycaster.h index 108f33dbd..c42b27b21 100644 --- a/src/alg/raycast/KDTreeRaycaster.h +++ b/src/alg/raycast/KDTreeRaycaster.h @@ -140,6 +140,10 @@ class KDTreeRaycasterSearch{ double const tmin, double const tmax, bool const groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray=false +#endif ) override; protected: @@ -183,5 +187,15 @@ class KDTreeRaycasterSearch{ double const tmin, double const tmax, KDTreeRaycasterSearch &search +#ifdef DATA_ANALYTICS + ,size_t &positiveDirectionCount, + size_t &negativeDirectionCount, + size_t ¶llelDirectionCount, + size_t &noSecondHalfCount, + size_t &noFirstHalfCount, + size_t &bothSidesCount, + size_t &bothSidesSecondTryCount, + bool const isSubray=false +#endif ) const; }; \ No newline at end of file diff --git a/src/alg/raycast/Raycaster.h b/src/alg/raycast/Raycaster.h index 9d6d03462..875363b9f 100644 --- a/src/alg/raycast/Raycaster.h +++ b/src/alg/raycast/Raycaster.h @@ -62,5 +62,9 @@ class Raycaster{ double tmin, double tmax, bool groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray=false +#endif ) = 0; }; \ No newline at end of file diff --git a/src/dataanalytics/HDA_GlobalVars.cpp b/src/dataanalytics/HDA_GlobalVars.cpp index f3964f8e6..d618cc407 100644 --- a/src/dataanalytics/HDA_GlobalVars.cpp +++ b/src/dataanalytics/HDA_GlobalVars.cpp @@ -53,6 +53,16 @@ HDA_GlobalVars & HDA_GlobalVars::incrementNonIntersectiveSubraysCount(){ return *this; } +HDA_GlobalVars & +HDA_GlobalVars::incrementNonIntersectiveSubraysDueToNullTimeCount(){ + std::unique_lock lock( + nonIntersectiveSubraysDueToNullTimeCount_mutex + ); + ++nonIntersectiveSubraysDueToNullTimeCount; + return *this; + +} + HDA_GlobalVars & HDA_GlobalVars::incrementSubrayIntersectionCount() { std::unique_lock lock(subrayIntersectionCount_mutex); ++subrayIntersectionCount; @@ -65,6 +75,62 @@ HDA_GlobalVars & HDA_GlobalVars::incrementSubrayNonIntersectionCount() { return *this; } +HDA_GlobalVars & +HDA_GlobalVars::incrementRaycasterLeafNegativeDistancesCount(){ + std::unique_lock lock( + raycasterLeafNegativeDistancesCount_mutex + ); + ++raycasterLeafNegativeDistancesCount; + return *this; +} + +HDA_GlobalVars & +HDA_GlobalVars::incrementRaycasterLeafFurtherThanClosestCount(){ + std::unique_lock lock( + raycasterLeafFurtherThanClosestCount_mutex + ); + ++raycasterLeafFurtherThanClosestCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementRaycasterLeafFailedTminCheckCount(){ + std::unique_lock lock(raycasterLeafFailedTminCheckCount_mutex); + ++raycasterLeafFailedTminCheckCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementRaycasterLeafFailedTmaxCheckCount(){ + std::unique_lock lock(raycasterLeafFailedTmaxCheckCount_mutex); + ++raycasterLeafFailedTmaxCheckCount; + return *this; +} + +HDA_GlobalVars & +HDA_GlobalVars::incrementSubrayLeafNegativeDistancesCount(){ + std::unique_lock lock(subrayLeafNegativeDistancesCount_mutex); + ++subrayLeafNegativeDistancesCount; + return *this; +} + +HDA_GlobalVars & +HDA_GlobalVars::incrementSubrayLeafFurtherThanClosestCount(){ + std::unique_lock lock(subrayLeafFurtherThanClosestCount_mutex); + ++subrayLeafFurtherThanClosestCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementSubrayLeafFailedTminCheckCount(){ + std::unique_lock lock(subrayLeafFailedTminCheckCount_mutex); + ++subrayLeafFailedTminCheckCount; + return *this; +} + +HDA_GlobalVars & HDA_GlobalVars::incrementSubrayLeafFailedTmaxCheckCount(){ + std::unique_lock lock(subrayLeafFailedTmaxCheckCount_mutex); + ++subrayLeafFailedTmaxCheckCount; + return *this; +} + // *** READ METHODS *** // // ********************** // std::size_t HDA_GlobalVars::getGeneratedSubraysCount(){ @@ -96,6 +162,13 @@ std::size_t HDA_GlobalVars::getNonIntersectiveSubraysCount() { return nonIntersectiveSubraysCount; } +std::size_t HDA_GlobalVars::getNonIntersectiveSubraysDueToNullTimeCount(){ + std::unique_lock lock( + nonIntersectiveSubraysDueToNullTimeCount_mutex + ); + return nonIntersectiveSubraysDueToNullTimeCount; +} + std::size_t HDA_GlobalVars::getSubrayIntersectionCount() { std::unique_lock lock(subrayIntersectionCount_mutex); return subrayIntersectionCount; @@ -111,6 +184,50 @@ std::size_t HDA_GlobalVars::getIntensityComputationsCount(){ return intensityComputationsCount; } +std::size_t HDA_GlobalVars::getRaycasterLeafNegativeDistancesCount(){ + std::unique_lock lock( + raycasterLeafNegativeDistancesCount_mutex + ); + return raycasterLeafNegativeDistancesCount; +} + +std::size_t HDA_GlobalVars::getRaycasterLeafFurtherThanClosestCount(){ + std::unique_lock lock( + raycasterLeafFurtherThanClosestCount_mutex + ); + return raycasterLeafFurtherThanClosestCount; +} + +std::size_t HDA_GlobalVars::getRaycasterLeafFailedTminCheckCount(){ + std::unique_lock lock(raycasterLeafFailedTminCheckCount_mutex); + return raycasterLeafFailedTminCheckCount; +} + +std::size_t HDA_GlobalVars::getRaycasterLeafFailedTmaxCheckCount(){ + std::unique_lock lock(raycasterLeafFailedTmaxCheckCount_mutex); + return raycasterLeafFailedTmaxCheckCount; +} + +unsigned long HDA_GlobalVars::getSubrayLeafNegativeDistancesCount(){ + std::unique_lock lock(subrayLeafNegativeDistancesCount_mutex); + return subrayLeafNegativeDistancesCount; +} + +unsigned long HDA_GlobalVars::getSubrayLeafFurtherThanClosestCount(){ + std::unique_lock lock(subrayLeafFurtherThanClosestCount_mutex); + return subrayLeafFurtherThanClosestCount; +} + +unsigned long HDA_GlobalVars::getSubrayLeafFailedTminCheckCount(){ + std::unique_lock lock(subrayLeafFailedTminCheckCount_mutex); + return subrayLeafFailedTminCheckCount; +} + +unsigned long HDA_GlobalVars::getSubrayLeafFailedTmaxCheckCount(){ + std::unique_lock lock(subrayLeafFailedTmaxCheckCount_mutex); + return subrayLeafFailedTmaxCheckCount; +} + }} diff --git a/src/dataanalytics/HDA_GlobalVars.h b/src/dataanalytics/HDA_GlobalVars.h index 024f97e91..b8d7d20ff 100644 --- a/src/dataanalytics/HDA_GlobalVars.h +++ b/src/dataanalytics/HDA_GlobalVars.h @@ -19,9 +19,18 @@ class HDA_GlobalVars{ std::size_t generatedSubraysCount; std::size_t intersectiveSubraysCount; std::size_t nonIntersectiveSubraysCount; + std::size_t nonIntersectiveSubraysDueToNullTimeCount; std::size_t subrayIntersectionCount; std::size_t subrayNonIntersectionCount; std::size_t intensityComputationsCount; + std::size_t raycasterLeafNegativeDistancesCount; + std::size_t raycasterLeafFurtherThanClosestCount; + std::size_t raycasterLeafFailedTminCheckCount; + std::size_t raycasterLeafFailedTmaxCheckCount; + unsigned long subrayLeafNegativeDistancesCount; + unsigned long subrayLeafFurtherThanClosestCount; + unsigned long subrayLeafFailedTminCheckCount; + unsigned long subrayLeafFailedTmaxCheckCount; protected: // *** CONCURRENCY HANDLING ATTRIBUTES *** // @@ -31,9 +40,18 @@ class HDA_GlobalVars{ std::mutex generatedSubraysCount_mutex; std::mutex intersectiveSubraysCount_mutex; std::mutex nonIntersectiveSubraysCount_mutex; + std::mutex nonIntersectiveSubraysDueToNullTimeCount_mutex; std::mutex subrayIntersectionCount_mutex; std::mutex subrayNonIntersectionCount_mutex; std::mutex intensityComputationsCount_mutex; + std::mutex raycasterLeafNegativeDistancesCount_mutex; + std::mutex raycasterLeafFurtherThanClosestCount_mutex; + std::mutex raycasterLeafFailedTminCheckCount_mutex; + std::mutex raycasterLeafFailedTmaxCheckCount_mutex; + std::mutex subrayLeafNegativeDistancesCount_mutex; + std::mutex subrayLeafFurtherThanClosestCount_mutex; + std::mutex subrayLeafFailedTminCheckCount_mutex; + std::mutex subrayLeafFailedTmaxCheckCount_mutex; public: // *** CONSTRUCTION / DESTRUCTION *** // @@ -44,6 +62,7 @@ class HDA_GlobalVars{ generatedSubraysCount(0), intersectiveSubraysCount(0), nonIntersectiveSubraysCount(0), + nonIntersectiveSubraysDueToNullTimeCount(0), subrayIntersectionCount(0), subrayNonIntersectionCount(0), intensityComputationsCount(0) @@ -57,9 +76,18 @@ class HDA_GlobalVars{ HDA_GlobalVars & incrementGeneratedSubraysCount(); HDA_GlobalVars & incrementIntersectiveSubraysCount(); HDA_GlobalVars & incrementNonIntersectiveSubraysCount(); + HDA_GlobalVars & incrementNonIntersectiveSubraysDueToNullTimeCount(); HDA_GlobalVars & incrementSubrayIntersectionCount(); HDA_GlobalVars & incrementSubrayNonIntersectionCount(); HDA_GlobalVars & incrementIntensityComputationsCount(); + HDA_GlobalVars & incrementRaycasterLeafNegativeDistancesCount(); + HDA_GlobalVars & incrementRaycasterLeafFurtherThanClosestCount(); + HDA_GlobalVars & incrementRaycasterLeafFailedTminCheckCount(); + HDA_GlobalVars & incrementRaycasterLeafFailedTmaxCheckCount(); + HDA_GlobalVars & incrementSubrayLeafNegativeDistancesCount(); + HDA_GlobalVars & incrementSubrayLeafFurtherThanClosestCount(); + HDA_GlobalVars & incrementSubrayLeafFailedTminCheckCount(); + HDA_GlobalVars & incrementSubrayLeafFailedTmaxCheckCount(); // *** READ METHODS *** // // ********************** // @@ -68,10 +96,18 @@ class HDA_GlobalVars{ std::size_t getGeneratedRaysAfterEarlyAbortCount(); std::size_t getIntersectiveSubraysCount(); std::size_t getNonIntersectiveSubraysCount(); + std::size_t getNonIntersectiveSubraysDueToNullTimeCount(); std::size_t getSubrayIntersectionCount(); std::size_t getSubrayNonIntersectionCount(); std::size_t getIntensityComputationsCount(); - + std::size_t getRaycasterLeafNegativeDistancesCount(); + std::size_t getRaycasterLeafFurtherThanClosestCount(); + std::size_t getRaycasterLeafFailedTminCheckCount(); + std::size_t getRaycasterLeafFailedTmaxCheckCount(); + unsigned long getSubrayLeafNegativeDistancesCount(); + unsigned long getSubrayLeafFurtherThanClosestCount(); + unsigned long getSubrayLeafFailedTminCheckCount(); + unsigned long getSubrayLeafFailedTmaxCheckCount(); }; }} diff --git a/src/dataanalytics/HDA_GlobalVarsReporter.h b/src/dataanalytics/HDA_GlobalVarsReporter.h index 4f03dc431..19ace808f 100644 --- a/src/dataanalytics/HDA_GlobalVarsReporter.h +++ b/src/dataanalytics/HDA_GlobalVarsReporter.h @@ -27,6 +27,16 @@ class HDA_GlobalVarsReporter{ // Initialize string stream to build the print std::stringstream ss; + // Extract variables for the sake of convenience + size_t const raycasterLeafFailedTminCheckCount = + HDA_GV.getRaycasterLeafFailedTminCheckCount(); + size_t const raycasterLeafFailedTmaxCheckCount = + HDA_GV.getRaycasterLeafFailedTmaxCheckCount(); + size_t const subrayLeafFailedTminCheckCount = + HDA_GV.getSubrayLeafFailedTminCheckCount(); + size_t const subrayLeafFailedTmaxCheckCount = + HDA_GV.getSubrayLeafFailedTmaxCheckCount(); + // Print global variables ss << "HDA GLOBAL VARS REPORT:\n\n"; ss << "Generated rays before early abort: " @@ -38,12 +48,42 @@ class HDA_GlobalVarsReporter{ << gv.getIntersectiveSubraysCount() << "\n"; ss << "Non-intersective subrays: " << gv.getNonIntersectiveSubraysCount() << "\n"; + ss << "\tNon-intersective subrays due to null time: " + << gv.getNonIntersectiveSubraysDueToNullTimeCount() << "\n"; ss << "Subray intersections: " << gv.getSubrayIntersectionCount() << "\n"; ss << "Subray non-intersections: " << gv.getSubrayNonIntersectionCount() << "\n"; ss << "Number of computed intensities: " << gv.getIntensityComputationsCount() << "\n"; + ss << "Raycaster fails-on-leaves distribution:\n" + << "\tNegative distances: " + << HDA_GV.getRaycasterLeafNegativeDistancesCount() << "\n" + << "\tFurther than current closest: " + << HDA_GV.getRaycasterLeafFurtherThanClosestCount() << "\n" + << "\tFailed tmin checks: " + << raycasterLeafFailedTminCheckCount << "\n" + << "\tFailed tmax checks: " + << raycasterLeafFailedTmaxCheckCount << "\n" + << "\tFailed t checks: " + << ( + raycasterLeafFailedTminCheckCount + + raycasterLeafFailedTmaxCheckCount + ) << "\n" + << "\tSubrays only:\n" + << "\t\tNegative distances: " + << HDA_GV.getSubrayLeafNegativeDistancesCount() << "\n" + << "\t\tFurther than current closest: " + << HDA_GV.getSubrayLeafFurtherThanClosestCount() << "\n" + << "\t\tFailed tmin checks: " + << subrayLeafFailedTminCheckCount << "\n" + << "\t\tFailed tmax checks: " + << subrayLeafFailedTmaxCheckCount << "\n" + << "\t\tFailed t checks: " + << ( + raycasterLeafFailedTminCheckCount + + raycasterLeafFailedTmaxCheckCount + ) << "\n"; // Print through info logging level system std::string text = ss.str(); logging::INFO(ss.str()); diff --git a/src/dataanalytics/HDA_PulseRecorder.cpp b/src/dataanalytics/HDA_PulseRecorder.cpp index e8518898d..0b27f94e5 100644 --- a/src/dataanalytics/HDA_PulseRecorder.cpp +++ b/src/dataanalytics/HDA_PulseRecorder.cpp @@ -56,7 +56,7 @@ void HDA_PulseRecorder::recordIntensityCalculation( } } -void HDA_PulseRecorder::recordSubraySimuilation( +void HDA_PulseRecorder::recordSubraySimulation( std::vector const &record ){ std::unique_lock lock(subraySimMutex); diff --git a/src/dataanalytics/HDA_PulseRecorder.h b/src/dataanalytics/HDA_PulseRecorder.h index fa862732d..c8c67e5f1 100644 --- a/src/dataanalytics/HDA_PulseRecorder.h +++ b/src/dataanalytics/HDA_PulseRecorder.h @@ -60,6 +60,49 @@ class HDA_PulseRecorder : public HDA_Recorder{ * [3] -> Circle step * * [4] -> Divergence angle (in rad) + * + * [5] -> Ray direction norm + * + * [6] -> Subray direction norm + * + * [7] -> Angle between ray and subray (in rad) + * + * [8] -> Ray-subray sign check (1 if sign match, 0 otherwise) + * + * [9] -> Min time for subray intersection + * + * [10] -> Max time for subray intersection + * + * [11] -> Count of subray as positive direction during ray tracing + * + * [12] -> Count of subray as negative direction during ray tracing + * + * [13] -> Count of subray as parallel direction during ray tracing + * + * [14] -> Count of subray as not touching the second half of a node during + * ray tracing + * + * [15] -> Count of subray as not touching the first half of a node during + * ray tracing + * + * [16] -> Count of subray as touching both sides of a node during ray + * tracing + * + * [17] -> Count of subrays as touching both sides of a node during a + * second ray tracing try (which uses thit-epsilon for tmin, while the + * first try uses thit+epsilon) + * + * [18] -> Subray direction (x component) + * + * [19] -> Subray direction (y component) + * + * [20] -> Subray direction (z component) + * + * [21] -> Ray direction (x component) + * + * [22] -> Ray direction (y component) + * + * [23] -> Ray direction (z component) */ std::shared_ptr>> subraySim; @@ -129,7 +172,7 @@ class HDA_PulseRecorder : public HDA_Recorder{ /** * @brief Handle all the records for the current subray simulation. */ - virtual void recordSubraySimuilation(std::vector const &record); + virtual void recordSubraySimulation(std::vector const &record); /** * @brief Like * HDA_PulseRecorder::recordSubraySimulation(std::vector) diff --git a/src/scanner/MultiScanner.cpp b/src/scanner/MultiScanner.cpp index e60eaa2a5..db051cbd4 100644 --- a/src/scanner/MultiScanner.cpp +++ b/src/scanner/MultiScanner.cpp @@ -167,7 +167,8 @@ void MultiScanner::computeSubrays( std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, vector const &tMinMax, diff --git a/src/scanner/MultiScanner.h b/src/scanner/MultiScanner.h index f04c47341..e4a4edac4 100644 --- a/src/scanner/MultiScanner.h +++ b/src/scanner/MultiScanner.h @@ -166,7 +166,8 @@ class MultiScanner : public Scanner{ std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, vector const &tMinMax, diff --git a/src/scanner/Scanner.h b/src/scanner/Scanner.h index 78bb769eb..e8bbc5db3 100644 --- a/src/scanner/Scanner.h +++ b/src/scanner/Scanner.h @@ -451,7 +451,8 @@ class Scanner : public Asset { std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, vector const &tMinMax, diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index 5e61ce83e..214c73624 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -227,7 +227,8 @@ void ScanningDevice::computeSubrays( std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, std::vector const &tMinMax, @@ -250,7 +251,8 @@ void ScanningDevice::computeSubrays( double const subrayDivergenceAngle_rad = radiusStep * radiusStep_rad; // Rotate subbeam into divergence step (towards outer rim of the beam cone): - Rotation r1 = Rotation(Directions::right, subrayDivergenceAngle_rad); + Rotation r1 = Rotation(Directions::right, subrayDivergenceAngle_rad); // TODO Restore + //Rotation r1 = Rotation(Directions::right, 0.0); // TODO Remove // Calculate circle step width: int circleSteps = (int)(PI_2 * radiusStep); @@ -264,6 +266,11 @@ void ScanningDevice::computeSubrays( // # Loop over sub-rays along the circle for (int circleStep = 0; circleStep < circleSteps; circleStep++){ +#ifdef DATA_ANALYTICS + std::vector subraySimRecord( + 24, std::numeric_limits::quiet_NaN() + ); +#endif handleSubray( tMinMax, circleStep, @@ -274,18 +281,18 @@ void ScanningDevice::computeSubrays( reflections, intersects #ifdef DATA_ANALYTICS - ,subrayHit + ,subrayHit, + subraySimRecord #endif ); #ifdef DATA_ANALYTICS HDA_GV.incrementGeneratedSubraysCount(); - pulseRecorder->recordSubraySimuilation(std::vector({ - (double)subrayHit, - (double) radiusStep, - (double) circleSteps, - (double) circleStep, - subrayDivergenceAngle_rad - })); + subraySimRecord[0] = (double) subrayHit; + subraySimRecord[1] = (double) radiusStep; + subraySimRecord[2] = (double) circleSteps; + subraySimRecord[3] = (double) circleStep; + subraySimRecord[4] = subrayDivergenceAngle_rad; + pulseRecorder->recordSubraySimulation(subraySimRecord); #endif } } diff --git a/src/scanner/ScanningDevice.h b/src/scanner/ScanningDevice.h index 4e919c1d5..11111ce37 100644 --- a/src/scanner/ScanningDevice.h +++ b/src/scanner/ScanningDevice.h @@ -309,7 +309,8 @@ class ScanningDevice : public Asset { std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, std::vector const &tMinMax, diff --git a/src/scanner/SingleScanner.cpp b/src/scanner/SingleScanner.cpp index 1a7c11b80..72d9f3b8e 100644 --- a/src/scanner/SingleScanner.cpp +++ b/src/scanner/SingleScanner.cpp @@ -203,7 +203,8 @@ void SingleScanner::computeSubrays( std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, vector const &tMinMax, diff --git a/src/scanner/SingleScanner.h b/src/scanner/SingleScanner.h index 34bb88bcb..1f7134053 100644 --- a/src/scanner/SingleScanner.h +++ b/src/scanner/SingleScanner.h @@ -139,7 +139,8 @@ class SingleScanner : public Scanner{ std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif )> handleSubray, vector const &tMinMax, diff --git a/src/scanner/detector/DynFullWaveformPulseRunnable.cpp b/src/scanner/detector/DynFullWaveformPulseRunnable.cpp index f71b04695..34a0542a5 100644 --- a/src/scanner/detector/DynFullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/DynFullWaveformPulseRunnable.cpp @@ -7,10 +7,17 @@ DynFullWaveformPulseRunnable::findIntersection( vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord +#endif ) const{ // Consider scene AABB intersection check was done before at operator() // Thus, proceed to raycasting directly return shared_ptr(raycaster->search( o, v, tMinMax[0], tMinMax[1], false +#ifdef DATA_ANALYTICS + ,subraySimRecord, + true // Subray flag +#endif )); } diff --git a/src/scanner/detector/DynFullWaveformPulseRunnable.h b/src/scanner/detector/DynFullWaveformPulseRunnable.h index 9bea8c46e..772d44a07 100644 --- a/src/scanner/detector/DynFullWaveformPulseRunnable.h +++ b/src/scanner/detector/DynFullWaveformPulseRunnable.h @@ -50,5 +50,8 @@ class DynFullWaveformPulseRunnable : public FullWaveformPulseRunnable { vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord +#endif ) const override; }; \ No newline at end of file diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index aac64abba..c2675480e 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -18,6 +18,9 @@ #ifdef DATA_ANALYTICS #include using helios::analytics::HDA_GV; + +#include +#include #endif using namespace std; @@ -52,11 +55,26 @@ void FullWaveformPulseRunnable::operator()( vector tMinMax = scene.getAABB()->getRayIntersection( pulse.getOriginRef(), beamDir - ); + ); // TODO Restore + // TODO Remove --- + /*std::shared_ptr aabb = std::make_shared(*scene.getAABB()); + aabb->vertices[0].pos.x -= 1.0; + aabb->vertices[0].pos.y -= 1.0; + aabb->vertices[0].pos.z -= 1.0; + aabb->vertices[1].pos.x += 1.0; + aabb->vertices[1].pos.y += 1.0; + aabb->vertices[1].pos.z += 1.0; + aabb->bounds[0] = aabb->vertices[0].pos; + aabb->bounds[1] = aabb->vertices[1].pos; + vector tMinMax = aabb->getRayIntersection( + pulse.getOriginRef(), + beamDir + );*/ + // --- TODO Remove #ifdef DATA_ANALYTICS HDA_GV.incrementGeneratedRaysBeforeEarlyAbortCount(); #endif - if (tMinMax.empty()) { + if (tMinMax.empty() || (tMinMax[0] < 0 && tMinMax[1] < 0)) { logging::DEBUG("Early abort - beam does not intersect with the scene"); scanner->setLastPulseWasHit(false, pulse.getDeviceIndex()); return; @@ -129,7 +147,8 @@ void FullWaveformPulseRunnable::computeSubrays( std::map &reflections, vector &intersects #ifdef DATA_ANALYTICS - ,bool &subrayHit + ,bool &subrayHit, + std::vector &subraySimRecord #endif ) -> void { handleSubray( @@ -143,6 +162,7 @@ void FullWaveformPulseRunnable::computeSubrays( intersects #ifdef DATA_ANALYTICS ,subrayHit, + subraySimRecord, calcIntensityRecords #endif ); @@ -169,6 +189,7 @@ void FullWaveformPulseRunnable::handleSubray( vector &intersects #ifdef DATA_ANALYTICS ,bool &subrayHit, + std::vector &subraySimRecord, std::vector> &calcIntensityRecords #endif ){ @@ -182,6 +203,24 @@ void FullWaveformPulseRunnable::handleSubray( glm::dvec3 subrayDirection = pulse.getAttitude().applyTo(r2) .applyTo(Directions::forward); +#ifdef DATA_ANALYTICS + glm::dvec3 rayDirection = pulse.computeDirection(); + subraySimRecord[5] = glm::l2Norm(rayDirection); // Ray norm + subraySimRecord[6] = glm::l2Norm(subrayDirection); // Subray norm + subraySimRecord[7] = glm::angle( // Angle between ray and subray + rayDirection, + subrayDirection + ); + subraySimRecord[8] = (rayDirection[0] < 0) == (subrayDirection[0] < 0); + subraySimRecord[9] = tMinMax[0]; + subraySimRecord[10] = tMinMax[1]; + subraySimRecord[18] = subrayDirection.x; + subraySimRecord[19] = subrayDirection.y; + subraySimRecord[20] = subrayDirection.z; + subraySimRecord[21] = rayDirection.x; + subraySimRecord[22] = rayDirection.y; + subraySimRecord[23] = rayDirection.z; +#endif glm::dvec3 subrayOrigin(pulse.getOrigin()); bool rayContinues = true; @@ -192,6 +231,9 @@ void FullWaveformPulseRunnable::handleSubray( tMinMax, subrayOrigin, subrayDirection +#ifdef DATA_ANALYTICS + ,subraySimRecord +#endif ); if (intersect != nullptr && intersect->prim != nullptr) { @@ -718,8 +760,17 @@ shared_ptr FullWaveformPulseRunnable::findIntersection( vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord +#endif ) const { - return scene.getIntersection(tMinMax, o, v, false); + return scene.getIntersection( + tMinMax, o, v, false +#ifdef DATA_ANALYTICS + ,subraySimRecord, + true // Subray flag +#endif + ); } void FullWaveformPulseRunnable::captureFullWave( diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index 0ca586486..dfa6be5d4 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -114,7 +114,8 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { vector &intersects #ifdef DATA_ANALYTICS ,bool &subrayHit, - std::vector> &calcIntensityRecords + std::vector &subraySimRecord, + std::vector> &calcIntensityRecords #endif ); /** @@ -273,6 +274,9 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord +#endif ) const; /** * @brief Detect full waveform peaks diff --git a/src/scene/Scene.cpp b/src/scene/Scene.cpp index b7d943d39..f404ef274 100644 --- a/src/scene/Scene.cpp +++ b/src/scene/Scene.cpp @@ -23,6 +23,11 @@ using namespace glm; #include #include +#ifdef DATA_ANALYTICS +#include +using helios::analytics::HDA_GV; +#endif + using SurfaceInspector::maths::Plane; using SurfaceInspector::maths::PlaneFitter; @@ -91,6 +96,16 @@ bool Scene::finalizeLoading(bool const safe) { // Store original bounding box (CRS coordinates): this->bbox_crs = AABB::getForPrimitives(primitives); + // TODO Rethink : Does this solve the issue ? --- + this->bbox_crs->vertices[0].pos.x -= 1.0; + this->bbox_crs->vertices[0].pos.y -= 1.0; + this->bbox_crs->vertices[0].pos.z -= 1.0; + this->bbox_crs->vertices[1].pos.x += 1.0; + this->bbox_crs->vertices[1].pos.y += 1.0; + this->bbox_crs->vertices[1].pos.z += 1.0; + this->bbox_crs->bounds[0] = this->bbox_crs->vertices[0].pos; + this->bbox_crs->bounds[1] = this->bbox_crs->vertices[1].pos; + // --- TODO Rethink : Does this solve the issue ? glm::dvec3 diff = this->bbox_crs->getMin(); stringstream ss; ss << "CRS bounding box (by vertices): " << this->bbox_crs->toString() @@ -110,6 +125,16 @@ bool Scene::finalizeLoading(bool const safe) { // Get new bounding box of translated scene: this->bbox = AABB::getForPrimitives(primitives); + // TODO Rethink : Does this solve the issue ? --- + this->bbox->vertices[0].pos.x -= 1.0; + this->bbox->vertices[0].pos.y -= 1.0; + this->bbox->vertices[0].pos.z -= 1.0; + this->bbox->vertices[1].pos.x += 1.0; + this->bbox->vertices[1].pos.y += 1.0; + this->bbox->vertices[1].pos.z += 1.0; + this->bbox->bounds[0] = this->bbox->vertices[0].pos; + this->bbox->bounds[1] = this->bbox->vertices[1].pos; + // --- TODO Rethink : Does this solve the issue ? ss << "Actual bounding box (by vertices): " << this->bbox->toString(); logging::INFO(ss.str()); @@ -171,7 +196,14 @@ Scene::getIntersection( bool const groundOnly ) const { vector tMinMax = bbox->getRayIntersection(rayOrigin, rayDir); +#ifdef DATA_ANALYTICS + std::vector subraySimRecord_fake(24, 0); // Not really recorded + return getIntersection( + tMinMax, rayOrigin, rayDir, groundOnly, subraySimRecord_fake + ); +#else return getIntersection(tMinMax, rayOrigin, rayDir, groundOnly); +#endif } std::shared_ptr Scene::getIntersection( @@ -179,13 +211,24 @@ std::shared_ptr Scene::getIntersection( glm::dvec3 const &rayOrigin, glm::dvec3 const &rayDir, bool const groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray +#endif ) const{ if (tMinMax.empty()) { logging::DEBUG("tMinMax is empty"); +#ifdef DATA_ANALYTICS + HDA_GV.incrementNonIntersectiveSubraysDueToNullTimeCount(); +#endif return nullptr; } return shared_ptr(raycaster->search( rayOrigin, rayDir, tMinMax[0], tMinMax[1], groundOnly +#ifdef DATA_ANALYTICS + ,subraySimRecord, + isSubray +#endif )); } diff --git a/src/scene/Scene.h b/src/scene/Scene.h index 99f7afb82..2481cdb34 100644 --- a/src/scene/Scene.h +++ b/src/scene/Scene.h @@ -217,6 +217,10 @@ class Scene : public Asset { glm::dvec3 const &rayOrigin, glm::dvec3 const &rayDir, bool const groundOnly +#ifdef DATA_ANALYTICS + ,std::vector &subraySimRecord, + bool const isSubray=false +#endif ) const ; /** * @brief Obtain all intersections between the ray and the scene, if any diff --git a/src/scene/primitives/AABB.cpp b/src/scene/primitives/AABB.cpp index 56d2bb250..8154d7a14 100644 --- a/src/scene/primitives/AABB.cpp +++ b/src/scene/primitives/AABB.cpp @@ -163,14 +163,15 @@ std::vector AABB::getRayIntersection( const int ysign = dir.y < 0; const int zsign = dir.z < 0; + // As long as divide by zero yields +-infinity, this logic should work double tmin, tmax; tmin = (bounds[xsign].x - orig.x) / dir.x; tmax = (bounds[1 - xsign].x - orig.x) / dir.x; const double tymin = (bounds[ysign].y - orig.y) / dir.y; const double tymax = (bounds[1 - ysign].y - orig.y) / dir.y; - if (tmin > tymax || tymin > tmax) return std::vector(); - if (tymin > tmin)tmin = tymin; + if (tmin > tymax || tymin > tmax) return {}; + if (tymin > tmin) tmin = tymin; if (tymax < tmax) tmax = tymax; const double tzmin = (bounds[zsign].z - orig.z) / dir.z; diff --git a/src/scene/primitives/AABB.h b/src/scene/primitives/AABB.h index 7fc6478ca..c1e06ddd8 100644 --- a/src/scene/primitives/AABB.h +++ b/src/scene/primitives/AABB.h @@ -128,6 +128,27 @@ class AABB : public Primitive { const glm::dvec3& intersectionPoint ) override; /** + * WARNING! The returned + * intersection times should be interpreted as follows, where \f$t_*\f$ + * is the minimum time and \f$t^*\f$ the maximum: + * + * If \f$t_* \geq 0, t^* \geq 0\f$ then the ray intersects the box twice, + * one time to enter the box, another time to leave it. + * + * If \f$t_* < 0, t^* < 0\f$ then the ray does not intersect the + * box, the line will do, but not the ray which is not allowed to + * go backward (see Convex Optimization by Stephen Boyd and Lieven + * Vandenberghe, where a ray is defined as + * \f$\left\{o + tv : t \geq 0\right\}\f$). + * + * If either \f$t_* < 0\f$ or \f$t^* < 0\f$ then the ray intersects the + * box once, it starts inside the box and the intersection occurs when + * the ray leaves the box. + * + * If the returned vector is empty, then there is no line-box intersection + * at all. + * + * * @see Primitive::getRayIntersection */ std::vector getRayIntersection( From b8094ff9b3bdf9afb5788f683c5311da46def200 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 28 Sep 2023 18:10:53 +0200 Subject: [PATCH 09/17] Cleaned new data analytics stuff --- scripts/debug/hda_pulse_records_plotter.py | 336 +++++++++++++----- src/alg/raycast/GroveKDTreeRaycaster.h | 8 - src/alg/raycast/KDGroveRaycaster.cpp | 8 - src/alg/raycast/KDGroveRaycaster.h | 4 - src/alg/raycast/KDTreeRaycaster.cpp | 133 ------- src/alg/raycast/KDTreeRaycaster.h | 14 - src/alg/raycast/Raycaster.h | 4 - src/dataanalytics/HDA_GlobalVars.cpp | 99 ------ src/dataanalytics/HDA_GlobalVars.h | 32 -- src/dataanalytics/HDA_GlobalVarsReporter.h | 38 -- src/dataanalytics/HDA_PulseRecorder.h | 31 +- src/scanner/ScanningDevice.cpp | 2 +- .../detector/DynFullWaveformPulseRunnable.cpp | 7 - .../detector/DynFullWaveformPulseRunnable.h | 3 - .../detector/FullWaveformPulseRunnable.cpp | 26 +- .../detector/FullWaveformPulseRunnable.h | 3 - src/scene/Scene.cpp | 31 +- src/scene/Scene.h | 4 - 18 files changed, 268 insertions(+), 515 deletions(-) diff --git a/scripts/debug/hda_pulse_records_plotter.py b/scripts/debug/hda_pulse_records_plotter.py index ecff9d91c..e96252a40 100755 --- a/scripts/debug/hda_pulse_records_plotter.py +++ b/scripts/debug/hda_pulse_records_plotter.py @@ -3,6 +3,7 @@ import time import numpy as np import matplotlib.pyplot as plt +import matplotlib as mpl # --- FUNCTIONS --- # @@ -101,13 +102,12 @@ def read_records(path, sep=','): 'ray_subray_sign_check': subray_sim[:, 8], 'subray_tmin': subray_sim[:, 9], 'subray_tmax': subray_sim[:, 10], - 'subray_rt_pos_dir': subray_sim[:, 11], # Ray-tracing positive dir. - 'subray_rt_neg_dir': subray_sim[:, 12], # Ray-tracing negative dir. - 'subray_rt_par_dir': subray_sim[:, 13], # Ray-tracing parallel dir. - 'subray_rt_no_second': subray_sim[:, 14], # Ray-tracing no second half - 'subray_rt_no_first': subray_sim[:, 15], # Ray-tracing no first half - 'subray_rt_both': subray_sim[:, 16], # Ray-tracing both sides - 'subray_rt_both2': subray_sim[:, 17] # Ray-tracing both, second try + 'subray_dir_x': subray_sim[:, 11], + 'subray_dir_y': subray_sim[:, 12], + 'subray_dir_z': subray_sim[:, 13], + 'ray_dir_x': subray_sim[:, 14], + 'ray_dir_y': subray_sim[:, 15], + 'ray_dir_z': subray_sim[:, 16] } @@ -134,7 +134,7 @@ def plot_records(arec, brec, outdir): do_by_incidence_angle_plots(arec, brec, outdir) do_subray_hit_plots(arec, brec, outdir) do_ray_subray_plots(arec, brec, outdir) - do_raytracing_plots(arec, brec, outdir) + do_ray_subray_dir_plots(arec, brec, outdir) def validate_record(key, rec, recid): @@ -153,26 +153,28 @@ def validate_record(key, rec, recid): return True -def init_figure(figsize=(20, 12)): +def init_figure(figsize=(20, 12), constrained_layout=False): """Initialize a matplotlib's figure context""" fig = plt.figure( - figsize=figsize + figsize=figsize, + constrained_layout=constrained_layout ) return fig def do_incidence_angle_subplot( fig, ax, phi, label=None, title=None, xlabel=None, ylabel=None, bins=32, - log=False + log=False, relative=False, label_fontsize=16 ): if title is not None: ax.set_title(title, fontsize=20) - hist = ax.hist(phi, bins=bins, label=label, log=log) + weights = 100*np.ones_like(phi)/len(phi) if relative else None + hist = ax.hist(phi, bins=bins, label=label, log=log, weights=weights) ax.axvline(x=np.mean(phi), color='tab:orange', lw=3, label='$\\mu$') if xlabel is not None: - ax.set_xlabel(xlabel, fontsize=16) + ax.set_xlabel(xlabel, fontsize=label_fontsize) if ylabel is not None: - ax.set_ylabel(ylabel, fontsize=16) + ax.set_ylabel(ylabel, fontsize=label_fontsize) ax.tick_params(axis='both', which='both', labelsize=14) ax.legend(loc='upper right', fontsize=14) ax.grid('both') @@ -464,7 +466,6 @@ def do_subray_hit_subplot_hist( fig, ax, hit, x, title=None, xlabel=None, ylabel=None, bins=7, relative=False ): - # TODO Rethink : Implement if title is not None: ax.set_title(title, fontsize=15) x_hit = x[hit] @@ -626,7 +627,6 @@ def do_subray_hit_plots(arec, brec, outdir): relative=True, xlabel='Divergence angle (deg $\\times 10^{-3}$)' ) - # TODO Rethink : Implement fig.tight_layout() # Save figure to file and remove it from memory fig.savefig(os.path.join(outdir, 'subray_hit.png')) @@ -725,108 +725,264 @@ def do_ray_subray_plots(arec, brec, outdir): plt.close(fig) -def do_raytracing_plots(arec, brec, outdir): - # TODO Rethink : Implement +def do_dir_2d_subplot( + fig, ax, x, y, hit=None, title=None, xlabel=None, ylabel=None, legend=False +): + if title is not None: + ax.set_title(title, fontsize=15) + # Plot unitary circumference + theta = np.linspace(-np.pi, np.pi) + ax.plot(np.cos(theta), np.sin(theta), color='black', lw=3, zorder=7) + if hit is not None: + ax.scatter(x[hit], y[hit], s=64, c='tab:red', zorder=6, label='hit') + ax.scatter(x[~hit], y[~hit], s=64, c='tab:blue', zorder=5, label='hit') + if legend: + ax.legend(loc='upper right').set_zorder(11) + else: + ax.scatter(x, y, s=64, c='tab:green', zorder=6) + if xlabel is not None: + ax.set_xlabel(xlabel, fontsize=14) + if ylabel is not None: + ax.set_ylabel(ylabel, fontsize=14) + ax.axis('equal') + + +def do_ray_subray_dir_plots(arec, brec, outdir): + # Validate ray and subray direction data if( - not validate_record('subray_hit', arec, 'a') or - not validate_record('subray_rt_pos_dir', arec, 'a') or - not validate_record('subray_rt_neg_dir', arec, 'a') or - not validate_record('subray_rt_par_dir', arec, 'a') or - not validate_record('subray_rt_no_second', arec, 'a') or - not validate_record('subray_rt_no_first', arec, 'a') or - not validate_record('subray_rt_both', arec, 'a') or - not validate_record('subray_rt_both2', arec, 'a') or - not validate_record('subray_hit', brec, 'b') or - not validate_record('subray_rt_pos_dir', brec, 'b') or - not validate_record('subray_rt_neg_dir', brec, 'b') or - not validate_record('subray_rt_par_dir', brec, 'b') or - not validate_record('subray_rt_no_second', brec, 'b') or - not validate_record('subray_rt_no_first', brec, 'b') or - not validate_record('subray_rt_both', brec, 'b') or - not validate_record('subray_rt_both2', brec, 'b') + not validate_record('subray_dir_x', arec, 'a') or + not validate_record('subray_dir_y', arec, 'a') or + not validate_record('subray_dir_z', arec, 'a') or + not validate_record('ray_dir_x', arec, 'a') or + not validate_record('ray_dir_y', arec, 'a') or + not validate_record('ray_dir_z', arec, 'a') or + not validate_record('subray_dir_x', brec, 'b') or + not validate_record('subray_dir_y', brec, 'b') or + not validate_record('subray_dir_z', brec, 'b') or + not validate_record('ray_dir_x', brec, 'b') or + not validate_record('ray_dir_y', brec, 'b') or + not validate_record('ray_dir_z', brec, 'b') ): - print('Cannot do ray-tracing plots') + print('Cannot do ray and subray direction plots') return - # Do the ray-tracing plots + # Do the ray subray direction plots fig = init_figure() # Initialize figure - # CASE A - ax = fig.add_subplot(4, 7, 1) # Initialize positive direction hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_pos_dir'], - ylabel='Absolute' + gs = plt.GridSpec(4, 1, figure=fig) + gs0 = mpl.gridspec.GridSpecFromSubplotSpec( + 1, 6, subplot_spec=gs[0], wspace=0.3 ) - ax = fig.add_subplot(4, 7, 2) # Initialize negative direction hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_neg_dir'], + gs1 = mpl.gridspec.GridSpecFromSubplotSpec( + 1, 4, subplot_spec=gs[1] ) - ax = fig.add_subplot(4, 7, 3) # Initialize parallel direction hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_par_dir'], + gs2 = mpl.gridspec.GridSpecFromSubplotSpec( + 1, 6, subplot_spec=gs[2], wspace=0.3 ) - ax = fig.add_subplot(4, 7, 4) # Initialize no second half hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_no_second'], + gs3 = mpl.gridspec.GridSpecFromSubplotSpec( + 1, 4, subplot_spec=gs[3] ) - ax = fig.add_subplot(4, 7, 5) # Initialize no second half hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_no_first'], + # CASE A + ax = fig.add_subplot(gs0[0, 0]) # Initialize subray dir xy subplot + subray_xynorm = np.linalg.norm(np.array([ + arec['subray_dir_x'], arec['subray_dir_y'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + arec['subray_dir_x']/subray_xynorm, + arec['subray_dir_y']/subray_xynorm, + hit=arec['subray_hit'], + title='A subray (x, y)', + xlabel='$x$', ylabel='$y$', + legend=True + ) + ax = fig.add_subplot(gs0[0, 1]) # Initialize subray dir xz subplot + xznorm = np.linalg.norm(np.array([ + arec['subray_dir_x'], arec['subray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + arec['subray_dir_x']/xznorm, + arec['subray_dir_z']/xznorm, + hit=arec['subray_hit'], + title='subray (x, z)', + xlabel='$x$', ylabel='$z$' + ) + ax = fig.add_subplot(gs0[0, 2]) # Initialize subray dir yz subplot + yznorm = np.linalg.norm(np.array([ + arec['subray_dir_y'], arec['subray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + arec['subray_dir_y']/yznorm, + arec['subray_dir_z']/yznorm, + hit=arec['subray_hit'], + title='subray (y, z)', + xlabel='$y$', ylabel='$z$' + ) + ax = fig.add_subplot(gs0[0, 3]) # Initialize ray dir xy subplot + ray_xynorm = np.linalg.norm(np.array([ + arec['ray_dir_x'], arec['ray_dir_y'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + arec['ray_dir_x']/ray_xynorm, + arec['ray_dir_y']/ray_xynorm, + title='ray (x, y)', + xlabel='$x$', ylabel='$y$', + legend=True + ) + ax = fig.add_subplot(gs0[0, 4]) # Initialize ray dir xz subplot + xznorm = np.linalg.norm(np.array([ + arec['ray_dir_x'], arec['ray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + arec['ray_dir_x']/xznorm, + arec['ray_dir_z']/xznorm, + title='ray (x, z)', + xlabel='$x$', ylabel='$z$' + ) + ax = fig.add_subplot(gs0[0, 5]) # Initialize ray dir yz subplot + yznorm = np.linalg.norm(np.array([ + arec['ray_dir_y'], arec['ray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + arec['ray_dir_y']/yznorm, + arec['ray_dir_z']/yznorm, + title='ray (y, z)', + xlabel='$y$', ylabel='$z$' ) - ax = fig.add_subplot(4, 7, 6) # Initialize both sides hist + + ax = fig.add_subplot(gs1[0, 0]) # Initialize subray dir xy histogram do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_both'], + fig, ax, arec['subray_hit'], subray_xynorm, + xlabel='Subray dir norm on (x, y)', + ylabel='A Relative (100%)', + relative=True ) - ax = fig.add_subplot(4, 7, 7) # Initialize both sides hist + ax = fig.add_subplot(gs1[0, 1]) # Initialize subray dir xy histogram do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_both2'], + fig, ax, arec['subray_hit'], arec['subray_dir_z'], + xlabel='Subray dir z', + relative=True ) - ax = fig.add_subplot(4, 7, 8) # Initialize positive direction hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_pos_dir'], + ax = fig.add_subplot(gs1[0, 2]) # Initialize subray dir xy histogram + do_incidence_angle_subplot( + fig, ax, ray_xynorm, + xlabel='Ray dir norm on (x, y)', relative=True, - xlabel='Positive direction', - ylabel='Relative (100%)' + label_fontsize=14 ) - ax = fig.add_subplot(4, 7, 9) # Initialize negative direction hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_neg_dir'], + ax = fig.add_subplot(gs1[0, 3]) # Initialize subray dir xy histogram + do_incidence_angle_subplot( + fig, ax, arec['ray_dir_z'], + xlabel='Ray dir z', relative=True, - xlabel='Negative direction', + label_fontsize=14 ) - ax = fig.add_subplot(4, 7, 10) # Initialize parallel direction hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_par_dir'], - relative=True, - xlabel='Parallel direction', + # CASE B + ax = fig.add_subplot(gs2[0, 0]) # Initialize subray dir xy subplot + subray_xynorm = np.linalg.norm(np.array([ + brec['subray_dir_x'], brec['subray_dir_y'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + brec['subray_dir_x']/subray_xynorm, + brec['subray_dir_y']/subray_xynorm, + hit=brec['subray_hit'], + title='B subray (x, y)', + xlabel='$x$', ylabel='$y$', + legend=True + ) + ax = fig.add_subplot(gs2[0, 1]) # Initialize subray dir xz subplot + xznorm = np.linalg.norm(np.array([ + brec['subray_dir_x'], brec['subray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + brec['subray_dir_x']/xznorm, + brec['subray_dir_z']/xznorm, + hit=brec['subray_hit'], + title='subray (x, z)', + xlabel='$x$', ylabel='$z$' + ) + ax = fig.add_subplot(gs2[0, 2]) # Initialize subray dir yz subplot + yznorm = np.linalg.norm(np.array([ + brec['subray_dir_y'], brec['subray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + brec['subray_dir_y']/yznorm, + brec['subray_dir_z']/yznorm, + hit=brec['subray_hit'], + title='subray (y, z)', + xlabel='$y$', ylabel='$z$' + ) + ax = fig.add_subplot(gs2[0, 3]) # Initialize ray dir xy subplot + ray_xynorm = np.linalg.norm(np.array([ + brec['ray_dir_x'], brec['ray_dir_y'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + brec['ray_dir_x']/ray_xynorm, + brec['ray_dir_y']/ray_xynorm, + title='ray (x, y)', + xlabel='$x$', ylabel='$y$', + legend=True + ) + ax = fig.add_subplot(gs2[0, 4]) # Initialize ray dir xz subplot + xznorm = np.linalg.norm(np.array([ + brec['ray_dir_x'], brec['ray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + brec['ray_dir_x']/xznorm, + brec['ray_dir_z']/xznorm, + title='ray (x, z)', + xlabel='$x$', ylabel='$z$' + ) + ax = fig.add_subplot(gs2[0, 5]) # Initialize ray dir yz subplot + yznorm = np.linalg.norm(np.array([ + brec['ray_dir_y'], brec['ray_dir_z'] + ]), axis=0) + do_dir_2d_subplot( + fig, ax, + brec['ray_dir_y']/yznorm, + brec['ray_dir_z']/yznorm, + title='ray (y, z)', + xlabel='$y$', ylabel='$z$' ) - ax = fig.add_subplot(4, 7, 11) # Initialize no second half hist + ax = fig.add_subplot(gs3[0, 0]) # Initialize subray dir xy histogram do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_no_second'], - relative=True, - xlabel='No second half', + fig, ax, brec['subray_hit'], subray_xynorm, + xlabel='Subray dir norm on (x, y)', + ylabel='B Relative (100%)', + relative=True ) - ax = fig.add_subplot(4, 7, 12) # Initialize no second half hist + ax = fig.add_subplot(gs3[0, 1]) # Initialize subray dir xy histogram do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_no_first'], - relative=True, - xlabel='No first half', + fig, ax, brec['subray_hit'], brec['subray_dir_z'], + xlabel='Subray dir z', + relative=True ) - ax = fig.add_subplot(4, 7, 13) # Initialize both sides hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_both'], + ax = fig.add_subplot(gs3[0, 2]) # Initialize subray dir xy histogram + do_incidence_angle_subplot( + fig, ax, ray_xynorm, + xlabel='Ray dir norm on (x, y)', relative=True, - xlabel='Both sides', + label_fontsize=14 ) - ax = fig.add_subplot(4, 7, 14) # Initialize both sides hist - do_subray_hit_subplot_hist( - fig, ax, arec['subray_hit'], arec['subray_rt_both2'], + ax = fig.add_subplot(gs3[0, 3]) # Initialize subray dir xy histogram + do_incidence_angle_subplot( + fig, ax, brec['ray_dir_z'], + xlabel='Ray dir z', relative=True, - xlabel='Both sides ($2^{\mathrm{nd}}$ try)', + label_fontsize=14 ) - # CASE B - fig.tight_layout() # Save figure to file and remove it from memory + fig.tight_layout() fig.savefig( - os.path.join(outdir, 'subray_ray_tracing.png') + os.path.join(outdir, 'ray_subray_dir.png') ) fig.clear() plt.close(fig) diff --git a/src/alg/raycast/GroveKDTreeRaycaster.h b/src/alg/raycast/GroveKDTreeRaycaster.h index 031fb7bb1..85ceac12e 100644 --- a/src/alg/raycast/GroveKDTreeRaycaster.h +++ b/src/alg/raycast/GroveKDTreeRaycaster.h @@ -80,16 +80,8 @@ class GroveKDTreeRaycaster : double tmin, double tmax, bool groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray=false -#endif ) override {return KDTreeRaycaster::search( rayOrigin, rayDir, tmin, tmax, groundOnly -#ifdef DATA_ANALYTICS - ,subraySimRecord, - isSubray -#endif );} // *** GROVE DYNAMIC TREE METHODS *** // diff --git a/src/alg/raycast/KDGroveRaycaster.cpp b/src/alg/raycast/KDGroveRaycaster.cpp index 007e57159..20342dde0 100644 --- a/src/alg/raycast/KDGroveRaycaster.cpp +++ b/src/alg/raycast/KDGroveRaycaster.cpp @@ -26,10 +26,6 @@ RaySceneIntersection * KDGroveRaycaster::search( double tmin, double tmax, bool groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray -#endif ){ std::map out; size_t const m = grove->getNumTrees(); @@ -37,10 +33,6 @@ RaySceneIntersection * KDGroveRaycaster::search( for(size_t i = 0 ; i < m ; ++i){ rsi = grove->getTreeShared(i)->search( rayOrigin, rayDir, tmin, tmax, groundOnly -#ifdef DATA_ANALYTICS - ,subraySimRecord, - isSubray -#endif ); if( bestRSI==nullptr || diff --git a/src/alg/raycast/KDGroveRaycaster.h b/src/alg/raycast/KDGroveRaycaster.h index 8dc4a18b0..943dcfbef 100644 --- a/src/alg/raycast/KDGroveRaycaster.h +++ b/src/alg/raycast/KDGroveRaycaster.h @@ -56,10 +56,6 @@ class KDGroveRaycaster : public Raycaster{ double tmin, double tmax, bool groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray=false -#endif ) override; // *** KDGROVE RELATED METHODS *** // diff --git a/src/alg/raycast/KDTreeRaycaster.cpp b/src/alg/raycast/KDTreeRaycaster.cpp index ccd860ce7..1c3e9367c 100644 --- a/src/alg/raycast/KDTreeRaycaster.cpp +++ b/src/alg/raycast/KDTreeRaycaster.cpp @@ -1,11 +1,6 @@ #include "KDTreeRaycaster.h" #include "logging.hpp" -#ifdef DATA_ANALYTICS -#include -using helios::analytics::HDA_GV; -#endif - using namespace std; map KDTreeRaycaster::searchAll( @@ -37,10 +32,6 @@ RaySceneIntersection* KDTreeRaycaster::search( double const tmin, double const tmax, bool const groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray -#endif ){ // Prepare search KDTreeRaycasterSearch search(rayDir, rayOrigin, groundOnly); @@ -52,38 +43,12 @@ RaySceneIntersection* KDTreeRaycaster::search( search.rayOriginArray.push_back(rayOrigin.z); // Do recursive search -#ifdef DATA_ANALYTICS - std::size_t positiveDirectionCount = 0, negativeDirectionCount = 0; - std::size_t noSecondHalfCount = 0, noFirstHalfCount = 0; - std::size_t parallelDirectionCount = 0, bothSidesCount = 0; - std::size_t bothSidesSecondTryCount = 0; -#endif Primitive* prim = this->search_recursive( this->root.get(), tmin-epsilon, tmax+epsilon, search -#ifdef DATA_ANALYTICS - ,positiveDirectionCount, - negativeDirectionCount, - parallelDirectionCount, - noSecondHalfCount, - noFirstHalfCount, - bothSidesCount, - bothSidesSecondTryCount, - isSubray -#endif ); -#ifdef DATA_ANALYTICS - // Write counts to subray simulation record - subraySimRecord[11] = (double) positiveDirectionCount; - subraySimRecord[12] = (double) negativeDirectionCount; - subraySimRecord[13] = (double) parallelDirectionCount; - subraySimRecord[14] = (double) noSecondHalfCount; - subraySimRecord[15] = (double) noFirstHalfCount; - subraySimRecord[16] = (double) bothSidesCount; - subraySimRecord[17] = (double) bothSidesSecondTryCount; -#endif // Handle search output if (prim == nullptr) return nullptr; @@ -205,16 +170,6 @@ Primitive* KDTreeRaycaster::search_recursive( double const tmin, double const tmax, KDTreeRaycasterSearch &search -#ifdef DATA_ANALYTICS - ,size_t &positiveDirectionCount, - size_t &negativeDirectionCount, - size_t ¶llelDirectionCount, - size_t &noSecondHalfCount, - size_t &noFirstHalfCount, - size_t &bothSidesCount, - size_t &bothSidesSecondTryCount, - bool const isSubray -#endif ) const { if(node==nullptr) return nullptr; // Null nodes cannot contain primitives Primitive* hitPrim = nullptr; @@ -242,43 +197,9 @@ Primitive* KDTreeRaycaster::search_recursive( // (in other leaves, with other primitives) that are *closer* to // the ray originWaypoint. If this was the case, the returned intersection // would be wrong. -#ifdef DATA_ANALYTICS - bool const nonNegativeDistance = newDistance > 0; - bool const closerThanClosest = - newDistance < search.closestHitDistance; - bool const tminCheck = newDistance >= tmin; - bool const tmaxCheck = newDistance <= tmax; - if(!nonNegativeDistance){ // For any traced ray - HDA_GV.incrementRaycasterLeafNegativeDistancesCount(); - } else if(!closerThanClosest){ - HDA_GV.incrementRaycasterLeafFurtherThanClosestCount(); - } else if(!tminCheck){ - HDA_GV.incrementRaycasterLeafFailedTminCheckCount(); - } - else if(!tmaxCheck){ - HDA_GV.incrementRaycasterLeafFailedTmaxCheckCount(); - } - if(isSubray){ // For any traced ray that is a subray - if(!nonNegativeDistance){ - HDA_GV.incrementSubrayLeafNegativeDistancesCount(); - } else if(!closerThanClosest){ - HDA_GV.incrementSubrayLeafFurtherThanClosestCount(); - } else if(!tminCheck){ - HDA_GV.incrementSubrayLeafFailedTminCheckCount(); - } - else if(!tmaxCheck){ - HDA_GV.incrementSubrayLeafFailedTmaxCheckCount(); - } - - } - if( - nonNegativeDistance && closerThanClosest && - tminCheck && tmaxCheck -#else if( newDistance > 0 && newDistance < search.closestHitDistance && newDistance >= tmin && newDistance <= tmax -#endif ){ if( !search.groundOnly || @@ -306,9 +227,6 @@ Primitive* KDTreeRaycaster::search_recursive( // Case 1: Ray goes in positive direction - it passes through the left side first, then through the right: if (search.rayDirArray[a] > 0) { -#ifdef DATA_ANALYTICS - ++positiveDirectionCount; -#endif first = node->left; second = node->right; @@ -317,9 +235,6 @@ Primitive* KDTreeRaycaster::search_recursive( } // Case 2: Ray goes in negative direction - it passes through the right side first, then through the left: else if (search.rayDirArray[a] < 0) { -#ifdef DATA_ANALYTICS - ++negativeDirectionCount; -#endif first = node->right; second = node->left; @@ -328,9 +243,6 @@ Primitive* KDTreeRaycaster::search_recursive( } // Case 3: Ray goes parallel to the split plane - it passes through only one side, depending on it's originWaypoint: else { -#ifdef DATA_ANALYTICS - ++parallelDirectionCount; -#endif first = (search.rayOriginArray[a] < node->splitPos) ? node->left : node->right; second = (search.rayOriginArray[a] < node->splitPos) ? @@ -343,74 +255,29 @@ Primitive* KDTreeRaycaster::search_recursive( // thit >= tmax means that the ray crosses the split plane *after it has already left the volume*. // In this case, it never enters the second half. if (thit >= tmax) { -#ifdef DATA_ANALYTICS - ++noSecondHalfCount; -#endif hitPrim = search_recursive( first, tmin, tmax, search -#ifdef DATA_ANALYTICS - ,positiveDirectionCount, - negativeDirectionCount, - parallelDirectionCount, - noSecondHalfCount, - noFirstHalfCount, - bothSidesCount, - bothSidesSecondTryCount -#endif ); } // thit <= tmin means that the ray crosses the split plane *before it enters the volume*. // In this case, it never enters the first half: else if (thit <= tmin) { -#ifdef DATA_ANALYTICS - ++noFirstHalfCount; -#endif hitPrim = search_recursive( second, tmin, tmax, search -#ifdef DATA_ANALYTICS - ,positiveDirectionCount, - negativeDirectionCount, - parallelDirectionCount, - noSecondHalfCount, - noFirstHalfCount, - bothSidesCount, - bothSidesSecondTryCount -#endif ); } // Otherwise, the ray crosses the split plane within the volume. // This means that it passes through both sides: else { -#ifdef DATA_ANALYTICS - ++bothSidesCount; -#endif hitPrim = search_recursive( first, tmin, thit+epsilon, search -#ifdef DATA_ANALYTICS - ,positiveDirectionCount, - negativeDirectionCount, - parallelDirectionCount, - noSecondHalfCount, - noFirstHalfCount, - bothSidesCount, - bothSidesSecondTryCount -#endif ); if (hitPrim == nullptr) { hitPrim = search_recursive( second, thit-epsilon, tmax, search -#ifdef DATA_ANALYTICS - ,positiveDirectionCount, - negativeDirectionCount, - parallelDirectionCount, - noSecondHalfCount, - noFirstHalfCount, - bothSidesCount, - bothSidesSecondTryCount -#endif ); } } diff --git a/src/alg/raycast/KDTreeRaycaster.h b/src/alg/raycast/KDTreeRaycaster.h index c42b27b21..108f33dbd 100644 --- a/src/alg/raycast/KDTreeRaycaster.h +++ b/src/alg/raycast/KDTreeRaycaster.h @@ -140,10 +140,6 @@ class KDTreeRaycasterSearch{ double const tmin, double const tmax, bool const groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray=false -#endif ) override; protected: @@ -187,15 +183,5 @@ class KDTreeRaycasterSearch{ double const tmin, double const tmax, KDTreeRaycasterSearch &search -#ifdef DATA_ANALYTICS - ,size_t &positiveDirectionCount, - size_t &negativeDirectionCount, - size_t ¶llelDirectionCount, - size_t &noSecondHalfCount, - size_t &noFirstHalfCount, - size_t &bothSidesCount, - size_t &bothSidesSecondTryCount, - bool const isSubray=false -#endif ) const; }; \ No newline at end of file diff --git a/src/alg/raycast/Raycaster.h b/src/alg/raycast/Raycaster.h index 875363b9f..9d6d03462 100644 --- a/src/alg/raycast/Raycaster.h +++ b/src/alg/raycast/Raycaster.h @@ -62,9 +62,5 @@ class Raycaster{ double tmin, double tmax, bool groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray=false -#endif ) = 0; }; \ No newline at end of file diff --git a/src/dataanalytics/HDA_GlobalVars.cpp b/src/dataanalytics/HDA_GlobalVars.cpp index d618cc407..695753ed3 100644 --- a/src/dataanalytics/HDA_GlobalVars.cpp +++ b/src/dataanalytics/HDA_GlobalVars.cpp @@ -75,61 +75,6 @@ HDA_GlobalVars & HDA_GlobalVars::incrementSubrayNonIntersectionCount() { return *this; } -HDA_GlobalVars & -HDA_GlobalVars::incrementRaycasterLeafNegativeDistancesCount(){ - std::unique_lock lock( - raycasterLeafNegativeDistancesCount_mutex - ); - ++raycasterLeafNegativeDistancesCount; - return *this; -} - -HDA_GlobalVars & -HDA_GlobalVars::incrementRaycasterLeafFurtherThanClosestCount(){ - std::unique_lock lock( - raycasterLeafFurtherThanClosestCount_mutex - ); - ++raycasterLeafFurtherThanClosestCount; - return *this; -} - -HDA_GlobalVars & HDA_GlobalVars::incrementRaycasterLeafFailedTminCheckCount(){ - std::unique_lock lock(raycasterLeafFailedTminCheckCount_mutex); - ++raycasterLeafFailedTminCheckCount; - return *this; -} - -HDA_GlobalVars & HDA_GlobalVars::incrementRaycasterLeafFailedTmaxCheckCount(){ - std::unique_lock lock(raycasterLeafFailedTmaxCheckCount_mutex); - ++raycasterLeafFailedTmaxCheckCount; - return *this; -} - -HDA_GlobalVars & -HDA_GlobalVars::incrementSubrayLeafNegativeDistancesCount(){ - std::unique_lock lock(subrayLeafNegativeDistancesCount_mutex); - ++subrayLeafNegativeDistancesCount; - return *this; -} - -HDA_GlobalVars & -HDA_GlobalVars::incrementSubrayLeafFurtherThanClosestCount(){ - std::unique_lock lock(subrayLeafFurtherThanClosestCount_mutex); - ++subrayLeafFurtherThanClosestCount; - return *this; -} - -HDA_GlobalVars & HDA_GlobalVars::incrementSubrayLeafFailedTminCheckCount(){ - std::unique_lock lock(subrayLeafFailedTminCheckCount_mutex); - ++subrayLeafFailedTminCheckCount; - return *this; -} - -HDA_GlobalVars & HDA_GlobalVars::incrementSubrayLeafFailedTmaxCheckCount(){ - std::unique_lock lock(subrayLeafFailedTmaxCheckCount_mutex); - ++subrayLeafFailedTmaxCheckCount; - return *this; -} // *** READ METHODS *** // // ********************** // @@ -184,50 +129,6 @@ std::size_t HDA_GlobalVars::getIntensityComputationsCount(){ return intensityComputationsCount; } -std::size_t HDA_GlobalVars::getRaycasterLeafNegativeDistancesCount(){ - std::unique_lock lock( - raycasterLeafNegativeDistancesCount_mutex - ); - return raycasterLeafNegativeDistancesCount; -} - -std::size_t HDA_GlobalVars::getRaycasterLeafFurtherThanClosestCount(){ - std::unique_lock lock( - raycasterLeafFurtherThanClosestCount_mutex - ); - return raycasterLeafFurtherThanClosestCount; -} - -std::size_t HDA_GlobalVars::getRaycasterLeafFailedTminCheckCount(){ - std::unique_lock lock(raycasterLeafFailedTminCheckCount_mutex); - return raycasterLeafFailedTminCheckCount; -} - -std::size_t HDA_GlobalVars::getRaycasterLeafFailedTmaxCheckCount(){ - std::unique_lock lock(raycasterLeafFailedTmaxCheckCount_mutex); - return raycasterLeafFailedTmaxCheckCount; -} - -unsigned long HDA_GlobalVars::getSubrayLeafNegativeDistancesCount(){ - std::unique_lock lock(subrayLeafNegativeDistancesCount_mutex); - return subrayLeafNegativeDistancesCount; -} - -unsigned long HDA_GlobalVars::getSubrayLeafFurtherThanClosestCount(){ - std::unique_lock lock(subrayLeafFurtherThanClosestCount_mutex); - return subrayLeafFurtherThanClosestCount; -} - -unsigned long HDA_GlobalVars::getSubrayLeafFailedTminCheckCount(){ - std::unique_lock lock(subrayLeafFailedTminCheckCount_mutex); - return subrayLeafFailedTminCheckCount; -} - -unsigned long HDA_GlobalVars::getSubrayLeafFailedTmaxCheckCount(){ - std::unique_lock lock(subrayLeafFailedTmaxCheckCount_mutex); - return subrayLeafFailedTmaxCheckCount; -} - }} diff --git a/src/dataanalytics/HDA_GlobalVars.h b/src/dataanalytics/HDA_GlobalVars.h index b8d7d20ff..248f904ad 100644 --- a/src/dataanalytics/HDA_GlobalVars.h +++ b/src/dataanalytics/HDA_GlobalVars.h @@ -23,14 +23,6 @@ class HDA_GlobalVars{ std::size_t subrayIntersectionCount; std::size_t subrayNonIntersectionCount; std::size_t intensityComputationsCount; - std::size_t raycasterLeafNegativeDistancesCount; - std::size_t raycasterLeafFurtherThanClosestCount; - std::size_t raycasterLeafFailedTminCheckCount; - std::size_t raycasterLeafFailedTmaxCheckCount; - unsigned long subrayLeafNegativeDistancesCount; - unsigned long subrayLeafFurtherThanClosestCount; - unsigned long subrayLeafFailedTminCheckCount; - unsigned long subrayLeafFailedTmaxCheckCount; protected: // *** CONCURRENCY HANDLING ATTRIBUTES *** // @@ -44,14 +36,6 @@ class HDA_GlobalVars{ std::mutex subrayIntersectionCount_mutex; std::mutex subrayNonIntersectionCount_mutex; std::mutex intensityComputationsCount_mutex; - std::mutex raycasterLeafNegativeDistancesCount_mutex; - std::mutex raycasterLeafFurtherThanClosestCount_mutex; - std::mutex raycasterLeafFailedTminCheckCount_mutex; - std::mutex raycasterLeafFailedTmaxCheckCount_mutex; - std::mutex subrayLeafNegativeDistancesCount_mutex; - std::mutex subrayLeafFurtherThanClosestCount_mutex; - std::mutex subrayLeafFailedTminCheckCount_mutex; - std::mutex subrayLeafFailedTmaxCheckCount_mutex; public: // *** CONSTRUCTION / DESTRUCTION *** // @@ -80,14 +64,6 @@ class HDA_GlobalVars{ HDA_GlobalVars & incrementSubrayIntersectionCount(); HDA_GlobalVars & incrementSubrayNonIntersectionCount(); HDA_GlobalVars & incrementIntensityComputationsCount(); - HDA_GlobalVars & incrementRaycasterLeafNegativeDistancesCount(); - HDA_GlobalVars & incrementRaycasterLeafFurtherThanClosestCount(); - HDA_GlobalVars & incrementRaycasterLeafFailedTminCheckCount(); - HDA_GlobalVars & incrementRaycasterLeafFailedTmaxCheckCount(); - HDA_GlobalVars & incrementSubrayLeafNegativeDistancesCount(); - HDA_GlobalVars & incrementSubrayLeafFurtherThanClosestCount(); - HDA_GlobalVars & incrementSubrayLeafFailedTminCheckCount(); - HDA_GlobalVars & incrementSubrayLeafFailedTmaxCheckCount(); // *** READ METHODS *** // // ********************** // @@ -100,14 +76,6 @@ class HDA_GlobalVars{ std::size_t getSubrayIntersectionCount(); std::size_t getSubrayNonIntersectionCount(); std::size_t getIntensityComputationsCount(); - std::size_t getRaycasterLeafNegativeDistancesCount(); - std::size_t getRaycasterLeafFurtherThanClosestCount(); - std::size_t getRaycasterLeafFailedTminCheckCount(); - std::size_t getRaycasterLeafFailedTmaxCheckCount(); - unsigned long getSubrayLeafNegativeDistancesCount(); - unsigned long getSubrayLeafFurtherThanClosestCount(); - unsigned long getSubrayLeafFailedTminCheckCount(); - unsigned long getSubrayLeafFailedTmaxCheckCount(); }; }} diff --git a/src/dataanalytics/HDA_GlobalVarsReporter.h b/src/dataanalytics/HDA_GlobalVarsReporter.h index 19ace808f..35e4034fa 100644 --- a/src/dataanalytics/HDA_GlobalVarsReporter.h +++ b/src/dataanalytics/HDA_GlobalVarsReporter.h @@ -27,16 +27,6 @@ class HDA_GlobalVarsReporter{ // Initialize string stream to build the print std::stringstream ss; - // Extract variables for the sake of convenience - size_t const raycasterLeafFailedTminCheckCount = - HDA_GV.getRaycasterLeafFailedTminCheckCount(); - size_t const raycasterLeafFailedTmaxCheckCount = - HDA_GV.getRaycasterLeafFailedTmaxCheckCount(); - size_t const subrayLeafFailedTminCheckCount = - HDA_GV.getSubrayLeafFailedTminCheckCount(); - size_t const subrayLeafFailedTmaxCheckCount = - HDA_GV.getSubrayLeafFailedTmaxCheckCount(); - // Print global variables ss << "HDA GLOBAL VARS REPORT:\n\n"; ss << "Generated rays before early abort: " @@ -56,34 +46,6 @@ class HDA_GlobalVarsReporter{ << gv.getSubrayNonIntersectionCount() << "\n"; ss << "Number of computed intensities: " << gv.getIntensityComputationsCount() << "\n"; - ss << "Raycaster fails-on-leaves distribution:\n" - << "\tNegative distances: " - << HDA_GV.getRaycasterLeafNegativeDistancesCount() << "\n" - << "\tFurther than current closest: " - << HDA_GV.getRaycasterLeafFurtherThanClosestCount() << "\n" - << "\tFailed tmin checks: " - << raycasterLeafFailedTminCheckCount << "\n" - << "\tFailed tmax checks: " - << raycasterLeafFailedTmaxCheckCount << "\n" - << "\tFailed t checks: " - << ( - raycasterLeafFailedTminCheckCount + - raycasterLeafFailedTmaxCheckCount - ) << "\n" - << "\tSubrays only:\n" - << "\t\tNegative distances: " - << HDA_GV.getSubrayLeafNegativeDistancesCount() << "\n" - << "\t\tFurther than current closest: " - << HDA_GV.getSubrayLeafFurtherThanClosestCount() << "\n" - << "\t\tFailed tmin checks: " - << subrayLeafFailedTminCheckCount << "\n" - << "\t\tFailed tmax checks: " - << subrayLeafFailedTmaxCheckCount << "\n" - << "\t\tFailed t checks: " - << ( - raycasterLeafFailedTminCheckCount + - raycasterLeafFailedTmaxCheckCount - ) << "\n"; // Print through info logging level system std::string text = ss.str(); logging::INFO(ss.str()); diff --git a/src/dataanalytics/HDA_PulseRecorder.h b/src/dataanalytics/HDA_PulseRecorder.h index c8c67e5f1..dce8fb55e 100644 --- a/src/dataanalytics/HDA_PulseRecorder.h +++ b/src/dataanalytics/HDA_PulseRecorder.h @@ -73,36 +73,17 @@ class HDA_PulseRecorder : public HDA_Recorder{ * * [10] -> Max time for subray intersection * - * [11] -> Count of subray as positive direction during ray tracing + * [11] -> Subray direction (x component) * - * [12] -> Count of subray as negative direction during ray tracing + * [12] -> Subray direction (y component) * - * [13] -> Count of subray as parallel direction during ray tracing + * [13] -> Subray direction (z component) * - * [14] -> Count of subray as not touching the second half of a node during - * ray tracing + * [14] -> Ray direction (x component) * - * [15] -> Count of subray as not touching the first half of a node during - * ray tracing + * [15] -> Ray direction (y component) * - * [16] -> Count of subray as touching both sides of a node during ray - * tracing - * - * [17] -> Count of subrays as touching both sides of a node during a - * second ray tracing try (which uses thit-epsilon for tmin, while the - * first try uses thit+epsilon) - * - * [18] -> Subray direction (x component) - * - * [19] -> Subray direction (y component) - * - * [20] -> Subray direction (z component) - * - * [21] -> Ray direction (x component) - * - * [22] -> Ray direction (y component) - * - * [23] -> Ray direction (z component) + * [16] -> Ray direction (z component) */ std::shared_ptr>> subraySim; diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index 214c73624..16548410b 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -268,7 +268,7 @@ void ScanningDevice::computeSubrays( for (int circleStep = 0; circleStep < circleSteps; circleStep++){ #ifdef DATA_ANALYTICS std::vector subraySimRecord( - 24, std::numeric_limits::quiet_NaN() + 17, std::numeric_limits::quiet_NaN() ); #endif handleSubray( diff --git a/src/scanner/detector/DynFullWaveformPulseRunnable.cpp b/src/scanner/detector/DynFullWaveformPulseRunnable.cpp index 34a0542a5..f71b04695 100644 --- a/src/scanner/detector/DynFullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/DynFullWaveformPulseRunnable.cpp @@ -7,17 +7,10 @@ DynFullWaveformPulseRunnable::findIntersection( vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord -#endif ) const{ // Consider scene AABB intersection check was done before at operator() // Thus, proceed to raycasting directly return shared_ptr(raycaster->search( o, v, tMinMax[0], tMinMax[1], false -#ifdef DATA_ANALYTICS - ,subraySimRecord, - true // Subray flag -#endif )); } diff --git a/src/scanner/detector/DynFullWaveformPulseRunnable.h b/src/scanner/detector/DynFullWaveformPulseRunnable.h index 772d44a07..9bea8c46e 100644 --- a/src/scanner/detector/DynFullWaveformPulseRunnable.h +++ b/src/scanner/detector/DynFullWaveformPulseRunnable.h @@ -50,8 +50,5 @@ class DynFullWaveformPulseRunnable : public FullWaveformPulseRunnable { vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord -#endif ) const override; }; \ No newline at end of file diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index c2675480e..0bcedc8dd 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -214,12 +214,12 @@ void FullWaveformPulseRunnable::handleSubray( subraySimRecord[8] = (rayDirection[0] < 0) == (subrayDirection[0] < 0); subraySimRecord[9] = tMinMax[0]; subraySimRecord[10] = tMinMax[1]; - subraySimRecord[18] = subrayDirection.x; - subraySimRecord[19] = subrayDirection.y; - subraySimRecord[20] = subrayDirection.z; - subraySimRecord[21] = rayDirection.x; - subraySimRecord[22] = rayDirection.y; - subraySimRecord[23] = rayDirection.z; + subraySimRecord[11] = subrayDirection.x; + subraySimRecord[12] = subrayDirection.y; + subraySimRecord[13] = subrayDirection.z; + subraySimRecord[14] = rayDirection.x; + subraySimRecord[15] = rayDirection.y; + subraySimRecord[16] = rayDirection.z; #endif glm::dvec3 subrayOrigin(pulse.getOrigin()); @@ -231,9 +231,6 @@ void FullWaveformPulseRunnable::handleSubray( tMinMax, subrayOrigin, subrayDirection -#ifdef DATA_ANALYTICS - ,subraySimRecord -#endif ); if (intersect != nullptr && intersect->prim != nullptr) { @@ -760,17 +757,8 @@ shared_ptr FullWaveformPulseRunnable::findIntersection( vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord -#endif ) const { - return scene.getIntersection( - tMinMax, o, v, false -#ifdef DATA_ANALYTICS - ,subraySimRecord, - true // Subray flag -#endif - ); + return scene.getIntersection(tMinMax, o, v, false); } void FullWaveformPulseRunnable::captureFullWave( diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index dfa6be5d4..00d13d62b 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -274,9 +274,6 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { vector const &tMinMax, glm::dvec3 const &o, glm::dvec3 const &v -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord -#endif ) const; /** * @brief Detect full waveform peaks diff --git a/src/scene/Scene.cpp b/src/scene/Scene.cpp index f404ef274..7c4cf10f9 100644 --- a/src/scene/Scene.cpp +++ b/src/scene/Scene.cpp @@ -97,14 +97,14 @@ bool Scene::finalizeLoading(bool const safe) { // Store original bounding box (CRS coordinates): this->bbox_crs = AABB::getForPrimitives(primitives); // TODO Rethink : Does this solve the issue ? --- - this->bbox_crs->vertices[0].pos.x -= 1.0; + /*this->bbox_crs->vertices[0].pos.x -= 1.0; this->bbox_crs->vertices[0].pos.y -= 1.0; this->bbox_crs->vertices[0].pos.z -= 1.0; this->bbox_crs->vertices[1].pos.x += 1.0; this->bbox_crs->vertices[1].pos.y += 1.0; this->bbox_crs->vertices[1].pos.z += 1.0; this->bbox_crs->bounds[0] = this->bbox_crs->vertices[0].pos; - this->bbox_crs->bounds[1] = this->bbox_crs->vertices[1].pos; + this->bbox_crs->bounds[1] = this->bbox_crs->vertices[1].pos;*/ // --- TODO Rethink : Does this solve the issue ? glm::dvec3 diff = this->bbox_crs->getMin(); stringstream ss; @@ -126,12 +126,12 @@ bool Scene::finalizeLoading(bool const safe) { // Get new bounding box of translated scene: this->bbox = AABB::getForPrimitives(primitives); // TODO Rethink : Does this solve the issue ? --- - this->bbox->vertices[0].pos.x -= 1.0; - this->bbox->vertices[0].pos.y -= 1.0; - this->bbox->vertices[0].pos.z -= 1.0; - this->bbox->vertices[1].pos.x += 1.0; - this->bbox->vertices[1].pos.y += 1.0; - this->bbox->vertices[1].pos.z += 1.0; + this->bbox->vertices[0].pos.x -= 0.01; + //this->bbox->vertices[0].pos.y -= 1.0; + //this->bbox->vertices[0].pos.z -= 1.0; + this->bbox->vertices[1].pos.x += 0.01; + //this->bbox->vertices[1].pos.y += 1.0; + //this->bbox->vertices[1].pos.z += 1.0; this->bbox->bounds[0] = this->bbox->vertices[0].pos; this->bbox->bounds[1] = this->bbox->vertices[1].pos; // --- TODO Rethink : Does this solve the issue ? @@ -196,14 +196,7 @@ Scene::getIntersection( bool const groundOnly ) const { vector tMinMax = bbox->getRayIntersection(rayOrigin, rayDir); -#ifdef DATA_ANALYTICS - std::vector subraySimRecord_fake(24, 0); // Not really recorded - return getIntersection( - tMinMax, rayOrigin, rayDir, groundOnly, subraySimRecord_fake - ); -#else return getIntersection(tMinMax, rayOrigin, rayDir, groundOnly); -#endif } std::shared_ptr Scene::getIntersection( @@ -211,10 +204,6 @@ std::shared_ptr Scene::getIntersection( glm::dvec3 const &rayOrigin, glm::dvec3 const &rayDir, bool const groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray -#endif ) const{ if (tMinMax.empty()) { logging::DEBUG("tMinMax is empty"); @@ -225,10 +214,6 @@ std::shared_ptr Scene::getIntersection( } return shared_ptr(raycaster->search( rayOrigin, rayDir, tMinMax[0], tMinMax[1], groundOnly -#ifdef DATA_ANALYTICS - ,subraySimRecord, - isSubray -#endif )); } diff --git a/src/scene/Scene.h b/src/scene/Scene.h index 2481cdb34..99f7afb82 100644 --- a/src/scene/Scene.h +++ b/src/scene/Scene.h @@ -217,10 +217,6 @@ class Scene : public Asset { glm::dvec3 const &rayOrigin, glm::dvec3 const &rayDir, bool const groundOnly -#ifdef DATA_ANALYTICS - ,std::vector &subraySimRecord, - bool const isSubray=false -#endif ) const ; /** * @brief Obtain all intersections between the ray and the scene, if any From 7cd08466893be69299508856b9a975eba8067a30 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 28 Sep 2023 19:16:11 +0200 Subject: [PATCH 10/17] Data analytics supports now level 1 and level 2 --- src/dataanalytics/HDA_GlobalVars.cpp | 2 +- src/dataanalytics/HDA_GlobalVars.h | 2 +- src/dataanalytics/HDA_GlobalVarsReporter.h | 2 +- src/main/Main.cpp | 2 +- src/main/helios_version.cpp | 2 +- src/scanner/BuddingScanningPulseProcess.cpp | 12 ++-- src/scanner/BuddingScanningPulseProcess.h | 8 ++- src/scanner/MultiScanner.cpp | 10 +-- src/scanner/MultiScanner.h | 6 +- src/scanner/Scanner.cpp | 4 +- src/scanner/Scanner.h | 6 +- src/scanner/ScanningDevice.cpp | 18 +++--- src/scanner/ScanningDevice.h | 8 +-- src/scanner/SingleScanner.cpp | 10 +-- src/scanner/SingleScanner.h | 6 +- src/scanner/WarehouseScanningPulseProcess.cpp | 12 ++-- src/scanner/WarehouseScanningPulseProcess.h | 10 +-- .../detector/AbstractPulseRunnable.cpp | 4 +- src/scanner/detector/AbstractPulseRunnable.h | 4 +- .../detector/FullWaveformPulseRunnable.cpp | 64 +++++++++---------- .../detector/FullWaveformPulseRunnable.h | 14 ++-- src/scanner/detector/PulseTask.h | 4 +- src/scanner/detector/PulseTaskDropper.h | 10 +-- src/scanner/detector/PulseThreadPool.h | 28 ++++---- .../detector/PulseThreadPoolInterface.h | 8 +-- .../detector/PulseWarehouseThreadPool.h | 20 +++--- src/scene/Scene.cpp | 4 +- 27 files changed, 144 insertions(+), 136 deletions(-) diff --git a/src/dataanalytics/HDA_GlobalVars.cpp b/src/dataanalytics/HDA_GlobalVars.cpp index 695753ed3..32534f72e 100644 --- a/src/dataanalytics/HDA_GlobalVars.cpp +++ b/src/dataanalytics/HDA_GlobalVars.cpp @@ -1,4 +1,4 @@ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include namespace helios { namespace analytics{ diff --git a/src/dataanalytics/HDA_GlobalVars.h b/src/dataanalytics/HDA_GlobalVars.h index 248f904ad..88c5382ef 100644 --- a/src/dataanalytics/HDA_GlobalVars.h +++ b/src/dataanalytics/HDA_GlobalVars.h @@ -1,4 +1,4 @@ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 #pragma once #include #include diff --git a/src/dataanalytics/HDA_GlobalVarsReporter.h b/src/dataanalytics/HDA_GlobalVarsReporter.h index 35e4034fa..467a52223 100644 --- a/src/dataanalytics/HDA_GlobalVarsReporter.h +++ b/src/dataanalytics/HDA_GlobalVarsReporter.h @@ -1,4 +1,4 @@ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #pragma once #include #include diff --git a/src/main/Main.cpp b/src/main/Main.cpp index ceeb82479..9e73d4289 100644 --- a/src/main/Main.cpp +++ b/src/main/Main.cpp @@ -166,7 +166,7 @@ int main(int argc, char** argv) { ); } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 helios::analytics::HDA_GlobalVarsReporter reporter( helios::analytics::HDA_GV ); diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index e8e4a5cc4..d739af54a 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "28bb2e3c"; +const char * HELIOS_GIT_HASH = "b8094ff9"; const char * getHeliosVersion(){ return HELIOS_VERSION; diff --git a/src/scanner/BuddingScanningPulseProcess.cpp b/src/scanner/BuddingScanningPulseProcess.cpp index 56a9ecfd5..4df3fc589 100644 --- a/src/scanner/BuddingScanningPulseProcess.cpp +++ b/src/scanner/BuddingScanningPulseProcess.cpp @@ -10,7 +10,7 @@ BuddingScanningPulseProcess::BuddingScanningPulseProcess( RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) : @@ -20,7 +20,7 @@ BuddingScanningPulseProcess::BuddingScanningPulseProcess( randGen1(randGen1), randGen2(randGen2), intersectionHandlingNoiseSource(intersectionHandlingNoiseSource) -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder(pulseRecorder) #endif { @@ -57,7 +57,7 @@ void BuddingScanningPulseProcess::onLegComplete(){ randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -88,7 +88,7 @@ void BuddingScanningPulseProcess::handlePulseComputationSequential( randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -144,7 +144,7 @@ void BuddingScanningPulseProcess::handlePulseComputationParallelDynamic( randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -192,7 +192,7 @@ void BuddingScanningPulseProcess::handlePulseComputationParallelStatic( randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); diff --git a/src/scanner/BuddingScanningPulseProcess.h b/src/scanner/BuddingScanningPulseProcess.h index bf1a3e216..f4f20520b 100644 --- a/src/scanner/BuddingScanningPulseProcess.h +++ b/src/scanner/BuddingScanningPulseProcess.h @@ -17,14 +17,16 @@ class BuddingScanningPulseProcess : public ScanningPulseProcess { #ifdef DATA_ANALYTICS public: +#else + protected: +#endif +#if DATA_ANALYTICS >= 2 /** * @brief The helios::analytics::PulseRecorder to be used to handle the * records representing the computed pulse tasks. * @see helios::analytics::PulseRecorder */ std::shared_ptr pulseRecorder; -#else -protected: #endif // *** ATTRIBUTES *** // // ******************** // @@ -115,7 +117,7 @@ class BuddingScanningPulseProcess : public ScanningPulseProcess { RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ); diff --git a/src/scanner/MultiScanner.cpp b/src/scanner/MultiScanner.cpp index db051cbd4..36df1e1b1 100644 --- a/src/scanner/MultiScanner.cpp +++ b/src/scanner/MultiScanner.cpp @@ -166,7 +166,7 @@ void MultiScanner::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -176,7 +176,7 @@ void MultiScanner::computeSubrays( std::map &reflections, vector &intersects, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ){ @@ -186,7 +186,7 @@ void MultiScanner::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -222,7 +222,7 @@ double MultiScanner::calcIntensity( double const targetArea, double const radius, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords #endif ) const{ @@ -232,7 +232,7 @@ double MultiScanner::calcIntensity( mat, targetArea, radius -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords #endif ); diff --git a/src/scanner/MultiScanner.h b/src/scanner/MultiScanner.h index e4a4edac4..59eabcaef 100644 --- a/src/scanner/MultiScanner.h +++ b/src/scanner/MultiScanner.h @@ -165,7 +165,7 @@ class MultiScanner : public Scanner{ NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -175,7 +175,7 @@ class MultiScanner : public Scanner{ std::map &reflections, vector &intersects, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) override; @@ -203,7 +203,7 @@ class MultiScanner : public Scanner{ double const targetArea, double const radius, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords #endif ) const override; diff --git a/src/scanner/Scanner.cpp b/src/scanner/Scanner.cpp index a3fd1fd31..aba242ff4 100644 --- a/src/scanner/Scanner.cpp +++ b/src/scanner/Scanner.cpp @@ -403,7 +403,7 @@ void Scanner::buildScanningPulseProcess( *randGen1, *randGen2, *intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pool->getPulseRecorder() #endif ) @@ -418,7 +418,7 @@ void Scanner::buildScanningPulseProcess( *randGen1, *randGen2, *intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pool->getPulseRecorder() #endif ) diff --git a/src/scanner/Scanner.h b/src/scanner/Scanner.h index e8bbc5db3..b8f1a1abc 100644 --- a/src/scanner/Scanner.h +++ b/src/scanner/Scanner.h @@ -450,7 +450,7 @@ class Scanner : public Asset { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -460,7 +460,7 @@ class Scanner : public Asset { std::map &reflections, vector &intersects, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) = 0; @@ -506,7 +506,7 @@ class Scanner : public Asset { double const targetArea, double const radius, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords #endif ) const = 0; diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index 16548410b..0454c0428 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -3,7 +3,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using namespace helios::analytics; #endif @@ -226,7 +226,7 @@ void ScanningDevice::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -235,11 +235,11 @@ void ScanningDevice::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, std::vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 ,std::shared_ptr pulseRecorder #endif ){ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 bool subrayHit; #endif @@ -266,7 +266,7 @@ void ScanningDevice::computeSubrays( // # Loop over sub-rays along the circle for (int circleStep = 0; circleStep < circleSteps; circleStep++){ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 std::vector subraySimRecord( 17, std::numeric_limits::quiet_NaN() ); @@ -280,12 +280,12 @@ void ScanningDevice::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 ,subrayHit, subraySimRecord #endif ); -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 HDA_GV.incrementGeneratedSubraysCount(); subraySimRecord[0] = (double) subrayHit; subraySimRecord[1] = (double) radiusStep; @@ -355,7 +355,7 @@ double ScanningDevice::calcIntensity( Material const &mat, double const targetArea, double const radius -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >=2 ,std::vector> &calcIntensityRecords #endif ) const { @@ -402,7 +402,7 @@ double ScanningDevice::calcIntensity( atmosphericExtinction, sigma ) * 1000000000.0; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 std::vector calcIntensityRecord( 11, std::numeric_limits::quiet_NaN() ); diff --git a/src/scanner/ScanningDevice.h b/src/scanner/ScanningDevice.h index 11111ce37..e6a6a4a0a 100644 --- a/src/scanner/ScanningDevice.h +++ b/src/scanner/ScanningDevice.h @@ -11,7 +11,7 @@ class AbstractDetector; #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using helios::analytics::HDA_PulseRecorder; #endif @@ -308,7 +308,7 @@ class ScanningDevice : public Asset { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -317,7 +317,7 @@ class ScanningDevice : public Asset { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, std::vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ); @@ -388,7 +388,7 @@ class ScanningDevice : public Asset { Material const &mat, double const targetArea, double const radius -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords #endif ) const; diff --git a/src/scanner/SingleScanner.cpp b/src/scanner/SingleScanner.cpp index 72d9f3b8e..860b5c7ae 100644 --- a/src/scanner/SingleScanner.cpp +++ b/src/scanner/SingleScanner.cpp @@ -202,7 +202,7 @@ void SingleScanner::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -212,7 +212,7 @@ void SingleScanner::computeSubrays( std::map &reflections, vector &intersects, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ){ @@ -222,7 +222,7 @@ void SingleScanner::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -258,7 +258,7 @@ double SingleScanner::calcIntensity( double const targetArea, double const radius, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords #endif ) const { @@ -268,7 +268,7 @@ double SingleScanner::calcIntensity( mat, targetArea, radius -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords #endif ); diff --git a/src/scanner/SingleScanner.h b/src/scanner/SingleScanner.h index 1f7134053..dd9256eff 100644 --- a/src/scanner/SingleScanner.h +++ b/src/scanner/SingleScanner.h @@ -138,7 +138,7 @@ class SingleScanner : public Scanner{ NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -148,7 +148,7 @@ class SingleScanner : public Scanner{ std::map &reflections, vector &intersects, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) override; @@ -176,7 +176,7 @@ class SingleScanner : public Scanner{ double const targetArea, double const radius, size_t const idx -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords #endif ) const override; diff --git a/src/scanner/WarehouseScanningPulseProcess.cpp b/src/scanner/WarehouseScanningPulseProcess.cpp index 458bba1fe..a27e0b949 100644 --- a/src/scanner/WarehouseScanningPulseProcess.cpp +++ b/src/scanner/WarehouseScanningPulseProcess.cpp @@ -11,7 +11,7 @@ WarehouseScanningPulseProcess::WarehouseScanningPulseProcess( RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) : @@ -21,7 +21,7 @@ WarehouseScanningPulseProcess::WarehouseScanningPulseProcess( randGen1(randGen1), randGen2(randGen2), intersectionHandlingNoiseSource(intersectionHandlingNoiseSource) -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder(pulseRecorder) #endif { @@ -49,7 +49,7 @@ void WarehouseScanningPulseProcess::onLegComplete(){ randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -59,7 +59,7 @@ void WarehouseScanningPulseProcess::onLegComplete(){ while( (task=pool.get()) != nullptr){ (*task)( apMatrix, randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -84,7 +84,7 @@ void WarehouseScanningPulseProcess::handlePulseComputationSequential( randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -110,7 +110,7 @@ void WarehouseScanningPulseProcess::handlePulseComputationParallel( randGen1, randGen2, intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); diff --git a/src/scanner/WarehouseScanningPulseProcess.h b/src/scanner/WarehouseScanningPulseProcess.h index 0723504b2..d30b4c18f 100644 --- a/src/scanner/WarehouseScanningPulseProcess.h +++ b/src/scanner/WarehouseScanningPulseProcess.h @@ -3,7 +3,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include #endif @@ -21,14 +21,16 @@ class WarehouseScanningPulseProcess : public ScanningPulseProcess { #ifdef DATA_ANALYTICS public: +#else +protected: +#endif +#if DATA_ANALYTICS >= 2 /** * @brief The helios::analytics::PulseRecorder to be used to handle the * records representing the computed pulse tasks. * @see helios::analytics::PulseRecorder */ std::shared_ptr pulseRecorder; -#else -protected: #endif // *** ATTRIBUTES *** // // ******************** // @@ -91,7 +93,7 @@ class WarehouseScanningPulseProcess : public ScanningPulseProcess { RandomnessGenerator &randGen1, RandomnessGenerator &randGen2, UniformNoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ); diff --git a/src/scanner/detector/AbstractPulseRunnable.cpp b/src/scanner/detector/AbstractPulseRunnable.cpp index 583a7fa3c..278504588 100644 --- a/src/scanner/detector/AbstractPulseRunnable.cpp +++ b/src/scanner/detector/AbstractPulseRunnable.cpp @@ -62,7 +62,7 @@ void AbstractPulseRunnable::capturePoint( std::mutex *allMeasurementsMutex, std::vector *cycleMeasurements, std::mutex *cycleMeasurementsMutex -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector &calcIntensityRecord, std::shared_ptr pulseRecorder #endif @@ -81,7 +81,7 @@ void AbstractPulseRunnable::capturePoint( // TODO Pending : Is it necessary to compute position again? Notice it is // known from ray intersection point at FullWaveformPulseRunnable m.position = m.beamOrigin + m.beamDirection * m.distance; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 calcIntensityRecord[10] = 1; pulseRecorder->recordIntensityCalculation(calcIntensityRecord); #endif diff --git a/src/scanner/detector/AbstractPulseRunnable.h b/src/scanner/detector/AbstractPulseRunnable.h index 8ff5e41f6..91052c094 100644 --- a/src/scanner/detector/AbstractPulseRunnable.h +++ b/src/scanner/detector/AbstractPulseRunnable.h @@ -7,7 +7,7 @@ class Measurement; #include "LasSpecification.h" class Scanner; #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include #endif @@ -93,7 +93,7 @@ class AbstractPulseRunnable : public PulseTask{ std::mutex *allMeasurementsMutex, std::vector *cycleMeasurements, std::mutex *cycleMeasurementsMutex -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector &calcIntensityRecord, std::shared_ptr pulseRecorder #endif diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index 0bcedc8dd..b40df12ee 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -15,7 +15,7 @@ #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using helios::analytics::HDA_GV; @@ -37,7 +37,7 @@ void FullWaveformPulseRunnable::operator()( RandomnessGenerator &randGen, RandomnessGenerator &randGen2, NoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ){ @@ -71,7 +71,7 @@ void FullWaveformPulseRunnable::operator()( beamDir );*/ // --- TODO Remove -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 HDA_GV.incrementGeneratedRaysBeforeEarlyAbortCount(); #endif if (tMinMax.empty() || (tMinMax[0] < 0 && tMinMax[1] < 0)) { @@ -79,14 +79,14 @@ void FullWaveformPulseRunnable::operator()( scanner->setLastPulseWasHit(false, pulse.getDeviceIndex()); return; } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 HDA_GV.incrementGeneratedRaysAfterEarlyAbortCount(); #endif // Ray casting (find intersections) map reflections; vector intersects; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 std::vector> calcIntensityRecords; #endif computeSubrays( @@ -94,7 +94,7 @@ void FullWaveformPulseRunnable::operator()( intersectionHandlingNoiseSource, reflections, intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords, pulseRecorder #endif @@ -108,7 +108,7 @@ void FullWaveformPulseRunnable::operator()( beamDir, reflections, intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords, pulseRecorder #endif @@ -131,7 +131,7 @@ void FullWaveformPulseRunnable::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -146,7 +146,7 @@ void FullWaveformPulseRunnable::computeSubrays( NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord #endif @@ -160,7 +160,7 @@ void FullWaveformPulseRunnable::computeSubrays( intersectionHandlingNoiseSource, reflections, intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,subrayHit, subraySimRecord, calcIntensityRecords @@ -172,7 +172,7 @@ void FullWaveformPulseRunnable::computeSubrays( reflections, intersects, pulse.getDeviceIndex() -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -187,13 +187,13 @@ void FullWaveformPulseRunnable::handleSubray( NoiseSource &intersectionHandlingNoiseSource, map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord, std::vector> &calcIntensityRecords #endif ){ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 subrayHit = false; #endif // Rotate around the circle: @@ -203,7 +203,7 @@ void FullWaveformPulseRunnable::handleSubray( glm::dvec3 subrayDirection = pulse.getAttitude().applyTo(r2) .applyTo(Directions::forward); -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 glm::dvec3 rayDirection = pulse.computeDirection(); subraySimRecord[5] = glm::l2Norm(rayDirection); // Ray norm subraySimRecord[6] = glm::l2Norm(subrayDirection); // Subray norm @@ -234,7 +234,7 @@ void FullWaveformPulseRunnable::handleSubray( ); if (intersect != nullptr && intersect->prim != nullptr) { -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 HDA_GV.incrementSubrayIntersectionCount(); subrayHit = true; #endif @@ -273,7 +273,7 @@ void FullWaveformPulseRunnable::handleSubray( ); } else { // Lighting-based intensity computation -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 HDA_GV.incrementIntensityComputationsCount(); #endif intensity = scanner->calcIntensity( @@ -283,7 +283,7 @@ void FullWaveformPulseRunnable::handleSubray( targetArea, radius, pulse.getDeviceIndex() -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 , calcIntensityRecords #endif ); @@ -330,7 +330,7 @@ void FullWaveformPulseRunnable::handleSubray( ); intersects.push_back(*intersect); } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 std::vector &calcIntensityRecord = calcIntensityRecords.back(); calcIntensityRecord[0] = intersect->point.x; @@ -342,7 +342,7 @@ void FullWaveformPulseRunnable::handleSubray( #endif } } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 if(subrayHit) HDA_GV.incrementIntersectiveSubraysCount(); else HDA_GV.incrementNonIntersectiveSubraysCount(); #endif @@ -355,7 +355,7 @@ void FullWaveformPulseRunnable::digestIntersections( glm::dvec3 &beamDir, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -367,7 +367,7 @@ void FullWaveformPulseRunnable::digestIntersections( // If nothing was hit, get out of here if (maxHitDist_m < 0) { scanner->setLastPulseWasHit(false, pulse.getDeviceIndex()); -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 if(!calcIntensityRecords.empty()) { pulseRecorder->recordIntensityCalculation(calcIntensityRecords); } @@ -388,7 +388,7 @@ void FullWaveformPulseRunnable::digestIntersections( peakIntensityIndex, numFullwaveBins )){ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 pulseRecorder->recordIntensityCalculation(calcIntensityRecords); #endif return; @@ -419,7 +419,7 @@ void FullWaveformPulseRunnable::digestIntersections( numFullwaveBins, peakIntensityIndex, minHitTime_ns -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords, pulseRecorder #endif @@ -435,7 +435,7 @@ void FullWaveformPulseRunnable::digestIntersections( maxHitTime_ns, randGen, randGen2 -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords, pulseRecorder #endif @@ -532,7 +532,7 @@ void FullWaveformPulseRunnable::digestFullWaveform( int const numFullwaveBins, int const peakIntensityIndex, double const minHitTime_ns -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -551,7 +551,7 @@ void FullWaveformPulseRunnable::digestFullWaveform( double echo_width = 0.0; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 std::unordered_set capturedIndices; #endif @@ -632,14 +632,14 @@ void FullWaveformPulseRunnable::digestFullWaveform( pointsMeasurement.push_back(tmp); ++numReturns; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 capturedIndices.insert(closestIntersectionIdx); #endif // Check if maximum number of returns per pulse has been reached if(!scanner->checkMaxNOR(numReturns, devIdx)) break; } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 // Record all non captured points and remove them from records size_t const numRecords = calcIntensityRecords.size(); size_t nonCapturedCount = 0; @@ -702,14 +702,14 @@ void FullWaveformPulseRunnable::exportOutput( double const maxHitTime_ns, RandomnessGenerator &randGen, RandomnessGenerator &randGen2 -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif ){ // ############ END Extract points from waveform data ################ if (numReturns > 0) { -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 size_t i = 0; #endif for (Measurement & pm : pointsMeasurement) { @@ -721,12 +721,12 @@ void FullWaveformPulseRunnable::exportOutput( scanner->allMeasurementsMutex.get(), scanner->cycleMeasurements.get(), scanner->cycleMeasurementsMutex.get() -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,calcIntensityRecords[i], pulseRecorder #endif ); -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ++i; #endif } diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index 00d13d62b..f027bfe0b 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -9,7 +9,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include #endif @@ -87,7 +87,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -112,7 +112,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,bool &subrayHit, std::vector &subraySimRecord, std::vector> &calcIntensityRecords @@ -139,7 +139,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { glm::dvec3 &beamDir, std::map &reflections, vector &intersects -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -214,7 +214,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { int const numFullwaveBins, int const peakIntensityIndex, double const minHitTime_ns -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -254,7 +254,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { double const maxHitTime_ns, RandomnessGenerator &randGen, RandomnessGenerator &randGen2 -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::vector> &calcIntensityRecords, std::shared_ptr pulseRecorder #endif @@ -338,7 +338,7 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { RandomnessGenerator &randGen, RandomnessGenerator &randGen2, NoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) override; diff --git a/src/scanner/detector/PulseTask.h b/src/scanner/detector/PulseTask.h index 5a935c5c3..23762d215 100644 --- a/src/scanner/detector/PulseTask.h +++ b/src/scanner/detector/PulseTask.h @@ -2,7 +2,7 @@ #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using helios::analytics::HDA_PulseRecorder; #endif @@ -37,7 +37,7 @@ class PulseTask{ RandomnessGenerator &randGen, RandomnessGenerator &randGen2, NoiseSource &intersectionHandlingNoiseSource -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr pulseRecorder #endif ) = 0; diff --git a/src/scanner/detector/PulseTaskDropper.h b/src/scanner/detector/PulseTaskDropper.h index c2199d621..444bbb0ff 100644 --- a/src/scanner/detector/PulseTaskDropper.h +++ b/src/scanner/detector/PulseTaskDropper.h @@ -6,7 +6,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using helios::analytics::HDA_PulseRecorder; #endif @@ -28,7 +28,7 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >{ @@ -56,7 +56,7 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >(maxTasks, delta1, initDelta1, delta2, lastSign) @@ -72,7 +72,7 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >::drop; // To avoid overriding hides drop overloads @@ -83,7 +83,7 @@ class PulseTaskDropper : public BuddingTaskDropper< RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >::tryDrop; // To avoid override hides tryDrop overloads diff --git a/src/scanner/detector/PulseThreadPool.h b/src/scanner/detector/PulseThreadPool.h index 0e61c4b70..979aa3265 100644 --- a/src/scanner/detector/PulseThreadPool.h +++ b/src/scanner/detector/PulseThreadPool.h @@ -5,7 +5,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include #endif @@ -20,7 +20,7 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >, @@ -28,9 +28,11 @@ class PulseThreadPool : { #ifdef DATA_ANALYTICS public: - std::shared_ptr pulseRecorder; #else protected: +#endif +#if DATA_ANALYTICS >= 2 + std::shared_ptr pulseRecorder; #endif // *** ATTRIBUTES *** // // ******************** // @@ -93,14 +95,14 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >(_pool_size), dynamic(dynamic) { // Allocate -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 pulseRecorder = std::make_shared( "helios_pulse_records" ); @@ -125,7 +127,7 @@ class PulseThreadPool : } virtual ~PulseThreadPool(){ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 // Flush and close pulse recorder this->pulseRecorder->closeBuffers(); #endif @@ -149,7 +151,7 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif > &dropper @@ -167,7 +169,7 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif > &dropper @@ -183,13 +185,13 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif >::join(); } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 /** * @see PulseThreadPoolInterface::getPulseRecorder */ @@ -212,7 +214,7 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif )> &task, @@ -223,7 +225,7 @@ class PulseThreadPool : randGens[resourceIdx], randGens2[resourceIdx], intersectionHandlingNoiseSources[resourceIdx] -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); @@ -239,7 +241,7 @@ class PulseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif )> &task, diff --git a/src/scanner/detector/PulseThreadPoolInterface.h b/src/scanner/detector/PulseThreadPoolInterface.h index 5b2a7a457..a42148baa 100644 --- a/src/scanner/detector/PulseThreadPoolInterface.h +++ b/src/scanner/detector/PulseThreadPoolInterface.h @@ -4,7 +4,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using helios::analytics::HDA_PulseRecorder; #endif @@ -42,7 +42,7 @@ class PulseThreadPoolInterface{ RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif > &dropper @@ -67,7 +67,7 @@ class PulseThreadPoolInterface{ RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif > &dropper @@ -77,7 +77,7 @@ class PulseThreadPoolInterface{ */ virtual void join() = 0; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 /** * @brief Obtain the pointer to the pulse recorder being used by the * pulse thread pool. diff --git a/src/scanner/detector/PulseWarehouseThreadPool.h b/src/scanner/detector/PulseWarehouseThreadPool.h index ee278eaa9..b72803521 100644 --- a/src/scanner/detector/PulseWarehouseThreadPool.h +++ b/src/scanner/detector/PulseWarehouseThreadPool.h @@ -5,7 +5,7 @@ #include #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include #endif @@ -26,14 +26,16 @@ class PulseWarehouseThreadPool : { #ifdef DATA_ANALYTICS public: +#else +protected: +#endif +#if DATA_ANALYTICS >= 2 /** * @brief The helios::analytics::PulseRecorder to be used to handle the * records representing the computed pulse tasks. * @see helios::analytics::PulseRecorder */ std::shared_ptr pulseRecorder; -#else -protected: #endif // *** ATTRIBUTES *** // // ******************** // @@ -79,7 +81,7 @@ class PulseWarehouseThreadPool : randGens2 = new RandomnessGenerator[this->pool_size]; intersectionHandlingNoiseSources = new UniformNoiseSource[this->pool_size]; -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 pulseRecorder = std::make_shared( "helios_pulse_records" ); @@ -99,7 +101,7 @@ class PulseWarehouseThreadPool : } virtual ~PulseWarehouseThreadPool(){ -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 // Flush and close pulse recorder this->pulseRecorder->closeBuffers(); #endif @@ -123,7 +125,7 @@ class PulseWarehouseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif > &dropper @@ -144,7 +146,7 @@ class PulseWarehouseThreadPool : RandomnessGenerator&, RandomnessGenerator&, NoiseSource& -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,std::shared_ptr #endif > &dropper @@ -159,7 +161,7 @@ class PulseWarehouseThreadPool : inline void join() override{ WarehouseThreadPool::join(); } -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 /** * @see PulseThreadPoolInterface::getPulseRecorder */ @@ -186,7 +188,7 @@ class PulseWarehouseThreadPool : randGens[tid], randGens2[tid], intersectionHandlingNoiseSources[tid] -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 ,pulseRecorder #endif ); diff --git a/src/scene/Scene.cpp b/src/scene/Scene.cpp index 7c4cf10f9..477c5bc00 100644 --- a/src/scene/Scene.cpp +++ b/src/scene/Scene.cpp @@ -23,7 +23,7 @@ using namespace glm; #include #include -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 #include using helios::analytics::HDA_GV; #endif @@ -207,7 +207,7 @@ std::shared_ptr Scene::getIntersection( ) const{ if (tMinMax.empty()) { logging::DEBUG("tMinMax is empty"); -#ifdef DATA_ANALYTICS +#if DATA_ANALYTICS >= 2 HDA_GV.incrementNonIntersectiveSubraysDueToNullTimeCount(); #endif return nullptr; From 3c759e63fd2bca28eeab6e4e7770f583691866ba Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 28 Sep 2023 19:20:39 +0200 Subject: [PATCH 11/17] Documented HDA_GlobalVars --- src/dataanalytics/HDA_GlobalVars.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/dataanalytics/HDA_GlobalVars.h b/src/dataanalytics/HDA_GlobalVars.h index 88c5382ef..20912982e 100644 --- a/src/dataanalytics/HDA_GlobalVars.h +++ b/src/dataanalytics/HDA_GlobalVars.h @@ -9,7 +9,19 @@ namespace helios { namespace analytics{ // *********************** // extern class HDA_GlobalVars HDA_GV; -// TODO Rethink : Document +/** + * @author Alberto M. Esmoris Pena + * @version 1.0 + * + * @brief Class to handle global variables together with methods for safe + * readings and updates. + * + * The HDA_GlobalVars class provides a series of variables and corresponding + * methods for safe operations. For example, variables that must be + * accessed through parallel threads are handled with a mutex such that, as + * long as the proper methods are used, read and write operations are + * thread safe. + */ class HDA_GlobalVars{ public: // *** ATTRIBUTES *** // From 8e49189eee2e0abeee6c1a16cc91b9aff184915d Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 28 Sep 2023 19:21:03 +0200 Subject: [PATCH 12/17] Updated CMake --- cmake/CMakeBuildExec.cmake | 2 +- cmake/CMakeDebugFlags.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/CMakeBuildExec.cmake b/cmake/CMakeBuildExec.cmake index 05f71f3c0..e40146d8d 100644 --- a/cmake/CMakeBuildExec.cmake +++ b/cmake/CMakeBuildExec.cmake @@ -1,6 +1,6 @@ # --- B U I L D I N G --- # # ------------------------- # -ADD_EXECUTABLE(helios ${sources} AppIcon.rc) +ADD_EXECUTABLE(helios ${sources} AppIcon.rc ../src/dataanalytics/HDA_PulseRecorder.h ../src/dataanalytics/HDA_PulseRecorder.cpp ../src/dataanalytics/HDA_Recorder.h ../src/dataanalytics/HDA_Recorder.cpp ../src/dataanalytics/HDA_OfstreamWrapper.h ../src/dataanalytics/HDA_GlobalVars.h ../src/dataanalytics/HDA_GlobalVars.cpp ../src/dataanalytics/HDA_GlobalVarsReporter.h) # HANDLE PYTHON BINDING if(PYTHON_BINDING) diff --git a/cmake/CMakeDebugFlags.cmake b/cmake/CMakeDebugFlags.cmake index d5e8fa220..42022a620 100644 --- a/cmake/CMakeDebugFlags.cmake +++ b/cmake/CMakeDebugFlags.cmake @@ -7,5 +7,5 @@ endif() #-DDATA_ANALYTICS=1 to enable if(${DATA_ANALYTICS}) - add_definitions(-DDATA_ANALYTICS) + add_compile_definitions(DATA_ANALYTICS=${DATA_ANALYTICS}) endif() \ No newline at end of file From ccc0d2ccec07503c6f448cc80070cd595aab0d4f Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 28 Sep 2023 19:23:03 +0200 Subject: [PATCH 13/17] Documented HDA_GlobalVarsReporter --- src/dataanalytics/HDA_GlobalVarsReporter.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dataanalytics/HDA_GlobalVarsReporter.h b/src/dataanalytics/HDA_GlobalVarsReporter.h index 467a52223..d25a72230 100644 --- a/src/dataanalytics/HDA_GlobalVarsReporter.h +++ b/src/dataanalytics/HDA_GlobalVarsReporter.h @@ -8,7 +8,14 @@ namespace helios { namespace analytics{ -// TODO Rethink : Document +/** + * @author Alberto M. Esmoris Pena + * @version 1.0 + * + * @brief Class to handle reports related to global variables. + * + * @see helios::analytics::HDA_GlobalVars + */ class HDA_GlobalVarsReporter{ protected: // *** ATTRIBUTES *** // From 33f9a0155d47d98192d6b1f81ca4eb3c11de7282 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Fri, 29 Sep 2023 16:31:50 +0200 Subject: [PATCH 14/17] Star spikes pattern solved with a not hardcoded number (subray tminmax is now properly computed. --- src/main/helios_version.cpp | 2 +- src/scanner/MultiScanner.cpp | 3 -- src/scanner/MultiScanner.h | 2 -- src/scanner/Scanner.h | 4 --- src/scanner/ScanningDevice.cpp | 6 +--- src/scanner/ScanningDevice.h | 2 -- src/scanner/SingleScanner.cpp | 3 -- src/scanner/SingleScanner.h | 2 -- .../detector/FullWaveformPulseRunnable.cpp | 33 +++++-------------- .../detector/FullWaveformPulseRunnable.h | 24 ++++++++++++-- src/scene/Scene.cpp | 20 ----------- 11 files changed, 32 insertions(+), 69 deletions(-) diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index d739af54a..f90c492c1 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "b8094ff9"; +const char * HELIOS_GIT_HASH = "ccc0d2cc"; const char * getHeliosVersion(){ return HELIOS_VERSION; diff --git a/src/scanner/MultiScanner.cpp b/src/scanner/MultiScanner.cpp index 36df1e1b1..b1cb5ed4f 100644 --- a/src/scanner/MultiScanner.cpp +++ b/src/scanner/MultiScanner.cpp @@ -158,7 +158,6 @@ Rotation MultiScanner::calcAbsoluteBeamAttitude(size_t const idx){ } void MultiScanner::computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -171,7 +170,6 @@ void MultiScanner::computeSubrays( std::vector &subraySimRecord #endif )> handleSubray, - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, @@ -182,7 +180,6 @@ void MultiScanner::computeSubrays( ){ scanDevs[idx].computeSubrays( handleSubray, - tMinMax, intersectionHandlingNoiseSource, reflections, intersects diff --git a/src/scanner/MultiScanner.h b/src/scanner/MultiScanner.h index 59eabcaef..b96b731db 100644 --- a/src/scanner/MultiScanner.h +++ b/src/scanner/MultiScanner.h @@ -157,7 +157,6 @@ class MultiScanner : public Scanner{ */ void computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -170,7 +169,6 @@ class MultiScanner : public Scanner{ std::vector &subraySimRecord #endif )> handleSubray, - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, diff --git a/src/scanner/Scanner.h b/src/scanner/Scanner.h index b8f1a1abc..865fd588b 100644 --- a/src/scanner/Scanner.h +++ b/src/scanner/Scanner.h @@ -429,8 +429,6 @@ class Scanner : public Asset { * @brief Perform ray casting to find intersections * @param[in] handleSubray The function where computed subrays must be * delegated to - * @param[in] tMinMax Minimum and maximum time to intersection with respect - * to the axis aligned bounding box that bounds the scene * @param[out] reflections Where reflections must be stored when a hit is * registered * @param[out] intersects Where intersections must be stored when a hit is @@ -442,7 +440,6 @@ class Scanner : public Asset { */ virtual void computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -455,7 +452,6 @@ class Scanner : public Asset { std::vector &subraySimRecord #endif )> handleSubray, - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, diff --git a/src/scanner/ScanningDevice.cpp b/src/scanner/ScanningDevice.cpp index 0454c0428..6653c37b8 100644 --- a/src/scanner/ScanningDevice.cpp +++ b/src/scanner/ScanningDevice.cpp @@ -218,7 +218,6 @@ Rotation ScanningDevice::calcExactAbsoluteBeamAttitude( void ScanningDevice::computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -231,7 +230,6 @@ void ScanningDevice::computeSubrays( std::vector &subraySimRecord #endif )> handleSubray, - std::vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, std::vector &intersects @@ -251,8 +249,7 @@ void ScanningDevice::computeSubrays( double const subrayDivergenceAngle_rad = radiusStep * radiusStep_rad; // Rotate subbeam into divergence step (towards outer rim of the beam cone): - Rotation r1 = Rotation(Directions::right, subrayDivergenceAngle_rad); // TODO Restore - //Rotation r1 = Rotation(Directions::right, 0.0); // TODO Remove + Rotation r1 = Rotation(Directions::right, subrayDivergenceAngle_rad); // Calculate circle step width: int circleSteps = (int)(PI_2 * radiusStep); @@ -272,7 +269,6 @@ void ScanningDevice::computeSubrays( ); #endif handleSubray( - tMinMax, circleStep, circleStep_rad, r1, diff --git a/src/scanner/ScanningDevice.h b/src/scanner/ScanningDevice.h index e6a6a4a0a..754727175 100644 --- a/src/scanner/ScanningDevice.h +++ b/src/scanner/ScanningDevice.h @@ -300,7 +300,6 @@ class ScanningDevice : public Asset { */ void computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -313,7 +312,6 @@ class ScanningDevice : public Asset { std::vector &subraySimRecord #endif )> handleSubray, - std::vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, std::vector &intersects diff --git a/src/scanner/SingleScanner.cpp b/src/scanner/SingleScanner.cpp index 860b5c7ae..8b7245d7f 100644 --- a/src/scanner/SingleScanner.cpp +++ b/src/scanner/SingleScanner.cpp @@ -194,7 +194,6 @@ Rotation SingleScanner::calcAbsoluteBeamAttitude(size_t const idx) { } void SingleScanner::computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -207,7 +206,6 @@ void SingleScanner::computeSubrays( std::vector &subraySimRecord #endif )> handleSubray, - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, @@ -218,7 +216,6 @@ void SingleScanner::computeSubrays( ){ scanDev.computeSubrays( handleSubray, - tMinMax, intersectionHandlingNoiseSource, reflections, intersects diff --git a/src/scanner/SingleScanner.h b/src/scanner/SingleScanner.h index dd9256eff..becee3d3a 100644 --- a/src/scanner/SingleScanner.h +++ b/src/scanner/SingleScanner.h @@ -130,7 +130,6 @@ class SingleScanner : public Scanner{ */ void computeSubrays( std::function const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -143,7 +142,6 @@ class SingleScanner : public Scanner{ std::vector &subraySimRecord #endif )> handleSubray, - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects, diff --git a/src/scanner/detector/FullWaveformPulseRunnable.cpp b/src/scanner/detector/FullWaveformPulseRunnable.cpp index b40df12ee..be11e3c12 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.cpp +++ b/src/scanner/detector/FullWaveformPulseRunnable.cpp @@ -52,29 +52,14 @@ void FullWaveformPulseRunnable::operator()( // performance optimization, so we should keep it nevertheless. sbecht 2016-04-24 // Early abort if central axis of the beam does not intersect with the scene: - vector tMinMax = scene.getAABB()->getRayIntersection( + vector const tMinMax = scene.getAABB()->getRayIntersection( pulse.getOriginRef(), beamDir - ); // TODO Restore - // TODO Remove --- - /*std::shared_ptr aabb = std::make_shared(*scene.getAABB()); - aabb->vertices[0].pos.x -= 1.0; - aabb->vertices[0].pos.y -= 1.0; - aabb->vertices[0].pos.z -= 1.0; - aabb->vertices[1].pos.x += 1.0; - aabb->vertices[1].pos.y += 1.0; - aabb->vertices[1].pos.z += 1.0; - aabb->bounds[0] = aabb->vertices[0].pos; - aabb->bounds[1] = aabb->vertices[1].pos; - vector tMinMax = aabb->getRayIntersection( - pulse.getOriginRef(), - beamDir - );*/ - // --- TODO Remove + ); #if DATA_ANALYTICS >= 2 HDA_GV.incrementGeneratedRaysBeforeEarlyAbortCount(); #endif - if (tMinMax.empty() || (tMinMax[0] < 0 && tMinMax[1] < 0)) { + if (checkEarlyAbort(tMinMax)) { logging::DEBUG("Early abort - beam does not intersect with the scene"); scanner->setLastPulseWasHit(false, pulse.getDeviceIndex()); return; @@ -90,7 +75,6 @@ void FullWaveformPulseRunnable::operator()( std::vector> calcIntensityRecords; #endif computeSubrays( - tMinMax, intersectionHandlingNoiseSource, reflections, intersects @@ -127,7 +111,6 @@ void FullWaveformPulseRunnable::initialize(){ ); } void FullWaveformPulseRunnable::computeSubrays( - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects @@ -138,7 +121,6 @@ void FullWaveformPulseRunnable::computeSubrays( ){ scanner->computeSubrays( [&] ( - vector const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -152,7 +134,6 @@ void FullWaveformPulseRunnable::computeSubrays( #endif ) -> void { handleSubray( - _tMinMax, circleStep, circleStep_rad, r1, @@ -167,7 +148,6 @@ void FullWaveformPulseRunnable::computeSubrays( #endif ); }, - tMinMax, intersectionHandlingNoiseSource, reflections, intersects, @@ -179,7 +159,6 @@ void FullWaveformPulseRunnable::computeSubrays( } void FullWaveformPulseRunnable::handleSubray( - vector const &_tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -197,12 +176,15 @@ void FullWaveformPulseRunnable::handleSubray( subrayHit = false; #endif // Rotate around the circle: - vector tMinMax = _tMinMax; Rotation r2 = Rotation(Directions::forward, circleStep_rad * circleStep); r2 = r2.applyTo(r1); glm::dvec3 subrayDirection = pulse.getAttitude().applyTo(r2) .applyTo(Directions::forward); + vector tMinMax = scene.getAABB()->getRayIntersection( + pulse.getOriginRef(), + subrayDirection + ); #if DATA_ANALYTICS >= 2 glm::dvec3 rayDirection = pulse.computeDirection(); subraySimRecord[5] = glm::l2Norm(rayDirection); // Ray norm @@ -221,6 +203,7 @@ void FullWaveformPulseRunnable::handleSubray( subraySimRecord[15] = rayDirection.y; subraySimRecord[16] = rayDirection.z; #endif + if(checkEarlyAbort(tMinMax)) return; glm::dvec3 subrayOrigin(pulse.getOrigin()); bool rayContinues = true; diff --git a/src/scanner/detector/FullWaveformPulseRunnable.h b/src/scanner/detector/FullWaveformPulseRunnable.h index f027bfe0b..3dcba2158 100644 --- a/src/scanner/detector/FullWaveformPulseRunnable.h +++ b/src/scanner/detector/FullWaveformPulseRunnable.h @@ -83,7 +83,6 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { * @see FullWaveformPulseRunnable::handleSubray */ void computeSubrays( - vector const &tMinMax, NoiseSource &intersectionHandlingNoiseSource, std::map &reflections, vector &intersects @@ -104,7 +103,6 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { * @see FullWaveformPulseRunnable::computeSubrays */ void handleSubray( - vector const &tMinMax, int const circleStep, double const circleStep_rad, Rotation &r1, @@ -310,6 +308,28 @@ class FullWaveformPulseRunnable : public AbstractPulseRunnable { RandomnessGenerator &rg2 ); + /** + * @brief Check whether the ray/subray must be aborted or not depending + * on its intersection times. + * + * NOTE that typically the tMinMax vector is expected to come from a + * intersection computation on the minimum axis aligned bounding box + * containing the scene, i.e., the Scene::bbox attribute. + * + * @param tMinMax The first component is the minimum intersection time + * \f$t_*\f$, the second component is the maximum intersection time + * \f$t^*\f$, and no components means no intersection. See + * AABB::getRayIntersection for more details because an early abort check + * is a ray-AABB (Axis-Aligned Bounding-Box) check. + * @return True if the ray fails to intersects with the axis-aligned + * bounding box, False otherwise. + * @see Scene + * @see AABB + */ + inline bool checkEarlyAbort(std::vector const &tMinMax){ + return tMinMax.empty() || (tMinMax[0] < 0 && tMinMax[1] <= 0); + } + public: // *** O P E R A T O R *** // // ************************* // diff --git a/src/scene/Scene.cpp b/src/scene/Scene.cpp index 477c5bc00..f9eee51c5 100644 --- a/src/scene/Scene.cpp +++ b/src/scene/Scene.cpp @@ -96,16 +96,6 @@ bool Scene::finalizeLoading(bool const safe) { // Store original bounding box (CRS coordinates): this->bbox_crs = AABB::getForPrimitives(primitives); - // TODO Rethink : Does this solve the issue ? --- - /*this->bbox_crs->vertices[0].pos.x -= 1.0; - this->bbox_crs->vertices[0].pos.y -= 1.0; - this->bbox_crs->vertices[0].pos.z -= 1.0; - this->bbox_crs->vertices[1].pos.x += 1.0; - this->bbox_crs->vertices[1].pos.y += 1.0; - this->bbox_crs->vertices[1].pos.z += 1.0; - this->bbox_crs->bounds[0] = this->bbox_crs->vertices[0].pos; - this->bbox_crs->bounds[1] = this->bbox_crs->vertices[1].pos;*/ - // --- TODO Rethink : Does this solve the issue ? glm::dvec3 diff = this->bbox_crs->getMin(); stringstream ss; ss << "CRS bounding box (by vertices): " << this->bbox_crs->toString() @@ -125,16 +115,6 @@ bool Scene::finalizeLoading(bool const safe) { // Get new bounding box of translated scene: this->bbox = AABB::getForPrimitives(primitives); - // TODO Rethink : Does this solve the issue ? --- - this->bbox->vertices[0].pos.x -= 0.01; - //this->bbox->vertices[0].pos.y -= 1.0; - //this->bbox->vertices[0].pos.z -= 1.0; - this->bbox->vertices[1].pos.x += 0.01; - //this->bbox->vertices[1].pos.y += 1.0; - //this->bbox->vertices[1].pos.z += 1.0; - this->bbox->bounds[0] = this->bbox->vertices[0].pos; - this->bbox->bounds[1] = this->bbox->vertices[1].pos; - // --- TODO Rethink : Does this solve the issue ? ss << "Actual bounding box (by vertices): " << this->bbox->toString(); logging::INFO(ss.str()); From 5cba90e3c39eee2dac2244ca718b6bfd6edb3eec Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Fri, 29 Sep 2023 17:07:13 +0200 Subject: [PATCH 15/17] CMake update --- cmake/CMakeBuildExec.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/CMakeBuildExec.cmake b/cmake/CMakeBuildExec.cmake index e40146d8d..05f71f3c0 100644 --- a/cmake/CMakeBuildExec.cmake +++ b/cmake/CMakeBuildExec.cmake @@ -1,6 +1,6 @@ # --- B U I L D I N G --- # # ------------------------- # -ADD_EXECUTABLE(helios ${sources} AppIcon.rc ../src/dataanalytics/HDA_PulseRecorder.h ../src/dataanalytics/HDA_PulseRecorder.cpp ../src/dataanalytics/HDA_Recorder.h ../src/dataanalytics/HDA_Recorder.cpp ../src/dataanalytics/HDA_OfstreamWrapper.h ../src/dataanalytics/HDA_GlobalVars.h ../src/dataanalytics/HDA_GlobalVars.cpp ../src/dataanalytics/HDA_GlobalVarsReporter.h) +ADD_EXECUTABLE(helios ${sources} AppIcon.rc) # HANDLE PYTHON BINDING if(PYTHON_BINDING) From 57f8a4701919ebabb9dca37f649552e1579616b2 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 5 Oct 2023 12:04:47 +0200 Subject: [PATCH 16/17] Updating pytests ... --- pytests/test_demo_scenes.py | 4 ++-- pytests/test_gpsStartTimeFlag.py | 6 +++--- pytests/test_pyhelios.py | 4 ++-- src/main/helios_version.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pytests/test_demo_scenes.py b/pytests/test_demo_scenes.py index be9d7542c..d1e72c3f5 100644 --- a/pytests/test_demo_scenes.py +++ b/pytests/test_demo_scenes.py @@ -120,7 +120,7 @@ def test_arbaro_tls_pyh(): def eval_arbaro_tls(dirname): assert (dirname / 'leg000_points.las').exists() - assert abs((dirname / 'leg000_points.las').stat().st_size - 21_656_853) < MAX_DIFFERENCE_BYTES + assert abs((dirname / 'leg000_points.las').stat().st_size - 21_755_791) < MAX_DIFFERENCE_BYTES assert (dirname / 'leg001_points.las').exists() assert abs((dirname / 'leg001_points.las').stat().st_size - 13_908_757) < MAX_DIFFERENCE_BYTES with open(dirname / 'leg000_trajectory.txt', 'r') as f: @@ -231,7 +231,7 @@ def test_interpolated_traj_pyh(): def eval_interpolated_traj(dirname): assert (dirname / 'leg000_points.laz').exists() assert (dirname / 'leg000_trajectory.txt').exists() - assert abs((dirname / 'leg000_points.laz').stat().st_size - 873_554) < MAX_DIFFERENCE_BYTES + assert abs((dirname / 'leg000_points.laz').stat().st_size - 875_054) < MAX_DIFFERENCE_BYTES with open(dirname / 'leg000_trajectory.txt', 'r') as f: for _ in range(3): next(f) diff --git a/pytests/test_gpsStartTimeFlag.py b/pytests/test_gpsStartTimeFlag.py index 684491810..4b4e1d114 100644 --- a/pytests/test_gpsStartTimeFlag.py +++ b/pytests/test_gpsStartTimeFlag.py @@ -66,7 +66,7 @@ def test_gpsStartTimeFlag_exe(): r3_sum = sha256sum(r3 / 'leg000_points.xyz') assert r2_sum == r3_sum assert r2_sum == 'e1daca137b066eca4bd29b62f3cb5ecde4bcc41650f2cdfc44110c87b97f23dc' or \ - r2_sum == '59b9d09d6e2a6b8a8c25112f5b06fc08430c4058216efeea6ec7324dff0c7797' # linux checksum + r2_sum == 'e5ff320c318bd8cb87865ff8a3fd5d8835ca7a66736cc7469e59ad2c365a3a31' # linux checksum assert r1_sum != r2_sum if DELETE_FILES_AFTER: @@ -95,7 +95,7 @@ def test_gpsStartTimeFlag_pyh(): r3_sum = sha256sum(r3 / 'leg000_points.xyz') assert r2_sum == r3_sum assert r2_sum == 'e1daca137b066eca4bd29b62f3cb5ecde4bcc41650f2cdfc44110c87b97f23dc' or \ - r2_sum == '59b9d09d6e2a6b8a8c25112f5b06fc08430c4058216efeea6ec7324dff0c7797' # linux checksum + r2_sum == 'e5ff320c318bd8cb87865ff8a3fd5d8835ca7a66736cc7469e59ad2c365a3a31' # linux checksum assert r1_sum != r2_sum if DELETE_FILES_AFTER: @@ -104,4 +104,4 @@ def test_gpsStartTimeFlag_pyh(): shutil.rmtree(r2) shutil.rmtree(r3) except Exception as e: - print(f"Error cleaning up: {e}") \ No newline at end of file + print(f"Error cleaning up: {e}") diff --git a/pytests/test_pyhelios.py b/pytests/test_pyhelios.py index d7b39b0ed..19e660e0b 100644 --- a/pytests/test_pyhelios.py +++ b/pytests/test_pyhelios.py @@ -278,7 +278,7 @@ def test_create_survey(): output = simB.join() meas, traj = pyhelios.outputToNumpy(output) # check length of output - assert meas.shape == (10397, 17) + assert meas.shape == (10470, 17) assert traj.shape == (6670, 7) # compare individual points np.testing.assert_allclose(meas[100, :3], np.array([83.32, -66.44204, 0.03114649])) @@ -373,7 +373,7 @@ def test_output(export_to_file): measurements_array, trajectory_array = pyhelios.outputToNumpy(output) np.testing.assert_allclose(measurements_array[0, :3], np.array([474500.3, 5473530.0, 106.0988]), rtol=0.000001) - assert measurements_array.shape == (2433, 17) + assert measurements_array.shape == (2435, 17) assert trajectory_array.shape == (9, 7) if export_to_file: assert Path(output.outpath).parent.parent == Path(WORKING_DIR) / "output" / "als_hd_demo" diff --git a/src/main/helios_version.cpp b/src/main/helios_version.cpp index f90c492c1..bfc9db9ca 100644 --- a/src/main/helios_version.cpp +++ b/src/main/helios_version.cpp @@ -4,7 +4,7 @@ const char * HELIOS_VERSION = "1.2.0"; -const char * HELIOS_GIT_HASH = "ccc0d2cc"; +const char * HELIOS_GIT_HASH = "5cba90e3"; const char * getHeliosVersion(){ return HELIOS_VERSION; From 4bec505ae238fbc7558c5949d641477df8dd3ae4 Mon Sep 17 00:00:00 2001 From: albertoesmp Date: Thu, 5 Oct 2023 12:54:28 +0200 Subject: [PATCH 17/17] Updated pytests --- pytests/test_demo_scenes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pytests/test_demo_scenes.py b/pytests/test_demo_scenes.py index d1e72c3f5..43a090074 100644 --- a/pytests/test_demo_scenes.py +++ b/pytests/test_demo_scenes.py @@ -122,7 +122,7 @@ def eval_arbaro_tls(dirname): assert (dirname / 'leg000_points.las').exists() assert abs((dirname / 'leg000_points.las').stat().st_size - 21_755_791) < MAX_DIFFERENCE_BYTES assert (dirname / 'leg001_points.las').exists() - assert abs((dirname / 'leg001_points.las').stat().st_size - 13_908_757) < MAX_DIFFERENCE_BYTES + assert abs((dirname / 'leg001_points.las').stat().st_size - 13_936_877) < MAX_DIFFERENCE_BYTES with open(dirname / 'leg000_trajectory.txt', 'r') as f: line = f.readline() assert line.startswith('1.0000 25.5000 0.0000')