Repository: DUNE/dune-tms
Pull request #202: Add ybar
Author: login: kyjung123
Created: 2025-02-04T15:58:16Z | Merged: 2025-04-04T13:20:39Z

Basically, just add all the variables needed for the Y bar in Reco.cpp such as HoughLinesY, GetCandidatesY, and so on.
The idea is that instead of calculating the y position and x position from close U,V bars, just use the x position from the y bar and y position from the x bar directly.
I named the function TrackMatching3D_XY() and it triggered only when UHitGroup is empty.



Also, noticed that there is a negative bar number in the X bar so I changed it by usingTMS_Const::TMS_Start_Exact[1].

Note> I didn't check the Kalman filter on XY. I believe it doesn't work. 
I remembered the conversation with Liam, in NoiseMatrix adding this code for the Y bar,
`  } else  if (LayerOrientation == TMS_Bar::kYBar) {
      NoiseMatrix(0,0) = A*A;
      NoiseMatrix(1,1) = B*B;
      NoiseMatrix(1,0) = NoiseMatrix(0,1) = 0;                                                                                                                                                              
      return;
    }
`



Diff:
diff --git a/src/TMS_Bar.cpp b/src/TMS_Bar.cpp
index 12f3931c..0a2f1271 100644
--- a/src/TMS_Bar.cpp
+++ b/src/TMS_Bar.cpp
@@ -69,7 +69,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
     }
 
     // This is the furthest down hit we have: scintillator bar
-    else if (NodeName.find(TMS_Const::TMS_ScintLayerName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerOrthoName) != std::string::npos) {
+    else if (NodeName.find(TMS_Const::TMS_ScintLayerName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerOrthoName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerParallelName) != std::string::npos) {
       BarNumber = geom->GetCurrentNode()->GetNumber();
 
       // Get the width
@@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
     if (GlobalBarNumber % 2 == 1) {
       BarNumber += 1;
     }
@@ -225,12 +225,14 @@ bool TMS_Bar::CheckBar() {
 
   // Sanity check the global bar number
   //if (BarNumber >= TMS_Const::nModulesPerSubModule || BarNumber < 0) {
-  if (BarNumber >= (TMS_Const::TMS_End_Exact[0]-TMS_Const::TMS_Start_Exact[0])/GetXw() || BarNumber < 0) {
-    std::cerr << "Bar number does not agree with expectation of between 0 to " << TMS_Const::nModulesPerSubModule << std::endl;
-    std::cerr << "Has the geometry been updated without updating the geometry constants in TMS_Constants.h?" << std::endl;
-    std::cout << "Bar number: " << BarNumber << std::endl;
-    throw;
-    return false;
+  if (BarOrient!=kXBar) {
+      if (BarNumber >= (TMS_Const::TMS_End_Exact[0]-TMS_Const::TMS_Start_Exact[0])/GetXw() || BarNumber < 0) {
+          std::cerr << "Bar number does not agree with expectation of between 0 to " << TMS_Const::nModulesPerSubModule << std::endl;
+          std::cerr << "Has the geometry been updated without updating the geometry constants in TMS_Constants.h?" << std::endl;
+          std::cout << "Bar number: " << BarNumber << std::endl;
+          throw;
+          return false;
+      }
   }
 
   if (GlobalBarNumber >= TMS_Const::nModules || GlobalBarNumber < 0) {
diff --git a/src/TMS_Constants.h b/src/TMS_Constants.h
index 4c0d4397..d4000074 100644
--- a/src/TMS_Constants.h
+++ b/src/TMS_Constants.h
@@ -111,6 +111,7 @@ namespace TMS_Const {
   // To find scintillator "box"
   const std::string TMS_ScintLayerName = "scinBoxlvTMS";
   const std::string TMS_ScintLayerOrthoName = "scinBoxlv_orthoTMS";
+  const std::string TMS_ScintLayerParallelName = "scinBoxlv_parallelTMS";
   // The top layer name
   const std::string TMS_TopLayerName = "volWorld";
   // The detector enclosure
diff --git a/src/TMS_Kalman.h b/src/TMS_Kalman.h
index b0177691..a660d2e7 100644
--- a/src/TMS_Kalman.h
+++ b/src/TMS_Kalman.h
@@ -174,6 +174,11 @@ class TMS_KalmanNode {
       NoiseMatrix(1,1) = A*A;
       NoiseMatrix(1,0) = NoiseMatrix(0,1) = 0.0;
       return;
+    } else if (LayerOrientation == TMS_Bar::kYBar) { // this should just work right?
+      NoiseMatrix(0,0) = A*A;
+      NoiseMatrix(1,1) = B*B;
+      NoiseMatrix(1,0) = NoiseMatrix(0,1) = 0.0;
+      return;
     } else {
       throw; // xd haha TODO tho
     }
diff --git a/src/TMS_Reco.cpp b/src/TMS_Reco.cpp
index 2766a3a1..c94b0589 100644
--- a/src/TMS_Reco.cpp
+++ b/src/TMS_Reco.cpp
@@ -48,6 +48,10 @@ TMS_TrackFinder::TMS_TrackFinder() :
   HoughLineX->SetLineStyle(kDashed);
   HoughLineX->SetLineColor(kMagenta-7);
 
+  HoughLineY = new TF1("LinearHough4", "[0]+[1]*x", TMS_Const::TMS_Thin_Start, TMS_Const::TMS_Thick_Start);
+  HoughLineY->SetLineStyle(kDashed);
+  HoughLineY->SetLineColor(kMagenta-6);
+
   DBSCAN.SetEpsilon(TMS_Manager::GetInstance().Get_Reco_DBSCAN_Epsilon());
   DBSCAN.SetMinPoints(TMS_Manager::GetInstance().Get_Reco_DBSCAN_MinPoints());
 
@@ -101,42 +105,57 @@ void TMS_TrackFinder::ClearClass() {
     delete i.second;
   }
 
+  for (auto &i: HoughLinesY) {
+    delete i.second;
+  }
+
   // Reset the candidate vector
   CandidatesU.clear();
   CandidatesV.clear();
   CandidatesX.clear();
+  CandidatesY.clear();
   RawHits.clear();
   TotalCandidatesU.clear();
   TotalCandidatesV.clear();
   TotalCandidatesX.clear();
+  TotalCandidatesY.clear();
   HoughLinesU.clear();
   HoughLinesV.clear();
   HoughLinesX.clear();
+  HoughLinesY.clear();
   HoughLinesU_Upstream.clear();
   HoughLinesV_Upstream.clear();
   HoughLinesX_Upstream.clear();
+  HoughLinesY_Upstream.clear();
   HoughLinesU_Downstream.clear();
   HoughLinesV_Downstream.clear();
   HoughLinesX_Downstream.clear();
+  HoughLinesY_Downstream.clear();
   HoughCandidatesU.clear();
   HoughCandidatesV.clear();
   HoughCandidatesX.clear();
+  HoughCandidatesY.clear();
   SortedHoughCandidatesU.clear();
   SortedHoughCandidatesV.clear();
   SortedHoughCandidatesX.clear();
+  SortedHoughCandidatesY.clear();
   ClusterCandidatesU.clear();
   ClusterCandidatesV.clear();
   ClusterCandidatesX.clear();
+  ClusterCandidatesY.clear();
   TrackLengthU.clear();
   TrackLengthV.clear();
   TrackLengthX.clear();
+  TrackLengthY.clear();
   TrackEnergyU.clear();
   TrackEnergyV.clear();
   TrackEnergyX.clear();
+  TrackEnergyY.clear();
 
   UHitGroup.clear();
   VHitGroup.clear();
   XHitGroup.clear();
+  YHitGroup.clear();
 
   HoughTracks3D.clear();
 }
@@ -207,13 +226,17 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
     else if (hit.GetBar().GetBarType() == TMS_Bar::kXBar) {
       XHitGroup.push_back(hit);
 //      std::cout << "X hit: " << hit.GetNotZ() << " | " << hit.GetZ() << std::endl;
+    }
+    else if (hit.GetBar().GetBarType() == TMS_Bar::kYBar) {
+      YHitGroup.push_back(hit);
+//      std::cout << "Y hit: " << hit.GetNotZ() << " | " << hit.GetZ() << std::endl;
     }
     else {
       hit.GetBar().Print();
     }
   }
  
-  if ( (UHitGroup.size() + VHitGroup.size() + XHitGroup.size()) != CleanedHits.size() ) {
+  if ( (UHitGroup.size() + VHitGroup.size() + XHitGroup.size() + YHitGroup.size()) != CleanedHits.size() ) {
     std::cout << "Not all hits in separated hit groups!" << std::endl;
     return;
   }
@@ -231,12 +254,14 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
       std::vector<std::vector<TMS_Hit> > DBScanCandidatesU = FindClusters(UHitGroup);
       std::vector<std::vector<TMS_Hit> > DBScanCandidatesV = FindClusters(VHitGroup);
       std::vector<std::vector<TMS_Hit> > DBScanCandidatesX = FindClusters(XHitGroup);
+      std::vector<std::vector<TMS_Hit> > DBScanCandidatesY = FindClusters(YHitGroup);
 
       // Prepare for only running track finding (Hough transform and A* algorithm) on track-like structures
       // for this the pre-clusters found by the DBScan need to be filtered out
       std::vector<TMS_Hit> TrackCandidatesU = UHitGroup;
       std::vector<TMS_Hit> TrackCandidatesV = VHitGroup;
       std::vector<TMS_Hit> TrackCandidatesX = XHitGroup;
+      std::vector<TMS_Hit> TrackCandidatesY = YHitGroup;
       
       for (auto it : DBScanCandidatesU) {
         MaskHits(TrackCandidatesU, it);
@@ -251,11 +276,15 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
       for (auto it : DBScanCandidatesX) {
         MaskHits(TrackCandidatesX, it);
       }
+      for (auto it : DBScanCandidatesY) {
+        MaskHits(TrackCandidatesY, it);
+      }
 
       // Now run the Hough transformation on the track-like structures
       HoughCandidatesU = HoughTransform(TrackCandidatesU, 'U');
       HoughCandidatesV = HoughTransform(TrackCandidatesV, 'V');
       HoughCandidatesX = HoughTransform(TrackCandidatesX, 'X');
+      HoughCandidatesY = HoughTransform(TrackCandidatesY, 'Y');
 #ifdef DEBUG
       std::cout << "Back extension" << std::endl;
       std::cout << "Found " << HoughCandidatesU.size() << " U simple tracks and " << HoughCandidatesV.size() << " V simple tracks" << std::endl;
@@ -319,6 +348,25 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
           }
         }
       }
+      // Same as for U above
+      for (auto it = HoughCandidatesY.begin(); it != HoughCandidatesY.end(); ++it) {
+        for (auto jt : DBScanCandidatesY) { 
+          std::vector<TMS_Hit> HoughY = (*it);
+          std::vector<TMS_Hit> preY = jt;
+
+          SpatialPrio(HoughY);
+
+          if (TMS_Manager::GetInstance().Get_Reco_EXTRAPOLATION_Extrapolation()) HoughY = Extrapolation(HoughY, preY);
+          for (auto HoughIt = HoughY.begin(); HoughIt != HoughY.end(); ) {
+            bool match = false;
+            for (auto TrackHits = (*it).begin(); TrackHits != (*it).end(); ++TrackHits) {
+              if ((*HoughIt) == (*TrackHits)) match = true;
+            }
+            if (!match) (*it).push_back(std::move(*HoughIt));
+            else HoughIt++;
+          }
+        }
+      }
 
       // Restore overwritten DBSCAN parameters to their previous values for final clustering
       DBSCAN.SetEpsilon(TMS_Manager::GetInstance().Get_Reco_DBSCAN_Epsilon());
@@ -350,16 +398,19 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
       HoughCandidatesU = HoughTransform(UHitGroup, 'U');
       HoughCandidatesV = HoughTransform(VHitGroup, 'V');
       HoughCandidatesX = HoughTransform(XHitGroup, 'X');
+      HoughCandidatesY = HoughTransform(YHitGroup, 'Y');
     }
   } else if (kTrackMethod == TrackMethod::kAStar) {
     BestFirstSearch(UHitGroup, 'U');
     BestFirstSearch(VHitGroup, 'V');
     BestFirstSearch(XHitGroup, 'X');
+    BestFirstSearch(YHitGroup, 'Y');
   }
 
   std::vector<TMS_Hit> MaskedU = UHitGroup;
   std::vector<TMS_Hit> MaskedV = VHitGroup;
   std::vector<TMS_Hit> MaskedX = XHitGroup;
+  std::vector<TMS_Hit> MaskedY = YHitGroup;
   // Loop over the Hough candidates
   for (auto Lines: HoughCandidatesU) {
 #ifdef DEBUG
@@ -390,10 +441,22 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
     std::cout << "Masked (x) size aft: " << MaskedX.size() << std::endl;
 #endif
   }
+
+for (auto Lines: HoughCandidatesY) {
+#ifdef DEBUG
+  std::cout << "Masked (x) size bef: " << MaskedY.size() << std::endl;
+#endif
+  MaskHits(MaskedY, Lines);
+#ifdef DEBUG
+  std::cout << "Masked (x) size aft: " << MaskedY.size() << std::endl;
+#endif
+}
+
 #ifdef DEBUG
   std::cout << "Masked (u) hits: " << MaskedU.size() << std::endl;
   std::cout << "Masked (v) hits: " << MaskedV.size() << std::endl;
   std::cout << "Masked (x) hits: " << MaskedX.size() << std::endl;
+  std::cout << "Masked (x) hits: " << MaskedY.size() << std::endl;
 #endif
   
   // Now we've got our tracks, refit the upstream and downstream separately with the Hough transform
@@ -510,6 +573,42 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
    linenoX++;
   }
 
+  int linenoY = 0;
+  for (auto Lines: HoughCandidatesY) {
+    std::pair<bool, TF1*> houghline = HoughLinesY[linenoY];
+    double slope, intercept = 0;
+    GetHoughLine(Lines, slope, intercept);
+    if (fabs(houghline.second->GetParameter(0) - intercept) > 1E2 ||
+	      fabs(houghline.second->GetParameter(1) - slope) > 1E-2) {
+      HoughLinesY[linenoY].second->SetParameter(0, intercept);
+      HoughLinesY[linenoY].second->SetParameter(1, slope);
+    }
+    
+    // The number of hits in this track, trake 20% and call upstream and downstream segments
+    int nrescanhits = 0.3*Lines.size()+1;
+    // If there are only a few hits, use all of them
+    if (nrescanhits < 5) nrescanhits = Lines.size();
+    std::vector<TMS_Hit> upstream;
+    std::vector<TMS_Hit> downstream;
+    for (int i = 0; i < nrescanhits; ++i) {
+      upstream.push_back(Lines[Lines.size()-1-i]);
+      downstream.push_back(Lines[i]);
+   }
+
+   double upstreamslope, upstreamintercept = 0;
+   double downstreamslope, downstreamintercept = 0;
+   GetHoughLine(upstream, upstreamslope, upstreamintercept);
+   GetHoughLine(downstream, downstreamslope, downstreamintercept);
+
+   std::pair<double, double> upstreamline = std::pair<double,double>(upstreamintercept, upstreamslope);
+   std::pair<double, double> downstreamline = std::pair<double,double>(downstreamintercept, downstreamslope);
+
+   HoughLinesY_Upstream.push_back(upstreamline);
+   HoughLinesY_Downstream.push_back(downstreamline);
+
+   linenoY++;
+  }
+
   // Run a pseudo track finding for X hits, if they exist but not enough for a track to be found
   if (!XHitGroup.empty() && HoughCandidatesX.empty()) {
     FindPseudoXTrack();
@@ -520,10 +619,16 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
     ClusterCandidatesU = FindClusters(MaskedU);
     ClusterCandidatesV = FindClusters(MaskedV);
     ClusterCandidatesX = FindClusters(MaskedX);
+    ClusterCandidatesY = FindClusters(MaskedY);
   }
 
   // Call TrackMatching3D
-  HoughTracks3D = TrackMatching3D();
+  if (!UHitGroup.empty()){
+      HoughTracks3D = TrackMatching3D();
+  }
+  else{
+      HoughTracks3D = TrackMatching3D_XY();
+  }
 
   // Let's try to find a vertex now, just looking at most upstream point, or if there are multiple tracks let's see where they intersect
   //if (nLines > 0) {
@@ -555,6 +660,12 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
     TrackEnergyX.push_back(TrackEnergy);
     TrackLengthX.push_back(TrackLength);
   }
+  for (auto it = HoughCandidatesY.begin(); it != HoughCandidatesY.end(); ++it) {
+    double TrackEnergy = CalculateTrackEnergy((*it));
+    double TrackLength = CalculateTrackLength((*it));
+    TrackEnergyY.push_back(TrackEnergy);
+    TrackLengthY.push_back(TrackLength);
+  }
 
   //EvaluateTrackFinding(event);
 
@@ -690,7 +801,7 @@ void TMS_TrackFinder::FindPseudoXTrack() {
     std::cout << "X hits added to Pseudo X track" << std::endl;
 #endif
     // Push pseudo X track into HoughCandidatesX
-    HoughCandidatesX.push_back(CheckedXHits);
+    if (CheckedXHits.size() > 0) HoughCandidatesX.push_back(CheckedXHits);
   }
   return;
 }
