From 60bed2bfaed71a40e9360617925831010a6d76e9 Mon Sep 17 00:00:00 2001
From: Marvin Gottowik <marvingottowik@web.de>
Date: Wed, 18 Sep 2024 11:49:33 +0200
Subject: [PATCH] rename all antennas to observers

---
 applications/c8_air_shower.cpp                |  38 +-
 corsika/detail/modules/radio/CoREAS.inl       |  46 +-
 corsika/detail/modules/radio/RadioProcess.inl |  86 ++--
 corsika/detail/modules/radio/ZHS.inl          |  88 ++--
 .../detail/modules/radio/antennas/Antenna.inl |  36 --
 .../radio/detectors/AntennaCollection.inl     |  45 --
 .../radio/detectors/ObserverCollection.inl    |  45 ++
 .../modules/radio/observers/Observer.inl      |  36 ++
 .../TimeDomainObserver.inl}                   |  38 +-
 .../radio/propagators/DummyTestPropagator.inl |   2 +-
 .../NumericalIntegratingPropagator.inl        |   2 +-
 .../TabulatedFlatAtmospherePropagator.inl     |   2 +-
 corsika/modules/radio/CoREAS.hpp              |   4 +-
 corsika/modules/radio/RadioProcess.hpp        |  18 +-
 corsika/modules/radio/ZHS.hpp                 |   4 +-
 .../radio/detectors/AntennaCollection.hpp     |  69 ---
 .../radio/detectors/ObserverCollection.hpp    |  69 +++
 .../Antenna.hpp => observers/Observer.hpp}    |  48 +-
 .../TimeDomainObserver.hpp}                   |  50 +--
 .../radio/propagators/DummyTestPropagator.hpp |   6 +-
 .../NumericalIntegratingPropagator.hpp        |   6 +-
 .../radio/propagators/RadioPropagator.hpp     |   4 +-
 .../TabulatedFlatAtmospherePropagator.hpp     |   4 +-
 examples/cascade_examples/radio_em_shower.cpp |  42 +-
 .../synchrotron_clover_leaf.cpp               |  24 +-
 .../synchrotron_test_C8tracking.cpp           |  22 +-
 .../synchrotron_test_manual_tracking.cpp      |  40 +-
 python/corsika/io/outputs/radio_process.py    |  76 ++--
 python/examples/radio_emission.py             |  95 ++--
 tests/modules/testRadio.cpp                   | 424 +++++++++---------
 30 files changed, 735 insertions(+), 734 deletions(-)
 delete mode 100644 corsika/detail/modules/radio/antennas/Antenna.inl
 delete mode 100644 corsika/detail/modules/radio/detectors/AntennaCollection.inl
 create mode 100644 corsika/detail/modules/radio/detectors/ObserverCollection.inl
 create mode 100644 corsika/detail/modules/radio/observers/Observer.inl
 rename corsika/detail/modules/radio/{antennas/TimeDomainAntenna.inl => observers/TimeDomainObserver.inl} (76%)
 delete mode 100644 corsika/modules/radio/detectors/AntennaCollection.hpp
 create mode 100644 corsika/modules/radio/detectors/ObserverCollection.hpp
 rename corsika/modules/radio/{antennas/Antenna.hpp => observers/Observer.hpp} (64%)
 rename corsika/modules/radio/{antennas/TimeDomainAntenna.hpp => observers/TimeDomainObserver.hpp} (71%)

diff --git a/applications/c8_air_shower.cpp b/applications/c8_air_shower.cpp
index ef86670d9..5383e95c2 100644
--- a/applications/c8_air_shower.cpp
+++ b/applications/c8_air_shower.cpp
@@ -69,9 +69,9 @@
 #include <corsika/modules/radio/CoREAS.hpp>
 #include <corsika/modules/radio/RadioProcess.hpp>
 #include <corsika/modules/radio/ZHS.hpp>
-#include <corsika/modules/radio/antennas/Antenna.hpp>
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
+#include <corsika/modules/radio/observers/Observer.hpp>
+#include <corsika/modules/radio/observers/TimeDomainObserver.hpp>
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
 #include <corsika/modules/radio/propagators/TabulatedFlatAtmospherePropagator.hpp>
 
 #include <corsika/setup/SetupStack.hpp>
