From 559a9a7c43b6ca1e152d889cf293bae848ce63ca Mon Sep 17 00:00:00 2001
From: Carles Fernandez <carles.fernandez@gmail.com>
Date: Sun, 24 Jun 2018 11:05:58 +0200
Subject: [PATCH] Fix problem caused by hdf5 when saving concurrently

Only one acquisition channel info is stored in dump file if dump is activated. New configuration parameter dump_channel, set to 0 by default.
Name of Matlab variable changed from gird to acq_grid to not overlap Matlab command.
---
 .../galileo_e1_pcps_ambiguous_acquisition.cc  |  1 +
 .../adapters/galileo_e5a_pcps_acquisition.cc  |  1 +
 .../glonass_l1_ca_pcps_acquisition.cc         |  1 +
 .../glonass_l2_ca_pcps_acquisition.cc         |  1 +
 .../adapters/gps_l1_ca_pcps_acquisition.cc    |  1 +
 .../adapters/gps_l2_m_pcps_acquisition.cc     |  1 +
 .../adapters/gps_l5i_pcps_acquisition.cc      |  1 +
 .../gnuradio_blocks/pcps_acquisition.cc       | 13 +++--
 .../gnuradio_blocks/pcps_acquisition.h        |  1 +
 src/algorithms/acquisition/libs/acq_conf.cc   |  1 +
 src/algorithms/acquisition/libs/acq_conf.h    |  1 +
 .../gps_l1_ca_pcps_acquisition_test.cc        |  1 +
 .../gps_l2_m_pcps_acquisition_test.cc         |  7 +--
 .../libs/acquisition_dump_reader.cc           | 53 ++++++++++++++++++-
 .../libs/acquisition_dump_reader.h            |  7 +++
 src/utils/matlab/plot_acq_grid.m              |  3 +-
 16 files changed, 84 insertions(+), 10 deletions(-)

diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc
index a9f96da43..3dedecfff 100644
--- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc
@@ -60,6 +60,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
     acq_parameters.fs_in = fs_in_;
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     blocking_ = configuration_->property(role + ".blocking", true);
     acq_parameters.blocking = blocking_;
     doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc
index 16142eab9..203f8b58b 100644
--- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc
@@ -65,6 +65,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
         }
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
     if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
     acq_parameters.doppler_max = doppler_max_;
diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc
index c49f1f0c4..29fc072fb 100644
--- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc
@@ -61,6 +61,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
     acq_parameters.fs_in = fs_in_;
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     blocking_ = configuration_->property(role + ".blocking", true);
     acq_parameters.blocking = blocking_;
     doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
diff --git a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc
index ec17ad911..5222e0ad8 100644
--- a/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/glonass_l2_ca_pcps_acquisition.cc
@@ -60,6 +60,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
     acq_parameters.fs_in = fs_in_;
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     blocking_ = configuration_->property(role + ".blocking", true);
     acq_parameters.blocking = blocking_;
     doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc
index 45a8d743c..f3bc7dcb2 100644
--- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc
@@ -62,6 +62,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
     acq_parameters.fs_in = fs_in_;
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     blocking_ = configuration_->property(role + ".blocking", true);
     acq_parameters.blocking = blocking_;
     doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc
index bb185c92c..2da535b82 100644
--- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc
@@ -62,6 +62,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
     acq_parameters.fs_in = fs_in_;
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     blocking_ = configuration_->property(role + ".blocking", true);
     acq_parameters.blocking = blocking_;
     doppler_max_ = configuration->property(role + ".doppler_max", 5000);
diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc
index 4595bd2e2..94d9356ad 100644
--- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc
+++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition.cc
@@ -61,6 +61,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
     acq_parameters.fs_in = fs_in_;
     dump_ = configuration_->property(role + ".dump", false);
     acq_parameters.dump = dump_;
