diff --git a/src/algorithms/calorimetry/TrackClusterMergeSplitter.cc b/src/algorithms/calorimetry/TrackClusterMergeSplitter.cc
index 4fdd64359..12cf9a739 100644
--- a/src/algorithms/calorimetry/TrackClusterMergeSplitter.cc
+++ b/src/algorithms/calorimetry/TrackClusterMergeSplitter.cc
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
 // Copyright (C) 2024 Derek Anderson
 
-#include <edm4eic/CalorimeterHit.h>
+#include <edm4hep/MCParticle.h>
+#include <edm4hep/RawCalorimeterHit.h>
+#include <edm4hep/SimCalorimeterHit.h>
 #include <edm4hep/Vector3f.h>
 #include <edm4hep/utils/vector_utils.h>
 #include <fmt/core.h>
@@ -37,14 +39,14 @@ namespace eicrecon {
   //! Process inputs
   // --------------------------------------------------------------------------
   /*! Primary algorithm call: algorithm ingests a collection
-   *  protoclusters and a collection of track projections.
-   *  It then decides to merge or split protoclusters according
-   *  to the following algorithm:
+   *  clusters and a collection of track projections. It then
+   *  decides to merge or split clusters according to the
+   *  following algorithm:
    *    1. Identify all tracks projections pointing to the
    *       specified calorimeter.
-   *    2. Match relevant track projections to protoclusters
+   *    2. Match relevant track projections to clusters
    *       based on distance between projection and the energy-
-   *       weighted barycenter of the protocluster;
+   *       weighted barycenter of the cluster;
    *    3. For each cluster-track pair:
    *       i.  Calculate the significance of the pair's
    *           E/p relative to the provided mean E/p and
@@ -52,10 +54,10 @@ namespace eicrecon {
    *       ii. If the significance is less than the
    *           significance specified by `minSigCut`,
    *           merge all clusters within `drAdd`.
-   *    4. Create a protocluster for each merged cluster
-   *       and copy all unused protoclusters into output.
+   *    4. Create a cluster for each merged cluster
+   *       and copy all unused clusters into output.
    *       - If multiple tracks point to the same merged
-   *         cluster, create a new protocluster for each
+   *         cluster, create a new cluster for each
    *         projection with hit weighted relative to
    *         the track momentum.
    */
@@ -65,30 +67,40 @@ namespace eicrecon {
   ) const {
 
     // grab inputs/outputs
-    const auto [in_protoclusters, in_projections] = input;
-    auto [out_protoclusters] = output;
+#if EDM4EIC_VERSION_MAJOR >= 7
+    const auto [in_clusters, in_projections, in_clust_associations, in_hit_associations] = input;
+#else
+    const auto [in_clusters, in_projections, in_clust_associations, in_sim_hits] = input;
+#endif
+#if EDM4EIC_VERSION_MAJOR >= 8
+    auto [out_clusters, out_matches, out_clust_associations] = output;
+#else
+    auto [out_clusters, out_clust_associations] = output;
+#endif
 
     // exit if no clusters in collection
-    if (in_protoclusters->size() == 0) {
-      debug("No proto-clusters in input collection.");
+    if (in_clusters->size() == 0) {
+      debug("No clusters in input collection.");
       return;
     }
 
     // ------------------------------------------------------------------------
     // 1. Identify projections to calorimeter
     // ------------------------------------------------------------------------
+    VecTrk  vecTrack;
     VecProj vecProject;
-    get_projections(in_projections, vecProject);
+    get_projections(in_projections, vecProject, vecTrack);
 
     // ------------------------------------------------------------------------
     // 2. Match relevant projections to clusters
     // ------------------------------------------------------------------------
+    MapToVecTrk  mapTrkToMatch;
     MapToVecProj mapProjToSplit;
     if (vecProject.size() == 0) {
       debug("No projections to match clusters to.");
       return;
     } else {
-      match_clusters_to_tracks(in_protoclusters, vecProject, mapProjToSplit);
+      match_clusters_to_tracks(in_clusters, vecProject, vecTrack, mapProjToSplit, mapTrkToMatch);
     }
 
     // ------------------------------------------------------------------------
@@ -112,7 +124,7 @@ namespace eicrecon {
       setUsedClust.insert( clustSeed );
 
       // grab cluster energy and projection momentum
-      const float eClustSeed = get_cluster_energy(clustSeed);
+      const float eClustSeed = clustSeed.getEnergy();
       const float eProjSeed = m_cfg.avgEP * edm4hep::utils::magnitude(projSeed.momentum);
 
       // ----------------------------------------------------------------------
@@ -130,14 +142,13 @@ namespace eicrecon {
       }
 
       // get eta, phi of seed
-      const auto posSeed = get_cluster_position(clustSeed);
-      const float etaSeed = edm4hep::utils::eta(posSeed);
-      const float phiSeed = edm4hep::utils::angleAzimuthal(posSeed);
+      const float etaSeed = edm4hep::utils::eta(clustSeed.getPosition());
+      const float phiSeed = edm4hep::utils::angleAzimuthal(clustSeed.getPosition());
 
       // loop over other clusters
       float eClustSum = eClustSeed;
       float sigSum = sigSeed;
-      for (auto in_cluster : *in_protoclusters) {
+      for (auto in_cluster : *in_clusters) {
 
         // ignore used clusters
         if (setUsedClust.count(in_cluster)) {
@@ -145,9 +156,8 @@ namespace eicrecon {
         }
 
         // get eta, phi of cluster
-        const auto posClust = get_cluster_position(in_cluster);
-        const float etaClust = edm4hep::utils::eta(posClust);
-        const float phiClust = edm4hep::utils::angleAzimuthal(posClust);
+        const float etaClust = edm4hep::utils::eta(in_cluster.getPosition());
+        const float phiClust = edm4hep::utils::angleAzimuthal(in_cluster.getPosition());
 
         // get distance to seed
         const float drToSeed = std::hypot(
@@ -177,7 +187,7 @@ namespace eicrecon {
         }
 
         // increment sums and output debugging
-        eClustSum += get_cluster_energy(in_cluster);
+        eClustSum += in_cluster.getEnergy();
         sigSum = (eClustSum - eProjSeed) / m_cfg.sigEP;
         trace(
           "{} clusters to merge: current sum = {}, current significance = {}, {} track(s) pointing to merged cluster",
@@ -190,21 +200,55 @@ namespace eicrecon {
     }  // end matched cluster-projection loop
 
     // ------------------------------------------------------------------------
-    // 4. Create an output protocluster for each merged cluster and for
+    // 4. Create an output cluster for each merged cluster and for
     //    each track pointing to merged cluster
     // ------------------------------------------------------------------------
     for (auto& [clustSeed, vecClustToMerge] : mapClustToMerge) {
+
+      // create a cluster for each projection to merged cluster
+      std::vector<edm4eic::MutableCluster> new_clusters;
+      for (const auto& proj : mapProjToSplit[clustSeed]) {
+        new_clusters.push_back( out_clusters->create() );
+      }
+
+      // merge & split as needed
       merge_and_split_clusters(
         vecClustToMerge,
         mapProjToSplit[clustSeed],
-        out_protoclusters
+        new_clusters
       );
+
+      // collect associations of merged clusters
+      for (const auto& new_clust : new_clusters) {
+        collect_associations(
+          new_clust,
+          vecClustToMerge,
+          in_clust_associations,
+#if EDM4EIC_VERSION_MAJOR >= 7
+          in_hit_associations,
+#else
+          in_sim_hits,
+#endif
+          out_clust_associations
+        );
+      }
+
+#if EDM4EIC_VERSION_MAJOR >= 8
+      // and finally create a track-cluster match for each pair
+      for (std::size_t iTrk = 0; const auto& trk : mapTrkToMatch[clustSeed]) {
+        edm4eic::MutableTrackClusterMatch match = out_matches->create();
+        match.setCluster( new_clusters[iTrk] );
+        match.setTrack( trk );
+        match.setWeight( 1.0 );  // FIXME placeholder
+        trace("Matched output cluster {} to track {}", new_clusters[iTrk].getObjectID().index, trk.getObjectID().index);
+      }
+#endif
     }  // end clusters to merge loop
 
     // ------------------------------------------------------------------------
     // copy unused clusters to output
     // ------------------------------------------------------------------------
-    for (auto in_cluster : *in_protoclusters) {
+    for (auto in_cluster : *in_clusters) {
 
       // ignore used clusters
       if (setUsedClust.count(in_cluster)) {
@@ -212,13 +256,25 @@ namespace eicrecon {
       }
 
       // copy cluster and add to output collection
-      edm4eic::MutableProtoCluster out_cluster = in_cluster.clone();
-      out_protoclusters->push_back(out_cluster);
+      edm4eic::MutableCluster out_cluster = in_cluster.clone();
+      out_clusters->push_back(out_cluster);
       trace("Copied input cluster {} onto output cluster {}",
         in_cluster.getObjectID().index,
         out_cluster.getObjectID().index
       );
 
+      // if provided, copy corresponding associations to
+      // output collection
+      for (auto in_assoc : *in_clust_associations) {
+        if (in_assoc.getRec() == in_cluster) {
+          edm4eic::MutableMCRecoClusterParticleAssociation out_assoc = in_assoc.clone();
+          out_clust_associations->push_back(out_assoc);
+          trace("Copied input association {} onto output association {}",
+            in_assoc.getObjectID().index,
+            out_assoc.getObjectID().index
+          );
+        }
+      }  // end association loop
     }  // end cluster loop
 
   }  // end 'process(Input&, Output&)'
@@ -228,9 +284,12 @@ namespace eicrecon {
   // --------------------------------------------------------------------------
   //! Collect projections pointing to calorimeter
   // --------------------------------------------------------------------------
+  /*! FIXME remove this once cluster-track matching has been centralized
+   */
   void TrackClusterMergeSplitter::get_projections(
     const edm4eic::TrackSegmentCollection* projections,
-    VecProj& relevant_projects
+    VecProj& relevant_projects,
+    VecTrk& relevant_trks
   ) const {
 
     // return if projections are empty
@@ -247,6 +306,8 @@ namespace eicrecon {
           (point.surface == 1)
         ) {
           relevant_projects.push_back(point);
+          relevant_trks.push_back(project.getTrack());
+          break;
         }
       }  // end point loop
     }  // end projection loop
@@ -262,9 +323,11 @@ namespace eicrecon {
   /*! FIXME remove this once cluster-track matching has been centralized
    */
   void TrackClusterMergeSplitter::match_clusters_to_tracks(
-    const edm4eic::ProtoClusterCollection* clusters,
+    const edm4eic::ClusterCollection* clusters,
     const VecProj& projections,
-    MapToVecProj& matches
+    const VecTrk& tracks,
+    MapToVecProj& matched_projects,
+    MapToVecTrk& matched_tracks
   ) const {
 
 
@@ -279,7 +342,7 @@ namespace eicrecon {
       const float phiProj = edm4hep::utils::angleAzimuthal(project.position);
 
       // to store matched cluster
-      edm4eic::ProtoCluster match;
+      edm4eic::Cluster match;
 
       // find closest cluster
       bool foundMatch = false;
@@ -287,9 +350,8 @@ namespace eicrecon {
       for (auto cluster : *clusters) {
 
         // get eta, phi of cluster
-        const auto  posClust = get_cluster_position(cluster);
-        const float etaClust = edm4hep::utils::eta(posClust);
-        const float phiClust = edm4hep::utils::angleAzimuthal(posClust);
+        const float etaClust = edm4hep::utils::eta(cluster.getPosition());
+        const float phiClust = edm4hep::utils::angleAzimuthal(cluster.getPosition());
 
         // calculate distance to centroid
         const float dist = std::hypot(
@@ -307,55 +369,47 @@ namespace eicrecon {
 
       // record match if found
       if (foundMatch) {
-        matches[match].push_back(project);
+        matched_projects[match].push_back(project);
+        matched_tracks[match].push_back(tracks[iProject]);
         trace("Matched cluster to track projection: eta-phi distance = {}", dMatch);
       }
-    }  // end cluster loop
-    debug("Finished matching clusters to track projections: {} matches", matches.size());
+    }  // end projection loop
+    debug("Finished matching clusters to track projections: {} matches", matched_projects.size());
 
-  }  // end 'match_clusters_to_tracks(edm4eic::ClusterCollection*, VecTrkPoint&, MapToVecProj&)'
+  }  // end 'match_clusters_to_tracks(edm4eic::ClusterCollection*, VecProj&, VecTrk&, MapToVecProj&, MapToVecTrk&)'
 
 
 
   // --------------------------------------------------------------------------
   //! Merge identified clusters and split if needed
   // --------------------------------------------------------------------------
-  /*! If multiple tracks are pointing to merged cluster, a new protocluster
-   *  is created for each track w/ hits weighted by its distance to the track
-   *  and the track's momentum.
+  /*! If multiple tracks are pointing to merged cluster, a new cluster
+   *  is created for each track w/ hits weighted by its distance to
+   *  the track and the track's momentum.
    */
   void TrackClusterMergeSplitter::merge_and_split_clusters(
     const VecClust& to_merge,
     const VecProj& to_split,
-    edm4eic::ProtoClusterCollection* out_protoclusters
+    std::vector<edm4eic::MutableCluster>& new_clusters
   ) const {
 
     // if only 1 matched track, no need to split
+    // otherwise split merged cluster for each
+    // matched track
     if (to_split.size() == 1) {
-      edm4eic::MutableProtoCluster new_clust = out_protoclusters->create();
-      for (const auto& old_clust : to_merge) {
-        for (const auto& hit : old_clust.getHits()) {
-          new_clust.addToHits( hit );
-          new_clust.addToWeights( 1. );
-        }
-        trace("Merged input cluster {} into output cluster {}", old_clust.getObjectID().index, new_clust.getObjectID().index);
-      }
+      make_cluster(to_merge, new_clusters.front());
       return;
+    } else {
+      trace("Splitting merged cluster across {} tracks", to_split.size());
     }
 
-    // otherwise split merged cluster for each matched track
-    std::vector<edm4eic::MutableProtoCluster> new_clusters;
-    for (const auto& proj : to_split) {
-      new_clusters.push_back( out_protoclusters->create() );
-    }
-    trace("Splitting merged cluster across {} tracks", to_split.size());
-
-    // loop over all hits from all clusters to merge
-    std::vector<float> weights( to_split.size(), 1. );
+    // calculate weights for splitting
+    VecWeights weights(to_split.size());
     for (const auto& old_clust : to_merge) {
       for (const auto& hit : old_clust.getHits()) {
 
-        // calculate hit's weight for each track
+        // calculate a weight for each projection
+        double wTotal = 0.;
         for (std::size_t iProj = 0; const auto& proj : to_split) {
 
           // get track eta, phi
@@ -373,77 +427,202 @@ namespace eicrecon {
             std::remainder(phiHit - phiProj, 2. * M_PI)
           );
 
-          // set weight
-          weights[iProj] = std::exp(-1. * dist / m_cfg.transverseEnergyProfileScale) * mom;
-          ++iProj;
-        }
+          // get weight
+          const float weight = std::exp(-1. * dist / m_cfg.transverseEnergyProfileScale) * mom ;
 
-        // normalize weights
-        float wTotal = 0.;
-        for (const float weight : weights) {
+          // set weight & increment sum of weights
+          weights[iProj][hit] = weight;
           wTotal += weight;
-        }
-        for (float& weight : weights) {
-          weight /= wTotal;
+          ++iProj;
         }
 
-        // add hit to each split merged cluster w/ relevant weight
-        for (std::size_t iProj = 0; auto& new_clust : new_clusters) {
-          new_clust.addToHits( hit );
-          new_clust.addToWeights( weights[iProj] );
+        // normalize weights over all projections
+        for (std::size_t iProj = 0; iProj < to_split.size(); ++iProj) {
+          weights[iProj][hit] /= wTotal;
         }
-
       }  // end hits to merge loop
     }  // end clusters to merge loop
 
-  }  // end 'merge_and_split_clusters(VecClust&, VecProj&, edm4eic::MutableCluster&)'
+   // make new clusters with relevant splitting weights
+   for (std::size_t iProj = 0; auto& new_clust : new_clusters) {
+     make_cluster(to_merge, new_clust, weights[iProj]);
+     ++iProj;
+   }
+
+  }  // end 'merge_and_split_clusters(VecClust&, VecProj&, std::vector<edm4eic::MutableCluster>&)'
 
 
 
   // --------------------------------------------------------------------------
-  //! Grab current energy of protocluster
+  //! Make new cluster out of old ones
   // --------------------------------------------------------------------------
-  float TrackClusterMergeSplitter::get_cluster_energy(const edm4eic::ProtoCluster& clust) const {
+  void TrackClusterMergeSplitter::make_cluster(
+    const VecClust& old_clusts,
+    edm4eic::MutableCluster& new_clust,
+    std::optional<MapToWeight> split_weights
+  ) const {
+
+    // determine total no. of hits
+    std::size_t nHits = 0;
+    for (const auto& old_clust : old_clusts) {
+      nHits += old_clust.getNhits();
+    }
+    new_clust.setNhits(nHits);
 
     float eClust = 0.;
-    for (auto hit : clust.getHits()) {
-      eClust += hit.getEnergy();
+    float wClust = 0.;
+    float tClust = 0.;
+    for (const auto& old_clust : old_clusts) {
+      for (std::size_t iHit = 0; const auto& hit : old_clust.getHits()) {
+
+        // get weight and update if needed
+        float weight = old_clust.getHitContributions()[iHit] / hit.getEnergy();
+        if (split_weights.has_value()) {
+          weight *= split_weights.value().at(hit);
+        }
+
+        // update running tallies
+        eClust += hit.getEnergy() * weight;
+        tClust += (hit.getTime() - tClust) * (hit.getEnergy() / eClust);
+        wClust += weight;
+
+        // add hits and increment counter
+        new_clust.addToHits(hit);
+        new_clust.addToHitContributions(hit.getEnergy() * weight);
+        ++iHit;
+      }  // end hit loop
+      trace("Merged input cluster {} into output cluster {}", old_clust.getObjectID().index, new_clust.getObjectID().index);
+    }  // end cluster loop
+
+    // update cluster position by taking energy-weighted
+    // average of positions of clusters to merge
+    edm4hep::Vector3f rClust = new_clust.getPosition();
+    for (const auto& old_clust : old_clusts) {
+      rClust = rClust + ((old_clust.getEnergy() / eClust) * old_clust.getPosition());
     }
-    return eClust / m_cfg.sampFrac;
 
-  }  // end 'get_cluster_energy(edm4eic::ProtoCluster&)'
+    // set parameters
+    new_clust.setEnergy(eClust);
+    new_clust.setEnergyError(0.);
+    new_clust.setTime(tClust);
+    new_clust.setTimeError(0.);
+    new_clust.setPosition(rClust);
+    new_clust.setPositionError({});
+
+  }  // end 'merge_cluster(VecClust&)'
 
 
 
   // --------------------------------------------------------------------------
-  //! Get current center of protocluster
+  //! Collect associations of merged clusters
   // --------------------------------------------------------------------------
-  edm4hep::Vector3f TrackClusterMergeSplitter::get_cluster_position(const edm4eic::ProtoCluster& clust) const {
+  /*! This collects the associations of all clusters being merged, and
+   *  and updates the weights of each to reflect the new merged cluster.
+   *
+   *  As in `CalorimeterClusterRecoCoG`, an association is made for each
+   *  contributing primary with a weight equal to the ratio of the
+   *  contributed energy energy over total sim hit energy.
+   */
+  void TrackClusterMergeSplitter::collect_associations(
+    const edm4eic::MutableCluster& new_clust,
+    const VecClust& old_clusts,
+    const edm4eic::MCRecoClusterParticleAssociationCollection* old_clust_assocs,
+#if EDM4EIC_VERSION_MAJOR >= 7
+    const edm4eic::MCRecoCalorimeterHitAssociationCollection* old_hit_assocs,
+#else
+    const edm4hep::SimCalorimeterHitCollection* old_sim_hits,
+#endif
+    edm4eic::MCRecoClusterParticleAssociationCollection* new_clust_assocs
+  ) const {
 
-    // grab total energy
-    const float eClust = get_cluster_energy(clust) * m_cfg.sampFrac;
+    // lambda to compare MCParticles
+    auto compare = [](const edm4hep::MCParticle& lhs, const edm4hep::MCParticle& rhs) {
+      if (lhs.getObjectID().collectionID == rhs.getObjectID().collectionID) {
+        return (lhs.getObjectID().index < rhs.getObjectID().index);
+      } else {
+        return (lhs.getObjectID().collectionID < rhs.getObjectID().collectionID);
+      }
+    };
 
-    // calculate energy-weighted center
-    float wTotal = 0.;
-    edm4hep::Vector3f position(0., 0., 0.);
-    for (auto hit : clust.getHits()) {
+    // create a map to hold associated particles and
+    // their weight
+    std::map<edm4hep::MCParticle, double, decltype(compare)> mapMCParToWeight(compare);
 
-      // calculate weight
-      float weight = hit.getEnergy() / eClust;
-      wTotal += weight;
+    // ------------------------------------------------------------------------
+    // loop through clusters
+    // ------------------------------------------------------------------------
+    double eMergeSimHitSum = 0.;
+    for (const auto& clust : old_clusts) {
 
-      // update cluster position
-      position = position + (hit.getPosition() * weight);
+      // ----------------------------------------------------------------------
+      // get total sim hit energy of old clust
+      // ----------------------------------------------------------------------
+      double eOldSimHitSum = 0.;
+      for (const auto& recHit : clust.getHits()) {
+#if EDM4EIC_VERSION_MAJOR >= 7
+        for (const auto& hitAssoc : *old_hit_assocs) {
+          if (hitAssoc.getRawHit() == recHit.getRawHit()) {
+            eOldSimHitSum += hitAssoc.getSimHit().getEnergy();
+          }
+        }  // end hit association loop
+#else
+        for (const auto& simHit : *old_sim_hits) {
+          if (simHit.getCellID() == recHit.getCellID()) {
+            eOldSimHitSum += simHit.getEnergy();
+            break;
+          }
+        }  // end sim hit loop
+#endif
+      }  // end rec hit loop
+      eMergeSimHitSum += eOldSimHitSum;
+
+      // ----------------------------------------------------------------------
+      // now collect all associations for this old cluster
+      // ----------------------------------------------------------------------
+      for (const auto& clustAssoc : *old_clust_assocs) {
+        if (clustAssoc.getRec() == clust) {
+          mapMCParToWeight[ clustAssoc.getSim() ] += (clustAssoc.getWeight() * eOldSimHitSum);
+        }
+      }  // end association loop
+    }  // end cluster loop
+
+    // ------------------------------------------------------------------------
+    // scale weights by sum of sim hit energies
+    // ------------------------------------------------------------------------
+    double wAssocSum = 0.;
+    for (auto& [par, weight] : mapMCParToWeight) {
+      weight /= eMergeSimHitSum;
+      wAssocSum += weight;
     }
 
-    float norm = 1.;
-    if (wTotal == 0.) {
-      warning("Total weight of 0 in position calculation!");
-    } else {
-      norm = wTotal;
+    // normalize weights if not already
+    if (wAssocSum != 1.0) {
+      trace("Sum of weight not unity, normalizing by sum ({})", wAssocSum);
+      for (auto& [par, weight] : mapMCParToWeight) {
+        weight /= wAssocSum;
+      }
+    }
+
+    // ------------------------------------------------------------------------
+    // and finally create an association for each unique primary
+    // ------------------------------------------------------------------------
+    for (const auto& [par, weight] : mapMCParToWeight) {
+      auto assoc = new_clust_assocs->create();
+      assoc.setRecID( new_clust.getObjectID().index );
+      assoc.setSimID( par.getObjectID().index );
+      assoc.setWeight( weight );
+      assoc.setRec( new_clust );
+      assoc.setSim( par );
+      trace("Associated output cluster {} to MC Particle {} (pid = {}, status = {}, energy = {}) with weight ({})",
+        new_clust.getObjectID().index,
+        par.getObjectID().index,
+        par.getPDG(),
+        par.getGeneratorStatus(),
+        par.getEnergy(),
+        weight
+      );
     }
-    return position / norm;
 
-  }  // end 'get_cluster_position(edm4eic::ProtoCluster&)'
+  }  // end 'collect_associations(...)'
 
 }  // end eicrecon namespace
diff --git a/src/algorithms/calorimetry/TrackClusterMergeSplitter.h b/src/algorithms/calorimetry/TrackClusterMergeSplitter.h
index e38e7e608..e3a86eabd 100644
--- a/src/algorithms/calorimetry/TrackClusterMergeSplitter.h
+++ b/src/algorithms/calorimetry/TrackClusterMergeSplitter.h
@@ -5,13 +5,24 @@
 
 #include <DD4hep/Detector.h>
 #include <algorithms/algorithm.h>
-#include <edm4eic/ProtoClusterCollection.h>
+#include <edm4eic/CalorimeterHit.h>
+#include <edm4eic/ClusterCollection.h>
+#include <edm4eic/EDM4eicVersion.h>
+#include <edm4eic/MCRecoClusterParticleAssociationCollection.h>
+#if EDM4EIC_VERSION_MAJOR >= 8
+#include <edm4eic/TrackClusterMatchCollection.h>
+#endif
+#include <edm4eic/Track.h>
 #include <edm4eic/TrackPoint.h>
 #include <edm4eic/TrackSegmentCollection.h>
-#include <edm4hep/Vector3f.h>
-#include <podio/ObjectID.h>
+#if EDM4EIC_VERSION_MAJOR >= 7
+#include <edm4eic/MCRecoCalorimeterHitAssociationCollection.h>
+#else
+#include <edm4hep/SimCalorimeterHitCollection.h>
+#endif
 #include <algorithm>
 #include <map>
+#include <optional>
 #include <set>
 #include <string>
 #include <string_view>
@@ -26,14 +37,14 @@
 namespace eicrecon {
 
   // --------------------------------------------------------------------------
-  //! Comparator struct for protoclusters
+  //! Comparator struct for object IDs
   // --------------------------------------------------------------------------
-  /*! Organizes protoclusters by their ObjectID's in decreasing collection
+  /*! Organizes objects by their ObjectID's in decreasing collection
    *  ID first, and second by decreasing index second.
    */
-  struct CompareProto {
+  template <typename T> struct CompareObjectID {
 
-    bool operator() (const edm4eic::ProtoCluster& lhs, const edm4eic::ProtoCluster& rhs) const {
+    bool operator() (const T& lhs, const T& rhs) const {
       if (lhs.getObjectID().collectionID == rhs.getObjectID().collectionID) {
         return (lhs.getObjectID().index < rhs.getObjectID().index);
       } else {
@@ -43,16 +54,24 @@ namespace eicrecon {
 
   };  // end CompareObjectID
 
+  // specialization for clusters, hits
+  using CompareClust = CompareObjectID<edm4eic::Cluster>;
+  using CompareHit = CompareObjectID<edm4eic::CalorimeterHit>;
+
 
 
   // --------------------------------------------------------------------------
   //! Convenience types
   // --------------------------------------------------------------------------
+  using VecTrk = std::vector<edm4eic::Track>;
   using VecProj = std::vector<edm4eic::TrackPoint>;
-  using VecClust = std::vector<edm4eic::ProtoCluster>;
-  using SetClust = std::set<edm4eic::ProtoCluster, CompareProto>;
-  using MapToVecProj = std::map<edm4eic::ProtoCluster, VecProj, CompareProto>;
-  using MapToVecClust = std::map<edm4eic::ProtoCluster, VecClust, CompareProto>;
+  using VecClust = std::vector<edm4eic::Cluster>;
+  using SetClust = std::set<edm4eic::Cluster, CompareClust>;
+  using MapToVecTrk = std::map<edm4eic::Cluster, VecTrk, CompareClust>;
+  using MapToVecProj = std::map<edm4eic::Cluster, VecProj, CompareClust>;
+  using MapToVecClust = std::map<edm4eic::Cluster, VecClust, CompareClust>;
+  using MapToWeight = std::map<edm4eic::CalorimeterHit, double, CompareHit>;
+  using VecWeights = std::vector<MapToWeight>;
 
 
 
@@ -61,11 +80,21 @@ namespace eicrecon {
   // --------------------------------------------------------------------------
   using TrackClusterMergeSplitterAlgorithm = algorithms::Algorithm<
     algorithms::Input<
-      edm4eic::ProtoClusterCollection,
-      edm4eic::TrackSegmentCollection
+      edm4eic::ClusterCollection,
+      edm4eic::TrackSegmentCollection,
+      std::optional<edm4eic::MCRecoClusterParticleAssociationCollection>,
+#if EDM4EIC_VERSION_MAJOR >= 7
+      std::optional<edm4eic::MCRecoCalorimeterHitAssociationCollection>
+#else
+      std::optional<edm4hep::SimCalorimeterHitCollection>
+#endif
     >,
     algorithms::Output<
-      edm4eic::ProtoClusterCollection
+      edm4eic::ClusterCollection,
+#if EDM4EIC_VERSION_MAJOR >= 8
+      edm4eic::TrackClusterMatchCollection,
+#endif
+      std::optional<edm4eic::MCRecoClusterParticleAssociationCollection>
     >
   >;
 
@@ -74,8 +103,8 @@ namespace eicrecon {
   // --------------------------------------------------------------------------
   //! Track-Based Cluster Merger/Splitter
   // --------------------------------------------------------------------------
-  /*! An algorithm which takes a collection of proto-clusters, matches
-   *  track projections, and then decides to merge or split those proto-
+  /*! An algorithm which takes a collection of clusters, matches
+   *  track projections, and then decides to merge or split those
    *  clusters based on average E/p from simulations.
    *
    *  Heavily inspired by Eur. Phys. J. C (2017) 77:466
@@ -91,8 +120,16 @@ namespace eicrecon {
       TrackClusterMergeSplitter(std::string_view name) :
         TrackClusterMergeSplitterAlgorithm {
           name,
-          {"InputProtoClusterCollection", "InputTrackProjections"},
-          {"OutputProtoClusterCollection"},
+#if EDM4EIC_VERSION_MAJOR >= 7
+          {"InputClusterCollection", "InputTrackProjections", "InputMCClusterAssociations", "InputMCHitAssociations"},
+#else
+          {"InputClusterCollection", "InputTrackProjections", "InputMCClusterAssociations", "InputMCHits"},
+#endif
+#if EDM4EIC_VERSION_MAJOR >= 8
+          {"OutputProtoClusterCollection", "OutputTrackClusterMatches", "OutputMCClusterAssociations"},
+#else
+          {"OutputProtoClusterCollection", "OutputMCClusterAssociations"},
+#endif
           "Merges or splits clusters based on tracks projected to them."
         } {}
 
@@ -103,11 +140,15 @@ namespace eicrecon {
     private:
 
       // private methods
-      void get_projections(const edm4eic::TrackSegmentCollection* projections, VecProj& relevant_projects) const;
-      void match_clusters_to_tracks(const edm4eic::ProtoClusterCollection* clusters, const VecProj& projections, MapToVecProj& matches) const;
-      void merge_and_split_clusters(const VecClust& to_merge, const VecProj& to_split, edm4eic::ProtoClusterCollection* out_protoclusters) const;
-      float get_cluster_energy(const edm4eic::ProtoCluster& clust) const;
-      edm4hep::Vector3f get_cluster_position(const edm4eic::ProtoCluster& clust) const;
+      void get_projections(const edm4eic::TrackSegmentCollection* projections, VecProj& relevant_projects, VecTrk& relevant_trks) const;
+      void match_clusters_to_tracks(const edm4eic::ClusterCollection* clusters, const VecProj& projections, const VecTrk& tracks, MapToVecProj& matched_projects, MapToVecTrk& matched_tracks) const;
+      void merge_and_split_clusters(const VecClust& to_merge, const VecProj& to_split, std::vector<edm4eic::MutableCluster>& new_clusters) const;
+      void make_cluster(const VecClust& old_clusts, edm4eic::MutableCluster& new_clust, std::optional<MapToWeight> split_weights = std::nullopt) const;
+#if EDM4EIC_VERSION_MAJOR >= 7
+      void collect_associations(const edm4eic::MutableCluster& new_clust, const VecClust& old_clusts, const edm4eic::MCRecoClusterParticleAssociationCollection* old_clust_assocs, const edm4eic::MCRecoCalorimeterHitAssociationCollection* old_hit_assocs, edm4eic::MCRecoClusterParticleAssociationCollection* new_clust_assocs) const;
+#else
+      void collect_associations(const edm4eic::MutableCluster& new_clust, const VecClust& old_clusts, const edm4eic::MCRecoClusterParticleAssociationCollection* old_clust_assocs, const edm4hep::SimCalorimeterHitCollection* old_sim_hits, edm4eic::MCRecoClusterParticleAssociationCollection* new_clust_assocs) const;
+#endif
 
       // calorimeter id
       int m_idCalo {0};
diff --git a/src/detectors/BHCAL/BHCAL.cc b/src/detectors/BHCAL/BHCAL.cc
index f205f4b89..13d7f17e7 100644
--- a/src/detectors/BHCAL/BHCAL.cc
+++ b/src/detectors/BHCAL/BHCAL.cc
@@ -194,10 +194,20 @@ extern "C" {
 
         app->Add(
           new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
-            "HcalBarrelSplitMergeProtoClusters",
-            {"HcalBarrelIslandProtoClusters",
-             "CalorimeterTrackProjections"},
-            {"HcalBarrelSplitMergeProtoClusters"},
+            "HcalBarrelSplitMergeClustersWithoutShapes",
+            {"HcalBarrelClusters",
+             "CalorimeterTrackProjections",
+             "HcalBarrelClusterAssociations",
+#if EDM4EIC_VERSION_MAJOR >= 7
+             "HcalBarrelRawHitAssociations"},
+#else
+             "HcalBarrelHits"},
+#endif
+            {"HcalBarrelSplitMergeClustersWithoutShapes",
+#if EDM4EIC_VERSION_MAJOR >= 8
+             "HcalBarrelTrackSplitMergeClusterMatches",
+#endif
+             "HcalBarrelSplitMergeClusterAssociationsWithoutShapes"},
             {
               .idCalo = "HcalBarrel_ID",
               .minSigCut = -2.0,
@@ -211,23 +221,6 @@ extern "C" {
           )
         );
 
-        app->Add(
-          new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
-             "HcalBarrelSplitMergeClustersWithoutShapes",
-            {"HcalBarrelSplitMergeProtoClusters", // edm4eic::ProtoClusterCollection
-             "HcalBarrelHits"},                          // edm4hep::SimCalorimeterHitCollection
-            {"HcalBarrelSplitMergeClustersWithoutShapes", // edm4eic::Cluster
-             "HcalBarrelSplitMergeClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
-            {
-              .energyWeight = "log",
-              .sampFrac = 1.0,
-              .logWeightBase = 6.2,
-              .enableEtaBounds = false
-            },
-            app   // TODO: Remove me once fixed
-          )
-        );
-
         app->Add(
           new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
             "HcalBarrelSplitMergeClusters",
@@ -235,10 +228,12 @@ extern "C" {
              "HcalBarrelSplitMergeClusterAssociationsWithoutShapes"},
             {"HcalBarrelSplitMergeClusters",
              "HcalBarrelSplitMergeClusterAssociations"},
-            {},
+            {
+              .energyWeight = "log",
+              .logWeightBase = 6.2
+            },
             app
           )
         );
-
     }
 }
diff --git a/src/detectors/EEMC/EEMC.cc b/src/detectors/EEMC/EEMC.cc
index bac5fdd00..d86210964 100644
--- a/src/detectors/EEMC/EEMC.cc
+++ b/src/detectors/EEMC/EEMC.cc
@@ -185,25 +185,6 @@ extern "C" {
           )
         );
 
-        app->Add(
-          new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
-            "EcalEndcapNSplitMergeProtoClusters",
-            {"EcalEndcapNIslandProtoClusters",
-             "CalorimeterTrackProjections"},
-            {"EcalEndcapNSplitMergeProtoClusters"},
-            {
-              .idCalo = "EcalEndcapN_ID",
-              .minSigCut = -1.0,
-              .avgEP = 1.0,
-              .sigEP = 0.10,
-              .drAdd = 0.08,
-              .sampFrac = 1.0,
-              .transverseEnergyProfileScale = 1.0
-            },
-            app   // TODO: remove me once fixed
-          )
-        );
-
 #if EDM4EIC_VERSION_MAJOR >= 8
         app->Add(new JOmniFactoryGeneratorT<CalorimeterParticleIDPreML_factory>(
             "EcalEndcapNParticleIDPreML",
@@ -248,19 +229,31 @@ extern "C" {
 #endif
 
         app->Add(
-          new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
-             "EcalEndcapNSplitMergeClustersWithoutShapes",
-            {"EcalEndcapNSplitMergeProtoClusters", // edm4eic::ProtoClusterCollection
-             "EcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection
-            {"EcalEndcapNSplitMergeClustersWithoutShapes", // edm4eic::Cluster
-             "EcalEndcapNSplitMergeClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
+          new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
+            "EcalEndcapNSplitMergeClustersWithoutShapes",
+            {"EcalEndcapNClustersWithoutPID",
+             "CalorimeterTrackProjections",
+             "EcalEndcapNClusterAssociations",
+#if EDM4EIC_VERSION_MAJOR >= 7
+             "EcalEndcapNRawHitAssociations"},
+#else
+             "EcalEndcapNHits"},
+#endif
+            {"EcalEndcapNSplitMergeClustersWithoutShapes",
+#if EDM4EIC_VERSION_MAJOR >= 8
+             "EcalEndcapNTrackSplitMergeClusterMatches",
+#endif
+             "EcalEndcapNSplitMergeClusterAssociationsWithoutShapes"},
             {
-              .energyWeight = "log",
+              .idCalo = "EcalEndcapN_ID",
+              .minSigCut = -1.0,
+              .avgEP = 1.0,
+              .sigEP = 0.10,
+              .drAdd = 0.08,
               .sampFrac = 1.0,
-              .logWeightBase = 3.6,
-              .enableEtaBounds = false
+              .transverseEnergyProfileScale = 1.0
             },
-            app   // TODO: Remove me once fixed
+            app   // TODO: remove me once fixed
           )
         );
 
diff --git a/src/detectors/EHCAL/EHCAL.cc b/src/detectors/EHCAL/EHCAL.cc
index 59c2283ea..033e81652 100644
--- a/src/detectors/EHCAL/EHCAL.cc
+++ b/src/detectors/EHCAL/EHCAL.cc
@@ -163,10 +163,20 @@ extern "C" {
         );
         app->Add(
           new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
-            "HcalEndcapNSplitMergeProtoClusters",
-            {"HcalEndcapNIslandProtoClusters",
-             "CalorimeterTrackProjections"},
-            {"HcalEndcapNSplitMergeProtoClusters"},
+            "HcalEndcapNSplitMergeClustersWithoutShapes",
+            {"HcalEndcapNClusters",
+             "CalorimeterTrackProjections",
+             "HcalEndcapNClusterAssociations",
+#if EDM4EIC_VERSION_MAJOR >= 7
+             "HcalEndcapNRawHitAssociations"},
+#else
+             "HcalEndcapNHits"},
+#endif
+            {"HcalEndcapNSplitMergeClustersWithoutShapes",
+#if EDM4EIC_VERSION_MAJOR >= 8
+             "HcalEndcapNTrackSplitMergeClusterMatches",
+#endif
+             "HcalEndcapNSplitMergeClusterAssociationsWithoutShapes"},
             {
               .idCalo = "HcalEndcapN_ID",
               .minSigCut = -2.0,
@@ -179,22 +189,6 @@ extern "C" {
             app   // TODO: remove me once fixed
           )
         );
-        app->Add(
-          new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
-             "HcalEndcapNSplitMergeClustersWithoutShapes",
-            {"HcalEndcapNSplitMergeProtoClusters", // edm4eic::ProtoClusterCollection
-             "HcalEndcapNHits"}, // edm4hep::SimCalorimeterHitCollection
-            {"HcalEndcapNSplitMergeClustersWithoutShapes", // edm4eic::Cluster
-             "HcalEndcapNSplitMergeClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
-            {
-              .energyWeight = "log",
-              .sampFrac = 1.0,
-              .logWeightBase = 6.2,
-              .enableEtaBounds = false
-            },
-            app   // TODO: Remove me once fixed
-          )
-        );
         app->Add(
           new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
             "HcalEndcapNSplitMergeClusters",
diff --git a/src/detectors/FEMC/FEMC.cc b/src/detectors/FEMC/FEMC.cc
index 209a5fbd4..c2ecf44b3 100644
--- a/src/detectors/FEMC/FEMC.cc
+++ b/src/detectors/FEMC/FEMC.cc
@@ -160,10 +160,20 @@ extern "C" {
 
         app->Add(
           new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
-            "EcalEndcapPSplitMergeProtoClusters",
-            {"EcalEndcapPIslandProtoClusters",
-             "CalorimeterTrackProjections"},
-            {"EcalEndcapPSplitMergeProtoClusters"},
+            "EcalEndcapPSplitMergeClustersWithoutShapes",
+            {"EcalEndcapPClusters",
+             "CalorimeterTrackProjections",
+             "EcalEndcapPClusterAssociations",
+#if EDM4EIC_VERSION_MAJOR >= 7
+             "EcalEndcapPRawHitAssociations"},
+#else
+             "EcalEndcapPHits"},
+#endif
+            {"EcalEndcapPSplitMergeClustersWithoutShapes",
+#if EDM4EIC_VERSION_MAJOR >= 8
+             "EcalEndcapPTrackSplitMergeClusterMatches",
+#endif
+             "EcalEndcapPSplitMergeClusterAssociationsWithoutShapes"},
             {
               .idCalo = "EcalEndcapP_ID",
               .minSigCut = -2.0,
@@ -177,23 +187,6 @@ extern "C" {
           )
         );
 
-        app->Add(
-          new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
-             "EcalEndcapPSplitMergeClustersWithoutShapes",
-            {"EcalEndcapPSplitMergeProtoClusters", // edm4eic::ProtoClusterCollection
-             "EcalEndcapPHits"},                          // edm4hep::SimCalorimeterHitCollection
-            {"EcalEndcapPSplitMergeClustersWithoutShapes", // edm4eic::Cluster
-             "EcalEndcapPSplitMergeClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
-            {
-              .energyWeight = "log",
-              .sampFrac = 1.0,
-              .logWeightBase = 3.6,
-              .enableEtaBounds = false
-            },
-            app   // TODO: Remove me once fixed
-          )
-        );
-
         app->Add(
           new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
             "EcalEndcapPSplitMergeClusters",
diff --git a/src/detectors/FHCAL/FHCAL.cc b/src/detectors/FHCAL/FHCAL.cc
index a7673d976..d25565548 100644
--- a/src/detectors/FHCAL/FHCAL.cc
+++ b/src/detectors/FHCAL/FHCAL.cc
@@ -363,10 +363,20 @@ extern "C" {
 
         app->Add(
           new JOmniFactoryGeneratorT<TrackClusterMergeSplitter_factory>(
-            "LFHCALSplitMergeProtoClusters",
-            {"LFHCALIslandProtoClusters",
-             "CalorimeterTrackProjections"},
-            {"LFHCALSplitMergeProtoClusters"},
+            "LFHCALSplitMergeClustersWithoutShapes",
+            {"LFHCALClusters",
+             "CalorimeterTrackProjections",
+             "LFHCALClusterAssociations",
+#if EDM4EIC_VERSION_MAJOR >= 7
+             "LFHCALRawHitAssocitions"},
+#else
+             "LFHCALHit"},
+#endif
+            {"LFHCALSplitMergeClustersWithoutShapes",
+#if EDM4EIC_VERSION_MAJOR >= 8
+             "LFHCALTrackSplitMergeClusterMatches",
+#endif
+             "LFHCALSplitMergeClusterAssociationsWithoutShapes"},
             {
               .idCalo = "LFHCAL_ID",
               .minSigCut = -2.0,
@@ -380,23 +390,6 @@ extern "C" {
           )
         );
 
-        app->Add(
-          new JOmniFactoryGeneratorT<CalorimeterClusterRecoCoG_factory>(
-             "LFHCALSplitMergeClustersWithoutShapes",
-            {"LFHCALSplitMergeProtoClusters", // edm4eic::ProtoClusterCollection
-             "LFHCALHits"}, // edm4hep::SimCalorimeterHitCollection
-            {"LFHCALSplitMergeClustersWithoutShapes", // edm4eic::Cluster
-             "LFHCALSplitMergeClusterAssociationsWithoutShapes"}, // edm4eic::MCRecoClusterParticleAssociation
-            {
-              .energyWeight = "log",
-              .sampFrac = 1.0,
-              .logWeightBase = 4.5,
-              .enableEtaBounds = false
-            },
-            app   // TODO: Remove me once fixed
-          )
-        );
-
         app->Add(
           new JOmniFactoryGeneratorT<CalorimeterClusterShape_factory>(
             "LFHCALSplitMergeClusters",
@@ -405,7 +398,9 @@ extern "C" {
             {"LFHCALSplitMergeClusters",
              "LFHCALSplitMergeClusterAssociations"},
             {
-              .longitudinalShowerInfoAvailable = true
+              .longitudinalShowerInfoAvailable = true,
+              .energyWeight = "log",
+              .logWeightBase = 4.5
             },
             app
           )
diff --git a/src/factories/calorimetry/TrackClusterMergeSplitter_factory.h b/src/factories/calorimetry/TrackClusterMergeSplitter_factory.h
index e5d6daec9..fd710da14 100644
--- a/src/factories/calorimetry/TrackClusterMergeSplitter_factory.h
+++ b/src/factories/calorimetry/TrackClusterMergeSplitter_factory.h
@@ -7,6 +7,8 @@
 #include <string>
 // dd4hep utilities
 #include <DD4hep/Detector.h>
+// edm utilities
+#include <edm4eic/EDM4eicVersion.h>
 // eicrecon components
 #include "extensions/jana/JOmniFactory.h"
 #include "services/geometry/dd4hep/DD4hep_service.h"
@@ -27,11 +29,21 @@ namespace eicrecon {
       std::unique_ptr<AlgoT> m_algo;
 
       // input collections
-      PodioInput<edm4eic::ProtoCluster> m_protoclusters_input {this};
+      PodioInput<edm4eic::Cluster> m_clusters_input {this};
       PodioInput<edm4eic::TrackSegment> m_track_projections_input {this};
+      PodioInput<edm4eic::MCRecoClusterParticleAssociation> m_cluster_association_input {this};
+#if EDM4EIC_VERSION_MAJOR >= 7
+      PodioInput<edm4eic::MCRecoCalorimeterHitAssociation> m_hit_association_input {this};
+#else
+      PodioInput<edm4hep::SimCalorimeterHit> m_sim_hit_input {this};
+#endif
 
       // output collections
-      PodioOutput<edm4eic::ProtoCluster> m_protoclusters_output {this};
+      PodioOutput<edm4eic::Cluster> m_clusters_output {this};
+#if EDM4EIC_VERSION_MAJOR >= 8
+      PodioOutput<edm4eic::TrackClusterMatch> m_track_cluster_match_output {this};
+#endif
+      PodioOutput<edm4eic::MCRecoClusterParticleAssociation> m_cluster_association_output {this};
 
       // parameter bindings
       ParameterRef<std::string> m_idCalo {this, "idCalo", config().idCalo};
@@ -60,8 +72,16 @@ namespace eicrecon {
 
       void Process(int64_t run_number, uint64_t event_number) {
         m_algo->process(
-          {m_protoclusters_input(), m_track_projections_input()},
-          {m_protoclusters_output().get()}
+#if EDM4EIC_VERSION_MAJOR >= 7
+          {m_clusters_input(), m_track_projections_input(), m_cluster_association_input(), m_hit_association_input()},
+#else
+          {m_clusters_input(), m_track_projections_input(), m_cluster_association_input(), m_sim_hit_input()},
+#endif
+#if EDM4EIC_VERSION_MAJOR >= 8
+          {m_clusters_output().get(), m_track_cluster_match_output().get(), m_cluster_association_output().get()}
+#else
+          {m_clusters_output().get(), m_cluster_association_output().get()}
+#endif
         );
       }