@@ -780,9 +891,12 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
     std::cout << "No X tracks? " << HoughCandidatesX.empty() << std::endl;
 #endif
     //  while (Xrun) {
-    if (HoughCandidatesX.empty()) Xrun = false;
-    std::vector<TMS_Hit> XTracks;
-    if (Xrun) XTracks = *helper;
+    if (SortedHoughCandidatesX.empty()) Xrun = false;
+    std::vector<TMS_Hit> XTracks = *Uhelper;
+    if (Xrun) {
+      XTracks = *helper;
+      if (XTracks.empty()) Xrun = false;
+    }
         
         // Run spatial prio just because one last time
     SpatialPrio(UTracks);
@@ -1563,7 +1677,7 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
       if (HoughCandidatesU.size() == 1) break;
       if (HoughCandidatesV.size() == 1) break;
 
-      if (!XTracks.empty()) {
+      if (Xrun && !XTracks.empty()) {
         // If match was made, remove the candidate tracks from candidate lists
         SortedHoughCandidatesV.erase(Vhelper);
         SortedHoughCandidatesX.erase(helper);
@@ -1579,7 +1693,7 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
         ++Uhelper;
       } 
     } else {
-      if (!XTracks.empty()) {
+      if (Xrun && !XTracks.empty()) {
         if (helper == SortedHoughCandidatesX.end()-1) {
           helper = SortedHoughCandidatesX.begin();
           if (Vhelper == SortedHoughCandidatesV.end()-1) {
@@ -1599,6 +1713,400 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
   return returned;
 }
 
+std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D_XY() {
+#ifdef DEBUG
+  std::cout << "3D matching" << std::endl;
+  std::cout << "size Candidates: U: " << HoughCandidatesU.size() << " | V: " << HoughCandidatesV.size() << std::endl;//" | X: " << HoughCandidatesX.size() << std::endl;
+#endif
+
+  // Sorting the candidate tracks descending by their hit numbers
+  if (HoughCandidatesY.size() > 1) {
+    std::sort(HoughCandidatesY.begin(), HoughCandidatesY.end(), SortByHitNumber);
+    SortedHoughCandidatesY = HoughCandidatesY;
+  } else SortedHoughCandidatesY = HoughCandidatesY;
+  if (HoughCandidatesX.size() > 1) {
+    std::sort(HoughCandidatesX.begin(), HoughCandidatesX.end(), SortByHitNumber);
+    SortedHoughCandidatesX = HoughCandidatesX;
+  } else SortedHoughCandidatesX = HoughCandidatesX;
+
+  std::vector<TMS_Track> returned;
+
+  bool TimeSlicing = TMS_Manager::GetInstance().Get_Reco_TIME_RunTimeSlicer();
+
+  // 3D matching of tracks
+  std::vector<std::vector<TMS_Hit> >::iterator Yhelper = SortedHoughCandidatesY.begin();
+  std::vector<std::vector<TMS_Hit> >::iterator Xhelper = SortedHoughCandidatesX.begin();
+
+  while (Xhelper != SortedHoughCandidatesX.end()) {
+    if (SortedHoughCandidatesY.empty()) {
+      std::cout << "Not enough Y tracks" << std::endl;
+      break;
+    }
+    std::vector<TMS_Hit> YTracks = *Yhelper;
+    std::vector<TMS_Hit> XTracks = *Xhelper;
+        
+    SpatialPrio(XTracks);
+    SpatialPrio(YTracks);
+#ifdef DEBUG
+        std::cout << "XTrack back: " << XTracks.front().GetPlaneNumber() << " | " << XTracks.front().GetBarNumber() << " | " << XTracks.front().GetT() << " front: " << XTracks.back().GetPlaneNumber() << " | " << XTracks.back().GetBarNumber() << " | " << XTracks.back().GetT() << std::endl;
+        std::cout << "YTrack back: " << YTracks.front().GetPlaneNumber() << " | " << YTracks.front().GetBarNumber() << " | " << YTracks.front().GetT() << " front: " << YTracks.back().GetPlaneNumber() << " | " << YTracks.back().GetBarNumber() << " | " << YTracks.back().GetT() << std::endl;
+#endif
+ 
+        // Conditions for close enough tracks: within +/-3 plane numbers, +/-12 bar numbers and in same time slice within 30ns (Asa note: changed to 15 ns for now and just one of time and plane number condition needs to be met)
+        bool back_match = false;
+        bool front_match = false;
+        int strike = 0;
+        // Check for the front and back whether both conditions (plane limit and time limit) are met or not
+        if (TimeSlicing) {
+          // front of simple tracks: set strike to 1
+          if (std::abs(XTracks.front().GetPlaneNumber() - YTracks.front().GetPlaneNumber()) > TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_PlaneLimit()
+              || std::abs(XTracks.front().GetT() - YTracks.front().GetT()) > TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_TimeLimit()) strike = 1;
+          // end of simple tracks: add 2 to strike
+          if (std::abs(XTracks.back().GetPlaneNumber() - YTracks.back().GetPlaneNumber()) > TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_PlaneLimit()
+              || std::abs(XTracks.back().GetT() - YTracks.back().GetT()) > TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_TimeLimit()) strike += 2;
+        }  
+        if (TimeSlicing) {
+            //unlike UV, it is hard to compare bar number directly in XY, ignore it.
+//          bool bar_front = (std::abs(XTracks.front().GetBarNumber() - YTracks.front().GetBarNumber()) <= TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_BarLimit());
+//          bool bar_back = (std::abs(XTracks.back().GetBarNumber() - YTracks.back().GetBarNumber()) <= TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_BarLimit());
+          bool slice_front = (XTracks.front().GetSlice() == YTracks.front().GetSlice());
+          bool slice_back = (XTracks.back().GetSlice() == YTracks.back().GetSlice());
+          //ignore time matching for XY for now.
+//          bool time_front = (std::abs(XTracks.front().GetT() - YTracks.front().GetT()) <= TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_TimeLimit());
+//          bool time_back = (std::abs(XTracks.back().GetT() - YTracks.back().GetT()) <= TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_TimeLimit());
+          bool time_front = true;
+          bool time_back = true;
+          bool plane_front = (std::abs(XTracks.front().GetPlaneNumber() - YTracks.front().GetPlaneNumber()) <= TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_PlaneLimit());
+          bool plane_back = (std::abs(XTracks.back().GetPlaneNumber() - YTracks.back().GetPlaneNumber()) <= TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_PlaneLimit());
+          if (strike == 0) {
+            // front and end match
+            back_match =  (slice_back && time_back && plane_back);
+            front_match = (slice_front && time_front && plane_front);
+          } else if (strike == 1) {
+            // front needs exemption, end matches
+            back_match =  (slice_back && time_back && plane_back);
+            front_match = (slice_front && (time_front || plane_front));
+          } else if (strike == 2) {
+            // front matches, end needs exemption
+            back_match =  (slice_back && (time_back || plane_back));
+            front_match = (slice_front && time_front && plane_front);
+          }
+        }
+        else {
+          back_match = (std::abs(XTracks.front().GetPlaneNumber() - YTracks.front().GetPlaneNumber()) < TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_PlaneLimit());
+          front_match = (std::abs(XTracks.back().GetPlaneNumber() - YTracks.back().GetPlaneNumber()) < TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_PlaneLimit());
+        } 
+
+        if (back_match&&front_match) { 
+            TMS_Track aTrack;
+
+            // Make sure that the hits are in the correct order
+            if (XTracks.back().GetZ() > XTracks.front().GetZ()) std::reverse(XTracks.begin(), XTracks.end());
+            if (YTracks.back().GetZ() > YTracks.front().GetZ()) std::reverse(YTracks.begin(), YTracks.end());
+#ifdef DEBUG          
+            std::cout << "XTrack FRONT: " << XTracks.back().GetPlaneNumber() << " BACK: " << XTracks.front().GetPlaneNumber() << std::endl;
+            std::cout << "YTrack FRONT: " << YTracks.back().GetPlaneNumber() << " BACK: " << YTracks.front().GetPlaneNumber() << std::endl;
+#endif          
+            // If same plane number for start but different for end (U/V)
+            if (XTracks.front().GetPlaneNumber() != YTracks.front().GetPlaneNumber()) {
+              // If XTrack ends after YTrack
+              if (XTracks.front().GetPlaneNumber() > YTracks.front().GetPlaneNumber()) {
+                bool stereo_view = true;
+                if (stereo_view) {
+                  XTracks.front().SetRecoX(YTracks.front().GetNotZ());
+                  XTracks.front().SetRecoY(XTracks.front().GetNotZ());
+                  aTrack.End[0] = YTracks.front().GetNotZ();
+                  aTrack.End[1] = XTracks.front().GetNotZ();
+                  aTrack.End[2] = XTracks.front().GetZ();
+                  (aTrack.Hits).push_back(XTracks.front());
+                }
+
+              } // If UTrack ends before VTrack
+                else if (XTracks.front().GetPlaneNumber() < YTracks.front().GetPlaneNumber()) {
+                bool stereo_view = true;
+                if (stereo_view) {
+                  YTracks.front().SetRecoX(YTracks.front().GetNotZ());
+                  YTracks.front().SetRecoY(XTracks.front().GetNotZ());
+                  aTrack.End[0] = YTracks.front().GetNotZ();
+                  aTrack.End[1] = XTracks.front().GetNotZ();
+                  aTrack.End[2] = YTracks.front().GetZ();
+                  (aTrack.Hits).push_back(YTracks.front());
+                } 
+              }
+            } 
+            // If different plane number for start but same for end (U/V)
+            if (XTracks.back().GetPlaneNumber() != YTracks.back().GetPlaneNumber()) {
+              // If XTrack starts after YTrack  
+              if (XTracks.back().GetPlaneNumber() > YTracks.back().GetPlaneNumber()) {
+                bool stereo_view = true;
+                if (stereo_view) {
+                  aTrack.Start[0] = YTracks.back().GetNotZ();
+                  aTrack.Start[1] = XTracks.back().GetNotZ();
+                  aTrack.Start[2] = YTracks.back().GetZ();
+#ifdef DEBUG
+                  std::cout << "YTrack starts before XTrack, no XTrack" << std::endl;
+#endif                
+                  YTracks.back().SetRecoX(YTracks.back().GetNotZ());
+                  YTracks.back().SetRecoY(XTracks.back().GetNotZ());
+                  (aTrack.Hits).push_back(YTracks.back());
+                } 
+              } 
+                else if (XTracks.back().GetPlaneNumber() < YTracks.back().GetPlaneNumber()) {
+                bool stereo_view = true;
+                if (stereo_view) {
+                  aTrack.Start[0] = YTracks.back().GetNotZ();
+                  aTrack.Start[1] = XTracks.back().GetNotZ();
+                  aTrack.Start[2] = XTracks.back().GetZ();
+#ifdef DEBUG                
+                  std::cout << "XTrack starts before YTrack, no XTrack" << std::endl;
+#endif                
+                  XTracks.back().SetRecoX(YTracks.back().GetNotZ());
+                  XTracks.back().SetRecoY(XTracks.back().GetNotZ());
+                  (aTrack.Hits).push_back(XTracks.back());
+                }
+              } 
+            }
+            // If same start and end, assign start and end hit in track
+            if (XTracks.front().GetPlaneNumber() == YTracks.front().GetPlaneNumber()) {
+                bool stereo_view = true;
+                if (stereo_view) {
+                    XTracks.front().SetRecoX(YTracks.front().GetNotZ());
+                    XTracks.front().SetRecoY(XTracks.front().GetNotZ());
+                    aTrack.End[0] = YTracks.front().GetNotZ();
+                    aTrack.End[1] = XTracks.front().GetNotZ();
+                    aTrack.End[2] = YTracks.front().GetZ();
+                    (aTrack.Hits).push_back(XTracks.front());
+                }
+            }
+            if (XTracks.back().GetPlaneNumber() == YTracks.back().GetPlaneNumber()) {
+                bool stereo_view = true;
+                if (stereo_view) {
+                    XTracks.back().SetRecoX(YTracks.back().GetNotZ());
+                    XTracks.back().SetRecoY(XTracks.back().GetNotZ());
+                    aTrack.Start[0] = YTracks.back().GetNotZ();
+                    aTrack.Start[1] = XTracks.back().GetNotZ();
+                    aTrack.Start[2] = XTracks.back().GetZ();
+                    (aTrack.Hits).push_back(XTracks.back());
+                } 
+            }
+
+            // Add hits to track
+            int itY = YTracks.size() - 1;
+            int itX = XTracks.size() - 1;
+
+            bool sane = (itY > 0 || itX > 0);
+
+            while (sane) {  // Track seems to be backwards, so run adding of hits backwards
+                // Sanity check for hits being in the detector volume (x and z)
+                bool hit_outside = false;
+                if (XTracks[itX].GetNotZ() > 500.0 || XTracks[itX].GetNotZ() == 0. || XTracks[itX].GetNotZ() < -4000.0
+                        || XTracks[itX].GetZ() < 11000 || XTracks[itX].GetZ() > 20000) {
+                    --itX;
+                    hit_outside = true;
+                }
+                if (std::abs(YTracks[itY].GetNotZ()) > 4000.0 or YTracks[itY].GetNotZ() == 0.
+                        || YTracks[itY].GetZ() < 11000 || YTracks[itY].GetZ() > 20000) {
+                    --itY;
+                    hit_outside = true;
+                }
+                if (hit_outside) continue;
+
+                // Stereo check
+                bool stereo_view = true;
+                // Check if a neighbouring hit is from a X layer
+                if ((XTracks[itX]).GetPlaneNumber() == (YTracks[itY]).GetPlaneNumber()) {
+                    if (stereo_view) {
+                        XTracks[itX].SetRecoX(YTracks[itY].GetNotZ());
+                        XTracks[itX].SetRecoY(XTracks[itX].GetNotZ());
+                        YTracks[itY].SetRecoX(YTracks[itY].GetNotZ());
+                        YTracks[itY].SetRecoY(XTracks[itX].GetNotZ());
+#ifdef DEBUG
+                        std::cout << "same" << std::endl;
+                        std::cout << "Hit: " << YTracks[itY].GetRecoX() << " | " << YTracks[itY].GetRecoY() << " | " << YTracks[itY].GetZ() << " than: " << XTracks[itX].GetRecoX() << " | " << XTracks[itX].GetRecoY() << " | " << XTracks[itX].GetZ() << std::endl;
+#endif
+                        // Handling cases of two hits in same plane to be matched
+                        // By adding a loop into these statements one could also take care of more than 2 hits in the same plane/with the same z coordinate
+
+                        
+                        if (itX > 0 && XTracks[itX].GetZ() == XTracks[itX - 1].GetZ()) {
+                            XTracks[itX-1].SetRecoX(YTracks[itY].GetNotZ());
+                            XTracks[itX-1].SetRecoY(XTracks[itX-1].GetNotZ());
+                            (aTrack.Hits).push_back(XTracks[itX]);  // This adds the original hit
+                            if (itX > 0) --itX; // and this allows for the other hit then to be added with the next push_back statement
+                        }
+                        if (itY > 0 && YTracks[itY].GetZ() == YTracks[itY - 1].GetZ()) {
+                            YTracks[itY-1].SetRecoX(YTracks[itY-1].GetNotZ());
+                            YTracks[itY-1].SetRecoY(XTracks[itX].GetNotZ());
+                            (aTrack.Hits).push_back(YTracks[itY]);
+                            if (itY > 0) --itY;
+                        }
+                        (aTrack.Hits).push_back(XTracks[itX]);
+                        (aTrack.Hits).push_back(YTracks[itY]);
+                    } 
+                    if (itX > 0) --itX;
+                    if (itY > 0) --itY;
+                }
+                //just change the following index from original code
+                else if ((XTracks[itX]).GetPlaneNumber() > (YTracks[itY]).GetPlaneNumber()) {
+                        if (itX > 0 && itY > 0) {
+                            YTracks[itY].SetRecoX(YTracks[itY].GetNotZ());
+                            YTracks[itY].SetRecoY(XTracks[itX-1].GetNotZ());
+                            if (YTracks[itY].GetZ() == YTracks[itY - 1].GetZ()) {
+                                YTracks[itY-1].SetRecoX(YTracks[itY-1].GetNotZ());
+                                YTracks[itY-1].SetRecoY(XTracks[itX-1].GetNotZ());
+                                (aTrack.Hits).push_back(YTracks[itY]);  // This adds the original hit
+                                if (itY > 0) --itY; // and this allows for the other hit then to be added with the next push_back statement
+                            }
+                            (aTrack.Hits).push_back(YTracks[itY]);
+                            if (itY > 0) --itY;
+                        } else if (itX == 0 && itY > 0) {
+                            YTracks[itY].SetRecoX(YTracks[itY].GetNotZ());
+                            YTracks[itY].SetRecoY(XTracks[itX].GetNotZ());
+                            if (YTracks[itY].GetZ() == YTracks[itY - 1].GetZ()) {
+                                YTracks[itY-1].SetRecoX(YTracks[itY-1].GetNotZ());
+                                YTracks[itY-1].SetRecoY(XTracks[itX].GetNotZ());
+                                (aTrack.Hits).push_back(YTracks[itY]);  // This adds the original hit
+                                if (itY > 0) --itY; // and this allows for the other hit then to be added with the next push_back statement
+                            }
+                            (aTrack.Hits).push_back(YTracks[itY]);
+                            if (itY > 0) --itY;
+                        } else if (itX > 0 && itY == 0) {
+                            XTracks[itX].SetRecoX(YTracks[itY].GetNotZ());
+                            XTracks[itX].SetRecoY(XTracks[itX].GetNotZ());
+                            if (XTracks[itX].GetZ() == XTracks[itX - 1].GetZ()) {
+                                XTracks[itX-1].SetRecoX(YTracks[itY].GetNotZ());
+                                XTracks[itX-1].SetRecoY(XTracks[itX-1].GetNotZ());
+                                (aTrack.Hits).push_back(XTracks[itX]);  // This adds the original hit
+                                if (itX > 0) --itX; // and this allows for the other hit then to be added with the next push_back statement
+                            }
+                            (aTrack.Hits).push_back(XTracks[itX]);
+                            if (itX > 0) --itX;
+                        }
+                } else if ((XTracks[itX]).GetPlaneNumber() < (YTracks[itY]).GetPlaneNumber()) {
+                    if (stereo_view) {
+                        if (itY > 0 && itX > 0) {
+                            XTracks[itX].SetRecoX(YTracks[itY-1].GetNotZ());
+                            XTracks[itX].SetRecoY(XTracks[itX].GetNotZ());
+                            if (XTracks[itX].GetZ() == XTracks[itX - 1].GetZ()) {
+                                XTracks[itX-1].SetRecoX(YTracks[itY-1].GetNotZ());
+                                XTracks[itX-1].SetRecoY(XTracks[itX-1].GetNotZ());
+                                (aTrack.Hits).push_back(XTracks[itX]);  // This adds the original hit
+                                if (itX > 0) --itX; // and this allows for the other hit then to be added with the next push_back statement
+                            }
+                            (aTrack.Hits).push_back(XTracks[itX]);
+                            if (itX > 0) --itX;
+                        } else if (itY == 0 && itX > 0) {
+                            XTracks[itX].SetRecoX(YTracks[itY].GetNotZ());
+                            XTracks[itX].SetRecoY(XTracks[itX].GetNotZ());
+                            if (XTracks[itX].GetZ() == XTracks[itX - 1].GetZ()) {
+                                XTracks[itX-1].SetRecoX(YTracks[itY].GetNotZ());
+                                XTracks[itX-1].SetRecoY(XTracks[itX-1].GetNotZ());
+                                (aTrack.Hits).push_back(XTracks[itX]);  // This adds the original hit
+                                if (itX > 0) --itX; // and this allows for the other hit then to be added with the next push_back statement
+                            }
+                            (aTrack.Hits).push_back(XTracks[itX]);
+                            if (itX > 0) --itX;
+                        } else if (itY > 0 && itX == 0) {
+                            YTracks[itY].SetRecoX(YTracks[itY].GetNotZ());
+                            YTracks[itY].SetRecoY(XTracks[itX].GetNotZ());
+                            if (YTracks[itY].GetZ() == YTracks[itY - 1].GetZ()) {
+                                YTracks[itY-1].SetRecoX(YTracks[itY-1].GetNotZ());
+                                YTracks[itY-1].SetRecoY(XTracks[itX].GetNotZ());
+                                (aTrack.Hits).push_back(YTracks[itY]);  // This adds the original hit
+                                if (itY > 0) --itY; // and this allows for the other hit then to be added with the next push_back statement
+                            }
+                            (aTrack.Hits).push_back(YTracks[itY]);
+                            if (itY > 0) --itY;
+                        }
+                    }
+                }
+                sane = (itX > 0 || itY > 0);
+            }//sane
+
+            // Sort track
+            SpatialPrio(aTrack.Hits);
+
+
+            if (TMS_Manager::GetInstance().Get_Reco_TRACKSMOOTHING_UseTrackSmoothing()) aTrack.ApplyTrackSmoothing();
+
+            // Smoothing of start and end of track in case of too much 'flailing around' in the y direction
+            // end
+            //            bool SameSign = true;
+            //            if ((aTrack.End[1] > 0 && aTrack.Hits[aTrack.Hits.size() - 3].GetRecoY() < 0) || (aTrack.End[1] < 0 && aTrack.Hits[aTrack.Hits.size() - 3].GetRecoY() > 0)) SameSign = false;
+            //            if ((SameSign &&std::abs(aTrack.End[1] - aTrack.Hits[aTrack.Hits.size() - 3].GetRecoY()) >= 676.6) || (!SameSign && std::abs(aTrack.End[1]) + std::abs(aTrack.Hits[aTrack.Hits.size() - 3].GetRecoY()) >= 674.6)) {
+            //              aTrack.End[1] = (aTrack.End[1] + aTrack.Hits[aTrack.Hits.size() - 3].GetRecoY()) / 2;
+            //              if (aTrack.End[1] > 244.0) aTrack.End[1] = 244.0;
+            //              else if (aTrack.End[1] < -2949.0) aTrack.End[1] = -2949.0;
+            //              aTrack.Hits[aTrack.Hits.size() - 1].SetRecoY(aTrack.End[1]);
+            //            }
+            //            // start
+            //             // std::cout<<"3"<<std::endl;
+            //            SameSign = true;
+            //            if ((aTrack.Start[1] > 0 && aTrack.Hits[2].GetRecoY() < 0) || (aTrack.Start[1] < 0 && aTrack.Hits[2].GetRecoY() > 0)) SameSign = false;
+            //            if ((SameSign && std::abs(aTrack.Start[1] - aTrack.Hits[2].GetRecoY()) >= 676.6) || (!SameSign && std::abs(aTrack.Start[1]) + std::abs(aTrack.Hits[2].GetRecoY()) >= 674.6)) {
+            //              aTrack.Start[1] = (aTrack.Start[1] + aTrack.Hits[2].GetRecoY()) / 2;
+            //              if (aTrack.Start[1] > 244.0) aTrack.Start[1] = 244.0;
+            //              else if (aTrack.Start[1] < -2949.0) aTrack.Start[1] = -2949.0;
+            //              aTrack.Hits[0].SetRecoY(aTrack.Start[1]);
+            //            }
+#ifdef DEBUG
+            for (auto hits: aTrack.Hits) {
+                std::cout << "Match: " << hits.GetRecoX() << "," << hits.GetRecoY() << "," << hits.GetZ() << std::endl;
+            }
+#endif
+            // Charge ID
+            aTrack.Charge = ChargeID.ID_Track_Charge(aTrack.Hits);
+
+            // Track Length
+            aTrack.Length = CalculateTrackLength3D(aTrack);
+#ifdef DEBUG
+            std::cout << "Added TrackLength: " << aTrack.Length << std::endl;
+#endif          
+            // Track Energy
+            aTrack.EnergyDeposit = CalculateTrackEnergy3D(aTrack);
+#ifdef DEBUG
+            std::cout << "Added TrackEnergyDeposit: " << aTrack.EnergyDeposit << std::endl;
+#endif
+            // Track Direction
+            if (TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_DirectionDistance() >= aTrack.Hits.size()) {
+              double direction_x = aTrack.Start[0] - aTrack.End[0];
+              double direction_y = aTrack.Start[1] - aTrack.End[1];
+              double direction_z = aTrack.Start[2] - aTrack.End[2];
+              aTrack.SetStartDirection(direction_x, direction_y, direction_z);
+            } else {
+              double direction_x = aTrack.Start[0] - aTrack.Hits[TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_DirectionDistance()].GetRecoX();
+              double direction_y = aTrack.Start[1] - aTrack.Hits[TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_DirectionDistance()].GetRecoY();
+              double direction_z = aTrack.Start[2] - aTrack.Hits[TMS_Manager::GetInstance().Get_Reco_TRACKMATCH_DirectionDistance()].GetZ();
+              aTrack.SetStartDirection(direction_x, direction_y, direction_z);
+            }
+#ifdef DEBUG          
+            std::cout << "Start: " << aTrack.Start[0] << " | " << aTrack.Start[1] << " | " << aTrack.Start[2] << std::endl;
+            std::cout << "End: " << aTrack.End[0] << " | " << aTrack.End[1] << " | " << aTrack.End[2] << std::endl;
+            //std::cout << "Added Direction: " << aTrack.Direction[0] << " | " << aTrack.Direction[1] << " | " << aTrack.Direction[2] << std::endl;
+            std::cout << "Added StartDirection: " << aTrack.StartDirection[0] << " | " << aTrack.StartDirection[1] << " | " << aTrack.StartDirection[2] << std::endl;
+#endif          
+
+            returned.push_back(aTrack);
+
+            if (HoughCandidatesX.size() == 1) break;
+            if (HoughCandidatesY.size() == 1) break;
+
+            // If match was made, remove the candidate (simple) track from candidate list
+            SortedHoughCandidatesY.erase(Yhelper);
+            if (SortedHoughCandidatesY.size() > 1) Yhelper = SortedHoughCandidatesY.begin();
+            // Set iterator for X tracks to next track
+            ++Xhelper;
+        } else {
+            if (Yhelper == SortedHoughCandidatesY.end()-1) {
+                ++Xhelper;
+                Yhelper = SortedHoughCandidatesY.begin();
+            } else ++Yhelper;
+            if (SortedHoughCandidatesY.size() < 2) break;
+        }   
+  }
+  return returned;
+}
+
 void TMS_TrackFinder::CalculateRecoY(TMS_Hit &OneHit, TMS_Hit &UHit, TMS_Hit &VHit) {
 //  TGeoManager *geom = TMS_Geom::GetInstance().GetGeometry();
 //  Double_t localOne[3] = {OneHit.GetNotZ(), 0, OneHit.GetZ()};
@@ -1846,6 +2354,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
     TMS_xz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kVBar);
   } else if (hitgroup == 'X') {
     TMS_xz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kXBar);
+  } else if (hitgroup == 'Y') {
+    TMS_xz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kYBar);
   }
 
   // Do a spatial analysis of the hits in y and x around low z to ignore hits that are disconnected from other hits
@@ -1883,6 +2393,10 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
         delete HoughLinesX.back().second;
 
         HoughLinesX.pop_back();
+      } else if (hitgroup == 'Y') {
+        delete HoughLinesY.back().second;
+
+          HoughLinesY.pop_back();
       } else {
           std::cout << "Removing built Hough lines goes wrong for hitgroups: hitgroup = " << hitgroup << std::endl;
           break;
@@ -1897,6 +2411,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
       for (auto &i: TMS_xz_cand) CandidatesV.push_back(std::move(i));
     } else if (hitgroup == 'X') {
       for (auto &i: TMS_xz_cand) CandidatesX.push_back(std::move(i));
+    } else if (hitgroup == 'Y') {
+      for (auto &i: TMS_xz_cand) CandidatesY.push_back(std::move(i));
     }
 
     // Loop over vector and remove used hits
