diff --git a/Processes/InteractionCounter/CMakeLists.txt b/Processes/InteractionCounter/CMakeLists.txt
index 30b8815312afe511b787c84a5dbee1efff274cf6..2323207a37e42a6723df1433553f80974606b732 100644
--- a/Processes/InteractionCounter/CMakeLists.txt
+++ b/Processes/InteractionCounter/CMakeLists.txt
@@ -1,24 +1,36 @@
 set (
   MODEL_HEADERS
   InteractionCounter.h
+  InteractionHistogram.h
   )
 
+set (
+  MODEL_SOURCES
+  InteractionHistogram.cc
+)
+
 set (
   MODEL_NAMESPACE
   corsika/process/interaction_counter
   )
 
-FIND_PACKAGE( Boost 1.70 REQUIRED )
-
-add_library (ProcessInteractionCounter INTERFACE)
+add_library (ProcessInteractionCounter STATIC ${MODEL_SOURCES})
 CORSIKA_COPY_HEADERS_TO_NAMESPACE (ProcessInteractionCounter ${MODEL_NAMESPACE} ${MODEL_HEADERS})
 
+set_target_properties (
+  ProcessInteractionCounter
+  PROPERTIES
+  VERSION ${PROJECT_VERSION}
+  SOVERSION 1
+#  PUBLIC_HEADER "${MODEL_HEADERS}"
+  )
+
 # target dependencies on other libraries (also the header onlys)
 target_link_libraries (
   ProcessInteractionCounter
-  INTERFACE
   CORSIKAunits
   CORSIKAprocesssequence
+  CORSIKAthirdparty
   )
 
 target_include_directories (
@@ -26,7 +38,6 @@ target_include_directories (
   INTERFACE 
   $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
   $<INSTALL_INTERFACE:include/include>
-  ${Boost_INCLUDE_DIR}
   )
 
 install (FILES ${MODEL_HEADERS} DESTINATION include/${MODEL_NAMESPACE})
diff --git a/Processes/InteractionCounter/InteractionCounter.h b/Processes/InteractionCounter/InteractionCounter.h
index a6fb6b43b8f8bb245697b935d0d54810ad2a1506..a03c528881ce6e3a67f530c1fe170312cd90ce7f 100644
--- a/Processes/InteractionCounter/InteractionCounter.h
+++ b/Processes/InteractionCounter/InteractionCounter.h
@@ -13,207 +13,10 @@
 
 #include <corsika/process/InteractionProcess.h>
 #include <corsika/process/ProcessSequence.h>
+#include <corsika/process/interaction_counter/InteractionHistogram.h>
 #include <corsika/setup/SetupStack.h>
-#include <corsika/units/PhysicalUnits.h>
-
-#include <boost/histogram.hpp>
-#include <boost/histogram/ostream.hpp>
-#include <fstream>
-#include <functional>
-#include <map>
-#include <utility>
-
-template <typename TKey, typename TVal>
-auto operator+=(std::map<TKey, TVal>& a, std::map<TKey, TVal> b) {
-  a.merge(b);
-  for (auto const& [id, hist] : b) { a[id] += hist; }
-  return a;
-}
 
 namespace corsika::process::interaction_counter {
-  using hist_type = decltype(boost::histogram::make_histogram(
-      std::declval<boost::histogram::axis::integer<particles::CodeIntType>>(),
-      std::declval<boost::histogram::axis::regular<
-          double, boost::histogram::axis::transform::log>>()));
-
-  using nucl_hist_type = decltype(boost::histogram::make_histogram(
-      std::declval<boost::histogram::axis::regular<
-          double, boost::histogram::axis::transform::log>>()));
-
-  using nuclear_hist_type = std::map<int32_t, nucl_hist_type>;
-
-  class InteractionHistogram {
-    static auto constexpr lower_edge_cms = 1., upper_edge_cms = 1e8;  // GeV sqrt s
-    static auto constexpr lower_edge_lab = 1., upper_edge_lab = 1e12; // GeV lab
-    static auto constexpr num_bins_lab = 120, num_bins_cms = 80;
-    static auto constexpr numIds =
-        static_cast<particles::CodeIntType>(particles::Code::LastParticle);
-
-    hist_type interaction_histogram_cms_;
-    hist_type interaction_histogram_lab_;
-
-    /*!
-     * These maps map PDG nuclei codes to their corresponding interaction histograms
-     */
-    nuclear_hist_type nuclear_inthist_lab_, nuclear_inthist_cms_;
-
-  public:
-    InteractionHistogram()
-        : interaction_histogram_cms_{boost::histogram::make_histogram(
-              boost::histogram::axis::integer<short>(0, numIds),
-              boost::histogram::axis::regular<double,
-                                              boost::histogram::axis::transform::log>(
-                  num_bins_cms, lower_edge_cms, upper_edge_cms))}
-        , interaction_histogram_lab_{boost::histogram::make_histogram(
-              boost::histogram::axis::integer<short>(0, numIds),
-              boost::histogram::axis::regular<double,
-                                              boost::histogram::axis::transform::log>(
-                  num_bins_lab, lower_edge_lab, upper_edge_lab))} {}
-
-    void fill(particles::Code projectile_id, units::si::HEPEnergyType lab_energy,
-              units::si::HEPEnergyType mass_target, int A = 0, int Z = 0) {
-      using namespace units::si;
-
-      if (projectile_id == particles::Code::Nucleus) {
-        auto const sqrtS =
-            sqrt(A * A * (units::constants::nucleonMass * units::constants::nucleonMass) +
-                 mass_target * mass_target + 2 * lab_energy * mass_target);
-
-        int32_t const pdg = 1'000'000'000l + Z * 10'000l + A * 10l;
-
-        if (nuclear_inthist_cms_.count(pdg) == 0) {
-          nuclear_inthist_lab_.emplace(
-              pdg,
-              boost::histogram::make_histogram(
-                  boost::histogram::axis::regular<double,
-                                                  boost::histogram::axis::transform::log>(
-                      num_bins_lab, lower_edge_lab, upper_edge_lab)));
-
-          nuclear_inthist_cms_.emplace(
-              pdg,
-              boost::histogram::make_histogram(
-                  boost::histogram::axis::regular<double,
-                                                  boost::histogram::axis::transform::log>(
-                      num_bins_cms, lower_edge_cms, upper_edge_cms)));
-        }
-
-        nuclear_inthist_lab_[pdg](lab_energy / 1_GeV);
-        nuclear_inthist_cms_[pdg](sqrtS / 1_GeV);
-      } else {
-        auto const projectile_mass = particles::GetMass(projectile_id);
-        auto const sqrtS = sqrt(projectile_mass * projectile_mass +
-                                mass_target * mass_target + 2 * lab_energy * mass_target);
-
-        interaction_histogram_cms_(
-            static_cast<corsika::particles::CodeIntType>(projectile_id), sqrtS / 1_GeV);
-
-        interaction_histogram_lab_(
-            static_cast<corsika::particles::CodeIntType>(projectile_id),
-            lab_energy / 1_GeV);
-      }
-    }
-
-    auto CMSHists() const {
-      return std::pair<decltype(interaction_histogram_cms_) const&,
-                       decltype(nuclear_inthist_cms_) const&>{interaction_histogram_cms_,
-                                                              nuclear_inthist_cms_};
-    }
-
-    auto labHists() const {
-      return std::pair<decltype(interaction_histogram_lab_) const&,
-                       decltype(nuclear_inthist_lab_) const&>(interaction_histogram_lab_,
-                                                              nuclear_inthist_lab_);
-    }
-
-    void saveLab(std::string const& filename) const {
-      save(interaction_histogram_lab_, nuclear_inthist_lab_, filename, "lab system");
-    }
-
-    void saveCMS(std::string const& filename) const {
-      save(interaction_histogram_lab_, nuclear_inthist_cms_, filename,
-           "center-of-mass system");
-    }
-
-    auto& operator+=(InteractionHistogram const& other) {
-      interaction_histogram_lab_ += other.interaction_histogram_lab_;
-      interaction_histogram_cms_ += other.interaction_histogram_cms_;
-
-      nuclear_inthist_lab_ += other.nuclear_inthist_lab_;
-      nuclear_inthist_cms_ += other.nuclear_inthist_cms_;
-
-      return *this;
-    }
-
-    auto operator+(InteractionHistogram other) const {
-      other.nuclear_inthist_lab_ += nuclear_inthist_lab_;
-      other.nuclear_inthist_cms_ += nuclear_inthist_cms_;
-
-      return other;
-    }
-
-  private:
-    /*! Save a histogram into a text file. The \arg comment string is written
-     * into the header of the text file.
-     * This method is static so that you can sum the histograms of multiple
-     * InteractionProcesses before saving them into the same file.
-     */
-
-    static void saveHist(hist_type const& hist, std::string const& filename,
-                         std::string const& comment = "") {
-      std::ofstream file;
-      file.open(filename);
-      saveHist(hist, file, comment);
-    }
-
-    static void saveHist(hist_type const& hist, std::ofstream& file,
-                         std::string const& comment = "") {
-      auto const& energy_axis = hist.axis(1);
-
-      file << "# interaction count histogram (" << comment << ")" << std::endl
-           << "# " << energy_axis.size() << " bins between " << energy_axis.bin(0).lower()
-           << " and " << energy_axis.bin(energy_axis.size() - 1).upper() << " GeV"
-           << std::endl;
-
-      for (particles::CodeIntType p = 0;
-           p < static_cast<particles::CodeIntType>(particles::Code::LastParticle); ++p) {
-
-        if (auto pdg = static_cast<particles::PDGCodeType>(
-                particles::GetPDG(static_cast<particles::Code>(p)));
-            pdg < 1'000'000'000l) {
-          file << "# " << static_cast<particles::Code>(p) << std::endl;
-          file << pdg;
-          for (int i = 0; i < energy_axis.size(); ++i) { file << ' ' << hist.at(p, i); }
-          file << std::endl;
-        }
-      }
-    }
-
-    static void saveHistMap(nuclear_hist_type const& histMap, std::ofstream& file) {
-      file << "# nuclei" << std::endl;
-      for (auto const& [pdg, hist] : histMap) {
-        auto const num_ebins_nucl = hist.axis(0).size();
-
-        file << pdg << ' ';
-        for (int i = 0; i < num_ebins_nucl; ++i) { file << ' ' << hist.at(i); }
-        file << std::endl;
-      }
-    }
-
-    /*!
-     * save both the "normal" particle histograms as well as the "nuclear" histograms
-     * into the same file
-     */
-
-    static void save(hist_type const& hist, nuclear_hist_type const& histMap,
-                     std::string const& filename, std::string const& comment = "") {
-      std::ofstream file;
-      file.open(filename);
-
-      saveHist(hist, file, comment);
-      saveHistMap(histMap, file);
-    }
-  };
-
   /*!
    * Wrapper around an InteractionProcess that fills histograms of the number
    * of calls to DoInteraction() binned in projectile energy (both in
diff --git a/Processes/InteractionCounter/InteractionHistogram.cc b/Processes/InteractionCounter/InteractionHistogram.cc
new file mode 100644
index 0000000000000000000000000000000000000000..556b58f2788f1063a594bb41fb06a552ed5c563d
--- /dev/null
+++ b/Processes/InteractionCounter/InteractionHistogram.cc
@@ -0,0 +1,147 @@
+/*
+ * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * See file AUTHORS for a list of contributors.
+ *
+ * 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.
+ */
+
+#include <corsika/process/interaction_counter/InteractionHistogram.h>
+
+#include <fstream>
+#include <string>
+
+using namespace corsika::process::interaction_counter;
+
+void InteractionHistogram::fill(particles::Code projectile_id,
+                                units::si::HEPEnergyType lab_energy,
+                                units::si::HEPEnergyType mass_target, int A, int Z) {
+  using namespace units::si;
+
+  if (projectile_id == particles::Code::Nucleus) {
+    auto const sqrtS =
+        sqrt(A * A * (units::constants::nucleonMass * units::constants::nucleonMass) +
+             mass_target * mass_target + 2 * lab_energy * mass_target);
+
+    int32_t const pdg = 1'000'000'000l + Z * 10'000l + A * 10l;
+
+    if (nuclear_inthist_cms_.count(pdg) == 0) {
+      nuclear_inthist_lab_.emplace(
+          pdg,
+          boost::histogram::make_histogram(
+              boost::histogram::axis::regular<double,
+                                              boost::histogram::axis::transform::log>(
+                  num_bins_lab, lower_edge_lab, upper_edge_lab)));
+
+      nuclear_inthist_cms_.emplace(
+          pdg,
+          boost::histogram::make_histogram(
+              boost::histogram::axis::regular<double,
+                                              boost::histogram::axis::transform::log>(
+                  num_bins_cms, lower_edge_cms, upper_edge_cms)));
+    }
+
+    nuclear_inthist_lab_[pdg](lab_energy / 1_GeV);
+    nuclear_inthist_cms_[pdg](sqrtS / 1_GeV);
+  } else {
+    auto const projectile_mass = particles::GetMass(projectile_id);
+    auto const sqrtS = sqrt(projectile_mass * projectile_mass +
+                            mass_target * mass_target + 2 * lab_energy * mass_target);
+
+    interaction_histogram_cms_(
+        static_cast<corsika::particles::CodeIntType>(projectile_id), sqrtS / 1_GeV);
+
+    interaction_histogram_lab_(
+        static_cast<corsika::particles::CodeIntType>(projectile_id), lab_energy / 1_GeV);
+  }
+}
+
+void InteractionHistogram::saveLab(std::string const& filename) const {
+  save(interaction_histogram_lab_, nuclear_inthist_lab_, filename, "lab system");
+}
+
+void InteractionHistogram::saveCMS(std::string const& filename) const {
+  save(interaction_histogram_lab_, nuclear_inthist_cms_, filename,
+       "center-of-mass system");
+}
+
+InteractionHistogram& InteractionHistogram::operator+=(
+    InteractionHistogram const& other) {
+  interaction_histogram_lab_ += other.interaction_histogram_lab_;
+  interaction_histogram_cms_ += other.interaction_histogram_cms_;
+
+  nuclear_inthist_lab_ += other.nuclear_inthist_lab_;
+  nuclear_inthist_cms_ += other.nuclear_inthist_cms_;
+
+  return *this;
+}
+
+InteractionHistogram InteractionHistogram::operator+(InteractionHistogram other) const {
+  other.nuclear_inthist_lab_ += nuclear_inthist_lab_;
+  other.nuclear_inthist_cms_ += nuclear_inthist_cms_;
+
+  return other;
+}
+
+void InteractionHistogram::saveHist(hist_type const& hist, std::string const& filename,
+                                    std::string const& comment) {
+  std::ofstream file;
+  file.open(filename);
+  saveHist(hist, file, comment);
+}
+
+void InteractionHistogram::saveHist(hist_type const& hist, std::ofstream& file,
+                                    std::string const& comment) {
+  auto const& energy_axis = hist.axis(1);
+
+  file << "# interaction count histogram (" << comment << ")" << std::endl
+       << "# " << energy_axis.size() << " bins between " << energy_axis.bin(0).lower()
+       << " and " << energy_axis.bin(energy_axis.size() - 1).upper() << " GeV"
+       << std::endl;
+
+  for (particles::CodeIntType p = 0;
+       p < static_cast<particles::CodeIntType>(particles::Code::LastParticle); ++p) {
+
+    if (auto pdg = static_cast<particles::PDGCodeType>(
+            particles::GetPDG(static_cast<particles::Code>(p)));
+        pdg < 1'000'000'000l) {
+      file << "# " << static_cast<particles::Code>(p) << std::endl;
+      file << pdg;
+      for (int i = 0; i < energy_axis.size(); ++i) { file << ' ' << hist.at(p, i); }
+      file << std::endl;
+    }
+  }
+}
+
+void InteractionHistogram::saveHistMap(nuclear_hist_type const& histMap,
+                                       std::ofstream& file) {
+  file << "# nuclei" << std::endl;
+  for (auto const& [pdg, hist] : histMap) {
+    auto const num_ebins_nucl = hist.axis(0).size();
+
+    file << pdg << ' ';
+    for (int i = 0; i < num_ebins_nucl; ++i) { file << ' ' << hist.at(i); }
+    file << std::endl;
+  }
+}
+
+void InteractionHistogram::save(hist_type const& hist, nuclear_hist_type const& histMap,
+                                std::string const& filename, std::string const& comment) {
+  std::ofstream file;
+  file.open(filename);
+
+  saveHist(hist, file, comment);
+  saveHistMap(histMap, file);
+}
+
+InteractionHistogram::InteractionHistogram()
+    : interaction_histogram_cms_{boost::histogram::make_histogram(
+          boost::histogram::axis::integer<short>(0, numIds),
+          boost::histogram::axis::regular<double, boost::histogram::axis::transform::log>(
+              num_bins_cms, lower_edge_cms, upper_edge_cms))}
+    , interaction_histogram_lab_{boost::histogram::make_histogram(
+          boost::histogram::axis::integer<short>(0, numIds),
+          boost::histogram::axis::regular<double, boost::histogram::axis::transform::log>(
+              num_bins_lab, lower_edge_lab, upper_edge_lab))} {}
diff --git a/Processes/InteractionCounter/InteractionHistogram.h b/Processes/InteractionCounter/InteractionHistogram.h
new file mode 100644
index 0000000000000000000000000000000000000000..98fedae84ee5b101e3904b2d1d18e5dc26e29d32
--- /dev/null
+++ b/Processes/InteractionCounter/InteractionHistogram.h
@@ -0,0 +1,107 @@
+/*
+ * (c) Copyright 2020 CORSIKA Project, corsika-project@lists.kit.edu
+ *
+ * See file AUTHORS for a list of contributors.
+ *
+ * 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.
+ */
+
+#include <corsika/particles/ParticleProperties.h>
+#include <corsika/units/PhysicalUnits.h>
+
+#include <boost/histogram.hpp>
+#include <boost/histogram/ostream.hpp>
+#include <fstream>
+#include <functional>
+#include <map>
+#include <utility>
+
+namespace corsika::process::interaction_counter {
+  using hist_type = decltype(boost::histogram::make_histogram(
+      std::declval<boost::histogram::axis::integer<particles::CodeIntType>>(),
+      std::declval<boost::histogram::axis::regular<
+          double, boost::histogram::axis::transform::log>>()));
+
+  using nucl_hist_type = decltype(boost::histogram::make_histogram(
+      std::declval<boost::histogram::axis::regular<
+          double, boost::histogram::axis::transform::log>>()));
+
+  using nuclear_hist_type = std::map<int32_t, nucl_hist_type>;
+
+  template <typename TKey, typename TVal>
+  auto operator+=(std::map<TKey, TVal>& a, std::map<TKey, TVal> b) {
+    a.merge(b);
+    for (auto const& [id, hist] : b) { a[id] += hist; }
+    return a;
+  }
+
+  class InteractionHistogram {
+    static auto constexpr lower_edge_cms = 1., upper_edge_cms = 1e8;  // GeV sqrt s
+    static auto constexpr lower_edge_lab = 1., upper_edge_lab = 1e12; // GeV lab
+    static auto constexpr num_bins_lab = 120, num_bins_cms = 80;
+    static auto constexpr numIds =
+        static_cast<particles::CodeIntType>(particles::Code::LastParticle);
+
+    hist_type interaction_histogram_cms_;
+    hist_type interaction_histogram_lab_;
+
+    /*!
+     * These maps map PDG nuclei codes to their corresponding interaction histograms
+     */
+    nuclear_hist_type nuclear_inthist_lab_, nuclear_inthist_cms_;
+
+  public:
+    InteractionHistogram();
+
+    //! fill both CMS and lab histograms at the same time
+    void fill(particles::Code projectile_id, units::si::HEPEnergyType lab_energy,
+              units::si::HEPEnergyType mass_target, int A = 0, int Z = 0);
+
+    auto CMSHists() const {
+      return std::pair<decltype(interaction_histogram_cms_) const&,
+                       decltype(nuclear_inthist_cms_) const&>{interaction_histogram_cms_,
+                                                              nuclear_inthist_cms_};
+    }
+
+    auto labHists() const {
+      return std::pair<decltype(interaction_histogram_lab_) const&,
+                       decltype(nuclear_inthist_lab_) const&>(interaction_histogram_lab_,
+                                                              nuclear_inthist_lab_);
+    }
+
+    void saveLab(std::string const& filename) const;
+
+    void saveCMS(std::string const& filename) const;
+
+    InteractionHistogram& operator+=(InteractionHistogram const& other);
+
+    InteractionHistogram operator+(InteractionHistogram other) const;
+
+  private:
+    /*!
+     * Save a histogram into a text file. The \arg comment string is written
+     * into the header of the text file.
+     * This method is static so that you can sum the histograms of multiple
+     * InteractionProcesses before saving them into the same file.
+     */
+
+    static void saveHist(hist_type const& hist, std::string const& filename,
+                         std::string const& comment = "");
+
+    static void saveHist(hist_type const& hist, std::ofstream& file,
+                         std::string const& comment = "");
+
+    static void saveHistMap(nuclear_hist_type const& histMap, std::ofstream& file);
+
+    /*!
+     * save both the "normal" particle histograms as well as the "nuclear" histograms
+     * into the same file
+     */
+
+    static void save(hist_type const& hist, nuclear_hist_type const& histMap,
+                     std::string const& filename, std::string const& comment = "");
+  };
+
+} // namespace corsika::process::interaction_counter