diff --git a/corsika/detail/modules/radio/CoREAS.inl b/corsika/detail/modules/radio/CoREAS.inl
index 9f25ae97265f97cddf955f19ad2eee0c199c01b8..f79a0f8d77f0d23a3e78a4165bbd3ef2485f06d3 100644
--- a/corsika/detail/modules/radio/CoREAS.inl
+++ b/corsika/detail/modules/radio/CoREAS.inl
@@ -23,11 +23,9 @@ namespace corsika {
                             // should use something similar to fCoreHitTime (?)
     auto const endTime_{step.getTimePost()}; // time at end point of track.
 
-    // LCOV_EXCL_START
     if (startTime_ == endTime_) {
       CORSIKA_LOG_ERROR("Time at the start and end of the track coincides! - radio");
       return ProcessReturn::Ok;
-      // LCOV_EXCL_STOP
     } else {
 
       // get start and end position of the track
@@ -66,281 +64,191 @@ namespace corsika {
         // get the SignalPathCollection (path2) from the end "endpoint" to the antenna.
         auto paths2{this->propagator_.propagate(endPoint_, antenna.getLocation(), 1_m)};
 
-        // throw an exception if path sizes don't match
-        try {
-          // loop over both paths at once and directly compare 'start' and 'end'
-          // attributes
-          for (size_t i = (paths1.size() == paths2.size()) ? 0 : throw(i = paths1.size());
-               (i < paths1.size() && i < paths2.size()); i++) {
-
-            // calculate preDoppler factor
-            double preDoppler_{1.0 - paths1[i].refractive_index_source_ *
-                                         beta_.dot(paths1[i].emit_)};
-
-            // check if preDoppler has become zero in case of refractive index of unity
-            // because of numerical limitations here you might need std::fabs(preDoppler)
-            // in the if statement - same with post & mid
-            // LCOV_EXCL_START
-            if (preDoppler_ == 0) {
-              CORSIKA_LOG_WARN("preDoppler factor numerically zero in COREAS");
-              // redo calculation with higher precision
-              auto const& beta_components_{beta_.getComponents(cs_)};
-              auto const& emit_components_{paths1[i].emit_.getComponents(cs_)};
-              long double const indexL_{paths1[i].refractive_index_source_};
-              long double const betaX_{static_cast<double>(beta_components_.getX())};
-              long double const betaY_{static_cast<double>(beta_components_.getY())};
-              long double const betaZ_{static_cast<double>(beta_components_.getZ())};
-              long double const startX_{static_cast<double>(emit_components_.getX())};
-              long double const startY_{static_cast<double>(emit_components_.getY())};
-              long double const startZ_{static_cast<double>(emit_components_.getZ())};
-              long double const doppler =
-                  1.0l -
-                  indexL_ * (betaX_ * startX_ + betaY_ * startY_ + betaZ_ * startZ_);
-              preDoppler_ = doppler;
-            }
-            // LCOV_EXCL_STOP
-
-            // calculate postDoppler factor
-            double postDoppler_{1.0 - paths2[i].refractive_index_source_ *
-                                          beta_.dot(paths2[i].emit_)};
-
-            // check if postDoppler has become zero in case of refractive index of unity
-            // because of numerical limitations
-            // LCOV_EXCL_START
-            if (postDoppler_ == 0) {
-              CORSIKA_LOG_WARN("postDoppler factor numerically zero in CoREAS");
-              // redo calculation with higher precision
-              auto const& beta_components_{beta_.getComponents(cs_)};
-              auto const& emit_components_{paths2[i].emit_.getComponents(cs_)};
-              long double const indexL_{paths2[i].refractive_index_source_};
-              long double const betaX_{static_cast<double>(beta_components_.getX())};
-              long double const betaY_{static_cast<double>(beta_components_.getY())};
-              long double const betaZ_{static_cast<double>(beta_components_.getZ())};
-              long double const endX_{static_cast<double>(emit_components_.getX())};
-              long double const endY_{static_cast<double>(emit_components_.getY())};
-              long double const endZ_{static_cast<double>(emit_components_.getZ())};
-              long double const doppler =
-                  1.0l - indexL_ * (betaX_ * endX_ + betaY_ * endY_ + betaZ_ * endZ_);
-              postDoppler_ = doppler;
-            }
-            // LCOV_EXCL_STOP
-
-            // calculate receive time for startpoint (aka time delay)
-            auto startPointReceiveTime_{
-                startTime_ +
-                paths1[i].propagation_time_}; // TODO: time 0 is when the imaginary
-                                              // primary hits the ground
-
-            // calculate receive time for endpoint
-            auto endPointReceiveTime_{endTime_ + paths2[i].propagation_time_};
-
-            // get unit vector for startpoint at antenna location
-            auto ReceiveVectorStart_{paths1[i].receive_};
-
-            // get unit vector for endpoint at antenna location
-            auto ReceiveVectorEnd_{paths2[i].receive_};
-
-            // perform ZHS-like calculation close to Cherenkov angle and for refractive
-            // index at antenna location greater than 1
-            if ((paths1[i].refractive_index_destination_ > 1) &&
-                ((std::fabs(preDoppler_) < approxThreshold_) ||
-                 (std::fabs(postDoppler_) < approxThreshold_))) {
-              CORSIKA_LOG_DEBUG("Used ZHS-like approximation in CoREAS - radio");
-
-              // clear the existing paths for this particle and track, since we don't need
-              // them anymore
-              paths1.clear();
-              paths2.clear();
-
-              auto const halfVector_{(startPoint_ - endPoint_) * 0.5};
-              auto const midPoint_{endPoint_ + halfVector_};
-
-              // get global simulation time for the middle point of that track.
-              TimeType const midTime_{(startTime_ + endTime_) * 0.5};
-
-              // get the SignalPathCollection (path3) from the middle "endpoint" to the
-              // antenna.
-              auto paths3{
-                  this->propagator_.propagate(midPoint_, antenna.getLocation(), 1_m)};
-
-              // now loop over the paths for endpoint that we got above
-              for (auto const& path : paths3) {
-
-                auto const midPointReceiveTime_{midTime_ + path.propagation_time_};
-                double midDoppler_{1.0 -
-                                   path.refractive_index_source_ * beta_.dot(path.emit_)};
-
-                // check if midDoppler has become zero because of numerical limitations
-                // LCOV_EXCL_START
-                if (midDoppler_ == 0) {
-                  CORSIKA_LOG_WARN("midDoppler factor numerically zero in COREAS");
-                  // redo calculation with higher precision
-                  auto const& beta_components_{beta_.getComponents(cs_)};
-                  auto const& emit_components_{path.emit_.getComponents(cs_)};
-                  long double const indexL_{path.refractive_index_source_};
-                  long double const betaX_{static_cast<double>(beta_components_.getX())};
-                  long double const betaY_{static_cast<double>(beta_components_.getY())};
-                  long double const betaZ_{static_cast<double>(beta_components_.getZ())};
-                  long double const midX_{static_cast<double>(emit_components_.getX())};
-                  long double const midY_{static_cast<double>(emit_components_.getY())};
-                  long double const midZ_{static_cast<double>(emit_components_.getZ())};
-                  long double const doppler =
-                      1.0l - indexL_ * (betaX_ * midX_ + betaY_ * midY_ + betaZ_ * midZ_);
-                  midDoppler_ = doppler;
-                }
-                // LCOV_EXCL_STOP
-
-                // change the values of the receive unit vectors of start and end
-                ReceiveVectorStart_ = path.receive_;
-                ReceiveVectorEnd_ = path.receive_;
-
-                // CoREAS calculation -> get ElectricFieldVector for "midPoint"
-                ElectricFieldVector EVmid_ = (path.emit_.cross(path.emit_.cross(beta_))) /
-                                             midDoppler_ / path.R_distance_ * constants_ *
-                                             antenna.getSampleRate();
-
-                ElectricFieldVector EV1_{EVmid_};
-                ElectricFieldVector EV2_{EVmid_ * (-1.0)};
-
-                TimeType deltaT_{tracklength_ / (constants::c * corrBetaValue) *
-                                 std::fabs(midDoppler_)}; // TODO: Caution with this!
-
-                if (startPointReceiveTime_ <
-                    endPointReceiveTime_) // EVstart_ arrives earlier
-                {
-                  startPointReceiveTime_ = midPointReceiveTime_ - 0.5 * deltaT_;
-                  endPointReceiveTime_ = midPointReceiveTime_ + 0.5 * deltaT_;
-                } else // EVend_ arrives earlier
-                {
-                  startPointReceiveTime_ = midPointReceiveTime_ + 0.5 * deltaT_;
-                  endPointReceiveTime_ = midPointReceiveTime_ - 0.5 * deltaT_;
-                }
-
-                TimeType const gridResolution_{1 / antenna.getSampleRate()};
-                deltaT_ = endPointReceiveTime_ - startPointReceiveTime_;
-
-                // redistribute contributions over time scale defined by the observation
-                // time resolution
-                if (abs(deltaT_) < (gridResolution_)) {
-
-                  EV1_ *= std::fabs((deltaT_ / gridResolution_));
-                  EV2_ *= std::fabs((deltaT_ / gridResolution_));
-
-                  // ToDO: be careful with times in C8!!! where is the zero (time). Is it
-                  // close-by?
-                  long const startBin = static_cast<long>(
-                      std::floor(startPointReceiveTime_ / gridResolution_ + 0.5l));
-                  long const endBin = static_cast<long>(
-                      std::floor(endPointReceiveTime_ / gridResolution_ + 0.5l));
-                  double const startBinFraction =
-                      (startPointReceiveTime_ / gridResolution_) -
-                      std::floor(startPointReceiveTime_ / gridResolution_);
-                  double const endBinFraction =
-                      (endPointReceiveTime_ / gridResolution_) -
-                      std::floor(endPointReceiveTime_ / gridResolution_);
-
-                  // only do timing modification if contributions would land in same bin
-                  if (startBin == endBin) {
-
-                    // if startE arrives before endE
-                    if ((deltaT_) >= 0_s) {
-                      if ((startBinFraction >= 0.5) &&
-                          (endBinFraction >= 0.5)) // both points left of bin center
-                      {
-                        startPointReceiveTime_ -=
-                            gridResolution_; // shift EV1_ to previous gridpoint
-                      } else if ((startBinFraction < 0.5) &&
-                                 (endBinFraction <
-                                  0.5)) // both points right of bin center
-                      {
-                        endPointReceiveTime_ +=
-                            gridResolution_; // shift EV2_ to next gridpoint
-                      } else                 // points on both sides of bin center
-                      {
-                        double const leftDist = 1.0 - startBinFraction;
-                        double const rightDist = endBinFraction;
-                        // check if asymmetry to right or left
-                        if (rightDist >= leftDist) {
-                          endPointReceiveTime_ +=
-                              gridResolution_; // shift EV2_ to next gridpoint
-                        } else {
-                          startPointReceiveTime_ -=
-                              gridResolution_; // shift EV1_ to previous gridpoint
-                        }
-                      }
-                    } else // if endE arrives before startE
-                    {
-                      if ((startBinFraction >= 0.5) &&
-                          (endBinFraction >= 0.5)) // both points left of bin center
-                      {
-                        endPointReceiveTime_ -=
-                            gridResolution_; // shift EV2_ to previous gridpoint
-                      } else if ((startBinFraction < 0.5) &&
-                                 (endBinFraction <
-                                  0.5)) // both points right of bin center
-                      {
-                        startPointReceiveTime_ +=
-                            gridResolution_; // shift EV1_ to next gridpoint
-                      } else                 // points on both sides of bin center
-                      {
-                        double const leftDist = 1.0 - endBinFraction;
-                        double const rightDist = startBinFraction;
-                        // check if asymmetry to right or left
-                        if (rightDist >= leftDist) {
-                          startPointReceiveTime_ +=
-                              gridResolution_; // shift EV1_ to next gridpoint
-                        } else {
-                          endPointReceiveTime_ -=
-                              gridResolution_; // shift EV2_ to previous gridpoint
-                        }
-                      }
-                    } // End of else statement
-                  }   // End of if for startbin == endbin
-                }     // End of if deltaT < gridresolution
-
-                // TODO: Be very careful with this. Maybe the EVs should be fed after the
-                // for loop of paths3
-                antenna.receive(startPointReceiveTime_, ReceiveVectorStart_, EV1_);
-                antenna.receive(endPointReceiveTime_, ReceiveVectorEnd_, EV2_);
-              } // End of looping over paths3
-
-            } // end of ZHS-like approximation
-            else {
-
-              // calculate electric field vector for startpoint
-              ElectricFieldVector EV1_ =
-                  (paths1[i].emit_.cross(paths1[i].emit_.cross(beta_))) / preDoppler_ /
-                  paths1[i].R_distance_ * constants_ * antenna.getSampleRate();
-
-              // calculate electric field vector for endpoint
-              ElectricFieldVector EV2_ =
-                  (paths2[i].emit_.cross(paths2[i].emit_.cross(beta_))) / postDoppler_ /
-                  paths2[i].R_distance_ * constants_ * (-1.0) * antenna.getSampleRate();
-
-              if ((preDoppler_ < 1.e-9) || (postDoppler_ < 1.e-9)) {
-
-                TimeType const gridResolution_{1 / antenna.getSampleRate()};
-                TimeType deltaT_{endPointReceiveTime_ - startPointReceiveTime_};
-
-                if (abs(deltaT_) < (gridResolution_)) {
-
-                  EV1_ *= std::fabs(deltaT_ / gridResolution_); // Todo: rename EV1 and 2
-                  EV2_ *= std::fabs(deltaT_ / gridResolution_);
-
-                  long const startBin = static_cast<long>(
-                      std::floor(startPointReceiveTime_ / gridResolution_ + 0.5l));
-                  long const endBin = static_cast<long>(
-                      std::floor(endPointReceiveTime_ / gridResolution_ + 0.5l));
-                  double const startBinFraction =
-                      (startPointReceiveTime_ / gridResolution_) -
-                      std::floor(startPointReceiveTime_ / gridResolution_);
-                  double const endBinFraction =
-                      (endPointReceiveTime_ / gridResolution_) -
-                      std::floor(endPointReceiveTime_ / gridResolution_);
-
-                  // only do timing modification if contributions would land in same bin
-                  if (startBin == endBin) {
+        // LCOV_EXCL_START
+        // This should never happen unless someone implements a bad propagator
+        // good to catch this, hard to test without writing a custom and broken propagator
+        if (paths1.size() != paths2.size()) {
+          CORSIKA_LOG_CRITICAL(
+              "Signal Paths do not have the same size in CoREAS. Path starts: {} and "
+              "path ends: {}",
+              paths1.size(), paths2.size());
+        }
+        // LCOV_EXCL_STOP
 
+        // loop over both paths at once and directly compare 'start' and 'end'
+        // attributes
+        for (size_t i = 0; (i < paths1.size() && i < paths2.size()); i++) {
+
+          // calculate preDoppler factor
+          double preDoppler_{1.0 - paths1[i].refractive_index_source_ *
+                                       beta_.dot(paths1[i].emit_)};
+
+          // check if preDoppler has become zero in case of refractive index of unity
+          // because of numerical limitations here you might need std::fabs(preDoppler)
+          // in the if statement - same with post & mid
+          // LCOV_EXCL_START
+          if (preDoppler_ == 0) {
+            CORSIKA_LOG_WARN("preDoppler factor numerically zero in COREAS");
+            // redo calculation with higher precision
+            auto const& beta_components_{beta_.getComponents(cs_)};
+            auto const& emit_components_{paths1[i].emit_.getComponents(cs_)};
+            long double const indexL_{paths1[i].refractive_index_source_};
+            long double const betaX_{static_cast<double>(beta_components_.getX())};
+            long double const betaY_{static_cast<double>(beta_components_.getY())};
+            long double const betaZ_{static_cast<double>(beta_components_.getZ())};
+            long double const startX_{static_cast<double>(emit_components_.getX())};
+            long double const startY_{static_cast<double>(emit_components_.getY())};
+            long double const startZ_{static_cast<double>(emit_components_.getZ())};
+            long double const doppler =
+                1.0l - indexL_ * (betaX_ * startX_ + betaY_ * startY_ + betaZ_ * startZ_);
+            preDoppler_ = doppler;
+          }
+          // LCOV_EXCL_STOP
+
+          // calculate postDoppler factor
+          double postDoppler_{1.0 - paths2[i].refractive_index_source_ *
+                                        beta_.dot(paths2[i].emit_)};
+
+          // check if postDoppler has become zero in case of refractive index of unity
+          // because of numerical limitations
+          // LCOV_EXCL_START
+          if (postDoppler_ == 0) {
+            CORSIKA_LOG_WARN("postDoppler factor numerically zero in CoREAS");
+            // redo calculation with higher precision
+            auto const& beta_components_{beta_.getComponents(cs_)};
+            auto const& emit_components_{paths2[i].emit_.getComponents(cs_)};
+            long double const indexL_{paths2[i].refractive_index_source_};
+            long double const betaX_{static_cast<double>(beta_components_.getX())};
+            long double const betaY_{static_cast<double>(beta_components_.getY())};
+            long double const betaZ_{static_cast<double>(beta_components_.getZ())};
+            long double const endX_{static_cast<double>(emit_components_.getX())};
+            long double const endY_{static_cast<double>(emit_components_.getY())};
+            long double const endZ_{static_cast<double>(emit_components_.getZ())};
+            long double const doppler =
+                1.0l - indexL_ * (betaX_ * endX_ + betaY_ * endY_ + betaZ_ * endZ_);
+            postDoppler_ = doppler;
+          }
+          // LCOV_EXCL_STOP
+
+          // calculate receive time for startpoint (aka time delay)
+          auto startPointReceiveTime_{
+              startTime_ +
+              paths1[i].propagation_time_}; // TODO: time 0 is when the imaginary
+                                            // primary hits the ground
+
+          // calculate receive time for endpoint
+          auto endPointReceiveTime_{endTime_ + paths2[i].propagation_time_};
+
+          // get unit vector for startpoint at antenna location
+          auto ReceiveVectorStart_{paths1[i].receive_};
+
+          // get unit vector for endpoint at antenna location
+          auto ReceiveVectorEnd_{paths2[i].receive_};
+
+          // perform ZHS-like calculation close to Cherenkov angle and for refractive
+          // index at antenna location greater than 1
+          if ((paths1[i].refractive_index_destination_ > 1) &&
+              ((std::fabs(preDoppler_) < approxThreshold_) ||
+               (std::fabs(postDoppler_) < approxThreshold_))) {
+            CORSIKA_LOG_DEBUG("Used ZHS-like approximation in CoREAS - radio");
+
+            // clear the existing paths for this particle and track, since we don't need
+            // them anymore
+            paths1.clear();
+            paths2.clear();
+
+            auto const halfVector_{(startPoint_ - endPoint_) * 0.5};
+            auto const midPoint_{endPoint_ + halfVector_};
+
+            // get global simulation time for the middle point of that track.
+            TimeType const midTime_{(startTime_ + endTime_) * 0.5};
+
+            // get the SignalPathCollection (path3) from the middle "endpoint" to the
+            // antenna.
+            auto paths3{
+                this->propagator_.propagate(midPoint_, antenna.getLocation(), 1_m)};
+
+            // now loop over the paths for endpoint that we got above
+            for (auto const& path : paths3) {
+
+              auto const midPointReceiveTime_{midTime_ + path.propagation_time_};
+              double midDoppler_{1.0 -
+                                 path.refractive_index_source_ * beta_.dot(path.emit_)};
+
+              // check if midDoppler has become zero because of numerical limitations
+              // LCOV_EXCL_START
+              if (midDoppler_ == 0) {
+                CORSIKA_LOG_WARN("midDoppler factor numerically zero in COREAS");
+                // redo calculation with higher precision
+                auto const& beta_components_{beta_.getComponents(cs_)};
+                auto const& emit_components_{path.emit_.getComponents(cs_)};
+                long double const indexL_{path.refractive_index_source_};
+                long double const betaX_{static_cast<double>(beta_components_.getX())};
+                long double const betaY_{static_cast<double>(beta_components_.getY())};
+                long double const betaZ_{static_cast<double>(beta_components_.getZ())};
+                long double const midX_{static_cast<double>(emit_components_.getX())};
+                long double const midY_{static_cast<double>(emit_components_.getY())};
+                long double const midZ_{static_cast<double>(emit_components_.getZ())};
+                long double const doppler =
+                    1.0l - indexL_ * (betaX_ * midX_ + betaY_ * midY_ + betaZ_ * midZ_);
+                midDoppler_ = doppler;
+              }
+              // LCOV_EXCL_STOP
+
+              // change the values of the receive unit vectors of start and end
+              ReceiveVectorStart_ = path.receive_;
+              ReceiveVectorEnd_ = path.receive_;
+
+              // CoREAS calculation -> get ElectricFieldVector for "midPoint"
+              ElectricFieldVector EVmid_ = (path.emit_.cross(path.emit_.cross(beta_))) /
+                                           midDoppler_ / path.R_distance_ * constants_ *
+                                           antenna.getSampleRate();
+
+              ElectricFieldVector EV1_{EVmid_};
+              ElectricFieldVector EV2_{EVmid_ * (-1.0)};
+
+              TimeType deltaT_{tracklength_ / (constants::c * corrBetaValue) *
+                               std::fabs(midDoppler_)}; // TODO: Caution with this!
+
+              if (startPointReceiveTime_ <
+                  endPointReceiveTime_) // EVstart_ arrives earlier
+              {
+                startPointReceiveTime_ = midPointReceiveTime_ - 0.5 * deltaT_;
+                endPointReceiveTime_ = midPointReceiveTime_ + 0.5 * deltaT_;
+              } else // EVend_ arrives earlier
+              {
+                startPointReceiveTime_ = midPointReceiveTime_ + 0.5 * deltaT_;
+                endPointReceiveTime_ = midPointReceiveTime_ - 0.5 * deltaT_;
+              }
+
+              TimeType const gridResolution_{1 / antenna.getSampleRate()};
+              deltaT_ = endPointReceiveTime_ - startPointReceiveTime_;
+
+              // redistribute contributions over time scale defined by the observation
+              // time resolution
+              if (abs(deltaT_) < (gridResolution_)) {
+
+                EV1_ *= std::fabs((deltaT_ / gridResolution_));
+                EV2_ *= std::fabs((deltaT_ / gridResolution_));
+
+                // ToDO: be careful with times in C8!!! where is the zero (time). Is it
+                // close-by?
+                long const startBin = static_cast<long>(
+                    std::floor(startPointReceiveTime_ / gridResolution_ + 0.5l));
+                long const endBin = static_cast<long>(
+                    std::floor(endPointReceiveTime_ / gridResolution_ + 0.5l));
+                double const startBinFraction =
+                    (startPointReceiveTime_ / gridResolution_) -
+                    std::floor(startPointReceiveTime_ / gridResolution_);
+                double const endBinFraction =
+                    (endPointReceiveTime_ / gridResolution_) -
+                    std::floor(endPointReceiveTime_ / gridResolution_);
+
+                // only do timing modification if contributions would land in same bin
+                if (startBin == endBin) {
+
+                  // if startE arrives before endE
+                  if ((deltaT_) >= 0_s) {
                     if ((startBinFraction >= 0.5) &&
                         (endBinFraction >= 0.5)) // both points left of bin center
                     {
@@ -364,22 +272,111 @@ namespace corsika {
                             gridResolution_; // shift EV1_ to previous gridpoint
                       }
                     }
+                  } else // if endE arrives before startE
+                  {
+                    if ((startBinFraction >= 0.5) &&
+                        (endBinFraction >= 0.5)) // both points left of bin center
+                    {
+                      endPointReceiveTime_ -=
+                          gridResolution_; // shift EV2_ to previous gridpoint
+                    } else if ((startBinFraction < 0.5) &&
+                               (endBinFraction < 0.5)) // both points right of bin center
+                    {
+                      startPointReceiveTime_ +=
+                          gridResolution_; // shift EV1_ to next gridpoint
+                    } else                 // points on both sides of bin center
+                    {
+                      double const leftDist = 1.0 - endBinFraction;
+                      double const rightDist = startBinFraction;
+                      // check if asymmetry to right or left
+                      if (rightDist >= leftDist) {
+                        startPointReceiveTime_ +=
+                            gridResolution_; // shift EV1_ to next gridpoint
+                      } else {
+                        endPointReceiveTime_ -=
+                            gridResolution_; // shift EV2_ to previous gridpoint
+                      }
+                    }
+                  } // End of else statement
+                }   // End of if for startbin == endbin
+              }     // End of if deltaT < gridresolution
 
-                  } // End of if for startbin == endbin
-                }   // End of if deltaT < gridresolution
-              }     // End of if that checks small doppler factors
+              // TODO: Be very careful with this. Maybe the EVs should be fed after the
+              // for loop of paths3
               antenna.receive(startPointReceiveTime_, ReceiveVectorStart_, EV1_);
               antenna.receive(endPointReceiveTime_, ReceiveVectorEnd_, EV2_);
-            } // End of else that does not perform ZHS-like approximation
+            } // End of looping over paths3
+
+          } // end of ZHS-like approximation
+          else {
+
+            // calculate electric field vector for startpoint
+            ElectricFieldVector EV1_ =
+                (paths1[i].emit_.cross(paths1[i].emit_.cross(beta_))) / preDoppler_ /
+                paths1[i].R_distance_ * constants_ * antenna.getSampleRate();
+
+            // calculate electric field vector for endpoint
+            ElectricFieldVector EV2_ =
+                (paths2[i].emit_.cross(paths2[i].emit_.cross(beta_))) / postDoppler_ /
+                paths2[i].R_distance_ * constants_ * (-1.0) * antenna.getSampleRate();
+
+            if ((preDoppler_ < 1.e-9) || (postDoppler_ < 1.e-9)) {
+
+              TimeType const gridResolution_{1 / antenna.getSampleRate()};
+              TimeType deltaT_{endPointReceiveTime_ - startPointReceiveTime_};
+
+              if (abs(deltaT_) < (gridResolution_)) {
+
+                EV1_ *= std::fabs(deltaT_ / gridResolution_); // Todo: rename EV1 and 2
+                EV2_ *= std::fabs(deltaT_ / gridResolution_);
+
+                long const startBin = static_cast<long>(
+                    std::floor(startPointReceiveTime_ / gridResolution_ + 0.5l));
+                long const endBin = static_cast<long>(
+                    std::floor(endPointReceiveTime_ / gridResolution_ + 0.5l));
+                double const startBinFraction =
+                    (startPointReceiveTime_ / gridResolution_) -
+                    std::floor(startPointReceiveTime_ / gridResolution_);
+                double const endBinFraction =
+                    (endPointReceiveTime_ / gridResolution_) -
+                    std::floor(endPointReceiveTime_ / gridResolution_);
+
+                // only do timing modification if contributions would land in same bin
+                if (startBin == endBin) {
+
+                  if ((startBinFraction >= 0.5) &&
+                      (endBinFraction >= 0.5)) // both points left of bin center
+                  {
+                    startPointReceiveTime_ -=
+                        gridResolution_; // shift EV1_ to previous gridpoint
+                  } else if ((startBinFraction < 0.5) &&
+                             (endBinFraction < 0.5)) // both points right of bin center
+                  {
+                    endPointReceiveTime_ +=
+                        gridResolution_; // shift EV2_ to next gridpoint
+                  } else                 // points on both sides of bin center
+                  {
+                    double const leftDist = 1.0 - startBinFraction;
+                    double const rightDist = endBinFraction;
+                    // check if asymmetry to right or left
+                    if (rightDist >= leftDist) {
+                      endPointReceiveTime_ +=
+                          gridResolution_; // shift EV2_ to next gridpoint
+                    } else {
+                      startPointReceiveTime_ -=
+                          gridResolution_; // shift EV1_ to previous gridpoint
+                    }
+                  }
 
-          } // End of loop over both paths to get signal info
-        }   // End of try block
-        // LCOV_EXCL_START
-        catch (size_t i) {
-          CORSIKA_LOG_ERROR("Signal Paths do not have the same size in CoREAS");
-        }
-        // LCOV_EXCL_STOP
-      } // End of looping over antennas
+                } // End of if for startbin == endbin
+              }   // End of if deltaT < gridresolution
+            }     // End of if that checks small doppler factors
+            antenna.receive(startPointReceiveTime_, ReceiveVectorStart_, EV1_);
+            antenna.receive(endPointReceiveTime_, ReceiveVectorEnd_, EV2_);
+          } // End of else that does not perform ZHS-like approximation
+
+        } // End of loop over both paths to get signal info
+      }   // End of looping over antennas
 
       return ProcessReturn::Ok;
     }
