Internal ROOT methods to split long TCut expression

Dear all,
I have a question which might be a bit naive.
Let’s say i have a very long TCut expression which is spitted out by some code which builds the chain logic of the cuts.
Is there any tool inside ROOT which is able to “re-decompose” the cut once build?
I basically would like to avoid to refactor our CutDefinition namespaces and the way we build the selection in our C++ classes and i was looking for some regular expression and parenthesis matching tool which is maybe used inside ROOT when a TCut is applied to the TTree.
I tried with splitting by && and || but the resulting string i get is not following anymore the cut logics we have, plus it gets polluted by many parenthesis which are hard to understand.

If there are no solution , probably i will follow the path of refactoring our code.

Thanks in advance
Renato

I am not sure tu understand what you are talking about. Can you give an example ?

Hi @couet :

Let’s say I get a a complex TCut expression like this :

((B0_BKGCAT == 0 || B0_BKGCAT == 10)||(B0_BKGCAT == 50))&&(((((((((nSPDHits < 600))&&((((E1_L0ElectronDecision_TOS)||(E2_L0ElectronDecision_TOS))&&(!(B0_L0Global_TIS)))))&&((((((((((((((E1_InAccEcal==1 && E2_InAccEcal==1)&&(TMath::Min(E1_L0Calo_ECAL_region,E2_L0Calo_ECAL_region) >= 0))&&(!((TMath::Abs(E1_L0Calo_ECAL_xProjection) < 363.6 && TMath::Abs(E1_L0Calo_ECAL_yProjection) < 282.6)||(TMath::Abs(E2_L0Calo_ECAL_xProjection) < 363.6 && TMath::Abs(E2_L0Calo_ECAL_yProjection) < 282.6))))&&(K_hasRich==1 && Pi_hasRich==1 && K_InAccMuon==1 && Pi_InAccMuon==1))&&(E1_hasRich==1 && E2_hasRich==1 && E1_hasCalo==1 && E2_hasCalo==1))&&(K_PT > 250 && Pi_PT > 250 && Pi_P > 2000 && K_P > 2000))&&(TMath::Min(E1_PT,E2_PT) > 500 && TMath::Min(E1_P,E2_P) > 3000))&&(Kst_PT > 500 && TMath::Min(K_IPCHI2_OWNPV,Pi_IPCHI2_OWNPV) > 9 ))&&(TMath::Min(E1_PT,E2_PT) > 300 && TMath::Min(E1_IPCHI2_OWNPV,E2_IPCHI2_OWNPV) > 9 && TMath::Min(TMath::Sqrt(TMath::Sq(E1_TRACK_PX)+TMath::Sq(E1_TRACK_PY)),TMath::Sqrt(TMath::Sq(E2_TRACK_PX)+TMath::Sq(E2_TRACK_PY))) > 200 && JPs_PT > 500))&&(TMath::Max(K_TRACK_CHI2NDOF,Pi_TRACK_CHI2NDOF) < 3 && TMath::Max(K_TRACK_GhostProb,Pi_TRACK_GhostProb) < 0.4))&&(TMath::Max(E1_TRACK_CHI2NDOF,E2_TRACK_CHI2NDOF) < 3 && TMath::Max(E1_TRACK_GhostProb,E2_TRACK_GhostProb) < 0.4))&&(L1L2_OA > 0.0005 && H1H2_OA > 0.0005 && L1H1_OA > 0.0005 && L1H2_OA > 0.0005 && L2H1_OA > 0.0005 && L2H2_OA > 0.0005))&&(TMath::Abs(Kst_M - 895.810000) < 100))&&((E1_L0ElectronDecision_TOS && E1_L0Calo_ECAL_realET > 2500 && !E2_L0ElectronDecision_TOS) || (E2_L0ElectronDecision_TOS && E2_L0Calo_ECAL_realET > 2500 && !E1_L0ElectronDecision_TOS) || (E1_L0ElectronDecision_TOS && E1_L0Calo_ECAL_realET > 2500 && E2_L0ElectronDecision_TOS && E2_L0Calo_ECAL_realET > 2500))))&&(((((TMath::Max(B0_M012,B0_M013_Subst3_pi2K) < 5100)&&(!(B0_M23_Subst3_pi2K < 1040 && Pi_MC12TuneV2_ProbNNpi_Meerkat < 0.8)))&&(!((TMath::Abs(B0_TRACK_M_Subst_Kl2lK_DTF_JPs - 5279.580000) < 60 && E1_MC12TuneV3_ProbNNe_Meerkat < 0.8) || (TMath::Abs(B0_TRACK_M_Subst_lpi2pil_DTF_JPs - 5279.580000) < 60 && E2_MC12TuneV3_ProbNNe_Meerkat < 0.8))))&&(!((TMath::Abs(B0_TRACK_M_Subst_Kl2lK_DTF_Psi - 5279.580000) < 60 && E1_MC12TuneV3_ProbNNe_Meerkat < 0.8) || (TMath::Abs(B0_TRACK_M_Subst_lpi2pil_DTF_Psi - 5279.580000) < 60 && E2_MC12TuneV3_ProbNNe_Meerkat < 0.8))))&&((!(TMath::Abs(TMath::Sqrt(TMath::Sq(K_PE+Pi_PE+TMath::Sqrt(TMath::Sq(139.570180)+TMath::Sq(E2_TRACK_PX)+TMath::Sq(E2_TRACK_PY)+TMath::Sq(E2_TRACK_PZ))) - TMath::Sq(K_PX+Pi_PX+E2_TRACK_PX) - TMath::Sq(K_PY+Pi_PY+E2_TRACK_PY) - TMath::Sq(K_PZ+Pi_PZ+E2_TRACK_PZ)) - 1869.650000) < 30 && E2_MC12TuneV3_ProbNNe_Meerkat < 0.8))&&(!(TMath::Abs(B0_TRACK_M12_Subst1_e2pi - 1864.830000) < 30 && E2_MC12TuneV3_ProbNNe_Meerkat < 0.8)))))&&(((((K_PIDK_Meerkat > -5)&&(K_MC12TuneV2_ProbNNk_Meerkat * (1 - K_MC12TuneV2_ProbNNp_Meerkat) > 0.05))&&(K_PIDK_Meerkat > 0))&&(Pi_MC12TuneV2_ProbNNpi_Meerkat * (1 - Pi_MC12TuneV2_ProbNNk_Meerkat) * (1 - Pi_MC12TuneV2_ProbNNp_Meerkat) > 0.1))&&(((TMath::Min(E1_PIDe_Meerkat,E2_PIDe_Meerkat) > 0)&&(TMath::Min(E1_MC12TuneV3_ProbNNe_Meerkat,E2_MC12TuneV3_ProbNNe_Meerkat) > 0.2))&&(TMath::Min(E1_PIDe_Meerkat, E2_PIDe_Meerkat) > 2))))&&(TMath::Sq(JPs_M/1000) > 6 && TMath::Sq(JPs_M/1000) < 11)))&&((( B0_Hlt1TrackAllL0Decision_TIS || B0_Hlt1TrackMuonDecision_TIS || B0_Hlt1TrackDiMuonDecision_TIS ))&&(( B0_Hlt2Topo2BodyBBDTDecision_TIS || B0_Hlt2Topo3BodyBBDTDecision_TIS || B0_Hlt2Topo4BodyBBDTDecision_TIS || B0_Hlt2TopoMu2BodyBBDTDecision_TIS || B0_Hlt2TopoMu3BodyBBDTDecision_TIS || B0_Hlt2TopoMu4BodyBBDTDecision_TIS || B0_Hlt2DiMuonDetachedDecision_TIS || B0_Hlt2TopoE2BodyBBDTDecision_TIS || B0_Hlt2TopoE3BodyBBDTDecision_TIS || B0_Hlt2TopoE4BodyBBDTDecision_TIS ))))

I wuld like to decompose it with some regular expression matching, or have a sort of method which can automatize the cut decomposition.

As I said in the thread i can modify the code which generate the cut, but I need to refactor a bit the code. I just ask in case it exists some kind of tool in ROOT or in general able to interpret the math expressions and reduce the problem giving me back a list of selection or something like that.

I am not aware of such tool. But why don’t you create smaller and simpler cuts and make the complex one a composition of those ?
That might be easier to manage.

Yes, indeed, that’s a change I had in mind on our analysis code.
The reason why I asked is because this kind of change requires some deep change on how the code we have is handling selection(s) and selection building. And update this requires a deep refactoring of our code.
Thanks for the feedback!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.