@@ -1914,6 +2430,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
       LineCandidates.push_back(std::move(CandidatesV));
     } else if (hitgroup == 'X') {
       LineCandidates.push_back(std::move(CandidatesX));
+    } else if (hitgroup == 'Y') {
+      LineCandidates.push_back(std::move(CandidatesY));
     }
       
     nRuns++;
@@ -1950,6 +2468,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
       double HoughVSlope_1 = 0.000;
       double HoughXInter_1 = 0.000;
       double HoughXSlope_1 = 0.000;
+      double HoughYInter_1 = 0.000;
+      double HoughYSlope_1 = 0.000;
 
       if (hitgroup == 'U') {
         HoughUInter_1 = HoughLinesU[lineit].second->GetParameter(0);
@@ -1960,6 +2480,9 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
       } else if (hitgroup == 'X') {
         HoughXInter_1 = HoughLinesX[lineit].second->GetParameter(0);
         HoughXSlope_1 = HoughLinesX[lineit].second->GetParameter(1);
+      } else if (hitgroup == 'Y') {
+        HoughYInter_1 = HoughLinesY[lineit].second->GetParameter(0);
+        HoughYSlope_1 = HoughLinesY[lineit].second->GetParameter(1);
       }
 
       // Now loop over the remaining hits
@@ -2002,6 +2525,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
         double HoughVSlope_2 = 0.000;
         double HoughXInter_2 = 0.000;
         double HoughXSlope_2 = 0.000;
+        double HoughYInter_2 = 0.000;
+        double HoughYSlope_2 = 0.000;
 
         if (hitgroup == 'U') {
           HoughUInter_2 = HoughLinesU[lineit_2].second->GetParameter(0);
@@ -2012,6 +2537,9 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
       	} else if (hitgroup == 'X') {
           HoughXInter_2 = HoughLinesX[lineit_2].second->GetParameter(0);
           HoughXSlope_2 = HoughLinesX[lineit_2].second->GetParameter(1);
+      	} else if (hitgroup == 'Y') {
+          HoughYInter_2 = HoughLinesY[lineit_2].second->GetParameter(0);
+          HoughYSlope_2 = HoughLinesY[lineit_2].second->GetParameter(1);
         }
 
         // Now check how similar the Hough lines are
@@ -2025,6 +2553,9 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
       	} else if (hitgroup == 'X') {
           mergehough = (fabs(HoughXInter_2 - HoughXInter_1) < 1000 &&
                        fabs(HoughXSlope_2 - HoughXSlope_1) < 0.1);
+      	} else if (hitgroup == 'Y') {
+          mergehough = (fabs(HoughYInter_2 - HoughYInter_1) < 1000 &&
+                       fabs(HoughYSlope_2 - HoughYSlope_1) < 0.1);
         }
 
         // Check if we should merge or not
@@ -2061,6 +2592,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
         HoughLinesV.erase(HoughLinesV.begin()+linenumber);
       } else if (hitgroup == 'X') {
         HoughLinesX.erase(HoughLinesX.begin()+linenumber);
+      } else if (hitgroup == 'Y') {
+        HoughLinesY.erase(HoughLinesY.begin()+linenumber);
       }
     } else {
       ++it;
@@ -2090,6 +2623,8 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::HoughTransform(const std::ve
 	        HoughLinesV.erase(HoughLinesV.begin()+tracknumber);
         } else if (hitgroup == 'X') {
           HoughLinesX.erase(HoughLinesX.begin()+tracknumber);
+        } else if (hitgroup == 'Y') {
+          HoughLinesY.erase(HoughLinesY.begin()+tracknumber);
         }
       } else {
         *it = CleanedHough;
@@ -2180,7 +2715,7 @@ std::vector<std::vector<TMS_Hit> > TMS_TrackFinder::FindClusters(const std::vect
 std::vector<TMS_Hit> TMS_TrackFinder::RunHough(const std::vector<TMS_Hit> &TMS_Hits, const char &hitgroup) {
 //TODO new orientation
   // Check if we're in XZ view
-  bool IsXZ = (TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kUBar || TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kVBar || TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kXBar);
+  bool IsXZ = (TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kUBar || TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kVBar || TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kXBar|| TMS_Hits.front().GetBar().GetBarType() == TMS_Bar::kYBar);
 
   // Recalculate Hough parameters event by event... not fully tested!
   bool VariableHough = false;
@@ -2232,9 +2767,11 @@ std::vector<TMS_Hit> TMS_TrackFinder::RunHough(const std::vector<TMS_Hit> &TMS_H
     HoughLineV->SetParameter(0, intercept);
     HoughLineV->SetParameter(1, slope);
   } else if (hitgroup == 'X') {
-
     HoughLineX->SetParameter(0, intercept);
     HoughLineX->SetParameter(1, slope);
+  } else if (hitgroup == 'Y') {
+    HoughLineY->SetParameter(0, intercept);
+    HoughLineY->SetParameter(1, slope);
   }
 
   // Different fitting regions for XZ and YZ views: 
@@ -2254,6 +2791,9 @@ std::vector<TMS_Hit> TMS_TrackFinder::RunHough(const std::vector<TMS_Hit> &TMS_H
   } else if (hitgroup == 'X') {
     HoughLineX->SetRange(zMinHough, zMaxHough);
     HoughCopy = (TF1*)HoughLineX->Clone();
+  } else if (hitgroup == 'Y') {
+    HoughLineY->SetRange(zMinHough, zMaxHough);
+    HoughCopy = (TF1*)HoughLineY->Clone();
   } else {
 #ifdef DEBUG
     std::cout << "Something is going wrong with the assigning of hitgroup" << std::endl;
@@ -2268,6 +2808,8 @@ std::vector<TMS_Hit> TMS_TrackFinder::RunHough(const std::vector<TMS_Hit> &TMS_H
     HoughLinesV.push_back(std::move(HoughPairs));
   } else if (hitgroup == 'X') {
     HoughLinesX.push_back(std::move(HoughPairs));
+  } else if (hitgroup == 'Y') {
+    HoughLinesY.push_back(std::move(HoughPairs));
   }
 
   // Then run a clustering on the Hough Transform
@@ -2299,6 +2841,8 @@ std::vector<TMS_Hit> TMS_TrackFinder::RunHough(const std::vector<TMS_Hit> &TMS_H
       HoughPoint = HoughLineV->Eval(zhit);
     } else if (hitgroup == 'X') {
       HoughPoint = HoughLineX->Eval(zhit);   
+    } else if (hitgroup == 'Y') {
+      HoughPoint = HoughLineY->Eval(zhit);   
     }
     // Hough point is inside bar -> start clustering around bar
     // (Check if 'x'-point is inside hit bar)
@@ -2844,6 +3388,8 @@ void TMS_TrackFinder::BestFirstSearch(const std::vector<TMS_Hit> &TMS_Hits, cons
     TMS_xz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kVBar);
   } else if (hitgroup == 'X') {
     TMS_xz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kXBar);
+  } else if (hitgroup == 'Y') {
+    TMS_xz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kYBar);
   }
   //std::vector<TMS_Hit> TMS_yz = ProjectHits(TMS_Hits_Cleaned, TMS_Bar::kXBar);
 
@@ -2902,6 +3448,8 @@ void TMS_TrackFinder::BestFirstSearch(const std::vector<TMS_Hit> &TMS_Hits, cons
         HoughCandidatesV.push_back(std::move(AStarHits_xz));
       } else if (hitgroup == 'X') {
         HoughCandidatesX.push_back(std::move(AStarHits_xz));
+      } else if (hitgroup == 'Y') {
+        HoughCandidatesY.push_back(std::move(AStarHits_xz));
       }
     }
     nRuns++;
