From ac75d15b46c50787073a31e3425b3f9bd9cdb53f Mon Sep 17 00:00:00 2001
From: xueting <xueting.yang@cern.ch>
Date: Thu, 15 Jun 2023 21:36:41 +0800
Subject: [PATCH 1/9] add_handler_pattern_matching

---
 handlers/PrCheckerSummaryHandler.py           | 87 +++++++++++--------
 handlers/PrCheckerSummaryHandler_withoutUT.py | 53 ++++++-----
 handlers/RootFilePatternHandler.py            | 44 ++++++++++
 3 files changed, 128 insertions(+), 56 deletions(-)
 create mode 100644 handlers/RootFilePatternHandler.py

diff --git a/handlers/PrCheckerSummaryHandler.py b/handlers/PrCheckerSummaryHandler.py
index 58631b6c..8808fdd6 100644
--- a/handlers/PrCheckerSummaryHandler.py
+++ b/handlers/PrCheckerSummaryHandler.py
@@ -26,6 +26,7 @@ from ROOT import TStyle
 from ROOT import gPad
 from .BaseHandler import BaseHandler
 from .gaussValidation import grepPattern
+from .RootFilePatternHandler import RootFilePatternHandler
 from collectRunResults import urlopen
 import logging
 import subprocess
@@ -33,7 +34,10 @@ import subprocess
 from collections import defaultdict
 
 