diff --git a/corsika/detail/modules/radio/antennas/Antenna.inl b/corsika/detail/modules/radio/antennas/Antenna.inl
index 0b97560aaefc129779fdf1e39dfdfe8f68e9e61b..89d511257c5d9b9069df9036a243956e17d9e06c 100644
--- a/corsika/detail/modules/radio/antennas/Antenna.inl
+++ b/corsika/detail/modules/radio/antennas/Antenna.inl
@@ -16,7 +16,7 @@ namespace corsika {
                                         CoordinateSystemPtr const& coordinateSystem)
       : name_(name)
       , location_(location)
-      , coordinateSystem_(coordinateSystem){};
+      , coordinateSystem_(coordinateSystem) {}
 
   template <typename TAntennaImpl>
   inline Point const& Antenna<TAntennaImpl>::getLocation() const {
diff --git a/corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl b/corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl
index 920b303b9d63281e708ad59b278b8089a4a98cf8..c32f51657d745f2cd7f4ee0f5ace92979f98ca88 100644
--- a/corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl
+++ b/corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl
@@ -20,56 +20,71 @@ namespace corsika {
                                               TimeType const ground_hit_time)
       : Antenna(name, location, coordinateSystem)
       , start_time_(start_time)
-      , duration_(duration)
-      , sample_rate_(sample_rate)
+      , duration_(std::abs(duration / 1_s) * 1_s)
+      , sample_rate_(std::abs(sample_rate / 1_Hz) * 1_Hz)
       , ground_hit_time_(ground_hit_time)
-      , num_bins_(static_cast<std::size_t>(duration * sample_rate + 1.5l))
+      , num_bins_(static_cast<std::size_t>(duration_ * sample_rate_ + 1.5l))
       , waveformEX_(num_bins_, 0)
       , waveformEY_(num_bins_, 0)
       , waveformEZ_(num_bins_, 0)
-      , time_axis_(createTimeAxis()){};
+      , time_axis_(createTimeAxis()) {
+    if (0_s == duration_) {
+      CORSIKA_LOG_WARN(
+          "Antenna: \"{}\" has a duration of zero. Nothing will be injected into it",
+          name);
+    } else if (duration_ != duration) {
+      CORSIKA_LOG_WARN(
+          "Antenna: \"{}\" was given a negative duration. Set to absolute value.", name);
+    }
+
+    if (sample_rate_ != sample_rate) {
+      CORSIKA_LOG_WARN(
+          "Antenna: \"{}\" was given a negative sampling rate. Set to absolute value.",
+          name);
+    }
+  }
 
-  inline void TimeDomainAntenna::receive(const TimeType time,
-                                         const Vector<dimensionless_d>& receive_vector,
-                                         const ElectricFieldVector& efield) {
+  inline void TimeDomainAntenna::receive(
+      const TimeType time, [[maybe_unused]] const Vector<dimensionless_d>& receive_vector,
+      const ElectricFieldVector& efield) {
 
     if (time < start_time_ || time > (start_time_ + duration_)) {
       return;
     } else {
       // figure out the correct timebin to store the E-field value.
       // NOTE: static cast is implicitly flooring
-      auto timebin_{static_cast<std::size_t>(
+      auto timebin{static_cast<std::size_t>(
           std::floor((time - start_time_) * sample_rate_ + 0.5l))};
 
       // store the x,y,z electric field components.
       auto const& Electric_field_components{efield.getComponents(coordinateSystem_)};
-      waveformEX_.at(timebin_) += (Electric_field_components.getX() * (1_m / 1_V));
-      waveformEY_.at(timebin_) += (Electric_field_components.getY() * (1_m / 1_V));
-      waveformEZ_.at(timebin_) += (Electric_field_components.getZ() * (1_m / 1_V));
+      waveformEX_.at(timebin) += (Electric_field_components.getX() * (1_m / 1_V));
+      waveformEY_.at(timebin) += (Electric_field_components.getY() * (1_m / 1_V));
+      waveformEZ_.at(timebin) += (Electric_field_components.getZ() * (1_m / 1_V));
       // TODO: Check how they are stored in memory, row-wise or column-wise? Probably use
       // a 3D object
     }
   }
 
-  inline void TimeDomainAntenna::receive(const TimeType time,
-                                         const Vector<dimensionless_d>& receive_vector,
-                                         const VectorPotential& vectorP) {
+  inline void TimeDomainAntenna::receive(
+      const TimeType time, [[maybe_unused]] const Vector<dimensionless_d>& receive_vector,
+      const VectorPotential& vectorP) {
 
     if (time < start_time_ || time > (start_time_ + duration_)) {
       return;
     } else {
       // figure out the correct timebin to store the E-field value.
       // NOTE: static cast is implicitly flooring
-      auto timebin_{static_cast<std::size_t>(
+      auto timebin{static_cast<std::size_t>(
           std::floor((time - start_time_) * sample_rate_ + 0.5l))};
 
       // store the x,y,z electric field components.
       auto const& Vector_potential_components{vectorP.getComponents(coordinateSystem_)};
-      waveformEX_.at(timebin_) +=
+      waveformEX_.at(timebin) +=
           (Vector_potential_components.getX() * (1_m / (1_V * 1_s)));
-      waveformEY_.at(timebin_) +=
+      waveformEY_.at(timebin) +=
           (Vector_potential_components.getY() * (1_m / (1_V * 1_s)));
-      waveformEZ_.at(timebin_) +=
+      waveformEZ_.at(timebin) +=
           (Vector_potential_components.getZ() * (1_m / (1_V * 1_s)));
       // TODO: Check how they are stored in memory, row-wise or column-wise? Probably use
       // a 3D object
@@ -91,7 +106,7 @@ namespace corsika {
     auto sample_period{1 / sample_rate_};
 
     // fill in every time-value
-    for (std::size_t i = 0; i < num_bins_; i++) {
+    for (uint64_t i = 0; i < num_bins_; i++) {
       // create the current time in nanoseconds
       times.at(i) = static_cast<long double>(
           ((start_time_ - ground_hit_time_) + i * sample_period) / 1_ns);
diff --git a/corsika/detail/modules/radio/propagators/SimplePropagator.inl b/corsika/detail/modules/radio/propagators/SimplePropagator.inl
index 4101878983cb7f3060e0743392a08caca9689508..36cf165e155cf85012ff837f2f5354e8775da4c7 100644
--- a/corsika/detail/modules/radio/propagators/SimplePropagator.inl
+++ b/corsika/detail/modules/radio/propagators/SimplePropagator.inl
@@ -13,12 +13,13 @@ namespace corsika {
 
   template <typename TEnvironment>
   inline SimplePropagator<TEnvironment>::SimplePropagator(TEnvironment const& env)
-      : RadioPropagator<SimplePropagator, TEnvironment>(env){};
+      : RadioPropagator<SimplePropagator, TEnvironment>(env) {}
 
   template <typename TEnvironment>
   inline typename SimplePropagator<TEnvironment>::SignalPathCollection
-  SimplePropagator<TEnvironment>::propagate(Point const& source, Point const& destination,
-                                            LengthType const stepsize) const {
+  SimplePropagator<TEnvironment>::propagate(
+      Point const& source, Point const& destination,
+      [[maybe_unused]] LengthType const stepsize) const {
 
     /**
      * This is the simplest case of straight propagator
@@ -62,8 +63,9 @@ namespace corsika {
     // compute the total time delay.
     TimeType const time = averageRefractiveIndex_ * (distance_ / constants::c);
 
-    return {SignalPath(time, averageRefractiveIndex_, ri_source, ri_destination, emit_,
-                       receive_, distance_, points)};
+    return std::vector<SignalPath>(
+        1, SignalPath(time, averageRefractiveIndex_, ri_source, ri_destination, emit_,
+                      receive_, distance_, points));
 
   } // END: propagate()
 
diff --git a/corsika/detail/modules/radio/propagators/StraightPropagator.inl b/corsika/detail/modules/radio/propagators/StraightPropagator.inl
index 9962fc133003d855ab682aa15b12c275e225c035..59b5c2c8e6b6cd85ca1aad199a18ed0ac0fd1505 100644
--- a/corsika/detail/modules/radio/propagators/StraightPropagator.inl
+++ b/corsika/detail/modules/radio/propagators/StraightPropagator.inl
@@ -14,7 +14,7 @@ namespace corsika {
   template <typename TEnvironment>
   // TODO: maybe the constructor doesn't take any arguments for the environment (?)
   inline StraightPropagator<TEnvironment>::StraightPropagator(TEnvironment const& env)
-      : RadioPropagator<StraightPropagator, TEnvironment>(env){};
+      : RadioPropagator<StraightPropagator, TEnvironment>(env) {}
 
   template <typename TEnvironment>
   inline typename StraightPropagator<TEnvironment>::SignalPathCollection
@@ -30,17 +30,17 @@ namespace corsika {
      */
 
     // these are used for the direction of emission and reception of signal at the antenna
-    auto const emit_{(destination - source).normalized()};
-    auto const receive_{-emit_};
+    auto const emit{(destination - source).normalized()};
+    auto const receive{-emit};
 
     // the distance from the point of emission to an observer
-    auto const distance_{(destination - source).getNorm()};
+    auto const distance{(destination - source).getNorm()};
 
     try {
-      if (stepsize <= 0.5 * distance_) {
+      if (stepsize <= 0.5 * distance) {
 
         // "step" is the direction vector with length `stepsize`
-        auto const step{emit_ * stepsize};
+        auto const step{emit * stepsize};
 
         // calculate the number of points (roughly) for the numerical integration
         auto const n_points{(destination - source).getNorm() / stepsize};
@@ -93,7 +93,7 @@ namespace corsika {
         auto N = rindex.size();
         std::size_t index = 0;
         double sum = rindex.at(index);
-        auto refra_ = rindex.at(index);
+        auto refra = rindex.at(index);
         TimeType time{0_s};
 
         if ((N - 1) % 2 == 0) {
@@ -102,15 +102,15 @@ namespace corsika {
 
           for (std::size_t index = 1; index < (N - 1); index += 2) {
             sum += 4 * rindex.at(index);
-            refra_ += rindex.at(index);
+            refra += rindex.at(index);
           }
           for (std::size_t index = 2; index < (N - 1); index += 2) {
             sum += 2 * rindex.at(index);
-            refra_ += rindex.at(index);
+            refra += rindex.at(index);
           }
           index = N - 1;
           sum = sum + rindex.at(index);
-          refra_ += rindex.at(index);
+          refra += rindex.at(index);
 
           // compute the total time delay.
           time = sum * (h / (3 * constants::c));
@@ -133,15 +133,15 @@ namespace corsika {
           auto const h = ((extrapoint2_ - source).getNorm()) / (N - 1);
           for (std::size_t index = 1; index < (N - 1); index += 2) {
             sum += 4 * rindex.at(index);
-            refra_ += rindex.at(index);
+            refra += rindex.at(index);
           }
           for (std::size_t index = 2; index < (N - 1); index += 2) {
             sum += 2 * rindex.at(index);
-            refra_ += rindex.at(index);
+            refra += rindex.at(index);
           }
           index = N - 1;
           sum = sum + rindex.at(index);
-          refra_ += rindex.at(index);
+          refra += rindex.at(index);
 
           // compute the total time delay including the correction
           time =
@@ -150,13 +150,14 @@ namespace corsika {
         }
 
         // uncomment the following if you want to skip the integration for fast tests
-        // TimeType time = ri_destination * (distance_ / constants::c);
+        // TimeType time = ri_destination * (distance / constants::c);
 
         // compute the average refractive index.
-        auto const averageRefractiveIndex_ = refra_ / N;
+        auto const averageRefractiveIndex = refra / N;
 
-        return {SignalPath(time, averageRefractiveIndex_, ri_source, ri_destination,
-                           emit_, receive_, distance_, points)};
+        return std::vector<SignalPath>(
+            1, SignalPath(time, averageRefractiveIndex, ri_source, ri_destination, emit,
+                          receive, distance, points));
       } else {
         throw stepsize;
       }
@@ -164,6 +165,11 @@ namespace corsika {
       CORSIKA_LOG_ERROR("Please choose a smaller stepsize for the numerical integration");
     }
 
-  } // END: propagate()
+    std::deque<Point> const defaultPoints;
+    return std::vector<SignalPath>(
+        1, SignalPath(0_s, 0, 0, 0, emit, receive, distance,
+                      defaultPoints)); // Dummy return that is never called (combat
+                                       // compile warnings)
+  }                                    // END: propagate()
 
 } // namespace corsika
diff --git a/corsika/modules/radio/CoREAS.hpp b/corsika/modules/radio/CoREAS.hpp
index 0756a78af2b932093312fd3416780929c319379b..058126aa7fb3070d2dac8e3c6de26989ad211e75 100644
--- a/corsika/modules/radio/CoREAS.hpp
+++ b/corsika/modules/radio/CoREAS.hpp
@@ -34,7 +34,7 @@ namespace corsika {
      */
     template <typename... TArgs>
     CoREAS(TRadioDetector& detector, TArgs&&... args)
-        : RadioProcess<TRadioDetector, CoREAS, TPropagator>(detector, args...){};
+        : RadioProcess<TRadioDetector, CoREAS, TPropagator>(detector, args...) {}
 
     /**
      * Simulate the radio emission from a particle across a track.
diff --git a/corsika/modules/radio/ZHS.hpp b/corsika/modules/radio/ZHS.hpp
index 5ec38895b8a8c75a9cb6974b996253a430de1f3e..49153ba25c5ac2707e5c58adfc98153928846c26 100644
--- a/corsika/modules/radio/ZHS.hpp
+++ b/corsika/modules/radio/ZHS.hpp
@@ -36,7 +36,7 @@ namespace corsika {
      */
     template <typename... TArgs>
     ZHS(TRadioDetector& detector, TArgs&&... args)
-        : RadioProcess<TRadioDetector, ZHS, TPropagator>(detector, args...){};
+        : RadioProcess<TRadioDetector, ZHS, TPropagator>(detector, args...) {}
 
     /**
      * Simulate the radio emission from a particle across a track.
diff --git a/corsika/modules/radio/antennas/TimeDomainAntenna.hpp b/corsika/modules/radio/antennas/TimeDomainAntenna.hpp
index 801c529b87a035a021ab1c3aeb52cd86adf9e14d..85fd9dd100743f674fef937f0aff8c69570b5d9c 100644
--- a/corsika/modules/radio/antennas/TimeDomainAntenna.hpp
+++ b/corsika/modules/radio/antennas/TimeDomainAntenna.hpp
@@ -8,6 +8,7 @@
 #pragma once
 
 #include <corsika/modules/radio/antennas/Antenna.hpp>
+#include <yaml-cpp/yaml.h>
 #include <vector>
 
 namespace corsika {
@@ -22,11 +23,11 @@ namespace corsika {
     TimeType const start_time_;         ///< The start time of this waveform.
     TimeType const duration_;           ///< The duration of this waveform.
     InverseTimeType const sample_rate_; ///< The sampling rate of this antenna.
-    int const num_bins_;                ///< The number of bins used.
-    std::vector<double> waveformEX_;    ///< EX polarization.
-    std::vector<double> waveformEY_;    ///< EY polarization.
-    std::vector<double> waveformEZ_;    ///< EZ polarization.
     TimeType const ground_hit_time_; ///< The time the primary particle hits the ground.
+    uint64_t const num_bins_;        ///< The number of bins used.
+    std::vector<double> waveformEX_; ///< EX polarization.
+    std::vector<double> waveformEY_; ///< EY polarization.
+    std::vector<double> waveformEZ_; ///< EZ polarization.
     std::vector<long double> const
         time_axis_; ///< The time axis corresponding to the electric field.
 
diff --git a/tests/modules/testRadio.cpp b/tests/modules/testRadio.cpp
index 2260107939952a45b0f8d7bdb122f67fc1de082d..e31434fd4be10d403b5bab43ac0d7373d9e71739 100644
--- a/tests/modules/testRadio.cpp
+++ b/tests/modules/testRadio.cpp
@@ -16,8 +16,10 @@
 #include <corsika/modules/radio/propagators/SignalPath.hpp>
 #include <corsika/modules/radio/propagators/RadioPropagator.hpp>
 
+#include <boost/filesystem.hpp>
 #include <vector>
 #include <istream>
+#include <filesystem>
 #include <fstream>
 #include <iostream>
 
@@ -65,60 +67,49 @@ TEST_CASE("Radio", "[processes]") {
 
     // This serves as a compiler test for any changes in the CoREAS algorithm
     // Environment
+
     using EnvironmentInterface =
         IRefractiveIndexModel<IMediumPropertyModel<IMagneticFieldModel<IMediumModel>>>;
 
-    //    using EnvType = setup::Environment;
     using EnvType = Environment<EnvironmentInterface>;
+    //    using EnvType = setup::Environment;
     EnvType envCoREAS;
-    CoordinateSystemPtr const& rootCSCoREAS = envCoREAS.getCoordinateSystem();
-    Point const center{rootCSCoREAS, 0_m, 0_m, 0_m};
+    CoordinateSystemPtr const& rootCS = envCoREAS.getCoordinateSystem();
+    Point const center{rootCS, 0_m, 0_m, 0_m};
 
-    //        1.000327,
     create_5layer_atmosphere<EnvironmentInterface, MyExtraEnv>(
         envCoREAS, AtmosphereId::LinsleyUSStd, center, 1.000327, Medium::AirDry1Atm,
-        MagneticFieldVector{rootCSCoREAS, 0_T, 50_uT, 0_T});
+        MagneticFieldVector{rootCS, 0_T, 50_uT, 0_T});
 
-    // now create antennas and detectors
-    // the antennas location
-    const auto point1{Point(envCoREAS.getCoordinateSystem(), 100_m, 2_m, 3_m)};
-    const auto point2{Point(envCoREAS.getCoordinateSystem(), 4_m, 80_m, 6_m)};
-    const auto point3{Point(envCoREAS.getCoordinateSystem(), 7_m, 8_m, 9_m)};
-    const auto point4{Point(envCoREAS.getCoordinateSystem(), 5_m, 5_m, 10_m)};
-
-    // create times for the antenna
+    // create the detector
+    const auto ant1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto ant2Loc{Point(rootCS, 4_m, 80_m, 6_m)};
     const TimeType t1{0_s};
     const TimeType t2{10_s};
     const InverseTimeType t3{1e+3_Hz};
-    const TimeType t4{11_s};
-
-    // check that I can create an antenna at (1, 2, 3)
-    TimeDomainAntenna ant1("antenna_name", point1, rootCSCoREAS, t1, t2, t3, t1);
-    TimeDomainAntenna ant2("antenna_name2", point2, rootCSCoREAS, t1, t2, t3, t1);
-
-    // construct a radio detector instance to store our antennas
+    TimeDomainAntenna ant1("antenna_name", ant1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainAntenna ant2("antenna_name2", ant2Loc, rootCS, t1, t2, t3, t1);
     AntennaCollection<TimeDomainAntenna> detector;
-
-    // add the antennas to the detector
     detector.addAntenna(ant1);
     detector.addAntenna(ant2);
 
-    // create a particle
-    const Code particle{Code::Electron};
-    // const Code particle{Code::Proton};
-    const auto pmass{get_mass(particle)};
+    const auto trackStart{Point(rootCS, 7_m, 8_m, 9_m)};
+    const auto trackEnd{Point(rootCS, 5_m, 5_m, 10_m)};
+
+    // create an electron
+    const Code electron{Code::Electron};
+    const auto pmass{get_mass(electron)};
 
-    VelocityVector v0(rootCSCoREAS, {5e+2_m / second, 5e+2_m / second, 5e+2_m / second});
+    VelocityVector v0(rootCS, {5e+2_m / second, 5e+2_m / second, 5e+2_m / second});
 
-    Vector B0(rootCSCoREAS, 5_T, 5_T, 5_T);
+    Vector B0(rootCS, 5_T, 5_T, 5_T);
 
-    Line const line(point3, v0);
+    Line const line(trackStart, v0);
 
     auto const k{1_m * ((1_m) / ((1_s * 1_s) * 1_V))};
 
     auto const t = 1e-12_s;
-    LeapFrogTrajectory base(point4, v0, B0, k, t);
-    // std::cout << "Leap Frog Trajectory is: " << base << std::endl;
+    LeapFrogTrajectory base(trackEnd, v0, B0, k, t);
 
     // create a new stack for each trial
     setup::Stack<EnvType> stack;
@@ -128,20 +119,16 @@ TEST_CASE("Radio", "[processes]") {
 
     // compute the necessary momentumn
     const HEPMomentumType P0{sqrt(E0 * E0 - pmass * pmass)};
-
-    // and create the momentum vector
-    const auto plab{MomentumVector(rootCSCoREAS, {0_GeV, 0_GeV, P0})};
+    const auto plab{MomentumVector(rootCS, {0_GeV, 0_GeV, P0})};
 
     // and create the location of the particle in this coordinate system
-    const Point pos(rootCSCoREAS, 50_m, 10_m, 80_m);
+    const Point pos(rootCS, 50_m, 10_m, 80_m);
 
     // add the particle to the stack
     auto const particle1{stack.addParticle(std::make_tuple(
-        particle, calculate_kinetic_energy(plab.getNorm(), get_mass(particle)),
+        electron, calculate_kinetic_energy(plab.getNorm(), get_mass(electron)),
         plab.normalized(), pos, 0_ns))};
 
-    auto const charge_{get_charge(particle1.getPID())};
-
     // create a radio process instance using CoREAS
     RadioProcess<decltype(detector),
                  CoREAS<decltype(detector), decltype(StraightPropagator(envCoREAS))>,
@@ -150,9 +137,149 @@ TEST_CASE("Radio", "[processes]") {
 
     Step step(particle1, base);
     // check doContinuous and simulate methods
-    coreas.doContinuous(step, true);
+    auto const result = coreas.doContinuous(step, true);
+    REQUIRE(ProcessReturn::Ok == result);
+
+    for (auto const& ant : detector.getAntennas()) {
+      // make sure something was put into the antenna
+      auto totalX = ant.getWaveformX()[0];
+      auto totalY = ant.getWaveformY()[0];
+      auto totalZ = ant.getWaveformZ()[0];
+      for (size_t i = 0; i < ant.getWaveformX().size(); i++) {
+        totalX += ant.getWaveformX()[i];
+        totalY += ant.getWaveformY()[i];
+        totalZ += ant.getWaveformZ()[i];
+      }
+      REQUIRE((totalX + totalY + totalZ) > (totalX * 0));
+    }
+
+    //////////////////////////////////////
+    // reset everything for a new particle
+    //////////////////////////////////////
+    ant1.reset();
+    ant2.reset();
+    stack.purge();
+
+    // add the particle to the stack that is VERY late
+    auto const particle2{stack.addParticle(std::make_tuple(
+        electron, calculate_kinetic_energy(plab.getNorm(), get_mass(electron)),
+        plab.normalized(), pos, t1 + t2 * 100000))};
+    Step step2(particle2, base);
+    auto const result2 = coreas.doContinuous(step2, true);
+    REQUIRE(ProcessReturn::Ok == result2);
+    for (auto const& ant : detector.getAntennas()) {
+      // make sure something was put into the antenna
+      auto total = ant.getWaveformX()[0];
+      for (size_t i = 0; i < ant.getWaveformX().size(); i++) {
+        total += ant.getWaveformX()[i] * ant.getWaveformX()[i];
+        total += ant.getWaveformY()[i] * ant.getWaveformY()[i];
+        total += ant.getWaveformZ()[i] * ant.getWaveformZ()[i];
+      }
+      REQUIRE(total < (1e-12 * ant.getWaveformX().size()));
+    }
+
+    coreas.endOfLibrary();
+
   } // END: SECTION("CoREAS process")
 
+  SECTION("CoREAS Edge Cases") {
+    using IModelInterface =
+        IRefractiveIndexModel<IMediumPropertyModel<IMagneticFieldModel<IMediumModel>>>;
+    using AtmModel = UniformRefractiveIndex<
+        MediumPropertyModel<UniformMagneticField<HomogeneousMedium<IModelInterface>>>>;
+    using EnvType = Environment<AtmModel>;
+    EnvType envCoREAS;
+    CoordinateSystemPtr const& rootCS = envCoREAS.getCoordinateSystem();
+    Point const center{rootCS, 0_m, 0_m, 0_m};
+
+    Vector B1(rootCS, 0_T, 0_T, 1_T);
+    NuclearComposition const protonComposition({Code::Proton}, {1.});
+    const double refractiveIndex{1.000327};
+    const auto density{1_g / cube(1_cm)};
+    auto Medium = EnvType::createNode<Sphere>(
+        center, 10_km * std::numeric_limits<double>::infinity());
+    auto const props = Medium->setModelProperties<AtmModel>(
+        refractiveIndex, Medium::AirDry1Atm, B1, density, protonComposition);
+    envCoREAS.getUniverse()->addChild(std::move(Medium));
+
+    // create the detector
+    const auto ant1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto ant2Loc{Point(rootCS, 4_m, 80_m, 6_m)};
+    const TimeType t1{0_s};
+    const TimeType t2{10_s};
+    const InverseTimeType t3{1e+3_Hz};
+    TimeDomainAntenna ant1("antenna_name", ant1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainAntenna ant2("antenna_name2", ant2Loc, rootCS, t1, t2, t3, t1);
+    AntennaCollection<TimeDomainAntenna> detector;
+    detector.addAntenna(ant1);
+    detector.addAntenna(ant2);
+
+    const auto trackStart{Point(rootCS, 7_m, 8_m, 9_m)};
+    const auto trackEnd{Point(rootCS, 5_m, 5_m, 10_m)};
+
+    // create an electron
+    const Code electron{Code::Electron};
+    const auto pmass{get_mass(electron)};
+
+    VelocityVector v0(rootCS, {1_m / second, 0_m / second, 0_m / second});
+
+    Vector B0(rootCS, 5_T, 5_T, 5_T);
+
+    Line const line(trackStart, v0);
+
+    // create a new stack for each trial
+    setup::Stack<EnvType> stack;
+
+    // construct an energy
+    const HEPEnergyType E0{1_TeV};
+
+    // compute the necessary momentumn
+    const HEPMomentumType P0{sqrt(E0 * E0 - pmass * pmass)};
+    const auto plab{MomentumVector(rootCS, {0_GeV, 0_GeV, P0})};
+
+    // and create the location of the particle in this coordinate system
+    const Point pos(rootCS, 50_m, 10_m, 80_m);
+
+    // add the particle to the stack
+    auto const particle1{stack.addParticle(std::make_tuple(
+        electron, calculate_kinetic_energy(plab.getNorm(), get_mass(electron)),
+        plab.normalized(), pos, 0_ns))};
+
+    // create a radio process instance using CoREAS
+    RadioProcess<decltype(detector),
+                 CoREAS<decltype(detector), decltype(StraightPropagator(envCoREAS))>,
+                 decltype(StraightPropagator(envCoREAS))>
+        coreas(detector, envCoREAS);
+
+    auto result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(line, 0_ns, 0_ns, v0, v0)), true);
+    REQUIRE(ProcessReturn::Ok == result);
+    result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(line, 0_ns, 1_ns, v0, v0)), true);
+    REQUIRE(ProcessReturn::Ok == result);
+    result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(line, 0_ns, -1_ns, v0, v0)), true);
+    REQUIRE(ProcessReturn::Ok == result);
+    result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(line, 1_ns, -1_ns, v0, v0)), true);
+    REQUIRE(ProcessReturn::Ok == result);
+    result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(line, -1_ns, 1_ns, v0, v0)), true);
+    REQUIRE(ProcessReturn::Ok == result);
+    result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(line, -1_ns, 1_ns, v0, -v0)), true);
+    REQUIRE(ProcessReturn::Ok == result);
+
+    // Use ZHS-like loop
+    auto const vParallel =
+        VelocityVector(rootCS, {0_m / second, 1_m / second, 0_m / second});
+    result = coreas.doContinuous(
+        Step(particle1, StraightTrajectory(Line(trackStart, vParallel), 0_ns, 1_ns,
+                                           vParallel, vParallel)),
+        true);
+    REQUIRE(ProcessReturn::Ok == result);
+  }
+
   SECTION("ZHS process") {
 
     // This section serves as a compiler test for any changes in the ZHS algorithm
@@ -163,9 +290,9 @@ TEST_CASE("Radio", "[processes]") {
         MediumPropertyModel<UniformMagneticField<HomogeneousMedium<IModelInterface>>>>;
     using EnvType = Environment<AtmModel>;
     EnvType envZHS;
-    CoordinateSystemPtr const& rootCSZHS = envZHS.getCoordinateSystem();
+    CoordinateSystemPtr const& rootCS = envZHS.getCoordinateSystem();
     // get the center point
-    Point const center{rootCSZHS, 0_m, 0_m, 0_m};
+    Point const center{rootCS, 0_m, 0_m, 0_m};
     // a refractive index
     const double ri_{1.000327};
 
@@ -176,7 +303,7 @@ TEST_CASE("Radio", "[processes]") {
     NuclearComposition const protonComposition({Code::Proton}, {1.});
 
     // create magnetic field vector
-    Vector B1(rootCSZHS, 0_T, 0_T, 1_T);
+    Vector B1(rootCS, 0_T, 0_T, 1_T);
 
     auto Medium = EnvType::createNode<Sphere>(
         center, 1_km * std::numeric_limits<double>::infinity());
@@ -186,25 +313,18 @@ TEST_CASE("Radio", "[processes]") {
     envZHS.getUniverse()->addChild(std::move(Medium));
 
     // the antennas location
-    const auto point1{Point(envZHS.getCoordinateSystem(), 100_m, 2_m, 3_m)};
-    const auto point2{Point(envZHS.getCoordinateSystem(), 4_m, 80_m, 6_m)};
-    const auto point3{Point(envZHS.getCoordinateSystem(), 7_m, 8_m, 9_m)};
-    const auto point4{Point(envZHS.getCoordinateSystem(), 5_m, 5_m, 10_m)};
+    const auto trackStart{Point(envZHS.getCoordinateSystem(), 7_m, 8_m, 9_m)};
+    const auto trackEnd{Point(envZHS.getCoordinateSystem(), 5_m, 5_m, 10_m)};
 
-    // create times for the antenna
+    // create the detector
+    const auto ant1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto ant2Loc{Point(rootCS, 4_m, 80_m, 6_m)};
     const TimeType t1{0_s};
     const TimeType t2{10_s};
     const InverseTimeType t3{1e+3_Hz};
-    const TimeType t4{11_s};
-
-    // check that I can create an antenna at (1, 2, 3)
-    TimeDomainAntenna ant1("antenna_zhs", point1, rootCSZHS, t1, t2, t3, t1);
-    TimeDomainAntenna ant2("antenna_zhs2", point2, rootCSZHS, t1, t2, t3, t1);
-
-    // construct a radio detector instance to store our antennas
+    TimeDomainAntenna ant1("antenna_name", ant1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainAntenna ant2("antenna_name2", ant2Loc, rootCS, t1, t2, t3, t1);
     AntennaCollection<TimeDomainAntenna> detector;
-
-    // add the antennas to the detector
     detector.addAntenna(ant1);
     detector.addAntenna(ant2);
 
@@ -212,17 +332,16 @@ TEST_CASE("Radio", "[processes]") {
     auto const particle{Code::Electron};
     const auto pmass{get_mass(particle)};
 
-    VelocityVector v0(rootCSZHS, {5e+2_m / second, 5e+2_m / second, 5e+2_m / second});
+    VelocityVector v0(rootCS, {5e+2_m / second, 5e+2_m / second, 5e+2_m / second});
 
-    Vector B0(rootCSZHS, 5_T, 5_T, 5_T);
+    Vector B0(rootCS, 5_T, 5_T, 5_T);
 
-    Line const line(point3, v0);
+    Line const line(trackStart, v0);
 
     auto const k{1_m * ((1_m) / ((1_s * 1_s) * 1_V))};
 
     auto const t = 1e-12_s;
-    LeapFrogTrajectory base(point4, v0, B0, k, t);
-    // std::cout << "Leap Frog Trajectory is: " << base << std::endl;
+    LeapFrogTrajectory base(trackEnd, v0, B0, k, t);
 
     // create a new stack for each trial
     setup::Stack<EnvType> stack;
@@ -232,12 +351,10 @@ TEST_CASE("Radio", "[processes]") {
 
     // compute the necessary momentum
     const HEPMomentumType P0{sqrt(E0 * E0 - pmass * pmass)};
-
-    // and create the momentum vector
-    const auto plab{MomentumVector(rootCSZHS, {0_GeV, 0_GeV, P0})};
+    const auto plab{MomentumVector(rootCS, {0_GeV, 0_GeV, P0})};
 
     // and create the location of the particle in this coordinate system
-    const Point pos(rootCSZHS, 50_m, 10_m, 80_m);
+    const Point pos(rootCS, 50_m, 10_m, 80_m);
 
     // add the particle to the stack
     auto const particle1{stack.addParticle(std::make_tuple(
@@ -309,7 +426,6 @@ TEST_CASE("Radio", "[processes]") {
     const Code particle2{Code::Proton};
 
     const auto pmass{get_mass(particle)};
-    const auto pmass2{get_mass(particle2)};
     // construct an energy
     const HEPEnergyType E0{1_TeV};
     // compute the necessary momentumn
@@ -373,11 +489,271 @@ TEST_CASE("Radio", "[processes]") {
 
   } // END: SECTION("Radio extreme cases")
 
+  SECTION("Process Library") {
+    using IModelInterface =
+        IRefractiveIndexModel<IMediumPropertyModel<IMagneticFieldModel<IMediumModel>>>;
+    using AtmModel = UniformRefractiveIndex<
+        MediumPropertyModel<UniformMagneticField<HomogeneousMedium<IModelInterface>>>>;
+    using EnvType = Environment<AtmModel>;
+    EnvType envCoREAS;
+    CoordinateSystemPtr const& rootCS = envCoREAS.getCoordinateSystem();
+    Point const center{rootCS, 0_m, 0_m, 0_m};
+
+    Vector B1(rootCS, 0_T, 0_T, 1_T);
+    NuclearComposition const protonComposition({Code::Proton}, {1.});
+    const double refractiveIndex{1.000327};
+    const auto density{1_g / cube(1_cm)};
+    auto Medium = EnvType::createNode<Sphere>(
+        center, 10_km * std::numeric_limits<double>::infinity());
+    auto const props = Medium->setModelProperties<AtmModel>(
+        refractiveIndex, Medium::AirDry1Atm, B1, density, protonComposition);
+    envCoREAS.getUniverse()->addChild(std::move(Medium));
+
+    // create the detector
+    const auto ant1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto ant2Loc{Point(rootCS, 4_m, 80_m, 6_m)};
+    const TimeType t1{0_s};
+    const TimeType t2{10_s};
+    const InverseTimeType t3{1e+3_Hz};
+    TimeDomainAntenna ant1("antenna_name", ant1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainAntenna ant2("antenna_name2", ant2Loc, rootCS, t1, t2, t3, t1);
+    AntennaCollection<TimeDomainAntenna> detector;
+    detector.addAntenna(ant1);
+    detector.addAntenna(ant2);
+
+    const auto trackStart{Point(rootCS, 7_m, 8_m, 9_m)};
+    const auto trackEnd{Point(rootCS, 5_m, 5_m, 10_m)};
+
+    // create an electron
+    const Code electron{Code::Electron};
+    const auto pmass{get_mass(electron)};
+
+    VelocityVector v0(rootCS, {1_m / second, 0_m / second, 0_m / second});
+
+    Vector B0(rootCS, 5_T, 5_T, 5_T);
+
+    Line const line(trackStart, v0);
+
+    // create a new stack for each trial
+    setup::Stack<EnvType> stack;
+
+    // construct an energy
+    const HEPEnergyType E0{1_TeV};
+
+    // compute the necessary momentumn
+    const HEPMomentumType P0{sqrt(E0 * E0 - pmass * pmass)};
+    const auto plab{MomentumVector(rootCS, {0_GeV, 0_GeV, P0})};
+
+    // and create the location of the particle in this coordinate system
+    const Point pos(rootCS, 50_m, 10_m, 80_m);
+
+    // add the particle to the stack
+    auto const particle1{stack.addParticle(std::make_tuple(
+        electron, calculate_kinetic_energy(plab.getNorm(), get_mass(electron)),
+        plab.normalized(), pos, 0_ns))};
+
+    // create a radio process instance using CoREAS
+    RadioProcess<decltype(detector),
+                 CoREAS<decltype(detector), decltype(StraightPropagator(envCoREAS))>,
+                 decltype(StraightPropagator(envCoREAS))>
+        coreas(detector, envCoREAS);
+
+    const auto config = coreas.getConfig();
+
+    CHECK(config["type"].as<std::string>() == "RadioProcess");
+    CHECK(config["algorithm"].as<std::string>() == "CoREAS");
+    CHECK(config["units"]["time"].as<std::string>() == "ns");
+    CHECK(config["units"]["frequency"].as<std::string>() == "GHz");
+    CHECK(config["units"]["electric field"].as<std::string>() == "V/m");
+    CHECK(config["units"]["distance"].as<std::string>() == "m");
+
+    CHECK(config["antennas"]["antenna_name"]["location"][0].as<double>() == 100);
+    CHECK(config["antennas"]["antenna_name"]["location"][1].as<double>() == 2);
+    CHECK(config["antennas"]["antenna_name"]["location"][2].as<double>() == 3);
+
+    CHECK(config["antennas"]["antenna_name2"]["location"][0].as<double>() == 4);
+    CHECK(config["antennas"]["antenna_name2"]["location"][1].as<double>() == 80);
+    CHECK(config["antennas"]["antenna_name2"]["location"][2].as<double>() == 6);
+  }
+
 } // END: TEST_CASE("Radio", "[processes]")
 
 TEST_CASE("Antennas") {
 
-  SECTION("TimeDomainAntenna") {
+  SECTION("TimeDomainAntenna Constructor") {
+    Environment<IRefractiveIndexModel<IMediumModel>> env;
+    const auto rootCS = env.getCoordinateSystem();
+    auto const antPos = Point(rootCS, {0_m, 0_m, 0_m});
+    TimeType const tStart(0_s);
+    TimeType const duration(10_ns);
+    InverseTimeType const sampleRate(1_GHz);
+    TimeType const groundHitTime(1e3_ns);
+
+    TimeDomainAntenna const antenna("antenna", antPos, rootCS, tStart, duration,
+                                    sampleRate, groundHitTime);
+
+    // All waveforms are of equal non-zero size
+    CHECK(antenna.getWaveformX().size() == antenna.getWaveformY().size());
+    CHECK(antenna.getWaveformX().size() == antenna.getWaveformZ().size());
+    CHECK(antenna.getWaveformX().size() > 0);
+
+    // All waveform values are initialized to zero
+    for (auto const& val : antenna.getWaveformX()) { CHECK(val * 0 == val); }
+    for (auto const& val : antenna.getWaveformY()) { CHECK(val * 0 == val); }
+    for (auto const& val : antenna.getWaveformZ()) { CHECK(val * 0 == val); }
+
+    // check that variables were set properly
+    CHECK("antenna" == antenna.getName());
+    CHECK(sampleRate == antenna.getSampleRate());
+    CHECK(tStart == antenna.getStartTime());
+
+    // and check that the antenna is at the right location
+    CHECK((antenna.getLocation() - antPos).getNorm() < 1e-12 * 1_m);
+  } // END: SECTION("TimeDomainAntenna Constructor")
+
+  SECTION("TimeDomainAntenna Bad Constructor") {
+    Environment<IRefractiveIndexModel<IMediumModel>> env;
+    const auto rootCS = env.getCoordinateSystem();
+    auto const antPos = Point(rootCS, {0_m, 0_m, 0_m});
+    TimeType const tStart(0_s);
+    TimeType const duration(1e3_ns);
+    InverseTimeType const sampleRate(1_GHz);
+    TimeType const groundHitTime(10_ns);
+
+    // Giving zero or negative values for sampling rate and duration
+    TimeDomainAntenna const antenna_bad1("bad_antenna", antPos, rootCS, tStart, -13_ns,
+                                         sampleRate, groundHitTime);
+    TimeDomainAntenna const antenna_bad2("bad_antenna", antPos, rootCS, tStart, 0_ns,
+                                         sampleRate, groundHitTime);
+    TimeDomainAntenna const antenna_bad3("bad_antenna", antPos, rootCS, tStart, duration,
+                                         -1_GHz, groundHitTime);
+  } // END: SECTION("TimeDomainAntenna Bad Constructor")
+
+  SECTION("TimeDomainAntenna Receive Efield") {
+    // Checks that the basic functionality of the receive function is working properly
+
+    using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
+    EnvType env;
+
+    const auto rootCS = env.getCoordinateSystem();
+
+    auto const point1 = Point(rootCS, {1_m, 2_m, 3_m});
+    auto const point2 = Point(rootCS, {4_m, 5_m, 6_m});
+
+    // create times for the antenna
+    const TimeType t1{10_s};
+    const TimeType t2{10_s};
+    const InverseTimeType t3{1 / 1_s};
+    const TimeType t4{11_s};
+
+    // make the two antennas with different start times
+    TimeDomainAntenna ant1("antenna_name", point1, rootCS, t1, t2, t3, t1);
+    TimeDomainAntenna ant2("antenna_name", point2, rootCS, t4, t2, t3, t4);
+
+    Vector<dimensionless_d> receiveVec1(rootCS, {0, 0, 1});
+    Vector<dimensionless_d> receiveVec2(rootCS, {0, 1, 0});
+
+    Vector<ElectricFieldType::dimension_type> eField1(
+        rootCS, {10_V / 1_m, 10_V / 1_m, 10_V / 1_m});
+    Vector<ElectricFieldType::dimension_type> eField2(
+        rootCS, {20_V / 1_m, 20_V / 1_m, 20_V / 1_m});
+
+    // inject efield into ant1
+    ant1.receive(15_s, receiveVec1, eField1);
+    REQUIRE(ant1.getWaveformX()[5] - 10 == 0);
+    REQUIRE(ant1.getWaveformX()[5] == ant1.getWaveformY()[5]);
+    REQUIRE(ant1.getWaveformX()[5] == ant1.getWaveformZ()[5]);
+
+    // inject efield but with different receive vector into ant2
+    ant2.receive(16_s, receiveVec2, eField1);
+    REQUIRE(ant1.getWaveformX()[5] ==
+            ant2.getWaveformX()[5]); // Currently receive vector does nothing
+    ant2.reset();
+    REQUIRE(ant2.getWaveformX()[5] == 0); // reset was successful
+
+    // inject the other eField into ant2
+    ant2.receive(16_s, receiveVec2, eField2);
+    REQUIRE(ant2.getWaveformX()[5] - 20 == 0);
+    REQUIRE(ant2.getWaveformX()[5] == ant2.getWaveformY()[5]);
+    REQUIRE(ant2.getWaveformX()[5] == ant2.getWaveformZ()[5]);
+
+    // make sure the next one is empty before filling it
+    REQUIRE(ant2.getWaveformX()[6] == 0);
+    ant2.receive(17_s, receiveVec2, eField2);
+    REQUIRE(ant2.getWaveformX()[6] - 20 == 0);
+
+    // reset ant1 and then put values in out of range
+    ant1.reset();
+    ant1.receive(-1000_s, receiveVec1, eField1);
+    for (auto const& val : ant1.getWaveformX()) { CHECK(val * 0 == val); }
+    ant1.reset();
+    ant1.receive(t1 + t2 + 1_s, receiveVec1, eField1);
+    for (auto const& val : ant1.getWaveformX()) { CHECK(val * 0 == val); }
+  } // END: SECTION("TimeDomainAntenna Receive EField")
+
+  SECTION("TimeDomainAntenna Receive Vector Potential") {
+    // Checks that the basic functionality of the receive function is working properly
+
+    using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
+    EnvType env;
+
+    const auto rootCS = env.getCoordinateSystem();
+
+    auto const point1 = Point(rootCS, {1_m, 2_m, 3_m});
+    auto const point2 = Point(rootCS, {4_m, 5_m, 6_m});
+
+    // create times for the antenna
+    const TimeType t1{10_s};
+    const TimeType t2{10_s};
+    const InverseTimeType t3{1 / 1_s};
+    const TimeType t4{11_s};
+
+    // make the two antennas with different start times
+    TimeDomainAntenna ant1("antenna_name", point1, rootCS, t1, t2, t3, t1);
+    TimeDomainAntenna ant2("antenna_name", point2, rootCS, t4, t2, t3, t4);
+
+    Vector<dimensionless_d> receiveVec1(rootCS, {0, 0, 1});
+    Vector<dimensionless_d> receiveVec2(rootCS, {0, 1, 0});
+
+    Vector<VectorPotentialType::dimension_type> vectorPotential1(
+        rootCS, {10_V * 1_s / 1_m, 10_V * 1_s / 1_m, 10_V * 1_s / 1_m});
+    Vector<VectorPotentialType::dimension_type> vectorPotential2(
+        rootCS, {20_V * 1_s / 1_m, 20_V * 1_s / 1_m, 20_V * 1_s / 1_m});
+
+    // inject efield into ant1
+    ant1.receive(15_s, receiveVec1, vectorPotential1);
+    REQUIRE(ant1.getWaveformX()[5] - 10 == 0);
+    REQUIRE(ant1.getWaveformX()[5] == ant1.getWaveformY()[5]);
+    REQUIRE(ant1.getWaveformX()[5] == ant1.getWaveformZ()[5]);
+
+    // inject efield but with different receive vector into ant2
+    ant2.receive(16_s, receiveVec2, vectorPotential1);
+    REQUIRE(ant1.getWaveformX()[5] ==
+            ant2.getWaveformX()[5]); // Currently receive vector does nothing
+    ant2.reset();
+    REQUIRE(ant2.getWaveformX()[5] == 0); // reset was successful
+
+    // inject the other eField into ant2
+    ant2.receive(16_s, receiveVec2, vectorPotential2);
+    REQUIRE(ant2.getWaveformX()[5] - 20 == 0);
+    REQUIRE(ant2.getWaveformX()[5] == ant2.getWaveformY()[5]);
+    REQUIRE(ant2.getWaveformX()[5] == ant2.getWaveformZ()[5]);
+
+    // make sure the next one is empty before filling it
+    REQUIRE(ant2.getWaveformX()[6] == 0);
+    ant2.receive(17_s, receiveVec2, vectorPotential2);
+    REQUIRE(ant2.getWaveformX()[6] - 20 == 0);
+
+    // reset ant1 and then put values in out of range
+    ant1.reset();
+    ant1.receive(-1000_s, receiveVec1, vectorPotential1);
+    for (auto const& val : ant1.getWaveformX()) { CHECK(val * 0 == val); }
+    ant1.reset();
+    ant1.receive(t1 + t2 + 1_s, receiveVec1, vectorPotential1);
+    for (auto const& val : ant1.getWaveformX()) { CHECK(val * 0 == val); }
+  } // END: SECTION("TimeDomainAntenna Receive Vector Potential")
+
+  SECTION("TimeDomainAntenna AntennaCollection") {
 
     // create an environment so we can get a coordinate system
     using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
@@ -391,10 +767,10 @@ TEST_CASE("Antennas") {
     const auto point2{Point(env6.getCoordinateSystem(), 4_m, 5_m, 6_m)};
 
     // get a coordinate system
-    const CoordinateSystemPtr rootCS6 = env6.getCoordinateSystem();
+    const CoordinateSystemPtr rootCS = env6.getCoordinateSystem();
 
     auto Medium6 = EnvType::createNode<Sphere>(
-        Point{rootCS6, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity());
+        Point{rootCS, 0_m, 0_m, 0_m}, 1_km * std::numeric_limits<double>::infinity());
 
     auto const props6 = Medium6->setModelProperties<UniRIndex>(
         1, 1_kg / (1_m * 1_m * 1_m), NuclearComposition({Code::Nitrogen}, {1.}));
@@ -407,100 +783,90 @@ TEST_CASE("Antennas") {
     const InverseTimeType t3{1 / 1_s};
     const TimeType t4{11_s};
 
-    // check that I can create an antenna at (1, 2, 3)
-    TimeDomainAntenna ant1("antenna_name", point1, rootCS6, t1, t2, t3, t1);
-    TimeDomainAntenna ant2("antenna_name2", point2, rootCS6, t4, t2, t3, t4);
-
-    // assert that the antenna name is correct
-    REQUIRE(ant1.getName() == "antenna_name");
-    REQUIRE(ant2.getName() == "antenna_name2");
-
-    // and check that the antenna is at the right location
-    REQUIRE((ant1.getLocation() - point1).getNorm() < 1e-12 * 1_m);
-    REQUIRE((ant2.getLocation() - point2).getNorm() < 1e-12 * 1_m);
-
     // construct a radio detector instance to store our antennas
     AntennaCollection<TimeDomainAntenna> detector;
 
-    // add this antenna to the process
-    detector.addAntenna(ant1);
-    detector.addAntenna(ant2);
-    CHECK(detector.size() == 2);
-
-    // get a unit vector
-    Vector<dimensionless_d> v1(rootCS6, {0, 0, 1});
-    Vector<ElectricFieldType::dimension_type> v11(rootCS6,
-                                                  {10_V / 1_m, 10_V / 1_m, 10_V / 1_m});
-
-    Vector<dimensionless_d> v2(rootCS6, {0, 1, 0});
-    Vector<ElectricFieldType::dimension_type> v22(rootCS6,
-                                                  {20_V / 1_m, 20_V / 1_m, 20_V / 1_m});
-
-    // use receive methods
-    ant1.receive(15_s, v1, v11);
-    ant2.receive(16_s, v2, v22);
-
-    // use getDataX,Y,Z() and getAxis() methods
-    auto Ex = ant1.getWaveformX();
-    CHECK(Ex[5] - 10 == 0);
-    auto tx = ant1.getAxis();
-    CHECK(tx[5] - 5 * 1_s / 1_ns == Approx(0.0));
-    auto Ey = ant1.getWaveformY();
-    CHECK(Ey[5] - 10 == 0);
-    auto Ez = ant1.getWaveformZ();
-    CHECK(Ez[5] - 10 == 0);
-    auto ty = ant1.getAxis();
-    auto tz = ant1.getAxis();
-    CHECK(tx[5] - ty[5] == 0);
-    CHECK(ty[5] - tz[5] == 0);
-    auto Ex2 = ant2.getWaveformX();
-    CHECK(Ex2[5] - 20 == 0);
-    auto Ey2 = ant2.getWaveformY();
-    CHECK(Ey2[5] - 20 == 0);
-    auto Ez2 = ant2.getWaveformZ();
-    CHECK(Ez2[5] - 20 == 0);
-
     // the following creates a star-shaped pattern of antennas in the ground
-    AntennaCollection<TimeDomainAntenna> detector__;
     const auto point11{Point(env6.getCoordinateSystem(), 1000_m, 20_m, 30_m)};
     const TimeType t2222{1e-6_s};
     const InverseTimeType t3333{1e+9_Hz};
 
     std::vector<std::string> antenna_names;
     std::vector<Point> antenna_locations;
-    for (auto radius_ = 100_m; radius_ <= 200_m; radius_ += 100_m) {
-      for (auto phi_ = 0; phi_ <= 315; phi_ += 45) {
-        auto phiRad_ = phi_ / 180. * M_PI;
-        auto const point_{Point(env6.getCoordinateSystem(), radius_ * cos(phiRad_),
-                                radius_ * sin(phiRad_), 0_m)};
-        antenna_locations.push_back(point_);
-        auto time__{(point11 - point_).getNorm() / constants::c};
-        const int rr_ = static_cast<int>(radius_ / 1_m);
-        std::string var_ = "antenna_R=" + std::to_string(rr_) +
-                           "_m-Phi=" + std::to_string(phi_) + "degrees";
-        antenna_names.push_back(var_);
-        TimeDomainAntenna ant111(var_, point_, rootCS6, time__, t2222, t3333, time__);
-        detector__.addAntenna(ant111);
+    for (auto radius = 100_m; radius <= 200_m; radius += 100_m) {
+      for (auto phi = 0; phi <= 315; phi += 45) {
+        auto phiRad = phi / 180. * M_PI;
+        auto const point{Point(env6.getCoordinateSystem(), radius * cos(phiRad),
+                               radius * sin(phiRad), 0_m)};
+        antenna_locations.push_back(point);
+        auto time__{(point11 - point).getNorm() / constants::c};
+        const int rr_ = static_cast<int>(radius / 1_m);
+        std::string name = "antenna_R=" + std::to_string(rr_) +
+                           "_m-Phi=" + std::to_string(phi) + "degrees";
+        antenna_names.push_back(name);
+        TimeDomainAntenna ant(name, point, rootCS, time__, t2222, t3333, time__);
+        detector.addAntenna(ant);
       }
     }
 
-    CHECK(detector__.size() == 16);
-    CHECK(detector__.getAntennas().size() == 16);
+    CHECK(detector.size() == 16);
+    CHECK(detector.getAntennas().size() == 16);
     int i = 0;
     // this prints out the antenna names and locations
-    for (auto const antenna : detector__.getAntennas()) {
+    for (auto const& antenna : detector.getAntennas()) {
       CHECK(antenna.getName() == antenna_names[i]);
       CHECK(distance(antenna.getLocation(), antenna_locations[i]) / 1_m == 0);
       i++;
     }
 
     // Check the .at() method for radio detectors
-    for (size_t i = 0; i <= (detector__.size() - 1); i++) {
-      CHECK(detector__.at(i).getName() == antenna_names[i]);
-      CHECK(distance(detector__.at(i).getLocation(), antenna_locations[i]) / 1_m == 0);
+    for (int i = 0; i <= (detector.size() - 1); i++) {
+      CHECK(detector.at(i).getName() == antenna_names[i]);
+      CHECK(distance(detector.at(i).getLocation(), antenna_locations[i]) / 1_m == 0);
+    }
+
+  } // END: SECTION("TimeDomainAntenna AntennaCollection")
+
+  SECTION("TimeDomainAntenna Library") {
+    // Runs checks that the file readers are working properly
+    Environment<IRefractiveIndexModel<IMediumModel>> env;
+    const auto rootCS = env.getCoordinateSystem();
+    auto const antPos = Point(rootCS, {0_m, 0_m, 0_m});
+    TimeType const tStart(0_s);
+    TimeType const duration(10_ns);
+    InverseTimeType const sampleRate(1_GHz);
+    TimeType const groundHitTime(1e3_ns);
+
+    TimeDomainAntenna antenna("test_antenna", antPos, rootCS, tStart, duration,
+                              sampleRate, groundHitTime);
+
+    // Run the start of lib and end of shower functions on the antenna
+    std::vector<std::string> implementations{"CoREAS", "ZHS"};
+    for (auto const implemen : implementations) {
+      // For each implementation type, save a file
+      boost::filesystem::path const tempPath{boost::filesystem::temp_directory_path() /
+                                             ("test_corsika_radio_" + implemen)};
+      if (boost::filesystem::exists(tempPath)) {
+        boost::filesystem::remove_all(tempPath);
+      }
+      boost::filesystem::create_directory(tempPath);
+      antenna.startOfLibrary(tempPath, implemen);
+      auto const outputFile = tempPath / (antenna.getName() + ".npz");
+      CHECK(boost::filesystem::exists(outputFile));
+
+      // run end of shower and make sure that something extra was added
+      auto const fileSize = boost::filesystem::file_size(outputFile);
+      antenna.endOfShower(0, implemen, sampleRate / 1_Hz);
+      CHECK(boost::filesystem::file_size(outputFile) > fileSize);
     }
 
-  } // END: SECTION("TimeDomainAntenna")
+    // Check the YAML file output
+    auto const config = antenna.getConfig();
+    CHECK(config["type"].as<std::string>() == "TimeDomainAntenna");
+    CHECK(config["start_time"].as<double>() == tStart / 1_ns);
+    CHECK(config["duration"].as<double>() == duration / 1_ns);
+    CHECK(config["sample_rate"].as<double>() == sampleRate / 1_GHz);
+  } // END: SECTION("TimeDomainAntenna Library")
 
 } // END: TEST_CASE("Antennas")