@@ -271,7 +271,7 @@ int main(int argc, char** argv) {
   bool multithin = false;
   app.add_flag("--multithin", multithin, "keep thinned particles (with weight=0)")
       ->group("Thinning");
-  app.add_option("--ring", "concentric ring of star shape pattern of antennas")
+  app.add_option("--ring", "concentric ring of star shape pattern of observers")
       ->default_val(0)
       ->check(CLI::Range(0, 20))
       ->group("Radio");
@@ -527,14 +527,14 @@ int main(int argc, char** argv) {
   auto const radius_{ring_number * 25_m};
   const int rr_ = static_cast<int>(radius_ / 1_m);
 
-  // Radio antennas and relevant information
-  // the antenna time variables
+  // Radio observers and relevant information
+  // the observer time variables
   const TimeType duration_{4e-7_s};
   const InverseTimeType sampleRate_{1e+9_Hz};
 
-  // the antenna collection for CoREAS and ZHS
-  AntennaCollection<TimeDomainAntenna> detectorCoREAS;
-  AntennaCollection<TimeDomainAntenna> detectorZHS;
+  // the observer collection for CoREAS and ZHS
+  ObserverCollection<TimeDomainObserver> detectorCoREAS;
+  ObserverCollection<TimeDomainObserver> detectorZHS;
 
   auto const showerCoreX_{showerCore.getCoordinates().getX()};
   auto const showerCoreY_{showerCore.getCoordinates().getY()};
@@ -544,34 +544,34 @@ int main(int argc, char** argv) {
   auto const triggerpoint_{Point(rootCS, injectionPosX_, injectionPosY_, injectionPosZ_)};
 
   if (ring_number != 0) {
-    // setup CoREAS antennas - use the for loop for star shape pattern
+    // setup CoREAS observers - use the for loop for star shape pattern
     for (auto phi_1 = 0; phi_1 <= 315; phi_1 += 45) {
       auto phiRad_1 = phi_1 / 180. * M_PI;
       auto const point_1{Point(rootCS, showerCoreX_ + radius_ * cos(phiRad_1),
                                showerCoreY_ + radius_ * sin(phiRad_1),
                                constants::EarthRadius::Mean)};
-      std::cout << "Antenna point CoREAS: " << point_1 << std::endl;
+      std::cout << "Observer point CoREAS: " << point_1 << std::endl;
       auto triggertime_1{(triggerpoint_ - point_1).getNorm() / constants::c};
       std::string name_1 = "CoREAS_R=" + std::to_string(rr_) +
                            "_m--Phi=" + std::to_string(phi_1) + "degrees";
-      TimeDomainAntenna antenna_1(name_1, point_1, rootCS, triggertime_1, duration_,
-                                  sampleRate_, triggertime_1);
-      detectorCoREAS.addAntenna(antenna_1);
+      TimeDomainObserver observer_1(name_1, point_1, rootCS, triggertime_1, duration_,
+                                   sampleRate_, triggertime_1);
+      detectorCoREAS.addObserver(observer_1);
     }
 
-    // setup ZHS antennas - use the for loop for star shape pattern
+    // setup ZHS observers - use the for loop for star shape pattern
     for (auto phi_ = 0; phi_ <= 315; phi_ += 45) {
       auto phiRad_ = phi_ / 180. * M_PI;
       auto const point_{Point(rootCS, showerCoreX_ + radius_ * cos(phiRad_),
                               showerCoreY_ + radius_ * sin(phiRad_),
                               constants::EarthRadius::Mean)};
-      std::cout << "Antenna point ZHS: " << point_ << std::endl;
+      std::cout << "Observer point ZHS: " << point_ << std::endl;
       auto triggertime_{(triggerpoint_ - point_).getNorm() / constants::c};
       std::string name_ =
           "ZHS_R=" + std::to_string(rr_) + "_m--Phi=" + std::to_string(phi_) + "degrees";
-      TimeDomainAntenna antenna_(name_, point_, rootCS, triggertime_, duration_,
-                                 sampleRate_, triggertime_);
-      detectorZHS.addAntenna(antenna_);
+      TimeDomainObserver observer_2(name_, point_, rootCS, triggertime_, duration_,
+                                  sampleRate_, triggertime_);
+      detectorZHS.addObserver(observer_2);
     }
   }
   LengthType const step = 1_m;
diff --git a/corsika/detail/modules/radio/CoREAS.inl b/corsika/detail/modules/radio/CoREAS.inl
index 2f70b8525..a779311db 100644
--- a/corsika/detail/modules/radio/CoREAS.inl
+++ b/corsika/detail/modules/radio/CoREAS.inl
@@ -54,16 +54,16 @@ namespace corsika {
       // set threshold for application of ZHS-like approximation.
       const double approxThreshold_{1.0e-3};
 
-      // loop over each antenna in the antenna collection (detector)
-      for (auto& antenna : antennas_.getAntennas()) {
+      // loop over each observer in the observer collection (detector)
+      for (auto& observer : observers_.getObservers()) {
 
-        // get the SignalPathCollection (path1) from the start "endpoint" to the antenna.
+        // get the SignalPathCollection (path1) from the start "endpoint" to the observer.
         auto paths1{this->propagator_.propagate(step.getParticlePre(), startPoint_,
-                                                antenna.getLocation())};
+                                                observer.getLocation())};
 
-        // get the SignalPathCollection (path2) from the end "endpoint" to the antenna.
+        // get the SignalPathCollection (path2) from the end "endpoint" to the observer.
         auto paths2{this->propagator_.propagate(step.getParticlePre(), endPoint_,
-                                                antenna.getLocation())};
+                                                observer.getLocation())};
 
         // LCOV_EXCL_START
         // This should never happen unless someone implements a bad propagator
@@ -140,14 +140,14 @@ namespace corsika {
           // calculate receive time for endpoint
           auto endPointReceiveTime_{endTime_ + paths2[i].propagation_time_};
 
-          // get unit vector for startpoint at antenna location
+          // get unit vector for startpoint at observer location
           auto ReceiveVectorStart_{paths1[i].receive_};
 
-          // get unit vector for endpoint at antenna location
+          // get unit vector for endpoint at observer location
           auto ReceiveVectorEnd_{paths2[i].receive_};
 
           // perform ZHS-like calculation close to Cherenkov angle and for refractive
-          // index at antenna location greater than 1
+          // index at observer location greater than 1
           if ((paths1[i].refractive_index_destination_ > 1) &&
               ((std::fabs(preDoppler_) < approxThreshold_) ||
                (std::fabs(postDoppler_) < approxThreshold_))) {
@@ -165,9 +165,9 @@ namespace corsika {
             TimeType const midTime_{(startTime_ + endTime_) * 0.5};
 
             // get the SignalPathCollection (path3) from the middle "endpoint" to the
-            // antenna.
+            // observer.
             auto paths3{this->propagator_.propagate(step.getParticlePre(), midPoint_,
-                                                    antenna.getLocation())};
+                                                    observer.getLocation())};
 
             // now loop over the paths for endpoint that we got above
             for (auto const& path : paths3) {
@@ -202,8 +202,8 @@ namespace corsika {
 
               // CoREAS calculation -> get ElectricFieldVector for "midPoint"
               ElectricFieldVector EVmid_ = (path.emit_.cross(path.emit_.cross(beta_))) /
-                                           midDoppler_ / path.R_distance_ * constants_ *
-                                           antenna.getSampleRate();
+                                            midDoppler_ / path.R_distance_ * constants_ *
+                                            observer.getSampleRate();
 
               ElectricFieldVector EV1_{EVmid_};
               ElectricFieldVector EV2_{EVmid_ * (-1.0)};
@@ -222,7 +222,7 @@ namespace corsika {
                 endPointReceiveTime_ = midPointReceiveTime_ - 0.5 * deltaT_;
               }
 
-              TimeType const gridResolution_{1 / antenna.getSampleRate()};
+              TimeType const gridResolution_{1 / observer.getSampleRate()};
               deltaT_ = endPointReceiveTime_ - startPointReceiveTime_;
 
               // redistribute contributions over time scale defined by the observation
@@ -304,8 +304,8 @@ namespace corsika {
 
               // 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_);
+              observer.receive(startPointReceiveTime_, ReceiveVectorStart_, EV1_);
+              observer.receive(endPointReceiveTime_, ReceiveVectorEnd_, EV2_);
             } // End of looping over paths3
 
           } // end of ZHS-like approximation
@@ -314,16 +314,16 @@ namespace corsika {
             // 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();
+                paths1[i].R_distance_ * constants_ * observer.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();
+                paths2[i].R_distance_ * constants_ * (-1.0) * observer.getSampleRate();
 
             if ((preDoppler_ < 1.e-9) || (postDoppler_ < 1.e-9)) {
 
-              TimeType const gridResolution_{1 / antenna.getSampleRate()};
+              TimeType const gridResolution_{1 / observer.getSampleRate()};
               TimeType deltaT_{endPointReceiveTime_ - startPointReceiveTime_};
 
               if (abs(deltaT_) < (gridResolution_)) {
@@ -372,15 +372,15 @@ namespace corsika {
                 } // 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_);
+            observer.receive(startPointReceiveTime_, ReceiveVectorStart_, EV1_);
+            observer.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
+      }   // End of looping over observer
 
       return ProcessReturn::Ok;
     }
   } // End of simulate method
 
-} // namespace corsika
\ No newline at end of file
+} // namespace corsika
diff --git a/corsika/detail/modules/radio/RadioProcess.inl b/corsika/detail/modules/radio/RadioProcess.inl
index 561030f71..d38bed0a0 100644
--- a/corsika/detail/modules/radio/RadioProcess.inl
+++ b/corsika/detail/modules/radio/RadioProcess.inl
@@ -11,32 +11,32 @@
 
 namespace corsika {
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
   inline TRadioImpl&
-  RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::implementation() {
+  RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::implementation() {
     return static_cast<TRadioImpl&>(*this);
   }
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
   inline TRadioImpl const&
-  RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::implementation() const {
+  RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::implementation() const {
     return static_cast<TRadioImpl const&>(*this);
   }
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
-  inline RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::RadioProcess(
-      TAntennaCollection& antennas, TPropagator& propagator)
-      : antennas_(antennas)
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
+  inline RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::RadioProcess(
+      TObserverCollection& observers, TPropagator& propagator)
+      : observers_(observers)
       , propagator_(propagator) {}
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
   template <typename Particle>
-  inline ProcessReturn RadioProcess<TAntennaCollection, TRadioImpl,
+  inline ProcessReturn RadioProcess<TObserverCollection, TRadioImpl,
                                     TPropagator>::doContinuous(const Step<Particle>& step,
                                                                const bool) {
 
-    // return immediately if radio process does not have any antennas
-    if (antennas_.size() == 0) return ProcessReturn::Ok;
+    // return immediately if radio process does not have any observers
+    if (observers_.size() == 0) return ProcessReturn::Ok;
 
     // we want the following particles:
     // Code::Electron & Code::Positron
@@ -57,21 +57,21 @@ namespace corsika {
     //}
   }
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
   template <typename Particle, typename Track>
   inline LengthType
-  RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::getMaxStepLength(
+  RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::getMaxStepLength(
       [[maybe_unused]] const Particle& vParticle,
       [[maybe_unused]] const Track& vTrack) const {
     return meter * std::numeric_limits<double>::infinity();
   }
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
-  inline void RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::startOfLibrary(
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
+  inline void RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::startOfLibrary(
       const boost::filesystem::path& directory) {
 
     // setup the streamer
-    output_.initStreamer((directory / ("antennas.parquet")).string());
+    output_.initStreamer((directory / ("observers.parquet")).string());
     // LCOV_EXCL_START
     // build the schema
     output_.addField("Time", parquet::Repetition::REQUIRED, parquet::Type::DOUBLE,
@@ -90,34 +90,34 @@ namespace corsika {
     output_.buildStreamer();
   }
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
-  inline void RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::endOfShower(
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
+  inline void RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::endOfShower(
       const unsigned int) {
 
-    // loop over every antenna and instruct them to
-    // flush data to disk, and then reset the antenna
+    // loop over every observer and instruct them to
+    // flush data to disk, and then reset the observer
     // before the next event
-    for (auto& antenna : antennas_.getAntennas()) {
+    for (auto& observer : observers_.getObservers()) {
 
-      auto const sampleRate = antenna.getSampleRate() * 1_s;
+      auto const sampleRate = observer.getSampleRate() * 1_s;
       auto const radioImplementation =
           static_cast<std::string>(this->implementation().algorithm);
 
-      // get the axis labels for this antenna and write the first row.
-      axistype axis = antenna.implementation().getAxis();
+      // get the axis labels for this observer and write the first row.
+      axistype axis = observer.implementation().getAxis();
 
       // get the copy of the waveform data for this event
-      std::vector<double> const& dataX = antenna.implementation().getWaveformX();
-      std::vector<double> const& dataY = antenna.implementation().getWaveformY();
-      std::vector<double> const& dataZ = antenna.implementation().getWaveformZ();
+      std::vector<double> const& dataX = observer.implementation().getWaveformX();
+      std::vector<double> const& dataY = observer.implementation().getWaveformY();
+      std::vector<double> const& dataZ = observer.implementation().getWaveformZ();
 
       // check for the axis name
       std::string label = "Unknown";
-      if (antenna.getDomainLabel() == "Time") {
+      if (observer.getDomainLabel() == "Time") {
         label = "Time";
       }
       // LCOV_EXCL_START
-      else if (antenna.getDomainLabel() == "Frequency") {
+      else if (observer.getDomainLabel() == "Frequency") {
         label = "Frequency";
       }
       // LCOV_EXCL_STOP
@@ -141,7 +141,7 @@ namespace corsika {
         }
       }
 
-      antenna.reset();
+      observer.reset();
     }
     output_.closeStreamer();
 
@@ -149,8 +149,8 @@ namespace corsika {
     showerId_++;
   }
 
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
-  inline YAML::Node RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>::getConfig()
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
+  inline YAML::Node RadioProcess<TObserverCollection, TRadioImpl, TPropagator>::getConfig()
       const {
 
     // top-level YAML node
@@ -164,18 +164,18 @@ namespace corsika {
     config["units"]["electric field"] = "V/m";
     config["units"]["distance"] = "m";
 
-    for (auto& antenna : antennas_.getAntennas()) {
-      // get the name/location of this antenna
-      auto name = antenna.getName();
-      auto location = antenna.getLocation().getCoordinates();
+    for (auto& observer : observers_.getObservers()) {
+      // get the name/location of this observer
+      auto name = observer.getName();
+      auto location = observer.getLocation().getCoordinates();
 
-      // get the antennas config
-      config["antennas"][name] = antenna.getConfig();
+      // get the observers config
+      config["observers"][name] = observer.getConfig();
 
-      // write the location of this antenna
-      config["antennas"][name]["location"].push_back(location.getX() / 1_m);
-      config["antennas"][name]["location"].push_back(location.getY() / 1_m);
-      config["antennas"][name]["location"].push_back(location.getZ() / 1_m);
+      // write the location of this observer
+      config["observers"][name]["location"].push_back(location.getX() / 1_m);
+      config["observers"][name]["location"].push_back(location.getY() / 1_m);
+      config["observers"][name]["location"].push_back(location.getZ() / 1_m);
     }
 
     return config;
diff --git a/corsika/detail/modules/radio/ZHS.inl b/corsika/detail/modules/radio/ZHS.inl
index ccd824ef7..7881f6a5a 100644
--- a/corsika/detail/modules/radio/ZHS.inl
+++ b/corsika/detail/modules/radio/ZHS.inl
@@ -45,15 +45,15 @@ namespace corsika {
 
       auto const constants{charge * emConstant_ * thinningWeight};
 
-      // we loop over each antenna in the collection
-      for (auto& antenna : antennas_.getAntennas()) {
+      // we loop over each observer in the collection
+      for (auto& observer : observers_.getObservers()) {
         auto midPaths{this->propagator_.propagate(step.getParticlePre(), midPoint,
-                                                  antenna.getLocation())};
+                                                  observer.getLocation())};
         // Loop over midPaths, first check Fraunhoffer limit
         for (size_t i{0}; i < midPaths.size(); i++) {
           double const uTimesK{beta.dot(midPaths[i].emit_) / betaModule};
           double const sinTheta2{1. - uTimesK * uTimesK};
-          LengthType const lambda{constants::c / antenna.getSampleRate()};
+          LengthType const lambda{constants::c / observer.getSampleRate()};
           double const fraunhLimit{sinTheta2 * trackLength * trackLength /
                                    midPaths[i].R_distance_ / lambda * 2 * M_PI};
           // Checks if we are in fraunhoffer domain
@@ -72,7 +72,7 @@ namespace corsika {
               auto const newHalfVector{(point1 - point2) / 2.};
               auto const newMidPoint{point2 + newHalfVector};
               auto const newMidPaths{this->propagator_.propagate(
-                  step.getParticlePre(), newMidPoint, antenna.getLocation())};
+                  step.getParticlePre(), newMidPoint, observer.getLocation())};
               // A function for calculating the field should be made since it is repeated
               // later
               for (size_t k{0}; k < newMidPaths.size(); k++) {
@@ -98,10 +98,10 @@ namespace corsika {
                 } // end if statement for time structure
 
                 double const startBin{std::floor(
-                    (detectionTime1 - antenna.getStartTime()) * antenna.getSampleRate() +
+                    (detectionTime1 - observer.getStartTime()) * observer.getSampleRate() +
                     0.5)};
-                double const endBin{std::floor((detectionTime2 - antenna.getStartTime()) *
-                                                   antenna.getSampleRate() +
+                double const endBin{std::floor((detectionTime2 - observer.getStartTime()) *
+                                                   observer.getSampleRate() +
                                                0.5)};
 
                 auto const betaPerp{
@@ -112,42 +112,42 @@ namespace corsika {
                   // track contained in bin
                   // if not in Cerenkov angle then
                   if (std::fabs(denominator) > 1.e-15) {
-                    double const f{std::fabs((detectionTime2 * antenna.getSampleRate() -
-                                              detectionTime1 * antenna.getSampleRate()))};
+                    double const f{std::fabs((detectionTime2 * observer.getSampleRate() -
+                                              detectionTime1 * observer.getSampleRate()))};
                     VectorPotential const Vp = betaPerp * sign * constants * f /
                                                denominator / newMidPaths[k].R_distance_;
-                    antenna.receive(detectionTime2, betaPerp, Vp);
+                    observer.receive(detectionTime2, betaPerp, Vp);
                   } else { // If emission in Cerenkov angle => approximation
-                    double const f{time2 * antenna.getSampleRate() -
-                                   time1 * antenna.getSampleRate()};
+                    double const f{time2 * observer.getSampleRate() -
+                                   time1 * observer.getSampleRate()};
                     VectorPotential const Vp =
                         betaPerp * sign * constants * f / newMidPaths[k].R_distance_;
-                    antenna.receive(detectionTime2, betaPerp, Vp);
+                    observer.receive(detectionTime2, betaPerp, Vp);
                   } // end if Cerenkov angle approx
                 } else {
                   /*Track is contained in more than one bin*/
                   int const numberOfBins{static_cast<int>(endBin - startBin)};
-                  // first contribution/ plus 1 bin minus 0.5 from new antenna ruonding
+                  // first contribution/ plus 1 bin minus 0.5 from new observer ruonding
                   double f{std::fabs(startBin + 0.5 -
-                                     (detectionTime1 - antenna.getStartTime()) *
-                                         antenna.getSampleRate())};
+                                     (detectionTime1 - observer.getStartTime()) *
+                                         observer.getSampleRate())};
                   VectorPotential Vp = betaPerp * sign * constants * f / denominator /
                                        newMidPaths[k].R_distance_;
-                  antenna.receive(detectionTime1, betaPerp, Vp);
+                  observer.receive(detectionTime1, betaPerp, Vp);
                   // intermidiate contributions
                   for (int it{1}; it < numberOfBins; ++it) {
                     Vp = betaPerp * constants / denominator / newMidPaths[k].R_distance_;
-                    antenna.receive(detectionTime1 +
-                                        static_cast<double>(it) / antenna.getSampleRate(),
+                    observer.receive(detectionTime1 +
+                                        static_cast<double>(it) / observer.getSampleRate(),
                                     betaPerp, Vp);
                   } // end loop over bins in which potential vector is not zero
-                  // final contribution// f +0.5 from new antenna rounding
-                  f = std::fabs((detectionTime2 - antenna.getStartTime()) *
-                                    antenna.getSampleRate() +
+                  // final contribution// f +0.5 from new observer rounding
+                  f = std::fabs((detectionTime2 - observer.getStartTime()) *
+                                    observer.getSampleRate() +
                                 0.5 - endBin);
                   Vp = betaPerp * sign * constants * f / denominator /
                        newMidPaths[k].R_distance_;
-                  antenna.receive(detectionTime2, betaPerp, Vp);
+                  observer.receive(detectionTime2, betaPerp, Vp);
                 } // end if statement for track in multiple bins
 
               } // end of loop over newMidPaths
@@ -178,11 +178,11 @@ namespace corsika {
               sign = -1.;
             } // end if statement for time structure
 
-            double const startBin{std::floor((detectionTime1 - antenna.getStartTime()) *
-                                                 antenna.getSampleRate() +
+            double const startBin{std::floor((detectionTime1 - observer.getStartTime()) *
+                                                 observer.getSampleRate() +
                                              0.5)};
-            double const endBin{std::floor((detectionTime2 - antenna.getStartTime()) *
-                                               antenna.getSampleRate() +
+            double const endBin{std::floor((detectionTime2 - observer.getStartTime()) *
+                                               observer.getSampleRate() +
                                            0.5)};
 
             auto const betaPerp{midPaths[i].emit_.cross(beta.cross(midPaths[i].emit_))};
@@ -193,18 +193,18 @@ namespace corsika {
               // track contained in bin
               // if not in Cerenkov angle then
               if (std::fabs(denominator) > 1.e-15) {
-                double const f{std::fabs((detectionTime2 * antenna.getSampleRate() -
-                                          detectionTime1 * antenna.getSampleRate()))};
+                double const f{std::fabs((detectionTime2 * observer.getSampleRate() -
+                                          detectionTime1 * observer.getSampleRate()))};
 
                 VectorPotential const Vp = betaPerp * sign * constants * f / denominator /
                                            midPaths[i].R_distance_;
-                antenna.receive(detectionTime2, betaPerp, Vp);
+                observer.receive(detectionTime2, betaPerp, Vp);
               } else { // If emission in Cerenkov angle => approximation
-                double const f{endTime * antenna.getSampleRate() -
-                               startTime * antenna.getSampleRate()};
+                double const f{endTime * observer.getSampleRate() -
+                               startTime * observer.getSampleRate()};
                 VectorPotential const Vp =
                     betaPerp * sign * constants * f / midPaths[i].R_distance_;
-                antenna.receive(detectionTime2, betaPerp, Vp);
+                observer.receive(detectionTime2, betaPerp, Vp);
               } // end if Cerenkov angle approx
             } else {
               /*Track is contained in more than one bin*/
@@ -212,34 +212,34 @@ namespace corsika {
               // TODO: should we check for Cerenkov angle?
               // first contribution
               double f{std::fabs(startBin + 0.5 -
-                                 (detectionTime1 - antenna.getStartTime()) *
-                                     antenna.getSampleRate())};
+                                 (detectionTime1 - observer.getStartTime()) *
+                                     observer.getSampleRate())};
               VectorPotential Vp =
                   betaPerp * sign * constants * f / denominator / midPaths[i].R_distance_;
-              antenna.receive(detectionTime1, betaPerp, Vp);
+              observer.receive(detectionTime1, betaPerp, Vp);
               // intermediate contributions
               for (int it{1}; it < numberOfBins; ++it) {
                 Vp = betaPerp * sign * constants / denominator / midPaths[i].R_distance_;
-                antenna.receive(
-                    detectionTime1 + static_cast<double>(it) / antenna.getSampleRate(),
+                observer.receive(
+                    detectionTime1 + static_cast<double>(it) / observer.getSampleRate(),
                     betaPerp, Vp);
               } // end loop over bins in which potential vector is not zero
               // final contribution
-              f = std::fabs((detectionTime2 - antenna.getStartTime()) *
-                                antenna.getSampleRate() +
+              f = std::fabs((detectionTime2 - observer.getStartTime()) *
+                                observer.getSampleRate() +
                             0.5 - endBin);
               Vp =
                   betaPerp * sign * constants * f / denominator / midPaths[i].R_distance_;
-              antenna.receive(detectionTime2, betaPerp, Vp);
+              observer.receive(detectionTime2, betaPerp, Vp);
             } // end if statement for track in multiple bins
 
           } // finish if statement of track in fraunhoffer or not
 
         } // end loop over mid paths
 
-      } // END: loop over antennas
+      } // END: loop over observers
       return ProcessReturn::Ok;
     }
   } // end simulate
 
-} // namespace corsika
\ No newline at end of file
+} // namespace corsika
diff --git a/corsika/detail/modules/radio/antennas/Antenna.inl b/corsika/detail/modules/radio/antennas/Antenna.inl
deleted file mode 100644
index cb2967f63..000000000
--- a/corsika/detail/modules/radio/antennas/Antenna.inl
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu
- *
- * This software is distributed under the terms of the GNU General Public
- * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
- * the license.
- */
-#pragma once
-
-#include <corsika/modules/radio/antennas/Antenna.hpp>
-
-namespace corsika {
-
-  template <typename TAntennaImpl>
-  inline Antenna<TAntennaImpl>::Antenna(std::string const& name, Point const& location,
-                                        CoordinateSystemPtr const& coordinateSystem)
-      : name_(name)
-      , location_(location)
-      , coordinateSystem_(coordinateSystem) {}
-
-  template <typename TAntennaImpl>
-  inline Point const& Antenna<TAntennaImpl>::getLocation() const {
-    return location_;
-  }
-
-  template <typename TAntennaImpl>
-  inline std::string const& Antenna<TAntennaImpl>::getName() const {
-    return name_;
-  }
-
-  template <typename TAntennaImpl>
-  inline TAntennaImpl& Antenna<TAntennaImpl>::implementation() {
-    return static_cast<TAntennaImpl&>(*this);
-  }
-
-} // namespace corsika
diff --git a/corsika/detail/modules/radio/detectors/AntennaCollection.inl b/corsika/detail/modules/radio/detectors/AntennaCollection.inl
deleted file mode 100644
index d985bb980..000000000
--- a/corsika/detail/modules/radio/detectors/AntennaCollection.inl
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu
- *
- * This software is distributed under the terms of the GNU General Public
- * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
- * the license.
- */
-#pragma once
-
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
-
-namespace corsika {
-
-  template <typename TAntennaImpl>
-  inline void AntennaCollection<TAntennaImpl>::addAntenna(TAntennaImpl const& antenna) {
-    antennas_.push_back(antenna);
-  }
-
-  template <typename TAntennaImpl>
-  inline TAntennaImpl& AntennaCollection<TAntennaImpl>::at(std::size_t const i) {
-    return antennas_.at(i);
-  }
-
-  template <typename TAntennaImpl>
-  inline TAntennaImpl const& AntennaCollection<TAntennaImpl>::at(
-      std::size_t const i) const {
-    return antennas_.at(i);
-  }
-
-  template <typename TAntennaImpl>
-  inline int AntennaCollection<TAntennaImpl>::size() const {
-    return antennas_.size();
-  }
-
-  template <typename TAntennaImpl>
-  inline std::vector<TAntennaImpl>& AntennaCollection<TAntennaImpl>::getAntennas() {
-    return antennas_;
-  }
-
-  template <typename TAntennaImpl>
-  inline void AntennaCollection<TAntennaImpl>::reset() {
-    std::for_each(antennas_.begin(), antennas_.end(), std::mem_fn(&TAntennaImpl::reset));
-  }
-
-} // namespace corsika
diff --git a/corsika/detail/modules/radio/detectors/ObserverCollection.inl b/corsika/detail/modules/radio/detectors/ObserverCollection.inl
new file mode 100644
index 000000000..c754581a2
--- /dev/null
+++ b/corsika/detail/modules/radio/detectors/ObserverCollection.inl
@@ -0,0 +1,45 @@
+/*
+ * (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+#pragma once
+
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
+
+namespace corsika {
+
+  template <typename TObserverImpl>
+  inline void ObserverCollection<TObserverImpl>::addObserver(TObserverImpl const& observer) {
+    observers_.push_back(observer);
+  }
+
+  template <typename TObserverImpl>
+  inline TObserverImpl& ObserverCollection<TObserverImpl>::at(std::size_t const i) {
+    return observers_.at(i);
+  }
+
+  template <typename TObserverImpl>
+  inline TObserverImpl const& ObserverCollection<TObserverImpl>::at(
+      std::size_t const i) const {
+    return observers_.at(i);
+  }
+
+  template <typename TObserverImpl>
+  inline int ObserverCollection<TObserverImpl>::size() const {
+    return observers_.size();
+  }
+
+  template <typename TObserverImpl>
+  inline std::vector<TObserverImpl>& ObserverCollection<TObserverImpl>::getObservers() {
+    return observers_;
+  }
+
+  template <typename TObserverImpl>
+  inline void ObserverCollection<TObserverImpl>::reset() {
+    std::for_each(observers_.begin(), observers_.end(), std::mem_fn(&TObserverImpl::reset));
+  }
+
+} // namespace corsika
diff --git a/corsika/detail/modules/radio/observers/Observer.inl b/corsika/detail/modules/radio/observers/Observer.inl
new file mode 100644
index 000000000..475ccb30b
--- /dev/null
+++ b/corsika/detail/modules/radio/observers/Observer.inl
@@ -0,0 +1,36 @@
+/*
+ * (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+#pragma once
+
+#include <corsika/modules/radio/observers/Observer.hpp>
+
+namespace corsika {
+
+  template <typename TObserverImpl>
+  inline Observer<TObserverImpl>::Observer(std::string const& name, Point const& location,
+                                           CoordinateSystemPtr const& coordinateSystem)
+      : name_(name)
+      , location_(location)
+      , coordinateSystem_(coordinateSystem) {}
+
+  template <typename TObserverImpl>
+  inline Point const& Observer<TObserverImpl>::getLocation() const {
+    return location_;
+  }
+
+  template <typename TObserverImpl>
+  inline std::string const& Observer<TObserverImpl>::getName() const {
+    return name_;
+  }
+
+  template <typename TObserverImpl>
+  inline TObserverImpl& Observer<TObserverImpl>::implementation() {
+    return static_cast<TObserverImpl&>(*this);
+  }
+
+} // namespace corsika
diff --git a/corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl b/corsika/detail/modules/radio/observers/TimeDomainObserver.inl
similarity index 76%
rename from corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl
rename to corsika/detail/modules/radio/observers/TimeDomainObserver.inl
index 1a270eadb..1f228caae 100644
--- a/corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl
+++ b/corsika/detail/modules/radio/observers/TimeDomainObserver.inl
@@ -7,18 +7,18 @@
  */
 #pragma once
 
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
+#include <corsika/modules/radio/observers/TimeDomainObserver.hpp>
 
 namespace corsika {
 
-  inline TimeDomainAntenna::TimeDomainAntenna(std::string const& name,
+  inline TimeDomainObserver::TimeDomainObserver(std::string const& name,
                                               Point const& location,
                                               CoordinateSystemPtr coordinateSystem,
                                               TimeType const& start_time,
                                               TimeType const& duration,
                                               InverseTimeType const& sample_rate,
                                               TimeType const ground_hit_time)
-      : Antenna(name, location, coordinateSystem)
+      : Observer(name, location, coordinateSystem)
       , start_time_(start_time)
       , duration_(std::abs(duration / 1_s) * 1_s)
       , sample_rate_(std::abs(sample_rate / 1_Hz) * 1_Hz)
@@ -30,21 +30,21 @@ namespace corsika {
       , time_axis_(createTimeAxis()) {
     if (0_s == duration_) {
       CORSIKA_LOG_WARN(
-          "Antenna: \"{}\" has a duration of zero. Nothing will be injected into it",
+          "Observer: \"{}\" 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);
+          "Observer: \"{}\" 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.",
+          "Observer: \"{}\" was given a negative sampling rate. Set to absolute value.",
           name);
     }
   }
 
-  inline void TimeDomainAntenna::receive(
+  inline void TimeDomainObserver::receive(
       const TimeType time, [[maybe_unused]] const Vector<dimensionless_d>& receive_vector,
       const ElectricFieldVector& efield) {
 
@@ -66,7 +66,7 @@ namespace corsika {
     }
   }
 
-  inline void TimeDomainAntenna::receive(
+  inline void TimeDomainObserver::receive(
       const TimeType time, [[maybe_unused]] const Vector<dimensionless_d>& receive_vector,
       const VectorPotential& vectorP) {
 
@@ -91,15 +91,15 @@ namespace corsika {
     }
   }
 
-  inline auto const& TimeDomainAntenna::getWaveformX() const { return waveformEX_; }
+  inline auto const& TimeDomainObserver::getWaveformX() const { return waveformEX_; }
 
-  inline auto const& TimeDomainAntenna::getWaveformY() const { return waveformEY_; }
+  inline auto const& TimeDomainObserver::getWaveformY() const { return waveformEY_; }
 
-  inline auto const& TimeDomainAntenna::getWaveformZ() const { return waveformEZ_; }
+  inline auto const& TimeDomainObserver::getWaveformZ() const { return waveformEZ_; }
 
-  inline std::string const TimeDomainAntenna::getDomainLabel() { return "Time"; }
+  inline std::string const TimeDomainObserver::getDomainLabel() { return "Time"; }
 
-  inline std::vector<long double> TimeDomainAntenna::createTimeAxis() const {
+  inline std::vector<long double> TimeDomainObserver::createTimeAxis() const {
 
     // create a 1-D xtensor to store time values so we can print them later.
     std::vector<long double> times(num_bins_, 0);
@@ -117,26 +117,26 @@ namespace corsika {
     return times;
   }
 
-  inline auto const TimeDomainAntenna::getAxis() const { return time_axis_; }
+  inline auto const TimeDomainObserver::getAxis() const { return time_axis_; }
 
-  inline InverseTimeType const& TimeDomainAntenna::getSampleRate() const {
+  inline InverseTimeType const& TimeDomainObserver::getSampleRate() const {
     return sample_rate_;
   }
 
-  inline TimeType const& TimeDomainAntenna::getStartTime() const { return start_time_; }
+  inline TimeType const& TimeDomainObserver::getStartTime() const { return start_time_; }
 
-  inline void TimeDomainAntenna::reset() {
+  inline void TimeDomainObserver::reset() {
     std::fill(waveformEX_.begin(), waveformEX_.end(), 0);
     std::fill(waveformEY_.begin(), waveformEY_.end(), 0);
     std::fill(waveformEZ_.begin(), waveformEZ_.end(), 0);
   }
 
-  inline YAML::Node TimeDomainAntenna::getConfig() const {
+  inline YAML::Node TimeDomainObserver::getConfig() const {
 
     // top-level config
     YAML::Node config;
 
-    config["type"] = "TimeDomainAntenna";
+    config["type"] = "TimeDomainObserver";
     config["start time"] = start_time_ / 1_ns;
     config["duration"] = duration_ / 1_ns;
     config["number of bins"] = duration_ * sample_rate_;
diff --git a/corsika/detail/modules/radio/propagators/DummyTestPropagator.inl b/corsika/detail/modules/radio/propagators/DummyTestPropagator.inl
index 8e90fc5b3..e953556ed 100644
--- a/corsika/detail/modules/radio/propagators/DummyTestPropagator.inl
+++ b/corsika/detail/modules/radio/propagators/DummyTestPropagator.inl
@@ -31,7 +31,7 @@ namespace corsika {
      *
      */
 
-    // these are used for the direction of emission and reception of signal at the antenna
+    // these are used for the direction of emission and reception of signal at the observer
     auto const emit_{(destination - source).normalized()};
     auto const receive_{-emit_};
 
diff --git a/corsika/detail/modules/radio/propagators/NumericalIntegratingPropagator.inl b/corsika/detail/modules/radio/propagators/NumericalIntegratingPropagator.inl
index 6046d50dc..8883c7e40 100644
--- a/corsika/detail/modules/radio/propagators/NumericalIntegratingPropagator.inl
+++ b/corsika/detail/modules/radio/propagators/NumericalIntegratingPropagator.inl
@@ -31,7 +31,7 @@ namespace corsika {
      * so they are both called direction
      */
 
-    // these are used for the direction of emission and reception of signal at the antenna
+    // these are used for the direction of emission and reception of signal at the observer
     auto const emit{(destination - source).normalized()};
     auto const receive{-emit};
 
diff --git a/corsika/detail/modules/radio/propagators/TabulatedFlatAtmospherePropagator.inl b/corsika/detail/modules/radio/propagators/TabulatedFlatAtmospherePropagator.inl
index fae21a212..5fae478fb 100644
--- a/corsika/detail/modules/radio/propagators/TabulatedFlatAtmospherePropagator.inl
+++ b/corsika/detail/modules/radio/propagators/TabulatedFlatAtmospherePropagator.inl
@@ -86,7 +86,7 @@ namespace corsika {
      *
      */
 
-    // these are used for the direction of emission and reception of signal at the antenna
+    // these are used for the direction of emission and reception of signal at the observer
     auto const emit_{(destination - source).normalized()};
     auto const receive_{-emit_};
 
diff --git a/corsika/modules/radio/CoREAS.hpp b/corsika/modules/radio/CoREAS.hpp
index 8e2665e40..d238efdb7 100644
--- a/corsika/modules/radio/CoREAS.hpp
+++ b/corsika/modules/radio/CoREAS.hpp
@@ -49,10 +49,10 @@ namespace corsika {
 
     using Base =
         RadioProcess<TRadioDetector, CoREAS<TRadioDetector, TPropagator>, TPropagator>;
-    using Base::antennas_;
+    using Base::observers_;
 
   }; // end of class CoREAS
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/CoREAS.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/CoREAS.inl>
diff --git a/corsika/modules/radio/RadioProcess.hpp b/corsika/modules/radio/RadioProcess.hpp
index 1dd4c357f..334e51e49 100644
--- a/corsika/modules/radio/RadioProcess.hpp
+++ b/corsika/modules/radio/RadioProcess.hpp
@@ -20,12 +20,12 @@ namespace corsika {
    * The base interface for radio emission processes.
    *
    * TRadioImpl is the concrete implementation of the radio algorithm.
-   * TAntennaCollection is the detector instance that stores antennas
+   * TObserverCollection is the detector instance that stores observers
    * and is responsible for managing the output writing.
    */
-  template <typename TAntennaCollection, typename TRadioImpl, typename TPropagator>
+  template <typename TObserverCollection, typename TRadioImpl, typename TPropagator>
   class RadioProcess : public ContinuousProcess<
-                           RadioProcess<TAntennaCollection, TRadioImpl, TPropagator>>,
+                           RadioProcess<TObserverCollection, TRadioImpl, TPropagator>>,
                        public BaseOutput {
 
     /*
@@ -44,17 +44,17 @@ namespace corsika {
     TRadioImpl const& implementation() const;
 
   protected:
-    TAntennaCollection& antennas_; ///< The radio antennas we store into.
-    TPropagator propagator_;       ///< The propagator implementation.
-    unsigned int showerId_{0};     ///< The current event ID.
-    ParquetStreamer output_;       //!< The parquet streamer for this process.
+    TObserverCollection& observers_; ///< The radio observers we store into.
+    TPropagator propagator_;         ///< The propagator implementation.
+    unsigned int showerId_{0};       ///< The current event ID.
+    ParquetStreamer output_;         //!< The parquet streamer for this process.
 
   public:
     using axistype = std::vector<long double>;
     /**
      * Construct a new RadioProcess.
      */
-    RadioProcess(TAntennaCollection& antennas, TPropagator& propagator);
+    RadioProcess(TObserverCollection& observers, TPropagator& propagator);
 
     /**
      * Perform the continuous process (radio emission).
@@ -106,4 +106,4 @@ namespace corsika {
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/RadioProcess.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/RadioProcess.inl>
diff --git a/corsika/modules/radio/ZHS.hpp b/corsika/modules/radio/ZHS.hpp
index 8715e3f98..577419910 100644
--- a/corsika/modules/radio/ZHS.hpp
+++ b/corsika/modules/radio/ZHS.hpp
@@ -52,10 +52,10 @@ namespace corsika {
   private:
     using Base =
         RadioProcess<TRadioDetector, ZHS<TRadioDetector, TPropagator>, TPropagator>;
-    using Base::antennas_;
+    using Base::observers_;
 
   }; // END: class ZHS
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/ZHS.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/ZHS.inl>
diff --git a/corsika/modules/radio/detectors/AntennaCollection.hpp b/corsika/modules/radio/detectors/AntennaCollection.hpp
deleted file mode 100644
index 368be18d9..000000000
--- a/corsika/modules/radio/detectors/AntennaCollection.hpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu
- *
- * This software is distributed under the terms of the GNU General Public
- * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
- * the license.
- */
-#pragma once
-
-namespace corsika {
-
-  /**
-   * The base interface for radio detectors.
-   * At the moment it is a collection of antennas with the same implementation.
-   */
-
-  template <typename TAntennaImpl>
-  class AntennaCollection {
-
-    /**
-     * The collection of antennas used in this simulation.
-     */
-    std::vector<TAntennaImpl> antennas_;
-
-  public:
-    /**
-     * Add an antenna to this radio process.
-     *
-     * @param antenna    The antenna to add
-     */
-    void addAntenna(TAntennaImpl const& antenna);
-
-    /**
-     * Get the specific antenna at that place in the collection
-     *
-     * @param index in the collection
-     */
-    TAntennaImpl& at(std::size_t const i);
-
-    TAntennaImpl const& at(std::size_t const i) const;
-
-    /**
-     * Get the number of antennas in the collection
-     */
-    int size() const;
-
-    /**
-     * Get a *non*-const reference to the collection of antennas.
-     *
-     * @returns    An iterable mutable reference to the antennas.
-     */
-    std::vector<TAntennaImpl>& getAntennas();
-
-    /**
-     * Get a const reference to the collection of antennas.
-     *
-     * @returns    An iterable mutable reference to the antennas.
-     */
-    std::vector<TAntennaImpl> const& getAntennas() const;
-
-    /**
-     * Reset all the antenna waveforms.
-     */
-    void reset();
-  }; // END: class RadioDetector
-
-} // namespace corsika
-
-#include <corsika/detail/modules/radio/detectors/AntennaCollection.inl>
diff --git a/corsika/modules/radio/detectors/ObserverCollection.hpp b/corsika/modules/radio/detectors/ObserverCollection.hpp
new file mode 100644
index 000000000..be6e0e299
--- /dev/null
+++ b/corsika/modules/radio/detectors/ObserverCollection.hpp
@@ -0,0 +1,69 @@
+/*
+ * (c) Copyright 2022 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
+ * the license.
+ */
+#pragma once
+
+namespace corsika {
+
+  /**
+   * The base interface for radio detectors.
+   * At the moment it is a collection of observers with the same implementation.
+   */
+
+  template <typename TObserverImpl>
+  class ObserverCollection {
+
+    /**
+     * The collection of observers used in this simulation.
+     */
+    std::vector<TObserverImpl> observers_;
+
+  public:
+    /**
+     * Add an observer to this radio process.
+     *
+     * @param observer    The observer to add
+     */
+    void addObserver(TObserverImpl const& observer);
+
+    /**
+     * Get the specific observer at that place in the collection
+     *
+     * @param index in the collection
+     */
+    TObserverImpl& at(std::size_t const i);
+
+    TObserverImpl const& at(std::size_t const i) const;
+
+    /**
+     * Get the number of observerss in the collection
+     */
+    int size() const;
+
+    /**
+     * Get a *non*-const reference to the collection of observers.
+     *
+     * @returns    An iterable mutable reference to the observers.
+     */
+    std::vector<TObserverImpl>& getObservers();
+
+    /**
+     * Get a const reference to the collection of observers.
+     *
+     * @returns    An iterable mutable reference to the observers.
+     */
+    std::vector<TObserverImpl> const& getObservers() const;
+
+    /**
+     * Reset all the observer waveforms.
+     */
+    void reset();
+  }; // END: class RadioDetector
+
+} // namespace corsika
+
+#include <corsika/detail/modules/radio/detectors/ObserverCollection.inl>
diff --git a/corsika/modules/radio/antennas/Antenna.hpp b/corsika/modules/radio/observers/Observer.hpp
similarity index 64%
rename from corsika/modules/radio/antennas/Antenna.hpp
rename to corsika/modules/radio/observers/Observer.hpp
index 3ae084e71..9d57e6a3b 100644
--- a/corsika/modules/radio/antennas/Antenna.hpp
+++ b/corsika/modules/radio/observers/Observer.hpp
@@ -15,57 +15,57 @@
 namespace corsika {
 
   /**
-   * A common abstract interface for radio antennas.
+   * A common abstract interface for radio oberservers.
    *
-   * All concrete antenna implementations should be of
-   * type Antenna<T> where T is a concrete antenna implementation.
+   * All concrete observer implementations should be of
+   * type Observer<T> where T is a concrete observer implementation.
    *
    */
-  template <typename TAntennaImpl>
-  class Antenna {
+  template <typename TObserverImpl>
+  class Observer {
 
   protected:
-    std::string const name_;                     ///< The name/identifier of this antenna.
-    Point const location_;                       ///< The location of this antenna.
-    CoordinateSystemPtr const coordinateSystem_; ///< The coordinate system of the antenna
+    std::string const name_;                     ///< The name/identifier of this observer.
+    Point const location_;                       ///< The location of this observer.
+    CoordinateSystemPtr const coordinateSystem_; ///< The coordinate system of the observer
 
   public:
     using axistype = std::vector<long double>;
 
     /**
-     * \brief Construct a base antenna instance.
+     * \brief Construct a base observer instance.
      *
-     * @param name    A name for this antenna.
-     * @param location    The location of this antenna.
+     * @param name    A name for this observer.
+     * @param location    The location of this observer.
      *
      */
-    Antenna(std::string const& name, Point const& location,
-            CoordinateSystemPtr const& coordinateSystem);
+    Observer(std::string const& name, Point const& location,
+             CoordinateSystemPtr const& coordinateSystem);
 
     /**
-     * Receive a signal at this antenna.
+     * Receive a signal at this observer.
      *
      * This is a general implementation call that must be specialized
-     * for the particular antenna implementation and usage.
+     * for the particular observer implementation and usage.
      *
      */
     template <typename... TVArgs>
     void receive(TVArgs&&... args);
 
     /**
-     * Get the location of this antenna.
+     * Get the location of this observer.
      */
     Point const& getLocation() const;
 
     /**
-     * Get the name of this name antenna.
+     * Get the name of this name observer.
      *
      * This is used in producing the output data file.
      */
     std::string const& getName() const;
 
     /**
-     * Reset the antenna before starting a new simulation.
+     * Reset the observer before starting a new simulation.
      */
     void reset();
 
@@ -80,7 +80,7 @@ namespace corsika {
     /**
      * Return a reference to the underlying waveform data for X polarization.
      *
-     * This is used when writing the antenna information to disk
+     * This is used when writing the observer information to disk
      * and will be converted to a 32-bit float before writing.
      */
     std::vector<double> const& getWaveformX() const;
@@ -88,7 +88,7 @@ namespace corsika {
     /**
      * Return a reference to the underlying waveform data for Y polarization.
      *
-     * This is used when writing the antenna information to disk
+     * This is used when writing the observer information to disk
      * and will be converted to a 32-bit float before writing.
      */
     std::vector<double> const& getWaveformY() const;
@@ -96,7 +96,7 @@ namespace corsika {
     /**
      * Return a reference to the underlying waveform data for Z polarization.
      *
-     * This is used when writing the antenna information to disk
+     * This is used when writing the observer information to disk
      * and will be converted to a 32-bit float before writing.
      */
     std::vector<double> const& getWaveformZ() const;
@@ -104,10 +104,10 @@ namespace corsika {
     /**
      * Get a reference to the underlying radio implementation.
      */
-    TAntennaImpl& implementation();
+    TObserverImpl& implementation();
 
-  }; // END: class Antenna final
+  }; // END: class Observer final
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/antennas/Antenna.inl>
+#include <corsika/detail/modules/radio/observers/Observer.inl>
diff --git a/corsika/modules/radio/antennas/TimeDomainAntenna.hpp b/corsika/modules/radio/observers/TimeDomainObserver.hpp
similarity index 71%
rename from corsika/modules/radio/antennas/TimeDomainAntenna.hpp
rename to corsika/modules/radio/observers/TimeDomainObserver.hpp
index 8c4ee2147..c99feec0e 100644
--- a/corsika/modules/radio/antennas/TimeDomainAntenna.hpp
+++ b/corsika/modules/radio/observers/TimeDomainObserver.hpp
@@ -7,22 +7,22 @@
  */
 #pragma once
 
-#include <corsika/modules/radio/antennas/Antenna.hpp>
+#include <corsika/modules/radio/observers/Observer.hpp>
 #include <yaml-cpp/yaml.h>
 #include <vector>
 
 namespace corsika {
 
   /**
-   * An implementation of a time-domain antenna that has a customized
+   * An implementation of a time-domain observer that has a customized
    * start time, sampling rate, and waveform duration.
    *
    */
-  class TimeDomainAntenna : public Antenna<TimeDomainAntenna> {
+  class TimeDomainObserver : public Observer<TimeDomainObserver> {
 
     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.
+    InverseTimeType const sample_rate_; ///< The sampling rate of this observer.
     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.
@@ -32,16 +32,16 @@ namespace corsika {
         time_axis_; ///< The time axis corresponding to the electric field.
 
   public:
-    // import the methods from the antenna
-    using Antenna<TimeDomainAntenna>::getName;
-    using Antenna<TimeDomainAntenna>::getLocation;
+    // import the methods from the observer
+    using Observer<TimeDomainObserver>::getName;
+    using Observer<TimeDomainObserver>::getLocation;
 
     /**
-     * Construct a new TimeDomainAntenna.
+     * Construct a new TimeDomainObserver.
      *
-     * @param name               The name of this antenna.
-     * @param location           The location of this antenna.
-     * @param coordinateSystem   The coordinate system of this antenna.
+     * @param name               The name of this observer.
+     * @param location           The location of this observer.
+     * @param coordinateSystem   The coordinate system of this observer.
      * @param start_time         The starting time of this waveform.
      * @param duration           The duration of this waveform.
      * @param sample_rate        The sample rate of this waveform.
@@ -49,15 +49,15 @@ namespace corsika {
      * straight vertical line.
      *
      */
-    TimeDomainAntenna(std::string const& name, Point const& location,
-                      CoordinateSystemPtr coordinateSystem, TimeType const& start_time,
-                      TimeType const& duration, InverseTimeType const& sample_rate,
-                      TimeType const ground_hit_time);
+    TimeDomainObserver(std::string const& name, Point const& location,
+                       CoordinateSystemPtr coordinateSystem, TimeType const& start_time,
+                       TimeType const& duration, InverseTimeType const& sample_rate,
+                       TimeType const ground_hit_time);
 
     /**
-     * Receive an electric field at this antenna.
+     * Receive an electric field at this observer.
      *
-     * This assumes that the antenna will receive
+     * This assumes that the observer will receive
      *  an *instantaneous* electric field modeled as a delta function (or timebin).
      *
      * @param time             The (global) time at which this signal is received.
@@ -65,7 +65,7 @@ namespace corsika {
      * @param field            The incident electric field vector.
      *
      */
-    // TODO: rethink this method a bit. If the endpoint is at the end of the antenna
+    // TODO: rethink this method a bit. If the endpoint is at the end of the observer
     // resolution then you get the startpoint signal but you lose the endpoint signal!
     void receive(TimeType const time, Vector<dimensionless_d> const& receive_vector,
                  ElectricFieldVector const& efield);
@@ -96,7 +96,7 @@ namespace corsika {
 
     /**
      * Return a label that indicates that this is a time
-     * domain antenna
+     * domain observer
      *
      * This returns the string "Time".
      */
@@ -117,27 +117,27 @@ namespace corsika {
     auto const getAxis() const;
 
     /**
-     * Returns the sampling rate of the time domain antenna.
+     * Returns the sampling rate of the time domain observer.
      */
     InverseTimeType const& getSampleRate() const;
 
     /**
-     * Returns the start time of detection for the time domain antenna.
+     * Returns the start time of detection for the time domain observer.
      */
     TimeType const& getStartTime() const;
 
     /**
-     * Reset the antenna before starting a new simulation.
+     * Reset the observer before starting a new simulation.
      */
     void reset();
 
     /**
-     * Return a YAML configuration for this antenna.
+     * Return a YAML configuration for this observer.
      */
     YAML::Node getConfig() const;
 
-  }; // END: class TimeDomainAntenna
+  }; // END: class TimeDomainObserver
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/antennas/TimeDomainAntenna.inl>
+#include <corsika/detail/modules/radio/observers/TimeDomainObserver.inl>
diff --git a/corsika/modules/radio/propagators/DummyTestPropagator.hpp b/corsika/modules/radio/propagators/DummyTestPropagator.hpp
index f9a02145e..a6e9790b2 100644
--- a/corsika/modules/radio/propagators/DummyTestPropagator.hpp
+++ b/corsika/modules/radio/propagators/DummyTestPropagator.hpp
@@ -19,7 +19,7 @@ namespace corsika {
   /**
    * This class implements a dummy propagator that uses
    * the straight-line (vector) between the particle
-   * location and the antenna as the trajectory.
+   * location and the observer as the trajectory.
    * It is intended mainly for fast testing as it only
    * works with 2 points in a uniform refractive index
    * atmospheric profile.
@@ -42,7 +42,7 @@ namespace corsika {
     /**
      * Return the collection of paths from `source` to `destination`.
      * Hence, the signal propagated from the
-     * emission point to the antenna location.
+     * emission point to the observer location.
      *
      */
     template <typename Particle>
@@ -63,4 +63,4 @@ namespace corsika {
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/propagators/DummyTestPropagator.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/propagators/DummyTestPropagator.inl>
diff --git a/corsika/modules/radio/propagators/NumericalIntegratingPropagator.hpp b/corsika/modules/radio/propagators/NumericalIntegratingPropagator.hpp
index 6f81464fb..c375aa6df 100644
--- a/corsika/modules/radio/propagators/NumericalIntegratingPropagator.hpp
+++ b/corsika/modules/radio/propagators/NumericalIntegratingPropagator.hpp
@@ -19,7 +19,7 @@ namespace corsika {
   /**
    * This class implements a basic propagator that uses
    * the straight-line (vector) between the particle
-   * location and the antenna as the trajectory.
+   * location and the observer as the trajectory.
    * To calculate the time delay of the signal, a basic
    * numerical integration scheme based on Simpson's rule
    * takes place. This propagator is slow and not
@@ -46,7 +46,7 @@ namespace corsika {
     /**
      * Return the collection of paths from `start` to `end`.
      * or from 'source' which is the emission point to 'destination'
-     * which is the location of the antenna
+     * which is the location of the observer
      */
     template <typename Particle>
     SignalPathCollection propagate(Particle const& particle, Point const& source,
@@ -66,4 +66,4 @@ namespace corsika {
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/propagators/NumericalIntegratingPropagator.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/propagators/NumericalIntegratingPropagator.inl>
diff --git a/corsika/modules/radio/propagators/RadioPropagator.hpp b/corsika/modules/radio/propagators/RadioPropagator.hpp
index 236a7b7b9..e57d3a55b 100644
--- a/corsika/modules/radio/propagators/RadioPropagator.hpp
+++ b/corsika/modules/radio/propagators/RadioPropagator.hpp
@@ -16,7 +16,7 @@ namespace corsika {
 
   /**
    * Radio propagators are used to calculate the propagation
-   * paths from particles to antennas. Any class that wants
+   * paths from particles to observers. Any class that wants
    * to be used as a RadioPropagator must implement the
    * following methods:
    *
@@ -44,4 +44,4 @@ namespace corsika {
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/propagators/RadioPropagator.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/propagators/RadioPropagator.inl>
diff --git a/corsika/modules/radio/propagators/TabulatedFlatAtmospherePropagator.hpp b/corsika/modules/radio/propagators/TabulatedFlatAtmospherePropagator.hpp
index cfd88292b..6713cad2a 100644
--- a/corsika/modules/radio/propagators/TabulatedFlatAtmospherePropagator.hpp
+++ b/corsika/modules/radio/propagators/TabulatedFlatAtmospherePropagator.hpp
@@ -44,7 +44,7 @@ namespace corsika {
     /**
      * Return the collection of paths from `source` to `destination`.
      * Hence, the signal propagated from the
-     * emission point to the antenna location.
+     * emission point to the oberserver location.
      *
      */
     template <typename Particle>
@@ -92,4 +92,4 @@ namespace corsika {
 
 } // namespace corsika
 
-#include <corsika/detail/modules/radio/propagators/TabulatedFlatAtmospherePropagator.inl>
\ No newline at end of file
+#include <corsika/detail/modules/radio/propagators/TabulatedFlatAtmospherePropagator.inl>
diff --git a/examples/cascade_examples/radio_em_shower.cpp b/examples/cascade_examples/radio_em_shower.cpp
index 4a3bb5d23..860da4582 100644
--- a/examples/cascade_examples/radio_em_shower.cpp
+++ b/examples/cascade_examples/radio_em_shower.cpp
@@ -47,9 +47,9 @@
 #include <corsika/modules/radio/RadioProcess.hpp>
 #include <corsika/modules/radio/CoREAS.hpp>
 #include <corsika/modules/radio/ZHS.hpp>
-#include <corsika/modules/radio/antennas/Antenna.hpp>
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
+#include <corsika/modules/radio/observers/Observer.hpp>
+#include <corsika/modules/radio/observers/TimeDomainObserver.hpp>
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
 #include <corsika/modules/radio/propagators/NumericalIntegratingPropagator.hpp>
 #include <corsika/modules/radio/propagators/DummyTestPropagator.hpp>
 
@@ -68,8 +68,8 @@ using namespace std;
 //
 // An example of running an casacde which generates radio input for a
 // cascade that has hadronic interactions turned off. Currently, this
-// will produce output for only one antenna, but there are lines below,
-// which are commented out, to enable a full star-shape pattern of antennas
+// will produce output for only one observer, but there are lines below,
+// which are commented out, to enable a full star-shape pattern of observers
 //
 
 void registerRandomStreams(int seed) {
@@ -159,17 +159,17 @@ int main(int argc, char** argv) {
                               false, 1000};
   auto const dX = 10_g / square(1_cm); // Binning of the writers along the shower axis
 
-  // setup the radio antennas
+  // setup the radio observers
   TimeType const groundHitTime{(showerCore - injectionPos).getNorm() / constants::c};
 
-  // Radio antennas and relevant information
-  // the antenna time variables
+  // Radio observers and relevant information
+  // the observer time variables
   TimeType const duration{1e-6_s};
   InverseTimeType const sampleRate{1e+9_Hz};
 
-  // the detector (aka antenna collection) for CoREAS and ZHS
-  AntennaCollection<TimeDomainAntenna> detectorCoREAS;
-  AntennaCollection<TimeDomainAntenna> detectorZHS;
+  // the detector (aka observer collection) for CoREAS and ZHS
+  ObserverCollection<TimeDomainObserver> detectorCoREAS;
+  ObserverCollection<TimeDomainObserver> detectorZHS;
 
   auto const showerCoreX{showerCore.getCoordinates().getX()};
   auto const showerCoreY{showerCore.getCoordinates().getY()};
@@ -187,7 +187,7 @@ int main(int argc, char** argv) {
                    (showerCore - injectionPos).getNorm() * 1.02);
   CORSIKA_LOG_INFO("Trigger Point is:   {}", triggerpoint);
 
-  // // setup CoREAS antennas - use the for loop for star shape pattern
+  // // setup CoREAS observers - use the for loop for star shape pattern
   // for (auto radius_coreas = 25_m; radius_coreas <= 500_m; radius_coreas += 25_m) {
   //   for (auto phi_coreas = 0; phi_coreas <= 315; phi_coreas += 45) {
   auto radius_coreas = 200_m;
@@ -197,18 +197,18 @@ int main(int argc, char** argv) {
   auto const point_coreas{Point(rootCS, showerCoreX + radius_coreas * cos(phiRad_coreas),
                                 showerCoreY + radius_coreas * sin(phiRad_coreas),
                                 constants::EarthRadius::Mean)};
-  std::cout << "Antenna point: " << point_coreas << std::endl;
-  CORSIKA_LOG_INFO("Antenna point    {}", injectionPos.getCoordinates());
+  std::cout << "Observer point: " << point_coreas << std::endl;
+  CORSIKA_LOG_INFO("Observer point    {}", injectionPos.getCoordinates());
   auto triggertime_coreas{(triggerpoint - point_coreas).getNorm() / constants::c};
   std::string name_coreas = "CoREAS_R=" + std::to_string(rr_coreas) +
                             "_m--Phi=" + std::to_string(phi_coreas) + "degrees";
-  TimeDomainAntenna antenna_coreas(name_coreas, point_coreas, rootCS, triggertime_coreas,
-                                   duration, sampleRate, triggertime_coreas);
-  detectorCoREAS.addAntenna(antenna_coreas);
+  TimeDomainObserver observer_coreas(name_coreas, point_coreas, rootCS, triggertime_coreas,
+                                    duration, sampleRate, triggertime_coreas);
+  detectorCoREAS.addObserver(observer_coreas);
   //   }
   // }
 
-  // // setup ZHS antennas - use the for loop for star shape pattern
+  // // setup ZHS observers - use the for loop for star shape pattern
   // for (auto radius_zhs = 25_m; radius_zhs <= 500_m; radius_zhs += 25_m) {
   //   for (auto phi_zhs = 0; phi_zhs <= 315; phi_zhs += 45) {
   auto radius_zhs = 200_m;
@@ -221,9 +221,9 @@ int main(int argc, char** argv) {
   auto triggertime_zhs{(triggerpoint - point_zhs).getNorm() / constants::c};
   std::string name_zhs = "ZHS_R=" + std::to_string(rr_zhs) +
                          "_m--Phi=" + std::to_string(phi_zhs) + "degrees";
-  TimeDomainAntenna antenna_zhs(name_zhs, point_zhs, rootCS, triggertime_zhs, duration,
-                                sampleRate, triggertime_zhs);
-  detectorZHS.addAntenna(antenna_zhs);
+  TimeDomainObserver observer_zhs(name_zhs, point_zhs, rootCS, triggertime_zhs, duration,
+                                 sampleRate, triggertime_zhs);
+  detectorZHS.addObserver(observer_zhs);
   //   }
   // }
 
diff --git a/examples/physics_examples/synchrotron_clover_leaf.cpp b/examples/physics_examples/synchrotron_clover_leaf.cpp
index a200ea101..3cd743c51 100644
--- a/examples/physics_examples/synchrotron_clover_leaf.cpp
+++ b/examples/physics_examples/synchrotron_clover_leaf.cpp
@@ -31,9 +31,9 @@
 #include <corsika/modules/radio/RadioProcess.hpp>
 #include <corsika/modules/radio/CoREAS.hpp>
 #include <corsika/modules/radio/ZHS.hpp>
-#include <corsika/modules/radio/antennas/Antenna.hpp>
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
+#include <corsika/modules/radio/observers/Observer.hpp>
+#include <corsika/modules/radio/observers/TimeDomainObserver.hpp>
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
 #include <corsika/modules/radio/propagators/DummyTestPropagator.hpp>
 #include <corsika/modules/writers/PrimaryWriter.hpp>
 
@@ -102,18 +102,18 @@ int main() {
   auto const injectionPosZ_{injectionPos.getCoordinates().getZ()};
   auto const triggerpoint_{Point(rootCS, injectionPosX_, injectionPosY_, injectionPosZ_)};
 
-  // the antenna characteristics
+  // the observer characteristics
   const TimeType duration_{2e-6_s};            // 0.8e-4_s
   const InverseTimeType sampleRate_{1e+11_Hz}; // 1e+9_Hz
 
   // the detectors
-  AntennaCollection<TimeDomainAntenna> detectorCoREAS;
+  ObserverCollection<TimeDomainObserver> detectorCoREAS;
 
   std::string name_center = "CoREAS_R=0_m--Phi=0degrees";
   auto triggertime_center{((triggerpoint_ - center).getNorm() / constants::c) - 500_ns};
-  TimeDomainAntenna antenna_center(name_center, center, rootCS, triggertime_center,
-                                   duration_, sampleRate_, triggertime_center);
-  detectorCoREAS.addAntenna(antenna_center);
+  TimeDomainObserver observer(name_center, center, rootCS, triggertime_center,
+                                    duration_, sampleRate_, triggertime_center);
+  detectorCoREAS.addObserver(observer_center);
 
   for (auto radius_1 = 25_m; radius_1 <= 1000_m; radius_1 += 25_m) {
     for (auto phi_1 = 0; phi_1 <= 315; phi_1 += 45) {
@@ -121,13 +121,13 @@ int main() {
       auto rr_1 = static_cast<int>(radius_1 / 1_m);
       auto const point_1{Point(rootCS, centerX + radius_1 * cos(phiRad_1),
                                centerY + radius_1 * sin(phiRad_1), centerZ)};
-      CORSIKA_LOG_INFO("Antenna point: {}", point_1);
+      CORSIKA_LOG_INFO("Observer point: {}", point_1);
       auto triggertime_1{((triggerpoint_ - point_1).getNorm() / constants::c) - 500_ns};
       std::string name_1 = "CoREAS_R=" + std::to_string(rr_1) +
                            "_m--Phi=" + std::to_string(phi_1) + "degrees";
-      TimeDomainAntenna antenna_1(name_1, point_1, rootCS, triggertime_1, duration_,
-                                  sampleRate_, triggertime_1);
-      detectorCoREAS.addAntenna(antenna_1);
+      TimeDomainObserver observer_1(name_1, point_1, rootCS, triggertime_1, duration_,
+                                   sampleRate_, triggertime_1);
+      detectorCoREAS.addObserver(observer_1);
     }
   }
 
diff --git a/examples/physics_examples/synchrotron_test_C8tracking.cpp b/examples/physics_examples/synchrotron_test_C8tracking.cpp
index d03d82d5a..76936405f 100644
--- a/examples/physics_examples/synchrotron_test_C8tracking.cpp
+++ b/examples/physics_examples/synchrotron_test_C8tracking.cpp
@@ -31,8 +31,8 @@
 #include <corsika/modules/radio/RadioProcess.hpp>
 #include <corsika/modules/radio/CoREAS.hpp>
 #include <corsika/modules/radio/ZHS.hpp>
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
+#include <corsika/modules/radio/observers/TimeDomainObserver.hpp>
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
 #include <corsika/modules/radio/propagators/DummyTestPropagator.hpp>
 
 #include <corsika/modules/TimeCut.hpp>
@@ -94,23 +94,23 @@ int main() {
 
   universe.addChild(std::move(world));
 
-  // the antenna locations
+  // the observer locations
   const auto point1{Point(rootCS, 30000_m, 0_m, 0_m)};
 
-  // the antenna time variables
+  // the observer time variables
   const TimeType t1{0.994e-4_s};
   const TimeType t2{1.07e-4_s - 0.994e-4_s};
   const InverseTimeType t3{5e+11_Hz};
 
-  // the antennas
-  TimeDomainAntenna ant1("antenna CoREAS", point1, rootCS, t1, t2, t3, t1);
-  TimeDomainAntenna ant2("antenna ZHS", point1, rootCS, t1, t2, t3, t1);
+  // the observers
+  TimeDomainObserver obs1("observer CoREAS", point1, rootCS, t1, t2, t3, t1);
+  TimeDomainObserver obs2("observer ZHS", point1, rootCS, t1, t2, t3, t1);
 
   // the detectors
-  AntennaCollection<TimeDomainAntenna> detectorCoREAS;
-  AntennaCollection<TimeDomainAntenna> detectorZHS;
-  detectorCoREAS.addAntenna(ant1);
-  detectorZHS.addAntenna(ant2);
+  ObserverCollection<TimeDomainObserver> detectorCoREAS;
+  ObserverCollection<TimeDomainObserver> detectorZHS;
+  detectorCoREAS.addObserver(obs1);
+  detectorZHS.addObserver(obs2);
 
   // setup particle stack, and add primary particle
   setup::Stack<EnvType> stack;
diff --git a/examples/physics_examples/synchrotron_test_manual_tracking.cpp b/examples/physics_examples/synchrotron_test_manual_tracking.cpp
index 210442899..b688d8a76 100644
--- a/examples/physics_examples/synchrotron_test_manual_tracking.cpp
+++ b/examples/physics_examples/synchrotron_test_manual_tracking.cpp
@@ -27,8 +27,8 @@
 #include <corsika/modules/radio/RadioProcess.hpp>
 #include <corsika/modules/radio/CoREAS.hpp>
 #include <corsika/modules/radio/ZHS.hpp>
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
+#include <corsika/modules/radio/observer/TimeDomainObserver.hpp>
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
 #include <corsika/modules/radio/propagators/DummyTestPropagator.hpp>
 
 #include <iomanip>
@@ -71,32 +71,32 @@ int main() {
   env.getUniverse()->addChild(std::move(Medium));
   auto const& node_ = env.getUniverse()->getChildNodes().front();
 
-  // the antennas location
+  // the observers location
   const auto point1{Point(rootCS, 30000_m, 0_m, 0_m)};
 
-  // create times for the antenna
+  // create times for the observer
   const TimeType start{0.994e-4_s};
   const TimeType duration{1.07e-4_s - 0.994e-4_s};
-  // 3 km antenna
+  // 3 km observer
   //    const TimeType start{0.994e-5_s};
   //    const TimeType duration{1.7e-5_s - 0.994e-5_s};
   const InverseTimeType sampleRate_{5e+11_Hz};
 
   std::cout << "number of points in time: " << duration * sampleRate_ << std::endl;
 
-  // create 2 antennas
-  TimeDomainAntenna ant1("CoREAS antenna", point1, rootCS, start, duration, sampleRate_,
-                         start);
-  TimeDomainAntenna ant2("ZHS antenna", point1, rootCS, start, duration, sampleRate_,
-                         start);
+  // create 2 observers
+  TimeDomainObserver obs1("CoREAS observer", point1, rootCS, start, duration, sampleRate_,
+                           start);
+  TimeDomainObserver obs2("ZHS observer", point1, rootCS, start, duration, sampleRate_,
+                           start);
 
-  // construct a radio detector instance to store our antennas
-  AntennaCollection<TimeDomainAntenna> detectorCoREAS;
-  AntennaCollection<TimeDomainAntenna> detectorZHS;
+  // construct a radio detector instance to store our observers
+  ObserverCollection<TimeDomainObserver> detectorCoREAS;
+  ObserverCollection<TimeDomainObserver> detectorZHS;
 
-  // add the antennas to the detector
-  detectorCoREAS.addAntenna(ant1);
-  detectorZHS.addAntenna(ant2);
+  // add the observers to the detector
+  detectorCoREAS.addObserver(obs1);
+  detectorZHS.addObserver(obs2);
 
   // create a new stack for each trial
   setup::Stack<EnvType> stack;
@@ -115,15 +115,15 @@ int main() {
   auto SP = make_dummy_test_radio_propagator(env);
 
   // create a radio process instance using CoREAS
-  RadioProcess<AntennaCollection<TimeDomainAntenna>,
-               CoREAS<AntennaCollection<TimeDomainAntenna>, decltype(SP)>, decltype(SP)>
+  RadioProcess<ObserverCollection<TimeDomainObserver>,
+               CoREAS<ObserverCollection<TimeDomainObserver>, decltype(SP)>, decltype(SP)>
       coreas(detectorCoREAS, SP);
   // register CoREAS to the output manager
   outputs.add("CoREAS", coreas);
 
   // create a radio process instance using ZHS
-  RadioProcess<AntennaCollection<TimeDomainAntenna>,
-               ZHS<AntennaCollection<TimeDomainAntenna>, decltype(SP)>, decltype(SP)>
+  RadioProcess<ObserverCollection<TimeDomainObserver>,
+               ZHS<ObserverCollection<TimeDomainObserver>, decltype(SP)>, decltype(SP)>
       zhs(detectorZHS, SP);
   // register ZHS to the output manager
   outputs.add("ZHS", zhs);
diff --git a/python/corsika/io/outputs/radio_process.py b/python/corsika/io/outputs/radio_process.py
index 16bc770ab..d118c85eb 100644
--- a/python/corsika/io/outputs/radio_process.py
+++ b/python/corsika/io/outputs/radio_process.py
@@ -30,9 +30,9 @@ class RadioProcess(Output):
         """
         Initialize this radio process reader (and load the data).
 
-        We load each antenna in a shared multidimensional pandas
-        dataframe . Every antenna can be accessed via the number
-        of the shower and the antenna name.
+        We load each observer in a shared multidimensional pandas
+        dataframe . Every observer can be accessed via the number
+        of the shower and the observer name.
 
         Parameters
         ----------
@@ -59,37 +59,37 @@ class RadioProcess(Output):
             The path to the directory containing this output.
 
         """
-        data = pq.read_table(op.join(path, "antennas.parquet"))
+        data = pq.read_table(op.join(path, "observers.parquet"))
         nshowers = int(data.to_pandas()["shower"].iloc[-1] + 1)
-        antennas = list(self.config["antennas"].keys())
+        observers = list(self.config["observers"].keys())
 
         # check that we got some events
         if nshowers == 0:
             logging.warn(f"Radio Process {self.config['name']} contains 0 showers.")
 
-        # if there are no antennas,
-        if len(antennas) == 0:
-            logging.warn(f"No antennas were found for {self.config['name']}")
+        # if there are no observers,
+        if len(observers) == 0:
+            logging.warn(f"No observers were found for {self.config['name']}")
 
-        ant_nr = 0
+        obs_nr = 0
         dictionary = {}
         dataset = {}
         # loop over all showers
         for i in range(nshowers):
-            # loop over each of the antennas
-            for name in antennas:
-                sampling_period = self.config["antennas"][name]["number of bins"]
-                start = int(ant_nr * sampling_period)
-                stop = int((ant_nr + 1) * sampling_period)
-                antenna_data = data[start:stop].to_pandas()
-                times = antenna_data["Time"]
-                Ex = antenna_data["Ex"]
-                Ey = antenna_data["Ey"]
-                Ez = antenna_data["Ez"]
+            # loop over each of the observers
+            for name in observers:
+                sampling_period = self.config["observers"][name]["number of bins"]
+                start = int(obs_nr * sampling_period)
+                stop = int((obs_nr + 1) * sampling_period)
+                observers_data = data[start:stop].to_pandas()
+                times = observers_data["Time"]
+                Ex = observers_data["Ex"]
+                Ey = observers_data["Ey"]
+                Ez = observers_data["Ez"]
                 dictionary[name] = pd.DataFrame(
                     {"time": times, "Ex": Ex, "Ey": Ey, "Ez": Ez}
                 )
-                ant_nr = ant_nr + 1
+                obs_nr += 1
 
             dataset[str(i)] = dictionary
 
@@ -109,7 +109,7 @@ class RadioProcess(Output):
 
     def astype(self, dtype: str = "pandas", **kwargs: Any) -> Any:
         """
-        Load the antenna data from this process.
+        Load the observer data from this process.
 
         Parameters
         ----------
@@ -131,30 +131,30 @@ class RadioProcess(Output):
                 )
             )
 
-    def get_antenna_list(self) -> list:
+    def get_observers_list(self) -> list:
         """
-        Return a list with the names of the antennas of this RadioProcess.
+        Return a list with the names of the observers of this RadioProcess.
         """
-        antennas = list(self.config["antennas"].keys())
-        return antennas
+        observers = list(self.config["observers"].keys())
+        return observers
 
-    def get_antennas(self) -> dict:
+    def get_observers(self) -> dict:
         """
-        Return a pandas dataframe with all the information for the antennas
-        of this RadioProcess. This information is shower number, antenna
+        Return a pandas dataframe with all the information for the observers
+        of this RadioProcess. This information is shower number, observers
         type, start time of detection, detection duration, number of bins,
         sampling frequency, location x, location y, location z.
         """
-        antennas = list(self.config["antennas"].keys())
+        observers = list(self.config["observers"].keys())
         dictionary = {}
-        # loop over each of the antennas
-        for name in antennas:
-            type = self.config["antennas"][name]["type"]
-            start_time = self.config["antennas"][name]["start time"]
-            duration = self.config["antennas"][name]["duration"]
-            nr_bins = self.config["antennas"][name]["number of bins"]
-            sampling_frequency = self.config["antennas"][name]["sampling frequency"]
-            location = self.config["antennas"][name]["location"]
+        # loop over each of the observers
+        for name in observers:
+            type = self.config["observers"][name]["type"]
+            start_time = self.config["observers"][name]["start time"]
+            duration = self.config["observers"][name]["duration"]
+            nr_bins = self.config["observers"][name]["number of bins"]
+            sampling_frequency = self.config["observers"][name]["sampling frequency"]
+            location = self.config["observers"][name]["location"]
             dictionary[name] = pd.DataFrame(
                 {
                     "type": type,
@@ -172,7 +172,7 @@ class RadioProcess(Output):
 
     def get_units(self) -> dict:
         """
-        Return the units of the antennas of this RadioProcess.
+        Return the units of the observers of this RadioProcess.
         """
         return self.config["units"]
 
diff --git a/python/examples/radio_emission.py b/python/examples/radio_emission.py
index 0eba1beef..7d830e358 100644
--- a/python/examples/radio_emission.py
+++ b/python/examples/radio_emission.py
@@ -37,7 +37,7 @@ found_zhs = False
 try:
     waveforms_config_zhs = lib.get("ZHS").config  # meta information
     waveforms_zhs = lib.get("ZHS").astype("pandas")
-    antennas_zhs = lib.get("ZHS").get_antennas()
+    observers_zhs = lib.get("ZHS").get_observers()
     found_zhs = True
 except Exception:
     print("No ZHS waveforms in this directory")
@@ -47,7 +47,7 @@ found_coreas = False
 try:
     waveforms_config_coreas = lib.get("CoREAS").config  # meta information
     waveforms_coreas = lib.get("CoREAS").astype("pandas")
-    antennas_coreas = lib.get("CoREAS").get_antennas()
+    observers_coreas = lib.get("CoREAS").get_observers()
     found_coreas = True
 except Exception:
     print("No CoREAS waveforms in this directory")
@@ -63,18 +63,18 @@ for ishower in range(n_showers):
     title = f"Primary: {primary.name}," + r" E$_{\rm tot}$:"
     title += f" {primary.total_energy:.2e} {primary_config['units']['energy']}"
 
-    # Get all of the unique antenna names to match up the CoREAS/ZHS waveforms
-    ant_names = []
+    # Get all of the unique observer names to match up the CoREAS/ZHS waveforms
+    obs_names = []
     if found_zhs:
-        ant_names += list(waveforms_zhs[str(ishower)].keys())
+        obs_names += list(waveforms_zhs[str(ishower)].keys())
         zhs_dict = waveforms_zhs[str(ishower)]
     if found_coreas:
-        ant_names += list(waveforms_coreas[str(ishower)].keys())
+        obs_names += list(waveforms_coreas[str(ishower)].keys())
         coreas_dict = waveforms_coreas[str(ishower)]
-    ant_names = np.unique(ant_names)
+    obs_names = np.unique(obs_names)
 
     ncols = 1
-    nrows = len(ant_names)
+    nrows = len(obs_names)
     fig, ax = plt.subplots(
         ncols=ncols,
         nrows=nrows,
@@ -84,72 +84,73 @@ for ishower in range(n_showers):
 
     if nrows == 1:
         ax = [ax]
-    
-    # Make a plot for each of the antenna locations
-    for iant, ant_name in enumerate(ant_names):
+
+    # Make a plot for each of the observer locations
+    for iobs, obs_name in enumerate(obs_names):
 
         # Add blank entry to show colors in legend
-        ax[iant].fill_between([], [], [], color="k", label="Ex")
-        ax[iant].fill_between([], [], [], color="r", label="Ey")
-        ax[iant].fill_between([], [], [], color="b", label="Ez")
+        ax[iobs].fill_between([], [], [], color="k", label="Ex")
+        ax[iobs].fill_between([], [], [], color="r", label="Ey")
+        ax[iobs].fill_between([], [], [], color="b", label="Ez")
 
-        if not iant:
-            ax[iant].set_title(title)
+        if not iobs:
+            ax[iobs].set_title(title)
 
         # Make the plots for the ZHS waveforms
-        if found_zhs and ant_name in antennas_zhs.keys():
-            ant_position = np.array(
+        if found_zhs and obs_name in observers_zhs.keys():
+            obs_position = np.array(
                 [
-                    antennas_zhs[ant_name]["x"],
-                    antennas_zhs[ant_name]["y"],
-                    antennas_zhs[ant_name]["z"],
+                    observers_zhs[obs_name]["x"],
+                    observers_zhs[obs_name]["y"],
+                    observers_zhs[obs_name]["z"],
                 ]
             ).flatten()
-            times = np.array(zhs_dict[ant_name]["time"])
+            times = np.array(zhs_dict[obs_name]["time"])
 
-            ax[iant].plot(
-                times, zhs_dict[ant_name]["Ex"], color="k", linestyle="-", label="ZHS"
+            ax[iobs].plot(
+                times, zhs_dict[obs_name]["Ex"], color="k", linestyle="-", label="ZHS"
             )
-            ax[iant].plot(times, zhs_dict[ant_name]["Ey"], color="r", linestyle="-")
-            ax[iant].plot(times, zhs_dict[ant_name]["Ez"], color="b", linestyle="-")
-            ax[iant].set_xlabel(f"Time [{waveforms_config_zhs['units']['time']}]")
-            ax[iant].set_ylabel(
+            ax[iobs].plot(times, zhs_dict[obs_name]["Ey"], color="r", linestyle="-")
+            ax[iobs].plot(times, zhs_dict[obs_name]["Ez"], color="b", linestyle="-")
+            ax[iobs].set_xlabel(f"Time [{waveforms_config_zhs['units']['time']}]")
+            ax[iobs].set_ylabel(
                 f"Amp ({waveforms_config_zhs['units']['electric field']})"
             )
 
         # Make the plots for the CoREAS waveforms
-        if found_coreas and ant_name in antennas_coreas.keys():
-            ant_position = np.array(
+        if found_coreas and obs_name in observers_coreas.keys():
+            obs_position = np.array(
                 [
-                    antennas_coreas[ant_name]["x"],
-                    antennas_coreas[ant_name]["y"],
-                    antennas_coreas[ant_name]["z"],
+                    observers_coreas[obs_name]["x"],
+                    observers_coreas[obs_name]["y"],
+                    observers_coreas[obs_name]["z"],
                 ]
             ).flatten()
-            times = np.array(coreas_dict[ant_name]["time"])
+            times = np.array(coreas_dict[obs_name]["time"])
 
-            ax[iant].plot(
+            ax[iobs].plot(
                 times,
-                coreas_dict[ant_name]["Ex"],
+                coreas_dict[obs_name]["Ex"],
                 color="k",
                 linestyle="--",
                 label="CoREAS",
             )
-            ax[iant].plot(times, coreas_dict[ant_name]["Ey"], color="r", linestyle="--")
-            ax[iant].plot(times, coreas_dict[ant_name]["Ez"], color="b", linestyle="--")
-            ax[iant].set_xlabel(f"Time ({waveforms_config_coreas['units']['time']})")
-            ax[iant].set_ylabel(
+            ax[iobs].plot(times, coreas_dict[obs_name]["Ey"], color="r", linestyle="--")
+            ax[iobs].plot(times, coreas_dict[obs_name]["Ez"], color="b", linestyle="--")
+            ax[iobs].set_xlabel(f"Time ({waveforms_config_coreas['units']['time']})")
+            ax[iobs].set_ylabel(
                 f"Amp ({waveforms_config_coreas['units']['electric field']})"
             )
 
-        ymin, ymax = ax[iant].get_ylim()
+        ymin, ymax = ax[iobs].get_ylim()
         max_amp = max(abs(ymin), abs(ymax))
-        ax[iant].set_ylim(-max_amp, max_amp)
-        text = f"Antenna @ ({ant_position[0]:0.0f}, {ant_position[1]:0.0f},"
-        text += f" {ant_position[2]:0.0f})"
-        ax[iant].text(times[-1], 2 * max_amp * 0.05 - max_amp, text, ha="right")
-        ax[iant].legend(loc="upper right")
+        ax[iobs].set_ylim(-max_amp, max_amp)
+        text = f"Observer @ ({obs_position[0]:0.0f}, {obs_position[1]:0.0f},"
+        text += f" {obs_position[2]:0.0f})"
+        ax[iobs].text(times[-1], 2 * max_amp * 0.05 - max_amp, text, ha="right")
+        ax[iobs].legend(loc="upper right")
 
-    plot_path = os.path.join(args.output_dir, f"AntennaWaveforms_Sh{ishower}.png")
+    plot_path = os.path.join(args.output_dir, f"ObserverWaveforms_Sh{ishower}.png")
     print("Saving", plot_path)
     fig.savefig(plot_path, bbox_inches="tight")
+
diff --git a/tests/modules/testRadio.cpp b/tests/modules/testRadio.cpp
index 3d44b3db2..6a031b5de 100644
--- a/tests/modules/testRadio.cpp
+++ b/tests/modules/testRadio.cpp
@@ -10,8 +10,8 @@
 #include <corsika/modules/radio/RadioProcess.hpp>
 #include <corsika/modules/radio/ZHS.hpp>
 #include <corsika/modules/radio/CoREAS.hpp>
-#include <corsika/modules/radio/antennas/TimeDomainAntenna.hpp>
-#include <corsika/modules/radio/detectors/AntennaCollection.hpp>
+#include <corsika/modules/radio/observers/TimeDomainObserver.hpp>
+#include <corsika/modules/radio/detectors/ObserverCollection.hpp>
 #include <corsika/modules/radio/propagators/NumericalIntegratingPropagator.hpp>
 #include <corsika/modules/radio/propagators/DummyTestPropagator.hpp>
 #include <corsika/modules/radio/propagators/TabulatedFlatAtmospherePropagator.hpp>
@@ -134,16 +134,16 @@ TEST_CASE("Radio", "[processes]") {
     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 auto obs1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto obs2Loc{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);
+    TimeDomainObserver obs1("observer_name", obs1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainObserver obs2("observer_name2", obs2Loc, rootCS, t1, t2, t3, t1);
+    ObserverCollection<TimeDomainObserver> detector;
+    detector.addObserver(obs1);
+    detector.addObserver(obs2);
 
     auto SP = make_numerical_integrating_radio_propagator(envCoREAS, 1_m);
     // create a radio process instance using CoREAS
@@ -156,15 +156,15 @@ TEST_CASE("Radio", "[processes]") {
     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];
+    for (auto const& obs : detector.getObservers()) {
+      // make sure something was put into the observer
+      auto totalX = obs.getWaveformX()[0];
+      auto totalY = obs.getWaveformY()[0];
+      auto totalZ = obs.getWaveformZ()[0];
+      for (size_t i = 0; i < obs.getWaveformX().size(); i++) {
+        totalX += obs.getWaveformX()[i];
+        totalY += obs.getWaveformY()[i];
+        totalZ += obs.getWaveformZ()[i];
       }
       REQUIRE((totalX + totalY + totalZ) > (totalX * 0));
     }
@@ -172,8 +172,8 @@ TEST_CASE("Radio", "[processes]") {
     //////////////////////////////////////
     // reset everything for a new particle
     //////////////////////////////////////
-    ant1.reset();
-    ant2.reset();
+    obs1.reset();
+    obs2.reset();
     stack.purge();
 
     // add the particle to the stack that is VERY late
@@ -183,15 +183,15 @@ TEST_CASE("Radio", "[processes]") {
     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];
+    for (auto const& obs : detector.getObservers()) {
+      // make sure something was put into the observer
+      auto total = obs.getWaveformX()[0];
+      for (size_t i = 0; i < obs.getWaveformX().size(); i++) {
+        total += obs.getWaveformX()[i] * obs.getWaveformX()[i];
+        total += obs.getWaveformY()[i] * obs.getWaveformY()[i];
+        total += obs.getWaveformZ()[i] * obs.getWaveformZ()[i];
       }
-      REQUIRE(total < (1e-12 * ant.getWaveformX().size()));
+      REQUIRE(total < (1e-12 * obs.getWaveformX().size()));
     }
 
     // coreas output check
@@ -205,7 +205,7 @@ TEST_CASE("Radio", "[processes]") {
 
     boost::filesystem::create_directory(tempPathC);
     coreas.startOfLibrary(tempPathC);
-    auto const outputFileC = tempPathC / ("antennas.parquet");
+    auto const outputFileC = tempPathC / ("observers.parquet");
     CHECK(boost::filesystem::exists(outputFileC));
     // run end of shower and make sure that something extra was added
     auto const fileSizeC = boost::filesystem::file_size(outputFileC);
@@ -268,16 +268,16 @@ TEST_CASE("Radio", "[processes]") {
     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 auto obs1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto obs2Loc{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);
+    TimeDomainObserver obs1("observer_name", obs1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainObserver obs2("observer_name2", obs2Loc, rootCS, t1, t2, t3, t1);
+    ObserverCollection<TimeDomainObserver> detector;
+    detector.addObserver(obs1);
+    detector.addObserver(obs2);
 
     auto SP = make_numerical_integrating_radio_propagator(envCoREAS, 1_m);
 
@@ -337,7 +337,7 @@ TEST_CASE("Radio", "[processes]") {
 
     Vector B0(rootCS, 5_T, 5_T, 5_T);
 
-    // the antennas location
+    // the observers location
     const auto trackStart{Point(envZHS.getCoordinateSystem(), 7_m, 8_m, 9_m)};
     const auto trackEnd{Point(envZHS.getCoordinateSystem(), 5_m, 5_m, 10_m)};
 
@@ -387,24 +387,24 @@ TEST_CASE("Radio", "[processes]") {
     envZHS.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 auto obs1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto obs2Loc{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);
+    TimeDomainObserver obs1("observer_name", obs1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainObserver obs2("observer_name2", obs2Loc, rootCS, t1, t2, t3, t1);
+    ObserverCollection<TimeDomainObserver> detector;
+    detector.addObserver(obs1);
+    detector.addObserver(obs2);
 
     auto const charge_{get_charge(particle1.getPID())};
 
     auto SP = make_numerical_integrating_radio_propagator(envZHS, 1_m);
 
     // create a radio process instance using ZHS
-    RadioProcess<AntennaCollection<TimeDomainAntenna>,
-                 ZHS<AntennaCollection<TimeDomainAntenna>, decltype(SP)>, decltype(SP)>
+    RadioProcess<ObserverCollection<TimeDomainObserver>,
+                 ZHS<ObserverCollection<TimeDomainObserver>, decltype(SP)>, decltype(SP)>
         zhs(detector, SP);
 
     Step step(particle1, base);
@@ -422,7 +422,7 @@ TEST_CASE("Radio", "[processes]") {
 
     boost::filesystem::create_directory(tempPathZ);
     zhs.startOfLibrary(tempPathZ);
-    auto const outputFileZ = tempPathZ / ("antennas.parquet");
+    auto const outputFileZ = tempPathZ / ("observers.parquet");
     CHECK(boost::filesystem::exists(outputFileZ));
     // run end of shower and make sure that something extra was added
     auto const fileSizeZ = boost::filesystem::file_size(outputFileZ);
@@ -490,8 +490,8 @@ TEST_CASE("Radio", "[processes]") {
     particle_stack_proton.setNode(Medium.get());
     envRadio.getUniverse()->addChild(std::move(Medium));
 
-    // now create antennas and detectors
-    // the antennas location
+    // now create observers and detectors
+    // the observers location
     const auto point1{Point(envRadio.getCoordinateSystem(), 0_m, 0_m, 0_m)};
 
     // track points
@@ -499,33 +499,33 @@ TEST_CASE("Radio", "[processes]") {
     Point const point_4(rootCSRadio, {0_m, 1_m, 0_m});
     const auto point_b{Point(rootCSRadio, 30000_m, 0_m, 0_m)};
 
-    // create times for the antenna
+    // create times for the observer
     const TimeType start{0_s};
     const TimeType duration{100_ns};
     const InverseTimeType sample{1e+12_Hz};
     const TimeType duration_dummy{2_s};
     const InverseTimeType sample_dummy{1_Hz};
 
-    // create specific times for antenna to do timebin check
+    // create specific times for observer to do timebin check
     const TimeType start_b{0.994e-4_s};
     const TimeType duration_b{1.07e-4_s - 0.994e-4_s};
     const InverseTimeType sampleRate_b{5e+11_Hz};
 
-    // check that I can create an antenna at (1, 2, 3)
-    TimeDomainAntenna ant1("antenna_name", point1, rootCSRadio, start, duration, sample,
-                           start);
-    TimeDomainAntenna ant2("dummy", point1, rootCSRadio, start, duration_dummy,
-                           sample_dummy, start);
-    TimeDomainAntenna ant_b("timebin", point_b, rootCSRadio, start_b, duration_b,
-                            sampleRate_b, start_b);
-    // construct a radio detector instance to store our antennas
-    AntennaCollection<TimeDomainAntenna> detector;
-    AntennaCollection<TimeDomainAntenna> detector_dummy;
-    AntennaCollection<TimeDomainAntenna> detector_b;
-    // add the antennas to the detector
-    detector.addAntenna(ant1);
-    detector_dummy.addAntenna(ant2);
-    detector_b.addAntenna(ant_b);
+    // check that I can create an observer at (1, 2, 3)
+    TimeDomainObserver obs1("observer_name", point1, rootCSRadio, start, duration, sample,
+                            start);
+    TimeDomainObserver obs2("dummy", point1, rootCSRadio, start, duration_dummy,
+                            sample_dummy, start);
+    TimeDomainObserver obs_b("timebin", point_b, rootCSRadio, start_b, duration_b,
+                             sampleRate_b, start_b);
+    // construct a radio detector instance to store our observers
+    ObserverCollection<TimeDomainObserver> detector;
+    ObserverCollection<TimeDomainObserver> detector_dummy;
+    ObserverCollection<TimeDomainObserver> detector_b;
+    // add the observers to the detector
+    detector.addObserver(obs1);
+    detector_dummy.addObserver(obs2);
+    detector_b.addObserver(obs_b);
 
     // feed radio with a proton track to check that it skips that track.
     TimeType tp{(point_2 - point_1).getNorm() / (0.999 * constants::c)};
@@ -544,7 +544,7 @@ TEST_CASE("Radio", "[processes]") {
     Step step_h(particle_stack, track_h);
     Step step_h_neg_time(particle_stack, track_h_neg_time);
 
-    // feed radio with an electron track that ends in a different antenna bin.
+    // feed radio with an electron track that ends in a different observer bin.
     Point const point_start(rootCSRadio, {100_m, 0_m, 0_m});
     Point const point_end(rootCSRadio, {100_m, 0.00628319_m, 0_m});
     TimeType tb{(point_end - point_start).getNorm() / (0.999 * constants::c)};
@@ -569,7 +569,7 @@ TEST_CASE("Radio", "[processes]") {
     zhs.doContinuous(step_h, true);
     zhs.doContinuous(step_h_neg_time, true);
 
-    // create radio processes with "dummy" antenna to trigger extreme time-binning
+    // create radio processes with "dummy" observer to trigger extreme time-binning
     RadioProcess<decltype(detector_dummy), CoREAS<decltype(detector_dummy), decltype(SP)>,
                  decltype(SP)>
         coreas_dummy(detector_dummy, SP);
@@ -616,16 +616,16 @@ TEST_CASE("Radio", "[processes]") {
     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 auto obs1Loc{Point(rootCS, 100_m, 2_m, 3_m)};
+    const auto obs2Loc{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);
+    TimeDomainObserver obs1("observer_name", obs1Loc, rootCS, t1, t2, t3, t1);
+    TimeDomainObserver obs2("observer_name2", obs2Loc, rootCS, t1, t2, t3, t1);
+    ObserverCollection<TimeDomainObserver> detector;
+    detector.addObserver(obs1);
+    detector.addObserver(obs2);
 
     const auto trackStart{Point(rootCS, 7_m, 8_m, 9_m)};
     const auto trackEnd{Point(rootCS, 5_m, 5_m, 10_m)};
@@ -674,69 +674,69 @@ TEST_CASE("Radio", "[processes]") {
     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["observers"]["observer_name"]["location"][0].as<double>() == 100);
+    CHECK(config["observers"]["observer_name"]["location"][1].as<double>() == 2);
+    CHECK(config["observers"]["observer_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);
+    CHECK(config["observers"]["observer_name2"]["location"][0].as<double>() == 4);
+    CHECK(config["observers"]["observer_name2"]["location"][1].as<double>() == 80);
+    CHECK(config["observers"]["observer_name2"]["location"][2].as<double>() == 6);
   } // END: SECTION("Process Library")
 
 } // END: TEST_CASE("Radio", "[processes]")
 
-TEST_CASE("Antennas") {
+TEST_CASE("observers") {
 
-  SECTION("TimeDomainAntenna Constructor") {
+  SECTION("TimeDomainObserver Constructor") {
     Environment<IRefractiveIndexModel<IMediumModel>> env;
     const auto rootCS = env.getCoordinateSystem();
-    auto const antPos = Point(rootCS, {0_m, 0_m, 0_m});
+    auto const obsPos = 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,
+    TimeDomainObserver const observer("observer", obsPos, 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);
+    CHECK(observer.getWaveformX().size() == observer.getWaveformY().size());
+    CHECK(observer.getWaveformX().size() == observer.getWaveformZ().size());
+    CHECK(observer.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); }
+    for (auto const& val : observer.getWaveformX()) { CHECK(val * 0 == val); }
+    for (auto const& val : observer.getWaveformY()) { CHECK(val * 0 == val); }
+    for (auto const& val : observer.getWaveformZ()) { CHECK(val * 0 == val); }
 
     // check that variables were set properly
-    CHECK("antenna" == antenna.getName());
-    CHECK(sampleRate == antenna.getSampleRate());
-    CHECK(tStart == antenna.getStartTime());
+    CHECK("observer" == observer.getName());
+    CHECK(sampleRate == observer.getSampleRate());
+    CHECK(tStart == observer.getStartTime());
 
-    // and check that the antenna is at the right location
-    CHECK((antenna.getLocation() - antPos).getNorm() < 1e-12 * 1_m);
-  } // END: SECTION("TimeDomainAntenna Constructor")
+    // and check that the observer is at the right location
+    CHECK((observer.getLocation() - obsPos).getNorm() < 1e-12 * 1_m);
+  } // END: SECTION("TimeDomainObserver Constructor")
 
-  SECTION("TimeDomainAntenna Bad Constructor") {
+  SECTION("TimeDomainObserver Bad Constructor") {
     Environment<IRefractiveIndexModel<IMediumModel>> env;
     const auto rootCS = env.getCoordinateSystem();
-    auto const antPos = Point(rootCS, {0_m, 0_m, 0_m});
+    auto const obsPos = 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") {
+    TimeDomainObserver const observer_bad1("bad_observer", obsPos, rootCS, tStart, -13_ns,
+                                           sampleRate, groundHitTime);
+    TimeDomainObserver const observer_bad2("bad_observer", obsPos, rootCS, tStart, 0_ns,
+                                           sampleRate, groundHitTime);
+    TimeDomainObserver const observer_bad3("bad_observer", obsPos, rootCS, tStart, duration,
+                                           -1_GHz, groundHitTime);
+  } // END: SECTION("TimeDomainObserver Bad Constructor")
+
+  SECTION("TimeDomainObserver Receive Efield") {
     // Checks that the basic functionality of the receive function is working properly
 
     using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
@@ -747,15 +747,15 @@ TEST_CASE("Antennas") {
     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
+    // create times for the observer
     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);
+    // make the two observers with different start times
+    TimeDomainObserver obs1("observer_name", point1, rootCS, t1, t2, t3, t1);
+    TimeDomainObserver obs2("observer_name", point2, rootCS, t4, t2, t3, t4);
 
     Vector<dimensionless_d> receiveVec1(rootCS, {0, 0, 1});
     Vector<dimensionless_d> receiveVec2(rootCS, {0, 1, 0});
@@ -765,40 +765,40 @@ TEST_CASE("Antennas") {
     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]);
+    // inject efield into obs1
+    obs1.receive(15_s, receiveVec1, eField1);
+    REQUIRE(obs1.getWaveformX()[5] - 10 == 0);
+    REQUIRE(obs1.getWaveformX()[5] == obs1.getWaveformY()[5]);
+    REQUIRE(obs1.getWaveformX()[5] == obs1.getWaveformZ()[5]);
+
+    // inject efield but with different receive vector into obs2
+    obs2.receive(16_s, receiveVec2, eField1);
+    REQUIRE(obs1.getWaveformX()[5] ==
+            obs2.getWaveformX()[5]); // Currently receive vector does nothing
+    obs2.reset();
+    REQUIRE(obs2.getWaveformX()[5] == 0); // reset was successful
+
+    // inject the other eField into obs2
+    obs2.receive(16_s, receiveVec2, eField2);
+    REQUIRE(obs2.getWaveformX()[5] - 20 == 0);
+    REQUIRE(obs2.getWaveformX()[5] == obs2.getWaveformY()[5]);
+    REQUIRE(obs2.getWaveformX()[5] == obs2.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") {
+    REQUIRE(obs2.getWaveformX()[6] == 0);
+    obs2.receive(17_s, receiveVec2, eField2);
+    REQUIRE(obs2.getWaveformX()[6] - 20 == 0);
+
+    // reset obs1 and then put values in out of range
+    obs1.reset();
+    obs1.receive(-1000_s, receiveVec1, eField1);
+    for (auto const& val : obs1.getWaveformX()) { CHECK(val * 0 == val); }
+    obs1.reset();
+    obs1.receive(t1 + t2 + 1_s, receiveVec1, eField1);
+    for (auto const& val : obs1.getWaveformX()) { CHECK(val * 0 == val); }
+  } // END: SECTION("TimeDomainObserver Receive EField")
+
+  SECTION("TimeDomainObserver Receive Vector Potential") {
     // Checks that the basic functionality of the receive function is working properly
 
     using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
@@ -809,15 +809,15 @@ TEST_CASE("Antennas") {
     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
+    // create times for the observer
     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);
+    // make the two observers with different start times
+    TimeDomainObserver obs1("observer_name", point1, rootCS, t1, t2, t3, t1);
+    TimeDomainObserver obs2("observer_name", point2, rootCS, t4, t2, t3, t4);
 
     Vector<dimensionless_d> receiveVec1(rootCS, {0, 0, 1});
     Vector<dimensionless_d> receiveVec2(rootCS, {0, 1, 0});
@@ -827,40 +827,40 @@ TEST_CASE("Antennas") {
     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]);
+    // inject efield into obs1
+    obs1.receive(15_s, receiveVec1, vectorPotential1);
+    REQUIRE(obs1.getWaveformX()[5] - 10 == 0);
+    REQUIRE(obs1.getWaveformX()[5] == obs1.getWaveformY()[5]);
+    REQUIRE(obs1.getWaveformX()[5] == obs1.getWaveformZ()[5]);
+
+    // inject efield but with different receive vector into obs2
+    obs2.receive(16_s, receiveVec2, vectorPotential1);
+    REQUIRE(obs1.getWaveformX()[5] ==
+            obs2.getWaveformX()[5]); // Currently receive vector does nothing
+    obs2.reset();
+    REQUIRE(obs2.getWaveformX()[5] == 0); // reset was successful
+
+    // inject the other eField into obs2
+    obs2.receive(16_s, receiveVec2, vectorPotential2);
+    REQUIRE(obs2.getWaveformX()[5] - 20 == 0);
+    REQUIRE(obs2.getWaveformX()[5] == obs2.getWaveformY()[5]);
+    REQUIRE(obs2.getWaveformX()[5] == obs2.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);
+    REQUIRE(obs2.getWaveformX()[6] == 0);
+    obs2.receive(17_s, receiveVec2, vectorPotential2);
+    REQUIRE(obs2.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")
+    // reset obs1 and then put values in out of range
+    obs1.reset();
+    obs1.receive(-1000_s, receiveVec1, vectorPotential1);
+    for (auto const& val : obs1.getWaveformX()) { CHECK(val * 0 == val); }
+    obs1.reset();
+    obs1.receive(t1 + t2 + 1_s, receiveVec1, vectorPotential1);
+    for (auto const& val : obs1.getWaveformX()) { CHECK(val * 0 == val); }
+  } // END: SECTION("TimeDomainObserver Receive Vector Potential")
 
-  SECTION("TimeDomainAntenna AntennaCollection") {
+  SECTION("TimeDomainObserver ObserverCollection") {
 
     // create an environment so we can get a coordinate system
     using EnvType = Environment<IRefractiveIndexModel<IMediumModel>>;
@@ -869,7 +869,7 @@ TEST_CASE("Antennas") {
     using UniRIndex =
         UniformRefractiveIndex<HomogeneousMedium<IRefractiveIndexModel<IMediumModel>>>;
 
-    // the antenna location
+    // the observer location
     const auto point1{Point(env6.getCoordinateSystem(), 1_m, 2_m, 3_m)};
     const auto point2{Point(env6.getCoordinateSystem(), 4_m, 5_m, 6_m)};
 
@@ -884,86 +884,86 @@ TEST_CASE("Antennas") {
 
     env6.getUniverse()->addChild(std::move(Medium6));
 
-    // create times for the antenna
+    // create times for the observer
     const TimeType t1{10_s};
     const TimeType t2{10_s};
     const InverseTimeType t3{1 / 1_s};
     const TimeType t4{11_s};
 
-    // construct a radio detector instance to store our antennas
-    AntennaCollection<TimeDomainAntenna> detector;
+    // construct a radio detector instance to store our observers
+    ObserverCollection<TimeDomainObserver> detector;
 
-    // the following creates a star-shaped pattern of antennas in the ground
+    // the following creates a star-shaped pattern of observers in the ground
     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;
+    std::vector<std::string> observer_names;
+    std::vector<Point> observer_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);
+        observer_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_) +
+        std::string name = "observer_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);
+        observer_names.push_back(name);
+        TimeDomainObserver obs(name, point, rootCS, time__, t2222, t3333, time__);
+        detector.addObserver(obs);
       }
     }
 
     CHECK(detector.size() == 16);
-    CHECK(detector.getAntennas().size() == 16);
+    CHECK(detector.getObservers().size() == 16);
     int i = 0;
-    // this prints out the antenna names and locations
-    for (auto const& antenna : detector.getAntennas()) {
-      CHECK(antenna.getName() == antenna_names[i]);
-      CHECK(distance(antenna.getLocation(), antenna_locations[i]) / 1_m == 0);
+    // this prints out the observer names and locations
+    for (auto const& observer : detector.getObservers()) {
+      CHECK(observer.getName() == observer_names[i]);
+      CHECK(distance(observer.getLocation(), observer_locations[i]) / 1_m == 0);
       i++;
     }
 
     // Check the .at() method for radio detectors
     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);
+      CHECK(detector.at(i).getName() == observer_names[i]);
+      CHECK(distance(detector.at(i).getLocation(), observer_locations[i]) / 1_m == 0);
     }
 
-  } // END: SECTION("TimeDomainAntenna AntennaCollection")
+  } // END: SECTION("TimeDomainObserver ObserverCollection")
 
-  SECTION("TimeDomainAntenna Config File") {
+  SECTION("TimeDomainObserver Config File") {
     // 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});
+    auto const obsPos = 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 antennaC("test_antennaCoREAS", antPos, rootCS, tStart, duration,
-                               sampleRate, groundHitTime);
-    TimeDomainAntenna antennaZ("test_antennaZHS", antPos, rootCS, tStart, duration,
-                               sampleRate, groundHitTime);
+    TimeDomainObserver observerC("test_observerCoREAS", obsPos, rootCS, tStart, duration,
+                                 sampleRate, groundHitTime);
+    TimeDomainObserver observerZ("test_observerZHS", obsPos, rootCS, tStart, duration,
+                                 sampleRate, groundHitTime);
 
     // Check the YAML file output
-    auto const configC = antennaC.getConfig();
-    CHECK(configC["type"].as<std::string>() == "TimeDomainAntenna");
+    auto const configC = observerC.getConfig();
+    CHECK(configC["type"].as<std::string>() == "TimeDomainObserver");
     CHECK(configC["start time"].as<double>() == tStart / 1_ns);
     CHECK(configC["duration"].as<double>() == duration / 1_ns);
     CHECK(configC["sampling frequency"].as<double>() == sampleRate / 1_GHz);
 
-    auto const configZ = antennaZ.getConfig();
-    CHECK(configZ["type"].as<std::string>() == "TimeDomainAntenna");
+    auto const configZ = observerZ.getConfig();
+    CHECK(configZ["type"].as<std::string>() == "TimeDomainObserver");
     CHECK(configZ["start time"].as<double>() == tStart / 1_ns);
     CHECK(configZ["duration"].as<double>() == duration / 1_ns);
     CHECK(configZ["sampling frequency"].as<double>() == sampleRate / 1_GHz);
-  } // END: SECTION("TimeDomainAntenna Config File")
+  } // END: SECTION("TimeDomainObserver Config File")
 
-} // END: TEST_CASE("Antennas")
+} // END: TEST_CASE("observers")
 
 TEST_CASE("Propagators") {
 
@@ -1003,7 +1003,7 @@ TEST_CASE("Propagators") {
     Point const center{rootCS, 0_m, 0_m, 0_m};
     // a refractive index for the vacuum
     const double ri_{1};
-    // the constant density
+    // the constobs density
     const auto density{19.2_g / cube(1_cm)};
     // the composition we use for the homogeneous medium
     NuclearComposition const Composition({Code::Nitrogen}, {1.});
@@ -1092,7 +1092,7 @@ TEST_CASE("Propagators") {
     Point const center{rootCS, 0_m, 0_m, 0_m};
     // a refractive index for the vacuum
     const double ri_{1};
-    // the constant density
+    // the constobs density
     const auto density{19.2_g / cube(1_cm)};
     // the composition we use for the homogeneous medium
     NuclearComposition const Composition({Code::Nitrogen}, {1.});
-- 
GitLab