-def effPlotsDict_long():
+def effPlotsDict_long(inputfile):
+    type = "long"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -43,15 +47,15 @@ def effPlotsDict_long():
     }
 
     basedict["Pt"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_Pt"
+        "path"] = "Track/"+matching_path+"/BestLong/01_long_Pt"
     basedict["P"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_P"
+        "path"] = "Track/"+matching_path+"/BestLong/01_long_P"
     basedict["Eta"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_Eta"
+        "path"] = "Track/"+matching_path+"/BestLong/01_long_Eta"
     basedict["nPV"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_nPV"
+        "path"] = "Track/"+matching_path+"/BestLong/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_docaz"
+        "path"] = "Track/"+matching_path+"/BestLong/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -69,7 +73,10 @@ def getEffPlots_long():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_down():
+def effPlotsDict_down(inputfile):
+    type = "down"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -79,15 +86,15 @@ def effPlotsDict_down():
     }
 
     basedict["Pt"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_Pt"
+        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_Pt"
     basedict["P"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_P"
+        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_P"
     basedict["Eta"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_Eta"
+        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_Eta"
     basedict["nPV"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_nPV"
+        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_nPV"
     basedict["docaz"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_docaz"
+        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -105,7 +112,10 @@ def getEffPlots_down():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_forward():
+def effPlotsDict_forward(inputfile):
+    type = "forward"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -115,15 +125,15 @@ def effPlotsDict_forward():
     }
 
     basedict["Pt"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_Pt"
+        "path"] = "Track/"+matching_path+"/Forward/01_long_Pt"
     basedict["P"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_P"
+        "path"] = "Track/"+matching_path+"/Forward/01_long_P"
     basedict["Eta"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_Eta"
+        "path"] = "Track/"+matching_path+"/Forward/01_long_Eta"
     basedict["nPV"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_nPV"
+        "path"] = "Track/"+matching_path+"/Forward/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_docaz"
+        "path"] = "Track/"+matching_path+"/Forward/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -141,7 +151,10 @@ def getEffPlots_forward():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_velo():
+def effPlotsDict_velo(inputfile):
+    type = "velo"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -151,15 +164,15 @@ def effPlotsDict_velo():
     }
 
     basedict["Pt"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_Pt"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Pt"
     basedict["P"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_P"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_P"
     basedict["Eta"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_Eta"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Eta"
     basedict["nPV"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_nPV"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_nPV"
     basedict["docaz"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_docaz"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -177,7 +190,10 @@ def getEffPlots_velo():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_ttrack():
+def effPlotsDict_ttrack(inputfile):
+    type = "ttrack"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -186,14 +202,14 @@ def effPlotsDict_ttrack():
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_Pt"
-    basedict["P"]["path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_P"
+    basedict["Pt"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_Pt"
+    basedict["P"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_P"
     basedict["Eta"][
-        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_Eta"
+        "path"] = "Track/"+matching_path+"/Seed/01_hasT_Eta"
     basedict["nPV"][
-        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_nPV"
+        "path"] = "Track/"+matching_path+"/Seed/01_hasT_nPV"
     basedict["docaz"][
-        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_docaz"
+        "path"] = "Track/"+matching_path+"/Seed/01_hasT_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -236,6 +252,7 @@ class PrCheckerSummaryHandler(BaseHandler):
 		)
                 """
         inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
+        inputfile_path=os.path.join(directory, rootfile)
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
@@ -254,15 +271,15 @@ class PrCheckerSummaryHandler(BaseHandler):
         outputfile.mkdir('ttrack')
 
         effPlots_long = getEffPlots_long()
-        eff_dict_long = effPlotsDict_long()
+        eff_dict_long = effPlotsDict_long(inputfile_path)
         effPlots_down = getEffPlots_down()
-        eff_dict_down = effPlotsDict_down()
+        eff_dict_down = effPlotsDict_down(inputfile_path)
         effPlots_forward = getEffPlots_forward()
-        eff_dict_forward = effPlotsDict_forward()
+        eff_dict_forward = effPlotsDict_forward(inputfile_path)
         effPlots_velo = getEffPlots_velo()
-        eff_dict_velo = effPlotsDict_velo()
+        eff_dict_velo = effPlotsDict_velo(inputfile_path)
         effPlots_ttrack = getEffPlots_ttrack()
-        eff_dict_ttrack = effPlotsDict_ttrack()
+        eff_dict_ttrack = effPlotsDict_ttrack(inputfile_path)
 
         for effPlot in effPlots_long:
             outputfile.cd("long")
diff --git a/handlers/PrCheckerSummaryHandler_withoutUT.py b/handlers/PrCheckerSummaryHandler_withoutUT.py
index 5e534ca2..05545219 100644
--- a/handlers/PrCheckerSummaryHandler_withoutUT.py
+++ b/handlers/PrCheckerSummaryHandler_withoutUT.py
@@ -22,6 +22,7 @@ from ROOT import TStyle
 from ROOT import gPad
 from .BaseHandler import BaseHandler
 from .gaussValidation import grepPattern
+from .RootFilePatternHandler import RootFilePatternHandler
 from collectRunResults import urlopen
 import logging
 import subprocess
@@ -29,7 +30,10 @@ import subprocess
 from collections import defaultdict
 
 
-def effPlotsDict_long():
+def effPlotsDict_long(inputfile):
+    type = "long"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -38,12 +42,12 @@ def effPlotsDict_long():
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_Pt"
-    basedict["P"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_P"
-    basedict["Eta"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_Eta"
-    basedict["nPV"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_nPV"
+    basedict["Pt"]["path"] = "Track/"+matching_path+"/BestLong/01_long_Pt"
+    basedict["P"]["path"] = "Track/"+matching_path+"/BestLong/01_long_P"
+    basedict["Eta"]["path"] = "Track/"+matching_path+"/BestLong/01_long_Eta"
+    basedict["nPV"]["path"] = "Track/"+matching_path+"/BestLong/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_docaz"
+        "path"] = "Track/"+matching_path+"/BestLong/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -61,7 +65,10 @@ def getEffPlots_long():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_velo():
+def effPlotsDict_velo(inputfile):
+    type = "velo"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -71,15 +78,15 @@ def effPlotsDict_velo():
     }
 
     basedict["Pt"][
-        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_Pt"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Pt"
     basedict["P"][
-        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_P"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_P"
     basedict["Eta"][
-        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_Eta"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Eta"
     basedict["nPV"][
-        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_nPV"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_nPV"
     basedict["docaz"][
-        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_docaz"
+        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -97,7 +104,10 @@ def getEffPlots_velo():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_ttrack():
+def effPlotsDict_ttrack(inputfile):
+    type = "ttrack"
+    parser = RootFilePatternHandler(inputfile)
+    matching_path = parser.get_matching_paths_TrackChecker(type)
     basedict = {
         "Pt": {},
         "P": {},
@@ -106,11 +116,11 @@ def effPlotsDict_ttrack():
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_Pt"
-    basedict["P"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_P"
-    basedict["Eta"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_Eta"
-    basedict["nPV"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_nPV"
-    basedict["docaz"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_docaz"
+    basedict["Pt"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_Pt"
+    basedict["P"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_P"
+    basedict["Eta"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_Eta"
+    basedict["nPV"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_nPV"
+    basedict["docaz"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -154,6 +164,7 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
         """
 
         inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
+        inputfile_path=os.path.join(directory, rootfile)
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
@@ -170,11 +181,11 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
         outputfile.mkdir('ttrack')
 
         effPlots_long = getEffPlots_long()
-        eff_dict_long = effPlotsDict_long()
+        eff_dict_long = effPlotsDict_long(inputfile_path)
         effPlots_velo = getEffPlots_velo()
-        eff_dict_velo = effPlotsDict_velo()
+        eff_dict_velo = effPlotsDict_velo(inputfile_path)
         effPlots_ttrack = getEffPlots_ttrack()
-        eff_dict_ttrack = effPlotsDict_ttrack()
+        eff_dict_ttrack = effPlotsDict_ttrack(inputfile_path)
 
         for effPlot in effPlots_long:
             outputfile.cd("long")
diff --git a/handlers/RootFilePatternHandler.py b/handlers/RootFilePatternHandler.py
new file mode 100644
index 00000000..70e43fe0
--- /dev/null
+++ b/handlers/RootFilePatternHandler.py
@@ -0,0 +1,44 @@
+import ROOT
+import re
+#Find 
+class RootFilePatternHandler:
+
+    """This class is used to match the path inside the input rootfile with certain track type. 
+    Currently, there are hash codes at the end of some dictionary names, making it difficult 
+    for other handlers to get the correct path. This class aim to solve it by using wildcard, 
+    e.g. check if the path contains specified pattern, then return the correct path."""
+
+    def __init__(self, root_file):
+        self.root_file = root_file
+        # Match tracktype with pattern in the path
+        self.mapping_TrackChecker = {
+        'long': 'BestLongTrackChecker',
+        'down': 'BestDownstreamTrackChecker',
+        'forward': 'ForwardTrackChecker',
+        'ttrack': 'SeedTrackChecker',
+        'velo':'VeloFullTrackChecker'
+        }
+        self.path_Track="Track"
+
+    def get_matching_paths_TrackChecker(self, type):
+        matching_paths = []
+        pattern = self.mapping_TrackChecker[type]
+
+        # Open the ROOT file
+        file = ROOT.TFile(self.root_file)
+        target_path = file.Get(self.path_Track)
+
+        # Get the list of keys (objects) in the dictionary
+        dics = target_path.GetListOfKeys()
+
+        # Iterate over the keys and extract dictionaries
+        for dic in dics:
+            # Check if the path contains the specified pattern
+            if re.search(pattern, dic.GetTitle()):
+                matching_paths.append(dic.GetTitle())
+
+        # Close the file
+        file.Close()
+
+        return str(matching_paths[0])
+
-- 
GitLab


From 3a83b1f95d8c3db6dae83ff481b4b2a10d5c9059 Mon Sep 17 00:00:00 2001
From: Xueting Yang <xueting.yang@cern.ch>
Date: Thu, 15 Jun 2023 15:57:35 +0200
Subject: [PATCH 2/9] Update RootFilePatternHandler.py

---
 handlers/RootFilePatternHandler.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/handlers/RootFilePatternHandler.py b/handlers/RootFilePatternHandler.py
index 70e43fe0..53f65325 100644
--- a/handlers/RootFilePatternHandler.py
+++ b/handlers/RootFilePatternHandler.py
@@ -1,6 +1,6 @@
 import ROOT
 import re
-#Find 
+
 class RootFilePatternHandler:
 
     """This class is used to match the path inside the input rootfile with certain track type. 
-- 
GitLab


From 6f326ce23573e8e22d423a443c208f51fb48ce00 Mon Sep 17 00:00:00 2001
From: xueting <xueting.yang@cern.ch>
Date: Mon, 17 Jul 2023 16:45:28 +0800
Subject: [PATCH 3/9] hash_remove_handler

---
 handlers/HashRemoveHandler.py | 75 +++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)
 create mode 100644 handlers/HashRemoveHandler.py

diff --git a/handlers/HashRemoveHandler.py b/handlers/HashRemoveHandler.py
new file mode 100644
index 00000000..2dd52221
--- /dev/null
+++ b/handlers/HashRemoveHandler.py
@@ -0,0 +1,75 @@
+import ROOT
+import re
+
+class HashRemoveHandler:
+
+    """This class is used to remove the hash code at the end of the directory names of a rootfile. 
+    Hash code is judged by un underline and 8 random characters e.g."_(\w{8})$". """
+        
+    def __init__(self, input_file_path, output_file_path):
+        self.input_file_path = input_file_path
+        self.output_file_path = output_file_path
+
+    def process_directory(self, old_dir, new_parent_dir, subdir_counts=None):
+        if subdir_counts is None:
+            subdir_counts = {}
+        new_dir_name = self.remove_hashcode(old_dir.GetName())
+        subdir_counts[new_dir_name] = subdir_counts.get(new_dir_name, 0) + 1
+        variant = subdir_counts[new_dir_name]
+        if variant > 1:
+            new_dir_name += "_variant" + str(variant)
+        if new_dir_name != self.input_file_path:
+            new_dir = new_parent_dir.mkdir(new_dir_name)
+        if new_dir_name == self.input_file_path:
+            new_dir = new_parent_dir
+
+        for key in old_dir.GetListOfKeys():
+            obj = key.ReadObj()
+            if isinstance(obj, ROOT.TDirectory):
+                self.process_directory(obj, new_dir, subdir_counts)
+            elif isinstance(obj, ROOT.TH1):
+                new_dir.cd()
+                histogram = obj.Clone()
+                histogram.Write()
+
+    def remove_hashcode(self, directory_name):
+        # Remove hash code at the end of the directory name
+        pattern = r"_(\w{8})$"
+        match = re.search(pattern, directory_name)
+        if match:
+            return directory_name[:match.start()]
+        return directory_name
+
+    def modify_root_file(self):
+        ROOT.gROOT.SetBatch(True)  # Enable batch mode to suppress graphics
+
+        # Open the original ROOT file
+        input_file = ROOT.TFile.Open(self.input_file_path)
+        if input_file is None or input_file.IsZombie():
+            print("Error: Failed to open the original file '{}'".format(self.input_file_path))
+            return
+
+        # Create a new ROOT file to save the modified directory structure
+        output_file = ROOT.TFile(self.output_file_path, "RECREATE")
+        if output_file.IsZombie():
+            print("Error: Failed to create the new file '{}'".format(self.output_file_path))
+            return
+
+        # Process the directories recursively
+        root_dir = input_file.GetDirectory("/")
+        self.process_directory(root_dir, output_file)
+
+        # Write and close the new ROOT file
+        output_file.Write()
+        output_file.Close()
+
+        # Close the original ROOT file
+        input_file.Close()
+
+        ROOT.gROOT.SetBatch(False)  # Disable batch mode
+
+
+# Example usage
+#modifier = HashRemoveHandler("old_file.root", "new_file.root")
+#modifier.modify_root_file()
+
-- 
GitLab


From c5c96beed54e3d1c16fc2064c6ef6b3e1f30798b Mon Sep 17 00:00:00 2001
From: Xueting Yang <xueting.yang@cern.ch>
Date: Tue, 18 Jul 2023 17:39:40 +0200
Subject: [PATCH 4/9] Update HashRemoveHandler.py, put the example usage below
 the general class description

---
 handlers/HashRemoveHandler.py | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/handlers/HashRemoveHandler.py b/handlers/HashRemoveHandler.py
index 2dd52221..df980de8 100644
--- a/handlers/HashRemoveHandler.py
+++ b/handlers/HashRemoveHandler.py
@@ -5,6 +5,9 @@ class HashRemoveHandler:
 
     """This class is used to remove the hash code at the end of the directory names of a rootfile. 
     Hash code is judged by un underline and 8 random characters e.g."_(\w{8})$". """
+    # Example usage
+    # modifier = HashRemoveHandler("old_file.root", "new_file.root")
+    # modifier.modify_root_file()
         
     def __init__(self, input_file_path, output_file_path):
         self.input_file_path = input_file_path
@@ -68,8 +71,3 @@ class HashRemoveHandler:
 
         ROOT.gROOT.SetBatch(False)  # Disable batch mode
 
-
-# Example usage
-#modifier = HashRemoveHandler("old_file.root", "new_file.root")
-#modifier.modify_root_file()
-
-- 
GitLab


From a506edbb56419ceb8d88dbd46c986031621378a2 Mon Sep 17 00:00:00 2001
From: xueting <xueting.yang@cern.ch>
Date: Tue, 18 Jul 2023 23:58:16 +0800
Subject: [PATCH 5/9] revert previous commit

---
 handlers/PrCheckerSummaryHandler.py           | 87 ++++++++-----------
 handlers/PrCheckerSummaryHandler_withoutUT.py | 53 +++++------
 handlers/RootFilePatternHandler.py            | 44 ----------
 3 files changed, 56 insertions(+), 128 deletions(-)
 delete mode 100644 handlers/RootFilePatternHandler.py

diff --git a/handlers/PrCheckerSummaryHandler.py b/handlers/PrCheckerSummaryHandler.py
index 8808fdd6..58631b6c 100644
--- a/handlers/PrCheckerSummaryHandler.py
+++ b/handlers/PrCheckerSummaryHandler.py
@@ -26,7 +26,6 @@ from ROOT import TStyle
 from ROOT import gPad
 from .BaseHandler import BaseHandler
 from .gaussValidation import grepPattern
-from .RootFilePatternHandler import RootFilePatternHandler
 from collectRunResults import urlopen
 import logging
 import subprocess
@@ -34,10 +33,7 @@ import subprocess
 from collections import defaultdict
 
 
-def effPlotsDict_long(inputfile):
-    type = "long"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_long():
     basedict = {
         "Pt": {},
         "P": {},
@@ -47,15 +43,15 @@ def effPlotsDict_long(inputfile):
     }
 
     basedict["Pt"][
-        "path"] = "Track/"+matching_path+"/BestLong/01_long_Pt"
+        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_Pt"
     basedict["P"][
-        "path"] = "Track/"+matching_path+"/BestLong/01_long_P"
+        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_P"
     basedict["Eta"][
-        "path"] = "Track/"+matching_path+"/BestLong/01_long_Eta"
+        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_Eta"
     basedict["nPV"][
-        "path"] = "Track/"+matching_path+"/BestLong/01_long_nPV"
+        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/BestLong/01_long_docaz"
+        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -73,10 +69,7 @@ def getEffPlots_long():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_down(inputfile):
-    type = "down"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_down():
     basedict = {
         "Pt": {},
         "P": {},
@@ -86,15 +79,15 @@ def effPlotsDict_down(inputfile):
     }
 
     basedict["Pt"][
-        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_Pt"
+        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_Pt"
     basedict["P"][
-        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_P"
+        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_P"
     basedict["Eta"][
-        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_Eta"
+        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_Eta"
     basedict["nPV"][
-        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_nPV"
+        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/BestDownstream/01_UT+T_docaz"
+        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -112,10 +105,7 @@ def getEffPlots_down():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_forward(inputfile):
-    type = "forward"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_forward():
     basedict = {
         "Pt": {},
         "P": {},
@@ -125,15 +115,15 @@ def effPlotsDict_forward(inputfile):
     }
 
     basedict["Pt"][
-        "path"] = "Track/"+matching_path+"/Forward/01_long_Pt"
+        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_Pt"
     basedict["P"][
-        "path"] = "Track/"+matching_path+"/Forward/01_long_P"
+        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_P"
     basedict["Eta"][
-        "path"] = "Track/"+matching_path+"/Forward/01_long_Eta"
+        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_Eta"
     basedict["nPV"][
-        "path"] = "Track/"+matching_path+"/Forward/01_long_nPV"
+        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/Forward/01_long_docaz"
+        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -151,10 +141,7 @@ def getEffPlots_forward():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_velo(inputfile):
-    type = "velo"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_velo():
     basedict = {
         "Pt": {},
         "P": {},
@@ -164,15 +151,15 @@ def effPlotsDict_velo(inputfile):
     }
 
     basedict["Pt"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Pt"
+        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_Pt"
     basedict["P"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_P"
+        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_P"
     basedict["Eta"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Eta"
+        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_Eta"
     basedict["nPV"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_nPV"
+        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_docaz"
+        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -190,10 +177,7 @@ def getEffPlots_velo():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_ttrack(inputfile):
-    type = "ttrack"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_ttrack():
     basedict = {
         "Pt": {},
         "P": {},
@@ -202,14 +186,14 @@ def effPlotsDict_ttrack(inputfile):
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_Pt"
-    basedict["P"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_P"
+    basedict["Pt"]["path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_Pt"
+    basedict["P"]["path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_P"
     basedict["Eta"][
-        "path"] = "Track/"+matching_path+"/Seed/01_hasT_Eta"
+        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_Eta"
     basedict["nPV"][
-        "path"] = "Track/"+matching_path+"/Seed/01_hasT_nPV"
+        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/Seed/01_hasT_docaz"
+        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -252,7 +236,6 @@ class PrCheckerSummaryHandler(BaseHandler):
 		)
                 """
         inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
-        inputfile_path=os.path.join(directory, rootfile)
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
@@ -271,15 +254,15 @@ class PrCheckerSummaryHandler(BaseHandler):
         outputfile.mkdir('ttrack')
 
         effPlots_long = getEffPlots_long()
-        eff_dict_long = effPlotsDict_long(inputfile_path)
+        eff_dict_long = effPlotsDict_long()
         effPlots_down = getEffPlots_down()
-        eff_dict_down = effPlotsDict_down(inputfile_path)
+        eff_dict_down = effPlotsDict_down()
         effPlots_forward = getEffPlots_forward()
-        eff_dict_forward = effPlotsDict_forward(inputfile_path)
+        eff_dict_forward = effPlotsDict_forward()
         effPlots_velo = getEffPlots_velo()
-        eff_dict_velo = effPlotsDict_velo(inputfile_path)
+        eff_dict_velo = effPlotsDict_velo()
         effPlots_ttrack = getEffPlots_ttrack()
-        eff_dict_ttrack = effPlotsDict_ttrack(inputfile_path)
+        eff_dict_ttrack = effPlotsDict_ttrack()
 
         for effPlot in effPlots_long:
             outputfile.cd("long")
diff --git a/handlers/PrCheckerSummaryHandler_withoutUT.py b/handlers/PrCheckerSummaryHandler_withoutUT.py
index 05545219..5e534ca2 100644
--- a/handlers/PrCheckerSummaryHandler_withoutUT.py
+++ b/handlers/PrCheckerSummaryHandler_withoutUT.py
@@ -22,7 +22,6 @@ from ROOT import TStyle
 from ROOT import gPad
 from .BaseHandler import BaseHandler
 from .gaussValidation import grepPattern
-from .RootFilePatternHandler import RootFilePatternHandler
 from collectRunResults import urlopen
 import logging
 import subprocess
@@ -30,10 +29,7 @@ import subprocess
 from collections import defaultdict
 
 
-def effPlotsDict_long(inputfile):
-    type = "long"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_long():
     basedict = {
         "Pt": {},
         "P": {},
@@ -42,12 +38,12 @@ def effPlotsDict_long(inputfile):
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/"+matching_path+"/BestLong/01_long_Pt"
-    basedict["P"]["path"] = "Track/"+matching_path+"/BestLong/01_long_P"
-    basedict["Eta"]["path"] = "Track/"+matching_path+"/BestLong/01_long_Eta"
-    basedict["nPV"]["path"] = "Track/"+matching_path+"/BestLong/01_long_nPV"
+    basedict["Pt"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_Pt"
+    basedict["P"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_P"
+    basedict["Eta"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_Eta"
+    basedict["nPV"]["path"] = "Track/BestLongTrackChecker/BestLong/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/BestLong/01_long_docaz"
+        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -65,10 +61,7 @@ def getEffPlots_long():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_velo(inputfile):
-    type = "velo"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_velo():
     basedict = {
         "Pt": {},
         "P": {},
@@ -78,15 +71,15 @@ def effPlotsDict_velo(inputfile):
     }
 
     basedict["Pt"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Pt"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_Pt"
     basedict["P"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_P"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_P"
     basedict["Eta"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_Eta"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_Eta"
     basedict["nPV"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_nPV"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_nPV"
     basedict["docaz"][
-        "path"] = "Track/"+matching_path+"/VeloFull/01_notElectron_Velo_docaz"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -104,10 +97,7 @@ def getEffPlots_velo():
     return ["Pt", "P", "Eta", "nPV", "docaz"]
 
 
-def effPlotsDict_ttrack(inputfile):
-    type = "ttrack"
-    parser = RootFilePatternHandler(inputfile)
-    matching_path = parser.get_matching_paths_TrackChecker(type)
+def effPlotsDict_ttrack():
     basedict = {
         "Pt": {},
         "P": {},
@@ -116,11 +106,11 @@ def effPlotsDict_ttrack(inputfile):
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_Pt"
-    basedict["P"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_P"
-    basedict["Eta"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_Eta"
-    basedict["nPV"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_nPV"
-    basedict["docaz"]["path"] = "Track/"+matching_path+"/Seed/01_hasT_docaz"
+    basedict["Pt"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_Pt"
+    basedict["P"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_P"
+    basedict["Eta"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_Eta"
+    basedict["nPV"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_nPV"
+    basedict["docaz"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -164,7 +154,6 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
         """
 
         inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
-        inputfile_path=os.path.join(directory, rootfile)
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
@@ -181,11 +170,11 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
         outputfile.mkdir('ttrack')
 
         effPlots_long = getEffPlots_long()
-        eff_dict_long = effPlotsDict_long(inputfile_path)
+        eff_dict_long = effPlotsDict_long()
         effPlots_velo = getEffPlots_velo()
-        eff_dict_velo = effPlotsDict_velo(inputfile_path)
+        eff_dict_velo = effPlotsDict_velo()
         effPlots_ttrack = getEffPlots_ttrack()
-        eff_dict_ttrack = effPlotsDict_ttrack(inputfile_path)
+        eff_dict_ttrack = effPlotsDict_ttrack()
 
         for effPlot in effPlots_long:
             outputfile.cd("long")
diff --git a/handlers/RootFilePatternHandler.py b/handlers/RootFilePatternHandler.py
deleted file mode 100644
index 53f65325..00000000
--- a/handlers/RootFilePatternHandler.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import ROOT
-import re
-
-class RootFilePatternHandler:
-
-    """This class is used to match the path inside the input rootfile with certain track type. 
-    Currently, there are hash codes at the end of some dictionary names, making it difficult 
-    for other handlers to get the correct path. This class aim to solve it by using wildcard, 
-    e.g. check if the path contains specified pattern, then return the correct path."""
-
-    def __init__(self, root_file):
-        self.root_file = root_file
-        # Match tracktype with pattern in the path
-        self.mapping_TrackChecker = {
-        'long': 'BestLongTrackChecker',
-        'down': 'BestDownstreamTrackChecker',
-        'forward': 'ForwardTrackChecker',
-        'ttrack': 'SeedTrackChecker',
-        'velo':'VeloFullTrackChecker'
-        }
-        self.path_Track="Track"
-
-    def get_matching_paths_TrackChecker(self, type):
-        matching_paths = []
-        pattern = self.mapping_TrackChecker[type]
-
-        # Open the ROOT file
-        file = ROOT.TFile(self.root_file)
-        target_path = file.Get(self.path_Track)
-
-        # Get the list of keys (objects) in the dictionary
-        dics = target_path.GetListOfKeys()
-
-        # Iterate over the keys and extract dictionaries
-        for dic in dics:
-            # Check if the path contains the specified pattern
-            if re.search(pattern, dic.GetTitle()):
-                matching_paths.append(dic.GetTitle())
-
-        # Close the file
-        file.Close()
-
-        return str(matching_paths[0])
-
-- 
GitLab


From ee2955d6df0432a3e9038618275db2546f4dfdcd Mon Sep 17 00:00:00 2001
From: xueting <xueting.yang@cern.ch>
Date: Wed, 19 Jul 2023 01:13:19 +0800
Subject: [PATCH 6/9] use original paths

---
 handlers/PrCheckerSummaryHandler.py           | 55 ++++++++++---------
 handlers/PrCheckerSummaryHandler_withoutUT.py |  5 +-
 2 files changed, 33 insertions(+), 27 deletions(-)

diff --git a/handlers/PrCheckerSummaryHandler.py b/handlers/PrCheckerSummaryHandler.py
index 58631b6c..7f30bc6f 100644
--- a/handlers/PrCheckerSummaryHandler.py
+++ b/handlers/PrCheckerSummaryHandler.py
@@ -26,6 +26,7 @@ from ROOT import TStyle
 from ROOT import gPad
 from .BaseHandler import BaseHandler
 from .gaussValidation import grepPattern
+from .HashRemoveHandler import HashRemoveHandler
 from collectRunResults import urlopen
 import logging
 import subprocess
@@ -43,15 +44,15 @@ def effPlotsDict_long():
     }
 
     basedict["Pt"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_Pt"
+        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_Pt"
     basedict["P"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_P"
+        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_P"
     basedict["Eta"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_Eta"
+        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_Eta"
     basedict["nPV"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_nPV"
+        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/BestLongTrackChecker_2b1808e5/BestLong/01_long_docaz"
+        "path"] = "Track/BestLongTrackChecker/BestLong/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -79,15 +80,15 @@ def effPlotsDict_down():
     }
 
     basedict["Pt"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_Pt"
+        "path"] = "Track/BestDownstreamTrackChecker/BestDownstream/01_UT+T_Pt"
     basedict["P"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_P"
+        "path"] = "Track/BestDownstreamTrackChecker/BestDownstream/01_UT+T_P"
     basedict["Eta"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_Eta"
+        "path"] = "Track/BestDownstreamTrackChecker/BestDownstream/01_UT+T_Eta"
     basedict["nPV"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_nPV"
+        "path"] = "Track/BestDownstreamTrackChecker/BestDownstream/01_UT+T_nPV"
     basedict["docaz"][
-        "path"] = "Track/BestDownstreamTrackChecker_16cf5e80/BestDownstream/01_UT+T_docaz"
+        "path"] = "Track/BestDownstreamTrackChecker/BestDownstream/01_UT+T_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -115,15 +116,15 @@ def effPlotsDict_forward():
     }
 
     basedict["Pt"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_Pt"
+        "path"] = "Track/ForwardTrackChecker/Forward/01_long_Pt"
     basedict["P"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_P"
+        "path"] = "Track/ForwardTrackChecker/Forward/01_long_P"
     basedict["Eta"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_Eta"
+        "path"] = "Track/ForwardTrackChecker/Forward/01_long_Eta"
     basedict["nPV"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_nPV"
+        "path"] = "Track/ForwardTrackChecker/Forward/01_long_nPV"
     basedict["docaz"][
-        "path"] = "Track/ForwardTrackChecker_38a3d1fd/Forward/01_long_docaz"
+        "path"] = "Track/ForwardTrackChecker/Forward/01_long_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -151,15 +152,15 @@ def effPlotsDict_velo():
     }
 
     basedict["Pt"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_Pt"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_Pt"
     basedict["P"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_P"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_P"
     basedict["Eta"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_Eta"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_Eta"
     basedict["nPV"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_nPV"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_nPV"
     basedict["docaz"][
-        "path"] = "Track/VeloFullTrackChecker_b448179f/VeloFull/01_notElectron_Velo_docaz"
+        "path"] = "Track/VeloFullTrackChecker/VeloFull/01_notElectron_Velo_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -186,14 +187,14 @@ def effPlotsDict_ttrack():
         "docaz": {},
     }
 
-    basedict["Pt"]["path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_Pt"
-    basedict["P"]["path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_P"
+    basedict["Pt"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_Pt"
+    basedict["P"]["path"] = "Track/SeedTrackChecker/Seed/01_hasT_P"
     basedict["Eta"][
-        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_Eta"
+        "path"] = "Track/SeedTrackChecker/Seed/01_hasT_Eta"
     basedict["nPV"][
-        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_nPV"
+        "path"] = "Track/SeedTrackChecker/Seed/01_hasT_nPV"
     basedict["docaz"][
-        "path"] = "Track/SeedTrackChecker_6f38a9cb/Seed/01_hasT_docaz"
+        "path"] = "Track/SeedTrackChecker/Seed/01_hasT_docaz"
     basedict["Pt"]["unit"] = "pT [MeV]"
     basedict["P"]["unit"] = "p [MeV]"
     basedict["Eta"]["unit"] = "#eta [-]"
@@ -235,7 +236,9 @@ class PrCheckerSummaryHandler(BaseHandler):
 			shell=True
 		)
                 """
-        inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
+        modifier = HashRemoveHandler(os.path.join(directory, rootfile), "new_file.root")
+        modifier.modify_root_file()
+        inputfile = ROOT.TFile.Open("new_file.root", 'read')
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
diff --git a/handlers/PrCheckerSummaryHandler_withoutUT.py b/handlers/PrCheckerSummaryHandler_withoutUT.py
index 5e534ca2..787e9daf 100644
--- a/handlers/PrCheckerSummaryHandler_withoutUT.py
+++ b/handlers/PrCheckerSummaryHandler_withoutUT.py
@@ -22,6 +22,7 @@ from ROOT import TStyle
 from ROOT import gPad
 from .BaseHandler import BaseHandler
 from .gaussValidation import grepPattern
+from .HashRemoveHandler import HashRemoveHandler
 from collectRunResults import urlopen
 import logging
 import subprocess
@@ -153,7 +154,9 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
         )
         """
 
-        inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
+        modifier = HashRemoveHandler(os.path.join(directory, rootfile), "new_file.root")
+        modifier.modify_root_file()
+        inputfile = ROOT.TFile.Open("new_file.root", 'read')
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
-- 
GitLab


From a7ee38ad1c9db523b608efe8922f0e7e9bf8bab6 Mon Sep 17 00:00:00 2001
From: Xueting Yang <xueting.yang@cern.ch>
Date: Wed, 19 Jul 2023 15:07:38 +0200
Subject: [PATCH 7/9] Update PrCheckerSummaryHandler.py, rename the new file
 it's original name

---
 handlers/PrCheckerSummaryHandler.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/handlers/PrCheckerSummaryHandler.py b/handlers/PrCheckerSummaryHandler.py
index 7f30bc6f..f87ffad8 100644
--- a/handlers/PrCheckerSummaryHandler.py
+++ b/handlers/PrCheckerSummaryHandler.py
@@ -236,9 +236,11 @@ class PrCheckerSummaryHandler(BaseHandler):
 			shell=True
 		)
                 """
+        # remove hash code
         modifier = HashRemoveHandler(os.path.join(directory, rootfile), "new_file.root")
         modifier.modify_root_file()
-        inputfile = ROOT.TFile.Open("new_file.root", 'read')
+        os.rename("new_file.root",os.path.join(directory, rootfile))
+        inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
-- 
GitLab


From 62c23fa3c24ca2e3438771b76895a93e3a86b28b Mon Sep 17 00:00:00 2001
From: Xueting Yang <xueting.yang@cern.ch>
Date: Wed, 19 Jul 2023 15:10:34 +0200
Subject: [PATCH 8/9] Update PrCheckerSummaryHandler_withoutUT.py, rename the
 new file to it's original name

---
 handlers/PrCheckerSummaryHandler_withoutUT.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/handlers/PrCheckerSummaryHandler_withoutUT.py b/handlers/PrCheckerSummaryHandler_withoutUT.py
index 787e9daf..55c1aad3 100644
--- a/handlers/PrCheckerSummaryHandler_withoutUT.py
+++ b/handlers/PrCheckerSummaryHandler_withoutUT.py
@@ -153,10 +153,11 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
             shell=True
         )
         """
-
+        # remove hash code
         modifier = HashRemoveHandler(os.path.join(directory, rootfile), "new_file.root")
         modifier.modify_root_file()
-        inputfile = ROOT.TFile.Open("new_file.root", 'read')
+        os.rename("new_file.root",os.path.join(directory, rootfile))
+        inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
-- 
GitLab


From db5c874ea454f61ee72d611d1fd420c7e166407d Mon Sep 17 00:00:00 2001
From: xueting <xueting.yang@cern.ch>
Date: Wed, 2 Aug 2023 11:01:31 +0800
Subject: [PATCH 9/9] debug_and_modification

---
 handlers/HashRemoveHandler.py                 | 36 +++++++++++++------
 handlers/PrCheckerSummaryHandler.py           |  4 +--
 handlers/PrCheckerSummaryHandler_withoutUT.py |  4 +--
 3 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/handlers/HashRemoveHandler.py b/handlers/HashRemoveHandler.py
index df980de8..72e5290d 100644
--- a/handlers/HashRemoveHandler.py
+++ b/handlers/HashRemoveHandler.py
@@ -1,24 +1,31 @@
 import ROOT
 import re
+import tempfile
+import os
+import shutil
 
 class HashRemoveHandler:
 
     """This class is used to remove the hash code at the end of the directory names of a rootfile. 
-    Hash code is judged by un underline and 8 random characters e.g."_(\w{8})$". """
+    Hash code is judged by an underline and 8 random characters e.g."_(\w{8})$". 
+    If both input_file_path and output_file_path are provided, modified file will be saved in output_file_path;
+    If only input_file_path is provided, modified file will replace the old file"""
     # Example usage
-    # modifier = HashRemoveHandler("old_file.root", "new_file.root")
+    # modifier = HashRemoveHandler("old_file.root", "new_file.root") or modifier = HashRemoveHandler("old_file.root")
     # modifier.modify_root_file()
         
-    def __init__(self, input_file_path, output_file_path):
+    def __init__(self, input_file_path, output_file_path=None):
         self.input_file_path = input_file_path
         self.output_file_path = output_file_path
 
-    def process_directory(self, old_dir, new_parent_dir, subdir_counts=None):
+    def process_directory(self, old_dir, new_parent_dir, subdir_counts=None, parent_path=""):
         if subdir_counts is None:
             subdir_counts = {}
+        directory_path = "/".join(filter(None, [parent_path, old_dir.GetName()]))
         new_dir_name = self.remove_hashcode(old_dir.GetName())
-        subdir_counts[new_dir_name] = subdir_counts.get(new_dir_name, 0) + 1
-        variant = subdir_counts[new_dir_name]
+        complete_dir_name = self.remove_hashcode(directory_path)
+        subdir_counts[complete_dir_name] = subdir_counts.get(complete_dir_name, 0) + 1
+        variant = subdir_counts[complete_dir_name]
         if variant > 1:
             new_dir_name += "_variant" + str(variant)
         if new_dir_name != self.input_file_path:
@@ -29,7 +36,7 @@ class HashRemoveHandler:
         for key in old_dir.GetListOfKeys():
             obj = key.ReadObj()
             if isinstance(obj, ROOT.TDirectory):
-                self.process_directory(obj, new_dir, subdir_counts)
+                self.process_directory(obj, new_dir, subdir_counts, parent_path=directory_path)
             elif isinstance(obj, ROOT.TH1):
                 new_dir.cd()
                 histogram = obj.Clone()
@@ -52,8 +59,14 @@ class HashRemoveHandler:
             print("Error: Failed to open the original file '{}'".format(self.input_file_path))
             return
 
-        # Create a new ROOT file to save the modified directory structure
-        output_file = ROOT.TFile(self.output_file_path, "RECREATE")
+        if self.output_file_path is None:
+            # If the output_file_path is not provided, create a temporary file
+            tmp_output_file_path = os.path.join(tempfile.gettempdir(), "tmp_modified_file.root")
+            output_file = ROOT.TFile(tmp_output_file_path, "RECREATE")
+        else:
+            # If the output_file_path is provided, create a new ROOT file
+            output_file = ROOT.TFile(self.output_file_path, "RECREATE")
+
         if output_file.IsZombie():
             print("Error: Failed to create the new file '{}'".format(self.output_file_path))
             return
@@ -69,5 +82,8 @@ class HashRemoveHandler:
         # Close the original ROOT file
         input_file.Close()
 
-        ROOT.gROOT.SetBatch(False)  # Disable batch mode
+        if self.output_file_path is None:
+            # If the output_file_path is not provided, replace the original file with the temporary one
+            shutil.move(tmp_output_file_path, self.input_file_path)
 
+        ROOT.gROOT.SetBatch(False)  # Disable batch mode
diff --git a/handlers/PrCheckerSummaryHandler.py b/handlers/PrCheckerSummaryHandler.py
index 7f30bc6f..be53d93b 100644
--- a/handlers/PrCheckerSummaryHandler.py
+++ b/handlers/PrCheckerSummaryHandler.py
@@ -236,9 +236,9 @@ class PrCheckerSummaryHandler(BaseHandler):
 			shell=True
 		)
                 """
-        modifier = HashRemoveHandler(os.path.join(directory, rootfile), "new_file.root")
+        modifier = HashRemoveHandler(os.path.join(directory, rootfile))
         modifier.modify_root_file()
-        inputfile = ROOT.TFile.Open("new_file.root", 'read')
+        inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
diff --git a/handlers/PrCheckerSummaryHandler_withoutUT.py b/handlers/PrCheckerSummaryHandler_withoutUT.py
index 787e9daf..4fc4e068 100644
--- a/handlers/PrCheckerSummaryHandler_withoutUT.py
+++ b/handlers/PrCheckerSummaryHandler_withoutUT.py
@@ -154,9 +154,9 @@ class PrCheckerSummaryHandler_withoutUT(BaseHandler):
         )
         """
 
-        modifier = HashRemoveHandler(os.path.join(directory, rootfile), "new_file.root")
+        modifier = HashRemoveHandler(os.path.join(directory, rootfile))
         modifier.modify_root_file()
-        inputfile = ROOT.TFile.Open("new_file.root", 'read')
+        inputfile = ROOT.TFile.Open(os.path.join(directory, rootfile), 'read')
         outputfile = ROOT.TFile("PrCheckerSummary.root", "recreate")
 
         from .utils.LHCbStyle import setLHCbStyle
-- 
GitLab