+    acq_parameters.dump_channel = configuration_->property(role + ".dump_channel", 0);
     blocking_ = configuration_->property(role + ".blocking", true);
     acq_parameters.blocking = blocking_;
     doppler_max_ = configuration->property(role + ".doppler_max", 5000);
diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc
index cf38db852..76adfc28c 100644
--- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc
+++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.cc
@@ -123,6 +123,7 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
     grid_ = arma::fmat();
     d_step_two = false;
     d_dump_number = 0;
+    d_dump_channel = acq_parameters.dump_channel;
 }
 
 
@@ -363,7 +364,7 @@ void pcps_acquisition::dump_results(int effective_fft_size)
     else
         {
             size_t dims[2] = {static_cast<size_t>(effective_fft_size), static_cast<size_t>(d_num_doppler_bins)};
-            matvar_t* matvar = Mat_VarCreate("grid", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, grid_.memptr(), 0);
+            matvar_t* matvar = Mat_VarCreate("acq_grid", MAT_C_SINGLE, MAT_T_SINGLE, 2, dims, grid_.memptr(), 0);
             Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB);  // or MAT_COMPRESSION_NONE
             Mat_VarFree(matvar);
 
@@ -407,6 +408,10 @@ void pcps_acquisition::dump_results(int effective_fft_size)
             Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB);  // or MAT_COMPRESSION_NONE
             Mat_VarFree(matvar);
 
+            matvar = Mat_VarCreate("PRN", MAT_C_UINT32, MAT_T_UINT32, 1, dims, &d_gnss_synchro->PRN, 0);
+            Mat_VarWrite(matfp, matvar, MAT_COMPRESSION_ZLIB);  // or MAT_COMPRESSION_NONE
+            Mat_VarFree(matvar);
+
             Mat_Close(matfp);
         }
 }
@@ -510,7 +515,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
                                 }
                         }
                     // Record results to file if required
-                    if (acq_parameters.dump)
+                    if (acq_parameters.dump and d_channel == d_dump_channel)
                         {
                             memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size);
                         }
@@ -579,7 +584,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
                                 }
                         }
                     // Record results to file if required
-                    if (acq_parameters.dump)
+                    if (acq_parameters.dump and d_channel == d_dump_channel)
                         {
                             memcpy(grid_.colptr(doppler_index), d_magnitude, sizeof(float) * effective_fft_size);
                         }
@@ -653,7 +658,7 @@ void pcps_acquisition::acquisition_core(unsigned long int samp_count)
         }
     d_worker_active = false;
     // Record results to file if required
-    if (acq_parameters.dump)
+    if (acq_parameters.dump and d_channel == d_dump_channel)
         {
             pcps_acquisition::dump_results(effective_fft_size);
         }
diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h
index d34888fd8..91bfaf112 100644
--- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h
+++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition.h
@@ -125,6 +125,7 @@ private:
     Gnss_Synchro* d_gnss_synchro;
     arma::fmat grid_;
     long int d_dump_number;
+    unsigned int d_dump_channel;
 
 public:
     ~pcps_acquisition();
diff --git a/src/algorithms/acquisition/libs/acq_conf.cc b/src/algorithms/acquisition/libs/acq_conf.cc
index f403992e4..f44f7a15f 100644
--- a/src/algorithms/acquisition/libs/acq_conf.cc
+++ b/src/algorithms/acquisition/libs/acq_conf.cc
@@ -48,5 +48,6 @@ Acq_Conf::Acq_Conf()
     blocking = false;
     make_2_steps = false;
     dump_filename = "";
+    dump_channel = 0;
     it_size = sizeof(char);
 }
diff --git a/src/algorithms/acquisition/libs/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h
index 422e889bc..7abcb2e98 100644
--- a/src/algorithms/acquisition/libs/acq_conf.h
+++ b/src/algorithms/acquisition/libs/acq_conf.h
@@ -53,6 +53,7 @@ public:
     bool blocking;
     bool make_2_steps;
     std::string dump_filename;