@@ -2992,7 +3540,7 @@ std::vector<TMS_Hit> TMS_TrackFinder::RunAstar(const std::vector<TMS_Hit> &TMS_x
 
   // Remember which orientation these hits are
   // needed when we potentially skip the air gap in xz (but not in yz!)
-  bool IsXZ = ((TMS_xz[0].GetBar()).GetBarType() == TMS_Bar::kUBar || (TMS_xz[0].GetBar()).GetBarType() == TMS_Bar::kVBar);
+  bool IsXZ = ((TMS_xz[0].GetBar()).GetBarType() == TMS_Bar::kUBar || (TMS_xz[0].GetBar()).GetBarType() == TMS_Bar::kVBar ||(TMS_xz[0].GetBar()).GetBarType() == TMS_Bar::kYBar);
   bool IsX = (TMS_xz.front().GetBar().GetBarType() == TMS_Bar::kXBar);
   // Reset remembering where gaps are in xz
   if (IsXZ) PlanesNearGap.clear();
diff --git a/src/TMS_Reco.h b/src/TMS_Reco.h
index 6407ffdc..8f3d37e8 100644
--- a/src/TMS_Reco.h
+++ b/src/TMS_Reco.h
@@ -185,9 +185,11 @@ class TMS_TrackFinder {
     const std::vector<TMS_Hit> & GetCandidatesU() { return CandidatesU; };
     const std::vector<TMS_Hit> & GetCandidatesV() { return CandidatesV; };
     const std::vector<TMS_Hit> & GetCandidatesX() { return CandidatesX; };
+    const std::vector<TMS_Hit> & GetCandidatesY() { return CandidatesY; };
     const std::vector<std::vector<TMS_Hit> >& GetTotalCandidatesU() { return TotalCandidatesU; };
     const std::vector<std::vector<TMS_Hit> >& GetTotalCandidatesV() { return TotalCandidatesV; };
     const std::vector<std::vector<TMS_Hit> >& GetTotalCandidatesX() { return TotalCandidatesX; };
+    const std::vector<std::vector<TMS_Hit> >& GetTotalCandidatesY() { return TotalCandidatesY; };
 
 
     const std::vector<TMS_Hit> &GetCleanedHits() { return CleanedHits; };
@@ -195,25 +197,31 @@ class TMS_TrackFinder {
     TF1* GetHoughLineU() { return HoughLineU; };
     TF1* GetHoughLineV() { return HoughLineV; };
     TF1* GetHoughLineX() { return HoughLineX; };
+    TF1* GetHoughLineY() { return HoughLineY; };
 
     std::vector<std::pair<bool, TF1*> > GetHoughLinesU() { return HoughLinesU; };
     std::vector<std::pair<bool, TF1*> > GetHoughLinesV() { return HoughLinesV; };
     std::vector<std::pair<bool, TF1*> > GetHoughLinesX() { return HoughLinesX; };
+    std::vector<std::pair<bool, TF1*> > GetHoughLinesY() { return HoughLinesY; };
     std::vector<std::pair<double,double> > GetHoughLinesU_Upstream() { return HoughLinesU_Upstream; };
     std::vector<std::pair<double,double> > GetHoughLinesU_Downstream() { return HoughLinesU_Downstream; };
     std::vector<std::pair<double,double> > GetHoughLinesV_Upstream() { return HoughLinesV_Upstream; };
     std::vector<std::pair<double,double> > GetHoughLinesV_Downstream() { return HoughLinesV_Downstream; };
     std::vector<std::pair<double,double> > GetHoughLinesX_Upstream() { return HoughLinesX_Upstream; };
     std::vector<std::pair<double,double> > GetHoughLinesX_Downstream() { return HoughLinesX_Downstream; };
+    std::vector<std::pair<double,double> > GetHoughLinesY_Upstream() { return HoughLinesY_Upstream; };
+    std::vector<std::pair<double,double> > GetHoughLinesY_Downstream() { return HoughLinesY_Downstream; };
 
     int **GetAccumulator() { return Accumulator; };
 
     std::vector<std::vector<TMS_Hit> > &GetClusterCandidatesU() { return ClusterCandidatesU; };
     std::vector<std::vector<TMS_Hit> > &GetClusterCandidatesV() { return ClusterCandidatesV; };
     std::vector<std::vector<TMS_Hit> > &GetClusterCandidatesX() { return ClusterCandidatesX; };
+    std::vector<std::vector<TMS_Hit> > &GetClusterCandidatesY() { return ClusterCandidatesY; };
     std::vector<std::vector<TMS_Hit> > &GetHoughCandidatesU() { return HoughCandidatesU; };
     std::vector<std::vector<TMS_Hit> > &GetHoughCandidatesV() { return HoughCandidatesV; };
     std::vector<std::vector<TMS_Hit> > &GetHoughCandidatesX() { return HoughCandidatesX; };
+    std::vector<std::vector<TMS_Hit> > &GetHoughCandidatesY() { return HoughCandidatesY; };
 
     std::vector<TMS_Track> &GetHoughTracks3D() { return HoughTracks3D; };
 
@@ -230,6 +238,8 @@ class TMS_TrackFinder {
     void CalculateTrackEnergyV(const std::vector<std::vector<TMS_Hit> > &Hits);
     void CalculateTrackLengthX(const std::vector<std::vector<TMS_Hit> > &Hits);
     void CalculateTrackEnergyX(const std::vector<std::vector<TMS_Hit> > &Hits);
+    void CalculateTrackLengthY(const std::vector<std::vector<TMS_Hit> > &Hits);
+    void CalculateTrackEnergyY(const std::vector<std::vector<TMS_Hit> > &Hits);
 
     double CalculateTrackLength3D(const TMS_Track &Hits);
     double CalculateTrackEnergy3D(const TMS_Track &Hits);
@@ -253,6 +263,7 @@ class TMS_TrackFinder {
 
     std::vector<TMS_Hit> Extrapolation(const std::vector<TMS_Hit> &TrackHits, const std::vector<TMS_Hit> &Hits);
     std::vector<TMS_Track> TrackMatching3D();
+    std::vector<TMS_Track> TrackMatching3D_XY(); //This function needs to be merged into TrackMatching3D() later.
     static bool SortByHitNumber(std::vector<TMS_Hit> &OneTrack, std::vector<TMS_Hit> &OtherTrack) { return (OneTrack.size() >= OtherTrack.size() ); };
     void FindPseudoXTrack();
     void CalculateRecoY(TMS_Hit &XHit, TMS_Hit &UHit, TMS_Hit &VHit); //XHit is here a placeholder for the hit that gets the RecoY set. This is then to be chosen as either UHit or VHit
@@ -268,6 +279,7 @@ class TMS_TrackFinder {
     std::vector<TMS_Hit> UHitGroup;
     std::vector<TMS_Hit> VHitGroup;
     std::vector<TMS_Hit> XHitGroup;
+    std::vector<TMS_Hit> YHitGroup;
 
     // Helper function to check if a hit is next to a gap
     bool NextToGap(double, double);
@@ -282,9 +294,11 @@ class TMS_TrackFinder {
     std::vector<double> &GetTrackLengthU() { return TrackLengthU; };
     std::vector<double> &GetTrackLengthV() { return TrackLengthV; };
     std::vector<double> &GetTrackLengthX() { return TrackLengthX; };
+    std::vector<double> &GetTrackLengthY() { return TrackLengthY; };
     std::vector<double> &GetTrackEnergyU() { return TrackEnergyU; };
     std::vector<double> &GetTrackEnergyV() { return TrackEnergyV; };
     std::vector<double> &GetTrackEnergyX() { return TrackEnergyX; };
+    std::vector<double> &GetTrackEnergyY() { return TrackEnergyY; };
 
     void GetHoughLine(const std::vector<TMS_Hit> &TMS_Hits, double &slope, double &intercept);
 
@@ -312,6 +326,7 @@ class TMS_TrackFinder {
     std::vector<TMS_Hit> CandidatesU;
     std::vector<TMS_Hit> CandidatesV;
     std::vector<TMS_Hit> CandidatesX;
+    std::vector<TMS_Hit> CandidatesY;
     std::vector<TMS_Hit> RawHits;
 
     std::vector<TMS_Track> TotalTracks;
@@ -319,24 +334,31 @@ class TMS_TrackFinder {
     std::vector<std::vector<TMS_Hit> > TotalCandidatesU;
     std::vector<std::vector<TMS_Hit> > TotalCandidatesV;
     std::vector<std::vector<TMS_Hit> > TotalCandidatesX;
+    std::vector<std::vector<TMS_Hit> > TotalCandidatesY;
     std::vector<std::pair<bool, TF1*> > HoughLinesU;
     std::vector<std::pair<bool, TF1*> > HoughLinesV;
     std::vector<std::pair<bool, TF1*> > HoughLinesX;
+    std::vector<std::pair<bool, TF1*> > HoughLinesY;
     std::vector<std::vector<TMS_Hit> > ClusterCandidatesU;
     std::vector<std::vector<TMS_Hit> > ClusterCandidatesV;
     std::vector<std::vector<TMS_Hit> > ClusterCandidatesX;
+    std::vector<std::vector<TMS_Hit> > ClusterCandidatesY;
     std::vector<std::vector<TMS_Hit> > HoughCandidatesU;
     std::vector<std::vector<TMS_Hit> > HoughCandidatesV;
     std::vector<std::vector<TMS_Hit> > HoughCandidatesX;
+    std::vector<std::vector<TMS_Hit> > HoughCandidatesY;
     std::vector<std::vector<TMS_Hit> > SortedHoughCandidatesU;
     std::vector<std::vector<TMS_Hit> > SortedHoughCandidatesV;
     std::vector<std::vector<TMS_Hit> > SortedHoughCandidatesX;
+    std::vector<std::vector<TMS_Hit> > SortedHoughCandidatesY;
     std::vector<std::pair<double,double>> HoughLinesU_Upstream;
     std::vector<std::pair<double,double>> HoughLinesU_Downstream;
     std::vector<std::pair<double,double>> HoughLinesV_Upstream;
     std::vector<std::pair<double,double>> HoughLinesV_Downstream;
     std::vector<std::pair<double,double>> HoughLinesX_Upstream;
     std::vector<std::pair<double,double>> HoughLinesX_Downstream;
+    std::vector<std::pair<double,double>> HoughLinesY_Upstream;
+    std::vector<std::pair<double,double>> HoughLinesY_Downstream;
     std::vector<TMS_Track> HoughTracks3D;
 
     char hitgroup;
@@ -364,6 +386,7 @@ class TMS_TrackFinder {
     TF1 *HoughLineU;
     TF1 *HoughLineV;
     TF1 *HoughLineX;
+    TF1 *HoughLineY;
 
     unsigned int nMinHits;
     unsigned int nMaxMerges;
@@ -384,9 +407,11 @@ class TMS_TrackFinder {
     std::vector<double> TrackEnergyU;
     std::vector<double> TrackEnergyV;
     std::vector<double> TrackEnergyX;
+    std::vector<double> TrackEnergyY;
     std::vector<double> TrackLengthU;
     std::vector<double> TrackLengthV;
     std::vector<double> TrackLengthX;
+    std::vector<double> TrackLengthY;
 
     // xvalue is x-axis, y value is y-axis
     void Accumulate(double xhit, double zhit); 
diff --git a/src/TMS_TreeWriter.cpp b/src/TMS_TreeWriter.cpp
index 78782638..25302e45 100644
--- a/src/TMS_TreeWriter.cpp
+++ b/src/TMS_TreeWriter.cpp
@@ -70,6 +70,7 @@ void TMS_TreeWriter::MakeBranches() {
   Branch_Lines->Branch("nLinesU", &nLinesU, "nLinesU/I");
   Branch_Lines->Branch("nLinesV", &nLinesV, "nLinesV/I");
   Branch_Lines->Branch("nLinesX", &nLinesX, "nLinesX/I");
+  Branch_Lines->Branch("nLinesY", &nLinesY, "nLinesY/I");
   Branch_Lines->Branch("nLines3D",    &nLines3D,    "nLines3D/I");
 
   Branch_Lines->Branch("SlopeU",     SlopeU,      "SlopeU[nLinesU]/F");
@@ -93,12 +94,21 @@ void TMS_TreeWriter::MakeBranches() {
   Branch_Lines->Branch("Slope_UpstreamX",       Slope_UpstreamX,        "Slope_UpstreamX[nLinesX]/F");
   Branch_Lines->Branch("Intercept_UpstreamX",   Intercept_UpstreamX,    "Intercept_UpstreamX[nLinesX]/F");
 
+  Branch_Lines->Branch("SlopeY",                SlopeY,                 "SlopeY[nLinesY]/F");
+  Branch_Lines->Branch("InterceptY",            InterceptY,             "InterceptY[nLinesY]/F");
+  Branch_Lines->Branch("Slope_DownstreamY",     Slope_DownstreamY,      "Slope_DownstreamY[nLinesY]/F");
+  Branch_Lines->Branch("Intercept_DownstreamY", Intercept_DownstreamY,  "Intercept_DownstreamY[nLinesY]/F");
+  Branch_Lines->Branch("Slope_UpstreamY",       Slope_UpstreamY,        "Slope_UpstreamY[nLinesY]/F");
+  Branch_Lines->Branch("Intercept_UpstreamY",   Intercept_UpstreamY,    "Intercept_UpstreamY[nLinesY]/F");
+
   Branch_Lines->Branch("DirectionZU", DirectionZU, "DirectionZU[nLinesU]/F");
   Branch_Lines->Branch("DirectionZV", DirectionZV, "DirectionZV[nLinesV]/F");
   Branch_Lines->Branch("DirectionZX", DirectionZX, "DirectionZX[nLinesX]/F");
+  Branch_Lines->Branch("DirectionZY", DirectionZY, "DirectionZY[nLinesY]/F");
   Branch_Lines->Branch("DirectionXU", DirectionXU, "DirectionXU[nLinesU]/F");
   Branch_Lines->Branch("DirectionXV", DirectionXV, "DirectionXV[nLinesV]/F");
   Branch_Lines->Branch("DirectionYX", DirectionYX, "DirectionYX[nLinesX]/F");
+  Branch_Lines->Branch("DirectionXY", DirectionXY, "DirectionXY[nLinesY]/F");
   Branch_Lines->Branch("DirectionZU_Downstream",   DirectionZU_Downstream,   "DirectionZU_Downstream[nLinesU]/F");
   Branch_Lines->Branch("DirectionXU_Downstream",   DirectionXU_Downstream,   "DirectionXU_Downstream[nLinesU]/F");
   Branch_Lines->Branch("DirectionZU_Upstream",     DirectionZU_Upstream,     "DirectionZU_Upstream[nLinesU]/F");
@@ -110,46 +120,62 @@ void TMS_TreeWriter::MakeBranches() {
   Branch_Lines->Branch("DirectionZX_Downstream",  DirectionZX_Downstream, "DirectionZX_Downstream[nLinesX]/F");
   Branch_Lines->Branch("DirectionYX_Downstream",  DirectionYX_Downstream, "DirectionYX_Downstream[nLinesX]/F");
   Branch_Lines->Branch("DirectionZX_Upstream",    DirectionZX_Upstream,   "DirectionZX_Upstream[nLinesX]/F");
-  Branch_Lines->Branch("DirectionYX_Upstream",    DirectionYX_Upstream,   "DirectionYX_Upstream[nLinesX]/F");
+  Branch_Lines->Branch("DirectionZY_Upstream",    DirectionZY_Upstream,   "DirectionZY_Upstream[nLinesY]/F");
+  Branch_Lines->Branch("DirectionZY_Downstream",  DirectionZY_Downstream, "DirectionZY_Downstream[nLinesY]/F");
+  Branch_Lines->Branch("DirectionXY_Downstream",  DirectionXY_Downstream, "DirectionXY_Downstream[nLinesY]/F");
+  Branch_Lines->Branch("DirectionZY_Upstream",  DirectionZY_Upstream, "DirectionZY_Upstream[nLinesY]/F");
+  Branch_Lines->Branch("DirectionXY_Upstream",  DirectionXY_Upstream, "DirectionXY_Upstream[nLinesY]/F");
 
   Branch_Lines->Branch("FirstHoughHitU",     FirstHitU,     "FirstHoughHitU[nLinesU][2]/F");
   Branch_Lines->Branch("FirstHoughHitV",     FirstHitV,     "FirstHoughHitV[nLinesV][2]/F");
   Branch_Lines->Branch("FirstHoughHitX",     FirstHitX,     "FirstHoughHitX[nLinesX][2]/F");
+  Branch_Lines->Branch("FirstHoughHitY",     FirstHitY,     "FirstHoughHitY[nLinesY][2]/F");
   Branch_Lines->Branch("LastHoughHitU",      LastHitU,      "LastHoughHitU[nLinesU][2]/F");
   Branch_Lines->Branch("LastHoughHitV",      LastHitV,      "LastHoughHitV[nLinesV][2]/F");
   Branch_Lines->Branch("LastHoughHitX",      LastHitX,      "LastHoughHitX[nLinesX][2]/F");
+  Branch_Lines->Branch("LastHoughHitY",      LastHitY,      "LastHoughHitY[nLinesY][2]/F");
   Branch_Lines->Branch("FirstHoughHitTimeU", FirstHitTimeU, "FirstHoughHitTimeU[nLinesU]/F");
   Branch_Lines->Branch("FirstHoughHitTimeV", FirstHitTimeV, "FirstHoughHitTimeV[nLinesV]/F"); 
   Branch_Lines->Branch("FirstHoughHitTimeX", FirstHitTimeX, "FirstHoughHitTimeX[nLinesX]/F");
+  Branch_Lines->Branch("FirstHoughHitTimeY", FirstHitTimeY, "FirstHoughHitTimeY[nLinesY]/F");
   Branch_Lines->Branch("LastHoughHitTimeU",  LastHitTimeU,  "LastHoughHitTimeU[nLinesU]/F");
   Branch_Lines->Branch("LastHoughHitTimeV",  LastHitTimeV,  "LastHoughHitTimeV[nLinesV]/F");
   Branch_Lines->Branch("LastHoughHitTImeX",  LastHitTimeX,  "LastHoughHitTimeX[nLinesX]/F");
+  Branch_Lines->Branch("LastHoughHitTImeY",  LastHitTimeY,  "LastHoughHitTimeY[nLinesY]/F");
   Branch_Lines->Branch("HoughEarliestHitTimeU", EarliestHitTimeU, "HoughEarliestHitTimeU[nLinesU]/F");
   Branch_Lines->Branch("HoughEarliestHitTimeV", EarliestHitTimeV, "HoughEarliestHitTimeV[nLinesV]/F");
   Branch_Lines->Branch("HoughEarliestHitTimeX", EarliestHitTimeX, "HoughEarliestHitTimeX[nLinesX]/F");
+  Branch_Lines->Branch("HoughEarliestHitTimeY", EarliestHitTimeY, "HoughEarliestHitTimeY[nLinesY]/F");
   Branch_Lines->Branch("HoughLatestHitTimeU",   LatestHitTimeU,   "HoughLatestHitTimeU[nLinesU]/F");
   Branch_Lines->Branch("HoughLatestHitTimeV",   LatestHitTimeV,   "HoughLatestHitTimeV[nLinesV]/F");
   Branch_Lines->Branch("HoughLatestHitTimeX",   LatestHitTimeX,   "HoughLatestHitTimeX[nLinesX]/F");
+  Branch_Lines->Branch("HoughLatestHitTimeY",   LatestHitTimeY,   "HoughLatestHitTimeY[nLinesY]/F");
   Branch_Lines->Branch("FirstHoughPlaneU", FirstPlaneU,   "FirstHoughPlaneU[nLinesU]/I");
   Branch_Lines->Branch("FirstHoughPlaneV", FirstPlaneV,   "FirstHoughPlaneV[nLinesV]/I");
   Branch_Lines->Branch("FirstHoughPlaneX", FirstPlaneX,   "FirstHoughPlaneX[nLinesX]/I");
+  Branch_Lines->Branch("FirstHoughPlaneY", FirstPlaneY,   "FirstHoughPlaneY[nLinesY]/I");
   Branch_Lines->Branch("LastHoughPlaneU",  LastPlaneU,    "LastHoughPlaneU[nLinesU]/I");
   Branch_Lines->Branch("LastHoughPlaneV",  LastPlaneV,    "LastHoughPlaneV[nLinesV]/I");
   Branch_Lines->Branch("LastHoughPlaneX",  LastPlaneX,    "LastHoughPlaneX[nLinesX]/I");
+  Branch_Lines->Branch("LastHoughPlaneY",  LastPlaneY,    "LastHoughPlaneY[nLinesY]/I");
   Branch_Lines->Branch("TMSStart",         &TMSStart,     "TMSStart/O");
   Branch_Lines->Branch("TMSStartTime",     &TMSStartTime, "TMSStartTime/F");
   Branch_Lines->Branch("OccupancyU",       OccupancyU,    "OccupancyU[nLinesU]/F");
   Branch_Lines->Branch("OccupancyV",       OccupancyV,    "OccupancyV[nLinesV]/F");
   Branch_Lines->Branch("OccupancyX",       OccupancyX,    "OccupancyX[nLinesX]/F");
+  Branch_Lines->Branch("OccupancyY",       OccupancyY,    "OccupancyY[nLinesY]/F");
   Branch_Lines->Branch("TrackLengthU",     TrackLengthU,  "TrackLengthU[nLinesU]/F");
   Branch_Lines->Branch("TrackLengthV",     TrackLengthV,  "TrackLengthV[nLinesV]/F");
   Branch_Lines->Branch("TrackLengthX",     TrackLengthX,  "TrackLengthX[nLinesX]/F");
+  Branch_Lines->Branch("TrackLengthY",     TrackLengthY,  "TrackLengthY[nLinesY]/F");
   Branch_Lines->Branch("TotalTrackEnergyU", TotalTrackEnergyU, "TotalTrackEnergyU[nLinesU]/F");
   Branch_Lines->Branch("TotalTrackEnergyV", TotalTrackEnergyV, "TotalTrackEnergyV[nLinesV]/F");
   Branch_Lines->Branch("TotalTrackEnergyX", TotalTrackEnergyX, "TotalTrackEnergyX[nLinesX]/F");
+  Branch_Lines->Branch("TotalTrackEnergyY", TotalTrackEnergyY, "TotalTrackEnergyY[nLinesY]/F");
   Branch_Lines->Branch("TrackStoppingU",    TrackStoppingU,    "TrackStoppingU[nLinesU]/O");
   Branch_Lines->Branch("TrackStoppingV",    TrackStoppingV,    "TrackStoppingV[nLinesV]/O");
   Branch_Lines->Branch("TrackStoppingX",    TrackStoppingX,    "TrackStoppingX[nLinesX]/O");
+  Branch_Lines->Branch("TrackStoppingY",    TrackStoppingY,    "TrackStoppingY[nLinesY]/O");
 
 /*  // 3D Track information
   Branch_Lines->Branch("FirstHoughHit3D",        FirstHit3D,        "FirstHoughHit3D[nLines3D][3]/F");
@@ -174,47 +200,61 @@ void TMS_TreeWriter::MakeBranches() {
   Branch_Lines->Branch("nHitsInTrackU",   &nHitsInTrackU,  "nHitsInTrackU[nLinesU]/I");
   Branch_Lines->Branch("nHitsInTrackV",   &nHitsInTrackV,  "nHitsInTrackV[nLinesV]/I");
   Branch_Lines->Branch("nHitsInTrackX",   &nHitsInTrackX,  "nHitsInTrackX[nLinesX]/I");
+  Branch_Lines->Branch("nHitsInTrackY",   &nHitsInTrackY,  "nHitsInTrackY[nLinesY]/I");
   Branch_Lines->Branch("TrackHitEnergyU", TrackHitEnergyU, "TrackHitEnergyU[10][200]/F");
   Branch_Lines->Branch("TrackHitEnergyV", TrackHitEnergyV, "TrackHitEnergyV[10][200]/F");
   Branch_Lines->Branch("TrackHitEnergyX", TrackHitEnergyX, "TrackHitEnergyX[10][200]/F");
+  Branch_Lines->Branch("TrackHitEnergyY", TrackHitEnergyY, "TrackHitEnergyY[10][200]/F");
   Branch_Lines->Branch("TrackHitPosU",    TrackHitPosU,    "TrackHitPosU[10][200][2]/F");
   Branch_Lines->Branch("TrackHitPosV",    TrackHitPosV,    "TrackHitPosV[10][200][2]/F");
   Branch_Lines->Branch("TrackHitPosX",    TrackHitPosX,    "TrackHitPosX[10][200][2]/F");
+  Branch_Lines->Branch("TrackHitPosY",    TrackHitPosY,    "TrackHitPosY[10][200][2]/F");
   Branch_Lines->Branch("TrackHitTimeU",   TrackHitTimeU,   "TrackHitTimeU[10][200]/F");
   Branch_Lines->Branch("TrackHitTimeV",   TrackHitTimeV,   "TrackHitTimeV[10][200]/F");
   Branch_Lines->Branch("TrackHitTimeX",   TrackHitTimeX,   "TrackHitTimeX[10][200]/F");
+  Branch_Lines->Branch("TrackHitTimeY",   TrackHitTimeY,   "TrackHitTimeY[10][200]/F");
 
   // Cluster information
   Branch_Lines->Branch("nClustersU",        &nClustersU,       "nClustersU/I");
   Branch_Lines->Branch("nClustersV",        &nClustersV,       "nClustersV/I");
   Branch_Lines->Branch("nClusterX",         &nClustersX,       "nClustersX/I");
+  Branch_Lines->Branch("nClusterY",         &nClustersY,       "nClustersY/I");
   Branch_Lines->Branch("ClusterEnergyU",    ClusterEnergyU,    "ClusterEnergyU[nClustersU]/F");
   Branch_Lines->Branch("ClusterEnergyV",    ClusterEnergyV,    "ClusterEnergyV[nClustersV]/F");
   Branch_Lines->Branch("ClusterEnergyX",    ClusterEnergyX,    "ClusterEnergyX[nClustersX]/F");
+  Branch_Lines->Branch("ClusterEnergyY",    ClusterEnergyY,    "ClusterEnergyY[nClustersY]/F");
   Branch_Lines->Branch("ClusterTimeU",      ClusterTimeU,      "ClusterTimeU[nClustersU]/F");
   Branch_Lines->Branch("ClusterTimeV",      ClusterTimeV,      "ClusterTimeV[nClustersV]/F");
   Branch_Lines->Branch("ClusterTimeX",      ClusterTimeX,      "ClusterTimeX[nClustersX]/F");
+  Branch_Lines->Branch("ClusterTimeY",      ClusterTimeY,      "ClusterTimeY[nClustersY]/F");
   Branch_Lines->Branch("ClusterPosMeanU",   ClusterPosMeanU,   "ClusterPosMeanU[25][2]/F");
   Branch_Lines->Branch("ClusterPosMeanV",   ClusterPosMeanV,   "ClusterPosMeanV[25][2]/F");
   Branch_Lines->Branch("ClusterPosMeanX",   ClusterPosMeanX,   "ClusterPosMeanX[25][2]/F");
+  Branch_Lines->Branch("ClusterPosMeanY",   ClusterPosMeanY,   "ClusterPosMeanY[25][2]/F");
   Branch_Lines->Branch("ClusterPosStdDevU", ClusterPosStdDevU, "ClusterPosStdDevU[25][2]/F");
   Branch_Lines->Branch("ClusterPosStdDevV", ClusterPosStdDevV, "ClusterPosStdDevV[25][2]/F");
   Branch_Lines->Branch("ClusterPosStdDevX", ClusterPosStdDevX, "ClusterPosStdDevX[25][2]/F");
+  Branch_Lines->Branch("ClusterPosStdDevY", ClusterPosStdDevY, "ClusterPosStdDevY[25][2]/F");
   Branch_Lines->Branch("nHitsInClusterU",   nHitsInClusterU,   "nHitsInClusterU[nClustersU]/I");
   Branch_Lines->Branch("nHitsInClusterV",   nHitsInClusterV,   "nHitsInClusterV[nClustersV]/I");
   Branch_Lines->Branch("nHitsInClusterX",   nHitsInClusterX,   "nHitsInClusterX[nClustersX]/I");
+  Branch_Lines->Branch("nHitsInClusterY",   nHitsInClusterY,   "nHitsInClusterY[nClustersY]/I");
   Branch_Lines->Branch("ClusterHitPosU",    ClusterHitPosU,    "ClusterHitPosU[25][200][2]/F");
   Branch_Lines->Branch("ClusterHitPosV",    ClusterHitPosV,    "ClusterHitPosV[25][200][2]/F");
   Branch_Lines->Branch("ClusterHitPosX",    ClusterHitPosX,    "ClusterHitPosX[25][200][2]/F");
+  Branch_Lines->Branch("ClusterHitPosY",    ClusterHitPosY,    "ClusterHitPosY[25][200][2]/F");
   Branch_Lines->Branch("ClusterHitEnergyU", ClusterHitEnergyU, "ClusterHitEnergyU[25][200]/F");
   Branch_Lines->Branch("ClusterHitEnergyV", ClusterHitEnergyV, "ClusterHitEnergyV[25][200]/F");
   Branch_Lines->Branch("ClusterHitEnergyX", ClusterHitEnergyX, "ClusterHitEnergyX[25][200]/F");
+  Branch_Lines->Branch("ClusterHitEnergyY", ClusterHitEnergyY, "ClusterHitEnergyY[25][200]/F");
   Branch_Lines->Branch("ClusterHitTimeU",   ClusterHitTimeU,   "ClusterHitTimeU[25][200]/F");
   Branch_Lines->Branch("ClusterHitTimeV",   ClusterHitTimeV,   "ClusterHitTimeV[25][200]/F");
   Branch_Lines->Branch("ClusterHitTimeX",   ClusterHitTimeX,   "ClusterHitTimeX[25][200]/F");
+  Branch_Lines->Branch("ClusterHitTimeY",   ClusterHitTimeY,   "ClusterHitTimeY[25][200]/F");
   Branch_Lines->Branch("ClusterHitSliceU",  ClusterHitSliceU,  "ClusterHitSliceU[25][200]/I");
   Branch_Lines->Branch("ClusterHitSliceV",  ClusterHitSliceV,  "ClusterHitSliceV[25][200]/I");
   Branch_Lines->Branch("ClusterHitSliceX",  ClusterHitSliceX,  "ClusterHitSliceX[25][200]/I");
+  Branch_Lines->Branch("ClusterHitSliceY",  ClusterHitSliceY,  "ClusterHitSliceY[25][200]/I");
 
   // Hit information
   Branch_Lines->Branch("nHits",         &nHits,        "nHits/I");
@@ -253,6 +293,7 @@ void TMS_TreeWriter::MakeBranches() {
   Reco_Tree->Branch("EnergyDeposit",  RecoTrackEnergyDeposit,   "EnergyDeposit[nTracks]/F");
   Reco_Tree->Branch("Momentum",       RecoTrackMomentum,        "Momentum[nTracks]/F");
   Reco_Tree->Branch("Length",         RecoTrackLength,          "Length[nTracks]/F");
+  Reco_Tree->Branch("Length_3D",      RecoTrackLength_3D,       "Length_3D[nTracks]/F");
   Reco_Tree->Branch("Charge",         RecoTrackCharge,          "Charge[nTracks]/I");
   
   Reco_Tree->Branch("Chi2",           RecoTrackChi2,             "Chi2[nTracks]/F");
@@ -548,8 +589,9 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
   NeutrinoX4[1] = event.GetNeutrinoVtx().Y();
   NeutrinoX4[2] = event.GetNeutrinoVtx().Z();
   NeutrinoX4[3] = event.GetNeutrinoVtx().T();
-  NeutrinoP4[0] = event.GetNeutrinoP4().X();
   IsCC = (event.GetReaction().find("[CC]") != std::string::npos);
+
+
   // Lepton info
   LeptonPDG = event.GetLeptonPDG();
   LeptonP4[1] = event.GetLeptonP4().Y();
@@ -587,13 +629,16 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
   std::vector<std::pair<bool, TF1*>> HoughLinesU = TMS_TrackFinder::GetFinder().GetHoughLinesU();
   std::vector<std::pair<bool, TF1*>> HoughLinesV = TMS_TrackFinder::GetFinder().GetHoughLinesV();
   std::vector<std::pair<bool, TF1*>> HoughLinesX = TMS_TrackFinder::GetFinder().GetHoughLinesX();
+  std::vector<std::pair<bool, TF1*>> HoughLinesY = TMS_TrackFinder::GetFinder().GetHoughLinesY();
   // Also get the size of the hits to get a measure of relative goodness
   std::vector<std::vector<TMS_Hit> > HoughCandidatesU = TMS_TrackFinder::GetFinder().GetHoughCandidatesU();
   std::vector<std::vector<TMS_Hit> > HoughCandidatesV = TMS_TrackFinder::GetFinder().GetHoughCandidatesV();
   std::vector<std::vector<TMS_Hit> > HoughCandidatesX = TMS_TrackFinder::GetFinder().GetHoughCandidatesX();
+  std::vector<std::vector<TMS_Hit> > HoughCandidatesY = TMS_TrackFinder::GetFinder().GetHoughCandidatesY();
   nLinesU = HoughCandidatesU.size();
   nLinesV = HoughCandidatesV.size();
   nLinesX = HoughCandidatesX.size();
+  nLinesY = HoughCandidatesY.size();
 
 
   // Skip the event if there aren't any Hough Lines
@@ -621,6 +666,14 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
     return;
   }
 
+  if (nLinesY > __TMS_MAX_LINES__) {
+    std::cerr << "Exceeded max number of HoughLines to write to file" << std::endl;
+    std::cerr << "Max lines: " << __TMS_MAX_LINES__ << std::endl;
+    std::cerr << "Number of lines in event (x): " << nLinesY << std::endl;
+    std::cerr << "Not writing evet" << std::endl;
+    return;
+  }
+
   int it = 0;
   for (auto &Lines: HoughLinesU) {
     // Get the slopes saved down
@@ -752,6 +805,49 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
     it++;
   }
 
+  it = 0;
+  for (auto &Lines: HoughLinesY) {
+    // Get the slopes saved down
+    InterceptY[it] = Lines.second->GetParameter(0);
+    Intercept_UpstreamY[it] = TMS_TrackFinder::GetFinder().GetHoughLinesY_Upstream()[it].first;
+    Intercept_DownstreamY[it] = TMS_TrackFinder::GetFinder().GetHoughLinesY_Downstream()[it].first;
+    SlopeY[it] = Lines.second->GetParameter(1);
+    Slope_UpstreamY[it] = TMS_TrackFinder::GetFinder().GetHoughLinesY_Upstream()[it].second;
+    Slope_DownstreamY[it] = TMS_TrackFinder::GetFinder().GetHoughLinesY_Downstream()[it].second;
+
+    // Calculate the z and x vectors by evaling the TF1 in thin and thick target
+    double xlow = TMS_Const::TMS_Thin_Start;
+    double xhi = TMS_Const::TMS_Thick_Start;
+    double ylow = Lines.second->Eval(xlow);
+    double yhi = Lines.second->Eval(xhi);
+    // Do the same for up and downstream portions
+    double ylow_upstream = Intercept_UpstreamY[it]+xlow*Slope_UpstreamY[it];
+    double yhi_upstream = Intercept_UpstreamY[it]+xhi*Slope_UpstreamY[it];
+
+    double ylow_downstream = Intercept_DownstreamY[it]+xlow*Slope_DownstreamY[it];
+    double yhi_downstream = Intercept_DownstreamY[it]+xhi*Slope_DownstreamY[it];
+
+    double xlen = xhi-xlow;
+    double ylen = yhi-ylow;
+    double len = sqrt(xlen*xlen+ylen*ylen);
+
+    double ylen_upstream = yhi_upstream - ylow_upstream;
+    double ylen_downstream = yhi_downstream - ylow_downstream;
+
+    double len_upstream = sqrt(xlen*xlen+ylen_upstream*ylen_upstream);
+    double len_downstream = sqrt(xlen*xlen+ylen_downstream*ylen_downstream);
+
+    DirectionZY[it] = xlen/len;
+    DirectionXY[it] = ylen/len;
+
+    DirectionZY_Upstream[it] = xlen/len_upstream;
+    DirectionXY_Upstream[it] = ylen_upstream/len_upstream;
+
+    DirectionZY_Downstream[it] = xlen/len_downstream;
+    DirectionXY_Downstream[it] = ylen_downstream/len_downstream;
+
+    it++;
+  }
 
   // Find where the first hough hit is
   TMSStart = false;
@@ -936,6 +1032,64 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
     it++;
   }
 
+  std::vector<std::vector<TMS_Hit> > HoughCandsY = TMS_TrackFinder::GetFinder().GetHoughCandidatesY();
+  it = 0;
+  for (auto &Candidates: HoughCandsY) {
+    // Loop over hits
+    for (auto &hit: Candidates) {
+      if (FirstTrack == NULL) {
+        FirstTrack = &hit;
+      } else if (hit.GetZ() < FirstTrack->GetZ()) {
+        FirstTrack = &hit;
+      }
+    }
+    nHitsInTrackY[it] = Candidates.size();
+
+    // Then save the hit info
+    FirstPlaneY[it] = Candidates.front().GetPlaneNumber();
+    FirstHitY[it][0] = Candidates.front().GetZ();
+    FirstHitY[it][1] = Candidates.front().GetNotZ();
+    FirstHitTimeY[it] = Candidates.front().GetT();
+
+    LastPlaneY[it] = Candidates.back().GetPlaneNumber();
+    LastHitY[it][0] = Candidates.back().GetZ();
+    LastHitY[it][1] = Candidates.back().GetNotZ();
+    LastHitTimeY[it] = Candidates.back().GetT();
+
+    TrackLengthY[it] = TMS_TrackFinder::GetFinder().GetTrackLengthY()[it];
+    TotalTrackEnergyY[it] = TMS_TrackFinder::GetFinder().GetTrackEnergyY()[it];
+    OccupancyY[it] = double(HoughCandsY[it].size())/TotalHits;
+    
+    float earliest_hit_time = 1e32;
+    float latest_hit_time = -1e32;
+    // Get each hit in the track and save its energy
+    for (unsigned int j = 0; j < Candidates.size(); ++j) {
+      TrackHitEnergyY[it][j] = Candidates[j].GetE();
+      TrackHitTimeY[it][j] = Candidates[j].GetT();
+      TrackHitPosY[it][j][0] = Candidates[j].GetZ();
+      TrackHitPosY[it][j][1] = Candidates[j].GetNotZ();
+      
+      float time = Candidates[j].GetT();
+      
+      if (time < earliest_hit_time) earliest_hit_time = time;
+      if (time > latest_hit_time) latest_hit_time = time;
+    }
+    EarliestHitTimeY[it] = earliest_hit_time;
+    LatestHitTimeY[it] = latest_hit_time;
+    
+
+    double maxenergy = 0;
+    unsigned int nLastHits_temp = nLastHits;
+    if ((unsigned int)nLastHits > Candidates.size()) nLastHits_temp = Candidates.size();
+    for (unsigned int i = 0; i < nLastHits_temp; ++i) {
+      double hitenergy = Candidates[nLastHits_temp-1-i].GetE();
+      if (hitenergy > maxenergy) maxenergy = hitenergy;
+    }
+    if (maxenergy > EnergyCut) TrackStoppingY[it] = true;
+
+
+    it++;
+  }
 
 /*  std::vector<TMS_Track> HoughCands3D = TMS_TrackFinder::GetFinder().GetHoughTracks3D(); //TODO this should be done by Liam with Reco_Tree
   it = 0;
@@ -1006,9 +1160,11 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
   std::vector<std::vector<TMS_Hit> > ClustersU = TMS_TrackFinder::GetFinder().GetClusterCandidatesU();
   std::vector<std::vector<TMS_Hit> > ClustersV = TMS_TrackFinder::GetFinder().GetClusterCandidatesV();
   std::vector<std::vector<TMS_Hit> > ClustersX = TMS_TrackFinder::GetFinder().GetClusterCandidatesX();
+  std::vector<std::vector<TMS_Hit> > ClustersY = TMS_TrackFinder::GetFinder().GetClusterCandidatesY();
   nClustersU = ClustersU.size();
   nClustersV = ClustersV.size();
   nClustersX = ClustersX.size();
+  nClustersY = ClustersY.size();
   if (nClustersU > __TMS_MAX_CLUSTERS__) {
     std::cerr << "Too many clusters in TMS_TreeWriter" << std::endl;
     std::cerr << "Hard-coded maximum: " << __TMS_MAX_CLUSTERS__ << std::endl;
@@ -1027,6 +1183,12 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
     std::cerr << "nClustersX in event: " << nClustersX << std::endl;
     return;
   }
+  if (nClustersY > __TMS_MAX_CLUSTERS__) {
+    std::cerr << "Too many clusters in TMS_TreeWriter" << std::endl;
+    std::cerr << "Hard-coded maximum: " << __TMS_MAX_CLUSTERS__ << std::endl;
+    std::cerr << "nClustersX in event: " << nClustersY << std::endl;
+    return;
+  }
 
   // Sum up the cluster candidates
   int stdit = 0;
@@ -1167,6 +1329,52 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
     ClusterPosStdDevX[stdit][0] = std_dev_z;
     ClusterPosStdDevX[stdit][1] = std_dev_notz;
   } 
+  stdit = 0;
+  for (auto it = ClustersY.begin(); it != ClustersY.end(); ++it, ++stdit) {
+    double total_energy = 0;
+    // Mean of cluster in z and not z
+    double mean_z = 0;
+    double mean_notz = 0;
+    // Mean of square of cluster in z and not z
+    double mean2_z = 0;
+    double mean2_notz = 0;
+    double min_cluster_time = 1e10;
+    int nhits = (*it).size();
+//    std::cout << "Cluster One nHits: " << nhits << std::endl;
+    for (int j = 0; j < nhits; ++j) {
+      mean_z += (*it)[j].GetZ();
+      mean_notz += (*it)[j].GetNotZ();
+      mean2_z += (*it)[j].GetZ()*(*it)[j].GetZ();
+      mean2_notz += (*it)[j].GetNotZ()*(*it)[j].GetNotZ();
+      total_energy += (*it)[j].GetE();
+      float time = (*it)[j].GetT();
+      if (time < min_cluster_time) min_cluster_time = time;
+//      std::cout << (*it)[j].GetZ() << " " << (*it)[j].GetNotZ() << std::endl;
+      ClusterHitPosY[stdit][j][0] = (*it)[j].GetZ();
+      ClusterHitPosY[stdit][j][1] = (*it)[j].GetNotZ();
+      ClusterHitEnergyY[stdit][j] = (*it)[j].GetE();
+      ClusterHitTimeY[stdit][j] = (*it)[j].GetT();
+      ClusterHitSliceY[stdit][j] = (*it)[j].GetSlice();
+    }
+    mean_z /= nhits;
+    mean_notz /= nhits;
+
+    mean2_z /= nhits;
+    mean2_notz /= nhits;
+
+    ClusterEnergyY[stdit] = total_energy;
+    ClusterTimeY[stdit] = min_cluster_time;
+    nHitsInClusterY[stdit] = nhits;
+    ClusterPosMeanY[stdit][0] = mean_z;
+    ClusterPosMeanY[stdit][1] = mean_notz;
+    // Calculate the standard deviation
+    double std_dev_z = mean2_z-mean_z*mean_z;
+    double std_dev_notz = mean2_z-mean_z*mean_z;
+    if (std_dev_z > 0) std_dev_z = sqrt(std_dev_z);
+    if (std_dev_notz > 0) std_dev_notz = sqrt(std_dev_notz);
+    ClusterPosStdDevY[stdit][0] = std_dev_z;
+    ClusterPosStdDevY[stdit][1] = std_dev_notz;
+  } 
 
   // Write out the hit information
   std::vector<TMS_Hit> CleanedHits = TMS_TrackFinder::GetFinder().GetCleanedHits();
@@ -1213,7 +1421,14 @@ void TMS_TreeWriter::Fill(TMS_Event &event) {
     nKalmanNodes[itTrack]           = (int) RecoTrack->KalmanNodes.size();
 //    std::cout << "TreeWriter number of hits: " << nHitsIn3DTrack[itTrack] << std::endl;
     RecoTrackEnergyRange[itTrack]   =       RecoTrack->EnergyRange;
-    RecoTrackLength[itTrack]        =       0.5 * (TrackLengthU[itTrack] + TrackLengthV[itTrack]); //RecoTrack->Length;// RecoTrack->Length;, 2d is better estimate than 3d because of y jumps
+    if (nLinesU<=0){
+        RecoTrackLength[itTrack]        =       0.5 * (TrackLengthX[itTrack] + TrackLengthY[itTrack]); //RecoTrack->Length;// RecoTrack->Length;, 2d is better estimate than 3d because of y jumps
+    }
+    else {
+        RecoTrackLength[itTrack]        =       0.5 * (TrackLengthU[itTrack] + TrackLengthV[itTrack]); //RecoTrack->Length;// RecoTrack->Length;, 2d is better estimate than 3d because of y jumps
+    }
+
+    RecoTrackLength_3D[itTrack]        =    RecoTrack->Length; 
     RecoTrackEnergyDeposit[itTrack] =       RecoTrack->EnergyDeposit;
     RecoTrackMomentum[itTrack]      =       RecoTrack->Momentum;
     RecoTrackCharge[itTrack]        =       RecoTrack->Charge;
@@ -1724,6 +1939,7 @@ void TMS_TreeWriter::Clear() {
   LArOuterShellEnergyFromVertex = LArTotalEnergyFromVertex = TotalNonTMSEnergyFromVertex = DEFAULT_CLEARING_FLOAT;
   Reaction = "";
   IsCC = false;
+
   for (int i = 0; i < 4; ++i) {
     MuonP4[i]=DEFAULT_CLEARING_FLOAT;
     Muon_Vertex[i]=DEFAULT_CLEARING_FLOAT;
@@ -1739,25 +1955,32 @@ void TMS_TreeWriter::Clear() {
   nLinesU = DEFAULT_CLEARING_FLOAT;
   nLinesV = DEFAULT_CLEARING_FLOAT;
   nLinesX = DEFAULT_CLEARING_FLOAT;
+  nLinesY = DEFAULT_CLEARING_FLOAT;
   for (int i = 0; i < __TMS_MAX_LINES__; ++i) {
     SlopeU[i] = DEFAULT_CLEARING_FLOAT;
     SlopeV[i] = DEFAULT_CLEARING_FLOAT;
     SlopeX[i] = DEFAULT_CLEARING_FLOAT;
+    SlopeY[i] = DEFAULT_CLEARING_FLOAT;
     InterceptU[i] = DEFAULT_CLEARING_FLOAT;
     InterceptV[i] = DEFAULT_CLEARING_FLOAT;
     InterceptX[i] = DEFAULT_CLEARING_FLOAT;
+    InterceptY[i] = DEFAULT_CLEARING_FLOAT;
     Slope_DownstreamU[i] = DEFAULT_CLEARING_FLOAT;
     Slope_DownstreamV[i] = DEFAULT_CLEARING_FLOAT;
     Slope_DownstreamX[i] = DEFAULT_CLEARING_FLOAT;
+    Slope_DownstreamY[i] = DEFAULT_CLEARING_FLOAT;
     Intercept_DownstreamU[i] = DEFAULT_CLEARING_FLOAT;
     Intercept_DownstreamV[i] = DEFAULT_CLEARING_FLOAT;
     Intercept_DownstreamX[i] = DEFAULT_CLEARING_FLOAT;
+    Intercept_DownstreamY[i] = DEFAULT_CLEARING_FLOAT;
     Slope_UpstreamU[i] = DEFAULT_CLEARING_FLOAT;
     Slope_UpstreamV[i] = DEFAULT_CLEARING_FLOAT;
     Slope_UpstreamX[i] = DEFAULT_CLEARING_FLOAT;
+    Slope_UpstreamY[i] = DEFAULT_CLEARING_FLOAT;
     Intercept_UpstreamU[i] = DEFAULT_CLEARING_FLOAT;
     Intercept_UpstreamV[i] = DEFAULT_CLEARING_FLOAT;
     Intercept_UpstreamX[i] = DEFAULT_CLEARING_FLOAT;
+    Intercept_UpstreamY[i] = DEFAULT_CLEARING_FLOAT;
 
     DirectionZU[i] = DEFAULT_CLEARING_FLOAT;
     DirectionXU[i] = DEFAULT_CLEARING_FLOAT;
@@ -1780,27 +2003,41 @@ void TMS_TreeWriter::Clear() {
     DirectionZX_Downstream[i] = DEFAULT_CLEARING_FLOAT;
     DirectionYX_Downstream[i] = DEFAULT_CLEARING_FLOAT;
 
+    DirectionZY[i] = DEFAULT_CLEARING_FLOAT;
+    DirectionXY[i] = DEFAULT_CLEARING_FLOAT;
+    DirectionZY_Upstream[i] = DEFAULT_CLEARING_FLOAT;
+    DirectionXY_Upstream[i] = DEFAULT_CLEARING_FLOAT;
+    DirectionZY_Downstream[i] = DEFAULT_CLEARING_FLOAT;
+    DirectionXY_Downstream[i] = DEFAULT_CLEARING_FLOAT;
+
     OccupancyU[i] = DEFAULT_CLEARING_FLOAT;
     OccupancyV[i] = DEFAULT_CLEARING_FLOAT;
     OccupancyX[i] = DEFAULT_CLEARING_FLOAT;
+    OccupancyY[i] = DEFAULT_CLEARING_FLOAT;
     TrackLengthU[i] = DEFAULT_CLEARING_FLOAT;
     TrackLengthV[i] = DEFAULT_CLEARING_FLOAT;
     TrackLengthX[i] = DEFAULT_CLEARING_FLOAT;
+    TrackLengthY[i] = DEFAULT_CLEARING_FLOAT;
     TotalTrackEnergyU[i] = DEFAULT_CLEARING_FLOAT;
     TotalTrackEnergyV[i] = DEFAULT_CLEARING_FLOAT;
     TotalTrackEnergyX[i] = DEFAULT_CLEARING_FLOAT;
+    TotalTrackEnergyY[i] = DEFAULT_CLEARING_FLOAT;
     FirstPlaneU[i] = DEFAULT_CLEARING_FLOAT;
     FirstPlaneV[i] = DEFAULT_CLEARING_FLOAT;
     FirstPlaneX[i] = DEFAULT_CLEARING_FLOAT;
+    FirstPlaneY[i] = DEFAULT_CLEARING_FLOAT;
     LastPlaneU[i] = DEFAULT_CLEARING_FLOAT;
     LastPlaneV[i] = DEFAULT_CLEARING_FLOAT;
     LastPlaneX[i] = DEFAULT_CLEARING_FLOAT;
+    LastPlaneY[i] = DEFAULT_CLEARING_FLOAT;
     nHitsInTrackU[i] = DEFAULT_CLEARING_FLOAT;
     nHitsInTrackV[i] = DEFAULT_CLEARING_FLOAT;
     nHitsInTrackX[i] = DEFAULT_CLEARING_FLOAT;
+    nHitsInTrackY[i] = DEFAULT_CLEARING_FLOAT;
     TrackStoppingU[i] = false;
     TrackStoppingV[i] = false;
     TrackStoppingX[i] = false;
+    TrackStoppingY[i] = false;
 
     for (int k = 0; k < 3; k++) {
       RecoTrackKalmanFirstPlaneBarView[i][k] = DEFAULT_CLEARING_FLOAT;
@@ -1860,13 +2097,16 @@ void TMS_TreeWriter::Clear() {
   nClustersU = DEFAULT_CLEARING_FLOAT;
   nClustersV = DEFAULT_CLEARING_FLOAT;
   nClustersX = DEFAULT_CLEARING_FLOAT;
+  nClustersY = DEFAULT_CLEARING_FLOAT;
   for (int i = 0; i < __TMS_MAX_CLUSTERS__; ++i) {
     ClusterEnergyU[i] = DEFAULT_CLEARING_FLOAT;
     ClusterEnergyV[i] = DEFAULT_CLEARING_FLOAT;
     ClusterEnergyX[i] = DEFAULT_CLEARING_FLOAT;
+    ClusterEnergyY[i] = DEFAULT_CLEARING_FLOAT;
     nHitsInClusterU[i] = DEFAULT_CLEARING_FLOAT;
     nHitsInClusterV[i] = DEFAULT_CLEARING_FLOAT;
     nHitsInClusterX[i] = DEFAULT_CLEARING_FLOAT;
+    nHitsInClusterY[i] = DEFAULT_CLEARING_FLOAT;
     for (int j = 0; j < 2; ++j) {
       ClusterPosMeanU[i][j] = DEFAULT_CLEARING_FLOAT;
       ClusterPosStdDevU[i][j] = DEFAULT_CLEARING_FLOAT;
@@ -1876,6 +2116,9 @@ void TMS_TreeWriter::Clear() {
 
       ClusterPosMeanX[i][j] = DEFAULT_CLEARING_FLOAT;
       ClusterPosStdDevX[i][j] = DEFAULT_CLEARING_FLOAT;
+
+      ClusterPosMeanY[i][j] = DEFAULT_CLEARING_FLOAT;
+      ClusterPosStdDevY[i][j] = DEFAULT_CLEARING_FLOAT;
     }
     for (int j = 0; j < __TMS_MAX_LINE_HITS__; ++j) {
       ClusterHitPosU[i][j][0] = DEFAULT_CLEARING_FLOAT;
@@ -1889,6 +2132,10 @@ void TMS_TreeWriter::Clear() {
       ClusterHitPosX[i][j][0] = DEFAULT_CLEARING_FLOAT;
       ClusterHitPosX[i][j][1] = DEFAULT_CLEARING_FLOAT;
       ClusterHitEnergyX[i][j] = DEFAULT_CLEARING_FLOAT;
+
+      ClusterHitPosY[i][j][0] = DEFAULT_CLEARING_FLOAT;
+      ClusterHitPosY[i][j][1] = DEFAULT_CLEARING_FLOAT;
+      ClusterHitEnergyY[i][j] = DEFAULT_CLEARING_FLOAT;
     }
   }
 
@@ -1913,6 +2160,7 @@ void TMS_TreeWriter::Clear() {
     RecoTrackEnergyRange[i] = DEFAULT_CLEARING_FLOAT;
     RecoTrackEnergyDeposit[i] = DEFAULT_CLEARING_FLOAT;
     RecoTrackLength[i] = DEFAULT_CLEARING_FLOAT;
+    RecoTrackLength_3D[i] = DEFAULT_CLEARING_FLOAT;
     RecoTrackCharge[i] = DEFAULT_CLEARING_FLOAT;
   }
   
diff --git a/src/TMS_TreeWriter.h b/src/TMS_TreeWriter.h
index 15d0fe2f..3091d7eb 100644
--- a/src/TMS_TreeWriter.h
+++ b/src/TMS_TreeWriter.h
@@ -68,6 +68,7 @@ class TMS_TreeWriter {
     float RecoTrackMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackTrueMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackLength[__TMS_MAX_TRACKS__];
+    float RecoTrackLength_3D[__TMS_MAX_TRACKS__];
     float RecoTrackChi2[__TMS_MAX_TRACKS__];
     int RecoTrackCharge[__TMS_MAX_TRACKS__];
     
@@ -97,6 +98,7 @@ class TMS_TreeWriter {
     int nLinesU;
     int nLinesV;
     int nLinesX;
+    int nLinesY;
 
     int nLines3D;
     
@@ -120,83 +122,107 @@ class TMS_TreeWriter {
     float SlopeU[__TMS_MAX_LINES__];
     float SlopeV[__TMS_MAX_LINES__];
     float SlopeX[__TMS_MAX_LINES__];
+    float SlopeY[__TMS_MAX_LINES__];
     float InterceptU[__TMS_MAX_LINES__];
     float InterceptV[__TMS_MAX_LINES__];
     float InterceptX[__TMS_MAX_LINES__];
+    float InterceptY[__TMS_MAX_LINES__];
 
     float Slope_DownstreamU[__TMS_MAX_LINES__];
     float Slope_DownstreamV[__TMS_MAX_LINES__];
     float Slope_DownstreamX[__TMS_MAX_LINES__];
+    float Slope_DownstreamY[__TMS_MAX_LINES__];
     float Intercept_DownstreamU[__TMS_MAX_LINES__];
     float Intercept_DownstreamV[__TMS_MAX_LINES__];
     float Intercept_DownstreamX[__TMS_MAX_LINES__];
+    float Intercept_DownstreamY[__TMS_MAX_LINES__];
 
     float Slope_UpstreamU[__TMS_MAX_LINES__];
     float Slope_UpstreamV[__TMS_MAX_LINES__];
     float Slope_UpstreamX[__TMS_MAX_LINES__];
+    float Slope_UpstreamY[__TMS_MAX_LINES__];
     float Intercept_UpstreamU[__TMS_MAX_LINES__];
     float Intercept_UpstreamV[__TMS_MAX_LINES__];
     float Intercept_UpstreamX[__TMS_MAX_LINES__];
+    float Intercept_UpstreamY[__TMS_MAX_LINES__];
 
     float DirectionZU[__TMS_MAX_LINES__];
     float DirectionZV[__TMS_MAX_LINES__];
     float DirectionZX[__TMS_MAX_LINES__];
+    float DirectionZY[__TMS_MAX_LINES__];
     float DirectionXU[__TMS_MAX_LINES__];
     float DirectionXV[__TMS_MAX_LINES__];
     float DirectionYX[__TMS_MAX_LINES__];
+    float DirectionXY[__TMS_MAX_LINES__];
 
     float DirectionZU_Upstream[__TMS_MAX_LINES__];
     float DirectionZV_Upstream[__TMS_MAX_LINES__];
     float DirectionZX_Upstream[__TMS_MAX_LINES__];
+    float DirectionZY_Upstream[__TMS_MAX_LINES__];
     float DirectionXU_Upstream[__TMS_MAX_LINES__];
     float DirectionXV_Upstream[__TMS_MAX_LINES__];
     float DirectionYX_Upstream[__TMS_MAX_LINES__];
+    float DirectionXY_Upstream[__TMS_MAX_LINES__];
 
     float DirectionZU_Downstream[__TMS_MAX_LINES__];
     float DirectionZV_Downstream[__TMS_MAX_LINES__];
     float DirectionZX_Downstream[__TMS_MAX_LINES__];
+    float DirectionZY_Downstream[__TMS_MAX_LINES__];
     float DirectionXU_Downstream[__TMS_MAX_LINES__];
     float DirectionXV_Downstream[__TMS_MAX_LINES__];
     float DirectionYX_Downstream[__TMS_MAX_LINES__];
+    float DirectionXY_Downstream[__TMS_MAX_LINES__];
 
     float FirstHitU[__TMS_MAX_LINES__][2]; // [0] is Z, [1] is NotZ
     float FirstHitV[__TMS_MAX_LINES__][2];
     float FirstHitX[__TMS_MAX_LINES__][2];
+    float FirstHitY[__TMS_MAX_LINES__][2];
     float LastHitU[__TMS_MAX_LINES__][2]; // [0] is Z, [1] is NotZ
     float LastHitV[__TMS_MAX_LINES__][2];
     float LastHitX[__TMS_MAX_LINES__][2];
+    float LastHitY[__TMS_MAX_LINES__][2];
     float FirstHitTimeU[__TMS_MAX_LINES__]; 
     float FirstHitTimeV[__TMS_MAX_LINES__];
     float FirstHitTimeX[__TMS_MAX_LINES__];
+    float FirstHitTimeY[__TMS_MAX_LINES__];
     float LastHitTimeU[__TMS_MAX_LINES__];
     float LastHitTimeV[__TMS_MAX_LINES__];
     float LastHitTimeX[__TMS_MAX_LINES__];
+    float LastHitTimeY[__TMS_MAX_LINES__];
     float EarliestHitTimeU[__TMS_MAX_LINES__]; 
     float EarliestHitTimeV[__TMS_MAX_LINES__];
     float EarliestHitTimeX[__TMS_MAX_LINES__];
+    float EarliestHitTimeY[__TMS_MAX_LINES__];
     float LatestHitTimeU[__TMS_MAX_LINES__];
     float LatestHitTimeV[__TMS_MAX_LINES__];
     float LatestHitTimeX[__TMS_MAX_LINES__];
+    float LatestHitTimeY[__TMS_MAX_LINES__];
     int FirstPlaneU[__TMS_MAX_LINES__];
     int FirstPlaneV[__TMS_MAX_LINES__];
     int FirstPlaneX[__TMS_MAX_LINES__];
+    int FirstPlaneY[__TMS_MAX_LINES__];
     int LastPlaneU[__TMS_MAX_LINES__];
     int LastPlaneV[__TMS_MAX_LINES__];
     int LastPlaneX[__TMS_MAX_LINES__];
+    int LastPlaneY[__TMS_MAX_LINES__];
     bool TMSStart;
     float TMSStartTime;
     float OccupancyU[__TMS_MAX_LINES__];
     float OccupancyV[__TMS_MAX_LINES__];
     float OccupancyX[__TMS_MAX_LINES__];
+    float OccupancyY[__TMS_MAX_LINES__];
     float TrackLengthU[__TMS_MAX_LINES__];
     float TrackLengthV[__TMS_MAX_LINES__];
     float TrackLengthX[__TMS_MAX_LINES__];
+    float TrackLengthY[__TMS_MAX_LINES__];
     float TotalTrackEnergyU[__TMS_MAX_LINES__];
     float TotalTrackEnergyV[__TMS_MAX_LINES__];
     float TotalTrackEnergyX[__TMS_MAX_LINES__];
+    float TotalTrackEnergyY[__TMS_MAX_LINES__];
     bool TrackStoppingU[__TMS_MAX_LINES__];
     bool TrackStoppingV[__TMS_MAX_LINES__];
     bool TrackStoppingX[__TMS_MAX_LINES__];
+    bool TrackStoppingY[__TMS_MAX_LINES__];
 
     /*float FirstHit3D[__TMS_MAX_LINES__][3]; // [0] is Z, [1] is 'X', [2] is Y
     float LastHit3D[__TMS_MAX_LINES__][3];
@@ -218,48 +244,62 @@ class TMS_TreeWriter {
     float TrackHitEnergyU[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__]; // Energy per track hit
     float TrackHitEnergyV[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
     float TrackHitEnergyX[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
+    float TrackHitEnergyY[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
     float TrackHitTimeU[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
     float TrackHitTimeV[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
     float TrackHitTimeX[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
+    float TrackHitTimeY[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__];
     float TrackHitPosU[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__][2]; // [0] is Z, [1] is NotZ
     float TrackHitPosV[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__][2];
     float TrackHitPosX[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__][2];
+    float TrackHitPosY[__TMS_MAX_LINES__][__TMS_MAX_LINE_HITS__][2];
     int nHitsInTrackU[__TMS_MAX_LINES__];
     int nHitsInTrackV[__TMS_MAX_LINES__];
     int nHitsInTrackX[__TMS_MAX_LINES__];
+    int nHitsInTrackY[__TMS_MAX_LINES__];
 
     // Cluster information
     int nClustersU; // Number of clusters
     int nClustersV;
     int nClustersX;
+    int nClustersY;
     float ClusterEnergyU[__TMS_MAX_CLUSTERS__]; // Energy in cluster
     float ClusterEnergyV[__TMS_MAX_CLUSTERS__];
     float ClusterEnergyX[__TMS_MAX_CLUSTERS__];
+    float ClusterEnergyY[__TMS_MAX_CLUSTERS__];
 
     float ClusterTimeU[__TMS_MAX_CLUSTERS__]; // Time in cluster
     float ClusterTimeV[__TMS_MAX_CLUSTERS__];
     float ClusterTimeX[__TMS_MAX_CLUSTERS__];
+    float ClusterTimeY[__TMS_MAX_CLUSTERS__];
     int nHitsInClusterU[__TMS_MAX_CLUSTERS__]; // Number of hits in cluster
     int nHitsInClusterV[__TMS_MAX_CLUSTERS__];
     int nHitsInClusterX[__TMS_MAX_CLUSTERS__];
+    int nHitsInClusterY[__TMS_MAX_CLUSTERS__];
     float ClusterPosMeanU[__TMS_MAX_CLUSTERS__][2]; // Mean cluster position, [0] is Z, [1] is NotZ
     float ClusterPosMeanV[__TMS_MAX_CLUSTERS__][2];
     float ClusterPosMeanX[__TMS_MAX_CLUSTERS__][2];
+    float ClusterPosMeanY[__TMS_MAX_CLUSTERS__][2];
     float ClusterPosStdDevU[__TMS_MAX_CLUSTERS__][2]; // Cluster standard deviation, [0] is Z, [1] is NotZ
     float ClusterPosStdDevV[__TMS_MAX_CLUSTERS__][2];
     float ClusterPosStdDevX[__TMS_MAX_CLUSTERS__][2];
+    float ClusterPosStdDevY[__TMS_MAX_CLUSTERS__][2];
     float ClusterHitPosU[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__][2]; // Cluster hit position
     float ClusterHitPosV[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__][2];
     float ClusterHitPosX[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__][2];
+    float ClusterHitPosY[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__][2];
     float ClusterHitEnergyU[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__]; // Cluster hit energy
     float ClusterHitEnergyV[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
     float ClusterHitEnergyX[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
+    float ClusterHitEnergyY[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
     float ClusterHitTimeU[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__]; // Cluster hit energy
     float ClusterHitTimeV[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
     float ClusterHitTimeX[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
+    float ClusterHitTimeY[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
     int ClusterHitSliceU[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__]; // Cluster hit slice
     int ClusterHitSliceV[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
     int ClusterHitSliceX[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
+    int ClusterHitSliceY[__TMS_MAX_CLUSTERS__][__TMS_MAX_LINE_HITS__];
 
     // Reco information
     int nHits; // How many hits in event


Reviews:
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:44:27Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:45:25Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:46:41Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:48:28Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:49:18Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:52:49Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:55:48Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:56:45Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:57:08Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:59:01Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T16:59:11Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T17:40:36Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T17:40:59Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T17:43:40Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T17:52:03Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-04T17:52:57Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T17:53:43Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T17:56:01Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T22:33:55Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-04T23:37:24Z
user: login: jdkio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-12T01:53:09Z
user: login: jdkio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-12T02:12:30Z
user: login: jdkio
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-12T02:13:33Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-18T11:07:07Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-18T11:07:21Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-20T18:32:48Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-02-20T18:35:16Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-21T11:08:17Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T14:35:53Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T14:36:45Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T14:37:30Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T03:46:31Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T03:51:35Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T07:14:35Z
user: login: LiamOS
body: Approved from my side, although I haven't looked in detail at the TMS_Reco changes.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-01T14:32:48Z
user: login: kyjung123
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-01T15:24:04Z
user: login: AsaNehm
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T15:50:42Z
user: login: AsaNehm
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T15:50:59Z

Review comments:
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: Is the factor -2 no longer needed? Why
created_at: 2025-02-04T16:44:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -153,6 +153,8 @@ class TMS_Event {
     int nVertices;
 
     std::string Reaction;
+
+
path: src/TMS_Event.h
user: login: AsaNehm
body: These lines can be removed
created_at: 2025-02-04T16:45:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -108,7 +108,7 @@
 
   [Recon.Kalman]
 
-    Run = true #false # Whether we run the Kalman filter or not
+    Run = false #true #false # Whether we run the Kalman filter or not
path: config/TMS_Default_Config.toml
user: login: AsaNehm
body: In general people want to use the Kalman filter. If it's turned on, would this apart from the XY case still work? Then please don't change this value
created_at: 2025-02-04T16:46:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -253,6 +263,7 @@ class TMS_TrackFinder {
 
     std::vector<TMS_Hit> Extrapolation(const std::vector<TMS_Hit> &TrackHits, const std::vector<TMS_Hit> &Hits);
     std::vector<TMS_Track> TrackMatching3D();
+    std::vector<TMS_Track> TrackMatching3D_XY();
path: src/TMS_Reco.h
user: login: AsaNehm
body: We should probably add a comment somewhere in the code that these functions should be merged.
If y hits -> use xy version, else don't use it. Then these two functions can be merged into one
created_at: 2025-02-04T16:48:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,6 +68,7 @@ class TMS_TreeWriter {
     float RecoTrackMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackTrueMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackLength[__TMS_MAX_TRACKS__];
+    float RecoTrackLength_3D[__TMS_MAX_TRACKS__];
path: src/TMS_TreeWriter.h
user: login: AsaNehm
body: Bad naming? This would mean that the RecoTrackLength is without 3D. Is this really the case?
created_at: 2025-02-04T16:49:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -517,10 +615,16 @@ void TMS_TrackFinder::FindTracks(TMS_Event &event) {
     ClusterCandidatesU = FindClusters(MaskedU);
     ClusterCandidatesV = FindClusters(MaskedV);
     ClusterCandidatesX = FindClusters(MaskedX);
+    ClusterCandidatesY = FindClusters(MaskedY);
   }
 
   // Call TrackMatching3D
-  HoughTracks3D = TrackMatching3D();
+  if (!UHitGroup.empty()){
+      HoughTracks3D = TrackMatching3D();
+  }
+  else{
path: src/TMS_Reco.cpp
user: login: AsaNehm
body: See comment from TMS_Reco.h
created_at: 2025-02-04T16:52:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1544,6 +1654,367 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
   return returned;
 }
 
+std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D_XY() {
path: src/TMS_Reco.cpp
user: login: AsaNehm
body: Do you need someone do go through this function in detail? Not doing it otherwise... (it's a lot)
created_at: 2025-02-04T16:55:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -253,6 +293,7 @@ void TMS_TreeWriter::MakeBranches() {
   Reco_Tree->Branch("EnergyDeposit",  RecoTrackEnergyDeposit,   "EnergyDeposit[nTracks]/F");
   Reco_Tree->Branch("Momentum",       RecoTrackMomentum,        "Momentum[nTracks]/F");
   Reco_Tree->Branch("Length",         RecoTrackLength,          "Length[nTracks]/F");
+  Reco_Tree->Branch("Length_3D",      RecoTrackLength_3D,       "Length_3D[nTracks]/F");
path: src/TMS_TreeWriter.cpp
user: login: AsaNehm
body: Bad naming again? Length should also be 3D, but this indicates otherwise
created_at: 2025-02-04T16:56:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -426,6 +467,7 @@ void TMS_TreeWriter::MakeTruthBranches(TTree* truth) {
   truth->Branch("SpillNo", &SpillNo, "SpillNo/I");
   truth->Branch("RunNo", &RunNo, "RunNo/I");
   truth->Branch("IsCC", &IsCC, "IsCC/O");
+
path: src/TMS_TreeWriter.cpp
user: login: AsaNehm
body: Empty line necessary?
created_at: 2025-02-04T16:57:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1541,7 +1757,8 @@ void TMS_TreeWriter::FillTruthInfo(TMS_Event &event) {
   NeutrinoX4[3] = event.GetNeutrinoVtx().T();
   IsCC = (event.GetReaction().find("[CC]") != std::string::npos);
 
-  TVector3 interaction_location = event.GetNeutrinoVtx().Vect(); 
+  TVector3 interaction_location = event.GetNeutrinoVtx().Vect()*1000.;//mm //GetNeutrinoVtx is in meter 
path: src/TMS_TreeWriter.cpp
user: login: AsaNehm
body: This is an important change. Everyone agree to do this?
created_at: 2025-02-04T16:59:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1541,7 +1757,8 @@ void TMS_TreeWriter::FillTruthInfo(TMS_Event &event) {
   NeutrinoX4[3] = event.GetNeutrinoVtx().T();
   IsCC = (event.GetReaction().find("[CC]") != std::string::npos);
 
-  TVector3 interaction_location = event.GetNeutrinoVtx().Vect(); 
+  TVector3 interaction_location = event.GetNeutrinoVtx().Vect()*1000.;//mm //GetNeutrinoVtx is in meter 
+//  std::cout<<"interaction:"<<interaction_location.X()<<std::endl;
path: src/TMS_TreeWriter.cpp
user: login: AsaNehm
body: Take this comment out
created_at: 2025-02-04T16:59:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: kyjung123
body: I think no longer needed, otherwise, the bar number goes 2,4,6 like this.
Actually, I don't get why there is -2.

created_at: 2025-02-04T17:40:36Z
author_association: MEMBER
diff_hunk: @@ -108,7 +108,7 @@
 
   [Recon.Kalman]
 
-    Run = true #false # Whether we run the Kalman filter or not
+    Run = false #true #false # Whether we run the Kalman filter or not
path: config/TMS_Default_Config.toml
user: login: kyjung123
body: Okay, thanks for letting me know.

created_at: 2025-02-04T17:40:59Z
author_association: MEMBER
diff_hunk: @@ -68,6 +68,7 @@ class TMS_TreeWriter {
     float RecoTrackMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackTrueMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackLength[__TMS_MAX_TRACKS__];
+    float RecoTrackLength_3D[__TMS_MAX_TRACKS__];
path: src/TMS_TreeWriter.h
user: login: kyjung123
body: Yes, I mean that now the variable RecoTrackLength here is defined as the average of the length from two Hough lines. and RecoTrackLength_3D refer to CalculateTrackLength3D().
created_at: 2025-02-04T17:43:40Z
author_association: MEMBER
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: The factor 2 is necessary as we have two modules side-by-side sharing the same y position for horizontal layers. The 2 doubles the amount of possible bar numbers which then get properly filled in (or should be, hope I have actually implemented this) with the GlobalBarNumber together. E.g. uneven bar numbers on left side and even bar numbers on right side
created_at: 2025-02-04T17:52:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: The minus is most likely due to the assignment direction. Definitely should be in as well
created_at: 2025-02-04T17:52:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1544,6 +1654,367 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
   return returned;
 }
 
+std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D_XY() {
path: src/TMS_Reco.cpp
user: login: kyjung123
body: I think it's okay so far, there is some part I can develop more. but the result seems reasonable.

created_at: 2025-02-04T17:53:43Z
author_association: MEMBER
diff_hunk: @@ -253,6 +263,7 @@ class TMS_TrackFinder {
 
     std::vector<TMS_Hit> Extrapolation(const std::vector<TMS_Hit> &TrackHits, const std::vector<TMS_Hit> &Hits);
     std::vector<TMS_Track> TrackMatching3D();
+    std::vector<TMS_Track> TrackMatching3D_XY();
path: src/TMS_Reco.h
user: login: kyjung123
body: So you mean merge TrackMatching3D_XY() into TrackMatcinh3D()?
instead of this?
`  if (!UHitGroup.empty()){
      HoughTracks3D = TrackMatching3D();
  }
  else{
        HoughTracks3D = TrackMatching3D_XY();
`
created_at: 2025-02-04T17:56:01Z
author_association: MEMBER
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: kyjung123
body: I see your point, and I appreciate the clarification. I hadn’t looked at the GlobalBarNumber below this line. However, I’m still unsure if dividing the left and right sides is necessary. Since we’ll be using the bar number instead of the y position in DBSCAN, clustering, Hough transform, and this process, wouldn’t having one long bar be more accurate?
created_at: 2025-02-04T22:33:55Z
author_association: MEMBER
diff_hunk: @@ -1541,7 +1757,8 @@ void TMS_TreeWriter::FillTruthInfo(TMS_Event &event) {
   NeutrinoX4[3] = event.GetNeutrinoVtx().T();
   IsCC = (event.GetReaction().find("[CC]") != std::string::npos);
 
-  TVector3 interaction_location = event.GetNeutrinoVtx().Vect(); 
+  TVector3 interaction_location = event.GetNeutrinoVtx().Vect()*1000.;//mm //GetNeutrinoVtx is in meter 
path: src/TMS_TreeWriter.cpp
user: login: kyjung123
body: I'm pretty sure. For example,  before I changed it, InteractionLArFiducial looks like this 
![image](https://github.com/user-attachments/assets/6dc2e274-4168-47d7-953a-96f81424b2aa)
Because, z position of vertex is very small so it's always false.


created_at: 2025-02-04T23:37:24Z
author_association: MEMBER
diff_hunk: @@ -1541,7 +1757,8 @@ void TMS_TreeWriter::FillTruthInfo(TMS_Event &event) {
   NeutrinoX4[3] = event.GetNeutrinoVtx().T();
   IsCC = (event.GetReaction().find("[CC]") != std::string::npos);
 
-  TVector3 interaction_location = event.GetNeutrinoVtx().Vect(); 
+  TVector3 interaction_location = event.GetNeutrinoVtx().Vect()*1000.;//mm //GetNeutrinoVtx is in meter 
path: src/TMS_TreeWriter.cpp
user: login: jdkio
body: No, don't fix it here. You should fix it when it's set. The reason this is happens is because it's being set from the genie tree, which uses units of m, instead of the edep sim tree, which uses units of mm. Fix it here,
https://github.com/DUNE/dune-tms/blob/main/src/TMS_Event.cpp#L1037
and the momentum/energy is set in GeV as well which is also inconsistent
created_at: 2025-02-12T01:53:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,6 +68,7 @@ class TMS_TreeWriter {
     float RecoTrackMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackTrueMomentum[__TMS_MAX_TRACKS__];
     float RecoTrackLength[__TMS_MAX_TRACKS__];
+    float RecoTrackLength_3D[__TMS_MAX_TRACKS__];
path: src/TMS_TreeWriter.h
user: login: jdkio
body: That's a historical artifact because the 3d track length is very wrong without the kalman filter. So using the average was less wrong. I think the plan was always to go back to the 3d track length function once it was fixed. But I think it's okay output the 3d result here since we have no plans on how to fix it
created_at: 2025-02-12T02:12:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -253,6 +293,7 @@ void TMS_TreeWriter::MakeBranches() {
   Reco_Tree->Branch("EnergyDeposit",  RecoTrackEnergyDeposit,   "EnergyDeposit[nTracks]/F");
   Reco_Tree->Branch("Momentum",       RecoTrackMomentum,        "Momentum[nTracks]/F");
   Reco_Tree->Branch("Length",         RecoTrackLength,          "Length[nTracks]/F");
+  Reco_Tree->Branch("Length_3D",      RecoTrackLength_3D,       "Length_3D[nTracks]/F");
path: src/TMS_TreeWriter.cpp
user: login: jdkio
body: See [this comment](https://github.com/DUNE/dune-tms/pull/202#discussion_r1951877445)
created_at: 2025-02-12T02:13:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: Not really (the long bar)
created_at: 2025-02-18T11:07:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: I checked again and the minus can be taken out
created_at: 2025-02-18T11:07:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1541,7 +1757,8 @@ void TMS_TreeWriter::FillTruthInfo(TMS_Event &event) {
   NeutrinoX4[3] = event.GetNeutrinoVtx().T();
   IsCC = (event.GetReaction().find("[CC]") != std::string::npos);
 
-  TVector3 interaction_location = event.GetNeutrinoVtx().Vect(); 
+  TVector3 interaction_location = event.GetNeutrinoVtx().Vect()*1000.;//mm //GetNeutrinoVtx is in meter 
path: src/TMS_TreeWriter.cpp
user: login: kyjung123
body: Okay! I'll do it later but not here.
created_at: 2025-02-20T18:32:48Z
author_association: MEMBER
diff_hunk: @@ -253,6 +263,7 @@ class TMS_TrackFinder {
 
     std::vector<TMS_Hit> Extrapolation(const std::vector<TMS_Hit> &TrackHits, const std::vector<TMS_Hit> &Hits);
     std::vector<TMS_Track> TrackMatching3D();
+    std::vector<TMS_Track> TrackMatching3D_XY();
path: src/TMS_Reco.h
user: login: kyjung123
body: @AsaNehm , I can't come up with the idea to merge them so far.
created_at: 2025-02-20T18:35:16Z
author_association: MEMBER
diff_hunk: @@ -253,6 +263,7 @@ class TMS_TrackFinder {
 
     std::vector<TMS_Hit> Extrapolation(const std::vector<TMS_Hit> &TrackHits, const std::vector<TMS_Hit> &Hits);
     std::vector<TMS_Track> TrackMatching3D();
+    std::vector<TMS_Track> TrackMatching3D_XY();
path: src/TMS_Reco.h
user: login: AsaNehm
body: You don't have to do this here. This is quite a lot to do. So just add a TODO comment in your code with the 'reminder' to do this at a later point
created_at: 2025-02-21T11:08:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -137,7 +137,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
   if (BarOrient == kUBar || BarOrient == kVBar || BarOrient == kYBar) {
     BarNumber = (GetX() - TMS_Const::TMS_Start_Exact[0]) / GetXw();
   } else if (BarOrient == kXBar) {
-    BarNumber = -2 * (GetY() - 2510) / GetYw(); //TODO refer to TMS_Const::TMS_Start_Exact[1] if equal to -2510
+    BarNumber = (GetY() - TMS_Const::TMS_Start_Exact[1]) / GetYw();
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: The factor 2 is still necessary
created_at: 2025-03-05T14:35:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,7 +69,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
     }
 
     // This is the furthest down hit we have: scintillator bar
-    else if (NodeName.find(TMS_Const::TMS_ScintLayerName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerOrthoName) != std::string::npos) {
+    else if (NodeName.find(TMS_Const::TMS_ScintLayerName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerOrthoName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerparallelName) != std::string::npos) {
path: src/TMS_Bar.cpp
user: login: AsaNehm
body: Might be good to have this name as TMS_ScintLayerParallelName as well to match the usual naming scheme
created_at: 2025-03-05T14:36:45Z
author_association: CONTRIBUTOR
path: .DS_Store
user: login: AsaNehm
body: Why is this file here? What is it used for? Can it be removed?
created_at: 2025-03-05T14:37:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,7 +69,7 @@ bool TMS_Bar::FindModules(double xval, double yval, double zval) {
     }
 
     // This is the furthest down hit we have: scintillator bar
-    else if (NodeName.find(TMS_Const::TMS_ScintLayerName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerOrthoName) != std::string::npos) {
+    else if (NodeName.find(TMS_Const::TMS_ScintLayerName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerOrthoName) != std::string::npos || NodeName.find(TMS_Const::TMS_ScintLayerparallelName) != std::string::npos) {
path: src/TMS_Bar.cpp
user: login: kyjung123
body: Yep! Good point! I changed it!
created_at: 2025-03-06T03:46:31Z
author_association: MEMBER
path: .DS_Store
user: login: kyjung123
body: I don't know where is from. I deleted it!

created_at: 2025-03-06T03:51:35Z
author_association: MEMBER
diff_hunk: @@ -1599,6 +1713,400 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
   return returned;
 }
 
+std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D_XY() {
path: src/TMS_Reco.cpp
user: login: AsaNehm
body: I changed the matching procedure a bit in the 'original' TrackMatching3D function to fix some issues. Please have a look through this and check whether a similar change in this matching function would make sense as well.
created_at: 2025-04-01T07:14:34Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1599,6 +1713,400 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
   return returned;
 }
 
+std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D_XY() {
path: src/TMS_Reco.cpp
user: login: kyjung123
body: Yes, I followed the updated logic that you used and it is work as well for XY case.
created_at: 2025-04-01T15:24:03Z
author_association: MEMBER
diff_hunk: @@ -1599,6 +1713,400 @@ std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D() {
   return returned;
 }
 
+std::vector<TMS_Track> TMS_TrackFinder::TrackMatching3D_XY() {
path: src/TMS_Reco.cpp
user: login: AsaNehm
body: Nice
created_at: 2025-04-01T15:50:42Z
author_association: CONTRIBUTOR

PR comments:
user: login: AsaNehm
created_at: 2025-02-26T11:05:15Z
body: What's the current status here? @kyjung123 could you summarize what changes you made in the last ~10 commits?
author_association: CONTRIBUTOR
user: login: kyjung123
created_at: 2025-02-27T15:54:32Z
body: I edited based on the comments here and updated with the most recent main branch,( this one is just a trial for myself).
author_association: MEMBER
user: login: kyjung123
created_at: 2025-03-05T01:10:47Z
body: Previously, main branch was not successfully merged. Now I updated it with a fixed one.  @AsaNehm Please have a look and merge it.
author_association: MEMBER
user: login: kyjung123
created_at: 2025-04-01T02:17:39Z
body: @AsaNehm @jdkio @LiamOS , I was update the TMS_Reco.cpp including Asa update.
Please have a look and merge it.
author_association: MEMBER
user: login: AsaNehm
created_at: 2025-04-01T07:15:09Z
body: Apart from this one comment, looks good to me
author_association: CONTRIBUTOR