From 8ad45a901aa64b7e61a5e50abb86c4dc68f68fa9 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Fri, 6 Sep 2019 18:52:26 -0600 Subject: [PATCH 1/8] Improved format of peak diagnostics (part of #280) --- src/GaussianFitter.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/GaussianFitter.cpp b/src/GaussianFitter.cpp index e2f0d2c..114d47c 100644 --- a/src/GaussianFitter.cpp +++ b/src/GaussianFitter.cpp @@ -246,16 +246,18 @@ void callback(const size_t iter, void *params, spdlog::trace("iter {}:",iter); size_t j; for(j=0; j* results, //are pointing to space used in LidarVolume results->clear(); - //UPDATE: We are only using a noise level of 6 because we want all peaks //with an amplitude >= 10 //Level up to and including which peaks will be excluded @@ -662,7 +663,7 @@ int GaussianFitter::guess_peaks(std::vector* results, std::cerr << "Max = " << max << " Noise = " << ((float)max)*.09 << std::endl; #endif - + if (noise_level < 6){ noise_level = 6; } @@ -775,7 +776,8 @@ int GaussianFitter::guess_peaks(std::vector* results, guess = guess_lt0_default; } - spdlog::debug("Guess for peak {}: amp {}; time: {}; width: {}", + spdlog::debug( + "Guess for peak {}: amp {}; time: {}; width: {}", i, ampData[peak_guesses_loc[i]], idxData[peak_guesses_loc[i]], guess); From 45ad0db88b4b346fc7c0a55e3c0e15fb342663f6 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Fri, 6 Sep 2019 22:56:24 -0600 Subject: [PATCH 2/8] Prototype of Gaussian Fitting from txt file appears to be working (#301) --- Makefile | 4 +-- src/LidarDriver.cpp | 56 +++++++++++++++++++++++++++++++++ src/LidarDriver.hpp | 5 +++ src/TxtWaveReader_unittests.cpp | 54 +++++++++++++++++++++++++++++++ src/pls_to_csv.cpp | 49 +++++++++++++++++++---------- src/pls_to_geotiff.cpp | 3 -- 6 files changed, 149 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 1f07918..bfe384e 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,7 @@ $(BIN)/LidarDriver_unittests: $(OBJ)/LidarDriver_unittests.o \ $(OBJ)/CmdLine.o \ $(OBJ)/FlightLineData.o $(OBJ)/LidarVolume.o \ $(OBJ)/LidarDriver.o $(OBJ)/WaveGPSInformation.o\ - $(OBJ)/PulseData.o \ + $(OBJ)/PulseData.o $(OBJ)/TxtWaveReader.o\ $(OBJ)/Peak.o $(OBJ)/GaussianFitter.o\ $(LIB)/gtest_main.a $(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@ -L \ @@ -221,7 +221,7 @@ $(BIN)/csv-driver: $(OBJ)/pls_to_csv.o $(OBJ)/csv_CmdLine.o \ $(OBJ)/FlightLineData.o $(OBJ)/LidarVolume.o \ $(OBJ)/LidarDriver.o $(OBJ)/WaveGPSInformation.o \ $(OBJ)/PulseData.o $(OBJ)/Peak.o $(OBJ)/GaussianFitter.o \ - $(OBJ)/CsvWriter.o + $(OBJ)/CsvWriter.o $(OBJ)/TxtWaveReader.o $(CXX) $(PFLAG) $(CPPFLAGS) $(CXXFLAGS) -g -lpthread $^ -o $@ -L \ $(PULSE_DIR)/lib -lpulsewaves -lgdal -lm -lgsl \ -lgslcblas diff --git a/src/LidarDriver.cpp b/src/LidarDriver.cpp index 3a69c6a..d01a24b 100644 --- a/src/LidarDriver.cpp +++ b/src/LidarDriver.cpp @@ -238,6 +238,62 @@ void LidarDriver::fit_data_csv(FlightLineData &raw_data, } } +/** + * Overloads fit_data_csv for TxtWaveReader support + * @param raw_data reference to TxtWaveReader object that holds raw data + * @param strings a place where peak to_string calls will be stored + * @param csv_CmdLine object that knows what data we want from peaks + */ +void LidarDriver::fit_data_csv(TxtWaveReader &raw_data, + std::vector &strings, csv_CmdLine &cmdLine) +{ + std::ostringstream stream; + GaussianFitter fitter; + std::vector peaks; + + //message the user + std::string fit_type=cmdLine.useGaussianFitting?"gaussian fitting": + "first difference"; + spdlog::info("Finding peaks with {}", fit_type); + + //parse each pulse + while (raw_data.next_wave()) { + + //Skip all the empty returning waveforms + if (raw_data.idx.empty()){ + continue; + } + + try { + // Smooth the data and test result + fitter.smoothing_expt(&raw_data.idx); + + // Check parameter for using gaussian fitting or first differencing + if (cmdLine.useGaussianFitting) { + fitter.find_peaks(&peaks, raw_data.wave, + raw_data.idx); + } else { + fitter.guess_peaks(&peaks, raw_data.wave, + raw_data.idx); + } + + // xyz calc isn't available for TxtWaveReader + + // for each peak we will call to_string and append them together + std::string *str = new std::string; + this->peaks_to_string(*str, cmdLine, peaks); + strings.push_back(str); + } catch (const char *msg) { + spdlog::error("{}", msg); + } + + // make sure that we have an empty vector and string + for (auto i = peaks.begin(); i != peaks.end(); ++i) { + delete (*i); + } + } +} + /** * Takes a vector of peaks from a single waveform and concats them together * @param str string will be put here diff --git a/src/LidarDriver.hpp b/src/LidarDriver.hpp index 8b12a97..740fa92 100644 --- a/src/LidarDriver.hpp +++ b/src/LidarDriver.hpp @@ -16,6 +16,7 @@ #include #include #include "csv_CmdLine.hpp" +#include "TxtWaveReader.hpp" const double NO_DATA = -99999; const double MAX_ELEV = 99999.99; @@ -32,6 +33,10 @@ class LidarDriver { std::vector &strings, csv_CmdLine &cmdLine); + void fit_data_csv(TxtWaveReader &raw_data, + std::vector &strings, + csv_CmdLine &cmdLine); + void peaks_to_string(std::string &str, csv_CmdLine &cmdLine, std::vector &peaks); diff --git a/src/TxtWaveReader_unittests.cpp b/src/TxtWaveReader_unittests.cpp index 7a507ff..0f4cb20 100644 --- a/src/TxtWaveReader_unittests.cpp +++ b/src/TxtWaveReader_unittests.cpp @@ -228,3 +228,57 @@ TEST_F(TxtWaveReaderTest, Valid_Invalid_ValidWaveTest) { EXPECT_TRUE(reader.wave == wave2); EXPECT_FALSE(reader.next_wave()); } + +TEST_F(TxtWaveReaderTest, Valid_Invalid_readanyways_Test) { + message = "9 8 7 6 5 4\n9 8 7 6 5 4\n3 2 1\n"; + writeTestFile(); + + std::vector idx0 = { 9, 8, 7, 6, 5, 4}; + std::vector wave0 = { 9, 8, 7, 6, 5, 4}; + std::vector idx1 = { 3, 2, 1 }; + std::vector wave1 = { }; + std::vector idx2 = { }; + std::vector wave2 = { }; + + EXPECT_NO_THROW(reader.open_file (fileName)); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx0); + EXPECT_TRUE(reader.wave == wave0); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx1); + EXPECT_TRUE(reader.wave == wave1); + EXPECT_FALSE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx2); + EXPECT_TRUE(reader.wave == wave2); + EXPECT_FALSE(reader.next_wave()); +} + +TEST_F(TxtWaveReaderTest, Valid_Valid_EmptyAndReadsAnyways_Test) { + message = "1 2 3\n1 2 3\n4 5 6\n4 5 6\n\n"; + writeTestFile(); + + std::vector idx0 = { 1, 2, 3 }; + std::vector wave0 = { 1, 2, 3 }; + std::vector idx1 = { 4, 5, 6 }; + std::vector wave1 = { 4, 5, 6 }; + std::vector idx2 = { }; + std::vector wave2 = { }; + + EXPECT_NO_THROW(reader.open_file (fileName)); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx0); + EXPECT_TRUE(reader.wave == wave0); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx1); + EXPECT_TRUE(reader.wave == wave1); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx2); + EXPECT_TRUE(reader.wave == wave2); + EXPECT_FALSE(reader.next_wave()); +} diff --git a/src/pls_to_csv.cpp b/src/pls_to_csv.cpp index 278ba15..c2624ae 100644 --- a/src/pls_to_csv.cpp +++ b/src/pls_to_csv.cpp @@ -2,6 +2,7 @@ // Created on: March 2019 // Author: Ravi, Ahmad, Spencer +#include "TxtWaveReader.hpp" #include "LidarDriver.hpp" #include "CsvWriter.hpp" #include @@ -14,10 +15,15 @@ typedef std::chrono::high_resolution_clock Clock; // Csv-maker driver int main (int argc, char *argv[]) { - LidarDriver driver; //driver object with tools - csv_CmdLine cmdLineArgs; //command line options - FlightLineData rawData; //the raw data read from PLS + WVS files - CsvWriter writer; //Writes CSV file + // Setting up logger + spdlog::set_pattern("[%^%=8l%$] %v"); + // Sets new pattern for timestamp + + TxtWaveReader rawData0; // Wave inputs from txt file + FlightLineData rawData1; // Wave inputs from pls file + LidarDriver driver; // Driver object with tools + csv_CmdLine cmdLineArgs; // Command line options + CsvWriter writer; // Writes CSV file writer.setLines(new std::vector); //Data stored here // Parse and validate the command line args @@ -25,30 +31,39 @@ int main (int argc, char *argv[]) { return 1; } - // Initialize data input per CmdLine specification - if (cmdLineArgs.is_txt) { - spdlog::info("txt file recognized"); - return 0; - } + bool is_txt = cmdLineArgs.is_txt; + std::string fname = cmdLineArgs.getInputFileName(true); // Collect start time Clock::time_point t1 = Clock::now(); - spdlog::info("Processing {}", cmdLineArgs.getInputFileName(true).c_str()); + spdlog::info("Processing {}", fname); - // ingest the raw flight data into an object - if (rawData.setFlightLineData(cmdLineArgs.getInputFileName(true))) { - return 1; + // Initialize data input per CmdLine specification + if (is_txt) { + spdlog::info("txt file recognized"); + if (rawData0.open_file(fname.c_str())) { + spdlog::critical("Opening txt file '{}' failed", fname); + return 1; + } + + driver.fit_data_csv(rawData0, *writer.getLines(), cmdLineArgs); + } else { + // ingest the raw flight data into an object + if (rawData1.setFlightLineData(cmdLineArgs.getInputFileName(true))) { + return 1; + } + + driver.fit_data_csv(rawData1, *writer.getLines(), cmdLineArgs); } - // fit data - driver.fit_data_csv(rawData, *writer.getLines(), cmdLineArgs); - // Write data to file writer.write_to_csv(cmdLineArgs.get_output_filename(1)); // Free memory - rawData.closeFlightLineData(); + if (!is_txt) { + rawData1.closeFlightLineData(); + } writer.freeLines(); diff --git a/src/pls_to_geotiff.cpp b/src/pls_to_geotiff.cpp index 33ac29a..46cbd15 100644 --- a/src/pls_to_geotiff.cpp +++ b/src/pls_to_geotiff.cpp @@ -21,9 +21,6 @@ int main (int argc, char *argv[]) { spdlog::set_pattern("[%^%=8l%$] %v"); // Sets new pattern for timestamp - auto logger = spdlog::create_async( - "logger"); - LidarDriver driver; //driver object with tools CmdLine cmdLineArgs; //command line options FlightLineData rawData; //the raw data read from PLS + WVS files From dbe6203acb4577473f79ca6da1bb7548927f2120 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Fri, 6 Sep 2019 23:12:03 -0600 Subject: [PATCH 3/8] Testing and adjusting things for #301 (txtWaveReader driver prototype) --- src/TxtWaveReader.cpp | 4 ++-- src/TxtWaveReader_unittests.cpp | 21 +++++++++++++++++++++ src/pls_to_csv.cpp | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/TxtWaveReader.cpp b/src/TxtWaveReader.cpp index 781ed0b..f5ce306 100644 --- a/src/TxtWaveReader.cpp +++ b/src/TxtWaveReader.cpp @@ -69,14 +69,14 @@ bool TxtWaveReader::get_vector (std::vector& vect) { // Makes sure an error has not occured during the last read. if (txtFile.bad() || txtFile.fail()) { - spdlog::error("{}: bad read on line {}", C_NAME, line_count); + spdlog::debug("{}: bad read on line {}", C_NAME, line_count); return true; } // Makes sure it is a sequence of digits 0-9 and space. bool valid = is_line_valid(); if (!valid) { - spdlog::error("{}: bad format read at line {}", C_NAME, + spdlog::debug("{}: bad format read at line {}", C_NAME, line_count); return true; } diff --git a/src/TxtWaveReader_unittests.cpp b/src/TxtWaveReader_unittests.cpp index 0f4cb20..bdb8ac6 100644 --- a/src/TxtWaveReader_unittests.cpp +++ b/src/TxtWaveReader_unittests.cpp @@ -282,3 +282,24 @@ TEST_F(TxtWaveReaderTest, Valid_Valid_EmptyAndReadsAnyways_Test) { EXPECT_TRUE(reader.wave == wave2); EXPECT_FALSE(reader.next_wave()); } + +TEST_F(TxtWaveReaderTest, Valid_Valid_EOF_andReadsAnyways_Test) { + message = "1 1 1\n1 1 1\n2 2 2\n 2 2 2\n"; + writeTestFile(); + + std::vector idx0 = { 1, 1, 1 }; + std::vector wave0 = { 1, 1, 1 }; + std::vector idx1 = { 2, 2, 2 }; + std::vector wave1 = { 2, 2, 2 }; + + EXPECT_NO_THROW(reader.open_file (fileName)); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx0); + EXPECT_TRUE(reader.wave == wave0); + EXPECT_TRUE(reader.next_wave()); + + EXPECT_TRUE(reader.idx == idx1); + EXPECT_TRUE(reader.wave == wave1); + EXPECT_FALSE(reader.next_wave()); +} diff --git a/src/pls_to_csv.cpp b/src/pls_to_csv.cpp index c2624ae..0b3ed48 100644 --- a/src/pls_to_csv.cpp +++ b/src/pls_to_csv.cpp @@ -7,6 +7,8 @@ #include "CsvWriter.hpp" #include +// Activity level must be included before spdlog +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE #include "spdlog/spdlog.h" typedef std::chrono::high_resolution_clock Clock; From f486918876a455cca6c256a1388f615d257cfbb6 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Wed, 11 Sep 2019 21:17:43 -0600 Subject: [PATCH 4/8] Added toggle option for logging extra diagnostics info (off by default); now logs when wave is skipped and logs raw input (#301) --- src/GaussianFitter.cpp | 37 +++++++++++++++++++++++-------------- src/GaussianFitter.hpp | 4 ++++ src/LidarDriver.cpp | 38 +++++++++++++++++++++++++++++++++++++- src/csv_CmdLine.cpp | 8 +++++++- src/csv_CmdLine.hpp | 3 +++ src/pls_to_csv.cpp | 4 ++++ 6 files changed, 78 insertions(+), 16 deletions(-) diff --git a/src/GaussianFitter.cpp b/src/GaussianFitter.cpp index 114d47c..655e64a 100644 --- a/src/GaussianFitter.cpp +++ b/src/GaussianFitter.cpp @@ -28,6 +28,12 @@ GaussianFitter::GaussianFitter(){ amp_upper_bound = AMP_UPPER_BOUND; amp_lower_bound = AMP_LOWER_BOUND; + + log_diagnostics = false; +} + +void GaussianFitter::setDiagnostics(bool newval) { + log_diagnostics = newval; } @@ -237,27 +243,27 @@ void callback(const size_t iter, void *params, double avratio = gsl_multifit_nlinear_avratio(w); double rcond; - (void) params; /* not used */ - /* compute reciprocal condition number of J(x) */ gsl_multifit_nlinear_rcond(&rcond, w); - size_t npeaks = x->size/3; - spdlog::trace("iter {}:",iter); - size_t j; - for(j=0; jsize/3; + spdlog::trace("iter {}:",iter); + size_t j; + for(j=0; j* results, guess = guess_lt0_default; } - spdlog::debug( - "Guess for peak {}: amp {}; time: {}; width: {}", - i, ampData[peak_guesses_loc[i]], idxData[peak_guesses_loc[i]], - guess); + if (log_diagnostics) { + spdlog::debug( + "Guess for peak {}: amp {}; time: {}; width: {}", + i, ampData[peak_guesses_loc[i]], + idxData[peak_guesses_loc[i]], guess); + } if(guess > 20) {guess = 10;} peaks_found++; diff --git a/src/GaussianFitter.hpp b/src/GaussianFitter.hpp index b0694e6..c20bfd4 100644 --- a/src/GaussianFitter.hpp +++ b/src/GaussianFitter.hpp @@ -47,6 +47,8 @@ class GaussianFitter{ int get_pass(); int get_total(); + void setDiagnostics(bool newval); + std::vector equations; //Fitted equations int max; //The max peak amplitude of each set of returning waves @@ -72,6 +74,8 @@ class GaussianFitter{ private: + bool log_diagnostics; + int solve_system (gsl_vector *x, gsl_multifit_nlinear_fdf *fdf, gsl_multifit_nlinear_parameters *params, int max); diff --git a/src/LidarDriver.cpp b/src/LidarDriver.cpp index d01a24b..4fe8cfc 100644 --- a/src/LidarDriver.cpp +++ b/src/LidarDriver.cpp @@ -175,6 +175,17 @@ void LidarDriver::fit_data(FlightLineData &raw_data, LidarVolume &fitted_data, spdlog::debug("Fail: {}", fitter.get_fail()); } +void log_raw_data(std::vector idx, std::vector wave) { + //Print raw wave + std::stringstream idxstr; + std::stringstream wavestr; + std::copy(idx.begin(), idx.end(), std::ostream_iterator(idxstr, " ")); + std::copy(wave.begin(), wave.end(), + std::ostream_iterator(wavestr, " ")); + spdlog::trace("raw pulse idx: {}; raw pulse wave: {}", idxstr.str(), + wavestr.str()); +} + /** * Fits the raw data using either gaussian or first difference fitting, * and sends each wave of peaks to be written to a CSV file. @@ -190,6 +201,10 @@ void LidarDriver::fit_data_csv(FlightLineData &raw_data, GaussianFitter fitter; std::vector peaks; + bool log_diagnostics = cmdLine.log_diagnostics; + + if (log_diagnostics) fitter.setDiagnostics(true); + //message the user std::string fit_type=cmdLine.useGaussianFitting?"gaussian fitting": "first difference"; @@ -202,10 +217,19 @@ void LidarDriver::fit_data_csv(FlightLineData &raw_data, // gets the raw data from the file raw_data.getNextPulse(&pd); - //Skip all the empty returning waveforms + // Skip all the empty returning waveforms if (pd.returningIdx.empty()){ + if (log_diagnostics) { + spdlog::trace("pulse idx was empty, skipping"); + } continue; } + + // Log data + if (log_diagnostics) { + log_raw_data(pd.returningIdx, pd.returningWave); + } + try { // Smooth the data and test result fitter.smoothing_expt(&pd.returningWave); @@ -251,6 +275,10 @@ void LidarDriver::fit_data_csv(TxtWaveReader &raw_data, GaussianFitter fitter; std::vector peaks; + bool log_diagnostics = cmdLine.log_diagnostics; + + if (log_diagnostics) fitter.setDiagnostics(true); + //message the user std::string fit_type=cmdLine.useGaussianFitting?"gaussian fitting": "first difference"; @@ -261,9 +289,17 @@ void LidarDriver::fit_data_csv(TxtWaveReader &raw_data, //Skip all the empty returning waveforms if (raw_data.idx.empty()){ + if (log_diagnostics) { + spdlog::trace("pulse idx was empty, skipping"); + } continue; } + // Log data + if (log_diagnostics) { + log_raw_data(raw_data.idx, raw_data.wave); + } + try { // Smooth the data and test result fitter.smoothing_expt(&raw_data.idx); diff --git a/src/csv_CmdLine.cpp b/src/csv_CmdLine.cpp index 8078ec4..f533c5d 100644 --- a/src/csv_CmdLine.cpp +++ b/src/csv_CmdLine.cpp @@ -68,6 +68,8 @@ void csv_CmdLine::setUsageMessage() << " :Prints this help message" << std::endl; buffer << " -p " << " :Writes peak data to CSV" << std::endl; + buffer << " -l " + << " :Logs extra diagnostics information about peaks" << std::endl; buffer << std::endl; buffer << "Peak variable options and letters:" << std::endl << std::endl; buffer << "| Variable | Number | Description " << std::endl; @@ -111,6 +113,7 @@ csv_CmdLine::csv_CmdLine(){ is_txt = false; printUsageMessage = false; useGaussianFitting = true; + log_diagnostics = false; exeName = ""; setUsageMessage(); } @@ -156,6 +159,7 @@ bool csv_CmdLine::parse_args(int argc,char *argv[]){ {"help", no_argument, NULL, 'h'}, {"firstdiff", no_argument, NULL, 'd'}, {"peaks", required_argument,NULL,'p'}, + {"log-diag", no_argument, NULL, 'l'}, {0, 0, 0, 0} }; @@ -165,7 +169,7 @@ bool csv_CmdLine::parse_args(int argc,char *argv[]){ * ":hf:s:" indicate that option 'h' is without arguments while * option 'f' and 's' require arguments */ - while((optionChar = getopt_long (argc, argv, "-:hdf:p:", + while((optionChar = getopt_long (argc, argv, "-:hdf:p:l", long_options, &option_index))!= -1){ if (optionChar == 'f') { //Set the filename to parse fArg = optarg; @@ -174,6 +178,8 @@ bool csv_CmdLine::parse_args(int argc,char *argv[]){ printUsageMessage = true; } else if (optionChar == 'd') { //Sets analysis method useGaussianFitting = false; + } else if (optionChar == 'l') {//Sets log_diagnostics + log_diagnostics = true; } else if (optionChar == 'p') { //Sets which pruducts to create and for which variable { // Without curly braces wrapping this case, there are compilation diff --git a/src/csv_CmdLine.hpp b/src/csv_CmdLine.hpp index c54b6aa..f8ab1b9 100644 --- a/src/csv_CmdLine.hpp +++ b/src/csv_CmdLine.hpp @@ -46,6 +46,9 @@ class csv_CmdLine{ //True means input file was a txt file bool is_txt; + //True means we're gonna print a lot of extra diagnostic info + bool log_diagnostics; + csv_CmdLine(); diff --git a/src/pls_to_csv.cpp b/src/pls_to_csv.cpp index 0b3ed48..b0e6828 100644 --- a/src/pls_to_csv.cpp +++ b/src/pls_to_csv.cpp @@ -39,6 +39,10 @@ int main (int argc, char *argv[]) { // Collect start time Clock::time_point t1 = Clock::now(); + if (cmdLineArgs.log_diagnostics) { + spdlog::info("Diagnostics enabled for this run"); + } + spdlog::info("Processing {}", fname); // Initialize data input per CmdLine specification From 0248c5e47a9a5653cd92404e5cb8a37db4ce7173 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Tue, 17 Sep 2019 15:51:24 -0600 Subject: [PATCH 5/8] Added some uint tests to csv_CmdLine (#310) --- Makefile | 3 +- src/LidarDriver_unittests.cpp | 9 -- src/TxtWaveReader_unittests.cpp | 12 -- src/csv_CmdLine.cpp | 55 ++++++--- src/csv_CmdLine.hpp | 11 +- src/csv_CmdLine_unittests.cpp | 201 ++++++++++++++++++++++++++++++-- 6 files changed, 238 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index bfe384e..ad1214f 100644 --- a/Makefile +++ b/Makefile @@ -205,7 +205,8 @@ $(BIN)/geotiff-driver: $(OBJ)/pls_to_geotiff.o $(OBJ)/CmdLine.o \ $(OBJ)/FlightLineData.o $(OBJ)/LidarVolume.o \ $(OBJ)/LidarDriver.o $(OBJ)/WaveGPSInformation.o\ $(OBJ)/WaveGPSInformation.o $(OBJ)/PulseData.o \ - $(OBJ)/Peak.o $(OBJ)/GaussianFitter.o + $(OBJ)/Peak.o $(OBJ)/GaussianFitter.o \ + $(OBJ)/TxtWaveReader.o $(CXX) $(PFLAG) $(CPPFLAGS) $(CXXFLAGS) -g -lpthread $^ -o $@ -L \ $(PULSE_DIR)/lib -lpulsewaves -lgdal -lm -lgsl \ -lgslcblas diff --git a/src/LidarDriver_unittests.cpp b/src/LidarDriver_unittests.cpp index 968c5b7..be2cdf3 100644 --- a/src/LidarDriver_unittests.cpp +++ b/src/LidarDriver_unittests.cpp @@ -737,12 +737,3 @@ TEST_F(LidarDriverTest, add_peaks_to_volume_test) EXPECT_EQ(peaks.at(0)->z_activation, lidarVolume.volume[5]-> at(0)->z_activation); } - -/******************************************************************************* - * - * fit_data_csv and peaks_to_string tests - * - ******************************************************************************/ - -//These need to be made testable along with fit_data, but that is an issue for -//later I think. Not too much later though. diff --git a/src/TxtWaveReader_unittests.cpp b/src/TxtWaveReader_unittests.cpp index bdb8ac6..c94acc1 100644 --- a/src/TxtWaveReader_unittests.cpp +++ b/src/TxtWaveReader_unittests.cpp @@ -114,9 +114,6 @@ TEST_F(TxtWaveReaderTest, oneValidLineTest) { EXPECT_NO_THROW(reader.open_file (fileName)); EXPECT_FALSE(reader.next_wave()); - //printVector(reader.idx); - //printVector(reader.wave); - EXPECT_TRUE(reader.idx == exp_idx); EXPECT_TRUE(reader.wave == exp_wave); } @@ -132,9 +129,6 @@ TEST_F(TxtWaveReaderTest, oneValidWaveTest) { EXPECT_NO_THROW(reader.open_file (fileName)); EXPECT_TRUE(reader.next_wave()); - //printVector(reader.idx); - //printVector(reader.wave); - EXPECT_TRUE(reader.idx == exp_idx); EXPECT_TRUE(reader.wave == exp_wave); EXPECT_FALSE(reader.next_wave()); @@ -151,9 +145,6 @@ TEST_F(TxtWaveReaderTest, oneInvalidWaveTest) { EXPECT_NO_THROW(reader.open_file (fileName)); EXPECT_TRUE(reader.next_wave()); - //printVector(reader.idx); - //printVector(reader.wave); - EXPECT_TRUE(reader.idx == idx0); EXPECT_TRUE(reader.wave == wave0); EXPECT_FALSE(reader.next_wave()); @@ -190,9 +181,6 @@ TEST_F(TxtWaveReaderTest, twoValidWaveTest) { EXPECT_NO_THROW(reader.open_file (fileName)); EXPECT_TRUE(reader.next_wave()); - //printVector(reader.idx); - //printVector(reader.wave); - EXPECT_TRUE(reader.idx == idx0); EXPECT_TRUE(reader.wave == wave0); EXPECT_TRUE(reader.next_wave()); diff --git a/src/csv_CmdLine.cpp b/src/csv_CmdLine.cpp index f533c5d..505cab0 100644 --- a/src/csv_CmdLine.cpp +++ b/src/csv_CmdLine.cpp @@ -20,30 +20,52 @@ const static std::string peakvars[10] = { ****************************************************************************/ /** - * Function that sets the command line arguments - * @param args + * Function that returns a file_type enum based on input filetype. 'Other' + * represents files that were not pls or txt. + * @param f_name filename to parse for file type + * @returns file_type enum representing what kind of file it is. */ -void csv_CmdLine::setInputFileName(char *args){ - //Check if the filename is a txt or a pls - plsFileName = args; - size_t begin = plsFileName.find_last_of("."); +csv_CmdLine::file_type csv_CmdLine::get_file_type (std::string &f_name) { + const size_t begin = f_name.find_last_of("."); if (begin == string::npos) { - std::cerr << "File not specified or has no extension" << std::endl; - printUsageMessage = true; - return; + return other; } - size_t len = plsFileName.size() - begin; - std::string file_ext = plsFileName.substr(begin, len); + const size_t len = f_name.size() - begin; + std::string file_ext = f_name.substr(begin, len); if (file_ext == ".pls") { - check_input_file_exists(); + return pls; } else if (file_ext == ".txt") { - is_txt = true; - check_input_txt_exists(); + return txt; } else { - std::cerr << "Not a supported filetype" << std::endl; - printUsageMessage = true; + return other; + } +} + +/** + * Function that sets the command line arguments + * @param args + */ +void csv_CmdLine::setInputFileName(char *args){ + plsFileName = args; + + // Check if the filename is a txt or a pls or other + std::string args_str (args); + const file_type f_type = get_file_type (args_str); + + switch (f_type) { + case pls: + check_input_file_exists(); + break; + case txt: + is_txt = true; + check_input_txt_exists(); + break; + case other: + default: + if (!quiet) std::cerr << "Not a supported filetype" << std::endl; + printUsageMessage = true; } } @@ -289,6 +311,7 @@ void csv_CmdLine::check_input_file_exists() { * check if the input file exists, print error message if not */ void csv_CmdLine::check_input_txt_exists() { + plsFileName = getInputFileName(true); if (!std::ifstream(plsFileName.c_str())) { if (!quiet) { std::cout << "\nFile " << plsFileName << " not found." diff --git a/src/csv_CmdLine.hpp b/src/csv_CmdLine.hpp index f8ab1b9..7a0d06e 100644 --- a/src/csv_CmdLine.hpp +++ b/src/csv_CmdLine.hpp @@ -40,23 +40,26 @@ class csv_CmdLine{ // True = gaussian fitting, False = first differencing bool useGaussianFitting; - //True stifles all output statements + // True stifles all output statements bool quiet; - //True means input file was a txt file + // True means input file was a txt file bool is_txt; - //True means we're gonna print a lot of extra diagnostic info + // True means we're gonna print a lot of extra diagnostic info bool log_diagnostics; - csv_CmdLine(); + // Used to communicate filetype efficiently between functions + enum file_type { pls, txt, other }; + csv_CmdLine(); bool parse_args(int argc, char *argv[]); void setUsageMessage(); std::string getUsageMessage(); void check_input_file_exists(); void check_input_txt_exists(); + file_type get_file_type(std::string &f_name); void setInputFileName(char *args); void setInputFileName(std::string filename); std::string getInputFileName(bool pls); diff --git a/src/csv_CmdLine_unittests.cpp b/src/csv_CmdLine_unittests.cpp index 19b14e6..7a791cd 100644 --- a/src/csv_CmdLine_unittests.cpp +++ b/src/csv_CmdLine_unittests.cpp @@ -1,7 +1,7 @@ /* * File name: csv_CmdLine_unittests.cpp * Created on: 16-July-2019 -* Author: ravi +* Author: ravi, spencer */ #include "csv_CmdLine.hpp" @@ -18,19 +18,31 @@ class csv_CmdLineTest : public testing::Test { numberOfArgs = 10; maxLengthOfArg = 256; commonArgSpace = allocateTestArgs(numberOfArgs,maxLengthOfArg); + //Set required arguments strncpy(commonArgSpace[0],"test",5); strncpy(commonArgSpace[1],"-f",3); strncpy(commonArgSpace[2],"do_not_use.pls",15); strncpy(commonArgSpace[3],"-p",3); strncpy(commonArgSpace[4],"1",2); - //Stifle command line error messages - cmd.quiet = true; + //Create test files std::ofstream pls ("do_not_use.pls"); pls.close(); std::ofstream wvs ("do_not_use.wvs"); wvs.close(); + std::ofstream txt ("do_not_use.txt"); + txt.close(); + + //Make fresh cmd objects + cmd = csv_CmdLine(); + cmd2 = csv_CmdLine(); + cmd3 = csv_CmdLine(); + + //Make them quiet + cmd.quiet = true; + cmd2.quiet = true; + cmd3.quiet = true; } static char** allocateTestArgs(int N,int M){ @@ -49,6 +61,7 @@ class csv_CmdLineTest : public testing::Test { //Delete test files std::remove("do_not_use.pls"); std::remove("do_not_use.wvs"); + std::remove("do_not_use.txt"); } char** commonArgSpace; @@ -68,10 +81,134 @@ TEST_F(csv_CmdLineTest, noArguments){ ASSERT_TRUE(cmd.printUsageMessage); } +/******************************************************************************* + * File type detection tests + ******************************************************************************/ + +// Tests that passing file with pls extension returns pls +TEST_F(csv_CmdLineTest, get_file_type_pls) { + std::string file_name = "what.pls"; + ASSERT_EQ(csv_CmdLine::pls, cmd.get_file_type(file_name)); +} + +// Tests that passing file with txt extension returns txt +TEST_F(csv_CmdLineTest, get_file_type_txt) { + std::string file_name = "what.txt"; + ASSERT_EQ(csv_CmdLine::txt, cmd.get_file_type(file_name)); +} + +// Tests that passing file with wvs extension returns other +TEST_F(csv_CmdLineTest, get_file_type_wvs) { + std::string file_name = "what.wvs"; + ASSERT_EQ(csv_CmdLine::other, cmd.get_file_type(file_name)); +} + +// Tests that passing file with arbitrary extension ('.abc') returns other +TEST_F(csv_CmdLineTest, get_file_type_arbitrary_extension) { + std::string file_name = "what.abc"; + ASSERT_EQ(csv_CmdLine::other, cmd.get_file_type(file_name)); +} + +// Tests that passing file with no extension returns other +TEST_F(csv_CmdLineTest, get_file_type_no_extension) { + std::string file_name = "what"; + ASSERT_EQ(csv_CmdLine::other, cmd.get_file_type(file_name)); +} + +/******************************************************************************* + * Set filename tests + ******************************************************************************/ + +// Tests that passing existing pls file: +// Keeps is_txt == false +// usage message will not print +TEST_F(csv_CmdLineTest, set_input_filename_pls) { + char name[20]; + strncpy(name, "do_not_use.pls", 15); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_FALSE(cmd.is_txt); +} + +// Tests that passing existing wvs file: +// usage message will print +TEST_F(csv_CmdLineTest, set_input_filename_wvs) { + char name[20]; + strncpy(name, "do_not_use.wvs", 15); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.printUsageMessage); +} + +// Tests that passing existing txt file: +// Sets is_txt to true +// usage message will not print +TEST_F(csv_CmdLineTest, set_input_filename_txt) { + char name[20]; + strncpy(name, "do_not_use.txt", 15); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.is_txt); + ASSERT_FALSE(cmd.printUsageMessage); +} + +// Tests that passing existing invalid filetype: +// usage message will print +TEST_F(csv_CmdLineTest, set_input_filename_invalid_filetype) { + char name[20]; + strncpy(name, "invalid.abc", 12); + + std::ofstream invalid_file (name); + invalid_file.close(); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.printUsageMessage); + + std::remove(name); +} + +// Tests that passing non-existing pls file: +// usage message will print +TEST_F(csv_CmdLineTest, set_input_filename_invalid_pls) { + char name[20]; + strncpy(name, "invalid.pls", 12); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.printUsageMessage); +} + +// Tests that passing non-existing wvs file: +// usage message will print +TEST_F(csv_CmdLineTest, set_input_filename_invalid_wvs) { + char name[20]; + strncpy(name, "invalid.wvs", 12); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.printUsageMessage); +} + +// Tests that passing non-existing txt file: +// usage message will print +TEST_F(csv_CmdLineTest, set_input_filename_invalid_txt) { + char name[20]; + strncpy(name, "invalid.txt", 12); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.printUsageMessage); +} + +// Tests that passing non-existing invalid filetype: +// usage message prints +TEST_F(csv_CmdLineTest, set_input_filename_invalid_nonexistant_filetype) { + char name[20]; + strncpy(name, "invalid.abc", 12); + + ASSERT_NO_THROW(cmd.setInputFileName(name)); + ASSERT_TRUE(cmd.printUsageMessage); +} + /**************************************************************************** - * - * File Name Tests - * + * File Name Tests (through command line parser) ****************************************************************************/ // Tests file was correctly set TEST_F(csv_CmdLineTest, validFileName){ @@ -80,8 +217,18 @@ TEST_F(csv_CmdLineTest, validFileName){ numberOfArgs = 5; ASSERT_NO_THROW(cmd.parse_args(numberOfArgs,commonArgSpace)); ASSERT_FALSE(cmd.printUsageMessage); + ASSERT_FALSE(cmd.is_txt); ASSERT_EQ("do_not_use.pls", cmd.getInputFileName(true)); ASSERT_EQ("do_not_use.wvs", cmd.getInputFileName(false)); + + //Txt file + optind = 0; + strncpy(commonArgSpace[2],"do_not_use.txt", 15); + ASSERT_NO_THROW(cmd2.parse_args(numberOfArgs,commonArgSpace)); + ASSERT_FALSE(cmd2.printUsageMessage); + ASSERT_TRUE(cmd2.is_txt); + ASSERT_EQ("do_not_use.txt", cmd2.getInputFileName(true)); + ASSERT_EQ("", cmd2.getInputFileName(false)); } //Tests file was incorrectly set @@ -105,6 +252,16 @@ TEST_F(csv_CmdLineTest, invalidFileName){ ASSERT_NO_THROW(cmd.parse_args(numberOfArgs,commonArgSpace)); ASSERT_TRUE(cmd.printUsageMessage); + //Add wvs back + std::ofstream wvs ("do_not_use.wvs"); + wvs.close(); + + //Filename is wvs type and not txt/pls + optind = 0; + strncpy(commonArgSpace[2], "do_not_use.wvs", 15); + ASSERT_NO_THROW(cmd.parse_args(numberOfArgs, commonArgSpace)); + ASSERT_TRUE(cmd.printUsageMessage); + //No file optind = 0; numberOfArgs = 4; @@ -112,6 +269,15 @@ TEST_F(csv_CmdLineTest, invalidFileName){ strncpy(commonArgSpace[3],"1",2); ASSERT_NO_THROW(cmd.parse_args(numberOfArgs,commonArgSpace)); ASSERT_TRUE(cmd.printUsageMessage); + + //no txt file + optind = 0; + numberOfArgs = 5; + std::remove("do_not_use.txt"); + strncpy(commonArgSpace[2], "do_not_use.txt", 15); + strncpy(commonArgSpace[3], "-p", 3); + ASSERT_NO_THROW(cmd.parse_args(numberOfArgs, commonArgSpace)); + ASSERT_TRUE(cmd.printUsageMessage); } //Tests file was correctly trimmed with various paths @@ -188,9 +354,7 @@ TEST_F(csv_CmdLineTest, setInputFileNameTest_valid) { } /**************************************************************************** - * * Product Option Tests - * ****************************************************************************/ //Tests valid product variable char TEST_F(csv_CmdLineTest, validProductOption){ @@ -248,25 +412,32 @@ TEST_F(csv_CmdLineTest, invalidProductNumber){ } /**************************************************************************** - * * Non-Product Option Tests - * ****************************************************************************/ //Tests for a valid non-product option TEST_F(csv_CmdLineTest, validNonProductOption){ - //Shouldn't trigger usage message + //Shouldn't trigger usage message, log_diagnostics should be false optind = 0; numberOfArgs = 6; strncpy(commonArgSpace[5],"-d",3); ASSERT_NO_THROW(cmd.parse_args(numberOfArgs,commonArgSpace)); ASSERT_FALSE(cmd.printUsageMessage); ASSERT_FALSE(cmd.useGaussianFitting); + ASSERT_FALSE(cmd.log_diagnostics); //Should trigger usage message optind = 0; strncpy(commonArgSpace[5],"-h",3); ASSERT_NO_THROW(cmd.parse_args(numberOfArgs,commonArgSpace)); ASSERT_TRUE(cmd.printUsageMessage); + ASSERT_FALSE(cmd.log_diagnostics); + + //Shouldn't trigger usage message; log_diagnostics should be true + optind = 0; + strncpy(commonArgSpace[5], "-l",3); + ASSERT_NO_THROW(cmd2.parse_args(numberOfArgs,commonArgSpace)); + ASSERT_FALSE(cmd2.printUsageMessage); + ASSERT_TRUE(cmd2.log_diagnostics); } //Tests for an invalid non-product option @@ -322,6 +493,14 @@ TEST_F(csv_CmdLineTest, validLongNonProductOption){ strncpy(commonArgSpace[5],"--help",7); ASSERT_NO_THROW(cmd.parse_args(numberOfArgs,commonArgSpace)); ASSERT_TRUE(cmd.printUsageMessage); + ASSERT_FALSE(cmd.log_diagnostics); + + //Should make log_diagnostics true + optind = 0; + strncpy(commonArgSpace[5], "--log-diag", 11); + ASSERT_NO_THROW(cmd2.parse_args(numberOfArgs, commonArgSpace)); + ASSERT_FALSE(cmd2.printUsageMessage); + ASSERT_TRUE(cmd2.log_diagnostics); } //Tests missing arguments for long options From 4de3f0782499d67dfe5015589b2960755814ffe8 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Tue, 17 Sep 2019 16:14:44 -0600 Subject: [PATCH 6/8] Fixed some more conflicts --- src/GaussianFitter.cpp | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/GaussianFitter.cpp b/src/GaussianFitter.cpp index 40c6745..02f2a65 100644 --- a/src/GaussianFitter.cpp +++ b/src/GaussianFitter.cpp @@ -648,17 +648,8 @@ int GaussianFitter::guess_peaks(std::vector* results, } noise_level = ((float)max)*.09; -<<<<<<< HEAD spdlog::error("Max = {} Noise = {}", max, ((float)max)*.09); - - -======= - #ifdef DEBUG - std::cerr << "Max = " << max << " Noise = " << ((float)max)*.09 - << std::endl; - #endif - ->>>>>>> diagnostics_driver + if (noise_level < 6){ noise_level = 6; } @@ -771,19 +762,12 @@ int GaussianFitter::guess_peaks(std::vector* results, guess = guess_lt0_default; } -<<<<<<< HEAD - spdlog::debug( + if (log_diagnostics) { + spdlog::debug( "Guess for peak {}: amp {}; time: {}; width: {}", i, ampData[peak_guesses_loc[i]], idxData[peak_guesses_loc[i]], guess); -======= - if (log_diagnostics) { - spdlog::debug( - "Guess for peak {}: amp {}; time: {}; width: {}", - i, ampData[peak_guesses_loc[i]], - idxData[peak_guesses_loc[i]], guess); } ->>>>>>> diagnostics_driver if(guess > 20) {guess = 10;} peaks_found++; From eb52b33aea23bac35a0a9a13c4c003a8e5b00285 Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Tue, 17 Sep 2019 20:19:48 -0600 Subject: [PATCH 7/8] max_iter is now a function argument again instead of a instance variable (#317) Also fixed PulseData testSetterGetter test (#314) --- src/GaussianFitter.cpp | 15 +++++++------- src/GaussianFitter.hpp | 7 +++---- src/GaussianFitter_unittests.cpp | 34 ++++++++++++++++---------------- src/LidarDriver.cpp | 11 ++++------- src/PulseData.cpp | 13 ++++++------ src/PulseData_unittests.cpp | 5 ++--- 6 files changed, 40 insertions(+), 45 deletions(-) diff --git a/src/GaussianFitter.cpp b/src/GaussianFitter.cpp index 02f2a65..ee50360 100644 --- a/src/GaussianFitter.cpp +++ b/src/GaussianFitter.cpp @@ -14,9 +14,7 @@ GaussianFitter::GaussianFitter(){ pass = 0; total = 0; - // Set fitter params to default values - max_iter = MAX_ITER; - + //Set instance variables to default values, as defined in header. tolerance_scales = TOL_SCALES; x_tolerance = X_TOL; g_tolerance = G_TOL; @@ -293,9 +291,8 @@ void handler (const char * reason, * @return */ int GaussianFitter::solve_system(gsl_vector *x, gsl_multifit_nlinear_fdf *fdf, - gsl_multifit_nlinear_parameters *params, int max) { - const size_t max_iter = this->max_iter; - + gsl_multifit_nlinear_parameters *params, int max, + const size_t max_iter) { const gsl_multifit_nlinear_type *T = gsl_multifit_nlinear_trust; const double xtol = tolerance_scales ? max / x_tolerance : x_tolerance; @@ -371,11 +368,13 @@ int GaussianFitter::solve_system(gsl_vector *x, gsl_multifit_nlinear_fdf *fdf, * @param results pointer to vector to store peaks * @param ampData * @param idxData + * @param max_iter * @return count of found peaks */ int GaussianFitter::find_peaks(std::vector* results, std::vector ampData, - std::vector idxData) { + std::vector idxData, + const size_t max_iter) { incr_total(); //Error handling @@ -464,7 +463,7 @@ int GaussianFitter::find_peaks(std::vector* results, spdlog::error("peakCount = {}",peakCount); - if(!solve_system(x, &fdf, &fdf_params, max)){ + if(!solve_system(x, &fdf, &fdf_params, max, max_iter)){ incr_pass(); //this loop is going through every peak diff --git a/src/GaussianFitter.hpp b/src/GaussianFitter.hpp index c20bfd4..960585d 100644 --- a/src/GaussianFitter.hpp +++ b/src/GaussianFitter.hpp @@ -35,7 +35,7 @@ class GaussianFitter{ public: int find_peaks(std::vector* results,std::vector ampData, - std::vector idxData); + std::vector idxData, const size_t max_iter); int noise_level; int guess_peaks(std::vector* results, std::vector ampData, @@ -58,8 +58,6 @@ class GaussianFitter{ // *** Fitter parameters (that were magic numbers once) *** - size_t max_iter; - bool tolerance_scales; double x_tolerance; double g_tolerance; @@ -78,7 +76,8 @@ class GaussianFitter{ int solve_system (gsl_vector *x, gsl_multifit_nlinear_fdf *fdf, - gsl_multifit_nlinear_parameters *params, int max); + gsl_multifit_nlinear_parameters *params, int max, + const size_t max_iter); std::vector calculateFirstDifferences(std::vectorampData); void incr_fail(); diff --git a/src/GaussianFitter_unittests.cpp b/src/GaussianFitter_unittests.cpp index 4469c84..a61b10a 100644 --- a/src/GaussianFitter_unittests.cpp +++ b/src/GaussianFitter_unittests.cpp @@ -74,7 +74,7 @@ TEST_F(GaussianFitterTest, NayaniClipped1){ EXPECT_EQ(34 ,peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); @@ -115,7 +115,7 @@ TEST_F(GaussianFitterTest, NayaniClipped2){ EXPECT_EQ(15, peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); @@ -158,7 +158,7 @@ TEST_F(GaussianFitterTest, gaussianFitter){ EXPECT_EQ(8, peaks.at(2)->amp); //this should't be here. fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); @@ -195,7 +195,7 @@ TEST_F(GaussianFitterTest, NayaniClipped3){ EXPECT_EQ(15,peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(2,count); //std::cerr << "--After guess_peaks and find_peaks--\n " << std::endl; @@ -236,7 +236,7 @@ TEST_F(GaussianFitterTest, NayaniClipped4){ EXPECT_EQ(7, peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(2,count); @@ -277,7 +277,7 @@ TEST_F(GaussianFitterTest, NayaniClipped5){ EXPECT_EQ(146,peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(2,count); @@ -322,7 +322,7 @@ TEST_F(GaussianFitterTest, NayaniClipped6){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(5,count); @@ -361,7 +361,7 @@ TEST_F(GaussianFitterTest, NayaniClipped7){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); @@ -400,7 +400,7 @@ TEST_F(GaussianFitterTest, NayaniClipped8){ EXPECT_EQ(21,peaks.at(2)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); @@ -445,7 +445,7 @@ TEST_F(GaussianFitterTest, max_iter_1){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); @@ -484,7 +484,7 @@ TEST_F(GaussianFitterTest, max_iter_2){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); } @@ -521,7 +521,7 @@ TEST_F(GaussianFitterTest, max_iter_3){ EXPECT_EQ(33,peaks.at(2)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); @@ -562,7 +562,7 @@ TEST_F(GaussianFitterTest, max_iter_4){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); } @@ -611,7 +611,7 @@ TEST_F(GaussianFitterTest, max_iter_5){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(8,count); @@ -649,7 +649,7 @@ TEST_F(GaussianFitterTest, trig_loc_1){ EXPECT_EQ(172,peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(2,count); @@ -689,7 +689,7 @@ TEST_F(GaussianFitterTest, trig_loc_2){ fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(3,count); @@ -727,7 +727,7 @@ TEST_F(GaussianFitterTest, num_iterations_10){ EXPECT_EQ(190, peaks.at(1)->amp); fitter.smoothing_expt(&Data); - int count = fitter.find_peaks(&peaks,ampData,idxData); + int count = fitter.find_peaks(&peaks,ampData,idxData,200); EXPECT_EQ(2,count); } diff --git a/src/LidarDriver.cpp b/src/LidarDriver.cpp index efa41f3..b01cea4 100644 --- a/src/LidarDriver.cpp +++ b/src/LidarDriver.cpp @@ -137,7 +137,7 @@ void LidarDriver::fit_data(FlightLineData &raw_data, LidarVolume &fitted_data, // Check parameter for using gaussian fitting or first differencing if (cmdLine.useGaussianFitting) { peak_count = fitter.find_peaks(&peaks, pd.returningWave, - pd.returningIdx); + pd.returningIdx, 200); } else { peak_count = fitter.guess_peaks(&peaks, pd.returningWave, pd.returningIdx); @@ -235,7 +235,7 @@ void LidarDriver::fit_data_csv(FlightLineData &raw_data, // Check parameter for using gaussian fitting or first differencing if (cmdLine.useGaussianFitting) { fitter.find_peaks(&peaks, pd.returningWave, - pd.returningIdx); + pd.returningIdx, 200); } else { fitter.guess_peaks(&peaks, pd.returningWave, pd.returningIdx); @@ -305,7 +305,7 @@ void LidarDriver::fit_data_csv(TxtWaveReader &raw_data, // Check parameter for using gaussian fitting or first differencing if (cmdLine.useGaussianFitting) { fitter.find_peaks(&peaks, raw_data.wave, - raw_data.idx); + raw_data.idx, 200); } else { fitter.guess_peaks(&peaks, raw_data.wave, raw_data.idx); @@ -397,11 +397,8 @@ void LidarDriver::peak_calculations(PulseData &pulse, std::vector &peaks, std::vector emitted_peaks; if (cmdLine.useGaussianFitting){ - size_t oldval = fitter.max_iter; - fitter.max_iter = 10; fitter.find_peaks(&emitted_peaks, pulse.outgoingWave, - pulse.outgoingIdx); - fitter.max_iter = oldval; + pulse.outgoingIdx, 200); } else { fitter.guess_peaks(&emitted_peaks, pulse.outgoingWave, pulse.outgoingIdx); diff --git a/src/PulseData.cpp b/src/PulseData.cpp index a4b59d9..043dbc0 100644 --- a/src/PulseData.cpp +++ b/src/PulseData.cpp @@ -47,28 +47,29 @@ void PulseData::setReturning(std::vector *idxArray, */ void PulseData::displayPulseData(std::ostream *outStream){ - *outStream << "\nOutgoing:\n" << std::endl; - *outStream << "\tindices:" << std::endl; + *outStream << "\nOutgoing:\n\n"; + *outStream << "\tindices:\n"; *outStream << "\t"; for(int i = 0; i<(int)outgoingIdx.size(); i++){ *outStream << outgoingIdx.at(i) << " "; } - *outStream << "\n\tamplitudes:" << std::endl; + *outStream << "\n\tamplitudes:\n"; *outStream << "\t"; for(int i = 0; i<(int)outgoingWave.size(); i++){ *outStream << outgoingWave.at(i) << " "; } - *outStream << "\n\nReturning Wave:\n" << std::endl; - *outStream << "\tindices:" << std::endl; + *outStream << "\n\nReturning Wave:\n\n"; + *outStream << "\tindices:\n"; *outStream << "\t"; for(int i = 0; i<(int)returningIdx.size(); i++){ *outStream << returningIdx.at(i) << " "; } - *outStream << "\n\tamplitudes:" << std::endl; + *outStream << "\n\tamplitudes:\n"; *outStream << "\t"; for(int i = 0; i<(int)returningWave.size(); i++){ *outStream << returningWave.at(i) << " "; } + outStream->flush(); } diff --git a/src/PulseData_unittests.cpp b/src/PulseData_unittests.cpp index 4064e3f..4b3cc18 100644 --- a/src/PulseData_unittests.cpp +++ b/src/PulseData_unittests.cpp @@ -54,11 +54,10 @@ TEST_F(PulseDataTest, testSetterGetter){ streamData = stream.str(); - realStream = "\nOutgoing:\n\n\tindices:\n\t0 1 2 \n\tamplitudes:" - " \n\t34 45 67 \n\nReturning Wave:\n\n\tindices:\n\t0 1 2 \n\t" + realStream = "\nOutgoing:\n\n\tindices:\n\t0 1 2 \n\tamplitudes:\n" + "\t34 45 67 \n\nReturning Wave:\n\n\tindices:\n\t0 1 2 \n\t" "amplitudes:\n\t76 65 43 "; - // testing for string will go here ASSERT_EQ( streamData, realStream); } From 1c86435970b934cce026ffdff4d4beb043a57c1b Mon Sep 17 00:00:00 2001 From: Spencer Fleming Date: Wed, 18 Sep 2019 18:33:42 -0600 Subject: [PATCH 8/8] Added verbosity option to geotiff-driver in case anyone got tired of the verbose log statements --- src/CmdLine.cpp | 33 ++++++++++++++++++++++++++++++--- src/CmdLine.hpp | 6 +++++- src/CmdLine_unittests.cpp | 2 ++ src/pls_to_geotiff.cpp | 24 ++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/CmdLine.cpp b/src/CmdLine.cpp index b91809d..1981aaf 100644 --- a/src/CmdLine.cpp +++ b/src/CmdLine.cpp @@ -16,6 +16,11 @@ const static std::string prod_peaks[3] = {"first", "last", "all"}; const static std::string prod_vars[7] = {"elev", "amp", "width", "riseTime", "backscatter", "heightAtEnergy", "energyAtHeight"}; +//Verbosities +const static int num_verbs = 6; +const static std::string verbs[num_verbs] = {"trace", "debug", "info", "warn", + "error", "critical"}; + const static std::vector start = {0,18,36,54,72,90};//,96,102}; /**************************************************************************** @@ -52,7 +57,7 @@ void CmdLine::setUsageMessage() << " :Disables gaussian fitter, using first diff method instead" << std::endl; buffer << " -h" << " :Prints this help message" << std::endl; - buffer << std::endl; + buffer << std::endl; buffer << "Product Type Options:" << std::endl; buffer << " -e " << " :Generates Elevation products" << std::endl; @@ -68,6 +73,10 @@ void CmdLine::setUsageMessage() buffer << " Scientific notation allowed for calibration constant" << " (e.g. 0.78 = 7.8e-1 = 7.8E-1)" << std::endl; + buffer << " -v " + << " :Sets the level of verbosity for the logger to use" << std::endl; + buffer << " Options are 'trace', 'debug', 'info', 'warn', 'error'" + << ", and 'critical'" << std::endl; buffer << " --all " << " :Generates all products for every variable. calibration constant" << " is used for backscatter coefficient calculations" << std::endl; @@ -124,6 +133,7 @@ CmdLine::CmdLine(){ printUsageMessage = false; useGaussianFitting = true; calcBackscatter = false; + verb = (verbosity) NULL; exeName = ""; setUsageMessage(); } @@ -138,7 +148,18 @@ std::string CmdLine::getInputFileName(bool pls){ return pls ? plsFileName : wvsFileName; } - +/** + * Tries to match option given with verbosity flag to a known value, + * and if so, sets verbosity instance variable to match it. + */ +void CmdLine::set_verbosity (char* new_verb) { + int i; + for (i = 0; i < num_verbs; i++) { + if (!std::strncmp (new_verb, verbs[i].c_str(), 9)) { + verb = (verbosity) i; + } + } +} /** * Function that parses the command line arguments @@ -171,6 +192,7 @@ bool CmdLine::parse_args(int argc,char *argv[]){ {"file", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"firstdiff", no_argument, NULL, 'd'}, + {"verbosity", required_argument, NULL, 'v'}, {"elevation", required_argument,NULL,'e'}, {"amplitude", required_argument,NULL,'a'}, {"width", required_argument,NULL,'w'}, @@ -188,7 +210,7 @@ bool CmdLine::parse_args(int argc,char *argv[]){ * ":hf:s:" indicate that option 'h' is without arguments while * option 'f' and 's' require arguments */ - while((optionChar = getopt_long (argc, argv, "-:hdf:e:a:w:r:b:l:", + while((optionChar = getopt_long (argc, argv, "-:hdf:e:a:w:r:b:l:v:", long_options, &option_index))!= -1){ if (optionChar == 'f') { //Set the filename to parse fArg = optarg; @@ -197,6 +219,11 @@ bool CmdLine::parse_args(int argc,char *argv[]){ printUsageMessage = true; } else if (optionChar == 'd') { //Sets analysis method useGaussianFitting = false; + } else if (optionChar == 'v') { + set_verbosity(optarg); + if (verb == (verbosity) NULL) { + printUsageMessage = true; + } } else if (optionChar == 'e' || optionChar == 'a' || optionChar == 'w' || optionChar == 'r' || optionChar == 'b'){ //Sets which pruducts to create and for which variable diff --git a/src/CmdLine.hpp b/src/CmdLine.hpp index a043364..e4e7023 100644 --- a/src/CmdLine.hpp +++ b/src/CmdLine.hpp @@ -31,7 +31,7 @@ class CmdLine{ // else, use smooth second difference bool max_elev_flag; - + void set_verbosity(char* new_verb); public: //calibration constant (for backscatter option) @@ -49,6 +49,10 @@ class CmdLine{ //True stifles all output statements bool quiet; + // For conveying verbosity to main function in a readable way + enum verbosity { trace, debug, info, warn, error, critical }; + verbosity verb; + CmdLine(); diff --git a/src/CmdLine_unittests.cpp b/src/CmdLine_unittests.cpp index 3e61525..9d2812d 100644 --- a/src/CmdLine_unittests.cpp +++ b/src/CmdLine_unittests.cpp @@ -305,6 +305,8 @@ TEST_F(CmdLineTest, invalidNonProductOption){ ASSERT_TRUE(cmd.printUsageMessage); } +//Tests that verbosity is set to the correct value by the -v option + /**************************************************************************** * * Long Option Tests diff --git a/src/pls_to_geotiff.cpp b/src/pls_to_geotiff.cpp index 46cbd15..0187d88 100644 --- a/src/pls_to_geotiff.cpp +++ b/src/pls_to_geotiff.cpp @@ -31,6 +31,30 @@ int main (int argc, char *argv[]) { return 1; } + // Set verbosity if not null + if (cmdLineArgs.verb != (CmdLine::verbosity) NULL) { + switch (cmdLineArgs.verb) { + case CmdLine::verbosity::trace: + spdlog::set_level(spdlog::level::trace); + break; + case CmdLine::verbosity::debug: + spdlog::set_level(spdlog::level::debug); + break; + case CmdLine::verbosity::info: + spdlog::set_level(spdlog::level::info); + break; + case CmdLine::verbosity::warn: + spdlog::set_level(spdlog::level::warn); + break; + case CmdLine::verbosity::error: + spdlog::set_level(spdlog::level::err); + break; + case CmdLine::verbosity::critical: + spdlog::set_level(spdlog::level::critical); + break; + } + } + //Collect start time Clock::time_point t1 = Clock::now();