+    unsigned int dump_channel;
     size_t it_size;
 
     Acq_Conf();
diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc
index d2c5a96c9..332dcc0e4 100644
--- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc
+++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc
@@ -160,6 +160,7 @@ void GpsL1CaPcpsAcquisitionTest::init()
             config->set_property("Acquisition_1C.dump", "false");
         }
     config->set_property("Acquisition_1C.dump_filename", "./tmp-acq-gps1/acquisition");
+    config->set_property("Acquisition_1C.dump_channel", "1");
     config->set_property("Acquisition_1C.threshold", "0.00001");
     config->set_property("Acquisition_1C.doppler_max", std::to_string(doppler_max));
     config->set_property("Acquisition_1C.doppler_step", std::to_string(doppler_step));
diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc
index 31e6e60ab..9d6caf0e6 100644
--- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc
+++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l2_m_pcps_acquisition_test.cc
@@ -163,7 +163,8 @@ void GpsL2MPcpsAcquisitionTest::init()
         {
             config->set_property("Acquisition_2S.dump", "false");
         }
-    config->set_property("Acquisition_2S.dump_filename", "./tmp-acq-gps2/acquisition");
+    config->set_property("Acquisition_2S.dump_filename", "./tmp-acq-gps2/acquisition_test");
+    config->set_property("Acquisition_2S.dump_channel", "1");
     config->set_property("Acquisition_2S.threshold", "0.001");
     config->set_property("Acquisition_2S.doppler_max", std::to_string(doppler_max));
     config->set_property("Acquisition_2S.doppler_step", std::to_string(doppler_step));
@@ -175,11 +176,11 @@ void GpsL2MPcpsAcquisitionTest::init()
 void GpsL2MPcpsAcquisitionTest::plot_grid()
 {
     //load the measured values
-    std::string basename = "./tmp-acq-gps2/acquisition_G_2S";
+    std::string basename = "./tmp-acq-gps2/acquisition_test_G_2S";
     unsigned int sat = static_cast<unsigned int>(gnss_synchro.PRN);
 
     unsigned int samples_per_code = static_cast<unsigned int>(floor(static_cast<double>(sampling_frequency_hz) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS))));
-    acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code);
+    acquisition_dump_reader acq_dump(basename, sat, doppler_max, doppler_step, samples_per_code, 1);
     if (!acq_dump.read_binary_acq()) std::cout << "Error reading files" << std::endl;
 
     std::vector<int> *doppler = &acq_dump.doppler;
diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc
index 063d02837..8cb81718b 100644
--- a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc
+++ b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.cc
@@ -43,7 +43,7 @@ bool acquisition_dump_reader::read_binary_acq()
             std::cout << "¡¡¡Unreachable Acquisition dump file!!!" << std::endl;
             return false;
         }
-    matvar_t* var_ = Mat_VarRead(matfile, "grid");
+    matvar_t* var_ = Mat_VarRead(matfile, "acq_grid");
     if (var_ == NULL)
         {
             std::cout << "¡¡¡Unreachable grid variable into Acquisition dump file!!!" << std::endl;
@@ -109,15 +109,20 @@ bool acquisition_dump_reader::read_binary_acq()
     positive_acq = *static_cast<int*>(var2_->data);
     Mat_VarFree(var2_);
 
+    var2_ = Mat_VarRead(matfile, "PRN");
+    PRN = *static_cast<int*>(var2_->data);
+    Mat_VarFree(var2_);
+
     std::vector<std::vector<float> >::iterator it1;
     std::vector<float>::iterator it2;
     float* aux = static_cast<float*>(var_->data);
     int k = 0;
+    float normalization_factor = std::pow(d_samples_per_code, 4) * input_power;
     for (it1 = mag.begin(); it1 != mag.end(); it1++)
         {
             for (it2 = it1->begin(); it2 != it1->end(); it2++)
                 {
-                    *it2 = static_cast<float>(aux[k]) / input_power;
+                    *it2 = static_cast<float>(aux[k]) / normalization_factor;
                     k++;
                 }
         }
@@ -128,6 +133,49 @@ bool acquisition_dump_reader::read_binary_acq()
 }
 
 
+acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
+    int channel,
+    int execution)
+{
+    unsigned int sat_ = 0;
+    unsigned int doppler_max_ = 0;
+    unsigned int doppler_step_ = 0;
+    unsigned int samples_per_code_ = 0;
+
+    mat_t* matfile = Mat_Open(d_dump_filename.c_str(), MAT_ACC_RDONLY);
+    if (matfile != NULL)
+        {
+            matvar_t* var_ = Mat_VarRead(matfile, "doppler_max");
+            doppler_max_ = *static_cast<unsigned int*>(var_->data);
+            Mat_VarFree(var_);
+
+            var_ = Mat_VarRead(matfile, "doppler_step");
+            doppler_step_ = *static_cast<unsigned int*>(var_->data);
+            Mat_VarFree(var_);
+
+            var_ = Mat_VarRead(matfile, "PRN");
+            sat_ = *static_cast<int*>(var_->data);
+            Mat_VarFree(var_);
+
+            var_ = Mat_VarRead(matfile, "grid");
+            samples_per_code_ = var_->dims[0];
+            Mat_VarFree(var_);
+
+            Mat_Close(matfile);
+        }
+    else
+        {
+            std::cout << "¡¡¡Unreachable Acquisition dump file!!!" << std::endl;
+        }
+    acquisition_dump_reader(basename,
+        sat_,
+        doppler_max_,
+        doppler_step_,
+        samples_per_code_,
+        channel,
+        execution);
+}
+
 acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
     unsigned int sat,
     unsigned int doppler_max,
@@ -148,6 +196,7 @@ acquisition_dump_reader::acquisition_dump_reader(const std::string& basename,
     threshold = 0.0;
     positive_acq = 0;
     sample_counter = 0;
+    PRN = 0;
     d_num_doppler_bins = static_cast<unsigned int>(ceil(static_cast<double>(static_cast<int>(d_doppler_max) - static_cast<int>(-d_doppler_max)) / static_cast<double>(d_doppler_step)));
     std::vector<std::vector<float> > mag_aux(d_num_doppler_bins, std::vector<float>(d_samples_per_code));
     mag = mag_aux;
diff --git a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h
index 3f6b40365..3958b98b2 100644
--- a/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h
+++ b/src/tests/unit-tests/signal-processing-blocks/libs/acquisition_dump_reader.h
@@ -45,7 +45,13 @@ public:
         unsigned int samples_per_code,
         int channel = 0,
         int execution = 1);
+
+    acquisition_dump_reader(const std::string& basename,
+        int channel = 0,
+        int execution = 1);
+
     ~acquisition_dump_reader();
+
     bool read_binary_acq();
 
     std::vector<int> doppler;
@@ -57,6 +63,7 @@ public:
     float input_power;
     float threshold;
     int positive_acq;
+    unsigned int PRN;
     long unsigned int sample_counter;
 
 private:
diff --git a/src/utils/matlab/plot_acq_grid.m b/src/utils/matlab/plot_acq_grid.m
index 182c09b02..86a710e76 100644
--- a/src/utils/matlab/plot_acq_grid.m
+++ b/src/utils/matlab/plot_acq_grid.m
@@ -107,7 +107,8 @@ xlabel('Doppler shift / Hz')
 ylabel('Test statistics')
 title(['Fixed code delay to ' num2str((d_max - 1) / n_fft * n_chips) ' chips'])
 subplot(2,1,2)
-plot(delay, grid(:, f_max))
+normalization = (d_samples_per_code^4) * input_power;
+plot(delay, acq_grid(:, f_max)./normalization)
 xlim([min(delay) max(delay)])
 xlabel('Code delay / chips')
 ylabel('Test statistics')